LCOV - code coverage report
Current view: top level - src/interpreter - interpreter-intrinsics-generator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 137 163 84.0 %
Date: 2019-04-19 Functions: 24 36 66.7 %

          Line data    Source code
       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         168 :   explicit IntrinsicsGenerator(InterpreterAssembler* assembler)
      30         168 :       : isolate_(assembler->isolate()),
      31         168 :         zone_(assembler->zone()),
      32         336 :         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         168 : Node* GenerateInvokeIntrinsic(
      69             :     InterpreterAssembler* assembler, Node* function_id, Node* context,
      70             :     const InterpreterAssembler::RegListNodePair& args) {
      71         168 :   IntrinsicsGenerator generator(assembler);
      72         168 :   return generator.InvokeIntrinsic(function_id, context, args);
      73             : }
      74             : 
      75             : #define __ assembler_->
      76             : 
      77         168 : Node* IntrinsicsGenerator::InvokeIntrinsic(
      78             :     Node* function_id, Node* context,
      79             :     const InterpreterAssembler::RegListNodePair& args) {
      80         504 :   InterpreterAssembler::Label abort(assembler_), end(assembler_);
      81         168 :   InterpreterAssembler::Variable result(assembler_,
      82         336 :                                         MachineRepresentation::kTagged);
      83             : 
      84             : #define MAKE_LABEL(name, lower_case, count) \
      85             :   InterpreterAssembler::Label lower_case(assembler_);
      86        4368 :   INTRINSICS_LIST(MAKE_LABEL)
      87             : #undef MAKE_LABEL
      88             : 
      89             : #define LABEL_POINTER(name, lower_case, count) &lower_case,
      90         168 :   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         168 :   int32_t cases[] = {INTRINSICS_LIST(CASE)};
      96             : #undef CASE
      97             : 
      98         168 :   __ 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        2016 :   INTRINSICS_LIST(HANDLE_CASE)
     112             : #undef HANDLE_CASE
     113             : 
     114         168 :   __ BIND(&abort);
     115             :   {
     116         168 :     __ Abort(AbortReason::kUnexpectedFunctionIDForInvokeIntrinsic);
     117         336 :     result.Bind(__ UndefinedConstant());
     118         168 :     __ Goto(&end);
     119             :   }
     120             : 
     121         168 :   __ BIND(&end);
     122         336 :   return result.value();
     123             : }
     124             : 
     125         336 : Node* IntrinsicsGenerator::CompareInstanceType(Node* object, int type,
     126             :                                                InstanceTypeCompareMode mode) {
     127         672 :   Node* instance_type = __ LoadInstanceType(object);
     128             : 
     129         336 :   if (mode == kInstanceTypeEqual) {
     130        1008 :     return __ Word32Equal(instance_type, __ Int32Constant(type));
     131             :   } else {
     132             :     DCHECK_EQ(mode, kInstanceTypeGreaterThanOrEqual);
     133           0 :     return __ Int32GreaterThanOrEqual(instance_type, __ Int32Constant(type));
     134             :   }
     135             : }
     136             : 
     137         336 : Node* IntrinsicsGenerator::IsInstanceType(Node* input, int type) {
     138         336 :   TNode<Oddball> result = __ Select<Oddball>(
     139        1008 :       __ TaggedIsSmi(input), [=] { return __ FalseConstant(); },
     140         336 :       [=] {
     141         672 :         return __ SelectBooleanConstant(
     142        1344 :             CompareInstanceType(input, type, kInstanceTypeEqual));
     143        1680 :       });
     144         336 :   return result;
     145             : }
     146             : 
     147         168 : Node* IntrinsicsGenerator::IsJSReceiver(
     148             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     149         168 :   Node* input = __ LoadRegisterFromRegisterList(args, 0);
     150         168 :   TNode<Oddball> result = __ Select<Oddball>(
     151         504 :       __ TaggedIsSmi(input), [=] { return __ FalseConstant(); },
     152        1008 :       [=] { return __ SelectBooleanConstant(__ IsJSReceiver(input)); });
     153         168 :   return result;
     154             : }
     155             : 
     156         168 : Node* IntrinsicsGenerator::IsArray(
     157             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     158         168 :   Node* input = __ LoadRegisterFromRegisterList(args, 0);
     159         168 :   return IsInstanceType(input, JS_ARRAY_TYPE);
     160             : }
     161             : 
     162         168 : Node* IntrinsicsGenerator::IsTypedArray(
     163             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     164         168 :   Node* input = __ LoadRegisterFromRegisterList(args, 0);
     165         168 :   return IsInstanceType(input, JS_TYPED_ARRAY_TYPE);
     166             : }
     167             : 
     168         168 : Node* IntrinsicsGenerator::IsSmi(
     169             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     170         168 :   Node* input = __ LoadRegisterFromRegisterList(args, 0);
     171         504 :   return __ SelectBooleanConstant(__ TaggedIsSmi(input));
     172             : }
     173             : 
     174        2688 : Node* IntrinsicsGenerator::IntrinsicAsStubCall(
     175             :     const InterpreterAssembler::RegListNodePair& args, Node* context,
     176             :     Callable const& callable) {
     177             :   int param_count = callable.descriptor().GetParameterCount();
     178        2688 :   int input_count = param_count + 2;  // +2 for target and context
     179        2688 :   Node** stub_args = zone()->NewArray<Node*>(input_count);
     180             :   int index = 0;
     181        5376 :   stub_args[index++] = __ HeapConstant(callable.code());
     182       13776 :   for (int i = 0; i < param_count; i++) {
     183        5544 :     stub_args[index++] = __ LoadRegisterFromRegisterList(args, i);
     184             :   }
     185        2688 :   stub_args[index++] = context;
     186        5376 :   return __ CallStubN(StubCallMode::kCallCodeObject, callable.descriptor(), 1,
     187        5376 :                       input_count, stub_args);
     188             : }
     189             : 
     190        1848 : Node* IntrinsicsGenerator::IntrinsicAsBuiltinCall(
     191             :     const InterpreterAssembler::RegListNodePair& args, Node* context,
     192             :     Builtins::Name name) {
     193        1848 :   Callable callable = Builtins::CallableFor(isolate_, name);
     194        3696 :   return IntrinsicAsStubCall(args, context, callable);
     195             : }
     196             : 
     197         168 : Node* IntrinsicsGenerator::CreateIterResultObject(
     198             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     199             :   return IntrinsicAsStubCall(
     200             :       args, context,
     201         336 :       Builtins::CallableFor(isolate(), Builtins::kCreateIterResultObject));
     202             : }
     203             : 
     204         168 : Node* IntrinsicsGenerator::HasProperty(
     205             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     206             :   return IntrinsicAsStubCall(
     207         336 :       args, context, Builtins::CallableFor(isolate(), Builtins::kHasProperty));
     208             : }
     209             : 
     210         168 : Node* IntrinsicsGenerator::ToString(
     211             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     212             :   return IntrinsicAsStubCall(
     213         336 :       args, context, Builtins::CallableFor(isolate(), Builtins::kToString));
     214             : }
     215             : 
     216         168 : Node* IntrinsicsGenerator::ToLength(
     217             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     218             :   return IntrinsicAsStubCall(
     219         336 :       args, context, Builtins::CallableFor(isolate(), Builtins::kToLength));
     220             : }
     221             : 
     222         168 : Node* IntrinsicsGenerator::ToObject(
     223             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     224             :   return IntrinsicAsStubCall(
     225         336 :       args, context, Builtins::CallableFor(isolate(), Builtins::kToObject));
     226             : }
     227             : 
     228         168 : Node* IntrinsicsGenerator::Call(
     229             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     230             :   // First argument register contains the function target.
     231         168 :   Node* function = __ LoadRegisterFromRegisterList(args, 0);
     232             : 
     233             :   // The arguments for the target function are from the second runtime call
     234             :   // argument.
     235             :   InterpreterAssembler::RegListNodePair target_args(
     236         168 :       __ RegisterLocationInRegisterList(args, 1),
     237         672 :       __ Int32Sub(args.reg_count(), __ Int32Constant(1)));
     238             : 
     239         168 :   if (FLAG_debug_code) {
     240           0 :     InterpreterAssembler::Label arg_count_positive(assembler_);
     241             :     Node* comparison =
     242           0 :         __ Int32LessThan(target_args.reg_count(), __ Int32Constant(0));
     243           0 :     __ GotoIfNot(comparison, &arg_count_positive);
     244           0 :     __ Abort(AbortReason::kWrongArgumentCountForInvokeIntrinsic);
     245           0 :     __ Goto(&arg_count_positive);
     246           0 :     __ BIND(&arg_count_positive);
     247             :   }
     248             : 
     249         168 :   __ CallJSAndDispatch(function, context, target_args,
     250         168 :                        ConvertReceiverMode::kAny);
     251         168 :   return nullptr;  // We never return from the CallJSAndDispatch above.
     252             : }
     253             : 
     254         168 : Node* IntrinsicsGenerator::CreateAsyncFromSyncIterator(
     255             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     256             :   InterpreterAssembler::Label not_receiver(
     257         336 :       assembler_, InterpreterAssembler::Label::kDeferred);
     258         336 :   InterpreterAssembler::Label done(assembler_);
     259         168 :   InterpreterAssembler::Variable return_value(assembler_,
     260         336 :                                               MachineRepresentation::kTagged);
     261             : 
     262         168 :   Node* sync_iterator = __ LoadRegisterFromRegisterList(args, 0);
     263             : 
     264         336 :   __ GotoIf(__ TaggedIsSmi(sync_iterator), &not_receiver);
     265         336 :   __ GotoIfNot(__ IsJSReceiver(sync_iterator), &not_receiver);
     266             : 
     267             :   Node* const next =
     268         336 :       __ GetProperty(context, sync_iterator, factory()->next_string());
     269             : 
     270         336 :   Node* const native_context = __ LoadNativeContext(context);
     271         504 :   Node* const map = __ LoadContextElement(
     272         336 :       native_context, Context::ASYNC_FROM_SYNC_ITERATOR_MAP_INDEX);
     273         168 :   Node* const iterator = __ AllocateJSObjectFromMap(map);
     274             : 
     275         168 :   __ StoreObjectFieldNoWriteBarrier(
     276         168 :       iterator, JSAsyncFromSyncIterator::kSyncIteratorOffset, sync_iterator);
     277         168 :   __ StoreObjectFieldNoWriteBarrier(iterator,
     278         168 :                                     JSAsyncFromSyncIterator::kNextOffset, next);
     279             : 
     280         168 :   return_value.Bind(iterator);
     281         168 :   __ Goto(&done);
     282             : 
     283         168 :   __ BIND(&not_receiver);
     284             :   {
     285             :     return_value.Bind(
     286         336 :         __ CallRuntime(Runtime::kThrowSymbolIteratorInvalid, context));
     287             : 
     288             :     // Unreachable due to the Throw in runtime call.
     289         168 :     __ Goto(&done);
     290             :   }
     291             : 
     292         168 :   __ BIND(&done);
     293         336 :   return return_value.value();
     294             : }
     295             : 
     296           0 : Node* IntrinsicsGenerator::CreateJSGeneratorObject(
     297             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     298             :   return IntrinsicAsBuiltinCall(args, context,
     299         168 :                                 Builtins::kCreateGeneratorObject);
     300             : }
     301             : 
     302         168 : Node* IntrinsicsGenerator::GeneratorGetResumeMode(
     303             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     304         168 :   Node* generator = __ LoadRegisterFromRegisterList(args, 0);
     305             :   Node* const value =
     306         168 :       __ LoadObjectField(generator, JSGeneratorObject::kResumeModeOffset);
     307             : 
     308         168 :   return value;
     309             : }
     310             : 
     311         168 : Node* IntrinsicsGenerator::GeneratorClose(
     312             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     313         168 :   Node* generator = __ LoadRegisterFromRegisterList(args, 0);
     314         168 :   __ StoreObjectFieldNoWriteBarrier(
     315             :       generator, JSGeneratorObject::kContinuationOffset,
     316         336 :       __ SmiConstant(JSGeneratorObject::kGeneratorClosed));
     317         336 :   return __ UndefinedConstant();
     318             : }
     319             : 
     320         168 : Node* IntrinsicsGenerator::GetImportMetaObject(
     321             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     322         336 :   Node* const module_context = __ LoadModuleContext(context);
     323             :   Node* const module =
     324         336 :       __ LoadContextElement(module_context, Context::EXTENSION_INDEX);
     325             :   Node* const import_meta =
     326         168 :       __ LoadObjectField(module, Module::kImportMetaOffset);
     327             : 
     328         168 :   InterpreterAssembler::Variable return_value(assembler_,
     329         336 :                                               MachineRepresentation::kTagged);
     330         168 :   return_value.Bind(import_meta);
     331             : 
     332         336 :   InterpreterAssembler::Label end(assembler_);
     333         336 :   __ GotoIfNot(__ IsTheHole(import_meta), &end);
     334             : 
     335         336 :   return_value.Bind(__ CallRuntime(Runtime::kGetImportMetaObject, context));
     336         168 :   __ Goto(&end);
     337             : 
     338         168 :   __ BIND(&end);
     339         336 :   return return_value.value();
     340             : }
     341             : 
     342           0 : Node* IntrinsicsGenerator::AsyncFunctionAwaitCaught(
     343             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     344             :   return IntrinsicAsBuiltinCall(args, context,
     345         168 :                                 Builtins::kAsyncFunctionAwaitCaught);
     346             : }
     347             : 
     348           0 : Node* IntrinsicsGenerator::AsyncFunctionAwaitUncaught(
     349             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     350             :   return IntrinsicAsBuiltinCall(args, context,
     351         168 :                                 Builtins::kAsyncFunctionAwaitUncaught);
     352             : }
     353             : 
     354           0 : Node* IntrinsicsGenerator::AsyncFunctionEnter(
     355             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     356         168 :   return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncFunctionEnter);
     357             : }
     358             : 
     359           0 : Node* IntrinsicsGenerator::AsyncFunctionReject(
     360             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     361         168 :   return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncFunctionReject);
     362             : }
     363             : 
     364           0 : Node* IntrinsicsGenerator::AsyncFunctionResolve(
     365             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     366         168 :   return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncFunctionResolve);
     367             : }
     368             : 
     369           0 : Node* IntrinsicsGenerator::AsyncGeneratorAwaitCaught(
     370             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     371             :   return IntrinsicAsBuiltinCall(args, context,
     372         168 :                                 Builtins::kAsyncGeneratorAwaitCaught);
     373             : }
     374             : 
     375           0 : Node* IntrinsicsGenerator::AsyncGeneratorAwaitUncaught(
     376             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     377             :   return IntrinsicAsBuiltinCall(args, context,
     378         168 :                                 Builtins::kAsyncGeneratorAwaitUncaught);
     379             : }
     380             : 
     381           0 : Node* IntrinsicsGenerator::AsyncGeneratorReject(
     382             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     383         168 :   return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncGeneratorReject);
     384             : }
     385             : 
     386           0 : Node* IntrinsicsGenerator::AsyncGeneratorResolve(
     387             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     388             :   return IntrinsicAsBuiltinCall(args, context,
     389         168 :                                 Builtins::kAsyncGeneratorResolve);
     390             : }
     391             : 
     392           0 : Node* IntrinsicsGenerator::AsyncGeneratorYield(
     393             :     const InterpreterAssembler::RegListNodePair& args, Node* context) {
     394         168 :   return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncGeneratorYield);
     395             : }
     396             : 
     397           0 : void IntrinsicsGenerator::AbortIfArgCountMismatch(int expected, Node* actual) {
     398           0 :   InterpreterAssembler::Label match(assembler_);
     399           0 :   Node* comparison = __ Word32Equal(actual, __ Int32Constant(expected));
     400           0 :   __ GotoIf(comparison, &match);
     401           0 :   __ Abort(AbortReason::kWrongArgumentCountForInvokeIntrinsic);
     402           0 :   __ Goto(&match);
     403           0 :   __ BIND(&match);
     404           0 : }
     405             : 
     406             : #undef __
     407             : 
     408             : }  // namespace interpreter
     409             : }  // namespace internal
     410       59480 : }  // namespace v8

Generated by: LCOV version 1.10