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