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(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(FulfillPromise)
91 REPLACE_STUB_CALL(PerformPromiseThen)
92 REPLACE_STUB_CALL(PromiseResolve)
93 REPLACE_STUB_CALL(RejectPromise)
94 REPLACE_STUB_CALL(ResolvePromise)
95 #undef REPLACE_STUB_CALL
96 
97 void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
98                                             CallDescriptor::Flags flags) {
99   ReplaceWithStubCall(node, callable, flags, node->op()->properties());
100 }
101 
ReplaceWithStubCall(Node * node,Callable callable,CallDescriptor::Flags flags,Operator::Properties properties,int result_size)102 void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
103                                             CallDescriptor::Flags flags,
104                                             Operator::Properties properties,
105                                             int result_size) {
106   const CallInterfaceDescriptor& descriptor = callable.descriptor();
107   auto call_descriptor = Linkage::GetStubCallDescriptor(
108       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(), flags,
109       properties, MachineType::AnyTagged(), result_size);
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   Handle<AllocationSite> const site = p.site();
363   ArrayConstructorDescriptor descriptor(isolate());
364   auto call_descriptor = Linkage::GetStubCallDescriptor(
365       isolate(), zone(), descriptor, arity + 1,
366       CallDescriptor::kNeedsFrameState, node->op()->properties(),
367       MachineType::AnyTagged());
368   Node* stub_code = jsgraph()->ArrayConstructorStubConstant();
369   Node* stub_arity = jsgraph()->Int32Constant(arity);
370   Node* type_info = site.is_null() ? jsgraph()->UndefinedConstant()
371                                    : jsgraph()->HeapConstant(site);
372   Node* receiver = jsgraph()->UndefinedConstant();
373   node->InsertInput(zone(), 0, stub_code);
374   node->InsertInput(zone(), 3, stub_arity);
375   node->InsertInput(zone(), 4, type_info);
376   node->InsertInput(zone(), 5, receiver);
377   NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
378 }
379 
LowerJSCreateArrayIterator(Node * node)380 void JSGenericLowering::LowerJSCreateArrayIterator(Node* node) {
381   UNREACHABLE();  // Eliminated in typed lowering.
382 }
383 
LowerJSCreateCollectionIterator(Node * node)384 void JSGenericLowering::LowerJSCreateCollectionIterator(Node* node) {
385   UNREACHABLE();  // Eliminated in typed lowering.
386 }
387 
LowerJSCreateBoundFunction(Node * node)388 void JSGenericLowering::LowerJSCreateBoundFunction(Node* node) {
389   UNREACHABLE();  // Eliminated in typed lowering.
390 }
391 
LowerJSObjectIsArray(Node * node)392 void JSGenericLowering::LowerJSObjectIsArray(Node* node) {
393   UNREACHABLE();  // Eliminated in typed lowering.
394 }
395 
LowerJSCreateObject(Node * node)396 void JSGenericLowering::LowerJSCreateObject(Node* node) {
397   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
398   Callable callable = Builtins::CallableFor(
399       isolate(), Builtins::kCreateObjectWithoutProperties);
400   ReplaceWithStubCall(node, callable, flags);
401 }
402 
LowerJSParseInt(Node * node)403 void JSGenericLowering::LowerJSParseInt(Node* node) {
404   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
405   Callable callable = Builtins::CallableFor(isolate(), Builtins::kParseInt);
406   ReplaceWithStubCall(node, callable, flags);
407 }
408 
LowerJSCreateClosure(Node * node)409 void JSGenericLowering::LowerJSCreateClosure(Node* node) {
410   CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
411   Handle<SharedFunctionInfo> const shared_info = p.shared_info();
412   node->InsertInput(zone(), 0, jsgraph()->HeapConstant(shared_info));
413   node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.feedback_cell()));
414   node->RemoveInput(4);  // control
415 
416   // Use the FastNewClosure builtin only for functions allocated in new space.
417   if (p.pretenure() == NOT_TENURED) {
418     Callable callable =
419         Builtins::CallableFor(isolate(), Builtins::kFastNewClosure);
420     CallDescriptor::Flags flags = FrameStateFlagForCall(node);
421     ReplaceWithStubCall(node, callable, flags);
422   } else {
423     ReplaceWithRuntimeCall(node, Runtime::kNewClosure_Tenured);
424   }
425 }
426 
427 
LowerJSCreateFunctionContext(Node * node)428 void JSGenericLowering::LowerJSCreateFunctionContext(Node* node) {
429   const CreateFunctionContextParameters& parameters =
430       CreateFunctionContextParametersOf(node->op());
431   Handle<ScopeInfo> scope_info = parameters.scope_info();
432   int slot_count = parameters.slot_count();
433   ScopeType scope_type = parameters.scope_type();
434   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
435 
436   if (slot_count <= ConstructorBuiltins::MaximumFunctionContextSlots()) {
437     Callable callable =
438         CodeFactory::FastNewFunctionContext(isolate(), scope_type);
439     node->InsertInput(zone(), 0, jsgraph()->HeapConstant(scope_info));
440     node->InsertInput(zone(), 1, jsgraph()->Int32Constant(slot_count));
441     ReplaceWithStubCall(node, callable, flags);
442   } else {
443     node->InsertInput(zone(), 0, jsgraph()->HeapConstant(scope_info));
444     ReplaceWithRuntimeCall(node, Runtime::kNewFunctionContext);
445   }
446 }
447 
LowerJSCreateGeneratorObject(Node * node)448 void JSGenericLowering::LowerJSCreateGeneratorObject(Node* node) {
449   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
450   Callable callable =
451       Builtins::CallableFor(isolate(), Builtins::kCreateGeneratorObject);
452   node->RemoveInput(4);  // control
453   ReplaceWithStubCall(node, callable, flags);
454 }
455 
LowerJSCreateIterResultObject(Node * node)456 void JSGenericLowering::LowerJSCreateIterResultObject(Node* node) {
457   UNREACHABLE();  // Eliminated in typed lowering.
458 }
459 
LowerJSCreateStringIterator(Node * node)460 void JSGenericLowering::LowerJSCreateStringIterator(Node* node) {
461   UNREACHABLE();  // Eliminated in typed lowering.
462 }
463 
LowerJSCreateKeyValueArray(Node * node)464 void JSGenericLowering::LowerJSCreateKeyValueArray(Node* node) {
465   UNREACHABLE();  // Eliminated in typed lowering.
466 }
467 
LowerJSCreatePromise(Node * node)468 void JSGenericLowering::LowerJSCreatePromise(Node* node) {
469   UNREACHABLE();  // Eliminated in typed lowering.
470 }
471 
LowerJSCreateTypedArray(Node * node)472 void JSGenericLowering::LowerJSCreateTypedArray(Node* node) {
473   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
474   Callable callable =
475       Builtins::CallableFor(isolate(), Builtins::kCreateTypedArray);
476   ReplaceWithStubCall(node, callable, flags);
477 }
478 
LowerJSCreateLiteralArray(Node * node)479 void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
480   CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
481   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
482   node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector()));
483   node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.feedback().index()));
484   node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
485 
486   // Use the CreateShallowArrayLiteratlr builtin only for shallow boilerplates
487   // without properties up to the number of elements that the stubs can handle.
488   if ((p.flags() & AggregateLiteral::kIsShallow) != 0 &&
489       p.length() < ConstructorBuiltins::kMaximumClonedShallowArrayElements) {
490     Callable callable =
491         Builtins::CallableFor(isolate(), Builtins::kCreateShallowArrayLiteral);
492     ReplaceWithStubCall(node, callable, flags);
493   } else {
494     node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
495     ReplaceWithRuntimeCall(node, Runtime::kCreateArrayLiteral);
496   }
497 }
498 
LowerJSCreateEmptyLiteralArray(Node * node)499 void JSGenericLowering::LowerJSCreateEmptyLiteralArray(Node* node) {
500   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
501   FeedbackParameter const& p = FeedbackParameterOf(node->op());
502   node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector()));
503   node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.feedback().index()));
504   node->RemoveInput(4);  // control
505   Callable callable =
506       Builtins::CallableFor(isolate(), Builtins::kCreateEmptyArrayLiteral);
507   ReplaceWithStubCall(node, callable, flags);
508 }
509 
LowerJSCreateLiteralObject(Node * node)510 void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
511   CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
512   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
513   node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector()));
514   node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.feedback().index()));
515   node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
516   node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
517 
518   // Use the CreateShallowObjectLiteratal builtin only for shallow boilerplates
519   // without elements up to the number of properties that the stubs can handle.
520   if ((p.flags() & AggregateLiteral::kIsShallow) != 0 &&
521       p.length() <=
522           ConstructorBuiltins::kMaximumClonedShallowObjectProperties) {
523     Callable callable =
524         Builtins::CallableFor(isolate(), Builtins::kCreateShallowObjectLiteral);
525     ReplaceWithStubCall(node, callable, flags);
526   } else {
527     ReplaceWithRuntimeCall(node, Runtime::kCreateObjectLiteral);
528   }
529 }
530 
LowerJSCreateEmptyLiteralObject(Node * node)531 void JSGenericLowering::LowerJSCreateEmptyLiteralObject(Node* node) {
532   UNREACHABLE();  // Eliminated in typed lowering.
533 }
534 
LowerJSCreateLiteralRegExp(Node * node)535 void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
536   CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
537   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
538   Callable callable =
539       Builtins::CallableFor(isolate(), Builtins::kCreateRegExpLiteral);
540   node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector()));
541   node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.feedback().index()));
542   node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
543   node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
544   ReplaceWithStubCall(node, callable, flags);
545 }
546 
547 
LowerJSCreateCatchContext(Node * node)548 void JSGenericLowering::LowerJSCreateCatchContext(Node* node) {
549   UNREACHABLE();  // Eliminated in typed lowering.
550 }
551 
LowerJSCreateWithContext(Node * node)552 void JSGenericLowering::LowerJSCreateWithContext(Node* node) {
553   UNREACHABLE();  // Eliminated in typed lowering.
554 }
555 
LowerJSCreateBlockContext(Node * node)556 void JSGenericLowering::LowerJSCreateBlockContext(Node* node) {
557   Handle<ScopeInfo> scope_info = ScopeInfoOf(node->op());
558   node->InsertInput(zone(), 0, jsgraph()->HeapConstant(scope_info));
559   ReplaceWithRuntimeCall(node, Runtime::kPushBlockContext);
560 }
561 
LowerJSConstructForwardVarargs(Node * node)562 void JSGenericLowering::LowerJSConstructForwardVarargs(Node* node) {
563   ConstructForwardVarargsParameters p =
564       ConstructForwardVarargsParametersOf(node->op());
565   int const arg_count = static_cast<int>(p.arity() - 2);
566   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
567   Callable callable = CodeFactory::ConstructForwardVarargs(isolate());
568   auto call_descriptor = Linkage::GetStubCallDescriptor(
569       isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
570   Node* stub_code = jsgraph()->HeapConstant(callable.code());
571   Node* stub_arity = jsgraph()->Int32Constant(arg_count);
572   Node* start_index = jsgraph()->Uint32Constant(p.start_index());
573   Node* new_target = node->InputAt(arg_count + 1);
574   Node* receiver = jsgraph()->UndefinedConstant();
575   node->RemoveInput(arg_count + 1);  // Drop new target.
576   node->InsertInput(zone(), 0, stub_code);
577   node->InsertInput(zone(), 2, new_target);
578   node->InsertInput(zone(), 3, stub_arity);
579   node->InsertInput(zone(), 4, start_index);
580   node->InsertInput(zone(), 5, receiver);
581   NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
582 }
583 
LowerJSConstruct(Node * node)584 void JSGenericLowering::LowerJSConstruct(Node* node) {
585   ConstructParameters const& p = ConstructParametersOf(node->op());
586   int const arg_count = static_cast<int>(p.arity() - 2);
587   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
588   Callable callable = CodeFactory::Construct(isolate());
589   auto call_descriptor = Linkage::GetStubCallDescriptor(
590       isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
591   Node* stub_code = jsgraph()->HeapConstant(callable.code());
592   Node* stub_arity = jsgraph()->Int32Constant(arg_count);
593   Node* new_target = node->InputAt(arg_count + 1);
594   Node* receiver = jsgraph()->UndefinedConstant();
595   node->RemoveInput(arg_count + 1);  // Drop new target.
596   node->InsertInput(zone(), 0, stub_code);
597   node->InsertInput(zone(), 2, new_target);
598   node->InsertInput(zone(), 3, stub_arity);
599   node->InsertInput(zone(), 4, receiver);
600   NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
601 }
602 
LowerJSConstructWithArrayLike(Node * node)603 void JSGenericLowering::LowerJSConstructWithArrayLike(Node* node) {
604   Callable callable =
605       Builtins::CallableFor(isolate(), Builtins::kConstructWithArrayLike);
606   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
607   auto call_descriptor = Linkage::GetStubCallDescriptor(
608       isolate(), zone(), callable.descriptor(), 1, flags);
609   Node* stub_code = jsgraph()->HeapConstant(callable.code());
610   Node* receiver = jsgraph()->UndefinedConstant();
611   Node* arguments_list = node->InputAt(1);
612   Node* new_target = node->InputAt(2);
613   node->InsertInput(zone(), 0, stub_code);
614   node->ReplaceInput(2, new_target);
615   node->ReplaceInput(3, arguments_list);
616   node->InsertInput(zone(), 4, receiver);
617   NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
618 }
619 
LowerJSConstructWithSpread(Node * node)620 void JSGenericLowering::LowerJSConstructWithSpread(Node* node) {
621   ConstructParameters const& p = ConstructParametersOf(node->op());
622   int const arg_count = static_cast<int>(p.arity() - 2);
623   int const spread_index = arg_count;
624   int const new_target_index = arg_count + 1;
625   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
626   Callable callable = CodeFactory::ConstructWithSpread(isolate());
627   auto call_descriptor = Linkage::GetStubCallDescriptor(
628       isolate(), zone(), callable.descriptor(), arg_count, flags);
629   Node* stub_code = jsgraph()->HeapConstant(callable.code());
630   Node* stack_arg_count = jsgraph()->Int32Constant(arg_count - 1);
631   Node* new_target = node->InputAt(new_target_index);
632   Node* spread = node->InputAt(spread_index);
633   Node* receiver = jsgraph()->UndefinedConstant();
634   DCHECK(new_target_index > spread_index);
635   node->RemoveInput(new_target_index);  // Drop new target.
636   node->RemoveInput(spread_index);
637 
638   node->InsertInput(zone(), 0, stub_code);
639   node->InsertInput(zone(), 2, new_target);
640   node->InsertInput(zone(), 3, stack_arg_count);
641   node->InsertInput(zone(), 4, spread);
642   node->InsertInput(zone(), 5, receiver);
643   NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
644 }
645 
LowerJSCallForwardVarargs(Node * node)646 void JSGenericLowering::LowerJSCallForwardVarargs(Node* node) {
647   CallForwardVarargsParameters p = CallForwardVarargsParametersOf(node->op());
648   int const arg_count = static_cast<int>(p.arity() - 2);
649   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
650   Callable callable = CodeFactory::CallForwardVarargs(isolate());
651   auto call_descriptor = Linkage::GetStubCallDescriptor(
652       isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
653   Node* stub_code = jsgraph()->HeapConstant(callable.code());
654   Node* stub_arity = jsgraph()->Int32Constant(arg_count);
655   Node* start_index = jsgraph()->Uint32Constant(p.start_index());
656   node->InsertInput(zone(), 0, stub_code);
657   node->InsertInput(zone(), 2, stub_arity);
658   node->InsertInput(zone(), 3, start_index);
659   NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
660 }
661 
LowerJSCall(Node * node)662 void JSGenericLowering::LowerJSCall(Node* node) {
663   CallParameters const& p = CallParametersOf(node->op());
664   int const arg_count = static_cast<int>(p.arity() - 2);
665   ConvertReceiverMode const mode = p.convert_mode();
666   Callable callable = CodeFactory::Call(isolate(), mode);
667   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
668   auto call_descriptor = Linkage::GetStubCallDescriptor(
669       isolate(), 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->InsertInput(zone(), 0, stub_code);
673   node->InsertInput(zone(), 2, stub_arity);
674   NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
675 }
676 
LowerJSCallWithArrayLike(Node * node)677 void JSGenericLowering::LowerJSCallWithArrayLike(Node* node) {
678   Callable callable = CodeFactory::CallWithArrayLike(isolate());
679   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
680   auto call_descriptor = Linkage::GetStubCallDescriptor(
681       isolate(), zone(), callable.descriptor(), 1, flags);
682   Node* stub_code = jsgraph()->HeapConstant(callable.code());
683   Node* receiver = node->InputAt(1);
684   Node* arguments_list = node->InputAt(2);
685   node->InsertInput(zone(), 0, stub_code);
686   node->ReplaceInput(3, receiver);
687   node->ReplaceInput(2, arguments_list);
688   NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
689 }
690 
LowerJSCallWithSpread(Node * node)691 void JSGenericLowering::LowerJSCallWithSpread(Node* node) {
692   CallParameters const& p = CallParametersOf(node->op());
693   int const arg_count = static_cast<int>(p.arity() - 2);
694   int const spread_index = static_cast<int>(p.arity() + 1);
695   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
696   Callable callable = CodeFactory::CallWithSpread(isolate());
697   auto call_descriptor = Linkage::GetStubCallDescriptor(
698       isolate(), zone(), callable.descriptor(), arg_count, flags);
699   Node* stub_code = jsgraph()->HeapConstant(callable.code());
700   // We pass the spread in a register, not on the stack.
701   Node* stack_arg_count = jsgraph()->Int32Constant(arg_count - 1);
702   node->InsertInput(zone(), 0, stub_code);
703   node->InsertInput(zone(), 2, stack_arg_count);
704   node->InsertInput(zone(), 3, node->InputAt(spread_index));
705   node->RemoveInput(spread_index + 1);
706   NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
707 }
708 
LowerJSCallRuntime(Node * node)709 void JSGenericLowering::LowerJSCallRuntime(Node* node) {
710   const CallRuntimeParameters& p = CallRuntimeParametersOf(node->op());
711   ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity()));
712 }
713 
LowerJSForInNext(Node * node)714 void JSGenericLowering::LowerJSForInNext(Node* node) {
715   UNREACHABLE();  // Eliminated in typed lowering.
716 }
717 
LowerJSForInPrepare(Node * node)718 void JSGenericLowering::LowerJSForInPrepare(Node* node) {
719   UNREACHABLE();  // Eliminated in typed lowering.
720 }
721 
LowerJSLoadMessage(Node * node)722 void JSGenericLowering::LowerJSLoadMessage(Node* node) {
723   UNREACHABLE();  // Eliminated in typed lowering.
724 }
725 
726 
LowerJSStoreMessage(Node * node)727 void JSGenericLowering::LowerJSStoreMessage(Node* node) {
728   UNREACHABLE();  // Eliminated in typed lowering.
729 }
730 
LowerJSLoadModule(Node * node)731 void JSGenericLowering::LowerJSLoadModule(Node* node) {
732   UNREACHABLE();  // Eliminated in typed lowering.
733 }
734 
LowerJSStoreModule(Node * node)735 void JSGenericLowering::LowerJSStoreModule(Node* node) {
736   UNREACHABLE();  // Eliminated in typed lowering.
737 }
738 
LowerJSGeneratorStore(Node * node)739 void JSGenericLowering::LowerJSGeneratorStore(Node* node) {
740   UNREACHABLE();  // Eliminated in typed lowering.
741 }
742 
LowerJSGeneratorRestoreContinuation(Node * node)743 void JSGenericLowering::LowerJSGeneratorRestoreContinuation(Node* node) {
744   UNREACHABLE();  // Eliminated in typed lowering.
745 }
746 
LowerJSGeneratorRestoreContext(Node * node)747 void JSGenericLowering::LowerJSGeneratorRestoreContext(Node* node) {
748   UNREACHABLE();  // Eliminated in typed lowering.
749 }
750 
LowerJSGeneratorRestoreInputOrDebugPos(Node * node)751 void JSGenericLowering::LowerJSGeneratorRestoreInputOrDebugPos(Node* node) {
752   UNREACHABLE();  // Eliminated in typed lowering.
753 }
754 
LowerJSGeneratorRestoreRegister(Node * node)755 void JSGenericLowering::LowerJSGeneratorRestoreRegister(Node* node) {
756   UNREACHABLE();  // Eliminated in typed lowering.
757 }
758 
LowerJSStackCheck(Node * node)759 void JSGenericLowering::LowerJSStackCheck(Node* node) {
760   Node* effect = NodeProperties::GetEffectInput(node);
761   Node* control = NodeProperties::GetControlInput(node);
762 
763   Node* limit = effect = graph()->NewNode(
764       machine()->Load(MachineType::Pointer()),
765       jsgraph()->ExternalConstant(
766           ExternalReference::address_of_stack_limit(isolate())),
767       jsgraph()->IntPtrConstant(0), effect, control);
768   Node* pointer = graph()->NewNode(machine()->LoadStackPointer());
769 
770   Node* check = graph()->NewNode(machine()->UintLessThan(), limit, pointer);
771   Node* branch =
772       graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
773 
774   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
775   Node* etrue = effect;
776 
777   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
778   NodeProperties::ReplaceControlInput(node, if_false);
779   NodeProperties::ReplaceEffectInput(node, effect);
780   Node* efalse = if_false = node;
781 
782   Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
783   Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
784 
785   // Wire the new diamond into the graph, {node} can still throw.
786   NodeProperties::ReplaceUses(node, node, ephi, merge, merge);
787   NodeProperties::ReplaceControlInput(merge, if_false, 1);
788   NodeProperties::ReplaceEffectInput(ephi, efalse, 1);
789 
790   // This iteration cuts out potential {IfSuccess} or {IfException} projection
791   // uses of the original node and places them inside the diamond, so that we
792   // can change the original {node} into the slow-path runtime call.
793   for (Edge edge : merge->use_edges()) {
794     if (!NodeProperties::IsControlEdge(edge)) continue;
795     if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
796       NodeProperties::ReplaceUses(edge.from(), nullptr, nullptr, merge);
797       NodeProperties::ReplaceControlInput(merge, edge.from(), 1);
798       edge.UpdateTo(node);
799     }
800     if (edge.from()->opcode() == IrOpcode::kIfException) {
801       NodeProperties::ReplaceEffectInput(edge.from(), node);
802       edge.UpdateTo(node);
803     }
804   }
805 
806   // Turn the stack check into a runtime call.
807   ReplaceWithRuntimeCall(node, Runtime::kStackGuard);
808 }
809 
LowerJSDebugger(Node * node)810 void JSGenericLowering::LowerJSDebugger(Node* node) {
811   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
812   Callable callable = CodeFactory::HandleDebuggerStatement(isolate());
813   ReplaceWithStubCall(node, callable, flags);
814 }
815 
zone() const816 Zone* JSGenericLowering::zone() const { return graph()->zone(); }
817 
818 
isolate() const819 Isolate* JSGenericLowering::isolate() const { return jsgraph()->isolate(); }
820 
821 
graph() const822 Graph* JSGenericLowering::graph() const { return jsgraph()->graph(); }
823 
824 
common() const825 CommonOperatorBuilder* JSGenericLowering::common() const {
826   return jsgraph()->common();
827 }
828 
829 
machine() const830 MachineOperatorBuilder* JSGenericLowering::machine() const {
831   return jsgraph()->machine();
832 }
833 
834 }  // namespace compiler
835 }  // namespace internal
836 }  // namespace v8
837