V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
interpreter-intrinsics-generator.cc
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 
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,
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,
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::IsTypedArray(
163  const InterpreterAssembler::RegListNodePair& args, Node* context) {
164  Node* input = __ LoadRegisterFromRegisterList(args, 0);
165  return IsInstanceType(input, JS_TYPED_ARRAY_TYPE);
166 }
167 
168 Node* IntrinsicsGenerator::IsSmi(
169  const InterpreterAssembler::RegListNodePair& args, Node* context) {
170  Node* input = __ LoadRegisterFromRegisterList(args, 0);
171  return __ SelectBooleanConstant(__ TaggedIsSmi(input));
172 }
173 
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; // +2 for target and context
179  Node** stub_args = zone()->NewArray<Node*>(input_count);
180  int index = 0;
181  stub_args[index++] = __ HeapConstant(callable.code());
182  for (int i = 0; i < param_count; i++) {
183  stub_args[index++] = __ LoadRegisterFromRegisterList(args, i);
184  }
185  stub_args[index++] = context;
186  return __ CallStubN(callable.descriptor(), 1, input_count, stub_args);
187 }
188 
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);
194 }
195 
196 Node* IntrinsicsGenerator::CreateIterResultObject(
197  const InterpreterAssembler::RegListNodePair& args, Node* context) {
198  return IntrinsicAsStubCall(
199  args, context,
200  Builtins::CallableFor(isolate(), Builtins::kCreateIterResultObject));
201 }
202 
203 Node* IntrinsicsGenerator::HasProperty(
204  const InterpreterAssembler::RegListNodePair& args, Node* context) {
205  return IntrinsicAsStubCall(
206  args, context, Builtins::CallableFor(isolate(), Builtins::kHasProperty));
207 }
208 
209 Node* IntrinsicsGenerator::ToString(
210  const InterpreterAssembler::RegListNodePair& args, Node* context) {
211  return IntrinsicAsStubCall(
212  args, context, Builtins::CallableFor(isolate(), Builtins::kToString));
213 }
214 
215 Node* IntrinsicsGenerator::ToLength(
216  const InterpreterAssembler::RegListNodePair& args, Node* context) {
217  return IntrinsicAsStubCall(
218  args, context, Builtins::CallableFor(isolate(), Builtins::kToLength));
219 }
220 
221 Node* IntrinsicsGenerator::ToObject(
222  const InterpreterAssembler::RegListNodePair& args, Node* context) {
223  return IntrinsicAsStubCall(
224  args, context, Builtins::CallableFor(isolate(), Builtins::kToObject));
225 }
226 
227 Node* IntrinsicsGenerator::Call(
228  const InterpreterAssembler::RegListNodePair& args, Node* context) {
229  // First argument register contains the function target.
230  Node* function = __ LoadRegisterFromRegisterList(args, 0);
231 
232  // The arguments for the target function are from the second runtime call
233  // argument.
234  InterpreterAssembler::RegListNodePair target_args(
235  __ RegisterLocationInRegisterList(args, 1),
236  __ Int32Sub(args.reg_count(), __ Int32Constant(1)));
237 
238  if (FLAG_debug_code) {
239  InterpreterAssembler::Label arg_count_positive(assembler_);
240  Node* comparison =
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);
246  }
247 
248  __ CallJSAndDispatch(function, context, target_args,
249  ConvertReceiverMode::kAny);
250  return nullptr; // We never return from the CallJSAndDispatch above.
251 }
252 
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);
260 
261  Node* sync_iterator = __ LoadRegisterFromRegisterList(args, 0);
262 
263  __ GotoIf(__ TaggedIsSmi(sync_iterator), &not_receiver);
264  __ GotoIfNot(__ IsJSReceiver(sync_iterator), &not_receiver);
265 
266  Node* const next =
267  __ GetProperty(context, sync_iterator, factory()->next_string());
268 
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);
273 
274  __ StoreObjectFieldNoWriteBarrier(
275  iterator, JSAsyncFromSyncIterator::kSyncIteratorOffset, sync_iterator);
276  __ StoreObjectFieldNoWriteBarrier(iterator,
277  JSAsyncFromSyncIterator::kNextOffset, next);
278 
279  return_value.Bind(iterator);
280  __ Goto(&done);
281 
282  __ BIND(&not_receiver);
283  {
284  return_value.Bind(
285  __ CallRuntime(Runtime::kThrowSymbolIteratorInvalid, context));
286 
287  // Unreachable due to the Throw in runtime call.
288  __ Goto(&done);
289  }
290 
291  __ BIND(&done);
292  return return_value.value();
293 }
294 
295 Node* IntrinsicsGenerator::CreateJSGeneratorObject(
296  const InterpreterAssembler::RegListNodePair& args, Node* context) {
297  return IntrinsicAsBuiltinCall(args, context,
298  Builtins::kCreateGeneratorObject);
299 }
300 
301 Node* IntrinsicsGenerator::GeneratorGetResumeMode(
302  const InterpreterAssembler::RegListNodePair& args, Node* context) {
303  Node* generator = __ LoadRegisterFromRegisterList(args, 0);
304  Node* const value =
305  __ LoadObjectField(generator, JSGeneratorObject::kResumeModeOffset);
306 
307  return value;
308 }
309 
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();
317 }
318 
319 Node* IntrinsicsGenerator::GetImportMetaObject(
320  const InterpreterAssembler::RegListNodePair& args, Node* context) {
321  Node* const module_context = __ LoadModuleContext(context);
322  Node* const module =
323  __ LoadContextElement(module_context, Context::EXTENSION_INDEX);
324  Node* const import_meta =
325  __ LoadObjectField(module, Module::kImportMetaOffset);
326 
327  InterpreterAssembler::Variable return_value(assembler_,
328  MachineRepresentation::kTagged);
329  return_value.Bind(import_meta);
330 
331  InterpreterAssembler::Label end(assembler_);
332  __ GotoIfNot(__ IsTheHole(import_meta), &end);
333 
334  return_value.Bind(__ CallRuntime(Runtime::kGetImportMetaObject, context));
335  __ Goto(&end);
336 
337  __ BIND(&end);
338  return return_value.value();
339 }
340 
341 Node* IntrinsicsGenerator::AsyncFunctionAwaitCaught(
342  const InterpreterAssembler::RegListNodePair& args, Node* context) {
343  return IntrinsicAsBuiltinCall(args, context,
344  Builtins::kAsyncFunctionAwaitCaught);
345 }
346 
347 Node* IntrinsicsGenerator::AsyncFunctionAwaitUncaught(
348  const InterpreterAssembler::RegListNodePair& args, Node* context) {
349  return IntrinsicAsBuiltinCall(args, context,
350  Builtins::kAsyncFunctionAwaitUncaught);
351 }
352 
353 Node* IntrinsicsGenerator::AsyncFunctionEnter(
354  const InterpreterAssembler::RegListNodePair& args, Node* context) {
355  return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncFunctionEnter);
356 }
357 
358 Node* IntrinsicsGenerator::AsyncFunctionReject(
359  const InterpreterAssembler::RegListNodePair& args, Node* context) {
360  return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncFunctionReject);
361 }
362 
363 Node* IntrinsicsGenerator::AsyncFunctionResolve(
364  const InterpreterAssembler::RegListNodePair& args, Node* context) {
365  return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncFunctionResolve);
366 }
367 
368 Node* IntrinsicsGenerator::AsyncGeneratorAwaitCaught(
369  const InterpreterAssembler::RegListNodePair& args, Node* context) {
370  return IntrinsicAsBuiltinCall(args, context,
371  Builtins::kAsyncGeneratorAwaitCaught);
372 }
373 
374 Node* IntrinsicsGenerator::AsyncGeneratorAwaitUncaught(
375  const InterpreterAssembler::RegListNodePair& args, Node* context) {
376  return IntrinsicAsBuiltinCall(args, context,
377  Builtins::kAsyncGeneratorAwaitUncaught);
378 }
379 
380 Node* IntrinsicsGenerator::AsyncGeneratorReject(
381  const InterpreterAssembler::RegListNodePair& args, Node* context) {
382  return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncGeneratorReject);
383 }
384 
385 Node* IntrinsicsGenerator::AsyncGeneratorResolve(
386  const InterpreterAssembler::RegListNodePair& args, Node* context) {
387  return IntrinsicAsBuiltinCall(args, context,
388  Builtins::kAsyncGeneratorResolve);
389 }
390 
391 Node* IntrinsicsGenerator::AsyncGeneratorYield(
392  const InterpreterAssembler::RegListNodePair& args, Node* context) {
393  return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncGeneratorYield);
394 }
395 
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);
401  __ Goto(&match);
402  __ BIND(&match);
403 }
404 
405 #undef __
406 
407 } // namespace interpreter
408 } // namespace internal
409 } // namespace v8
Definition: libplatform.h:13