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