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