5 #include "src/interpreter/interpreter-intrinsics-generator.h" 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" 21 namespace interpreter {
25 using TNode = compiler::TNode<T>;
30 : isolate_(assembler->isolate()),
31 zone_(assembler->zone()),
32 assembler_(assembler) {}
38 enum InstanceTypeCompareMode {
40 kInstanceTypeGreaterThanOrEqual
44 Node* CompareInstanceType(
Node* map,
int type, InstanceTypeCompareMode mode);
47 Node* IntrinsicAsBuiltinCall(
50 void AbortIfArgCountMismatch(
int expected,
compiler::Node* actual);
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 57 Isolate* isolate() {
return isolate_; }
58 Zone* zone() {
return zone_; }
59 Factory* factory() {
return isolate()->factory(); }
68 Node* GenerateInvokeIntrinsic(
72 return generator.InvokeIntrinsic(function_id, context, args);
75 #define __ assembler_-> 77 Node* IntrinsicsGenerator::InvokeIntrinsic(
79 const InterpreterAssembler::RegListNodePair& args) {
80 InterpreterAssembler::Label abort(assembler_), end(assembler_);
81 InterpreterAssembler::Variable result(assembler_,
82 MachineRepresentation::kTagged);
84 #define MAKE_LABEL(name, lower_case, count) \ 85 InterpreterAssembler::Label lower_case(assembler_); 86 INTRINSICS_LIST(MAKE_LABEL)
89 #define LABEL_POINTER(name, lower_case, count) &lower_case, 90 InterpreterAssembler::Label* labels[] = {INTRINSICS_LIST(LABEL_POINTER)};
93 #define CASE(name, lower_case, count) \ 94 static_cast<int32_t>(IntrinsicsHelper::IntrinsicId::k##name), 95 int32_t cases[] = {INTRINSICS_LIST(CASE)};
98 __ Switch(function_id, &abort, cases, labels, arraysize(cases));
99 #define HANDLE_CASE(name, lower_case, expected_arg_count) \ 100 __ BIND(&lower_case); \ 102 if (FLAG_debug_code && expected_arg_count >= 0) { \ 103 AbortIfArgCountMismatch(expected_arg_count, args.reg_count()); \ 105 Node* value = name(args, context); \ 107 result.Bind(value); \ 111 INTRINSICS_LIST(HANDLE_CASE)
116 __ Abort(AbortReason::kUnexpectedFunctionIDForInvokeIntrinsic);
117 result.Bind(__ UndefinedConstant());
122 return result.value();
125 Node* IntrinsicsGenerator::CompareInstanceType(Node*
object,
int type,
126 InstanceTypeCompareMode mode) {
127 Node* instance_type = __ LoadInstanceType(
object);
129 if (mode == kInstanceTypeEqual) {
130 return __ Word32Equal(instance_type, __ Int32Constant(type));
132 DCHECK_EQ(mode, kInstanceTypeGreaterThanOrEqual);
133 return __ Int32GreaterThanOrEqual(instance_type, __ Int32Constant(type));
137 Node* IntrinsicsGenerator::IsInstanceType(Node* input,
int type) {
138 TNode<Oddball> result = __ Select<Oddball>(
139 __ TaggedIsSmi(input), [=] {
return __ FalseConstant(); },
141 return __ SelectBooleanConstant(
142 CompareInstanceType(input, type, kInstanceTypeEqual));
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)); });
156 Node* IntrinsicsGenerator::IsArray(
157 const InterpreterAssembler::RegListNodePair& args, Node* context) {
158 Node* input = __ LoadRegisterFromRegisterList(args, 0);
159 return IsInstanceType(input, JS_ARRAY_TYPE);
162 Node* IntrinsicsGenerator::IsTypedArray(
163 const InterpreterAssembler::RegListNodePair& args, Node* context) {
164 Node* input = __ LoadRegisterFromRegisterList(args, 0);
165 return IsInstanceType(input, JS_TYPED_ARRAY_TYPE);
168 Node* IntrinsicsGenerator::IsSmi(
169 const InterpreterAssembler::RegListNodePair& args, Node* context) {
170 Node* input = __ LoadRegisterFromRegisterList(args, 0);
171 return __ SelectBooleanConstant(__ TaggedIsSmi(input));
174 Node* IntrinsicsGenerator::IntrinsicAsStubCall(
175 const InterpreterAssembler::RegListNodePair& args, Node* context,
176 Callable
const& callable) {
177 int param_count = callable.descriptor().GetParameterCount();
178 int input_count = param_count + 2;
179 Node** stub_args = zone()->NewArray<Node*>(input_count);
181 stub_args[index++] = __ HeapConstant(callable.code());
182 for (
int i = 0;
i < param_count;
i++) {
183 stub_args[index++] = __ LoadRegisterFromRegisterList(args,
i);
185 stub_args[index++] = context;
186 return __ CallStubN(callable.descriptor(), 1, input_count, stub_args);
189 Node* IntrinsicsGenerator::IntrinsicAsBuiltinCall(
190 const InterpreterAssembler::RegListNodePair& args, Node* context,
191 Builtins::Name name) {
192 Callable callable = Builtins::CallableFor(isolate_, name);
193 return IntrinsicAsStubCall(args, context, callable);
196 Node* IntrinsicsGenerator::CreateIterResultObject(
197 const InterpreterAssembler::RegListNodePair& args, Node* context) {
198 return IntrinsicAsStubCall(
200 Builtins::CallableFor(isolate(), Builtins::kCreateIterResultObject));
203 Node* IntrinsicsGenerator::HasProperty(
204 const InterpreterAssembler::RegListNodePair& args, Node* context) {
205 return IntrinsicAsStubCall(
206 args, context, Builtins::CallableFor(isolate(), Builtins::kHasProperty));
209 Node* IntrinsicsGenerator::ToString(
210 const InterpreterAssembler::RegListNodePair& args, Node* context) {
211 return IntrinsicAsStubCall(
212 args, context, Builtins::CallableFor(isolate(), Builtins::kToString));
215 Node* IntrinsicsGenerator::ToLength(
216 const InterpreterAssembler::RegListNodePair& args, Node* context) {
217 return IntrinsicAsStubCall(
218 args, context, Builtins::CallableFor(isolate(), Builtins::kToLength));
221 Node* IntrinsicsGenerator::ToObject(
222 const InterpreterAssembler::RegListNodePair& args, Node* context) {
223 return IntrinsicAsStubCall(
224 args, context, Builtins::CallableFor(isolate(), Builtins::kToObject));
227 Node* IntrinsicsGenerator::Call(
228 const InterpreterAssembler::RegListNodePair& args, Node* context) {
230 Node*
function = __ LoadRegisterFromRegisterList(args, 0);
234 InterpreterAssembler::RegListNodePair target_args(
235 __ RegisterLocationInRegisterList(args, 1),
236 __ Int32Sub(args.reg_count(), __ Int32Constant(1)));
238 if (FLAG_debug_code) {
239 InterpreterAssembler::Label arg_count_positive(assembler_);
241 __ Int32LessThan(target_args.reg_count(), __ Int32Constant(0));
242 __ GotoIfNot(comparison, &arg_count_positive);
243 __ Abort(AbortReason::kWrongArgumentCountForInvokeIntrinsic);
244 __ Goto(&arg_count_positive);
245 __ BIND(&arg_count_positive);
248 __ CallJSAndDispatch(
function, context, target_args,
249 ConvertReceiverMode::kAny);
253 Node* IntrinsicsGenerator::CreateAsyncFromSyncIterator(
254 const InterpreterAssembler::RegListNodePair& args, Node* context) {
255 InterpreterAssembler::Label not_receiver(
256 assembler_, InterpreterAssembler::Label::kDeferred);
257 InterpreterAssembler::Label done(assembler_);
258 InterpreterAssembler::Variable return_value(assembler_,
259 MachineRepresentation::kTagged);
261 Node* sync_iterator = __ LoadRegisterFromRegisterList(args, 0);
263 __ GotoIf(__ TaggedIsSmi(sync_iterator), ¬_receiver);
264 __ GotoIfNot(__ IsJSReceiver(sync_iterator), ¬_receiver);
267 __ GetProperty(context, sync_iterator, factory()->next_string());
269 Node*
const native_context = __ LoadNativeContext(context);
270 Node*
const map = __ LoadContextElement(
271 native_context, Context::ASYNC_FROM_SYNC_ITERATOR_MAP_INDEX);
272 Node*
const iterator = __ AllocateJSObjectFromMap(map);
274 __ StoreObjectFieldNoWriteBarrier(
275 iterator, JSAsyncFromSyncIterator::kSyncIteratorOffset, sync_iterator);
276 __ StoreObjectFieldNoWriteBarrier(iterator,
277 JSAsyncFromSyncIterator::kNextOffset, next);
279 return_value.Bind(iterator);
282 __ BIND(¬_receiver);
285 __ CallRuntime(Runtime::kThrowSymbolIteratorInvalid, context));
292 return return_value.value();
295 Node* IntrinsicsGenerator::CreateJSGeneratorObject(
296 const InterpreterAssembler::RegListNodePair& args, Node* context) {
297 return IntrinsicAsBuiltinCall(args, context,
298 Builtins::kCreateGeneratorObject);
301 Node* IntrinsicsGenerator::GeneratorGetResumeMode(
302 const InterpreterAssembler::RegListNodePair& args, Node* context) {
303 Node* generator = __ LoadRegisterFromRegisterList(args, 0);
305 __ LoadObjectField(generator, JSGeneratorObject::kResumeModeOffset);
310 Node* IntrinsicsGenerator::GeneratorClose(
311 const InterpreterAssembler::RegListNodePair& args, Node* context) {
312 Node* generator = __ LoadRegisterFromRegisterList(args, 0);
313 __ StoreObjectFieldNoWriteBarrier(
314 generator, JSGeneratorObject::kContinuationOffset,
315 __ SmiConstant(JSGeneratorObject::kGeneratorClosed));
316 return __ UndefinedConstant();
319 Node* IntrinsicsGenerator::GetImportMetaObject(
320 const InterpreterAssembler::RegListNodePair& args, Node* context) {
321 Node*
const module_context = __ LoadModuleContext(context);
323 __ LoadContextElement(module_context, Context::EXTENSION_INDEX);
324 Node*
const import_meta =
325 __ LoadObjectField(module, Module::kImportMetaOffset);
327 InterpreterAssembler::Variable return_value(assembler_,
328 MachineRepresentation::kTagged);
329 return_value.Bind(import_meta);
331 InterpreterAssembler::Label end(assembler_);
332 __ GotoIfNot(__ IsTheHole(import_meta), &end);
334 return_value.Bind(__ CallRuntime(Runtime::kGetImportMetaObject, context));
338 return return_value.value();
341 Node* IntrinsicsGenerator::AsyncFunctionAwaitCaught(
342 const InterpreterAssembler::RegListNodePair& args, Node* context) {
343 return IntrinsicAsBuiltinCall(args, context,
344 Builtins::kAsyncFunctionAwaitCaught);
347 Node* IntrinsicsGenerator::AsyncFunctionAwaitUncaught(
348 const InterpreterAssembler::RegListNodePair& args, Node* context) {
349 return IntrinsicAsBuiltinCall(args, context,
350 Builtins::kAsyncFunctionAwaitUncaught);
353 Node* IntrinsicsGenerator::AsyncFunctionEnter(
354 const InterpreterAssembler::RegListNodePair& args, Node* context) {
355 return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncFunctionEnter);
358 Node* IntrinsicsGenerator::AsyncFunctionReject(
359 const InterpreterAssembler::RegListNodePair& args, Node* context) {
360 return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncFunctionReject);
363 Node* IntrinsicsGenerator::AsyncFunctionResolve(
364 const InterpreterAssembler::RegListNodePair& args, Node* context) {
365 return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncFunctionResolve);
368 Node* IntrinsicsGenerator::AsyncGeneratorAwaitCaught(
369 const InterpreterAssembler::RegListNodePair& args, Node* context) {
370 return IntrinsicAsBuiltinCall(args, context,
371 Builtins::kAsyncGeneratorAwaitCaught);
374 Node* IntrinsicsGenerator::AsyncGeneratorAwaitUncaught(
375 const InterpreterAssembler::RegListNodePair& args, Node* context) {
376 return IntrinsicAsBuiltinCall(args, context,
377 Builtins::kAsyncGeneratorAwaitUncaught);
380 Node* IntrinsicsGenerator::AsyncGeneratorReject(
381 const InterpreterAssembler::RegListNodePair& args, Node* context) {
382 return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncGeneratorReject);
385 Node* IntrinsicsGenerator::AsyncGeneratorResolve(
386 const InterpreterAssembler::RegListNodePair& args, Node* context) {
387 return IntrinsicAsBuiltinCall(args, context,
388 Builtins::kAsyncGeneratorResolve);
391 Node* IntrinsicsGenerator::AsyncGeneratorYield(
392 const InterpreterAssembler::RegListNodePair& args, Node* context) {
393 return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncGeneratorYield);
396 void IntrinsicsGenerator::AbortIfArgCountMismatch(
int expected, Node* actual) {
397 InterpreterAssembler::Label match(assembler_);
398 Node* comparison = __ Word32Equal(actual, __ Int32Constant(expected));
399 __ GotoIf(comparison, &match);
400 __ Abort(AbortReason::kWrongArgumentCountForInvokeIntrinsic);