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