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