• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/builtins/builtins.h"
8 #include "src/codegen/code-factory.h"
9 #include "src/execution/frames.h"
10 #include "src/heap/factory-inl.h"
11 #include "src/interpreter/bytecodes.h"
12 #include "src/interpreter/interpreter-assembler.h"
13 #include "src/interpreter/interpreter-intrinsics.h"
14 #include "src/objects/js-generator.h"
15 #include "src/objects/objects-inl.h"
16 #include "src/objects/source-text-module.h"
17 #include "src/utils/allocation.h"
18 
19 namespace v8 {
20 namespace internal {
21 namespace interpreter {
22 
23 class IntrinsicsGenerator {
24  public:
IntrinsicsGenerator(InterpreterAssembler * assembler)25   explicit IntrinsicsGenerator(InterpreterAssembler* assembler)
26       : isolate_(assembler->isolate()),
27         zone_(assembler->zone()),
28         assembler_(assembler) {}
29   IntrinsicsGenerator(const IntrinsicsGenerator&) = delete;
30   IntrinsicsGenerator& operator=(const IntrinsicsGenerator&) = delete;
31 
32   TNode<Object> InvokeIntrinsic(
33       TNode<Uint32T> function_id, TNode<Context> context,
34       const InterpreterAssembler::RegListNodePair& args);
35 
36  private:
37   TNode<Object> IntrinsicAsBuiltinCall(
38       const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
39       Builtin name, int arg_count);
40   void AbortIfArgCountMismatch(int expected, TNode<Word32T> actual);
41 
42 #define DECLARE_INTRINSIC_HELPER(name, lower_case, count)               \
43   TNode<Object> name(const InterpreterAssembler::RegListNodePair& args, \
44                      TNode<Context> context, int arg_count);
INTRINSICS_LIST(DECLARE_INTRINSIC_HELPER)45   INTRINSICS_LIST(DECLARE_INTRINSIC_HELPER)
46 #undef DECLARE_INTRINSIC_HELPER
47 
48   Isolate* isolate() { return isolate_; }
zone()49   Zone* zone() { return zone_; }
factory()50   Factory* factory() { return isolate()->factory(); }
51 
52   Isolate* isolate_;
53   Zone* zone_;
54   InterpreterAssembler* assembler_;
55 };
56 
GenerateInvokeIntrinsic(InterpreterAssembler * assembler,TNode<Uint32T> function_id,TNode<Context> context,const InterpreterAssembler::RegListNodePair & args)57 TNode<Object> GenerateInvokeIntrinsic(
58     InterpreterAssembler* assembler, TNode<Uint32T> function_id,
59     TNode<Context> context, const InterpreterAssembler::RegListNodePair& args) {
60   IntrinsicsGenerator generator(assembler);
61   return generator.InvokeIntrinsic(function_id, context, args);
62 }
63 
64 #define __ assembler_->
65 
InvokeIntrinsic(TNode<Uint32T> function_id,TNode<Context> context,const InterpreterAssembler::RegListNodePair & args)66 TNode<Object> IntrinsicsGenerator::InvokeIntrinsic(
67     TNode<Uint32T> function_id, TNode<Context> context,
68     const InterpreterAssembler::RegListNodePair& args) {
69   InterpreterAssembler::Label abort(assembler_), end(assembler_);
70   InterpreterAssembler::TVariable<Object> result(assembler_);
71 
72 #define MAKE_LABEL(name, lower_case, count) \
73   InterpreterAssembler::Label lower_case(assembler_);
74   INTRINSICS_LIST(MAKE_LABEL)
75 #undef MAKE_LABEL
76 
77 #define LABEL_POINTER(name, lower_case, count) &lower_case,
78   InterpreterAssembler::Label* labels[] = {INTRINSICS_LIST(LABEL_POINTER)};
79 #undef LABEL_POINTER
80 
81 #define CASE(name, lower_case, count) \
82   static_cast<int32_t>(IntrinsicsHelper::IntrinsicId::k##name),
83   int32_t cases[] = {INTRINSICS_LIST(CASE)};
84 #undef CASE
85 
86   __ Switch(function_id, &abort, cases, labels, arraysize(cases));
87 #define HANDLE_CASE(name, lower_case, expected_arg_count)            \
88   __ BIND(&lower_case);                                              \
89   {                                                                  \
90     if (FLAG_debug_code && expected_arg_count >= 0) {                \
91       AbortIfArgCountMismatch(expected_arg_count, args.reg_count()); \
92     }                                                                \
93     TNode<Object> value = name(args, context, expected_arg_count);   \
94     if (value) {                                                     \
95       result = value;                                                \
96       __ Goto(&end);                                                 \
97     }                                                                \
98   }
99   INTRINSICS_LIST(HANDLE_CASE)
100 #undef HANDLE_CASE
101 
102   __ BIND(&abort);
103   {
104     __ Abort(AbortReason::kUnexpectedFunctionIDForInvokeIntrinsic);
105     result = __ UndefinedConstant();
106     __ Goto(&end);
107   }
108 
109   __ BIND(&end);
110   return result.value();
111 }
112 
IntrinsicAsBuiltinCall(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,Builtin name,int arg_count)113 TNode<Object> IntrinsicsGenerator::IntrinsicAsBuiltinCall(
114     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
115     Builtin name, int arg_count) {
116   Callable callable = Builtins::CallableFor(isolate_, name);
117   switch (arg_count) {
118     case 1:
119       return __ CallStub(callable, context,
120                          __ LoadRegisterFromRegisterList(args, 0));
121     case 2:
122       return __ CallStub(callable, context,
123                          __ LoadRegisterFromRegisterList(args, 0),
124                          __ LoadRegisterFromRegisterList(args, 1));
125     case 3:
126       return __ CallStub(callable, context,
127                          __ LoadRegisterFromRegisterList(args, 0),
128                          __ LoadRegisterFromRegisterList(args, 1),
129                          __ LoadRegisterFromRegisterList(args, 2));
130     default:
131       UNREACHABLE();
132   }
133 }
134 
CopyDataProperties(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)135 TNode<Object> IntrinsicsGenerator::CopyDataProperties(
136     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
137     int arg_count) {
138   return IntrinsicAsBuiltinCall(args, context, Builtin::kCopyDataProperties,
139                                 arg_count);
140 }
141 
142 TNode<Object>
CopyDataPropertiesWithExcludedPropertiesOnStack(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)143 IntrinsicsGenerator::CopyDataPropertiesWithExcludedPropertiesOnStack(
144     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
145     int arg_count) {
146   TNode<IntPtrT> offset = __ TimesSystemPointerSize(__ IntPtrConstant(1));
147   auto base = __ Signed(__ IntPtrSub(args.base_reg_location(), offset));
148   Callable callable = Builtins::CallableFor(
149       isolate_, Builtin::kCopyDataPropertiesWithExcludedPropertiesOnStack);
150   TNode<IntPtrT> excluded_property_count = __ IntPtrSub(
151       __ ChangeInt32ToIntPtr(args.reg_count()), __ IntPtrConstant(1));
152   return __ CallStub(callable, context,
153                      __ LoadRegisterFromRegisterList(args, 0),
154                      excluded_property_count, base);
155 }
156 
CreateIterResultObject(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)157 TNode<Object> IntrinsicsGenerator::CreateIterResultObject(
158     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
159     int arg_count) {
160   return IntrinsicAsBuiltinCall(args, context, Builtin::kCreateIterResultObject,
161                                 arg_count);
162 }
163 
CreateAsyncFromSyncIterator(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)164 TNode<Object> IntrinsicsGenerator::CreateAsyncFromSyncIterator(
165     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
166     int arg_count) {
167   TNode<Object> sync_iterator = __ LoadRegisterFromRegisterList(args, 0);
168   return __ CreateAsyncFromSyncIterator(context, sync_iterator);
169 }
170 
CreateJSGeneratorObject(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)171 TNode<Object> IntrinsicsGenerator::CreateJSGeneratorObject(
172     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
173     int arg_count) {
174   return IntrinsicAsBuiltinCall(args, context, Builtin::kCreateGeneratorObject,
175                                 arg_count);
176 }
177 
GeneratorGetResumeMode(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)178 TNode<Object> IntrinsicsGenerator::GeneratorGetResumeMode(
179     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
180     int arg_count) {
181   TNode<JSGeneratorObject> generator =
182       __ CAST(__ LoadRegisterFromRegisterList(args, 0));
183   const TNode<Object> value =
184       __ LoadObjectField(generator, JSGeneratorObject::kResumeModeOffset);
185 
186   return value;
187 }
188 
GeneratorClose(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)189 TNode<Object> IntrinsicsGenerator::GeneratorClose(
190     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
191     int arg_count) {
192   TNode<JSGeneratorObject> generator =
193       __ CAST(__ LoadRegisterFromRegisterList(args, 0));
194   __ StoreObjectFieldNoWriteBarrier(
195       generator, JSGeneratorObject::kContinuationOffset,
196       __ SmiConstant(JSGeneratorObject::kGeneratorClosed));
197   return __ UndefinedConstant();
198 }
199 
GetImportMetaObject(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)200 TNode<Object> IntrinsicsGenerator::GetImportMetaObject(
201     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
202     int arg_count) {
203   return __ GetImportMetaObject(context);
204 }
205 
AsyncFunctionAwaitCaught(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)206 TNode<Object> IntrinsicsGenerator::AsyncFunctionAwaitCaught(
207     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
208     int arg_count) {
209   return IntrinsicAsBuiltinCall(args, context,
210                                 Builtin::kAsyncFunctionAwaitCaught, arg_count);
211 }
212 
AsyncFunctionAwaitUncaught(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)213 TNode<Object> IntrinsicsGenerator::AsyncFunctionAwaitUncaught(
214     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
215     int arg_count) {
216   return IntrinsicAsBuiltinCall(
217       args, context, Builtin::kAsyncFunctionAwaitUncaught, arg_count);
218 }
219 
AsyncFunctionEnter(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)220 TNode<Object> IntrinsicsGenerator::AsyncFunctionEnter(
221     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
222     int arg_count) {
223   return IntrinsicAsBuiltinCall(args, context, Builtin::kAsyncFunctionEnter,
224                                 arg_count);
225 }
226 
AsyncFunctionReject(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)227 TNode<Object> IntrinsicsGenerator::AsyncFunctionReject(
228     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
229     int arg_count) {
230   return IntrinsicAsBuiltinCall(args, context, Builtin::kAsyncFunctionReject,
231                                 arg_count);
232 }
233 
AsyncFunctionResolve(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)234 TNode<Object> IntrinsicsGenerator::AsyncFunctionResolve(
235     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
236     int arg_count) {
237   return IntrinsicAsBuiltinCall(args, context, Builtin::kAsyncFunctionResolve,
238                                 arg_count);
239 }
240 
AsyncGeneratorAwaitCaught(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)241 TNode<Object> IntrinsicsGenerator::AsyncGeneratorAwaitCaught(
242     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
243     int arg_count) {
244   return IntrinsicAsBuiltinCall(args, context,
245                                 Builtin::kAsyncGeneratorAwaitCaught, arg_count);
246 }
247 
AsyncGeneratorAwaitUncaught(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)248 TNode<Object> IntrinsicsGenerator::AsyncGeneratorAwaitUncaught(
249     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
250     int arg_count) {
251   return IntrinsicAsBuiltinCall(
252       args, context, Builtin::kAsyncGeneratorAwaitUncaught, arg_count);
253 }
254 
AsyncGeneratorReject(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)255 TNode<Object> IntrinsicsGenerator::AsyncGeneratorReject(
256     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
257     int arg_count) {
258   return IntrinsicAsBuiltinCall(args, context, Builtin::kAsyncGeneratorReject,
259                                 arg_count);
260 }
261 
AsyncGeneratorResolve(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)262 TNode<Object> IntrinsicsGenerator::AsyncGeneratorResolve(
263     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
264     int arg_count) {
265   return IntrinsicAsBuiltinCall(args, context, Builtin::kAsyncGeneratorResolve,
266                                 arg_count);
267 }
268 
AsyncGeneratorYield(const InterpreterAssembler::RegListNodePair & args,TNode<Context> context,int arg_count)269 TNode<Object> IntrinsicsGenerator::AsyncGeneratorYield(
270     const InterpreterAssembler::RegListNodePair& args, TNode<Context> context,
271     int arg_count) {
272   return IntrinsicAsBuiltinCall(args, context, Builtin::kAsyncGeneratorYield,
273                                 arg_count);
274 }
275 
AbortIfArgCountMismatch(int expected,TNode<Word32T> actual)276 void IntrinsicsGenerator::AbortIfArgCountMismatch(int expected,
277                                                   TNode<Word32T> actual) {
278   InterpreterAssembler::Label match(assembler_);
279   TNode<BoolT> comparison = __ Word32Equal(actual, __ Int32Constant(expected));
280   __ GotoIf(comparison, &match);
281   __ Abort(AbortReason::kWrongArgumentCountForInvokeIntrinsic);
282   __ Goto(&match);
283   __ BIND(&match);
284 }
285 
286 #undef __
287 
288 }  // namespace interpreter
289 }  // namespace internal
290 }  // namespace v8
291