V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
js-generic-lowering.cc
1 // Copyright 2014 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/compiler/js-generic-lowering.h"
6 
7 #include "src/ast/ast.h"
8 #include "src/builtins/builtins-constructor.h"
9 #include "src/code-factory.h"
10 #include "src/code-stubs.h"
11 #include "src/compiler/common-operator.h"
12 #include "src/compiler/js-graph.h"
13 #include "src/compiler/machine-operator.h"
14 #include "src/compiler/node-matchers.h"
15 #include "src/compiler/node-properties.h"
16 #include "src/compiler/operator-properties.h"
17 #include "src/feedback-vector.h"
18 #include "src/objects/scope-info.h"
19 
20 namespace v8 {
21 namespace internal {
22 namespace compiler {
23 
24 namespace {
25 
26 CallDescriptor::Flags FrameStateFlagForCall(Node* node) {
27  return OperatorProperties::HasFrameStateInput(node->op())
28  ? CallDescriptor::kNeedsFrameState
29  : CallDescriptor::kNoFlags;
30 }
31 
32 } // namespace
33 
34 JSGenericLowering::JSGenericLowering(JSGraph* jsgraph) : jsgraph_(jsgraph) {}
35 
36 JSGenericLowering::~JSGenericLowering() = default;
37 
38 
39 Reduction JSGenericLowering::Reduce(Node* node) {
40  switch (node->opcode()) {
41 #define DECLARE_CASE(x) \
42  case IrOpcode::k##x: \
43  Lower##x(node); \
44  break;
45  JS_OP_LIST(DECLARE_CASE)
46 #undef DECLARE_CASE
47  default:
48  // Nothing to see.
49  return NoChange();
50  }
51  return Changed(node);
52 }
53 
54 #define REPLACE_STUB_CALL(Name) \
55  void JSGenericLowering::LowerJS##Name(Node* node) { \
56  CallDescriptor::Flags flags = FrameStateFlagForCall(node); \
57  Callable callable = Builtins::CallableFor(isolate(), Builtins::k##Name); \
58  ReplaceWithStubCall(node, callable, flags); \
59  }
60 REPLACE_STUB_CALL(Add)
61 REPLACE_STUB_CALL(Subtract)
62 REPLACE_STUB_CALL(Multiply)
63 REPLACE_STUB_CALL(Divide)
64 REPLACE_STUB_CALL(Modulus)
65 REPLACE_STUB_CALL(Exponentiate)
66 REPLACE_STUB_CALL(BitwiseAnd)
67 REPLACE_STUB_CALL(BitwiseOr)
68 REPLACE_STUB_CALL(BitwiseXor)
69 REPLACE_STUB_CALL(ShiftLeft)
70 REPLACE_STUB_CALL(ShiftRight)
71 REPLACE_STUB_CALL(ShiftRightLogical)
72 REPLACE_STUB_CALL(LessThan)
73 REPLACE_STUB_CALL(LessThanOrEqual)
74 REPLACE_STUB_CALL(GreaterThan)
75 REPLACE_STUB_CALL(GreaterThanOrEqual)
76 REPLACE_STUB_CALL(BitwiseNot)
77 REPLACE_STUB_CALL(Decrement)
78 REPLACE_STUB_CALL(Increment)
79 REPLACE_STUB_CALL(Negate)
80 REPLACE_STUB_CALL(HasProperty)
81 REPLACE_STUB_CALL(Equal)
82 REPLACE_STUB_CALL(ToLength)
83 REPLACE_STUB_CALL(ToNumber)
84 REPLACE_STUB_CALL(ToNumberConvertBigInt)
85 REPLACE_STUB_CALL(ToNumeric)
86 REPLACE_STUB_CALL(ToName)
87 REPLACE_STUB_CALL(ToObject)
88 REPLACE_STUB_CALL(ToString)
89 REPLACE_STUB_CALL(ForInEnumerate)
90 REPLACE_STUB_CALL(AsyncFunctionEnter)
91 REPLACE_STUB_CALL(AsyncFunctionReject)
92 REPLACE_STUB_CALL(AsyncFunctionResolve)
93 REPLACE_STUB_CALL(FulfillPromise)
94 REPLACE_STUB_CALL(PerformPromiseThen)
95 REPLACE_STUB_CALL(PromiseResolve)
96 REPLACE_STUB_CALL(RejectPromise)
97 REPLACE_STUB_CALL(ResolvePromise)
98 #undef REPLACE_STUB_CALL
99 
100 void JSGenericLowering::ReplaceWithStubCall(Node* node,
101  Callable callable,
102  CallDescriptor::Flags flags) {
103  ReplaceWithStubCall(node, callable, flags, node->op()->properties());
104 }
105 
106 void JSGenericLowering::ReplaceWithStubCall(Node* node,
107  Callable callable,
108  CallDescriptor::Flags flags,
109  Operator::Properties properties) {
110  const CallInterfaceDescriptor& descriptor = callable.descriptor();
111  auto call_descriptor = Linkage::GetStubCallDescriptor(
112  zone(), descriptor, descriptor.GetStackParameterCount(), flags,
113  properties);
114  Node* stub_code = jsgraph()->HeapConstant(callable.code());
115  node->InsertInput(zone(), 0, stub_code);
116  NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
117 }
118 
119 
120 void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
121  Runtime::FunctionId f,
122  int nargs_override) {
123  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
124  Operator::Properties properties = node->op()->properties();
125  const Runtime::Function* fun = Runtime::FunctionForId(f);
126  int nargs = (nargs_override < 0) ? fun->nargs : nargs_override;
127  auto call_descriptor =
128  Linkage::GetRuntimeCallDescriptor(zone(), f, nargs, properties, flags);
129  Node* ref = jsgraph()->ExternalConstant(ExternalReference::Create(f));
130  Node* arity = jsgraph()->Int32Constant(nargs);
131  node->InsertInput(zone(), 0, jsgraph()->CEntryStubConstant(fun->result_size));
132  node->InsertInput(zone(), nargs + 1, ref);
133  node->InsertInput(zone(), nargs + 2, arity);
134  NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
135 }
136 
137 void JSGenericLowering::LowerJSStrictEqual(Node* node) {
138  // The === operator doesn't need the current context.
139  NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
140  Callable callable = Builtins::CallableFor(isolate(), Builtins::kStrictEqual);
141  node->RemoveInput(4); // control
142  ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags,
143  Operator::kEliminatable);
144 }
145 
146 void JSGenericLowering::LowerJSLoadProperty(Node* node) {
147  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
148  const PropertyAccess& p = PropertyAccessOf(node->op());
149  Node* frame_state = NodeProperties::GetFrameStateInput(node);
150  Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
151  node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
152  if (outer_state->opcode() != IrOpcode::kFrameState) {
153  Callable callable = Builtins::CallableFor(
154  isolate(), p.feedback().ic_state() == MEGAMORPHIC
155  ? Builtins::kKeyedLoadICTrampoline_Megamorphic
156  : Builtins::kKeyedLoadICTrampoline);
157  ReplaceWithStubCall(node, callable, flags);
158  } else {
159  Callable callable = Builtins::CallableFor(
160  isolate(), p.feedback().ic_state() == MEGAMORPHIC
161  ? Builtins::kKeyedLoadIC_Megamorphic
162  : Builtins::kKeyedLoadIC);
163  Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
164  node->InsertInput(zone(), 3, vector);
165  ReplaceWithStubCall(node, callable, flags);
166  }
167 }
168 
169 void JSGenericLowering::LowerJSLoadNamed(Node* node) {
170  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
171  NamedAccess const& p = NamedAccessOf(node->op());
172  Node* frame_state = NodeProperties::GetFrameStateInput(node);
173  Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
174  node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
175  if (!p.feedback().IsValid()) {
176  Callable callable =
177  Builtins::CallableFor(isolate(), Builtins::kGetProperty);
178  ReplaceWithStubCall(node, callable, flags);
179  return;
180  }
181  node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
182  if (outer_state->opcode() != IrOpcode::kFrameState) {
183  Callable callable = Builtins::CallableFor(
184  isolate(), p.feedback().ic_state() == MEGAMORPHIC
185  ? Builtins::kLoadICTrampoline_Megamorphic
186  : Builtins::kLoadICTrampoline);
187  ReplaceWithStubCall(node, callable, flags);
188  } else {
189  Callable callable =
190  Builtins::CallableFor(isolate(), p.feedback().ic_state() == MEGAMORPHIC
191  ? Builtins::kLoadIC_Megamorphic
192  : Builtins::kLoadIC);
193  Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
194  node->InsertInput(zone(), 3, vector);
195  ReplaceWithStubCall(node, callable, flags);
196  }
197 }
198 
199 void JSGenericLowering::LowerJSLoadGlobal(Node* node) {
200  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
201  const LoadGlobalParameters& p = LoadGlobalParametersOf(node->op());
202  Node* frame_state = NodeProperties::GetFrameStateInput(node);
203  Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
204  node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.name()));
205  node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.feedback().index()));
206  if (outer_state->opcode() != IrOpcode::kFrameState) {
207  Callable callable = CodeFactory::LoadGlobalIC(isolate(), p.typeof_mode());
208  ReplaceWithStubCall(node, callable, flags);
209  } else {
210  Callable callable =
211  CodeFactory::LoadGlobalICInOptimizedCode(isolate(), p.typeof_mode());
212  Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
213  node->InsertInput(zone(), 2, vector);
214  ReplaceWithStubCall(node, callable, flags);
215  }
216 }
217 
218 void JSGenericLowering::LowerJSStoreProperty(Node* node) {
219  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
220  PropertyAccess const& p = PropertyAccessOf(node->op());
221  Node* frame_state = NodeProperties::GetFrameStateInput(node);
222  Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
223  node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
224  if (outer_state->opcode() != IrOpcode::kFrameState) {
225  Callable callable =
226  Builtins::CallableFor(isolate(), Builtins::kKeyedStoreICTrampoline);
227  ReplaceWithStubCall(node, callable, flags);
228  } else {
229  Callable callable =
230  Builtins::CallableFor(isolate(), Builtins::kKeyedStoreIC);
231  Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
232  node->InsertInput(zone(), 4, vector);
233  ReplaceWithStubCall(node, callable, flags);
234  }
235 }
236 
237 void JSGenericLowering::LowerJSStoreNamed(Node* node) {
238  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
239  NamedAccess const& p = NamedAccessOf(node->op());
240  Node* frame_state = NodeProperties::GetFrameStateInput(node);
241  Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
242  node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
243  if (!p.feedback().IsValid()) {
244  node->InsertInput(
245  zone(), 3, jsgraph()->SmiConstant(static_cast<int>(p.language_mode())));
246  ReplaceWithRuntimeCall(node, Runtime::kSetNamedProperty);
247  return;
248  }
249  node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
250  if (outer_state->opcode() != IrOpcode::kFrameState) {
251  Callable callable =
252  Builtins::CallableFor(isolate(), Builtins::kStoreICTrampoline);
253  ReplaceWithStubCall(node, callable, flags);
254  } else {
255  Callable callable = Builtins::CallableFor(isolate(), Builtins::kStoreIC);
256  Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
257  node->InsertInput(zone(), 4, vector);
258  ReplaceWithStubCall(node, callable, flags);
259  }
260 }
261 
262 void JSGenericLowering::LowerJSStoreNamedOwn(Node* node) {
263  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
264  StoreNamedOwnParameters const& p = StoreNamedOwnParametersOf(node->op());
265  Node* frame_state = NodeProperties::GetFrameStateInput(node);
266  Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
267  node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
268  node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
269  if (outer_state->opcode() != IrOpcode::kFrameState) {
270  Callable callable = CodeFactory::StoreOwnIC(isolate());
271  ReplaceWithStubCall(node, callable, flags);
272  } else {
273  Callable callable = CodeFactory::StoreOwnICInOptimizedCode(isolate());
274  Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
275  node->InsertInput(zone(), 4, vector);
276  ReplaceWithStubCall(node, callable, flags);
277  }
278 }
279 
280 void JSGenericLowering::LowerJSStoreGlobal(Node* node) {
281  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
282  const StoreGlobalParameters& p = StoreGlobalParametersOf(node->op());
283  Node* frame_state = NodeProperties::GetFrameStateInput(node);
284  Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
285  node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.name()));
286  node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
287  if (outer_state->opcode() != IrOpcode::kFrameState) {
288  Callable callable =
289  Builtins::CallableFor(isolate(), Builtins::kStoreGlobalICTrampoline);
290  ReplaceWithStubCall(node, callable, flags);
291  } else {
292  Callable callable =
293  Builtins::CallableFor(isolate(), Builtins::kStoreGlobalIC);
294  Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
295  node->InsertInput(zone(), 3, vector);
296  ReplaceWithStubCall(node, callable, flags);
297  }
298 }
299 
300 void JSGenericLowering::LowerJSStoreDataPropertyInLiteral(Node* node) {
301  FeedbackParameter const& p = FeedbackParameterOf(node->op());
302  node->InsertInputs(zone(), 4, 2);
303  node->ReplaceInput(4, jsgraph()->HeapConstant(p.feedback().vector()));
304  node->ReplaceInput(5, jsgraph()->SmiConstant(p.feedback().index()));
305  ReplaceWithRuntimeCall(node, Runtime::kDefineDataPropertyInLiteral);
306 }
307 
308 void JSGenericLowering::LowerJSStoreInArrayLiteral(Node* node) {
309  Callable callable =
310  Builtins::CallableFor(isolate(), Builtins::kStoreInArrayLiteralIC);
311  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
312  FeedbackParameter const& p = FeedbackParameterOf(node->op());
313  node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
314  node->InsertInput(zone(), 4, jsgraph()->HeapConstant(p.feedback().vector()));
315  ReplaceWithStubCall(node, callable, flags);
316 }
317 
318 void JSGenericLowering::LowerJSDeleteProperty(Node* node) {
319  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
320  Callable callable =
321  Builtins::CallableFor(isolate(), Builtins::kDeleteProperty);
322  ReplaceWithStubCall(node, callable, flags);
323 }
324 
325 void JSGenericLowering::LowerJSGetSuperConstructor(Node* node) {
326  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
327  Callable callable =
328  Builtins::CallableFor(isolate(), Builtins::kGetSuperConstructor);
329  ReplaceWithStubCall(node, callable, flags);
330 }
331 
332 void JSGenericLowering::LowerJSHasInPrototypeChain(Node* node) {
333  ReplaceWithRuntimeCall(node, Runtime::kHasInPrototypeChain);
334 }
335 
336 void JSGenericLowering::LowerJSInstanceOf(Node* node) {
337  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
338  Callable callable = Builtins::CallableFor(isolate(), Builtins::kInstanceOf);
339  ReplaceWithStubCall(node, callable, flags);
340 }
341 
342 void JSGenericLowering::LowerJSOrdinaryHasInstance(Node* node) {
343  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
344  Callable callable =
345  Builtins::CallableFor(isolate(), Builtins::kOrdinaryHasInstance);
346  ReplaceWithStubCall(node, callable, flags);
347 }
348 
349 void JSGenericLowering::LowerJSLoadContext(Node* node) {
350  UNREACHABLE(); // Eliminated in typed lowering.
351 }
352 
353 
354 void JSGenericLowering::LowerJSStoreContext(Node* node) {
355  UNREACHABLE(); // Eliminated in typed lowering.
356 }
357 
358 
359 void JSGenericLowering::LowerJSCreate(Node* node) {
360  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
361  Callable callable =
362  Builtins::CallableFor(isolate(), Builtins::kFastNewObject);
363  ReplaceWithStubCall(node, callable, flags);
364 }
365 
366 
367 void JSGenericLowering::LowerJSCreateArguments(Node* node) {
368  CreateArgumentsType const type = CreateArgumentsTypeOf(node->op());
369  switch (type) {
370  case CreateArgumentsType::kMappedArguments:
371  ReplaceWithRuntimeCall(node, Runtime::kNewSloppyArguments_Generic);
372  break;
373  case CreateArgumentsType::kUnmappedArguments:
374  ReplaceWithRuntimeCall(node, Runtime::kNewStrictArguments);
375  break;
376  case CreateArgumentsType::kRestParameter:
377  ReplaceWithRuntimeCall(node, Runtime::kNewRestParameter);
378  break;
379  }
380 }
381 
382 
383 void JSGenericLowering::LowerJSCreateArray(Node* node) {
384  CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
385  int const arity = static_cast<int>(p.arity());
386  auto call_descriptor = Linkage::GetStubCallDescriptor(
387  zone(), ArrayConstructorDescriptor{}, arity + 1,
388  CallDescriptor::kNeedsFrameState, node->op()->properties());
389  Node* stub_code = jsgraph()->ArrayConstructorStubConstant();
390  Node* stub_arity = jsgraph()->Int32Constant(arity);
391  MaybeHandle<AllocationSite> const maybe_site = p.site();
392  Handle<AllocationSite> site;
393  Node* type_info = maybe_site.ToHandle(&site) ? jsgraph()->HeapConstant(site)
394  : jsgraph()->UndefinedConstant();
395  Node* receiver = jsgraph()->UndefinedConstant();
396  node->InsertInput(zone(), 0, stub_code);
397  node->InsertInput(zone(), 3, stub_arity);
398  node->InsertInput(zone(), 4, type_info);
399  node->InsertInput(zone(), 5, receiver);
400  NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
401 }
402 
403 void JSGenericLowering::LowerJSCreateArrayIterator(Node* node) {
404  UNREACHABLE(); // Eliminated in typed lowering.
405 }
406 
407 void JSGenericLowering::LowerJSCreateAsyncFunctionObject(Node* node) {
408  UNREACHABLE(); // Eliminated in typed lowering.
409 }
410 
411 void JSGenericLowering::LowerJSCreateCollectionIterator(Node* node) {
412  UNREACHABLE(); // Eliminated in typed lowering.
413 }
414 
415 void JSGenericLowering::LowerJSCreateBoundFunction(Node* node) {
416  UNREACHABLE(); // Eliminated in typed lowering.
417 }
418 
419 void JSGenericLowering::LowerJSObjectIsArray(Node* node) {
420  UNREACHABLE(); // Eliminated in typed lowering.
421 }
422 
423 void JSGenericLowering::LowerJSCreateObject(Node* node) {
424  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
425  Callable callable = Builtins::CallableFor(
426  isolate(), Builtins::kCreateObjectWithoutProperties);
427  ReplaceWithStubCall(node, callable, flags);
428 }
429 
430 void JSGenericLowering::LowerJSParseInt(Node* node) {
431  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
432  Callable callable = Builtins::CallableFor(isolate(), Builtins::kParseInt);
433  ReplaceWithStubCall(node, callable, flags);
434 }
435 
436 void JSGenericLowering::LowerJSRegExpTest(Node* node) {
437  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
438  Callable callable =
439  Builtins::CallableFor(isolate(), Builtins::kRegExpPrototypeTestFast);
440  ReplaceWithStubCall(node, callable, flags);
441 }
442 
443 void JSGenericLowering::LowerJSCreateClosure(Node* node) {
444  CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
445  Handle<SharedFunctionInfo> const shared_info = p.shared_info();
446  node->InsertInput(zone(), 0, jsgraph()->HeapConstant(shared_info));
447  node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.feedback_cell()));
448  node->RemoveInput(4); // control
449 
450  // Use the FastNewClosure builtin only for functions allocated in new space.
451  if (p.pretenure() == NOT_TENURED) {
452  Callable callable =
453  Builtins::CallableFor(isolate(), Builtins::kFastNewClosure);
454  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
455  ReplaceWithStubCall(node, callable, flags);
456  } else {
457  ReplaceWithRuntimeCall(node, Runtime::kNewClosure_Tenured);
458  }
459 }
460 
461 
462 void JSGenericLowering::LowerJSCreateFunctionContext(Node* node) {
463  const CreateFunctionContextParameters& parameters =
464  CreateFunctionContextParametersOf(node->op());
465  Handle<ScopeInfo> scope_info = parameters.scope_info();
466  int slot_count = parameters.slot_count();
467  ScopeType scope_type = parameters.scope_type();
468  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
469 
470  if (slot_count <= ConstructorBuiltins::MaximumFunctionContextSlots()) {
471  Callable callable =
472  CodeFactory::FastNewFunctionContext(isolate(), scope_type);
473  node->InsertInput(zone(), 0, jsgraph()->HeapConstant(scope_info));
474  node->InsertInput(zone(), 1, jsgraph()->Int32Constant(slot_count));
475  ReplaceWithStubCall(node, callable, flags);
476  } else {
477  node->InsertInput(zone(), 0, jsgraph()->HeapConstant(scope_info));
478  ReplaceWithRuntimeCall(node, Runtime::kNewFunctionContext);
479  }
480 }
481 
482 void JSGenericLowering::LowerJSCreateGeneratorObject(Node* node) {
483  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
484  Callable callable =
485  Builtins::CallableFor(isolate(), Builtins::kCreateGeneratorObject);
486  node->RemoveInput(4); // control
487  ReplaceWithStubCall(node, callable, flags);
488 }
489 
490 void JSGenericLowering::LowerJSCreateIterResultObject(Node* node) {
491  UNREACHABLE(); // Eliminated in typed lowering.
492 }
493 
494 void JSGenericLowering::LowerJSCreateStringIterator(Node* node) {
495  UNREACHABLE(); // Eliminated in typed lowering.
496 }
497 
498 void JSGenericLowering::LowerJSCreateKeyValueArray(Node* node) {
499  UNREACHABLE(); // Eliminated in typed lowering.
500 }
501 
502 void JSGenericLowering::LowerJSCreatePromise(Node* node) {
503  UNREACHABLE(); // Eliminated in typed lowering.
504 }
505 
506 void JSGenericLowering::LowerJSCreateTypedArray(Node* node) {
507  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
508  Callable callable =
509  Builtins::CallableFor(isolate(), Builtins::kCreateTypedArray);
510  ReplaceWithStubCall(node, callable, flags);
511 }
512 
513 void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
514  CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
515  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
516  node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector()));
517  node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.feedback().index()));
518  node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
519 
520  // Use the CreateShallowArrayLiteratlr builtin only for shallow boilerplates
521  // without properties up to the number of elements that the stubs can handle.
522  if ((p.flags() & AggregateLiteral::kIsShallow) != 0 &&
523  p.length() < ConstructorBuiltins::kMaximumClonedShallowArrayElements) {
524  Callable callable =
525  Builtins::CallableFor(isolate(), Builtins::kCreateShallowArrayLiteral);
526  ReplaceWithStubCall(node, callable, flags);
527  } else {
528  node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
529  ReplaceWithRuntimeCall(node, Runtime::kCreateArrayLiteral);
530  }
531 }
532 
533 void JSGenericLowering::LowerJSCreateEmptyLiteralArray(Node* node) {
534  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
535  FeedbackParameter const& p = FeedbackParameterOf(node->op());
536  node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector()));
537  node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.feedback().index()));
538  node->RemoveInput(4); // control
539  Callable callable =
540  Builtins::CallableFor(isolate(), Builtins::kCreateEmptyArrayLiteral);
541  ReplaceWithStubCall(node, callable, flags);
542 }
543 
544 void JSGenericLowering::LowerJSCreateArrayFromIterable(Node* node) {
545  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
546  Callable callable = Builtins::CallableFor(
547  isolate(), Builtins::kIterableToListWithSymbolLookup);
548  ReplaceWithStubCall(node, callable, flags);
549 }
550 
551 void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
552  CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
553  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
554  node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector()));
555  node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.feedback().index()));
556  node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
557  node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
558 
559  // Use the CreateShallowObjectLiteratal builtin only for shallow boilerplates
560  // without elements up to the number of properties that the stubs can handle.
561  if ((p.flags() & AggregateLiteral::kIsShallow) != 0 &&
562  p.length() <=
563  ConstructorBuiltins::kMaximumClonedShallowObjectProperties) {
564  Callable callable =
565  Builtins::CallableFor(isolate(), Builtins::kCreateShallowObjectLiteral);
566  ReplaceWithStubCall(node, callable, flags);
567  } else {
568  ReplaceWithRuntimeCall(node, Runtime::kCreateObjectLiteral);
569  }
570 }
571 
572 void JSGenericLowering::LowerJSCloneObject(Node* node) {
573  CloneObjectParameters const& p = CloneObjectParametersOf(node->op());
574  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
575  Callable callable =
576  Builtins::CallableFor(isolate(), Builtins::kCloneObjectIC);
577  node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.flags()));
578  node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
579  node->InsertInput(zone(), 3, jsgraph()->HeapConstant(p.feedback().vector()));
580  ReplaceWithStubCall(node, callable, flags);
581 }
582 
583 void JSGenericLowering::LowerJSCreateEmptyLiteralObject(Node* node) {
584  UNREACHABLE(); // Eliminated in typed lowering.
585 }
586 
587 void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
588  CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
589  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
590  Callable callable =
591  Builtins::CallableFor(isolate(), Builtins::kCreateRegExpLiteral);
592  node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector()));
593  node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.feedback().index()));
594  node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
595  node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
596  ReplaceWithStubCall(node, callable, flags);
597 }
598 
599 
600 void JSGenericLowering::LowerJSCreateCatchContext(Node* node) {
601  UNREACHABLE(); // Eliminated in typed lowering.
602 }
603 
604 void JSGenericLowering::LowerJSCreateWithContext(Node* node) {
605  UNREACHABLE(); // Eliminated in typed lowering.
606 }
607 
608 void JSGenericLowering::LowerJSCreateBlockContext(Node* node) {
609  Handle<ScopeInfo> scope_info = ScopeInfoOf(node->op());
610  node->InsertInput(zone(), 0, jsgraph()->HeapConstant(scope_info));
611  ReplaceWithRuntimeCall(node, Runtime::kPushBlockContext);
612 }
613 
614 void JSGenericLowering::LowerJSConstructForwardVarargs(Node* node) {
615  ConstructForwardVarargsParameters p =
616  ConstructForwardVarargsParametersOf(node->op());
617  int const arg_count = static_cast<int>(p.arity() - 2);
618  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
619  Callable callable = CodeFactory::ConstructForwardVarargs(isolate());
620  auto call_descriptor = Linkage::GetStubCallDescriptor(
621  zone(), callable.descriptor(), arg_count + 1, flags);
622  Node* stub_code = jsgraph()->HeapConstant(callable.code());
623  Node* stub_arity = jsgraph()->Int32Constant(arg_count);
624  Node* start_index = jsgraph()->Uint32Constant(p.start_index());
625  Node* new_target = node->InputAt(arg_count + 1);
626  Node* receiver = jsgraph()->UndefinedConstant();
627  node->RemoveInput(arg_count + 1); // Drop new target.
628  node->InsertInput(zone(), 0, stub_code);
629  node->InsertInput(zone(), 2, new_target);
630  node->InsertInput(zone(), 3, stub_arity);
631  node->InsertInput(zone(), 4, start_index);
632  node->InsertInput(zone(), 5, receiver);
633  NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
634 }
635 
636 void JSGenericLowering::LowerJSConstruct(Node* node) {
637  ConstructParameters const& p = ConstructParametersOf(node->op());
638  int const arg_count = static_cast<int>(p.arity() - 2);
639  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
640  Callable callable = CodeFactory::Construct(isolate());
641  auto call_descriptor = Linkage::GetStubCallDescriptor(
642  zone(), callable.descriptor(), arg_count + 1, flags);
643  Node* stub_code = jsgraph()->HeapConstant(callable.code());
644  Node* stub_arity = jsgraph()->Int32Constant(arg_count);
645  Node* new_target = node->InputAt(arg_count + 1);
646  Node* receiver = jsgraph()->UndefinedConstant();
647  node->RemoveInput(arg_count + 1); // Drop new target.
648  node->InsertInput(zone(), 0, stub_code);
649  node->InsertInput(zone(), 2, new_target);
650  node->InsertInput(zone(), 3, stub_arity);
651  node->InsertInput(zone(), 4, receiver);
652  NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
653 }
654 
655 void JSGenericLowering::LowerJSConstructWithArrayLike(Node* node) {
656  Callable callable =
657  Builtins::CallableFor(isolate(), Builtins::kConstructWithArrayLike);
658  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
659  auto call_descriptor =
660  Linkage::GetStubCallDescriptor(zone(), callable.descriptor(), 1, flags);
661  Node* stub_code = jsgraph()->HeapConstant(callable.code());
662  Node* receiver = jsgraph()->UndefinedConstant();
663  Node* arguments_list = node->InputAt(1);
664  Node* new_target = node->InputAt(2);
665  node->InsertInput(zone(), 0, stub_code);
666  node->ReplaceInput(2, new_target);
667  node->ReplaceInput(3, arguments_list);
668  node->InsertInput(zone(), 4, receiver);
669  NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
670 }
671 
672 void JSGenericLowering::LowerJSConstructWithSpread(Node* node) {
673  ConstructParameters const& p = ConstructParametersOf(node->op());
674  int const arg_count = static_cast<int>(p.arity() - 2);
675  int const spread_index = arg_count;
676  int const new_target_index = arg_count + 1;
677  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
678  Callable callable = CodeFactory::ConstructWithSpread(isolate());
679  auto call_descriptor = Linkage::GetStubCallDescriptor(
680  zone(), callable.descriptor(), arg_count, flags);
681  Node* stub_code = jsgraph()->HeapConstant(callable.code());
682  Node* stack_arg_count = jsgraph()->Int32Constant(arg_count - 1);
683  Node* new_target = node->InputAt(new_target_index);
684  Node* spread = node->InputAt(spread_index);
685  Node* receiver = jsgraph()->UndefinedConstant();
686  DCHECK(new_target_index > spread_index);
687  node->RemoveInput(new_target_index); // Drop new target.
688  node->RemoveInput(spread_index);
689 
690  node->InsertInput(zone(), 0, stub_code);
691  node->InsertInput(zone(), 2, new_target);
692  node->InsertInput(zone(), 3, stack_arg_count);
693  node->InsertInput(zone(), 4, spread);
694  node->InsertInput(zone(), 5, receiver);
695  NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
696 }
697 
698 void JSGenericLowering::LowerJSCallForwardVarargs(Node* node) {
699  CallForwardVarargsParameters p = CallForwardVarargsParametersOf(node->op());
700  int const arg_count = static_cast<int>(p.arity() - 2);
701  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
702  Callable callable = CodeFactory::CallForwardVarargs(isolate());
703  auto call_descriptor = Linkage::GetStubCallDescriptor(
704  zone(), callable.descriptor(), arg_count + 1, flags);
705  Node* stub_code = jsgraph()->HeapConstant(callable.code());
706  Node* stub_arity = jsgraph()->Int32Constant(arg_count);
707  Node* start_index = jsgraph()->Uint32Constant(p.start_index());
708  node->InsertInput(zone(), 0, stub_code);
709  node->InsertInput(zone(), 2, stub_arity);
710  node->InsertInput(zone(), 3, start_index);
711  NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
712 }
713 
714 void JSGenericLowering::LowerJSCall(Node* node) {
715  CallParameters const& p = CallParametersOf(node->op());
716  int const arg_count = static_cast<int>(p.arity() - 2);
717  ConvertReceiverMode const mode = p.convert_mode();
718  Callable callable = CodeFactory::Call(isolate(), mode);
719  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
720  auto call_descriptor = Linkage::GetStubCallDescriptor(
721  zone(), callable.descriptor(), arg_count + 1, flags);
722  Node* stub_code = jsgraph()->HeapConstant(callable.code());
723  Node* stub_arity = jsgraph()->Int32Constant(arg_count);
724  node->InsertInput(zone(), 0, stub_code);
725  node->InsertInput(zone(), 2, stub_arity);
726  NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
727 }
728 
729 void JSGenericLowering::LowerJSCallWithArrayLike(Node* node) {
730  Callable callable = CodeFactory::CallWithArrayLike(isolate());
731  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
732  auto call_descriptor =
733  Linkage::GetStubCallDescriptor(zone(), callable.descriptor(), 1, flags);
734  Node* stub_code = jsgraph()->HeapConstant(callable.code());
735  Node* receiver = node->InputAt(1);
736  Node* arguments_list = node->InputAt(2);
737  node->InsertInput(zone(), 0, stub_code);
738  node->ReplaceInput(3, receiver);
739  node->ReplaceInput(2, arguments_list);
740  NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
741 }
742 
743 void JSGenericLowering::LowerJSCallWithSpread(Node* node) {
744  CallParameters const& p = CallParametersOf(node->op());
745  int const arg_count = static_cast<int>(p.arity() - 2);
746  int const spread_index = static_cast<int>(p.arity() + 1);
747  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
748  Callable callable = CodeFactory::CallWithSpread(isolate());
749  auto call_descriptor = Linkage::GetStubCallDescriptor(
750  zone(), callable.descriptor(), arg_count, flags);
751  Node* stub_code = jsgraph()->HeapConstant(callable.code());
752  // We pass the spread in a register, not on the stack.
753  Node* stack_arg_count = jsgraph()->Int32Constant(arg_count - 1);
754  node->InsertInput(zone(), 0, stub_code);
755  node->InsertInput(zone(), 2, stack_arg_count);
756  node->InsertInput(zone(), 3, node->InputAt(spread_index));
757  node->RemoveInput(spread_index + 1);
758  NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
759 }
760 
761 void JSGenericLowering::LowerJSCallRuntime(Node* node) {
762  const CallRuntimeParameters& p = CallRuntimeParametersOf(node->op());
763  ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity()));
764 }
765 
766 void JSGenericLowering::LowerJSForInNext(Node* node) {
767  UNREACHABLE(); // Eliminated in typed lowering.
768 }
769 
770 void JSGenericLowering::LowerJSForInPrepare(Node* node) {
771  UNREACHABLE(); // Eliminated in typed lowering.
772 }
773 
774 void JSGenericLowering::LowerJSLoadMessage(Node* node) {
775  UNREACHABLE(); // Eliminated in typed lowering.
776 }
777 
778 
779 void JSGenericLowering::LowerJSStoreMessage(Node* node) {
780  UNREACHABLE(); // Eliminated in typed lowering.
781 }
782 
783 void JSGenericLowering::LowerJSLoadModule(Node* node) {
784  UNREACHABLE(); // Eliminated in typed lowering.
785 }
786 
787 void JSGenericLowering::LowerJSStoreModule(Node* node) {
788  UNREACHABLE(); // Eliminated in typed lowering.
789 }
790 
791 void JSGenericLowering::LowerJSGeneratorStore(Node* node) {
792  UNREACHABLE(); // Eliminated in typed lowering.
793 }
794 
795 void JSGenericLowering::LowerJSGeneratorRestoreContinuation(Node* node) {
796  UNREACHABLE(); // Eliminated in typed lowering.
797 }
798 
799 void JSGenericLowering::LowerJSGeneratorRestoreContext(Node* node) {
800  UNREACHABLE(); // Eliminated in typed lowering.
801 }
802 
803 void JSGenericLowering::LowerJSGeneratorRestoreInputOrDebugPos(Node* node) {
804  UNREACHABLE(); // Eliminated in typed lowering.
805 }
806 
807 void JSGenericLowering::LowerJSGeneratorRestoreRegister(Node* node) {
808  UNREACHABLE(); // Eliminated in typed lowering.
809 }
810 
811 void JSGenericLowering::LowerJSStackCheck(Node* node) {
812  Node* effect = NodeProperties::GetEffectInput(node);
813  Node* control = NodeProperties::GetControlInput(node);
814 
815  Node* limit = effect = graph()->NewNode(
816  machine()->Load(MachineType::Pointer()),
817  jsgraph()->ExternalConstant(
818  ExternalReference::address_of_stack_limit(isolate())),
819  jsgraph()->IntPtrConstant(0), effect, control);
820  Node* pointer = graph()->NewNode(machine()->LoadStackPointer());
821 
822  Node* check = graph()->NewNode(machine()->UintLessThan(), limit, pointer);
823  Node* branch =
824  graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
825 
826  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
827  Node* etrue = effect;
828 
829  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
830  NodeProperties::ReplaceControlInput(node, if_false);
831  NodeProperties::ReplaceEffectInput(node, effect);
832  Node* efalse = if_false = node;
833 
834  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
835  Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
836 
837  // Wire the new diamond into the graph, {node} can still throw.
838  NodeProperties::ReplaceUses(node, node, ephi, merge, merge);
839  NodeProperties::ReplaceControlInput(merge, if_false, 1);
840  NodeProperties::ReplaceEffectInput(ephi, efalse, 1);
841 
842  // This iteration cuts out potential {IfSuccess} or {IfException} projection
843  // uses of the original node and places them inside the diamond, so that we
844  // can change the original {node} into the slow-path runtime call.
845  for (Edge edge : merge->use_edges()) {
846  if (!NodeProperties::IsControlEdge(edge)) continue;
847  if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
848  NodeProperties::ReplaceUses(edge.from(), nullptr, nullptr, merge);
849  NodeProperties::ReplaceControlInput(merge, edge.from(), 1);
850  edge.UpdateTo(node);
851  }
852  if (edge.from()->opcode() == IrOpcode::kIfException) {
853  NodeProperties::ReplaceEffectInput(edge.from(), node);
854  edge.UpdateTo(node);
855  }
856  }
857 
858  // Turn the stack check into a runtime call.
859  ReplaceWithRuntimeCall(node, Runtime::kStackGuard);
860 }
861 
862 void JSGenericLowering::LowerJSDebugger(Node* node) {
863  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
864  Callable callable = CodeFactory::HandleDebuggerStatement(isolate());
865  ReplaceWithStubCall(node, callable, flags);
866 }
867 
868 Zone* JSGenericLowering::zone() const { return graph()->zone(); }
869 
870 
871 Isolate* JSGenericLowering::isolate() const { return jsgraph()->isolate(); }
872 
873 
874 Graph* JSGenericLowering::graph() const { return jsgraph()->graph(); }
875 
876 
877 CommonOperatorBuilder* JSGenericLowering::common() const {
878  return jsgraph()->common();
879 }
880 
881 
882 MachineOperatorBuilder* JSGenericLowering::machine() const {
883  return jsgraph()->machine();
884 }
885 
886 } // namespace compiler
887 } // namespace internal
888 } // namespace v8
Definition: libplatform.h:13