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/allocation-site-scopes.h"
8#include "src/code-factory.h"
9#include "src/compilation-dependencies.h"
10#include "src/compiler/access-builder.h"
11#include "src/compiler/common-operator.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.h"
16#include "src/compiler/node-properties.h"
17#include "src/compiler/operator-properties.h"
18#include "src/compiler/simplified-operator.h"
19#include "src/compiler/state-values-utils.h"
20
21namespace v8 {
22namespace internal {
23namespace compiler {
24
25namespace {
26
27// A helper class to construct inline allocations on the simplified operator
28// level. This keeps track of the effect chain for initial stores on a newly
29// allocated object and also provides helpers for commonly allocated objects.
30class AllocationBuilder final {
31 public:
32  AllocationBuilder(JSGraph* jsgraph, Node* effect, Node* control)
33      : jsgraph_(jsgraph),
34        allocation_(nullptr),
35        effect_(effect),
36        control_(control) {}
37
38  // Primitive allocation of static size.
39  void Allocate(int size, PretenureFlag pretenure = NOT_TENURED) {
40    effect_ = graph()->NewNode(
41        common()->BeginRegion(RegionObservability::kNotObservable), effect_);
42    allocation_ =
43        graph()->NewNode(simplified()->Allocate(pretenure),
44                         jsgraph()->Constant(size), effect_, control_);
45    effect_ = allocation_;
46  }
47
48  // Primitive store into a field.
49  void Store(const FieldAccess& access, Node* value) {
50    effect_ = graph()->NewNode(simplified()->StoreField(access), allocation_,
51                               value, effect_, control_);
52  }
53
54  // Primitive store into an element.
55  void Store(ElementAccess const& access, Node* index, Node* value) {
56    effect_ = graph()->NewNode(simplified()->StoreElement(access), allocation_,
57                               index, value, effect_, control_);
58  }
59
60  // Compound allocation of a FixedArray.
61  void AllocateArray(int length, Handle<Map> map,
62                     PretenureFlag pretenure = NOT_TENURED) {
63    DCHECK(map->instance_type() == FIXED_ARRAY_TYPE ||
64           map->instance_type() == FIXED_DOUBLE_ARRAY_TYPE);
65    int size = (map->instance_type() == FIXED_ARRAY_TYPE)
66                   ? FixedArray::SizeFor(length)
67                   : FixedDoubleArray::SizeFor(length);
68    Allocate(size, pretenure);
69    Store(AccessBuilder::ForMap(), map);
70    Store(AccessBuilder::ForFixedArrayLength(), jsgraph()->Constant(length));
71  }
72
73  // Compound store of a constant into a field.
74  void Store(const FieldAccess& access, Handle<Object> value) {
75    Store(access, jsgraph()->Constant(value));
76  }
77
78  void FinishAndChange(Node* node) {
79    NodeProperties::SetType(allocation_, NodeProperties::GetType(node));
80    node->ReplaceInput(0, allocation_);
81    node->ReplaceInput(1, effect_);
82    node->TrimInputCount(2);
83    NodeProperties::ChangeOp(node, common()->FinishRegion());
84  }
85
86  Node* Finish() {
87    return graph()->NewNode(common()->FinishRegion(), allocation_, effect_);
88  }
89
90 protected:
91  JSGraph* jsgraph() { return jsgraph_; }
92  Graph* graph() { return jsgraph_->graph(); }
93  CommonOperatorBuilder* common() { return jsgraph_->common(); }
94  SimplifiedOperatorBuilder* simplified() { return jsgraph_->simplified(); }
95
96 private:
97  JSGraph* const jsgraph_;
98  Node* allocation_;
99  Node* effect_;
100  Node* control_;
101};
102
103// Retrieves the frame state holding actual argument values.
104Node* GetArgumentsFrameState(Node* frame_state) {
105  Node* const outer_state = NodeProperties::GetFrameStateInput(frame_state, 0);
106  FrameStateInfo outer_state_info = OpParameter<FrameStateInfo>(outer_state);
107  return outer_state_info.type() == FrameStateType::kArgumentsAdaptor
108             ? outer_state
109             : frame_state;
110}
111
112// Checks whether allocation using the given target and new.target can be
113// inlined.
114bool IsAllocationInlineable(Handle<JSFunction> target,
115                            Handle<JSFunction> new_target) {
116  return new_target->has_initial_map() &&
117         new_target->initial_map()->constructor_or_backpointer() == *target;
118}
119
120// When initializing arrays, we'll unfold the loop if the number of
121// elements is known to be of this type.
122const int kElementLoopUnrollLimit = 16;
123
124// Limits up to which context allocations are inlined.
125const int kFunctionContextAllocationLimit = 16;
126const int kBlockContextAllocationLimit = 16;
127
128// Determines whether the given array or object literal boilerplate satisfies
129// all limits to be considered for fast deep-copying and computes the total
130// size of all objects that are part of the graph.
131bool IsFastLiteral(Handle<JSObject> boilerplate, int max_depth,
132                   int* max_properties) {
133  DCHECK_GE(max_depth, 0);
134  DCHECK_GE(*max_properties, 0);
135
136  // Make sure the boilerplate map is not deprecated.
137  if (!JSObject::TryMigrateInstance(boilerplate)) return false;
138
139  // Check for too deep nesting.
140  if (max_depth == 0) return false;
141
142  // Check the elements.
143  Isolate* const isolate = boilerplate->GetIsolate();
144  Handle<FixedArrayBase> elements(boilerplate->elements(), isolate);
145  if (elements->length() > 0 &&
146      elements->map() != isolate->heap()->fixed_cow_array_map()) {
147    if (boilerplate->HasFastSmiOrObjectElements()) {
148      Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
149      int length = elements->length();
150      for (int i = 0; i < length; i++) {
151        if ((*max_properties)-- == 0) return false;
152        Handle<Object> value(fast_elements->get(i), isolate);
153        if (value->IsJSObject()) {
154          Handle<JSObject> value_object = Handle<JSObject>::cast(value);
155          if (!IsFastLiteral(value_object, max_depth - 1, max_properties)) {
156            return false;
157          }
158        }
159      }
160    } else if (!boilerplate->HasFastDoubleElements()) {
161      return false;
162    }
163  }
164
165  // TODO(turbofan): Do we want to support out-of-object properties?
166  Handle<FixedArray> properties(boilerplate->properties(), isolate);
167  if (properties->length() > 0) return false;
168
169  // Check the in-object properties.
170  Handle<DescriptorArray> descriptors(
171      boilerplate->map()->instance_descriptors(), isolate);
172  int limit = boilerplate->map()->NumberOfOwnDescriptors();
173  for (int i = 0; i < limit; i++) {
174    PropertyDetails details = descriptors->GetDetails(i);
175    if (details.type() != DATA) continue;
176    if ((*max_properties)-- == 0) return false;
177    FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
178    if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
179    Handle<Object> value(boilerplate->RawFastPropertyAt(field_index), isolate);
180    if (value->IsJSObject()) {
181      Handle<JSObject> value_object = Handle<JSObject>::cast(value);
182      if (!IsFastLiteral(value_object, max_depth - 1, max_properties)) {
183        return false;
184      }
185    }
186  }
187  return true;
188}
189
190// Maximum depth and total number of elements and properties for literal
191// graphs to be considered for fast deep-copying.
192const int kMaxFastLiteralDepth = 3;
193const int kMaxFastLiteralProperties = 8;
194
195}  // namespace
196
197Reduction JSCreateLowering::Reduce(Node* node) {
198  switch (node->opcode()) {
199    case IrOpcode::kJSCreate:
200      return ReduceJSCreate(node);
201    case IrOpcode::kJSCreateArguments:
202      return ReduceJSCreateArguments(node);
203    case IrOpcode::kJSCreateArray:
204      return ReduceJSCreateArray(node);
205    case IrOpcode::kJSCreateClosure:
206      return ReduceJSCreateClosure(node);
207    case IrOpcode::kJSCreateIterResultObject:
208      return ReduceJSCreateIterResultObject(node);
209    case IrOpcode::kJSCreateLiteralArray:
210    case IrOpcode::kJSCreateLiteralObject:
211      return ReduceJSCreateLiteral(node);
212    case IrOpcode::kJSCreateFunctionContext:
213      return ReduceJSCreateFunctionContext(node);
214    case IrOpcode::kJSCreateWithContext:
215      return ReduceJSCreateWithContext(node);
216    case IrOpcode::kJSCreateCatchContext:
217      return ReduceJSCreateCatchContext(node);
218    case IrOpcode::kJSCreateBlockContext:
219      return ReduceJSCreateBlockContext(node);
220    default:
221      break;
222  }
223  return NoChange();
224}
225
226Reduction JSCreateLowering::ReduceJSCreate(Node* node) {
227  DCHECK_EQ(IrOpcode::kJSCreate, node->opcode());
228  Node* const target = NodeProperties::GetValueInput(node, 0);
229  Type* const target_type = NodeProperties::GetType(target);
230  Node* const new_target = NodeProperties::GetValueInput(node, 1);
231  Type* const new_target_type = NodeProperties::GetType(new_target);
232  Node* const effect = NodeProperties::GetEffectInput(node);
233  // Extract constructor and original constructor function.
234  if (target_type->IsConstant() &&
235      new_target_type->IsConstant() &&
236      new_target_type->AsConstant()->Value()->IsJSFunction()) {
237    Handle<JSFunction> constructor =
238        Handle<JSFunction>::cast(target_type->AsConstant()->Value());
239    Handle<JSFunction> original_constructor =
240        Handle<JSFunction>::cast(new_target_type->AsConstant()->Value());
241    DCHECK(constructor->IsConstructor());
242    DCHECK(original_constructor->IsConstructor());
243
244    // Check if we can inline the allocation.
245    if (IsAllocationInlineable(constructor, original_constructor)) {
246      // Force completion of inobject slack tracking before
247      // generating code to finalize the instance size.
248      original_constructor->CompleteInobjectSlackTrackingIfActive();
249
250      // Compute instance size from initial map of {original_constructor}.
251      Handle<Map> initial_map(original_constructor->initial_map(), isolate());
252      int const instance_size = initial_map->instance_size();
253
254      // Add a dependency on the {initial_map} to make sure that this code is
255      // deoptimized whenever the {initial_map} of the {original_constructor}
256      // changes.
257      dependencies()->AssumeInitialMapCantChange(initial_map);
258
259      // Emit code to allocate the JSObject instance for the
260      // {original_constructor}.
261      AllocationBuilder a(jsgraph(), effect, graph()->start());
262      a.Allocate(instance_size);
263      a.Store(AccessBuilder::ForMap(), initial_map);
264      a.Store(AccessBuilder::ForJSObjectProperties(),
265              jsgraph()->EmptyFixedArrayConstant());
266      a.Store(AccessBuilder::ForJSObjectElements(),
267              jsgraph()->EmptyFixedArrayConstant());
268      for (int i = 0; i < initial_map->GetInObjectProperties(); ++i) {
269        a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
270                jsgraph()->UndefinedConstant());
271      }
272      a.FinishAndChange(node);
273      return Changed(node);
274    }
275  }
276  return NoChange();
277}
278
279Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
280  DCHECK_EQ(IrOpcode::kJSCreateArguments, node->opcode());
281  CreateArgumentsType type = CreateArgumentsTypeOf(node->op());
282  Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0);
283  Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
284  Node* const control = graph()->start();
285  FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
286
287  // Use the ArgumentsAccessStub for materializing both mapped and unmapped
288  // arguments object, but only for non-inlined (i.e. outermost) frames.
289  if (outer_state->opcode() != IrOpcode::kFrameState) {
290    switch (type) {
291      case CreateArgumentsType::kMappedArguments: {
292        // TODO(mstarzinger): Duplicate parameters are not handled yet.
293        Handle<SharedFunctionInfo> shared_info;
294        if (!state_info.shared_info().ToHandle(&shared_info) ||
295            shared_info->has_duplicate_parameters()) {
296          return NoChange();
297        }
298        Callable callable = CodeFactory::FastNewSloppyArguments(isolate());
299        Operator::Properties properties = node->op()->properties();
300        CallDescriptor* desc = Linkage::GetStubCallDescriptor(
301            isolate(), graph()->zone(), callable.descriptor(), 0,
302            CallDescriptor::kNoFlags, properties);
303        const Operator* new_op = common()->Call(desc);
304        Node* stub_code = jsgraph()->HeapConstant(callable.code());
305        node->InsertInput(graph()->zone(), 0, stub_code);
306        node->RemoveInput(3);  // Remove the frame state.
307        NodeProperties::ChangeOp(node, new_op);
308        return Changed(node);
309      }
310      case CreateArgumentsType::kUnmappedArguments: {
311        Callable callable = CodeFactory::FastNewStrictArguments(isolate());
312        Operator::Properties properties = node->op()->properties();
313        CallDescriptor* desc = Linkage::GetStubCallDescriptor(
314            isolate(), graph()->zone(), callable.descriptor(), 0,
315            CallDescriptor::kNeedsFrameState, properties);
316        const Operator* new_op = common()->Call(desc);
317        Node* stub_code = jsgraph()->HeapConstant(callable.code());
318        node->InsertInput(graph()->zone(), 0, stub_code);
319        NodeProperties::ChangeOp(node, new_op);
320        return Changed(node);
321      }
322      case CreateArgumentsType::kRestParameter: {
323        Callable callable = CodeFactory::FastNewRestParameter(isolate());
324        Operator::Properties properties = node->op()->properties();
325        CallDescriptor* desc = Linkage::GetStubCallDescriptor(
326            isolate(), graph()->zone(), callable.descriptor(), 0,
327            CallDescriptor::kNeedsFrameState, properties);
328        const Operator* new_op = common()->Call(desc);
329        Node* stub_code = jsgraph()->HeapConstant(callable.code());
330        node->InsertInput(graph()->zone(), 0, stub_code);
331        NodeProperties::ChangeOp(node, new_op);
332        return Changed(node);
333      }
334    }
335    UNREACHABLE();
336  } else if (outer_state->opcode() == IrOpcode::kFrameState) {
337    // Use inline allocation for all mapped arguments objects within inlined
338    // (i.e. non-outermost) frames, independent of the object size.
339    if (type == CreateArgumentsType::kMappedArguments) {
340      Handle<SharedFunctionInfo> shared;
341      if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
342      Node* const callee = NodeProperties::GetValueInput(node, 0);
343      Node* const context = NodeProperties::GetContextInput(node);
344      Node* effect = NodeProperties::GetEffectInput(node);
345      // TODO(mstarzinger): Duplicate parameters are not handled yet.
346      if (shared->has_duplicate_parameters()) return NoChange();
347      // Choose the correct frame state and frame state info depending on
348      // whether there conceptually is an arguments adaptor frame in the call
349      // chain.
350      Node* const args_state = GetArgumentsFrameState(frame_state);
351      FrameStateInfo args_state_info = OpParameter<FrameStateInfo>(args_state);
352      // Prepare element backing store to be used by arguments object.
353      bool has_aliased_arguments = false;
354      Node* const elements = AllocateAliasedArguments(
355          effect, control, args_state, context, shared, &has_aliased_arguments);
356      effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
357      // Load the arguments object map from the current native context.
358      Node* const load_native_context = effect = graph()->NewNode(
359          javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
360          context, context, effect);
361      Node* const load_arguments_map = effect = graph()->NewNode(
362          simplified()->LoadField(AccessBuilder::ForContextSlot(
363              has_aliased_arguments ? Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX
364                                    : Context::SLOPPY_ARGUMENTS_MAP_INDEX)),
365          load_native_context, effect, control);
366      // Actually allocate and initialize the arguments object.
367      AllocationBuilder a(jsgraph(), effect, control);
368      Node* properties = jsgraph()->EmptyFixedArrayConstant();
369      int length = args_state_info.parameter_count() - 1;  // Minus receiver.
370      STATIC_ASSERT(JSSloppyArgumentsObject::kSize == 5 * kPointerSize);
371      a.Allocate(JSSloppyArgumentsObject::kSize);
372      a.Store(AccessBuilder::ForMap(), load_arguments_map);
373      a.Store(AccessBuilder::ForJSObjectProperties(), properties);
374      a.Store(AccessBuilder::ForJSObjectElements(), elements);
375      a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length));
376      a.Store(AccessBuilder::ForArgumentsCallee(), callee);
377      RelaxControls(node);
378      a.FinishAndChange(node);
379      return Changed(node);
380    } else if (type == CreateArgumentsType::kUnmappedArguments) {
381      // Use inline allocation for all unmapped arguments objects within inlined
382      // (i.e. non-outermost) frames, independent of the object size.
383      Node* const context = NodeProperties::GetContextInput(node);
384      Node* effect = NodeProperties::GetEffectInput(node);
385      // Choose the correct frame state and frame state info depending on
386      // whether there conceptually is an arguments adaptor frame in the call
387      // chain.
388      Node* const args_state = GetArgumentsFrameState(frame_state);
389      FrameStateInfo args_state_info = OpParameter<FrameStateInfo>(args_state);
390      // Prepare element backing store to be used by arguments object.
391      Node* const elements = AllocateArguments(effect, control, args_state);
392      effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
393      // Load the arguments object map from the current native context.
394      Node* const load_native_context = effect = graph()->NewNode(
395          javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
396          context, context, effect);
397      Node* const load_arguments_map = effect = graph()->NewNode(
398          simplified()->LoadField(AccessBuilder::ForContextSlot(
399              Context::STRICT_ARGUMENTS_MAP_INDEX)),
400          load_native_context, effect, control);
401      // Actually allocate and initialize the arguments object.
402      AllocationBuilder a(jsgraph(), effect, control);
403      Node* properties = jsgraph()->EmptyFixedArrayConstant();
404      int length = args_state_info.parameter_count() - 1;  // Minus receiver.
405      STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
406      a.Allocate(JSStrictArgumentsObject::kSize);
407      a.Store(AccessBuilder::ForMap(), load_arguments_map);
408      a.Store(AccessBuilder::ForJSObjectProperties(), properties);
409      a.Store(AccessBuilder::ForJSObjectElements(), elements);
410      a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length));
411      RelaxControls(node);
412      a.FinishAndChange(node);
413      return Changed(node);
414    } else if (type == CreateArgumentsType::kRestParameter) {
415      Handle<SharedFunctionInfo> shared;
416      if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
417      int start_index = shared->internal_formal_parameter_count();
418      // Use inline allocation for all unmapped arguments objects within inlined
419      // (i.e. non-outermost) frames, independent of the object size.
420      Node* const context = NodeProperties::GetContextInput(node);
421      Node* effect = NodeProperties::GetEffectInput(node);
422      // Choose the correct frame state and frame state info depending on
423      // whether there conceptually is an arguments adaptor frame in the call
424      // chain.
425      Node* const args_state = GetArgumentsFrameState(frame_state);
426      FrameStateInfo args_state_info = OpParameter<FrameStateInfo>(args_state);
427      // Prepare element backing store to be used by the rest array.
428      Node* const elements =
429          AllocateRestArguments(effect, control, args_state, start_index);
430      effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
431      // Load the JSArray object map from the current native context.
432      Node* const load_native_context = effect = graph()->NewNode(
433          javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
434          context, context, effect);
435      Node* const load_jsarray_map = effect = graph()->NewNode(
436          simplified()->LoadField(AccessBuilder::ForContextSlot(
437              Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX)),
438          load_native_context, effect, control);
439      // Actually allocate and initialize the jsarray.
440      AllocationBuilder a(jsgraph(), effect, control);
441      Node* properties = jsgraph()->EmptyFixedArrayConstant();
442
443      // -1 to minus receiver
444      int argument_count = args_state_info.parameter_count() - 1;
445      int length = std::max(0, argument_count - start_index);
446      STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
447      a.Allocate(JSArray::kSize);
448      a.Store(AccessBuilder::ForMap(), load_jsarray_map);
449      a.Store(AccessBuilder::ForJSObjectProperties(), properties);
450      a.Store(AccessBuilder::ForJSObjectElements(), elements);
451      a.Store(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS),
452              jsgraph()->Constant(length));
453      RelaxControls(node);
454      a.FinishAndChange(node);
455      return Changed(node);
456    }
457  }
458
459  return NoChange();
460}
461
462Reduction JSCreateLowering::ReduceNewArray(Node* node, Node* length,
463                                           int capacity,
464                                           Handle<AllocationSite> site) {
465  DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
466  Node* context = NodeProperties::GetContextInput(node);
467  Node* effect = NodeProperties::GetEffectInput(node);
468  Node* control = NodeProperties::GetControlInput(node);
469
470  // Extract transition and tenuring feedback from the {site} and add
471  // appropriate code dependencies on the {site} if deoptimization is
472  // enabled.
473  PretenureFlag pretenure = site->GetPretenureMode();
474  ElementsKind elements_kind = site->GetElementsKind();
475  DCHECK(IsFastElementsKind(elements_kind));
476  if (NodeProperties::GetType(length)->Max() > 0) {
477    elements_kind = GetHoleyElementsKind(elements_kind);
478  }
479  dependencies()->AssumeTenuringDecision(site);
480  dependencies()->AssumeTransitionStable(site);
481
482  // Retrieve the initial map for the array from the appropriate native context.
483  Node* native_context = effect = graph()->NewNode(
484      javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
485      context, context, effect);
486  Node* js_array_map = effect = graph()->NewNode(
487      javascript()->LoadContext(0, Context::ArrayMapIndex(elements_kind), true),
488      native_context, native_context, effect);
489
490  // Setup elements and properties.
491  Node* elements;
492  if (capacity == 0) {
493    elements = jsgraph()->EmptyFixedArrayConstant();
494  } else {
495    elements = effect =
496        AllocateElements(effect, control, elements_kind, capacity, pretenure);
497  }
498  Node* properties = jsgraph()->EmptyFixedArrayConstant();
499
500  // Perform the allocation of the actual JSArray object.
501  AllocationBuilder a(jsgraph(), effect, control);
502  a.Allocate(JSArray::kSize, pretenure);
503  a.Store(AccessBuilder::ForMap(), js_array_map);
504  a.Store(AccessBuilder::ForJSObjectProperties(), properties);
505  a.Store(AccessBuilder::ForJSObjectElements(), elements);
506  a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length);
507  RelaxControls(node);
508  a.FinishAndChange(node);
509  return Changed(node);
510}
511
512Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
513  DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
514  CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
515  Node* target = NodeProperties::GetValueInput(node, 0);
516  Node* new_target = NodeProperties::GetValueInput(node, 1);
517
518  // TODO(bmeurer): Optimize the subclassing case.
519  if (target != new_target) return NoChange();
520
521  // Check if we have a feedback {site} on the {node}.
522  Handle<AllocationSite> site = p.site();
523  if (p.site().is_null()) return NoChange();
524
525  // Attempt to inline calls to the Array constructor for the relevant cases
526  // where either no arguments are provided, or exactly one unsigned number
527  // argument is given.
528  if (site->CanInlineCall()) {
529    if (p.arity() == 0) {
530      Node* length = jsgraph()->ZeroConstant();
531      int capacity = JSArray::kPreallocatedArrayElements;
532      return ReduceNewArray(node, length, capacity, site);
533    } else if (p.arity() == 1) {
534      Node* length = NodeProperties::GetValueInput(node, 2);
535      Type* length_type = NodeProperties::GetType(length);
536      if (length_type->Is(Type::SignedSmall()) &&
537          length_type->Min() >= 0 &&
538          length_type->Max() <= kElementLoopUnrollLimit) {
539        int capacity = static_cast<int>(length_type->Max());
540        return ReduceNewArray(node, length, capacity, site);
541      }
542    }
543  }
544
545  return NoChange();
546}
547
548Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
549  DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode());
550  CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
551  Handle<SharedFunctionInfo> shared = p.shared_info();
552
553  Node* effect = NodeProperties::GetEffectInput(node);
554  Node* control = NodeProperties::GetControlInput(node);
555  Node* context = NodeProperties::GetContextInput(node);
556  Node* native_context = effect = graph()->NewNode(
557      javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
558      context, context, effect);
559  int function_map_index =
560      Context::FunctionMapIndex(shared->language_mode(), shared->kind());
561  Node* function_map = effect =
562      graph()->NewNode(javascript()->LoadContext(0, function_map_index, true),
563                       native_context, native_context, effect);
564  // Note that it is only safe to embed the raw entry point of the compile
565  // lazy stub into the code, because that stub is immortal and immovable.
566  Node* compile_entry = jsgraph()->IntPtrConstant(reinterpret_cast<intptr_t>(
567      jsgraph()->isolate()->builtins()->CompileLazy()->entry()));
568  Node* empty_fixed_array = jsgraph()->EmptyFixedArrayConstant();
569  Node* empty_literals_array = jsgraph()->EmptyLiteralsArrayConstant();
570  Node* the_hole = jsgraph()->TheHoleConstant();
571  Node* undefined = jsgraph()->UndefinedConstant();
572  AllocationBuilder a(jsgraph(), effect, control);
573  STATIC_ASSERT(JSFunction::kSize == 9 * kPointerSize);
574  a.Allocate(JSFunction::kSize, p.pretenure());
575  a.Store(AccessBuilder::ForMap(), function_map);
576  a.Store(AccessBuilder::ForJSObjectProperties(), empty_fixed_array);
577  a.Store(AccessBuilder::ForJSObjectElements(), empty_fixed_array);
578  a.Store(AccessBuilder::ForJSFunctionLiterals(), empty_literals_array);
579  a.Store(AccessBuilder::ForJSFunctionPrototypeOrInitialMap(), the_hole);
580  a.Store(AccessBuilder::ForJSFunctionSharedFunctionInfo(), shared);
581  a.Store(AccessBuilder::ForJSFunctionContext(), context);
582  a.Store(AccessBuilder::ForJSFunctionCodeEntry(), compile_entry);
583  a.Store(AccessBuilder::ForJSFunctionNextFunctionLink(), undefined);
584  RelaxControls(node);
585  a.FinishAndChange(node);
586  return Changed(node);
587}
588
589Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) {
590  DCHECK_EQ(IrOpcode::kJSCreateIterResultObject, node->opcode());
591  Node* value = NodeProperties::GetValueInput(node, 0);
592  Node* done = NodeProperties::GetValueInput(node, 1);
593  Node* context = NodeProperties::GetContextInput(node);
594  Node* effect = NodeProperties::GetEffectInput(node);
595
596  // Load the JSIteratorResult map for the {context}.
597  Node* native_context = effect = graph()->NewNode(
598      javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
599      context, context, effect);
600  Node* iterator_result_map = effect = graph()->NewNode(
601      javascript()->LoadContext(0, Context::ITERATOR_RESULT_MAP_INDEX, true),
602      native_context, native_context, effect);
603
604  // Emit code to allocate the JSIteratorResult instance.
605  AllocationBuilder a(jsgraph(), effect, graph()->start());
606  a.Allocate(JSIteratorResult::kSize);
607  a.Store(AccessBuilder::ForMap(), iterator_result_map);
608  a.Store(AccessBuilder::ForJSObjectProperties(),
609          jsgraph()->EmptyFixedArrayConstant());
610  a.Store(AccessBuilder::ForJSObjectElements(),
611          jsgraph()->EmptyFixedArrayConstant());
612  a.Store(AccessBuilder::ForJSIteratorResultValue(), value);
613  a.Store(AccessBuilder::ForJSIteratorResultDone(), done);
614  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
615  a.FinishAndChange(node);
616  return Changed(node);
617}
618
619Reduction JSCreateLowering::ReduceJSCreateLiteral(Node* node) {
620  DCHECK(node->opcode() == IrOpcode::kJSCreateLiteralArray ||
621         node->opcode() == IrOpcode::kJSCreateLiteralObject);
622  CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
623  Node* effect = NodeProperties::GetEffectInput(node);
624  Node* control = NodeProperties::GetControlInput(node);
625
626  Handle<LiteralsArray> literals_array;
627  if (GetSpecializationLiterals(node).ToHandle(&literals_array)) {
628    Handle<Object> literal(literals_array->literal(p.index()), isolate());
629    if (literal->IsAllocationSite()) {
630      Handle<AllocationSite> site = Handle<AllocationSite>::cast(literal);
631      Handle<JSObject> boilerplate(JSObject::cast(site->transition_info()),
632                                   isolate());
633      int max_properties = kMaxFastLiteralProperties;
634      if (IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
635        AllocationSiteUsageContext site_context(isolate(), site, false);
636        site_context.EnterNewScope();
637        Node* value = effect =
638            AllocateFastLiteral(effect, control, boilerplate, &site_context);
639        site_context.ExitScope(site, boilerplate);
640        ReplaceWithValue(node, value, effect, control);
641        return Replace(value);
642      }
643    }
644  }
645
646  return NoChange();
647}
648
649Reduction JSCreateLowering::ReduceJSCreateFunctionContext(Node* node) {
650  DCHECK_EQ(IrOpcode::kJSCreateFunctionContext, node->opcode());
651  int slot_count = OpParameter<int>(node->op());
652  Node* const closure = NodeProperties::GetValueInput(node, 0);
653
654  // Use inline allocation for function contexts up to a size limit.
655  if (slot_count < kFunctionContextAllocationLimit) {
656    // JSCreateFunctionContext[slot_count < limit]](fun)
657    Node* effect = NodeProperties::GetEffectInput(node);
658    Node* control = NodeProperties::GetControlInput(node);
659    Node* context = NodeProperties::GetContextInput(node);
660    Node* extension = jsgraph()->TheHoleConstant();
661    Node* native_context = effect = graph()->NewNode(
662        javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
663        context, context, effect);
664    AllocationBuilder a(jsgraph(), effect, control);
665    STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
666    int context_length = slot_count + Context::MIN_CONTEXT_SLOTS;
667    a.AllocateArray(context_length, factory()->function_context_map());
668    a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure);
669    a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
670    a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
671    a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
672            native_context);
673    for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) {
674      a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant());
675    }
676    RelaxControls(node);
677    a.FinishAndChange(node);
678    return Changed(node);
679  }
680
681  return NoChange();
682}
683
684Reduction JSCreateLowering::ReduceJSCreateWithContext(Node* node) {
685  DCHECK_EQ(IrOpcode::kJSCreateWithContext, node->opcode());
686  Node* object = NodeProperties::GetValueInput(node, 0);
687  Node* closure = NodeProperties::GetValueInput(node, 1);
688  Node* effect = NodeProperties::GetEffectInput(node);
689  Node* control = NodeProperties::GetControlInput(node);
690  Node* context = NodeProperties::GetContextInput(node);
691  Node* native_context = effect = graph()->NewNode(
692      javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
693      context, context, effect);
694  AllocationBuilder a(jsgraph(), effect, control);
695  STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
696  a.AllocateArray(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map());
697  a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure);
698  a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
699  a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), object);
700  a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
701          native_context);
702  RelaxControls(node);
703  a.FinishAndChange(node);
704  return Changed(node);
705}
706
707Reduction JSCreateLowering::ReduceJSCreateCatchContext(Node* node) {
708  DCHECK_EQ(IrOpcode::kJSCreateCatchContext, node->opcode());
709  Handle<String> name = OpParameter<Handle<String>>(node);
710  Node* exception = NodeProperties::GetValueInput(node, 0);
711  Node* closure = NodeProperties::GetValueInput(node, 1);
712  Node* effect = NodeProperties::GetEffectInput(node);
713  Node* control = NodeProperties::GetControlInput(node);
714  Node* context = NodeProperties::GetContextInput(node);
715  Node* native_context = effect = graph()->NewNode(
716      javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
717      context, context, effect);
718  AllocationBuilder a(jsgraph(), effect, control);
719  STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
720  a.AllocateArray(Context::MIN_CONTEXT_SLOTS + 1,
721                  factory()->catch_context_map());
722  a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure);
723  a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
724  a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), name);
725  a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
726          native_context);
727  a.Store(AccessBuilder::ForContextSlot(Context::THROWN_OBJECT_INDEX),
728          exception);
729  RelaxControls(node);
730  a.FinishAndChange(node);
731  return Changed(node);
732}
733
734Reduction JSCreateLowering::ReduceJSCreateBlockContext(Node* node) {
735  DCHECK_EQ(IrOpcode::kJSCreateBlockContext, node->opcode());
736  Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
737  int const context_length = scope_info->ContextLength();
738  Node* const closure = NodeProperties::GetValueInput(node, 0);
739
740  // Use inline allocation for block contexts up to a size limit.
741  if (context_length < kBlockContextAllocationLimit) {
742    // JSCreateBlockContext[scope[length < limit]](fun)
743    Node* effect = NodeProperties::GetEffectInput(node);
744    Node* control = NodeProperties::GetControlInput(node);
745    Node* context = NodeProperties::GetContextInput(node);
746    Node* extension = jsgraph()->Constant(scope_info);
747    Node* native_context = effect = graph()->NewNode(
748        javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
749        context, context, effect);
750    AllocationBuilder a(jsgraph(), effect, control);
751    STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
752    a.AllocateArray(context_length, factory()->block_context_map());
753    a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure);
754    a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
755    a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
756    a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
757            native_context);
758    for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) {
759      a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant());
760    }
761    RelaxControls(node);
762    a.FinishAndChange(node);
763    return Changed(node);
764  }
765
766  return NoChange();
767}
768
769// Helper that allocates a FixedArray holding argument values recorded in the
770// given {frame_state}. Serves as backing store for JSCreateArguments nodes.
771Node* JSCreateLowering::AllocateArguments(Node* effect, Node* control,
772                                          Node* frame_state) {
773  FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
774  int argument_count = state_info.parameter_count() - 1;  // Minus receiver.
775  if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant();
776
777  // Prepare an iterator over argument values recorded in the frame state.
778  Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
779  StateValuesAccess parameters_access(parameters);
780  auto parameters_it = ++parameters_access.begin();
781
782  // Actually allocate the backing store.
783  AllocationBuilder a(jsgraph(), effect, control);
784  a.AllocateArray(argument_count, factory()->fixed_array_map());
785  for (int i = 0; i < argument_count; ++i, ++parameters_it) {
786    a.Store(AccessBuilder::ForFixedArraySlot(i), (*parameters_it).node);
787  }
788  return a.Finish();
789}
790
791// Helper that allocates a FixedArray holding argument values recorded in the
792// given {frame_state}. Serves as backing store for JSCreateArguments nodes.
793Node* JSCreateLowering::AllocateRestArguments(Node* effect, Node* control,
794                                              Node* frame_state,
795                                              int start_index) {
796  FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
797  int argument_count = state_info.parameter_count() - 1;  // Minus receiver.
798  int num_elements = std::max(0, argument_count - start_index);
799  if (num_elements == 0) return jsgraph()->EmptyFixedArrayConstant();
800
801  // Prepare an iterator over argument values recorded in the frame state.
802  Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
803  StateValuesAccess parameters_access(parameters);
804  auto parameters_it = ++parameters_access.begin();
805
806  // Skip unused arguments.
807  for (int i = 0; i < start_index; i++) {
808    ++parameters_it;
809  }
810
811  // Actually allocate the backing store.
812  AllocationBuilder a(jsgraph(), effect, control);
813  a.AllocateArray(num_elements, factory()->fixed_array_map());
814  for (int i = 0; i < num_elements; ++i, ++parameters_it) {
815    a.Store(AccessBuilder::ForFixedArraySlot(i), (*parameters_it).node);
816  }
817  return a.Finish();
818}
819
820// Helper that allocates a FixedArray serving as a parameter map for values
821// recorded in the given {frame_state}. Some elements map to slots within the
822// given {context}. Serves as backing store for JSCreateArguments nodes.
823Node* JSCreateLowering::AllocateAliasedArguments(
824    Node* effect, Node* control, Node* frame_state, Node* context,
825    Handle<SharedFunctionInfo> shared, bool* has_aliased_arguments) {
826  FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
827  int argument_count = state_info.parameter_count() - 1;  // Minus receiver.
828  if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant();
829
830  // If there is no aliasing, the arguments object elements are not special in
831  // any way, we can just return an unmapped backing store instead.
832  int parameter_count = shared->internal_formal_parameter_count();
833  if (parameter_count == 0) {
834    return AllocateArguments(effect, control, frame_state);
835  }
836
837  // Calculate number of argument values being aliased/mapped.
838  int mapped_count = Min(argument_count, parameter_count);
839  *has_aliased_arguments = true;
840
841  // Prepare an iterator over argument values recorded in the frame state.
842  Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
843  StateValuesAccess parameters_access(parameters);
844  auto paratemers_it = ++parameters_access.begin();
845
846  // The unmapped argument values recorded in the frame state are stored yet
847  // another indirection away and then linked into the parameter map below,
848  // whereas mapped argument values are replaced with a hole instead.
849  AllocationBuilder aa(jsgraph(), effect, control);
850  aa.AllocateArray(argument_count, factory()->fixed_array_map());
851  for (int i = 0; i < mapped_count; ++i, ++paratemers_it) {
852    aa.Store(AccessBuilder::ForFixedArraySlot(i), jsgraph()->TheHoleConstant());
853  }
854  for (int i = mapped_count; i < argument_count; ++i, ++paratemers_it) {
855    aa.Store(AccessBuilder::ForFixedArraySlot(i), (*paratemers_it).node);
856  }
857  Node* arguments = aa.Finish();
858
859  // Actually allocate the backing store.
860  AllocationBuilder a(jsgraph(), arguments, control);
861  a.AllocateArray(mapped_count + 2, factory()->sloppy_arguments_elements_map());
862  a.Store(AccessBuilder::ForFixedArraySlot(0), context);
863  a.Store(AccessBuilder::ForFixedArraySlot(1), arguments);
864  for (int i = 0; i < mapped_count; ++i) {
865    int idx = Context::MIN_CONTEXT_SLOTS + parameter_count - 1 - i;
866    a.Store(AccessBuilder::ForFixedArraySlot(i + 2), jsgraph()->Constant(idx));
867  }
868  return a.Finish();
869}
870
871Node* JSCreateLowering::AllocateElements(Node* effect, Node* control,
872                                         ElementsKind elements_kind,
873                                         int capacity,
874                                         PretenureFlag pretenure) {
875  DCHECK_LE(1, capacity);
876  DCHECK_LE(capacity, JSArray::kInitialMaxFastElementArray);
877
878  Handle<Map> elements_map = IsFastDoubleElementsKind(elements_kind)
879                                 ? factory()->fixed_double_array_map()
880                                 : factory()->fixed_array_map();
881  ElementAccess access = IsFastDoubleElementsKind(elements_kind)
882                             ? AccessBuilder::ForFixedDoubleArrayElement()
883                             : AccessBuilder::ForFixedArrayElement();
884  Node* value =
885      IsFastDoubleElementsKind(elements_kind)
886          ? jsgraph()->Float64Constant(bit_cast<double>(kHoleNanInt64))
887          : jsgraph()->TheHoleConstant();
888
889  // Actually allocate the backing store.
890  AllocationBuilder a(jsgraph(), effect, control);
891  a.AllocateArray(capacity, elements_map, pretenure);
892  for (int i = 0; i < capacity; ++i) {
893    Node* index = jsgraph()->Constant(i);
894    a.Store(access, index, value);
895  }
896  return a.Finish();
897}
898
899Node* JSCreateLowering::AllocateFastLiteral(
900    Node* effect, Node* control, Handle<JSObject> boilerplate,
901    AllocationSiteUsageContext* site_context) {
902  Handle<AllocationSite> current_site(*site_context->current(), isolate());
903  dependencies()->AssumeTransitionStable(current_site);
904
905  PretenureFlag pretenure = NOT_TENURED;
906  if (FLAG_allocation_site_pretenuring) {
907    Handle<AllocationSite> top_site(*site_context->top(), isolate());
908    pretenure = top_site->GetPretenureMode();
909    if (current_site.is_identical_to(top_site)) {
910      // We install a dependency for pretenuring only on the outermost literal.
911      dependencies()->AssumeTenuringDecision(top_site);
912    }
913  }
914
915  // Setup the properties backing store.
916  Node* properties = jsgraph()->EmptyFixedArrayConstant();
917
918  // Setup the elements backing store.
919  Node* elements = AllocateFastLiteralElements(effect, control, boilerplate,
920                                               pretenure, site_context);
921  if (elements->op()->EffectOutputCount() > 0) effect = elements;
922
923  // Compute the in-object properties to store first (might have effects).
924  Handle<Map> boilerplate_map(boilerplate->map(), isolate());
925  ZoneVector<std::pair<FieldAccess, Node*>> inobject_fields(zone());
926  inobject_fields.reserve(boilerplate_map->GetInObjectProperties());
927  int const boilerplate_nof = boilerplate_map->NumberOfOwnDescriptors();
928  for (int i = 0; i < boilerplate_nof; ++i) {
929    PropertyDetails const property_details =
930        boilerplate_map->instance_descriptors()->GetDetails(i);
931    if (property_details.type() != DATA) continue;
932    Handle<Name> property_name(
933        boilerplate_map->instance_descriptors()->GetKey(i), isolate());
934    FieldIndex index = FieldIndex::ForDescriptor(*boilerplate_map, i);
935    FieldAccess access = {
936        kTaggedBase,    index.offset(),           property_name,
937        Type::Tagged(), MachineType::AnyTagged(), kFullWriteBarrier};
938    Node* value;
939    if (boilerplate->IsUnboxedDoubleField(index)) {
940      access.machine_type = MachineType::Float64();
941      access.type = Type::Number();
942      value = jsgraph()->Constant(boilerplate->RawFastDoublePropertyAt(index));
943    } else {
944      Handle<Object> boilerplate_value(boilerplate->RawFastPropertyAt(index),
945                                       isolate());
946      if (boilerplate_value->IsJSObject()) {
947        Handle<JSObject> boilerplate_object =
948            Handle<JSObject>::cast(boilerplate_value);
949        Handle<AllocationSite> current_site = site_context->EnterNewScope();
950        value = effect = AllocateFastLiteral(effect, control,
951                                             boilerplate_object, site_context);
952        site_context->ExitScope(current_site, boilerplate_object);
953      } else if (property_details.representation().IsDouble()) {
954        // Allocate a mutable HeapNumber box and store the value into it.
955        effect = graph()->NewNode(
956            common()->BeginRegion(RegionObservability::kNotObservable), effect);
957        value = effect = graph()->NewNode(
958            simplified()->Allocate(NOT_TENURED),
959            jsgraph()->Constant(HeapNumber::kSize), effect, control);
960        effect = graph()->NewNode(
961            simplified()->StoreField(AccessBuilder::ForMap()), value,
962            jsgraph()->HeapConstant(factory()->mutable_heap_number_map()),
963            effect, control);
964        effect = graph()->NewNode(
965            simplified()->StoreField(AccessBuilder::ForHeapNumberValue()),
966            value, jsgraph()->Constant(
967                       Handle<HeapNumber>::cast(boilerplate_value)->value()),
968            effect, control);
969        value = effect =
970            graph()->NewNode(common()->FinishRegion(), value, effect);
971      } else if (property_details.representation().IsSmi()) {
972        // Ensure that value is stored as smi.
973        value = boilerplate_value->IsUninitialized(isolate())
974                    ? jsgraph()->ZeroConstant()
975                    : jsgraph()->Constant(boilerplate_value);
976      } else {
977        value = jsgraph()->Constant(boilerplate_value);
978      }
979    }
980    inobject_fields.push_back(std::make_pair(access, value));
981  }
982
983  // Fill slack at the end of the boilerplate object with filler maps.
984  int const boilerplate_length = boilerplate_map->GetInObjectProperties();
985  for (int index = static_cast<int>(inobject_fields.size());
986       index < boilerplate_length; ++index) {
987    FieldAccess access =
988        AccessBuilder::ForJSObjectInObjectProperty(boilerplate_map, index);
989    Node* value = jsgraph()->HeapConstant(factory()->one_pointer_filler_map());
990    inobject_fields.push_back(std::make_pair(access, value));
991  }
992
993  // Actually allocate and initialize the object.
994  AllocationBuilder builder(jsgraph(), effect, control);
995  builder.Allocate(boilerplate_map->instance_size(), pretenure);
996  builder.Store(AccessBuilder::ForMap(), boilerplate_map);
997  builder.Store(AccessBuilder::ForJSObjectProperties(), properties);
998  builder.Store(AccessBuilder::ForJSObjectElements(), elements);
999  if (boilerplate_map->IsJSArrayMap()) {
1000    Handle<JSArray> boilerplate_array = Handle<JSArray>::cast(boilerplate);
1001    builder.Store(
1002        AccessBuilder::ForJSArrayLength(boilerplate_array->GetElementsKind()),
1003        handle(boilerplate_array->length(), isolate()));
1004  }
1005  for (auto const inobject_field : inobject_fields) {
1006    builder.Store(inobject_field.first, inobject_field.second);
1007  }
1008  return builder.Finish();
1009}
1010
1011Node* JSCreateLowering::AllocateFastLiteralElements(
1012    Node* effect, Node* control, Handle<JSObject> boilerplate,
1013    PretenureFlag pretenure, AllocationSiteUsageContext* site_context) {
1014  Handle<FixedArrayBase> boilerplate_elements(boilerplate->elements(),
1015                                              isolate());
1016
1017  // Empty or copy-on-write elements just store a constant.
1018  if (boilerplate_elements->length() == 0 ||
1019      boilerplate_elements->map() == isolate()->heap()->fixed_cow_array_map()) {
1020    if (pretenure == TENURED &&
1021        isolate()->heap()->InNewSpace(*boilerplate_elements)) {
1022      // If we would like to pretenure a fixed cow array, we must ensure that
1023      // the array is already in old space, otherwise we'll create too many
1024      // old-to-new-space pointers (overflowing the store buffer).
1025      boilerplate_elements = Handle<FixedArrayBase>(
1026          isolate()->factory()->CopyAndTenureFixedCOWArray(
1027              Handle<FixedArray>::cast(boilerplate_elements)));
1028      boilerplate->set_elements(*boilerplate_elements);
1029    }
1030    return jsgraph()->HeapConstant(boilerplate_elements);
1031  }
1032
1033  // Compute the elements to store first (might have effects).
1034  int const elements_length = boilerplate_elements->length();
1035  Handle<Map> elements_map(boilerplate_elements->map(), isolate());
1036  ZoneVector<Node*> elements_values(elements_length, zone());
1037  if (elements_map->instance_type() == FIXED_DOUBLE_ARRAY_TYPE) {
1038    Handle<FixedDoubleArray> elements =
1039        Handle<FixedDoubleArray>::cast(boilerplate_elements);
1040    for (int i = 0; i < elements_length; ++i) {
1041      if (elements->is_the_hole(i)) {
1042        // TODO(turbofan): We cannot currently safely pass thru the (signaling)
1043        // hole NaN in C++ code, as the C++ compiler on Intel might use FPU
1044        // instructions/registers for doubles and therefore make the NaN quiet.
1045        // We should consider passing doubles in the compiler as raw int64
1046        // values to prevent this.
1047        elements_values[i] = effect =
1048            graph()->NewNode(simplified()->LoadElement(
1049                                 AccessBuilder::ForFixedDoubleArrayElement()),
1050                             jsgraph()->HeapConstant(elements),
1051                             jsgraph()->Constant(i), effect, control);
1052      } else {
1053        elements_values[i] = jsgraph()->Constant(elements->get_scalar(i));
1054      }
1055    }
1056  } else {
1057    Handle<FixedArray> elements =
1058        Handle<FixedArray>::cast(boilerplate_elements);
1059    for (int i = 0; i < elements_length; ++i) {
1060      if (elements->is_the_hole(i)) {
1061        elements_values[i] = jsgraph()->TheHoleConstant();
1062      } else {
1063        Handle<Object> element_value(elements->get(i), isolate());
1064        if (element_value->IsJSObject()) {
1065          Handle<JSObject> boilerplate_object =
1066              Handle<JSObject>::cast(element_value);
1067          Handle<AllocationSite> current_site = site_context->EnterNewScope();
1068          elements_values[i] = effect = AllocateFastLiteral(
1069              effect, control, boilerplate_object, site_context);
1070          site_context->ExitScope(current_site, boilerplate_object);
1071        } else {
1072          elements_values[i] = jsgraph()->Constant(element_value);
1073        }
1074      }
1075    }
1076  }
1077
1078  // Allocate the backing store array and store the elements.
1079  AllocationBuilder builder(jsgraph(), effect, control);
1080  builder.AllocateArray(elements_length, elements_map, pretenure);
1081  ElementAccess const access =
1082      (elements_map->instance_type() == FIXED_DOUBLE_ARRAY_TYPE)
1083          ? AccessBuilder::ForFixedDoubleArrayElement()
1084          : AccessBuilder::ForFixedArrayElement();
1085  for (int i = 0; i < elements_length; ++i) {
1086    builder.Store(access, jsgraph()->Constant(i), elements_values[i]);
1087  }
1088  return builder.Finish();
1089}
1090
1091MaybeHandle<LiteralsArray> JSCreateLowering::GetSpecializationLiterals(
1092    Node* node) {
1093  Node* const closure = NodeProperties::GetValueInput(node, 0);
1094  switch (closure->opcode()) {
1095    case IrOpcode::kHeapConstant: {
1096      Handle<HeapObject> object = OpParameter<Handle<HeapObject>>(closure);
1097      return handle(Handle<JSFunction>::cast(object)->literals());
1098    }
1099    case IrOpcode::kParameter: {
1100      int const index = ParameterIndexOf(closure->op());
1101      // The closure is always the last parameter to a JavaScript function, and
1102      // {Parameter} indices start at -1, so value outputs of {Start} look like
1103      // this: closure, receiver, param0, ..., paramN, context.
1104      if (index == -1) {
1105        return literals_array_;
1106      }
1107      break;
1108    }
1109    default:
1110      break;
1111  }
1112  return MaybeHandle<LiteralsArray>();
1113}
1114
1115Factory* JSCreateLowering::factory() const { return isolate()->factory(); }
1116
1117Graph* JSCreateLowering::graph() const { return jsgraph()->graph(); }
1118
1119Isolate* JSCreateLowering::isolate() const { return jsgraph()->isolate(); }
1120
1121JSOperatorBuilder* JSCreateLowering::javascript() const {
1122  return jsgraph()->javascript();
1123}
1124
1125CommonOperatorBuilder* JSCreateLowering::common() const {
1126  return jsgraph()->common();
1127}
1128
1129SimplifiedOperatorBuilder* JSCreateLowering::simplified() const {
1130  return jsgraph()->simplified();
1131}
1132
1133MachineOperatorBuilder* JSCreateLowering::machine() const {
1134  return jsgraph()->machine();
1135}
1136
1137}  // namespace compiler
1138}  // namespace internal
1139}  // namespace v8
1140