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