Home | History | Annotate | Download | only in compiler
      1 // Copyright 2014 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/code-factory.h"
      6 #include "src/code-stubs.h"
      7 #include "src/compiler/common-operator.h"
      8 #include "src/compiler/js-generic-lowering.h"
      9 #include "src/compiler/js-graph.h"
     10 #include "src/compiler/machine-operator.h"
     11 #include "src/compiler/node-matchers.h"
     12 #include "src/compiler/node-properties.h"
     13 #include "src/compiler/operator-properties.h"
     14 
     15 namespace v8 {
     16 namespace internal {
     17 namespace compiler {
     18 
     19 static CallDescriptor::Flags AdjustFrameStatesForCall(Node* node) {
     20   int count = OperatorProperties::GetFrameStateInputCount(node->op());
     21   if (count > 1) {
     22     int index = NodeProperties::FirstFrameStateIndex(node) + 1;
     23     do {
     24       node->RemoveInput(index);
     25     } while (--count > 1);
     26   }
     27   return count > 0 ? CallDescriptor::kNeedsFrameState
     28                    : CallDescriptor::kNoFlags;
     29 }
     30 
     31 JSGenericLowering::JSGenericLowering(JSGraph* jsgraph) : jsgraph_(jsgraph) {}
     32 
     33 JSGenericLowering::~JSGenericLowering() {}
     34 
     35 
     36 Reduction JSGenericLowering::Reduce(Node* node) {
     37   switch (node->opcode()) {
     38 #define DECLARE_CASE(x)  \
     39     case IrOpcode::k##x: \
     40       Lower##x(node);    \
     41       break;
     42     JS_OP_LIST(DECLARE_CASE)
     43 #undef DECLARE_CASE
     44     default:
     45       // Nothing to see.
     46       return NoChange();
     47   }
     48   return Changed(node);
     49 }
     50 #define REPLACE_RUNTIME_CALL(op, fun)             \
     51   void JSGenericLowering::Lower##op(Node* node) { \
     52     ReplaceWithRuntimeCall(node, fun);            \
     53   }
     54 REPLACE_RUNTIME_CALL(JSCreateWithContext, Runtime::kPushWithContext)
     55 REPLACE_RUNTIME_CALL(JSCreateModuleContext, Runtime::kPushModuleContext)
     56 REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver)
     57 #undef REPLACE_RUNTIME_CALL
     58 
     59 #define REPLACE_STUB_CALL(Name)                                   \
     60   void JSGenericLowering::LowerJS##Name(Node* node) {             \
     61     CallDescriptor::Flags flags = AdjustFrameStatesForCall(node); \
     62     Callable callable = CodeFactory::Name(isolate());             \
     63     ReplaceWithStubCall(node, callable, flags);                   \
     64   }
     65 REPLACE_STUB_CALL(Add)
     66 REPLACE_STUB_CALL(Subtract)
     67 REPLACE_STUB_CALL(Multiply)
     68 REPLACE_STUB_CALL(Divide)
     69 REPLACE_STUB_CALL(Modulus)
     70 REPLACE_STUB_CALL(BitwiseAnd)
     71 REPLACE_STUB_CALL(BitwiseOr)
     72 REPLACE_STUB_CALL(BitwiseXor)
     73 REPLACE_STUB_CALL(ShiftLeft)
     74 REPLACE_STUB_CALL(ShiftRight)
     75 REPLACE_STUB_CALL(ShiftRightLogical)
     76 REPLACE_STUB_CALL(LessThan)
     77 REPLACE_STUB_CALL(LessThanOrEqual)
     78 REPLACE_STUB_CALL(GreaterThan)
     79 REPLACE_STUB_CALL(GreaterThanOrEqual)
     80 REPLACE_STUB_CALL(HasProperty)
     81 REPLACE_STUB_CALL(Equal)
     82 REPLACE_STUB_CALL(NotEqual)
     83 REPLACE_STUB_CALL(ToInteger)
     84 REPLACE_STUB_CALL(ToLength)
     85 REPLACE_STUB_CALL(ToNumber)
     86 REPLACE_STUB_CALL(ToName)
     87 REPLACE_STUB_CALL(ToObject)
     88 REPLACE_STUB_CALL(ToString)
     89 #undef REPLACE_STUB_CALL
     90 
     91 void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
     92                                             CallDescriptor::Flags flags) {
     93   ReplaceWithStubCall(node, callable, flags, node->op()->properties());
     94 }
     95 
     96 void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
     97                                             CallDescriptor::Flags flags,
     98                                             Operator::Properties properties) {
     99   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    100       isolate(), zone(), callable.descriptor(), 0, flags, properties);
    101   Node* stub_code = jsgraph()->HeapConstant(callable.code());
    102   node->InsertInput(zone(), 0, stub_code);
    103   NodeProperties::ChangeOp(node, common()->Call(desc));
    104 }
    105 
    106 
    107 void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
    108                                                Runtime::FunctionId f,
    109                                                int nargs_override) {
    110   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
    111   Operator::Properties properties = node->op()->properties();
    112   const Runtime::Function* fun = Runtime::FunctionForId(f);
    113   int nargs = (nargs_override < 0) ? fun->nargs : nargs_override;
    114   CallDescriptor* desc =
    115       Linkage::GetRuntimeCallDescriptor(zone(), f, nargs, properties, flags);
    116   Node* ref = jsgraph()->ExternalConstant(ExternalReference(f, isolate()));
    117   Node* arity = jsgraph()->Int32Constant(nargs);
    118   node->InsertInput(zone(), 0, jsgraph()->CEntryStubConstant(fun->result_size));
    119   node->InsertInput(zone(), nargs + 1, ref);
    120   node->InsertInput(zone(), nargs + 2, arity);
    121   NodeProperties::ChangeOp(node, common()->Call(desc));
    122 }
    123 
    124 void JSGenericLowering::LowerJSStrictEqual(Node* node) {
    125   Callable callable = CodeFactory::StrictEqual(isolate());
    126   node->AppendInput(zone(), graph()->start());
    127   ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags,
    128                       Operator::kEliminatable);
    129 }
    130 
    131 void JSGenericLowering::LowerJSStrictNotEqual(Node* node) {
    132   Callable callable = CodeFactory::StrictNotEqual(isolate());
    133   node->AppendInput(zone(), graph()->start());
    134   ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags,
    135                       Operator::kEliminatable);
    136 }
    137 
    138 void JSGenericLowering::LowerJSToBoolean(Node* node) {
    139   Callable callable = CodeFactory::ToBoolean(isolate());
    140   node->AppendInput(zone(), graph()->start());
    141   ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
    142                       Operator::kEliminatable);
    143 }
    144 
    145 void JSGenericLowering::LowerJSTypeOf(Node* node) {
    146   Callable callable = CodeFactory::Typeof(isolate());
    147   node->AppendInput(zone(), graph()->start());
    148   ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
    149                       Operator::kEliminatable);
    150 }
    151 
    152 
    153 void JSGenericLowering::LowerJSLoadProperty(Node* node) {
    154   Node* closure = NodeProperties::GetValueInput(node, 2);
    155   Node* effect = NodeProperties::GetEffectInput(node);
    156   Node* control = NodeProperties::GetControlInput(node);
    157   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
    158   const PropertyAccess& p = PropertyAccessOf(node->op());
    159   Callable callable = CodeFactory::KeyedLoadICInOptimizedCode(isolate());
    160   // Load the type feedback vector from the closure.
    161   Node* literals = effect = graph()->NewNode(
    162       machine()->Load(MachineType::AnyTagged()), closure,
    163       jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
    164       effect, control);
    165   Node* vector = effect = graph()->NewNode(
    166       machine()->Load(MachineType::AnyTagged()), literals,
    167       jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
    168                                 kHeapObjectTag),
    169       effect, control);
    170   node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
    171   node->ReplaceInput(3, vector);
    172   node->ReplaceInput(6, effect);
    173   ReplaceWithStubCall(node, callable, flags);
    174 }
    175 
    176 
    177 void JSGenericLowering::LowerJSLoadNamed(Node* node) {
    178   Node* closure = NodeProperties::GetValueInput(node, 1);
    179   Node* effect = NodeProperties::GetEffectInput(node);
    180   Node* control = NodeProperties::GetControlInput(node);
    181   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
    182   NamedAccess const& p = NamedAccessOf(node->op());
    183   Callable callable = CodeFactory::LoadICInOptimizedCode(isolate());
    184   // Load the type feedback vector from the closure.
    185   Node* literals = effect = graph()->NewNode(
    186       machine()->Load(MachineType::AnyTagged()), closure,
    187       jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
    188       effect, control);
    189   Node* vector = effect = graph()->NewNode(
    190       machine()->Load(MachineType::AnyTagged()), literals,
    191       jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
    192                                 kHeapObjectTag),
    193       effect, control);
    194   node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
    195   node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
    196   node->ReplaceInput(3, vector);
    197   node->ReplaceInput(6, effect);
    198   ReplaceWithStubCall(node, callable, flags);
    199 }
    200 
    201 
    202 void JSGenericLowering::LowerJSLoadGlobal(Node* node) {
    203   Node* closure = NodeProperties::GetValueInput(node, 0);
    204   Node* effect = NodeProperties::GetEffectInput(node);
    205   Node* control = NodeProperties::GetControlInput(node);
    206   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
    207   const LoadGlobalParameters& p = LoadGlobalParametersOf(node->op());
    208   Callable callable =
    209       CodeFactory::LoadGlobalICInOptimizedCode(isolate(), p.typeof_mode());
    210   // Load the type feedback vector from the closure.
    211   Node* literals = effect = graph()->NewNode(
    212       machine()->Load(MachineType::AnyTagged()), closure,
    213       jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
    214       effect, control);
    215   Node* vector = effect = graph()->NewNode(
    216       machine()->Load(MachineType::AnyTagged()), literals,
    217       jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
    218                                 kHeapObjectTag),
    219       effect, control);
    220   node->InsertInput(zone(), 0, jsgraph()->SmiConstant(p.feedback().index()));
    221   node->ReplaceInput(1, vector);
    222   node->ReplaceInput(4, effect);
    223   ReplaceWithStubCall(node, callable, flags);
    224 }
    225 
    226 
    227 void JSGenericLowering::LowerJSStoreProperty(Node* node) {
    228   Node* closure = NodeProperties::GetValueInput(node, 3);
    229   Node* effect = NodeProperties::GetEffectInput(node);
    230   Node* control = NodeProperties::GetControlInput(node);
    231   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
    232   PropertyAccess const& p = PropertyAccessOf(node->op());
    233   LanguageMode language_mode = p.language_mode();
    234   Callable callable =
    235       CodeFactory::KeyedStoreICInOptimizedCode(isolate(), language_mode);
    236   // Load the type feedback vector from the closure.
    237   Node* literals = effect = graph()->NewNode(
    238       machine()->Load(MachineType::AnyTagged()), closure,
    239       jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
    240       effect, control);
    241   Node* vector = effect = graph()->NewNode(
    242       machine()->Load(MachineType::AnyTagged()), literals,
    243       jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
    244                                 kHeapObjectTag),
    245       effect, control);
    246   node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
    247   node->ReplaceInput(4, vector);
    248   node->ReplaceInput(7, effect);
    249   ReplaceWithStubCall(node, callable, flags);
    250 }
    251 
    252 
    253 void JSGenericLowering::LowerJSStoreNamed(Node* node) {
    254   Node* closure = NodeProperties::GetValueInput(node, 2);
    255   Node* effect = NodeProperties::GetEffectInput(node);
    256   Node* control = NodeProperties::GetControlInput(node);
    257   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
    258   NamedAccess const& p = NamedAccessOf(node->op());
    259   Callable callable =
    260       CodeFactory::StoreICInOptimizedCode(isolate(), p.language_mode());
    261   // Load the type feedback vector from the closure.
    262   Node* literals = effect = graph()->NewNode(
    263       machine()->Load(MachineType::AnyTagged()), closure,
    264       jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
    265       effect, control);
    266   Node* vector = effect = graph()->NewNode(
    267       machine()->Load(MachineType::AnyTagged()), literals,
    268       jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
    269                                 kHeapObjectTag),
    270       effect, control);
    271   node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
    272   node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
    273   node->ReplaceInput(4, vector);
    274   node->ReplaceInput(7, effect);
    275   ReplaceWithStubCall(node, callable, flags);
    276 }
    277 
    278 
    279 void JSGenericLowering::LowerJSStoreGlobal(Node* node) {
    280   Node* closure = NodeProperties::GetValueInput(node, 1);
    281   Node* context = NodeProperties::GetContextInput(node);
    282   Node* effect = NodeProperties::GetEffectInput(node);
    283   Node* control = NodeProperties::GetControlInput(node);
    284   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
    285   const StoreGlobalParameters& p = StoreGlobalParametersOf(node->op());
    286   Callable callable =
    287       CodeFactory::StoreICInOptimizedCode(isolate(), p.language_mode());
    288   // Load the type feedback vector from the closure.
    289   Node* literals = effect = graph()->NewNode(
    290       machine()->Load(MachineType::AnyTagged()), closure,
    291       jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
    292       effect, control);
    293   Node* vector = effect = graph()->NewNode(
    294       machine()->Load(MachineType::AnyTagged()), literals,
    295       jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
    296                                 kHeapObjectTag),
    297       effect, control);
    298   // Load global object from the context.
    299   Node* native_context = effect =
    300       graph()->NewNode(machine()->Load(MachineType::AnyTagged()), context,
    301                        jsgraph()->IntPtrConstant(
    302                            Context::SlotOffset(Context::NATIVE_CONTEXT_INDEX)),
    303                        effect, control);
    304   Node* global = effect = graph()->NewNode(
    305       machine()->Load(MachineType::AnyTagged()), native_context,
    306       jsgraph()->IntPtrConstant(Context::SlotOffset(Context::EXTENSION_INDEX)),
    307       effect, control);
    308   node->InsertInput(zone(), 0, global);
    309   node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
    310   node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
    311   node->ReplaceInput(4, vector);
    312   node->ReplaceInput(7, effect);
    313   ReplaceWithStubCall(node, callable, flags);
    314 }
    315 
    316 
    317 void JSGenericLowering::LowerJSDeleteProperty(Node* node) {
    318   LanguageMode language_mode = OpParameter<LanguageMode>(node);
    319   ReplaceWithRuntimeCall(node, is_strict(language_mode)
    320                                    ? Runtime::kDeleteProperty_Strict
    321                                    : Runtime::kDeleteProperty_Sloppy);
    322 }
    323 
    324 
    325 void JSGenericLowering::LowerJSInstanceOf(Node* node) {
    326   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
    327   Callable callable = CodeFactory::InstanceOf(isolate());
    328   ReplaceWithStubCall(node, callable, flags);
    329 }
    330 
    331 
    332 void JSGenericLowering::LowerJSLoadContext(Node* node) {
    333   const ContextAccess& access = ContextAccessOf(node->op());
    334   for (size_t i = 0; i < access.depth(); ++i) {
    335     node->ReplaceInput(
    336         0, graph()->NewNode(machine()->Load(MachineType::AnyTagged()),
    337                             NodeProperties::GetValueInput(node, 0),
    338                             jsgraph()->Int32Constant(
    339                                 Context::SlotOffset(Context::PREVIOUS_INDEX)),
    340                             NodeProperties::GetEffectInput(node),
    341                             graph()->start()));
    342   }
    343   node->ReplaceInput(1, jsgraph()->Int32Constant(Context::SlotOffset(
    344                             static_cast<int>(access.index()))));
    345   node->AppendInput(zone(), graph()->start());
    346   NodeProperties::ChangeOp(node, machine()->Load(MachineType::AnyTagged()));
    347 }
    348 
    349 
    350 void JSGenericLowering::LowerJSStoreContext(Node* node) {
    351   const ContextAccess& access = ContextAccessOf(node->op());
    352   for (size_t i = 0; i < access.depth(); ++i) {
    353     node->ReplaceInput(
    354         0, graph()->NewNode(machine()->Load(MachineType::AnyTagged()),
    355                             NodeProperties::GetValueInput(node, 0),
    356                             jsgraph()->Int32Constant(
    357                                 Context::SlotOffset(Context::PREVIOUS_INDEX)),
    358                             NodeProperties::GetEffectInput(node),
    359                             graph()->start()));
    360   }
    361   node->ReplaceInput(2, NodeProperties::GetValueInput(node, 1));
    362   node->ReplaceInput(1, jsgraph()->Int32Constant(Context::SlotOffset(
    363                             static_cast<int>(access.index()))));
    364   NodeProperties::ChangeOp(
    365       node, machine()->Store(StoreRepresentation(MachineRepresentation::kTagged,
    366                                                  kFullWriteBarrier)));
    367 }
    368 
    369 
    370 void JSGenericLowering::LowerJSCreate(Node* node) {
    371   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
    372   Callable callable = CodeFactory::FastNewObject(isolate());
    373   ReplaceWithStubCall(node, callable, flags);
    374 }
    375 
    376 
    377 void JSGenericLowering::LowerJSCreateArguments(Node* node) {
    378   CreateArgumentsType const type = CreateArgumentsTypeOf(node->op());
    379   switch (type) {
    380     case CreateArgumentsType::kMappedArguments:
    381       ReplaceWithRuntimeCall(node, Runtime::kNewSloppyArguments_Generic);
    382       break;
    383     case CreateArgumentsType::kUnmappedArguments:
    384       ReplaceWithRuntimeCall(node, Runtime::kNewStrictArguments);
    385       break;
    386     case CreateArgumentsType::kRestParameter:
    387       ReplaceWithRuntimeCall(node, Runtime::kNewRestParameter);
    388       break;
    389   }
    390 }
    391 
    392 
    393 void JSGenericLowering::LowerJSCreateArray(Node* node) {
    394   CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
    395   int const arity = static_cast<int>(p.arity());
    396   Handle<AllocationSite> const site = p.site();
    397 
    398   // TODO(turbofan): We embed the AllocationSite from the Operator at this
    399   // point, which we should not do once we want to both consume the feedback
    400   // but at the same time shared the optimized code across native contexts,
    401   // as the AllocationSite is associated with a single native context (it's
    402   // stored in the type feedback vector after all). Once we go for cross
    403   // context code generation, we should somehow find a way to get to the
    404   // allocation site for the actual native context at runtime.
    405   if (!site.is_null()) {
    406     // Reduce {node} to the appropriate ArrayConstructorStub backend.
    407     // Note that these stubs "behave" like JSFunctions, which means they
    408     // expect a receiver on the stack, which they remove. We just push
    409     // undefined for the receiver.
    410     ElementsKind elements_kind = site->GetElementsKind();
    411     AllocationSiteOverrideMode override_mode =
    412         (AllocationSite::GetMode(elements_kind) == TRACK_ALLOCATION_SITE)
    413             ? DISABLE_ALLOCATION_SITES
    414             : DONT_OVERRIDE;
    415     if (arity == 0) {
    416       ArrayNoArgumentConstructorStub stub(isolate(), elements_kind,
    417                                           override_mode);
    418       CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    419           isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 1,
    420           CallDescriptor::kNeedsFrameState);
    421       node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
    422       node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site));
    423       node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(0));
    424       node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
    425       NodeProperties::ChangeOp(node, common()->Call(desc));
    426     } else if (arity == 1) {
    427       // TODO(bmeurer): Optimize for the 0 length non-holey case?
    428       ArraySingleArgumentConstructorStub stub(
    429           isolate(), GetHoleyElementsKind(elements_kind), override_mode);
    430       CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    431           isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 2,
    432           CallDescriptor::kNeedsFrameState);
    433       node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
    434       node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site));
    435       node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(1));
    436       node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
    437       NodeProperties::ChangeOp(node, common()->Call(desc));
    438     } else {
    439       ArrayNArgumentsConstructorStub stub(isolate());
    440       CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    441           isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(),
    442           arity + 1, CallDescriptor::kNeedsFrameState);
    443       node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
    444       node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site));
    445       node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(arity));
    446       node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
    447       NodeProperties::ChangeOp(node, common()->Call(desc));
    448     }
    449   } else {
    450     Node* new_target = node->InputAt(1);
    451     Node* type_info = site.is_null() ? jsgraph()->UndefinedConstant()
    452                                      : jsgraph()->HeapConstant(site);
    453     node->RemoveInput(1);
    454     node->InsertInput(zone(), 1 + arity, new_target);
    455     node->InsertInput(zone(), 2 + arity, type_info);
    456     ReplaceWithRuntimeCall(node, Runtime::kNewArray, arity + 3);
    457   }
    458 }
    459 
    460 
    461 void JSGenericLowering::LowerJSCreateClosure(Node* node) {
    462   CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
    463   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
    464   Handle<SharedFunctionInfo> const shared_info = p.shared_info();
    465   node->InsertInput(zone(), 0, jsgraph()->HeapConstant(shared_info));
    466 
    467   // Use the FastNewClosureStub only for functions allocated in new space.
    468   if (p.pretenure() == NOT_TENURED) {
    469     Callable callable = CodeFactory::FastNewClosure(
    470         isolate(), shared_info->language_mode(), shared_info->kind());
    471     ReplaceWithStubCall(node, callable, flags);
    472   } else {
    473     ReplaceWithRuntimeCall(node, (p.pretenure() == TENURED)
    474                                      ? Runtime::kNewClosure_Tenured
    475                                      : Runtime::kNewClosure);
    476   }
    477 }
    478 
    479 
    480 void JSGenericLowering::LowerJSCreateFunctionContext(Node* node) {
    481   int const slot_count = OpParameter<int>(node->op());
    482   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
    483 
    484   // Use the FastNewContextStub only for function contexts up maximum size.
    485   if (slot_count <= FastNewContextStub::kMaximumSlots) {
    486     Callable callable = CodeFactory::FastNewContext(isolate(), slot_count);
    487     ReplaceWithStubCall(node, callable, flags);
    488   } else {
    489     ReplaceWithRuntimeCall(node, Runtime::kNewFunctionContext);
    490   }
    491 }
    492 
    493 
    494 void JSGenericLowering::LowerJSCreateIterResultObject(Node* node) {
    495   ReplaceWithRuntimeCall(node, Runtime::kCreateIterResultObject);
    496 }
    497 
    498 
    499 void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
    500   CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
    501   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
    502   node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
    503   node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
    504 
    505   // Use the FastCloneShallowArrayStub only for shallow boilerplates up to the
    506   // initial length limit for arrays with "fast" elements kind.
    507   if ((p.flags() & ArrayLiteral::kShallowElements) != 0 &&
    508       p.length() < JSArray::kInitialMaxFastElementArray) {
    509     Callable callable = CodeFactory::FastCloneShallowArray(isolate());
    510     ReplaceWithStubCall(node, callable, flags);
    511   } else {
    512     node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
    513     ReplaceWithRuntimeCall(node, Runtime::kCreateArrayLiteral);
    514   }
    515 }
    516 
    517 
    518 void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
    519   CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
    520   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
    521   node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
    522   node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
    523   node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
    524 
    525   // Use the FastCloneShallowObjectStub only for shallow boilerplates without
    526   // elements up to the number of properties that the stubs can handle.
    527   if ((p.flags() & ObjectLiteral::kShallowProperties) != 0 &&
    528       p.length() <= FastCloneShallowObjectStub::kMaximumClonedProperties) {
    529     Callable callable =
    530         CodeFactory::FastCloneShallowObject(isolate(), p.length());
    531     ReplaceWithStubCall(node, callable, flags);
    532   } else {
    533     ReplaceWithRuntimeCall(node, Runtime::kCreateObjectLiteral);
    534   }
    535 }
    536 
    537 
    538 void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
    539   CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
    540   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
    541   Callable callable = CodeFactory::FastCloneRegExp(isolate());
    542   Node* literal_index = jsgraph()->SmiConstant(p.index());
    543   Node* literal_flags = jsgraph()->SmiConstant(p.flags());
    544   Node* pattern = jsgraph()->HeapConstant(p.constant());
    545   node->InsertInput(graph()->zone(), 1, literal_index);
    546   node->InsertInput(graph()->zone(), 2, pattern);
    547   node->InsertInput(graph()->zone(), 3, literal_flags);
    548   ReplaceWithStubCall(node, callable, flags);
    549 }
    550 
    551 
    552 void JSGenericLowering::LowerJSCreateCatchContext(Node* node) {
    553   Handle<String> name = OpParameter<Handle<String>>(node);
    554   node->InsertInput(zone(), 0, jsgraph()->HeapConstant(name));
    555   ReplaceWithRuntimeCall(node, Runtime::kPushCatchContext);
    556 }
    557 
    558 
    559 void JSGenericLowering::LowerJSCreateBlockContext(Node* node) {
    560   Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
    561   node->InsertInput(zone(), 0, jsgraph()->HeapConstant(scope_info));
    562   ReplaceWithRuntimeCall(node, Runtime::kPushBlockContext);
    563 }
    564 
    565 
    566 void JSGenericLowering::LowerJSCreateScriptContext(Node* node) {
    567   Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
    568   node->InsertInput(zone(), 1, jsgraph()->HeapConstant(scope_info));
    569   ReplaceWithRuntimeCall(node, Runtime::kNewScriptContext);
    570 }
    571 
    572 
    573 void JSGenericLowering::LowerJSCallConstruct(Node* node) {
    574   CallConstructParameters const& p = CallConstructParametersOf(node->op());
    575   int const arg_count = static_cast<int>(p.arity() - 2);
    576   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
    577   Callable callable = CodeFactory::Construct(isolate());
    578   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    579       isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
    580   Node* stub_code = jsgraph()->HeapConstant(callable.code());
    581   Node* stub_arity = jsgraph()->Int32Constant(arg_count);
    582   Node* new_target = node->InputAt(arg_count + 1);
    583   Node* receiver = jsgraph()->UndefinedConstant();
    584   node->RemoveInput(arg_count + 1);  // Drop new target.
    585   node->InsertInput(zone(), 0, stub_code);
    586   node->InsertInput(zone(), 2, new_target);
    587   node->InsertInput(zone(), 3, stub_arity);
    588   node->InsertInput(zone(), 4, receiver);
    589   NodeProperties::ChangeOp(node, common()->Call(desc));
    590 }
    591 
    592 
    593 void JSGenericLowering::LowerJSCallFunction(Node* node) {
    594   CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
    595   int const arg_count = static_cast<int>(p.arity() - 2);
    596   ConvertReceiverMode const mode = p.convert_mode();
    597   Callable callable = CodeFactory::Call(isolate(), mode);
    598   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
    599   if (p.tail_call_mode() == TailCallMode::kAllow) {
    600     flags |= CallDescriptor::kSupportsTailCalls;
    601   }
    602   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    603       isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
    604   Node* stub_code = jsgraph()->HeapConstant(callable.code());
    605   Node* stub_arity = jsgraph()->Int32Constant(arg_count);
    606   node->InsertInput(zone(), 0, stub_code);
    607   node->InsertInput(zone(), 2, stub_arity);
    608   NodeProperties::ChangeOp(node, common()->Call(desc));
    609 }
    610 
    611 
    612 void JSGenericLowering::LowerJSCallRuntime(Node* node) {
    613   const CallRuntimeParameters& p = CallRuntimeParametersOf(node->op());
    614   AdjustFrameStatesForCall(node);
    615   ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity()));
    616 }
    617 
    618 
    619 void JSGenericLowering::LowerJSForInDone(Node* node) {
    620   ReplaceWithRuntimeCall(node, Runtime::kForInDone);
    621 }
    622 
    623 
    624 void JSGenericLowering::LowerJSForInNext(Node* node) {
    625   ReplaceWithRuntimeCall(node, Runtime::kForInNext);
    626 }
    627 
    628 
    629 void JSGenericLowering::LowerJSForInPrepare(Node* node) {
    630   ReplaceWithRuntimeCall(node, Runtime::kForInPrepare);
    631 }
    632 
    633 
    634 void JSGenericLowering::LowerJSForInStep(Node* node) {
    635   ReplaceWithRuntimeCall(node, Runtime::kForInStep);
    636 }
    637 
    638 
    639 void JSGenericLowering::LowerJSLoadMessage(Node* node) {
    640   ExternalReference message_address =
    641       ExternalReference::address_of_pending_message_obj(isolate());
    642   node->RemoveInput(NodeProperties::FirstContextIndex(node));
    643   node->InsertInput(zone(), 0, jsgraph()->ExternalConstant(message_address));
    644   node->InsertInput(zone(), 1, jsgraph()->IntPtrConstant(0));
    645   NodeProperties::ChangeOp(node, machine()->Load(MachineType::AnyTagged()));
    646 }
    647 
    648 
    649 void JSGenericLowering::LowerJSStoreMessage(Node* node) {
    650   ExternalReference message_address =
    651       ExternalReference::address_of_pending_message_obj(isolate());
    652   node->RemoveInput(NodeProperties::FirstContextIndex(node));
    653   node->InsertInput(zone(), 0, jsgraph()->ExternalConstant(message_address));
    654   node->InsertInput(zone(), 1, jsgraph()->IntPtrConstant(0));
    655   StoreRepresentation representation(MachineRepresentation::kTagged,
    656                                      kNoWriteBarrier);
    657   NodeProperties::ChangeOp(node, machine()->Store(representation));
    658 }
    659 
    660 void JSGenericLowering::LowerJSGeneratorStore(Node* node) {
    661   UNREACHABLE();  // Eliminated in typed lowering.
    662 }
    663 
    664 void JSGenericLowering::LowerJSGeneratorRestoreContinuation(Node* node) {
    665   UNREACHABLE();  // Eliminated in typed lowering.
    666 }
    667 
    668 void JSGenericLowering::LowerJSGeneratorRestoreRegister(Node* node) {
    669   UNREACHABLE();  // Eliminated in typed lowering.
    670 }
    671 
    672 void JSGenericLowering::LowerJSStackCheck(Node* node) {
    673   Node* effect = NodeProperties::GetEffectInput(node);
    674   Node* control = NodeProperties::GetControlInput(node);
    675 
    676   Node* limit = graph()->NewNode(
    677       machine()->Load(MachineType::Pointer()),
    678       jsgraph()->ExternalConstant(
    679           ExternalReference::address_of_stack_limit(isolate())),
    680       jsgraph()->IntPtrConstant(0), effect, control);
    681   Node* pointer = graph()->NewNode(machine()->LoadStackPointer());
    682 
    683   Node* check = graph()->NewNode(machine()->UintLessThan(), limit, pointer);
    684   Node* branch =
    685       graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
    686 
    687   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    688   Node* etrue = effect;
    689 
    690   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    691   NodeProperties::ReplaceControlInput(node, if_false);
    692   Node* efalse = node;
    693 
    694   Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
    695   Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
    696 
    697   // Wire the new diamond into the graph, {node} can still throw.
    698   NodeProperties::ReplaceUses(node, node, ephi, node, node);
    699   NodeProperties::ReplaceEffectInput(ephi, efalse, 1);
    700 
    701   // TODO(mstarzinger): This iteration cuts out the IfSuccess projection from
    702   // the node and places it inside the diamond. Come up with a helper method!
    703   for (Node* use : node->uses()) {
    704     if (use->opcode() == IrOpcode::kIfSuccess) {
    705       use->ReplaceUses(merge);
    706       merge->ReplaceInput(1, use);
    707     }
    708   }
    709 
    710   // Turn the stack check into a runtime call.
    711   ReplaceWithRuntimeCall(node, Runtime::kStackGuard);
    712 }
    713 
    714 
    715 Zone* JSGenericLowering::zone() const { return graph()->zone(); }
    716 
    717 
    718 Isolate* JSGenericLowering::isolate() const { return jsgraph()->isolate(); }
    719 
    720 
    721 Graph* JSGenericLowering::graph() const { return jsgraph()->graph(); }
    722 
    723 
    724 CommonOperatorBuilder* JSGenericLowering::common() const {
    725   return jsgraph()->common();
    726 }
    727 
    728 
    729 MachineOperatorBuilder* JSGenericLowering::machine() const {
    730   return jsgraph()->machine();
    731 }
    732 
    733 }  // namespace compiler
    734 }  // namespace internal
    735 }  // namespace v8
    736