Line data Source code
1 : // Copyright 2016 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/compiler/js-create-lowering.h"
6 :
7 : #include "src/code-factory.h"
8 : #include "src/compiler/access-builder.h"
9 : #include "src/compiler/allocation-builder-inl.h"
10 : #include "src/compiler/common-operator.h"
11 : #include "src/compiler/compilation-dependencies.h"
12 : #include "src/compiler/js-graph.h"
13 : #include "src/compiler/js-operator.h"
14 : #include "src/compiler/linkage.h"
15 : #include "src/compiler/node-matchers.h"
16 : #include "src/compiler/node-properties.h"
17 : #include "src/compiler/node.h"
18 : #include "src/compiler/operator-properties.h"
19 : #include "src/compiler/simplified-operator.h"
20 : #include "src/compiler/state-values-utils.h"
21 : #include "src/objects-inl.h"
22 : #include "src/objects/arguments.h"
23 : #include "src/objects/hash-table-inl.h"
24 : #include "src/objects/heap-number.h"
25 : #include "src/objects/js-collection-iterator.h"
26 : #include "src/objects/js-generator.h"
27 : #include "src/objects/js-promise.h"
28 : #include "src/objects/js-regexp-inl.h"
29 :
30 : namespace v8 {
31 : namespace internal {
32 : namespace compiler {
33 :
34 : namespace {
35 :
36 : // Retrieves the frame state holding actual argument values.
37 1625 : Node* GetArgumentsFrameState(Node* frame_state) {
38 1625 : Node* const outer_state = NodeProperties::GetFrameStateInput(frame_state);
39 1625 : FrameStateInfo outer_state_info = FrameStateInfoOf(outer_state->op());
40 : return outer_state_info.type() == FrameStateType::kArgumentsAdaptor
41 : ? outer_state
42 1625 : : frame_state;
43 : }
44 :
45 : // When initializing arrays, we'll unfold the loop if the number of
46 : // elements is known to be of this type.
47 : const int kElementLoopUnrollLimit = 16;
48 :
49 : // Limits up to which context allocations are inlined.
50 : const int kFunctionContextAllocationLimit = 16;
51 : const int kBlockContextAllocationLimit = 16;
52 :
53 : } // namespace
54 :
55 33827959 : Reduction JSCreateLowering::Reduce(Node* node) {
56 : DisallowHeapAccess disallow_heap_access;
57 33827959 : switch (node->opcode()) {
58 : case IrOpcode::kJSCreate:
59 3681 : return ReduceJSCreate(node);
60 : case IrOpcode::kJSCreateArguments:
61 19365 : return ReduceJSCreateArguments(node);
62 : case IrOpcode::kJSCreateArray:
63 1548 : return ReduceJSCreateArray(node);
64 : case IrOpcode::kJSCreateArrayIterator:
65 981 : return ReduceJSCreateArrayIterator(node);
66 : case IrOpcode::kJSCreateAsyncFunctionObject:
67 1133 : return ReduceJSCreateAsyncFunctionObject(node);
68 : case IrOpcode::kJSCreateBoundFunction:
69 115 : return ReduceJSCreateBoundFunction(node);
70 : case IrOpcode::kJSCreateClosure:
71 442104 : return ReduceJSCreateClosure(node);
72 : case IrOpcode::kJSCreateCollectionIterator:
73 211 : return ReduceJSCreateCollectionIterator(node);
74 : case IrOpcode::kJSCreateIterResultObject:
75 2745 : return ReduceJSCreateIterResultObject(node);
76 : case IrOpcode::kJSCreateStringIterator:
77 62 : return ReduceJSCreateStringIterator(node);
78 : case IrOpcode::kJSCreateKeyValueArray:
79 91 : return ReduceJSCreateKeyValueArray(node);
80 : case IrOpcode::kJSCreatePromise:
81 1472 : return ReduceJSCreatePromise(node);
82 : case IrOpcode::kJSCreateLiteralArray:
83 : case IrOpcode::kJSCreateLiteralObject:
84 24307 : return ReduceJSCreateLiteralArrayOrObject(node);
85 : case IrOpcode::kJSCreateLiteralRegExp:
86 6437 : return ReduceJSCreateLiteralRegExp(node);
87 : case IrOpcode::kJSCreateEmptyLiteralArray:
88 22333 : return ReduceJSCreateEmptyLiteralArray(node);
89 : case IrOpcode::kJSCreateEmptyLiteralObject:
90 6112 : return ReduceJSCreateEmptyLiteralObject(node);
91 : case IrOpcode::kJSCreateFunctionContext:
92 29506 : return ReduceJSCreateFunctionContext(node);
93 : case IrOpcode::kJSCreateWithContext:
94 495 : return ReduceJSCreateWithContext(node);
95 : case IrOpcode::kJSCreateCatchContext:
96 15144 : return ReduceJSCreateCatchContext(node);
97 : case IrOpcode::kJSCreateBlockContext:
98 9405 : return ReduceJSCreateBlockContext(node);
99 : case IrOpcode::kJSCreateGeneratorObject:
100 1264 : return ReduceJSCreateGeneratorObject(node);
101 : case IrOpcode::kJSCreateObject:
102 78 : return ReduceJSCreateObject(node);
103 : default:
104 : break;
105 : }
106 : return NoChange();
107 : }
108 :
109 3681 : Reduction JSCreateLowering::ReduceJSCreate(Node* node) {
110 : DCHECK_EQ(IrOpcode::kJSCreate, node->opcode());
111 3681 : Node* const new_target = NodeProperties::GetValueInput(node, 1);
112 3681 : Node* const effect = NodeProperties::GetEffectInput(node);
113 3681 : Node* const control = NodeProperties::GetControlInput(node);
114 :
115 : base::Optional<MapRef> initial_map =
116 3681 : NodeProperties::GetJSCreateMap(broker(), node);
117 3681 : if (!initial_map.has_value()) return NoChange();
118 :
119 : JSFunctionRef original_constructor =
120 3405 : HeapObjectMatcher(new_target).Ref(broker()).AsJSFunction();
121 : SlackTrackingPrediction slack_tracking_prediction =
122 : dependencies()->DependOnInitialMapInstanceSizePrediction(
123 3405 : original_constructor);
124 :
125 : // Emit code to allocate the JSObject instance for the
126 : // {original_constructor}.
127 : AllocationBuilder a(jsgraph(), effect, control);
128 3405 : a.Allocate(slack_tracking_prediction.instance_size());
129 3405 : a.Store(AccessBuilder::ForMap(), *initial_map);
130 6810 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
131 3405 : jsgraph()->EmptyFixedArrayConstant());
132 6810 : a.Store(AccessBuilder::ForJSObjectElements(),
133 3405 : jsgraph()->EmptyFixedArrayConstant());
134 17315 : for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
135 : ++i) {
136 13910 : a.Store(AccessBuilder::ForJSObjectInObjectProperty(*initial_map, i),
137 6955 : jsgraph()->UndefinedConstant());
138 : }
139 :
140 : RelaxControls(node);
141 3405 : a.FinishAndChange(node);
142 : return Changed(node);
143 : }
144 :
145 19365 : Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
146 : DCHECK_EQ(IrOpcode::kJSCreateArguments, node->opcode());
147 19365 : CreateArgumentsType type = CreateArgumentsTypeOf(node->op());
148 19365 : Node* const frame_state = NodeProperties::GetFrameStateInput(node);
149 : Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
150 : Node* const control = graph()->start();
151 19365 : FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
152 : SharedFunctionInfoRef shared(broker(),
153 : state_info.shared_info().ToHandleChecked());
154 :
155 : // Use the ArgumentsAccessStub for materializing both mapped and unmapped
156 : // arguments object, but only for non-inlined (i.e. outermost) frames.
157 19365 : if (outer_state->opcode() != IrOpcode::kFrameState) {
158 17740 : switch (type) {
159 : case CreateArgumentsType::kMappedArguments: {
160 : // TODO(mstarzinger): Duplicate parameters are not handled yet.
161 11289 : if (shared.has_duplicate_parameters()) return NoChange();
162 11281 : Node* const callee = NodeProperties::GetValueInput(node, 0);
163 11281 : Node* const context = NodeProperties::GetContextInput(node);
164 11281 : Node* effect = NodeProperties::GetEffectInput(node);
165 : Node* const arguments_frame =
166 11281 : graph()->NewNode(simplified()->ArgumentsFrame());
167 11281 : Node* const arguments_length = graph()->NewNode(
168 : simplified()->ArgumentsLength(
169 : shared.internal_formal_parameter_count(), false),
170 : arguments_frame);
171 : // Allocate the elements backing store.
172 11281 : bool has_aliased_arguments = false;
173 : Node* const elements = effect = AllocateAliasedArguments(
174 : effect, control, context, arguments_frame, arguments_length, shared,
175 11281 : &has_aliased_arguments);
176 : // Load the arguments object map.
177 33843 : Node* const arguments_map = jsgraph()->Constant(
178 : has_aliased_arguments
179 16045 : ? native_context().fast_aliased_arguments_map()
180 40360 : : native_context().sloppy_arguments_map());
181 : // Actually allocate and initialize the arguments object.
182 : AllocationBuilder a(jsgraph(), effect, control);
183 11281 : Node* properties = jsgraph()->EmptyFixedArrayConstant();
184 : STATIC_ASSERT(JSSloppyArgumentsObject::kSize == 5 * kTaggedSize);
185 11281 : a.Allocate(JSSloppyArgumentsObject::kSize);
186 11281 : a.Store(AccessBuilder::ForMap(), arguments_map);
187 11281 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
188 11281 : a.Store(AccessBuilder::ForJSObjectElements(), elements);
189 11281 : a.Store(AccessBuilder::ForArgumentsLength(), arguments_length);
190 11281 : a.Store(AccessBuilder::ForArgumentsCallee(), callee);
191 : RelaxControls(node);
192 11281 : a.FinishAndChange(node);
193 : return Changed(node);
194 : }
195 : case CreateArgumentsType::kUnmappedArguments: {
196 5758 : Node* effect = NodeProperties::GetEffectInput(node);
197 : Node* const arguments_frame =
198 5758 : graph()->NewNode(simplified()->ArgumentsFrame());
199 5758 : Node* const arguments_length = graph()->NewNode(
200 : simplified()->ArgumentsLength(
201 : shared.internal_formal_parameter_count(), false),
202 : arguments_frame);
203 : // Allocate the elements backing store.
204 : Node* const elements = effect =
205 5758 : graph()->NewNode(simplified()->NewArgumentsElements(0),
206 : arguments_frame, arguments_length, effect);
207 : // Load the arguments object map.
208 : Node* const arguments_map =
209 5758 : jsgraph()->Constant(native_context().strict_arguments_map());
210 : // Actually allocate and initialize the arguments object.
211 : AllocationBuilder a(jsgraph(), effect, control);
212 5758 : Node* properties = jsgraph()->EmptyFixedArrayConstant();
213 : STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kTaggedSize);
214 5758 : a.Allocate(JSStrictArgumentsObject::kSize);
215 5758 : a.Store(AccessBuilder::ForMap(), arguments_map);
216 5758 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
217 5758 : a.Store(AccessBuilder::ForJSObjectElements(), elements);
218 5758 : a.Store(AccessBuilder::ForArgumentsLength(), arguments_length);
219 : RelaxControls(node);
220 5758 : a.FinishAndChange(node);
221 : return Changed(node);
222 : }
223 : case CreateArgumentsType::kRestParameter: {
224 693 : Node* effect = NodeProperties::GetEffectInput(node);
225 : Node* const arguments_frame =
226 693 : graph()->NewNode(simplified()->ArgumentsFrame());
227 693 : Node* const rest_length = graph()->NewNode(
228 : simplified()->ArgumentsLength(
229 : shared.internal_formal_parameter_count(), true),
230 : arguments_frame);
231 : // Allocate the elements backing store. Since NewArgumentsElements
232 : // copies from the end of the arguments adapter frame, this is a suffix
233 : // of the actual arguments.
234 : Node* const elements = effect =
235 693 : graph()->NewNode(simplified()->NewArgumentsElements(0),
236 : arguments_frame, rest_length, effect);
237 : // Load the JSArray object map.
238 : Node* const jsarray_map = jsgraph()->Constant(
239 693 : native_context().js_array_packed_elements_map());
240 : // Actually allocate and initialize the jsarray.
241 : AllocationBuilder a(jsgraph(), effect, control);
242 693 : Node* properties = jsgraph()->EmptyFixedArrayConstant();
243 : STATIC_ASSERT(JSArray::kSize == 4 * kTaggedSize);
244 693 : a.Allocate(JSArray::kSize);
245 693 : a.Store(AccessBuilder::ForMap(), jsarray_map);
246 693 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
247 693 : a.Store(AccessBuilder::ForJSObjectElements(), elements);
248 693 : a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS), rest_length);
249 : RelaxControls(node);
250 693 : a.FinishAndChange(node);
251 : return Changed(node);
252 : }
253 : }
254 0 : UNREACHABLE();
255 1625 : } else if (outer_state->opcode() == IrOpcode::kFrameState) {
256 : // Use inline allocation for all mapped arguments objects within inlined
257 : // (i.e. non-outermost) frames, independent of the object size.
258 1625 : if (type == CreateArgumentsType::kMappedArguments) {
259 642 : Node* const callee = NodeProperties::GetValueInput(node, 0);
260 642 : Node* const context = NodeProperties::GetContextInput(node);
261 642 : Node* effect = NodeProperties::GetEffectInput(node);
262 : // TODO(mstarzinger): Duplicate parameters are not handled yet.
263 642 : if (shared.has_duplicate_parameters()) return NoChange();
264 : // Choose the correct frame state and frame state info depending on
265 : // whether there conceptually is an arguments adaptor frame in the call
266 : // chain.
267 642 : Node* const args_state = GetArgumentsFrameState(frame_state);
268 642 : if (args_state->InputAt(kFrameStateParametersInput)->opcode() ==
269 : IrOpcode::kDeadValue) {
270 : // This protects against an incompletely propagated DeadValue node.
271 : // If the FrameState has a DeadValue input, then this node will be
272 : // pruned anyway.
273 : return NoChange();
274 : }
275 642 : FrameStateInfo args_state_info = FrameStateInfoOf(args_state->op());
276 : // Prepare element backing store to be used by arguments object.
277 642 : bool has_aliased_arguments = false;
278 : Node* const elements = AllocateAliasedArguments(
279 642 : effect, control, args_state, context, shared, &has_aliased_arguments);
280 642 : effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
281 : // Load the arguments object map.
282 1926 : Node* const arguments_map = jsgraph()->Constant(
283 1328 : has_aliased_arguments ? native_context().fast_aliased_arguments_map()
284 1882 : : native_context().sloppy_arguments_map());
285 : // Actually allocate and initialize the arguments object.
286 : AllocationBuilder a(jsgraph(), effect, control);
287 642 : Node* properties = jsgraph()->EmptyFixedArrayConstant();
288 642 : int length = args_state_info.parameter_count() - 1; // Minus receiver.
289 : STATIC_ASSERT(JSSloppyArgumentsObject::kSize == 5 * kTaggedSize);
290 642 : a.Allocate(JSSloppyArgumentsObject::kSize);
291 642 : a.Store(AccessBuilder::ForMap(), arguments_map);
292 642 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
293 642 : a.Store(AccessBuilder::ForJSObjectElements(), elements);
294 642 : a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length));
295 642 : a.Store(AccessBuilder::ForArgumentsCallee(), callee);
296 : RelaxControls(node);
297 642 : a.FinishAndChange(node);
298 : return Changed(node);
299 983 : } else if (type == CreateArgumentsType::kUnmappedArguments) {
300 : // Use inline allocation for all unmapped arguments objects within inlined
301 : // (i.e. non-outermost) frames, independent of the object size.
302 423 : Node* effect = NodeProperties::GetEffectInput(node);
303 : // Choose the correct frame state and frame state info depending on
304 : // whether there conceptually is an arguments adaptor frame in the call
305 : // chain.
306 423 : Node* const args_state = GetArgumentsFrameState(frame_state);
307 423 : if (args_state->InputAt(kFrameStateParametersInput)->opcode() ==
308 : IrOpcode::kDeadValue) {
309 : // This protects against an incompletely propagated DeadValue node.
310 : // If the FrameState has a DeadValue input, then this node will be
311 : // pruned anyway.
312 : return NoChange();
313 : }
314 423 : FrameStateInfo args_state_info = FrameStateInfoOf(args_state->op());
315 : // Prepare element backing store to be used by arguments object.
316 423 : Node* const elements = AllocateArguments(effect, control, args_state);
317 423 : effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
318 : // Load the arguments object map.
319 : Node* const arguments_map =
320 423 : jsgraph()->Constant(native_context().strict_arguments_map());
321 : // Actually allocate and initialize the arguments object.
322 : AllocationBuilder a(jsgraph(), effect, control);
323 423 : Node* properties = jsgraph()->EmptyFixedArrayConstant();
324 423 : int length = args_state_info.parameter_count() - 1; // Minus receiver.
325 : STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kTaggedSize);
326 423 : a.Allocate(JSStrictArgumentsObject::kSize);
327 423 : a.Store(AccessBuilder::ForMap(), arguments_map);
328 423 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
329 423 : a.Store(AccessBuilder::ForJSObjectElements(), elements);
330 423 : a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length));
331 : RelaxControls(node);
332 423 : a.FinishAndChange(node);
333 : return Changed(node);
334 560 : } else if (type == CreateArgumentsType::kRestParameter) {
335 560 : int start_index = shared.internal_formal_parameter_count();
336 : // Use inline allocation for all unmapped arguments objects within inlined
337 : // (i.e. non-outermost) frames, independent of the object size.
338 560 : Node* effect = NodeProperties::GetEffectInput(node);
339 : // Choose the correct frame state and frame state info depending on
340 : // whether there conceptually is an arguments adaptor frame in the call
341 : // chain.
342 560 : Node* const args_state = GetArgumentsFrameState(frame_state);
343 560 : if (args_state->InputAt(kFrameStateParametersInput)->opcode() ==
344 : IrOpcode::kDeadValue) {
345 : // This protects against an incompletely propagated DeadValue node.
346 : // If the FrameState has a DeadValue input, then this node will be
347 : // pruned anyway.
348 : return NoChange();
349 : }
350 560 : FrameStateInfo args_state_info = FrameStateInfoOf(args_state->op());
351 : // Prepare element backing store to be used by the rest array.
352 : Node* const elements =
353 560 : AllocateRestArguments(effect, control, args_state, start_index);
354 560 : effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
355 : // Load the JSArray object map.
356 : Node* const jsarray_map =
357 560 : jsgraph()->Constant(native_context().js_array_packed_elements_map());
358 : // Actually allocate and initialize the jsarray.
359 : AllocationBuilder a(jsgraph(), effect, control);
360 560 : Node* properties = jsgraph()->EmptyFixedArrayConstant();
361 :
362 : // -1 to minus receiver
363 560 : int argument_count = args_state_info.parameter_count() - 1;
364 1120 : int length = std::max(0, argument_count - start_index);
365 : STATIC_ASSERT(JSArray::kSize == 4 * kTaggedSize);
366 560 : a.Allocate(JSArray::kSize);
367 560 : a.Store(AccessBuilder::ForMap(), jsarray_map);
368 560 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
369 560 : a.Store(AccessBuilder::ForJSObjectElements(), elements);
370 1120 : a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS),
371 560 : jsgraph()->Constant(length));
372 : RelaxControls(node);
373 560 : a.FinishAndChange(node);
374 : return Changed(node);
375 : }
376 : }
377 :
378 : return NoChange();
379 : }
380 :
381 1264 : Reduction JSCreateLowering::ReduceJSCreateGeneratorObject(Node* node) {
382 : DCHECK_EQ(IrOpcode::kJSCreateGeneratorObject, node->opcode());
383 1264 : Node* const closure = NodeProperties::GetValueInput(node, 0);
384 1264 : Node* const receiver = NodeProperties::GetValueInput(node, 1);
385 1264 : Node* const context = NodeProperties::GetContextInput(node);
386 1264 : Type const closure_type = NodeProperties::GetType(closure);
387 1264 : Node* effect = NodeProperties::GetEffectInput(node);
388 1264 : Node* const control = NodeProperties::GetControlInput(node);
389 1264 : if (closure_type.IsHeapConstant()) {
390 : DCHECK(closure_type.AsHeapConstant()->Ref().IsJSFunction());
391 : JSFunctionRef js_function =
392 1222 : closure_type.AsHeapConstant()->Ref().AsJSFunction();
393 1222 : if (!js_function.has_initial_map()) return NoChange();
394 :
395 : SlackTrackingPrediction slack_tracking_prediction =
396 473 : dependencies()->DependOnInitialMapInstanceSizePrediction(js_function);
397 :
398 473 : MapRef initial_map = js_function.initial_map();
399 : DCHECK(initial_map.instance_type() == JS_GENERATOR_OBJECT_TYPE ||
400 : initial_map.instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE);
401 :
402 : // Allocate a register file.
403 473 : SharedFunctionInfoRef shared = js_function.shared();
404 : DCHECK(shared.HasBytecodeArray());
405 473 : int parameter_count_no_receiver = shared.internal_formal_parameter_count();
406 : int size = parameter_count_no_receiver +
407 473 : shared.GetBytecodeArray().register_count();
408 : AllocationBuilder ab(jsgraph(), effect, control);
409 473 : ab.AllocateArray(size, factory()->fixed_array_map());
410 6731 : for (int i = 0; i < size; ++i) {
411 6258 : ab.Store(AccessBuilder::ForFixedArraySlot(i),
412 3129 : jsgraph()->UndefinedConstant());
413 : }
414 473 : Node* parameters_and_registers = effect = ab.Finish();
415 :
416 : // Emit code to allocate the JS[Async]GeneratorObject instance.
417 : AllocationBuilder a(jsgraph(), effect, control);
418 473 : a.Allocate(slack_tracking_prediction.instance_size());
419 473 : Node* empty_fixed_array = jsgraph()->EmptyFixedArrayConstant();
420 473 : Node* undefined = jsgraph()->UndefinedConstant();
421 473 : a.Store(AccessBuilder::ForMap(), initial_map);
422 473 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), empty_fixed_array);
423 473 : a.Store(AccessBuilder::ForJSObjectElements(), empty_fixed_array);
424 473 : a.Store(AccessBuilder::ForJSGeneratorObjectContext(), context);
425 473 : a.Store(AccessBuilder::ForJSGeneratorObjectFunction(), closure);
426 473 : a.Store(AccessBuilder::ForJSGeneratorObjectReceiver(), receiver);
427 473 : a.Store(AccessBuilder::ForJSGeneratorObjectInputOrDebugPos(), undefined);
428 946 : a.Store(AccessBuilder::ForJSGeneratorObjectResumeMode(),
429 473 : jsgraph()->Constant(JSGeneratorObject::kNext));
430 946 : a.Store(AccessBuilder::ForJSGeneratorObjectContinuation(),
431 473 : jsgraph()->Constant(JSGeneratorObject::kGeneratorExecuting));
432 946 : a.Store(AccessBuilder::ForJSGeneratorObjectParametersAndRegisters(),
433 473 : parameters_and_registers);
434 :
435 473 : if (initial_map.instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE) {
436 35 : a.Store(AccessBuilder::ForJSAsyncGeneratorObjectQueue(), undefined);
437 70 : a.Store(AccessBuilder::ForJSAsyncGeneratorObjectIsAwaiting(),
438 35 : jsgraph()->ZeroConstant());
439 : }
440 :
441 : // Handle in-object properties, too.
442 501 : for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
443 : ++i) {
444 28 : a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
445 14 : undefined);
446 : }
447 473 : a.FinishAndChange(node);
448 : return Changed(node);
449 : }
450 : return NoChange();
451 : }
452 :
453 : // Constructs an array with a variable {length} when no upper bound
454 : // is known for the capacity.
455 472 : Reduction JSCreateLowering::ReduceNewArray(
456 : Node* node, Node* length, MapRef initial_map, ElementsKind elements_kind,
457 : AllocationType allocation,
458 : const SlackTrackingPrediction& slack_tracking_prediction) {
459 : DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
460 472 : Node* effect = NodeProperties::GetEffectInput(node);
461 472 : Node* control = NodeProperties::GetControlInput(node);
462 :
463 : // Constructing an Array via new Array(N) where N is an unsigned
464 : // integer, always creates a holey backing store.
465 472 : ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
466 : initial_map,
467 : initial_map.AsElementsKind(GetHoleyElementsKind(elements_kind)));
468 :
469 : // Check that the {limit} is an unsigned integer in the valid range.
470 : // This has to be kept in sync with src/runtime/runtime-array.cc,
471 : // where this limit is protected.
472 944 : length = effect = graph()->NewNode(
473 : simplified()->CheckBounds(VectorSlotPair()), length,
474 : jsgraph()->Constant(JSArray::kInitialMaxFastElementArray), effect,
475 : control);
476 :
477 : // Construct elements and properties for the resulting JSArray.
478 : Node* elements = effect =
479 944 : graph()->NewNode(IsDoubleElementsKind(initial_map.elements_kind())
480 : ? simplified()->NewDoubleElements(allocation)
481 : : simplified()->NewSmiOrObjectElements(allocation),
482 : length, effect, control);
483 472 : Node* properties = jsgraph()->EmptyFixedArrayConstant();
484 :
485 : // Perform the allocation of the actual JSArray object.
486 : AllocationBuilder a(jsgraph(), effect, control);
487 472 : a.Allocate(slack_tracking_prediction.instance_size(), allocation);
488 472 : a.Store(AccessBuilder::ForMap(), initial_map);
489 472 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
490 472 : a.Store(AccessBuilder::ForJSObjectElements(), elements);
491 472 : a.Store(AccessBuilder::ForJSArrayLength(initial_map.elements_kind()), length);
492 472 : for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
493 : ++i) {
494 0 : a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
495 0 : jsgraph()->UndefinedConstant());
496 : }
497 : RelaxControls(node);
498 472 : a.FinishAndChange(node);
499 : return Changed(node);
500 : }
501 :
502 : // Constructs an array with a variable {length} when an actual
503 : // upper bound is known for the {capacity}.
504 1437 : Reduction JSCreateLowering::ReduceNewArray(
505 : Node* node, Node* length, int capacity, MapRef initial_map,
506 : ElementsKind elements_kind, AllocationType allocation,
507 : const SlackTrackingPrediction& slack_tracking_prediction) {
508 : DCHECK(node->opcode() == IrOpcode::kJSCreateArray ||
509 : node->opcode() == IrOpcode::kJSCreateEmptyLiteralArray);
510 1437 : Node* effect = NodeProperties::GetEffectInput(node);
511 1437 : Node* control = NodeProperties::GetControlInput(node);
512 :
513 : // Determine the appropriate elements kind.
514 1437 : if (NodeProperties::GetType(length).Max() > 0.0) {
515 : elements_kind = GetHoleyElementsKind(elements_kind);
516 : }
517 1437 : ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
518 : initial_map, initial_map.AsElementsKind(elements_kind));
519 : DCHECK(IsFastElementsKind(elements_kind));
520 :
521 : // Setup elements and properties.
522 : Node* elements;
523 1437 : if (capacity == 0) {
524 980 : elements = jsgraph()->EmptyFixedArrayConstant();
525 : } else {
526 : elements = effect =
527 457 : AllocateElements(effect, control, elements_kind, capacity, allocation);
528 : }
529 1437 : Node* properties = jsgraph()->EmptyFixedArrayConstant();
530 :
531 : // Perform the allocation of the actual JSArray object.
532 : AllocationBuilder a(jsgraph(), effect, control);
533 1437 : a.Allocate(slack_tracking_prediction.instance_size(), allocation);
534 1437 : a.Store(AccessBuilder::ForMap(), initial_map);
535 1437 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
536 1437 : a.Store(AccessBuilder::ForJSObjectElements(), elements);
537 1437 : a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length);
538 1563 : for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
539 : ++i) {
540 126 : a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
541 63 : jsgraph()->UndefinedConstant());
542 : }
543 : RelaxControls(node);
544 1437 : a.FinishAndChange(node);
545 : return Changed(node);
546 : }
547 :
548 460 : Reduction JSCreateLowering::ReduceNewArray(
549 : Node* node, std::vector<Node*> values, MapRef initial_map,
550 : ElementsKind elements_kind, AllocationType allocation,
551 : const SlackTrackingPrediction& slack_tracking_prediction) {
552 : DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
553 460 : Node* effect = NodeProperties::GetEffectInput(node);
554 460 : Node* control = NodeProperties::GetControlInput(node);
555 :
556 : // Determine the appropriate elements kind.
557 : DCHECK(IsFastElementsKind(elements_kind));
558 460 : ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
559 : initial_map, initial_map.AsElementsKind(elements_kind));
560 :
561 : // Check {values} based on the {elements_kind}. These checks are guarded
562 : // by the {elements_kind} feedback on the {site}, so it's safe to just
563 : // deoptimize in this case.
564 460 : if (IsSmiElementsKind(elements_kind)) {
565 455 : for (auto& value : values) {
566 700 : if (!NodeProperties::GetType(value).Is(Type::SignedSmall())) {
567 192 : value = effect = graph()->NewNode(
568 96 : simplified()->CheckSmi(VectorSlotPair()), value, effect, control);
569 : }
570 : }
571 355 : } else if (IsDoubleElementsKind(elements_kind)) {
572 244 : for (auto& value : values) {
573 364 : if (!NodeProperties::GetType(value).Is(Type::Number())) {
574 : value = effect =
575 0 : graph()->NewNode(simplified()->CheckNumber(VectorSlotPair()), value,
576 0 : effect, control);
577 : }
578 : // Make sure we do not store signaling NaNs into double arrays.
579 364 : value = graph()->NewNode(simplified()->NumberSilenceNaN(), value);
580 : }
581 : }
582 :
583 : // Setup elements, properties and length.
584 : Node* elements = effect =
585 460 : AllocateElements(effect, control, elements_kind, values, allocation);
586 460 : Node* properties = jsgraph()->EmptyFixedArrayConstant();
587 460 : Node* length = jsgraph()->Constant(static_cast<int>(values.size()));
588 :
589 : // Perform the allocation of the actual JSArray object.
590 : AllocationBuilder a(jsgraph(), effect, control);
591 460 : a.Allocate(slack_tracking_prediction.instance_size(), allocation);
592 460 : a.Store(AccessBuilder::ForMap(), initial_map);
593 460 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
594 460 : a.Store(AccessBuilder::ForJSObjectElements(), elements);
595 460 : a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length);
596 796 : for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
597 : ++i) {
598 336 : a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
599 168 : jsgraph()->UndefinedConstant());
600 : }
601 : RelaxControls(node);
602 460 : a.FinishAndChange(node);
603 : return Changed(node);
604 : }
605 :
606 1548 : Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
607 : DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
608 1548 : CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
609 1548 : int const arity = static_cast<int>(p.arity());
610 1548 : base::Optional<AllocationSiteRef> site_ref;
611 : {
612 : Handle<AllocationSite> site;
613 1548 : if (p.site().ToHandle(&site)) {
614 535 : site_ref = AllocationSiteRef(broker(), site);
615 : }
616 : }
617 : AllocationType allocation = AllocationType::kYoung;
618 :
619 : base::Optional<MapRef> initial_map =
620 1548 : NodeProperties::GetJSCreateMap(broker(), node);
621 1548 : if (!initial_map.has_value()) return NoChange();
622 :
623 1537 : Node* new_target = NodeProperties::GetValueInput(node, 1);
624 : JSFunctionRef original_constructor =
625 1537 : HeapObjectMatcher(new_target).Ref(broker()).AsJSFunction();
626 : SlackTrackingPrediction slack_tracking_prediction =
627 : dependencies()->DependOnInitialMapInstanceSizePrediction(
628 1537 : original_constructor);
629 :
630 : // Tells whether we are protected by either the {site} or a
631 : // protector cell to do certain speculative optimizations.
632 : bool can_inline_call = false;
633 :
634 : // Check if we have a feedback {site} on the {node}.
635 1537 : ElementsKind elements_kind = initial_map->elements_kind();
636 1537 : if (site_ref) {
637 531 : elements_kind = site_ref->GetElementsKind();
638 531 : can_inline_call = site_ref->CanInlineCall();
639 531 : allocation = dependencies()->DependOnPretenureMode(*site_ref);
640 531 : dependencies()->DependOnElementsKind(*site_ref);
641 : } else {
642 : CellRef array_constructor_protector(
643 : broker(), factory()->array_constructor_protector());
644 : can_inline_call =
645 1006 : array_constructor_protector.value().AsSmi() == Isolate::kProtectorValid;
646 : }
647 :
648 1537 : if (arity == 0) {
649 221 : Node* length = jsgraph()->ZeroConstant();
650 : int capacity = JSArray::kPreallocatedArrayElements;
651 : return ReduceNewArray(node, length, capacity, *initial_map, elements_kind,
652 221 : allocation, slack_tracking_prediction);
653 1316 : } else if (arity == 1) {
654 1063 : Node* length = NodeProperties::GetValueInput(node, 2);
655 1063 : Type length_type = NodeProperties::GetType(length);
656 1063 : if (!length_type.Maybe(Type::Number())) {
657 : // Handle the single argument case, where we know that the value
658 : // cannot be a valid Array length.
659 215 : elements_kind = GetMoreGeneralElementsKind(
660 : elements_kind, IsHoleyElementsKind(elements_kind) ? HOLEY_ELEMENTS
661 : : PACKED_ELEMENTS);
662 : return ReduceNewArray(node, std::vector<Node*>{length}, *initial_map,
663 : elements_kind, allocation,
664 645 : slack_tracking_prediction);
665 : }
666 2369 : if (length_type.Is(Type::SignedSmall()) && length_type.Min() >= 0 &&
667 1845 : length_type.Max() <= kElementLoopUnrollLimit &&
668 244 : length_type.Min() == length_type.Max()) {
669 236 : int capacity = static_cast<int>(length_type.Max());
670 : return ReduceNewArray(node, length, capacity, *initial_map, elements_kind,
671 236 : allocation, slack_tracking_prediction);
672 : }
673 612 : if (length_type.Maybe(Type::UnsignedSmall()) && can_inline_call) {
674 : return ReduceNewArray(node, length, *initial_map, elements_kind,
675 472 : allocation, slack_tracking_prediction);
676 : }
677 253 : } else if (arity <= JSArray::kInitialMaxFastElementArray) {
678 : // Gather the values to store into the newly created array.
679 : bool values_all_smis = true, values_all_numbers = true,
680 : values_any_nonnumber = false;
681 : std::vector<Node*> values;
682 253 : values.reserve(p.arity());
683 2125 : for (int i = 0; i < arity; ++i) {
684 936 : Node* value = NodeProperties::GetValueInput(node, 2 + i);
685 936 : Type value_type = NodeProperties::GetType(value);
686 936 : if (!value_type.Is(Type::SignedSmall())) {
687 : values_all_smis = false;
688 : }
689 936 : if (!value_type.Is(Type::Number())) {
690 : values_all_numbers = false;
691 : }
692 936 : if (!value_type.Maybe(Type::Number())) {
693 : values_any_nonnumber = true;
694 : }
695 936 : values.push_back(value);
696 : }
697 :
698 : // Try to figure out the ideal elements kind statically.
699 253 : if (values_all_smis) {
700 : // Smis can be stored with any elements kind.
701 178 : } else if (values_all_numbers) {
702 60 : elements_kind = GetMoreGeneralElementsKind(
703 : elements_kind, IsHoleyElementsKind(elements_kind)
704 : ? HOLEY_DOUBLE_ELEMENTS
705 : : PACKED_DOUBLE_ELEMENTS);
706 118 : } else if (values_any_nonnumber) {
707 78 : elements_kind = GetMoreGeneralElementsKind(
708 : elements_kind, IsHoleyElementsKind(elements_kind) ? HOLEY_ELEMENTS
709 : : PACKED_ELEMENTS);
710 40 : } else if (!can_inline_call) {
711 : // We have some crazy combination of types for the {values} where
712 : // there's no clear decision on the elements kind statically. And
713 : // we don't have a protection against deoptimization loops for the
714 : // checks that are introduced in the call to ReduceNewArray, so
715 : // we cannot inline this invocation of the Array constructor here.
716 : return NoChange();
717 : }
718 : return ReduceNewArray(node, values, *initial_map, elements_kind, allocation,
719 490 : slack_tracking_prediction);
720 : }
721 : return NoChange();
722 : }
723 :
724 981 : Reduction JSCreateLowering::ReduceJSCreateArrayIterator(Node* node) {
725 : DCHECK_EQ(IrOpcode::kJSCreateArrayIterator, node->opcode());
726 : CreateArrayIteratorParameters const& p =
727 981 : CreateArrayIteratorParametersOf(node->op());
728 981 : Node* iterated_object = NodeProperties::GetValueInput(node, 0);
729 981 : Node* effect = NodeProperties::GetEffectInput(node);
730 981 : Node* control = NodeProperties::GetControlInput(node);
731 :
732 : // Create the JSArrayIterator result.
733 : AllocationBuilder a(jsgraph(), effect, control);
734 : a.Allocate(JSArrayIterator::kSize, AllocationType::kYoung,
735 981 : Type::OtherObject());
736 1962 : a.Store(AccessBuilder::ForMap(),
737 2943 : native_context().initial_array_iterator_map());
738 1962 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
739 981 : jsgraph()->EmptyFixedArrayConstant());
740 1962 : a.Store(AccessBuilder::ForJSObjectElements(),
741 981 : jsgraph()->EmptyFixedArrayConstant());
742 981 : a.Store(AccessBuilder::ForJSArrayIteratorIteratedObject(), iterated_object);
743 1962 : a.Store(AccessBuilder::ForJSArrayIteratorNextIndex(),
744 981 : jsgraph()->ZeroConstant());
745 1962 : a.Store(AccessBuilder::ForJSArrayIteratorKind(),
746 981 : jsgraph()->Constant(static_cast<int>(p.kind())));
747 : RelaxControls(node);
748 981 : a.FinishAndChange(node);
749 981 : return Changed(node);
750 : }
751 :
752 1133 : Reduction JSCreateLowering::ReduceJSCreateAsyncFunctionObject(Node* node) {
753 : DCHECK_EQ(IrOpcode::kJSCreateAsyncFunctionObject, node->opcode());
754 1133 : int const register_count = RegisterCountOf(node->op());
755 1133 : Node* closure = NodeProperties::GetValueInput(node, 0);
756 1133 : Node* receiver = NodeProperties::GetValueInput(node, 1);
757 1133 : Node* promise = NodeProperties::GetValueInput(node, 2);
758 1133 : Node* context = NodeProperties::GetContextInput(node);
759 1133 : Node* effect = NodeProperties::GetEffectInput(node);
760 1133 : Node* control = NodeProperties::GetControlInput(node);
761 :
762 : // Create the register file.
763 : AllocationBuilder ab(jsgraph(), effect, control);
764 1133 : ab.AllocateArray(register_count, factory()->fixed_array_map());
765 24375 : for (int i = 0; i < register_count; ++i) {
766 23242 : ab.Store(AccessBuilder::ForFixedArraySlot(i),
767 11621 : jsgraph()->UndefinedConstant());
768 : }
769 1133 : Node* parameters_and_registers = effect = ab.Finish();
770 :
771 : // Create the JSAsyncFunctionObject result.
772 : AllocationBuilder a(jsgraph(), effect, control);
773 1133 : a.Allocate(JSAsyncFunctionObject::kSize);
774 1133 : Node* empty_fixed_array = jsgraph()->EmptyFixedArrayConstant();
775 2266 : a.Store(AccessBuilder::ForMap(),
776 3399 : native_context().async_function_object_map());
777 1133 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), empty_fixed_array);
778 1133 : a.Store(AccessBuilder::ForJSObjectElements(), empty_fixed_array);
779 1133 : a.Store(AccessBuilder::ForJSGeneratorObjectContext(), context);
780 1133 : a.Store(AccessBuilder::ForJSGeneratorObjectFunction(), closure);
781 1133 : a.Store(AccessBuilder::ForJSGeneratorObjectReceiver(), receiver);
782 2266 : a.Store(AccessBuilder::ForJSGeneratorObjectInputOrDebugPos(),
783 1133 : jsgraph()->UndefinedConstant());
784 2266 : a.Store(AccessBuilder::ForJSGeneratorObjectResumeMode(),
785 1133 : jsgraph()->Constant(JSGeneratorObject::kNext));
786 2266 : a.Store(AccessBuilder::ForJSGeneratorObjectContinuation(),
787 1133 : jsgraph()->Constant(JSGeneratorObject::kGeneratorExecuting));
788 2266 : a.Store(AccessBuilder::ForJSGeneratorObjectParametersAndRegisters(),
789 1133 : parameters_and_registers);
790 1133 : a.Store(AccessBuilder::ForJSAsyncFunctionObjectPromise(), promise);
791 1133 : a.FinishAndChange(node);
792 1133 : return Changed(node);
793 : }
794 :
795 : namespace {
796 :
797 211 : MapRef MapForCollectionIterationKind(const NativeContextRef& native_context,
798 : CollectionKind collection_kind,
799 : IterationKind iteration_kind) {
800 211 : switch (collection_kind) {
801 : case CollectionKind::kSet:
802 116 : switch (iteration_kind) {
803 : case IterationKind::kKeys:
804 0 : UNREACHABLE();
805 : case IterationKind::kValues:
806 94 : return native_context.set_value_iterator_map();
807 : case IterationKind::kEntries:
808 22 : return native_context.set_key_value_iterator_map();
809 : }
810 : break;
811 : case CollectionKind::kMap:
812 95 : switch (iteration_kind) {
813 : case IterationKind::kKeys:
814 23 : return native_context.map_key_iterator_map();
815 : case IterationKind::kValues:
816 43 : return native_context.map_value_iterator_map();
817 : case IterationKind::kEntries:
818 29 : return native_context.map_key_value_iterator_map();
819 : }
820 : break;
821 : }
822 0 : UNREACHABLE();
823 : }
824 :
825 : } // namespace
826 :
827 211 : Reduction JSCreateLowering::ReduceJSCreateCollectionIterator(Node* node) {
828 : DCHECK_EQ(IrOpcode::kJSCreateCollectionIterator, node->opcode());
829 : CreateCollectionIteratorParameters const& p =
830 211 : CreateCollectionIteratorParametersOf(node->op());
831 211 : Node* iterated_object = NodeProperties::GetValueInput(node, 0);
832 211 : Node* effect = NodeProperties::GetEffectInput(node);
833 211 : Node* control = NodeProperties::GetControlInput(node);
834 :
835 : // Load the OrderedHashTable from the {receiver}.
836 211 : Node* table = effect = graph()->NewNode(
837 422 : simplified()->LoadField(AccessBuilder::ForJSCollectionTable()),
838 : iterated_object, effect, control);
839 :
840 : // Create the JSArrayIterator result.
841 : AllocationBuilder a(jsgraph(), effect, control);
842 : a.Allocate(JSCollectionIterator::kSize, AllocationType::kYoung,
843 211 : Type::OtherObject());
844 422 : a.Store(AccessBuilder::ForMap(),
845 422 : MapForCollectionIterationKind(native_context(), p.collection_kind(),
846 211 : p.iteration_kind()));
847 422 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
848 211 : jsgraph()->EmptyFixedArrayConstant());
849 422 : a.Store(AccessBuilder::ForJSObjectElements(),
850 211 : jsgraph()->EmptyFixedArrayConstant());
851 211 : a.Store(AccessBuilder::ForJSCollectionIteratorTable(), table);
852 422 : a.Store(AccessBuilder::ForJSCollectionIteratorIndex(),
853 211 : jsgraph()->ZeroConstant());
854 : RelaxControls(node);
855 211 : a.FinishAndChange(node);
856 211 : return Changed(node);
857 : }
858 :
859 115 : Reduction JSCreateLowering::ReduceJSCreateBoundFunction(Node* node) {
860 : DCHECK_EQ(IrOpcode::kJSCreateBoundFunction, node->opcode());
861 : CreateBoundFunctionParameters const& p =
862 115 : CreateBoundFunctionParametersOf(node->op());
863 115 : int const arity = static_cast<int>(p.arity());
864 : MapRef const map(broker(), p.map());
865 115 : Node* bound_target_function = NodeProperties::GetValueInput(node, 0);
866 115 : Node* bound_this = NodeProperties::GetValueInput(node, 1);
867 115 : Node* effect = NodeProperties::GetEffectInput(node);
868 115 : Node* control = NodeProperties::GetControlInput(node);
869 :
870 : // Create the [[BoundArguments]] for the result.
871 115 : Node* bound_arguments = jsgraph()->EmptyFixedArrayConstant();
872 115 : if (arity > 0) {
873 : AllocationBuilder a(jsgraph(), effect, control);
874 66 : a.AllocateArray(arity, factory()->fixed_array_map());
875 234 : for (int i = 0; i < arity; ++i) {
876 168 : a.Store(AccessBuilder::ForFixedArraySlot(i),
877 84 : NodeProperties::GetValueInput(node, 2 + i));
878 : }
879 66 : bound_arguments = effect = a.Finish();
880 : }
881 :
882 : // Create the JSBoundFunction result.
883 : AllocationBuilder a(jsgraph(), effect, control);
884 : a.Allocate(JSBoundFunction::kSize, AllocationType::kYoung,
885 115 : Type::BoundFunction());
886 115 : a.Store(AccessBuilder::ForMap(), map);
887 230 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
888 115 : jsgraph()->EmptyFixedArrayConstant());
889 230 : a.Store(AccessBuilder::ForJSObjectElements(),
890 115 : jsgraph()->EmptyFixedArrayConstant());
891 230 : a.Store(AccessBuilder::ForJSBoundFunctionBoundTargetFunction(),
892 115 : bound_target_function);
893 115 : a.Store(AccessBuilder::ForJSBoundFunctionBoundThis(), bound_this);
894 115 : a.Store(AccessBuilder::ForJSBoundFunctionBoundArguments(), bound_arguments);
895 : RelaxControls(node);
896 115 : a.FinishAndChange(node);
897 115 : return Changed(node);
898 : }
899 :
900 442105 : Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
901 : DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode());
902 442105 : CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
903 : SharedFunctionInfoRef shared(broker(), p.shared_info());
904 : HeapObjectRef feedback_cell(broker(), p.feedback_cell());
905 : HeapObjectRef code(broker(), p.code());
906 442106 : Node* effect = NodeProperties::GetEffectInput(node);
907 442106 : Node* control = NodeProperties::GetControlInput(node);
908 442106 : Node* context = NodeProperties::GetContextInput(node);
909 :
910 : // Use inline allocation of closures only for instantiation sites that have
911 : // seen more than one instantiation, this simplifies the generated code and
912 : // also serves as a heuristic of which allocation sites benefit from it.
913 442106 : if (!feedback_cell.map().equals(
914 : MapRef(broker(), factory()->many_closures_cell_map()))) {
915 : return NoChange();
916 : }
917 :
918 : MapRef function_map =
919 64262 : native_context().GetFunctionMapFromIndex(shared.function_map_index());
920 : DCHECK(!function_map.IsInobjectSlackTrackingInProgress());
921 : DCHECK(!function_map.is_dictionary_map());
922 :
923 : // TODO(turbofan): We should use the pretenure flag from {p} here,
924 : // but currently the heuristic in the parser works against us, as
925 : // it marks closures like
926 : //
927 : // args[l] = function(...) { ... }
928 : //
929 : // for old-space allocation, which doesn't always make sense. For
930 : // example in case of the bluebird-parallel benchmark, where this
931 : // is a core part of the *promisify* logic (see crbug.com/810132).
932 : AllocationType allocation = AllocationType::kYoung;
933 :
934 : // Emit code to allocate the JSFunction instance.
935 : STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kTaggedSize);
936 : AllocationBuilder a(jsgraph(), effect, control);
937 32131 : a.Allocate(function_map.instance_size(), allocation, Type::Function());
938 32131 : a.Store(AccessBuilder::ForMap(), function_map);
939 64262 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
940 32131 : jsgraph()->EmptyFixedArrayConstant());
941 64262 : a.Store(AccessBuilder::ForJSObjectElements(),
942 32131 : jsgraph()->EmptyFixedArrayConstant());
943 32131 : a.Store(AccessBuilder::ForJSFunctionSharedFunctionInfo(), shared);
944 32131 : a.Store(AccessBuilder::ForJSFunctionContext(), context);
945 32131 : a.Store(AccessBuilder::ForJSFunctionFeedbackCell(), feedback_cell);
946 32131 : a.Store(AccessBuilder::ForJSFunctionCode(), code);
947 : STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kTaggedSize);
948 32131 : if (function_map.has_prototype_slot()) {
949 4542 : a.Store(AccessBuilder::ForJSFunctionPrototypeOrInitialMap(),
950 2271 : jsgraph()->TheHoleConstant());
951 : STATIC_ASSERT(JSFunction::kSizeWithPrototype == 8 * kTaggedSize);
952 : }
953 32209 : for (int i = 0; i < function_map.GetInObjectProperties(); i++) {
954 78 : a.Store(AccessBuilder::ForJSObjectInObjectProperty(function_map, i),
955 39 : jsgraph()->UndefinedConstant());
956 : }
957 : RelaxControls(node);
958 32131 : a.FinishAndChange(node);
959 : return Changed(node);
960 : }
961 :
962 2745 : Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) {
963 : DCHECK_EQ(IrOpcode::kJSCreateIterResultObject, node->opcode());
964 2745 : Node* value = NodeProperties::GetValueInput(node, 0);
965 2745 : Node* done = NodeProperties::GetValueInput(node, 1);
966 2745 : Node* effect = NodeProperties::GetEffectInput(node);
967 :
968 : Node* iterator_result_map =
969 2745 : jsgraph()->Constant(native_context().iterator_result_map());
970 :
971 : // Emit code to allocate the JSIteratorResult instance.
972 : AllocationBuilder a(jsgraph(), effect, graph()->start());
973 2745 : a.Allocate(JSIteratorResult::kSize);
974 2745 : a.Store(AccessBuilder::ForMap(), iterator_result_map);
975 5490 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
976 2745 : jsgraph()->EmptyFixedArrayConstant());
977 5490 : a.Store(AccessBuilder::ForJSObjectElements(),
978 2745 : jsgraph()->EmptyFixedArrayConstant());
979 2745 : a.Store(AccessBuilder::ForJSIteratorResultValue(), value);
980 2745 : a.Store(AccessBuilder::ForJSIteratorResultDone(), done);
981 : STATIC_ASSERT(JSIteratorResult::kSize == 5 * kTaggedSize);
982 2745 : a.FinishAndChange(node);
983 2745 : return Changed(node);
984 : }
985 :
986 62 : Reduction JSCreateLowering::ReduceJSCreateStringIterator(Node* node) {
987 : DCHECK_EQ(IrOpcode::kJSCreateStringIterator, node->opcode());
988 62 : Node* string = NodeProperties::GetValueInput(node, 0);
989 62 : Node* effect = NodeProperties::GetEffectInput(node);
990 :
991 : Node* map =
992 62 : jsgraph()->Constant(native_context().initial_string_iterator_map());
993 : // Allocate new iterator and attach the iterator to this string.
994 : AllocationBuilder a(jsgraph(), effect, graph()->start());
995 : a.Allocate(JSStringIterator::kSize, AllocationType::kYoung,
996 62 : Type::OtherObject());
997 62 : a.Store(AccessBuilder::ForMap(), map);
998 124 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
999 62 : jsgraph()->EmptyFixedArrayConstant());
1000 124 : a.Store(AccessBuilder::ForJSObjectElements(),
1001 62 : jsgraph()->EmptyFixedArrayConstant());
1002 62 : a.Store(AccessBuilder::ForJSStringIteratorString(), string);
1003 62 : a.Store(AccessBuilder::ForJSStringIteratorIndex(), jsgraph()->SmiConstant(0));
1004 : STATIC_ASSERT(JSIteratorResult::kSize == 5 * kTaggedSize);
1005 62 : a.FinishAndChange(node);
1006 62 : return Changed(node);
1007 : }
1008 :
1009 91 : Reduction JSCreateLowering::ReduceJSCreateKeyValueArray(Node* node) {
1010 : DCHECK_EQ(IrOpcode::kJSCreateKeyValueArray, node->opcode());
1011 91 : Node* key = NodeProperties::GetValueInput(node, 0);
1012 91 : Node* value = NodeProperties::GetValueInput(node, 1);
1013 91 : Node* effect = NodeProperties::GetEffectInput(node);
1014 :
1015 : Node* array_map =
1016 91 : jsgraph()->Constant(native_context().js_array_packed_elements_map());
1017 91 : Node* properties = jsgraph()->EmptyFixedArrayConstant();
1018 91 : Node* length = jsgraph()->Constant(2);
1019 :
1020 : AllocationBuilder aa(jsgraph(), effect, graph()->start());
1021 91 : aa.AllocateArray(2, factory()->fixed_array_map());
1022 182 : aa.Store(AccessBuilder::ForFixedArrayElement(PACKED_ELEMENTS),
1023 91 : jsgraph()->ZeroConstant(), key);
1024 182 : aa.Store(AccessBuilder::ForFixedArrayElement(PACKED_ELEMENTS),
1025 91 : jsgraph()->OneConstant(), value);
1026 91 : Node* elements = aa.Finish();
1027 :
1028 : AllocationBuilder a(jsgraph(), elements, graph()->start());
1029 91 : a.Allocate(JSArray::kSize);
1030 91 : a.Store(AccessBuilder::ForMap(), array_map);
1031 91 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
1032 91 : a.Store(AccessBuilder::ForJSObjectElements(), elements);
1033 91 : a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS), length);
1034 : STATIC_ASSERT(JSArray::kSize == 4 * kTaggedSize);
1035 91 : a.FinishAndChange(node);
1036 91 : return Changed(node);
1037 : }
1038 :
1039 1472 : Reduction JSCreateLowering::ReduceJSCreatePromise(Node* node) {
1040 : DCHECK_EQ(IrOpcode::kJSCreatePromise, node->opcode());
1041 1472 : Node* effect = NodeProperties::GetEffectInput(node);
1042 :
1043 1472 : MapRef promise_map = native_context().promise_function().initial_map();
1044 :
1045 : AllocationBuilder a(jsgraph(), effect, graph()->start());
1046 1472 : a.Allocate(promise_map.instance_size());
1047 1472 : a.Store(AccessBuilder::ForMap(), promise_map);
1048 2944 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
1049 1472 : jsgraph()->EmptyFixedArrayConstant());
1050 2944 : a.Store(AccessBuilder::ForJSObjectElements(),
1051 1472 : jsgraph()->EmptyFixedArrayConstant());
1052 2944 : a.Store(AccessBuilder::ForJSObjectOffset(JSPromise::kReactionsOrResultOffset),
1053 1472 : jsgraph()->ZeroConstant());
1054 : STATIC_ASSERT(v8::Promise::kPending == 0);
1055 2944 : a.Store(AccessBuilder::ForJSObjectOffset(JSPromise::kFlagsOffset),
1056 1472 : jsgraph()->ZeroConstant());
1057 : STATIC_ASSERT(JSPromise::kSize == 5 * kTaggedSize);
1058 : for (int offset = JSPromise::kSize;
1059 : offset < JSPromise::kSizeWithEmbedderFields; offset += kTaggedSize) {
1060 : a.Store(AccessBuilder::ForJSObjectOffset(offset),
1061 : jsgraph()->ZeroConstant());
1062 : }
1063 1472 : a.FinishAndChange(node);
1064 1472 : return Changed(node);
1065 : }
1066 :
1067 24307 : Reduction JSCreateLowering::ReduceJSCreateLiteralArrayOrObject(Node* node) {
1068 : DCHECK(node->opcode() == IrOpcode::kJSCreateLiteralArray ||
1069 : node->opcode() == IrOpcode::kJSCreateLiteralObject);
1070 24307 : CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
1071 24307 : Node* effect = NodeProperties::GetEffectInput(node);
1072 24307 : Node* control = NodeProperties::GetControlInput(node);
1073 :
1074 : FeedbackVectorRef feedback_vector(broker(), p.feedback().vector());
1075 24307 : ObjectRef feedback = feedback_vector.get(p.feedback().slot());
1076 24307 : if (feedback.IsAllocationSite()) {
1077 6283 : AllocationSiteRef site = feedback.AsAllocationSite();
1078 6283 : if (site.IsFastLiteral()) {
1079 : AllocationType allocation = AllocationType::kYoung;
1080 6064 : if (FLAG_allocation_site_pretenuring) {
1081 6064 : allocation = dependencies()->DependOnPretenureMode(site);
1082 : }
1083 6064 : dependencies()->DependOnElementsKinds(site);
1084 12128 : JSObjectRef boilerplate = site.boilerplate().value();
1085 : Node* value = effect =
1086 6064 : AllocateFastLiteral(effect, control, boilerplate, allocation);
1087 : ReplaceWithValue(node, value, effect, control);
1088 : return Replace(value);
1089 : }
1090 : }
1091 : return NoChange();
1092 : }
1093 :
1094 22333 : Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralArray(Node* node) {
1095 : DCHECK_EQ(IrOpcode::kJSCreateEmptyLiteralArray, node->opcode());
1096 22333 : FeedbackParameter const& p = FeedbackParameterOf(node->op());
1097 : FeedbackVectorRef fv(broker(), p.feedback().vector());
1098 22333 : ObjectRef feedback = fv.get(p.feedback().slot());
1099 22333 : if (feedback.IsAllocationSite()) {
1100 980 : AllocationSiteRef site = feedback.AsAllocationSite();
1101 : DCHECK(!site.PointsToLiteral());
1102 : MapRef initial_map =
1103 1960 : native_context().GetInitialJSArrayMap(site.GetElementsKind());
1104 : AllocationType const allocation =
1105 980 : dependencies()->DependOnPretenureMode(site);
1106 980 : dependencies()->DependOnElementsKind(site);
1107 980 : Node* length = jsgraph()->ZeroConstant();
1108 : DCHECK(!initial_map.IsInobjectSlackTrackingInProgress());
1109 : SlackTrackingPrediction slack_tracking_prediction(
1110 980 : initial_map, initial_map.instance_size());
1111 : return ReduceNewArray(node, length, 0, initial_map,
1112 980 : initial_map.elements_kind(), allocation,
1113 980 : slack_tracking_prediction);
1114 : }
1115 : return NoChange();
1116 : }
1117 :
1118 6112 : Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralObject(Node* node) {
1119 : DCHECK_EQ(IrOpcode::kJSCreateEmptyLiteralObject, node->opcode());
1120 6112 : Node* effect = NodeProperties::GetEffectInput(node);
1121 6112 : Node* control = NodeProperties::GetControlInput(node);
1122 :
1123 : // Retrieve the initial map for the object.
1124 6112 : MapRef map = native_context().object_function().initial_map();
1125 : DCHECK(!map.is_dictionary_map());
1126 : DCHECK(!map.IsInobjectSlackTrackingInProgress());
1127 6112 : Node* js_object_map = jsgraph()->Constant(map);
1128 :
1129 : // Setup elements and properties.
1130 6112 : Node* elements = jsgraph()->EmptyFixedArrayConstant();
1131 6112 : Node* properties = jsgraph()->EmptyFixedArrayConstant();
1132 :
1133 : // Perform the allocation of the actual JSArray object.
1134 : AllocationBuilder a(jsgraph(), effect, control);
1135 6112 : a.Allocate(map.instance_size());
1136 6112 : a.Store(AccessBuilder::ForMap(), js_object_map);
1137 6112 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
1138 6112 : a.Store(AccessBuilder::ForJSObjectElements(), elements);
1139 55008 : for (int i = 0; i < map.GetInObjectProperties(); i++) {
1140 48896 : a.Store(AccessBuilder::ForJSObjectInObjectProperty(map, i),
1141 24448 : jsgraph()->UndefinedConstant());
1142 : }
1143 :
1144 : RelaxControls(node);
1145 6112 : a.FinishAndChange(node);
1146 6112 : return Changed(node);
1147 : }
1148 :
1149 6437 : Reduction JSCreateLowering::ReduceJSCreateLiteralRegExp(Node* node) {
1150 : DCHECK_EQ(IrOpcode::kJSCreateLiteralRegExp, node->opcode());
1151 6437 : CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
1152 6437 : Node* effect = NodeProperties::GetEffectInput(node);
1153 6437 : Node* control = NodeProperties::GetControlInput(node);
1154 :
1155 : FeedbackVectorRef feedback_vector(broker(), p.feedback().vector());
1156 6437 : ObjectRef feedback = feedback_vector.get(p.feedback().slot());
1157 6437 : if (feedback.IsJSRegExp()) {
1158 574 : JSRegExpRef boilerplate = feedback.AsJSRegExp();
1159 574 : Node* value = effect = AllocateLiteralRegExp(effect, control, boilerplate);
1160 : ReplaceWithValue(node, value, effect, control);
1161 : return Replace(value);
1162 : }
1163 : return NoChange();
1164 : }
1165 :
1166 29506 : Reduction JSCreateLowering::ReduceJSCreateFunctionContext(Node* node) {
1167 : DCHECK_EQ(IrOpcode::kJSCreateFunctionContext, node->opcode());
1168 : const CreateFunctionContextParameters& parameters =
1169 29506 : CreateFunctionContextParametersOf(node->op());
1170 : ScopeInfoRef scope_info(broker(), parameters.scope_info());
1171 : int slot_count = parameters.slot_count();
1172 : ScopeType scope_type = parameters.scope_type();
1173 :
1174 : // Use inline allocation for function contexts up to a size limit.
1175 29506 : if (slot_count < kFunctionContextAllocationLimit) {
1176 : // JSCreateFunctionContext[slot_count < limit]](fun)
1177 24731 : Node* effect = NodeProperties::GetEffectInput(node);
1178 24731 : Node* control = NodeProperties::GetControlInput(node);
1179 24731 : Node* context = NodeProperties::GetContextInput(node);
1180 24731 : Node* extension = jsgraph()->TheHoleConstant();
1181 : AllocationBuilder a(jsgraph(), effect, control);
1182 : STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered.
1183 24731 : int context_length = slot_count + Context::MIN_CONTEXT_SLOTS;
1184 : Handle<Map> map;
1185 24731 : switch (scope_type) {
1186 : case EVAL_SCOPE:
1187 5625 : map = factory()->eval_context_map();
1188 5625 : break;
1189 : case FUNCTION_SCOPE:
1190 19106 : map = factory()->function_context_map();
1191 19106 : break;
1192 : default:
1193 0 : UNREACHABLE();
1194 : }
1195 24731 : a.AllocateContext(context_length, map);
1196 49462 : a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX),
1197 24731 : scope_info);
1198 24731 : a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
1199 24731 : a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
1200 49462 : a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
1201 74193 : jsgraph()->Constant(native_context()));
1202 144685 : for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) {
1203 59977 : a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant());
1204 : }
1205 : RelaxControls(node);
1206 24731 : a.FinishAndChange(node);
1207 : return Changed(node);
1208 : }
1209 :
1210 : return NoChange();
1211 : }
1212 :
1213 495 : Reduction JSCreateLowering::ReduceJSCreateWithContext(Node* node) {
1214 : DCHECK_EQ(IrOpcode::kJSCreateWithContext, node->opcode());
1215 495 : ScopeInfoRef scope_info(broker(), ScopeInfoOf(node->op()));
1216 495 : Node* extension = NodeProperties::GetValueInput(node, 0);
1217 495 : Node* effect = NodeProperties::GetEffectInput(node);
1218 495 : Node* control = NodeProperties::GetControlInput(node);
1219 495 : Node* context = NodeProperties::GetContextInput(node);
1220 :
1221 : AllocationBuilder a(jsgraph(), effect, control);
1222 : STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered.
1223 495 : a.AllocateContext(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map());
1224 495 : a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX), scope_info);
1225 495 : a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
1226 495 : a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
1227 990 : a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
1228 1485 : jsgraph()->Constant(native_context()));
1229 : RelaxControls(node);
1230 495 : a.FinishAndChange(node);
1231 495 : return Changed(node);
1232 : }
1233 :
1234 15144 : Reduction JSCreateLowering::ReduceJSCreateCatchContext(Node* node) {
1235 : DCHECK_EQ(IrOpcode::kJSCreateCatchContext, node->opcode());
1236 15144 : ScopeInfoRef scope_info(broker(), ScopeInfoOf(node->op()));
1237 15144 : Node* exception = NodeProperties::GetValueInput(node, 0);
1238 15144 : Node* effect = NodeProperties::GetEffectInput(node);
1239 15144 : Node* control = NodeProperties::GetControlInput(node);
1240 15144 : Node* context = NodeProperties::GetContextInput(node);
1241 15144 : Node* extension = jsgraph()->TheHoleConstant();
1242 :
1243 : AllocationBuilder a(jsgraph(), effect, control);
1244 : STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered.
1245 : a.AllocateContext(Context::MIN_CONTEXT_SLOTS + 1,
1246 15144 : factory()->catch_context_map());
1247 15144 : a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX), scope_info);
1248 15144 : a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
1249 15144 : a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
1250 30288 : a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
1251 45432 : jsgraph()->Constant(native_context()));
1252 30288 : a.Store(AccessBuilder::ForContextSlot(Context::THROWN_OBJECT_INDEX),
1253 15144 : exception);
1254 : RelaxControls(node);
1255 15144 : a.FinishAndChange(node);
1256 15144 : return Changed(node);
1257 : }
1258 :
1259 9405 : Reduction JSCreateLowering::ReduceJSCreateBlockContext(Node* node) {
1260 : DCHECK_EQ(IrOpcode::kJSCreateBlockContext, node->opcode());
1261 9405 : ScopeInfoRef scope_info(broker(), ScopeInfoOf(node->op()));
1262 9405 : int const context_length = scope_info.ContextLength();
1263 :
1264 : // Use inline allocation for block contexts up to a size limit.
1265 9405 : if (context_length < kBlockContextAllocationLimit) {
1266 : // JSCreateBlockContext[scope[length < limit]](fun)
1267 9405 : Node* effect = NodeProperties::GetEffectInput(node);
1268 9405 : Node* control = NodeProperties::GetControlInput(node);
1269 9405 : Node* context = NodeProperties::GetContextInput(node);
1270 9405 : Node* extension = jsgraph()->TheHoleConstant();
1271 :
1272 : AllocationBuilder a(jsgraph(), effect, control);
1273 : STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered.
1274 9405 : a.AllocateContext(context_length, factory()->block_context_map());
1275 18810 : a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX),
1276 9405 : scope_info);
1277 9405 : a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
1278 9405 : a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
1279 18810 : a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
1280 28215 : jsgraph()->Constant(native_context()));
1281 24855 : for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) {
1282 7725 : a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant());
1283 : }
1284 : RelaxControls(node);
1285 9405 : a.FinishAndChange(node);
1286 : return Changed(node);
1287 : }
1288 :
1289 : return NoChange();
1290 : }
1291 :
1292 : namespace {
1293 40 : base::Optional<MapRef> GetObjectCreateMap(JSHeapBroker* broker,
1294 : HeapObjectRef prototype) {
1295 : MapRef standard_map =
1296 40 : broker->native_context().object_function().initial_map();
1297 40 : if (prototype.equals(standard_map.prototype())) {
1298 : return standard_map;
1299 : }
1300 32 : if (prototype.map().oddball_type() == OddballType::kNull) {
1301 32 : return broker->native_context().slow_object_with_null_prototype_map();
1302 : }
1303 16 : if (prototype.IsJSObject()) {
1304 16 : return prototype.AsJSObject().GetObjectCreateMap();
1305 : }
1306 0 : return base::Optional<MapRef>();
1307 : }
1308 : } // namespace
1309 :
1310 78 : Reduction JSCreateLowering::ReduceJSCreateObject(Node* node) {
1311 : DCHECK_EQ(IrOpcode::kJSCreateObject, node->opcode());
1312 78 : Node* effect = NodeProperties::GetEffectInput(node);
1313 78 : Node* control = NodeProperties::GetControlInput(node);
1314 78 : Node* prototype = NodeProperties::GetValueInput(node, 0);
1315 78 : Type prototype_type = NodeProperties::GetType(prototype);
1316 78 : if (!prototype_type.IsHeapConstant()) return NoChange();
1317 :
1318 40 : HeapObjectRef prototype_const = prototype_type.AsHeapConstant()->Ref();
1319 40 : auto maybe_instance_map = GetObjectCreateMap(broker(), prototype_const);
1320 40 : if (!maybe_instance_map) return NoChange();
1321 32 : MapRef instance_map = maybe_instance_map.value();
1322 :
1323 32 : Node* properties = jsgraph()->EmptyFixedArrayConstant();
1324 32 : if (instance_map.is_dictionary_map()) {
1325 : DCHECK_EQ(prototype_const.map().oddball_type(), OddballType::kNull);
1326 : // Allocate an empty NameDictionary as backing store for the properties.
1327 : MapRef map(broker(), factory()->name_dictionary_map());
1328 : int capacity =
1329 : NameDictionary::ComputeCapacity(NameDictionary::kInitialCapacity);
1330 : DCHECK(base::bits::IsPowerOfTwo(capacity));
1331 : int length = NameDictionary::EntryToIndex(capacity);
1332 : int size = NameDictionary::SizeFor(length);
1333 :
1334 : AllocationBuilder a(jsgraph(), effect, control);
1335 16 : a.Allocate(size, AllocationType::kYoung, Type::Any());
1336 16 : a.Store(AccessBuilder::ForMap(), map);
1337 : // Initialize FixedArray fields.
1338 32 : a.Store(AccessBuilder::ForFixedArrayLength(),
1339 16 : jsgraph()->SmiConstant(length));
1340 : // Initialize HashTable fields.
1341 32 : a.Store(AccessBuilder::ForHashTableBaseNumberOfElements(),
1342 16 : jsgraph()->SmiConstant(0));
1343 32 : a.Store(AccessBuilder::ForHashTableBaseNumberOfDeletedElement(),
1344 16 : jsgraph()->SmiConstant(0));
1345 32 : a.Store(AccessBuilder::ForHashTableBaseCapacity(),
1346 16 : jsgraph()->SmiConstant(capacity));
1347 : // Initialize Dictionary fields.
1348 32 : a.Store(AccessBuilder::ForDictionaryNextEnumerationIndex(),
1349 16 : jsgraph()->SmiConstant(PropertyDetails::kInitialIndex));
1350 32 : a.Store(AccessBuilder::ForDictionaryObjectHashIndex(),
1351 16 : jsgraph()->SmiConstant(PropertyArray::kNoHashSentinel));
1352 : // Initialize the Properties fields.
1353 16 : Node* undefined = jsgraph()->UndefinedConstant();
1354 : STATIC_ASSERT(NameDictionary::kElementsStartIndex ==
1355 : NameDictionary::kObjectHashIndex + 1);
1356 400 : for (int index = NameDictionary::kElementsStartIndex; index < length;
1357 : index++) {
1358 384 : a.Store(AccessBuilder::ForFixedArraySlot(index, kNoWriteBarrier),
1359 192 : undefined);
1360 : }
1361 16 : properties = effect = a.Finish();
1362 : }
1363 :
1364 32 : int const instance_size = instance_map.instance_size();
1365 32 : if (instance_size > kMaxRegularHeapObjectSize) return NoChange();
1366 32 : CHECK(!instance_map.IsInobjectSlackTrackingInProgress());
1367 :
1368 : // Emit code to allocate the JSObject instance for the given
1369 : // {instance_map}.
1370 : AllocationBuilder a(jsgraph(), effect, control);
1371 32 : a.Allocate(instance_size, AllocationType::kYoung, Type::Any());
1372 32 : a.Store(AccessBuilder::ForMap(), instance_map);
1373 32 : a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
1374 64 : a.Store(AccessBuilder::ForJSObjectElements(),
1375 32 : jsgraph()->EmptyFixedArrayConstant());
1376 : // Initialize Object fields.
1377 32 : Node* undefined = jsgraph()->UndefinedConstant();
1378 160 : for (int offset = JSObject::kHeaderSize; offset < instance_size;
1379 : offset += kTaggedSize) {
1380 128 : a.Store(AccessBuilder::ForJSObjectOffset(offset, kNoWriteBarrier),
1381 64 : undefined);
1382 : }
1383 32 : Node* value = effect = a.Finish();
1384 :
1385 : ReplaceWithValue(node, value, effect, control);
1386 : return Replace(value);
1387 : }
1388 :
1389 : // Helper that allocates a FixedArray holding argument values recorded in the
1390 : // given {frame_state}. Serves as backing store for JSCreateArguments nodes.
1391 600 : Node* JSCreateLowering::AllocateArguments(Node* effect, Node* control,
1392 : Node* frame_state) {
1393 600 : FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
1394 600 : int argument_count = state_info.parameter_count() - 1; // Minus receiver.
1395 600 : if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant();
1396 :
1397 : // Prepare an iterator over argument values recorded in the frame state.
1398 : Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
1399 : StateValuesAccess parameters_access(parameters);
1400 559 : auto parameters_it = ++parameters_access.begin();
1401 :
1402 : // Actually allocate the backing store.
1403 : AllocationBuilder a(jsgraph(), effect, control);
1404 559 : a.AllocateArray(argument_count, factory()->fixed_array_map());
1405 3205 : for (int i = 0; i < argument_count; ++i, ++parameters_it) {
1406 : DCHECK_NOT_NULL((*parameters_it).node);
1407 2646 : a.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i),
1408 1323 : (*parameters_it).node);
1409 : }
1410 559 : return a.Finish();
1411 : }
1412 :
1413 : // Helper that allocates a FixedArray holding argument values recorded in the
1414 : // given {frame_state}. Serves as backing store for JSCreateArguments nodes.
1415 560 : Node* JSCreateLowering::AllocateRestArguments(Node* effect, Node* control,
1416 : Node* frame_state,
1417 : int start_index) {
1418 560 : FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
1419 560 : int argument_count = state_info.parameter_count() - 1; // Minus receiver.
1420 1120 : int num_elements = std::max(0, argument_count - start_index);
1421 560 : if (num_elements == 0) return jsgraph()->EmptyFixedArrayConstant();
1422 :
1423 : // Prepare an iterator over argument values recorded in the frame state.
1424 : Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
1425 : StateValuesAccess parameters_access(parameters);
1426 461 : auto parameters_it = ++parameters_access.begin();
1427 :
1428 : // Skip unused arguments.
1429 739 : for (int i = 0; i < start_index; i++) {
1430 139 : ++parameters_it;
1431 : }
1432 :
1433 : // Actually allocate the backing store.
1434 : AllocationBuilder a(jsgraph(), effect, control);
1435 461 : a.AllocateArray(num_elements, factory()->fixed_array_map());
1436 2239 : for (int i = 0; i < num_elements; ++i, ++parameters_it) {
1437 : DCHECK_NOT_NULL((*parameters_it).node);
1438 1778 : a.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i),
1439 889 : (*parameters_it).node);
1440 : }
1441 461 : return a.Finish();
1442 : }
1443 :
1444 : // Helper that allocates a FixedArray serving as a parameter map for values
1445 : // recorded in the given {frame_state}. Some elements map to slots within the
1446 : // given {context}. Serves as backing store for JSCreateArguments nodes.
1447 642 : Node* JSCreateLowering::AllocateAliasedArguments(
1448 : Node* effect, Node* control, Node* frame_state, Node* context,
1449 : const SharedFunctionInfoRef& shared, bool* has_aliased_arguments) {
1450 642 : FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
1451 642 : int argument_count = state_info.parameter_count() - 1; // Minus receiver.
1452 642 : if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant();
1453 :
1454 : // If there is no aliasing, the arguments object elements are not special in
1455 : // any way, we can just return an unmapped backing store instead.
1456 520 : int parameter_count = shared.internal_formal_parameter_count();
1457 520 : if (parameter_count == 0) {
1458 177 : return AllocateArguments(effect, control, frame_state);
1459 : }
1460 :
1461 : // Calculate number of argument values being aliased/mapped.
1462 : int mapped_count = Min(argument_count, parameter_count);
1463 343 : *has_aliased_arguments = true;
1464 :
1465 : // Prepare an iterator over argument values recorded in the frame state.
1466 : Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
1467 : StateValuesAccess parameters_access(parameters);
1468 343 : auto parameters_it = ++parameters_access.begin();
1469 :
1470 : // The unmapped argument values recorded in the frame state are stored yet
1471 : // another indirection away and then linked into the parameter map below,
1472 : // whereas mapped argument values are replaced with a hole instead.
1473 : AllocationBuilder aa(jsgraph(), effect, control);
1474 343 : aa.AllocateArray(argument_count, factory()->fixed_array_map());
1475 1345 : for (int i = 0; i < mapped_count; ++i, ++parameters_it) {
1476 1002 : aa.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i),
1477 501 : jsgraph()->TheHoleConstant());
1478 : }
1479 357 : for (int i = mapped_count; i < argument_count; ++i, ++parameters_it) {
1480 : DCHECK_NOT_NULL((*parameters_it).node);
1481 14 : aa.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i),
1482 7 : (*parameters_it).node);
1483 : }
1484 343 : Node* arguments = aa.Finish();
1485 :
1486 : // Actually allocate the backing store.
1487 : AllocationBuilder a(jsgraph(), arguments, control);
1488 343 : a.AllocateArray(mapped_count + 2, factory()->sloppy_arguments_elements_map());
1489 686 : a.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(0),
1490 343 : context);
1491 686 : a.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(1),
1492 343 : arguments);
1493 1345 : for (int i = 0; i < mapped_count; ++i) {
1494 501 : int idx = Context::MIN_CONTEXT_SLOTS + parameter_count - 1 - i;
1495 1002 : a.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i + 2),
1496 501 : jsgraph()->Constant(idx));
1497 : }
1498 343 : return a.Finish();
1499 : }
1500 :
1501 : // Helper that allocates a FixedArray serving as a parameter map for values
1502 : // unknown at compile-time, the true {arguments_length} and {arguments_frame}
1503 : // values can only be determined dynamically at run-time and are provided.
1504 : // Serves as backing store for JSCreateArguments nodes.
1505 11281 : Node* JSCreateLowering::AllocateAliasedArguments(
1506 : Node* effect, Node* control, Node* context, Node* arguments_frame,
1507 : Node* arguments_length, const SharedFunctionInfoRef& shared,
1508 : bool* has_aliased_arguments) {
1509 : // If there is no aliasing, the arguments object elements are not
1510 : // special in any way, we can just return an unmapped backing store.
1511 11281 : int parameter_count = shared.internal_formal_parameter_count();
1512 11281 : if (parameter_count == 0) {
1513 8899 : return graph()->NewNode(simplified()->NewArgumentsElements(0),
1514 8899 : arguments_frame, arguments_length, effect);
1515 : }
1516 :
1517 : // From here on we are going to allocate a mapped (aka. aliased) elements
1518 : // backing store. We do not statically know how many arguments exist, but
1519 : // dynamically selecting the hole for some of the "mapped" elements allows
1520 : // using a static shape for the parameter map.
1521 : int mapped_count = parameter_count;
1522 2382 : *has_aliased_arguments = true;
1523 :
1524 : // The unmapped argument values are stored yet another indirection away and
1525 : // then linked into the parameter map below, whereas mapped argument values
1526 : // (i.e. the first {mapped_count} elements) are replaced with a hole instead.
1527 : Node* arguments =
1528 2382 : graph()->NewNode(simplified()->NewArgumentsElements(mapped_count),
1529 : arguments_frame, arguments_length, effect);
1530 :
1531 : // Actually allocate the backing store.
1532 : AllocationBuilder a(jsgraph(), arguments, control);
1533 2382 : a.AllocateArray(mapped_count + 2, factory()->sloppy_arguments_elements_map());
1534 4764 : a.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(0),
1535 2382 : context);
1536 4764 : a.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(1),
1537 2382 : arguments);
1538 9928 : for (int i = 0; i < mapped_count; ++i) {
1539 3773 : int idx = Context::MIN_CONTEXT_SLOTS + parameter_count - 1 - i;
1540 7546 : Node* value = graph()->NewNode(
1541 : common()->Select(MachineRepresentation::kTagged),
1542 : graph()->NewNode(simplified()->NumberLessThan(), jsgraph()->Constant(i),
1543 : arguments_length),
1544 : jsgraph()->Constant(idx), jsgraph()->TheHoleConstant());
1545 7546 : a.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i + 2),
1546 3773 : value);
1547 : }
1548 2382 : return a.Finish();
1549 : }
1550 :
1551 457 : Node* JSCreateLowering::AllocateElements(Node* effect, Node* control,
1552 : ElementsKind elements_kind,
1553 : int capacity,
1554 : AllocationType allocation) {
1555 : DCHECK_LE(1, capacity);
1556 : DCHECK_LE(capacity, JSArray::kInitialMaxFastElementArray);
1557 :
1558 : Handle<Map> elements_map = IsDoubleElementsKind(elements_kind)
1559 : ? factory()->fixed_double_array_map()
1560 914 : : factory()->fixed_array_map();
1561 : ElementAccess access = IsDoubleElementsKind(elements_kind)
1562 : ? AccessBuilder::ForFixedDoubleArrayElement()
1563 457 : : AccessBuilder::ForFixedArrayElement();
1564 457 : Node* value = jsgraph()->TheHoleConstant();
1565 :
1566 : // Actually allocate the backing store.
1567 : AllocationBuilder a(jsgraph(), effect, control);
1568 457 : a.AllocateArray(capacity, elements_map, allocation);
1569 4711 : for (int i = 0; i < capacity; ++i) {
1570 2127 : Node* index = jsgraph()->Constant(i);
1571 2127 : a.Store(access, index, value);
1572 : }
1573 457 : return a.Finish();
1574 : }
1575 :
1576 460 : Node* JSCreateLowering::AllocateElements(Node* effect, Node* control,
1577 : ElementsKind elements_kind,
1578 : std::vector<Node*> const& values,
1579 : AllocationType allocation) {
1580 460 : int const capacity = static_cast<int>(values.size());
1581 : DCHECK_LE(1, capacity);
1582 : DCHECK_LE(capacity, JSArray::kInitialMaxFastElementArray);
1583 :
1584 : Handle<Map> elements_map = IsDoubleElementsKind(elements_kind)
1585 : ? factory()->fixed_double_array_map()
1586 920 : : factory()->fixed_array_map();
1587 : ElementAccess access = IsDoubleElementsKind(elements_kind)
1588 : ? AccessBuilder::ForFixedDoubleArrayElement()
1589 460 : : AccessBuilder::ForFixedArrayElement();
1590 :
1591 : // Actually allocate the backing store.
1592 : AllocationBuilder a(jsgraph(), effect, control);
1593 460 : a.AllocateArray(capacity, elements_map, allocation);
1594 2714 : for (int i = 0; i < capacity; ++i) {
1595 1127 : Node* index = jsgraph()->Constant(i);
1596 2254 : a.Store(access, index, values[i]);
1597 : }
1598 460 : return a.Finish();
1599 : }
1600 :
1601 7014 : Node* JSCreateLowering::AllocateFastLiteral(Node* effect, Node* control,
1602 : JSObjectRef boilerplate,
1603 : AllocationType allocation) {
1604 : // Setup the properties backing store.
1605 7014 : Node* properties = jsgraph()->EmptyFixedArrayConstant();
1606 :
1607 : // Compute the in-object properties to store first (might have effects).
1608 7014 : MapRef boilerplate_map = boilerplate.map();
1609 : ZoneVector<std::pair<FieldAccess, Node*>> inobject_fields(zone());
1610 7014 : inobject_fields.reserve(boilerplate_map.GetInObjectProperties());
1611 7014 : int const boilerplate_nof = boilerplate_map.NumberOfOwnDescriptors();
1612 22204 : for (int i = 0; i < boilerplate_nof; ++i) {
1613 : PropertyDetails const property_details =
1614 7595 : boilerplate_map.GetPropertyDetails(i);
1615 11850 : if (property_details.location() != kField) continue;
1616 : DCHECK_EQ(kData, property_details.kind());
1617 3340 : NameRef property_name = boilerplate_map.GetPropertyKey(i);
1618 3340 : FieldIndex index = boilerplate_map.GetFieldIndexFor(i);
1619 : FieldAccess access = {
1620 : kTaggedBase, index.offset(), property_name.object(),
1621 : MaybeHandle<Map>(), Type::Any(), MachineType::AnyTagged(),
1622 3340 : kFullWriteBarrier};
1623 : Node* value;
1624 3340 : if (boilerplate_map.IsUnboxedDoubleField(i)) {
1625 : access.machine_type = MachineType::Float64();
1626 : access.type = Type::Number();
1627 130 : value = jsgraph()->Constant(boilerplate.RawFastDoublePropertyAt(index));
1628 : } else {
1629 3210 : ObjectRef boilerplate_value = boilerplate.RawFastPropertyAt(index);
1630 3210 : if (boilerplate_value.IsJSObject()) {
1631 312 : JSObjectRef boilerplate_object = boilerplate_value.AsJSObject();
1632 : value = effect = AllocateFastLiteral(effect, control,
1633 312 : boilerplate_object, allocation);
1634 2898 : } else if (property_details.representation().IsDouble()) {
1635 0 : double number = boilerplate_value.AsMutableHeapNumber().value();
1636 : // Allocate a mutable HeapNumber box and store the value into it.
1637 : AllocationBuilder builder(jsgraph(), effect, control);
1638 0 : builder.Allocate(HeapNumber::kSize, allocation);
1639 0 : builder.Store(AccessBuilder::ForMap(),
1640 0 : factory()->mutable_heap_number_map());
1641 0 : builder.Store(AccessBuilder::ForHeapNumberValue(),
1642 0 : jsgraph()->Constant(number));
1643 0 : value = effect = builder.Finish();
1644 2898 : } else if (property_details.representation().IsSmi()) {
1645 : // Ensure that value is stored as smi.
1646 : bool is_uninitialized =
1647 1666 : boilerplate_value.IsHeapObject() &&
1648 2023 : boilerplate_value.AsHeapObject().map().oddball_type() ==
1649 952 : OddballType::kUninitialized;
1650 : value = is_uninitialized
1651 : ? jsgraph()->ZeroConstant()
1652 1309 : : jsgraph()->Constant(boilerplate_value.AsSmi());
1653 : } else {
1654 1589 : value = jsgraph()->Constant(boilerplate_value);
1655 : }
1656 : }
1657 3340 : inobject_fields.push_back(std::make_pair(access, value));
1658 : }
1659 :
1660 : // Fill slack at the end of the boilerplate object with filler maps.
1661 7014 : int const boilerplate_length = boilerplate_map.GetInObjectProperties();
1662 9896 : for (int index = static_cast<int>(inobject_fields.size());
1663 9896 : index < boilerplate_length; ++index) {
1664 : FieldAccess access =
1665 2882 : AccessBuilder::ForJSObjectInObjectProperty(boilerplate_map, index);
1666 2882 : Node* value = jsgraph()->HeapConstant(factory()->one_pointer_filler_map());
1667 2882 : inobject_fields.push_back(std::make_pair(access, value));
1668 : }
1669 :
1670 : // Setup the elements backing store.
1671 : Node* elements =
1672 7014 : AllocateFastLiteralElements(effect, control, boilerplate, allocation);
1673 7014 : if (elements->op()->EffectOutputCount() > 0) effect = elements;
1674 :
1675 : // Actually allocate and initialize the object.
1676 : AllocationBuilder builder(jsgraph(), effect, control);
1677 7014 : builder.Allocate(boilerplate_map.instance_size(), allocation,
1678 7014 : Type::For(boilerplate_map));
1679 7014 : builder.Store(AccessBuilder::ForMap(), boilerplate_map);
1680 7014 : builder.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
1681 7014 : builder.Store(AccessBuilder::ForJSObjectElements(), elements);
1682 7014 : if (boilerplate.IsJSArray()) {
1683 4255 : JSArrayRef boilerplate_array = boilerplate.AsJSArray();
1684 : builder.Store(
1685 8510 : AccessBuilder::ForJSArrayLength(boilerplate_array.GetElementsKind()),
1686 12765 : boilerplate_array.length());
1687 : }
1688 13236 : for (auto const& inobject_field : inobject_fields) {
1689 6222 : builder.Store(inobject_field.first, inobject_field.second);
1690 : }
1691 14028 : return builder.Finish();
1692 : }
1693 :
1694 7014 : Node* JSCreateLowering::AllocateFastLiteralElements(Node* effect, Node* control,
1695 : JSObjectRef boilerplate,
1696 : AllocationType allocation) {
1697 7014 : FixedArrayBaseRef boilerplate_elements = boilerplate.elements();
1698 :
1699 : // Empty or copy-on-write elements just store a constant.
1700 7014 : int const elements_length = boilerplate_elements.length();
1701 7014 : MapRef elements_map = boilerplate_elements.map();
1702 7014 : if (boilerplate_elements.length() == 0 || elements_map.IsFixedCowArrayMap()) {
1703 4661 : if (allocation == AllocationType::kOld) {
1704 40 : boilerplate.EnsureElementsTenured();
1705 40 : boilerplate_elements = boilerplate.elements();
1706 : }
1707 9322 : return jsgraph()->HeapConstant(boilerplate_elements.object());
1708 : }
1709 :
1710 : // Compute the elements to store first (might have effects).
1711 2353 : ZoneVector<Node*> elements_values(elements_length, zone());
1712 2353 : if (elements_map.instance_type() == FIXED_DOUBLE_ARRAY_TYPE) {
1713 516 : FixedDoubleArrayRef elements = boilerplate_elements.AsFixedDoubleArray();
1714 14902 : for (int i = 0; i < elements_length; ++i) {
1715 7193 : if (elements.is_the_hole(i)) {
1716 198 : elements_values[i] = jsgraph()->TheHoleConstant();
1717 : } else {
1718 14188 : elements_values[i] = jsgraph()->Constant(elements.get_scalar(i));
1719 : }
1720 : }
1721 : } else {
1722 1837 : FixedArrayRef elements = boilerplate_elements.AsFixedArray();
1723 16943 : for (int i = 0; i < elements_length; ++i) {
1724 7553 : ObjectRef element_value = elements.get(i);
1725 7553 : if (element_value.IsJSObject()) {
1726 1276 : elements_values[i] = effect = AllocateFastLiteral(
1727 638 : effect, control, element_value.AsJSObject(), allocation);
1728 : } else {
1729 13830 : elements_values[i] = jsgraph()->Constant(element_value);
1730 : }
1731 : }
1732 : }
1733 :
1734 : // Allocate the backing store array and store the elements.
1735 : AllocationBuilder builder(jsgraph(), effect, control);
1736 2353 : builder.AllocateArray(elements_length, elements_map.object(), allocation);
1737 : ElementAccess const access =
1738 2353 : (elements_map.instance_type() == FIXED_DOUBLE_ARRAY_TYPE)
1739 : ? AccessBuilder::ForFixedDoubleArrayElement()
1740 2353 : : AccessBuilder::ForFixedArrayElement();
1741 31845 : for (int i = 0; i < elements_length; ++i) {
1742 29492 : builder.Store(access, jsgraph()->Constant(i), elements_values[i]);
1743 : }
1744 2353 : return builder.Finish();
1745 : }
1746 :
1747 574 : Node* JSCreateLowering::AllocateLiteralRegExp(Node* effect, Node* control,
1748 : JSRegExpRef boilerplate) {
1749 574 : MapRef boilerplate_map = boilerplate.map();
1750 :
1751 : // Sanity check that JSRegExp object layout hasn't changed.
1752 : STATIC_ASSERT(static_cast<int>(JSRegExp::kDataOffset) ==
1753 : static_cast<int>(JSObject::kHeaderSize));
1754 : STATIC_ASSERT(JSRegExp::kSourceOffset == JSRegExp::kDataOffset + kTaggedSize);
1755 : STATIC_ASSERT(JSRegExp::kFlagsOffset ==
1756 : JSRegExp::kSourceOffset + kTaggedSize);
1757 : STATIC_ASSERT(JSRegExp::kSize == JSRegExp::kFlagsOffset + kTaggedSize);
1758 : STATIC_ASSERT(JSRegExp::kLastIndexOffset == JSRegExp::kSize);
1759 : STATIC_ASSERT(JSRegExp::kInObjectFieldCount == 1); // LastIndex.
1760 :
1761 : const AllocationType allocation = AllocationType::kYoung;
1762 : const int size =
1763 : JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kTaggedSize;
1764 :
1765 : AllocationBuilder builder(jsgraph(), effect, control);
1766 574 : builder.Allocate(size, allocation, Type::For(boilerplate_map));
1767 574 : builder.Store(AccessBuilder::ForMap(), boilerplate_map);
1768 1148 : builder.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
1769 1722 : boilerplate.raw_properties_or_hash());
1770 574 : builder.Store(AccessBuilder::ForJSObjectElements(), boilerplate.elements());
1771 :
1772 574 : builder.Store(AccessBuilder::ForJSRegExpData(), boilerplate.data());
1773 574 : builder.Store(AccessBuilder::ForJSRegExpSource(), boilerplate.source());
1774 574 : builder.Store(AccessBuilder::ForJSRegExpFlags(), boilerplate.flags());
1775 1148 : builder.Store(AccessBuilder::ForJSRegExpLastIndex(),
1776 1722 : boilerplate.last_index());
1777 :
1778 574 : return builder.Finish();
1779 : }
1780 :
1781 0 : Factory* JSCreateLowering::factory() const {
1782 0 : return jsgraph()->isolate()->factory();
1783 : }
1784 :
1785 0 : Graph* JSCreateLowering::graph() const { return jsgraph()->graph(); }
1786 :
1787 0 : CommonOperatorBuilder* JSCreateLowering::common() const {
1788 0 : return jsgraph()->common();
1789 : }
1790 :
1791 0 : SimplifiedOperatorBuilder* JSCreateLowering::simplified() const {
1792 0 : return jsgraph()->simplified();
1793 : }
1794 :
1795 0 : NativeContextRef JSCreateLowering::native_context() const {
1796 115050 : return broker()->native_context();
1797 : }
1798 :
1799 : } // namespace compiler
1800 : } // namespace internal
1801 122004 : } // namespace v8
|