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