Home | History | Annotate | Download | only in interpreter
      1 // Copyright 2017 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/interpreter/interpreter-intrinsics-generator.h"
      6 
      7 #include "src/allocation.h"
      8 #include "src/builtins/builtins.h"
      9 #include "src/code-factory.h"
     10 #include "src/frames.h"
     11 #include "src/heap/factory-inl.h"
     12 #include "src/interpreter/bytecodes.h"
     13 #include "src/interpreter/interpreter-assembler.h"
     14 #include "src/interpreter/interpreter-intrinsics.h"
     15 #include "src/objects-inl.h"
     16 #include "src/objects/js-generator.h"
     17 #include "src/objects/module.h"
     18 
     19 namespace v8 {
     20 namespace internal {
     21 namespace interpreter {
     22 
     23 using compiler::Node;
     24 template <typename T>
     25 using TNode = compiler::TNode<T>;
     26 
     27 class IntrinsicsGenerator {
     28  public:
     29   explicit IntrinsicsGenerator(InterpreterAssembler* assembler)
     30       : isolate_(assembler->isolate()),
     31         zone_(assembler->zone()),
     32         assembler_(assembler) {}
     33 
     34   Node* InvokeIntrinsic(Node* function_id, Node* context,
     35                         const InterpreterAssembler::RegListNodePair& args);
     36 
     37  private:
     38   enum InstanceTypeCompareMode {
     39     kInstanceTypeEqual,
     40     kInstanceTypeGreaterThanOrEqual
     41   };
     42 
     43   Node* IsInstanceType(Node* input, int type);
     44   Node* CompareInstanceType(Node* map, int type, InstanceTypeCompareMode mode);
     45   Node* IntrinsicAsStubCall(const InterpreterAssembler::RegListNodePair& args,
     46                             Node* context, Callable const& callable);
     47   Node* IntrinsicAsBuiltinCall(
     48       const InterpreterAssembler::RegListNodePair& args, Node* context,
     49       Builtins::Name name);
     50   void AbortIfArgCountMismatch(int expected, compiler::Node* actual);
     51 
     52 #define DECLARE_INTRINSIC_HELPER(name, lower_case, count) \
     53   Node* name(const InterpreterAssembler::RegListNodePair& args, Node* context);
     54   INTRINSICS_LIST(DECLARE_INTRINSIC_HELPER)
     55 #undef DECLARE_INTRINSIC_HELPER
     56 
     57   Isolate* isolate() { return isolate_; }
     58   Zone* zone() { return zone_; }
     59   Factory* factory() { return isolate()->factory(); }
     60 
     61   Isolate* isolate_;
     62   Zone* zone_;
     63   InterpreterAssembler* assembler_;
     64 
     65   DISALLOW_COPY_AND_ASSIGN(IntrinsicsGenerator);
     66 };
     67 
     68 Node* GenerateInvokeIntrinsic(
     69     InterpreterAssembler* assembler, Node* function_id, Node* context,
     70     const InterpreterAssembler::RegListNodePair& args) {
     71   IntrinsicsGenerator generator(assembler);
     72   return generator.InvokeIntrinsic(function_id, context, args);
     73 }
     74 
     75 #define __ assembler_->
     76 
     77 Node* IntrinsicsGenerator::InvokeIntrinsic(
     78     Node* function_id, Node* context,
     79     const InterpreterAssembler::RegListNodePair& args) {
     80   InterpreterAssembler::Label abort(assembler_), end(assembler_);
     81   InterpreterAssembler::Variable result(assembler_,
     82                                         MachineRepresentation::kTagged);
     83 
     84 #define MAKE_LABEL(name, lower_case, count) \
     85   InterpreterAssembler::Label lower_case(assembler_);
     86   INTRINSICS_LIST(MAKE_LABEL)
     87 #undef MAKE_LABEL
     88 
     89 #define LABEL_POINTER(name, lower_case, count) &lower_case,
     90   InterpreterAssembler::Label* labels[] = {INTRINSICS_LIST(LABEL_POINTER)};
     91 #undef LABEL_POINTER
     92 
     93 #define CASE(name, lower_case, count) \
     94   static_cast<int32_t>(IntrinsicsHelper::IntrinsicId::k##name),
     95   int32_t cases[] = {INTRINSICS_LIST(CASE)};
     96 #undef CASE
     97 
     98   __ Switch(function_id, &abort, cases, labels, arraysize(cases));
     99 #define HANDLE_CASE(name, lower_case, expected_arg_count)            \
    100   __ BIND(&lower_case);                                              \
    101   {                                                                  \
    102     if (FLAG_debug_code && expected_arg_count >= 0) {                \
    103       AbortIfArgCountMismatch(expected_arg_count, args.reg_count()); \
    104     }                                                                \
    105     Node* value = name(args, context);                               \
    106     if (value) {                                                     \
    107       result.Bind(value);                                            \
    108       __ Goto(&end);                                                 \
    109     }                                                                \
    110   }
    111   INTRINSICS_LIST(HANDLE_CASE)
    112 #undef HANDLE_CASE
    113 
    114   __ BIND(&abort);
    115   {
    116     __ Abort(AbortReason::kUnexpectedFunctionIDForInvokeIntrinsic);
    117     result.Bind(__ UndefinedConstant());
    118     __ Goto(&end);
    119   }
    120 
    121   __ BIND(&end);
    122   return result.value();
    123 }
    124 
    125 Node* IntrinsicsGenerator::CompareInstanceType(Node* object, int type,
    126                                                InstanceTypeCompareMode mode) {
    127   Node* instance_type = __ LoadInstanceType(object);
    128 
    129   if (mode == kInstanceTypeEqual) {
    130     return __ Word32Equal(instance_type, __ Int32Constant(type));
    131   } else {
    132     DCHECK_EQ(mode, kInstanceTypeGreaterThanOrEqual);
    133     return __ Int32GreaterThanOrEqual(instance_type, __ Int32Constant(type));
    134   }
    135 }
    136 
    137 Node* IntrinsicsGenerator::IsInstanceType(Node* input, int type) {
    138   TNode<Oddball> result = __ Select<Oddball>(
    139       __ TaggedIsSmi(input), [=] { return __ FalseConstant(); },
    140       [=] {
    141         return __ SelectBooleanConstant(
    142             CompareInstanceType(input, type, kInstanceTypeEqual));
    143       });
    144   return result;
    145 }
    146 
    147 Node* IntrinsicsGenerator::IsJSReceiver(
    148     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    149   Node* input = __ LoadRegisterFromRegisterList(args, 0);
    150   TNode<Oddball> result = __ Select<Oddball>(
    151       __ TaggedIsSmi(input), [=] { return __ FalseConstant(); },
    152       [=] { return __ SelectBooleanConstant(__ IsJSReceiver(input)); });
    153   return result;
    154 }
    155 
    156 Node* IntrinsicsGenerator::IsArray(
    157     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    158   Node* input = __ LoadRegisterFromRegisterList(args, 0);
    159   return IsInstanceType(input, JS_ARRAY_TYPE);
    160 }
    161 
    162 Node* IntrinsicsGenerator::IsJSProxy(
    163     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    164   Node* input = __ LoadRegisterFromRegisterList(args, 0);
    165   return IsInstanceType(input, JS_PROXY_TYPE);
    166 }
    167 
    168 Node* IntrinsicsGenerator::IsTypedArray(
    169     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    170   Node* input = __ LoadRegisterFromRegisterList(args, 0);
    171   return IsInstanceType(input, JS_TYPED_ARRAY_TYPE);
    172 }
    173 
    174 Node* IntrinsicsGenerator::IsSmi(
    175     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    176   Node* input = __ LoadRegisterFromRegisterList(args, 0);
    177   return __ SelectBooleanConstant(__ TaggedIsSmi(input));
    178 }
    179 
    180 Node* IntrinsicsGenerator::IntrinsicAsStubCall(
    181     const InterpreterAssembler::RegListNodePair& args, Node* context,
    182     Callable const& callable) {
    183   int param_count = callable.descriptor().GetParameterCount();
    184   int input_count = param_count + 2;  // +2 for target and context
    185   Node** stub_args = zone()->NewArray<Node*>(input_count);
    186   int index = 0;
    187   stub_args[index++] = __ HeapConstant(callable.code());
    188   for (int i = 0; i < param_count; i++) {
    189     stub_args[index++] = __ LoadRegisterFromRegisterList(args, i);
    190   }
    191   stub_args[index++] = context;
    192   return __ CallStubN(callable.descriptor(), 1, input_count, stub_args);
    193 }
    194 
    195 Node* IntrinsicsGenerator::IntrinsicAsBuiltinCall(
    196     const InterpreterAssembler::RegListNodePair& args, Node* context,
    197     Builtins::Name name) {
    198   Callable callable = Builtins::CallableFor(isolate_, name);
    199   return IntrinsicAsStubCall(args, context, callable);
    200 }
    201 
    202 Node* IntrinsicsGenerator::CreateIterResultObject(
    203     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    204   return IntrinsicAsStubCall(
    205       args, context,
    206       Builtins::CallableFor(isolate(), Builtins::kCreateIterResultObject));
    207 }
    208 
    209 Node* IntrinsicsGenerator::HasProperty(
    210     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    211   return IntrinsicAsStubCall(
    212       args, context, Builtins::CallableFor(isolate(), Builtins::kHasProperty));
    213 }
    214 
    215 Node* IntrinsicsGenerator::GetProperty(
    216     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    217   return IntrinsicAsStubCall(
    218       args, context, Builtins::CallableFor(isolate(), Builtins::kGetProperty));
    219 }
    220 
    221 Node* IntrinsicsGenerator::RejectPromise(
    222     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    223   return IntrinsicAsStubCall(
    224       args, context,
    225       Builtins::CallableFor(isolate(), Builtins::kRejectPromise));
    226 }
    227 
    228 Node* IntrinsicsGenerator::ResolvePromise(
    229     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    230   return IntrinsicAsStubCall(
    231       args, context,
    232       Builtins::CallableFor(isolate(), Builtins::kResolvePromise));
    233 }
    234 
    235 Node* IntrinsicsGenerator::ToString(
    236     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    237   return IntrinsicAsStubCall(
    238       args, context, Builtins::CallableFor(isolate(), Builtins::kToString));
    239 }
    240 
    241 Node* IntrinsicsGenerator::ToLength(
    242     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    243   return IntrinsicAsStubCall(
    244       args, context, Builtins::CallableFor(isolate(), Builtins::kToLength));
    245 }
    246 
    247 Node* IntrinsicsGenerator::ToInteger(
    248     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    249   return IntrinsicAsStubCall(
    250       args, context, Builtins::CallableFor(isolate(), Builtins::kToInteger));
    251 }
    252 
    253 Node* IntrinsicsGenerator::ToNumber(
    254     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    255   return IntrinsicAsStubCall(
    256       args, context, Builtins::CallableFor(isolate(), Builtins::kToNumber));
    257 }
    258 
    259 Node* IntrinsicsGenerator::ToObject(
    260     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    261   return IntrinsicAsStubCall(
    262       args, context, Builtins::CallableFor(isolate(), Builtins::kToObject));
    263 }
    264 
    265 Node* IntrinsicsGenerator::Call(
    266     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    267   // First argument register contains the function target.
    268   Node* function = __ LoadRegisterFromRegisterList(args, 0);
    269 
    270   // The arguments for the target function are from the second runtime call
    271   // argument.
    272   InterpreterAssembler::RegListNodePair target_args(
    273       __ RegisterLocationInRegisterList(args, 1),
    274       __ Int32Sub(args.reg_count(), __ Int32Constant(1)));
    275 
    276   if (FLAG_debug_code) {
    277     InterpreterAssembler::Label arg_count_positive(assembler_);
    278     Node* comparison =
    279         __ Int32LessThan(target_args.reg_count(), __ Int32Constant(0));
    280     __ GotoIfNot(comparison, &arg_count_positive);
    281     __ Abort(AbortReason::kWrongArgumentCountForInvokeIntrinsic);
    282     __ Goto(&arg_count_positive);
    283     __ BIND(&arg_count_positive);
    284   }
    285 
    286   __ CallJSAndDispatch(function, context, target_args,
    287                        ConvertReceiverMode::kAny);
    288   return nullptr;  // We never return from the CallJSAndDispatch above.
    289 }
    290 
    291 Node* IntrinsicsGenerator::CreateAsyncFromSyncIterator(
    292     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    293   InterpreterAssembler::Label not_receiver(
    294       assembler_, InterpreterAssembler::Label::kDeferred);
    295   InterpreterAssembler::Label done(assembler_);
    296   InterpreterAssembler::Variable return_value(assembler_,
    297                                               MachineRepresentation::kTagged);
    298 
    299   Node* sync_iterator = __ LoadRegisterFromRegisterList(args, 0);
    300 
    301   __ GotoIf(__ TaggedIsSmi(sync_iterator), &not_receiver);
    302   __ GotoIfNot(__ IsJSReceiver(sync_iterator), &not_receiver);
    303 
    304   Node* const next =
    305       __ GetProperty(context, sync_iterator, factory()->next_string());
    306 
    307   Node* const native_context = __ LoadNativeContext(context);
    308   Node* const map = __ LoadContextElement(
    309       native_context, Context::ASYNC_FROM_SYNC_ITERATOR_MAP_INDEX);
    310   Node* const iterator = __ AllocateJSObjectFromMap(map);
    311 
    312   __ StoreObjectFieldNoWriteBarrier(
    313       iterator, JSAsyncFromSyncIterator::kSyncIteratorOffset, sync_iterator);
    314   __ StoreObjectFieldNoWriteBarrier(iterator,
    315                                     JSAsyncFromSyncIterator::kNextOffset, next);
    316 
    317   return_value.Bind(iterator);
    318   __ Goto(&done);
    319 
    320   __ BIND(&not_receiver);
    321   {
    322     return_value.Bind(
    323         __ CallRuntime(Runtime::kThrowSymbolIteratorInvalid, context));
    324 
    325     // Unreachable due to the Throw in runtime call.
    326     __ Goto(&done);
    327   }
    328 
    329   __ BIND(&done);
    330   return return_value.value();
    331 }
    332 
    333 Node* IntrinsicsGenerator::CreateJSGeneratorObject(
    334     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    335   return IntrinsicAsBuiltinCall(args, context,
    336                                 Builtins::kCreateGeneratorObject);
    337 }
    338 
    339 Node* IntrinsicsGenerator::GeneratorGetInputOrDebugPos(
    340     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    341   Node* generator = __ LoadRegisterFromRegisterList(args, 0);
    342   Node* const value =
    343       __ LoadObjectField(generator, JSGeneratorObject::kInputOrDebugPosOffset);
    344 
    345   return value;
    346 }
    347 
    348 Node* IntrinsicsGenerator::GeneratorGetResumeMode(
    349     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    350   Node* generator = __ LoadRegisterFromRegisterList(args, 0);
    351   Node* const value =
    352       __ LoadObjectField(generator, JSGeneratorObject::kResumeModeOffset);
    353 
    354   return value;
    355 }
    356 
    357 Node* IntrinsicsGenerator::GeneratorClose(
    358     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    359   Node* generator = __ LoadRegisterFromRegisterList(args, 0);
    360   __ StoreObjectFieldNoWriteBarrier(
    361       generator, JSGeneratorObject::kContinuationOffset,
    362       __ SmiConstant(JSGeneratorObject::kGeneratorClosed));
    363   return __ UndefinedConstant();
    364 }
    365 
    366 Node* IntrinsicsGenerator::GetImportMetaObject(
    367     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    368   Node* const module_context = __ LoadModuleContext(context);
    369   Node* const module =
    370       __ LoadContextElement(module_context, Context::EXTENSION_INDEX);
    371   Node* const import_meta =
    372       __ LoadObjectField(module, Module::kImportMetaOffset);
    373 
    374   InterpreterAssembler::Variable return_value(assembler_,
    375                                               MachineRepresentation::kTagged);
    376   return_value.Bind(import_meta);
    377 
    378   InterpreterAssembler::Label end(assembler_);
    379   __ GotoIfNot(__ IsTheHole(import_meta), &end);
    380 
    381   return_value.Bind(__ CallRuntime(Runtime::kGetImportMetaObject, context));
    382   __ Goto(&end);
    383 
    384   __ BIND(&end);
    385   return return_value.value();
    386 }
    387 
    388 Node* IntrinsicsGenerator::AsyncGeneratorReject(
    389     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    390   return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncGeneratorReject);
    391 }
    392 
    393 Node* IntrinsicsGenerator::AsyncGeneratorResolve(
    394     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    395   return IntrinsicAsBuiltinCall(args, context,
    396                                 Builtins::kAsyncGeneratorResolve);
    397 }
    398 
    399 Node* IntrinsicsGenerator::AsyncGeneratorYield(
    400     const InterpreterAssembler::RegListNodePair& args, Node* context) {
    401   return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncGeneratorYield);
    402 }
    403 
    404 void IntrinsicsGenerator::AbortIfArgCountMismatch(int expected, Node* actual) {
    405   InterpreterAssembler::Label match(assembler_);
    406   Node* comparison = __ Word32Equal(actual, __ Int32Constant(expected));
    407   __ GotoIf(comparison, &match);
    408   __ Abort(AbortReason::kWrongArgumentCountForInvokeIntrinsic);
    409   __ Goto(&match);
    410   __ BIND(&match);
    411 }
    412 
    413 #undef __
    414 
    415 }  // namespace interpreter
    416 }  // namespace internal
    417 }  // namespace v8
    418