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