LCOV - code coverage report
Current view: top level - src/compiler - js-create-lowering.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 601 638 94.2 %
Date: 2017-04-26 Functions: 32 39 82.1 %

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

Generated by: LCOV version 1.10