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