• 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/objects-inl.h"
18 
19 namespace v8 {
20 namespace internal {
21 namespace compiler {
22 
23 namespace {
24 
FrameStateFlagForCall(Node * node)25 CallDescriptor::Flags FrameStateFlagForCall(Node* node) {
26   return OperatorProperties::HasFrameStateInput(node->op())
27              ? CallDescriptor::kNeedsFrameState
28              : CallDescriptor::kNoFlags;
29 }
30 
31 }  // namespace
32 
JSGenericLowering(JSGraph * jsgraph)33 JSGenericLowering::JSGenericLowering(JSGraph* jsgraph) : jsgraph_(jsgraph) {}
34 
~JSGenericLowering()35 JSGenericLowering::~JSGenericLowering() {}
36 
37 
Reduce(Node * node)38 Reduction JSGenericLowering::Reduce(Node* node) {
39   switch (node->opcode()) {
40 #define DECLARE_CASE(x)  \
41     case IrOpcode::k##x: \
42       Lower##x(node);    \
43       break;
44     JS_OP_LIST(DECLARE_CASE)
45 #undef DECLARE_CASE
46     default:
47       // Nothing to see.
48       return NoChange();
49   }
50   return Changed(node);
51 }
52 
53 #define REPLACE_STUB_CALL(Name)                                \
54   void JSGenericLowering::LowerJS##Name(Node* node) {          \
55     CallDescriptor::Flags flags = FrameStateFlagForCall(node); \
56     Callable callable = CodeFactory::Name(isolate());          \
57     ReplaceWithStubCall(node, callable, flags);                \
58   }
59 REPLACE_STUB_CALL(Add)
REPLACE_STUB_CALL(Subtract)60 REPLACE_STUB_CALL(Subtract)
61 REPLACE_STUB_CALL(Multiply)
62 REPLACE_STUB_CALL(Divide)
63 REPLACE_STUB_CALL(Modulus)
64 REPLACE_STUB_CALL(BitwiseAnd)
65 REPLACE_STUB_CALL(BitwiseOr)
66 REPLACE_STUB_CALL(BitwiseXor)
67 REPLACE_STUB_CALL(ShiftLeft)
68 REPLACE_STUB_CALL(ShiftRight)
69 REPLACE_STUB_CALL(ShiftRightLogical)
70 REPLACE_STUB_CALL(LessThan)
71 REPLACE_STUB_CALL(LessThanOrEqual)
72 REPLACE_STUB_CALL(GreaterThan)
73 REPLACE_STUB_CALL(GreaterThanOrEqual)
74 REPLACE_STUB_CALL(HasProperty)
75 REPLACE_STUB_CALL(Equal)
76 REPLACE_STUB_CALL(NotEqual)
77 REPLACE_STUB_CALL(ToInteger)
78 REPLACE_STUB_CALL(ToLength)
79 REPLACE_STUB_CALL(ToNumber)
80 REPLACE_STUB_CALL(ToName)
81 REPLACE_STUB_CALL(ToObject)
82 REPLACE_STUB_CALL(ToString)
83 #undef REPLACE_STUB_CALL
84 
85 void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
86                                             CallDescriptor::Flags flags) {
87   ReplaceWithStubCall(node, callable, flags, node->op()->properties());
88 }
89 
ReplaceWithStubCall(Node * node,Callable callable,CallDescriptor::Flags flags,Operator::Properties properties,int result_size)90 void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
91                                             CallDescriptor::Flags flags,
92                                             Operator::Properties properties,
93                                             int result_size) {
94   const CallInterfaceDescriptor& descriptor = callable.descriptor();
95   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
96       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(), flags,
97       properties, MachineType::AnyTagged(), result_size);
98   Node* stub_code = jsgraph()->HeapConstant(callable.code());
99   node->InsertInput(zone(), 0, stub_code);
100   NodeProperties::ChangeOp(node, common()->Call(desc));
101 }
102 
103 
ReplaceWithRuntimeCall(Node * node,Runtime::FunctionId f,int nargs_override)104 void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
105                                                Runtime::FunctionId f,
106                                                int nargs_override) {
107   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
108   Operator::Properties properties = node->op()->properties();
109   const Runtime::Function* fun = Runtime::FunctionForId(f);
110   int nargs = (nargs_override < 0) ? fun->nargs : nargs_override;
111   CallDescriptor* desc =
112       Linkage::GetRuntimeCallDescriptor(zone(), f, nargs, properties, flags);
113   Node* ref = jsgraph()->ExternalConstant(ExternalReference(f, isolate()));
114   Node* arity = jsgraph()->Int32Constant(nargs);
115   node->InsertInput(zone(), 0, jsgraph()->CEntryStubConstant(fun->result_size));
116   node->InsertInput(zone(), nargs + 1, ref);
117   node->InsertInput(zone(), nargs + 2, arity);
118   NodeProperties::ChangeOp(node, common()->Call(desc));
119 }
120 
LowerJSStrictEqual(Node * node)121 void JSGenericLowering::LowerJSStrictEqual(Node* node) {
122   // The === operator doesn't need the current context.
123   NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
124   Callable callable = CodeFactory::StrictEqual(isolate());
125   node->RemoveInput(4);  // control
126   ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags,
127                       Operator::kEliminatable);
128 }
129 
LowerJSStrictNotEqual(Node * node)130 void JSGenericLowering::LowerJSStrictNotEqual(Node* node) {
131   // The !== operator doesn't need the current context.
132   NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
133   Callable callable = CodeFactory::StrictNotEqual(isolate());
134   node->RemoveInput(4);  // control
135   ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags,
136                       Operator::kEliminatable);
137 }
138 
LowerJSToBoolean(Node * node)139 void JSGenericLowering::LowerJSToBoolean(Node* node) {
140   // The ToBoolean conversion doesn't need the current context.
141   NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
142   Callable callable = CodeFactory::ToBoolean(isolate());
143   node->AppendInput(zone(), graph()->start());
144   ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
145                       Operator::kEliminatable);
146 }
147 
LowerJSClassOf(Node * node)148 void JSGenericLowering::LowerJSClassOf(Node* node) {
149   // The %_ClassOf intrinsic doesn't need the current context.
150   NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
151   Callable callable = CodeFactory::ClassOf(isolate());
152   node->AppendInput(zone(), graph()->start());
153   ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
154                       Operator::kEliminatable);
155 }
156 
LowerJSTypeOf(Node * node)157 void JSGenericLowering::LowerJSTypeOf(Node* node) {
158   // The typeof operator doesn't need the current context.
159   NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
160   Callable callable = CodeFactory::Typeof(isolate());
161   node->AppendInput(zone(), graph()->start());
162   ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
163                       Operator::kEliminatable);
164 }
165 
166 
LowerJSLoadProperty(Node * node)167 void JSGenericLowering::LowerJSLoadProperty(Node* node) {
168   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
169   const PropertyAccess& p = PropertyAccessOf(node->op());
170   Callable callable = CodeFactory::KeyedLoadICInOptimizedCode(isolate());
171   Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
172   node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
173   node->InsertInput(zone(), 3, vector);
174   ReplaceWithStubCall(node, callable, flags);
175 }
176 
177 
LowerJSLoadNamed(Node * node)178 void JSGenericLowering::LowerJSLoadNamed(Node* node) {
179   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
180   NamedAccess const& p = NamedAccessOf(node->op());
181   Callable callable = CodeFactory::LoadICInOptimizedCode(isolate());
182   Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
183   node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
184   node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
185   node->InsertInput(zone(), 3, vector);
186   ReplaceWithStubCall(node, callable, flags);
187 }
188 
189 
LowerJSLoadGlobal(Node * node)190 void JSGenericLowering::LowerJSLoadGlobal(Node* node) {
191   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
192   const LoadGlobalParameters& p = LoadGlobalParametersOf(node->op());
193   Callable callable =
194       CodeFactory::LoadGlobalICInOptimizedCode(isolate(), p.typeof_mode());
195   Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
196   node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.name()));
197   node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.feedback().index()));
198   node->InsertInput(zone(), 2, vector);
199   ReplaceWithStubCall(node, callable, flags);
200 }
201 
202 
LowerJSStoreProperty(Node * node)203 void JSGenericLowering::LowerJSStoreProperty(Node* node) {
204   Node* receiver = NodeProperties::GetValueInput(node, 0);
205   Node* key = NodeProperties::GetValueInput(node, 1);
206   Node* value = NodeProperties::GetValueInput(node, 2);
207   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
208   PropertyAccess const& p = PropertyAccessOf(node->op());
209   Callable callable =
210       CodeFactory::KeyedStoreICInOptimizedCode(isolate(), p.language_mode());
211   Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
212   typedef StoreWithVectorDescriptor Descriptor;
213   node->InsertInputs(zone(), 0, 2);
214   node->ReplaceInput(Descriptor::kReceiver, receiver);
215   node->ReplaceInput(Descriptor::kName, key);
216   node->ReplaceInput(Descriptor::kValue, value);
217   node->ReplaceInput(Descriptor::kSlot,
218                      jsgraph()->SmiConstant(p.feedback().index()));
219   node->ReplaceInput(Descriptor::kVector, vector);
220   ReplaceWithStubCall(node, callable, flags);
221 }
222 
223 
LowerJSStoreNamed(Node * node)224 void JSGenericLowering::LowerJSStoreNamed(Node* node) {
225   Node* receiver = NodeProperties::GetValueInput(node, 0);
226   Node* value = NodeProperties::GetValueInput(node, 1);
227   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
228   NamedAccess const& p = NamedAccessOf(node->op());
229   Callable callable =
230       CodeFactory::StoreICInOptimizedCode(isolate(), p.language_mode());
231   Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
232   typedef StoreWithVectorDescriptor Descriptor;
233   node->InsertInputs(zone(), 0, 3);
234   node->ReplaceInput(Descriptor::kReceiver, receiver);
235   node->ReplaceInput(Descriptor::kName, jsgraph()->HeapConstant(p.name()));
236   node->ReplaceInput(Descriptor::kValue, value);
237   node->ReplaceInput(Descriptor::kSlot,
238                      jsgraph()->SmiConstant(p.feedback().index()));
239   node->ReplaceInput(Descriptor::kVector, vector);
240   ReplaceWithStubCall(node, callable, flags);
241 }
242 
LowerJSStoreNamedOwn(Node * node)243 void JSGenericLowering::LowerJSStoreNamedOwn(Node* node) {
244   Node* receiver = NodeProperties::GetValueInput(node, 0);
245   Node* value = NodeProperties::GetValueInput(node, 1);
246   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
247   StoreNamedOwnParameters const& p = StoreNamedOwnParametersOf(node->op());
248   Callable callable = CodeFactory::StoreOwnICInOptimizedCode(isolate());
249   Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
250   typedef StoreWithVectorDescriptor Descriptor;
251   node->InsertInputs(zone(), 0, 3);
252   node->ReplaceInput(Descriptor::kReceiver, receiver);
253   node->ReplaceInput(Descriptor::kName, jsgraph()->HeapConstant(p.name()));
254   node->ReplaceInput(Descriptor::kValue, value);
255   node->ReplaceInput(Descriptor::kSlot,
256                      jsgraph()->SmiConstant(p.feedback().index()));
257   node->ReplaceInput(Descriptor::kVector, vector);
258   ReplaceWithStubCall(node, callable, flags);
259 }
260 
LowerJSStoreGlobal(Node * node)261 void JSGenericLowering::LowerJSStoreGlobal(Node* node) {
262   Node* value = NodeProperties::GetValueInput(node, 0);
263   Node* context = NodeProperties::GetContextInput(node);
264   Node* effect = NodeProperties::GetEffectInput(node);
265   Node* control = NodeProperties::GetControlInput(node);
266   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
267   const StoreGlobalParameters& p = StoreGlobalParametersOf(node->op());
268   Callable callable =
269       CodeFactory::StoreICInOptimizedCode(isolate(), p.language_mode());
270   Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
271   // Load global object from the context.
272   Node* native_context = effect =
273       graph()->NewNode(machine()->Load(MachineType::AnyTagged()), context,
274                        jsgraph()->IntPtrConstant(
275                            Context::SlotOffset(Context::NATIVE_CONTEXT_INDEX)),
276                        effect, control);
277   Node* global = effect = graph()->NewNode(
278       machine()->Load(MachineType::AnyTagged()), native_context,
279       jsgraph()->IntPtrConstant(Context::SlotOffset(Context::EXTENSION_INDEX)),
280       effect, control);
281   typedef StoreWithVectorDescriptor Descriptor;
282   node->InsertInputs(zone(), 0, 4);
283   node->ReplaceInput(Descriptor::kReceiver, global);
284   node->ReplaceInput(Descriptor::kName, jsgraph()->HeapConstant(p.name()));
285   node->ReplaceInput(Descriptor::kValue, value);
286   node->ReplaceInput(Descriptor::kSlot,
287                      jsgraph()->SmiConstant(p.feedback().index()));
288   node->ReplaceInput(Descriptor::kVector, vector);
289   node->ReplaceInput(7, effect);
290   ReplaceWithStubCall(node, callable, flags);
291 }
292 
LowerJSStoreDataPropertyInLiteral(Node * node)293 void JSGenericLowering::LowerJSStoreDataPropertyInLiteral(Node* node) {
294   DataPropertyParameters const& p = DataPropertyParametersOf(node->op());
295   node->InsertInputs(zone(), 4, 2);
296   node->ReplaceInput(4, jsgraph()->HeapConstant(p.feedback().vector()));
297   node->ReplaceInput(5, jsgraph()->SmiConstant(p.feedback().index()));
298   ReplaceWithRuntimeCall(node, Runtime::kDefineDataPropertyInLiteral);
299 }
300 
LowerJSDeleteProperty(Node * node)301 void JSGenericLowering::LowerJSDeleteProperty(Node* node) {
302   LanguageMode language_mode = OpParameter<LanguageMode>(node);
303   ReplaceWithRuntimeCall(node, is_strict(language_mode)
304                                    ? Runtime::kDeleteProperty_Strict
305                                    : Runtime::kDeleteProperty_Sloppy);
306 }
307 
LowerJSGetSuperConstructor(Node * node)308 void JSGenericLowering::LowerJSGetSuperConstructor(Node* node) {
309   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
310   Callable callable = CodeFactory::GetSuperConstructor(isolate());
311   ReplaceWithStubCall(node, callable, flags);
312 }
313 
LowerJSInstanceOf(Node * node)314 void JSGenericLowering::LowerJSInstanceOf(Node* node) {
315   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
316   Callable callable = CodeFactory::InstanceOf(isolate());
317   ReplaceWithStubCall(node, callable, flags);
318 }
319 
LowerJSOrdinaryHasInstance(Node * node)320 void JSGenericLowering::LowerJSOrdinaryHasInstance(Node* node) {
321   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
322   Callable callable = CodeFactory::OrdinaryHasInstance(isolate());
323   ReplaceWithStubCall(node, callable, flags);
324 }
325 
LowerJSLoadContext(Node * node)326 void JSGenericLowering::LowerJSLoadContext(Node* node) {
327   UNREACHABLE();  // Eliminated in typed lowering.
328 }
329 
330 
LowerJSStoreContext(Node * node)331 void JSGenericLowering::LowerJSStoreContext(Node* node) {
332   UNREACHABLE();  // Eliminated in typed lowering.
333 }
334 
335 
LowerJSCreate(Node * node)336 void JSGenericLowering::LowerJSCreate(Node* node) {
337   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
338   Callable callable = CodeFactory::FastNewObject(isolate());
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   Node* new_target = node->InputAt(1);
364   Node* type_info = site.is_null() ? jsgraph()->UndefinedConstant()
365                                    : jsgraph()->HeapConstant(site);
366   node->RemoveInput(1);
367   node->InsertInput(zone(), 1 + arity, new_target);
368   node->InsertInput(zone(), 2 + arity, type_info);
369   ReplaceWithRuntimeCall(node, Runtime::kNewArray, arity + 3);
370 }
371 
372 
LowerJSCreateClosure(Node * node)373 void JSGenericLowering::LowerJSCreateClosure(Node* node) {
374   CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
375   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
376   Handle<SharedFunctionInfo> const shared_info = p.shared_info();
377   node->InsertInput(zone(), 0, jsgraph()->HeapConstant(shared_info));
378 
379   // Use the FastNewClosurebuiltin only for functions allocated in new
380   // space.
381   if (p.pretenure() == NOT_TENURED) {
382     Callable callable = CodeFactory::FastNewClosure(isolate());
383     node->InsertInput(zone(), 1,
384                       jsgraph()->HeapConstant(p.feedback().vector()));
385     node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
386     ReplaceWithStubCall(node, callable, flags);
387   } else {
388     node->InsertInput(zone(), 1,
389                       jsgraph()->HeapConstant(p.feedback().vector()));
390     node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
391     ReplaceWithRuntimeCall(node, (p.pretenure() == TENURED)
392                                      ? Runtime::kNewClosure_Tenured
393                                      : Runtime::kNewClosure);
394   }
395 }
396 
397 
LowerJSCreateFunctionContext(Node * node)398 void JSGenericLowering::LowerJSCreateFunctionContext(Node* node) {
399   const CreateFunctionContextParameters& parameters =
400       CreateFunctionContextParametersOf(node->op());
401   int slot_count = parameters.slot_count();
402   ScopeType scope_type = parameters.scope_type();
403   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
404 
405   if (slot_count <=
406       ConstructorBuiltinsAssembler::MaximumFunctionContextSlots()) {
407     Callable callable =
408         CodeFactory::FastNewFunctionContext(isolate(), scope_type);
409     node->InsertInput(zone(), 1, jsgraph()->Int32Constant(slot_count));
410     ReplaceWithStubCall(node, callable, flags);
411   } else {
412     node->InsertInput(zone(), 1, jsgraph()->SmiConstant(scope_type));
413     ReplaceWithRuntimeCall(node, Runtime::kNewFunctionContext);
414   }
415 }
416 
417 
LowerJSCreateIterResultObject(Node * node)418 void JSGenericLowering::LowerJSCreateIterResultObject(Node* node) {
419   ReplaceWithRuntimeCall(node, Runtime::kCreateIterResultObject);
420 }
421 
LowerJSCreateKeyValueArray(Node * node)422 void JSGenericLowering::LowerJSCreateKeyValueArray(Node* node) {
423   ReplaceWithRuntimeCall(node, Runtime::kCreateKeyValueArray);
424 }
425 
LowerJSCreateLiteralArray(Node * node)426 void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
427   CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
428   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
429   node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
430   node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
431 
432   // Use the FastCloneShallowArray builtin only for shallow boilerplates without
433   // properties up to the number of elements that the stubs can handle.
434   if ((p.flags() & ArrayLiteral::kShallowElements) != 0 &&
435       p.length() <
436           ConstructorBuiltinsAssembler::kMaximumClonedShallowArrayElements) {
437     Callable callable = CodeFactory::FastCloneShallowArray(
438         isolate(), DONT_TRACK_ALLOCATION_SITE);
439     ReplaceWithStubCall(node, callable, flags);
440   } else {
441     node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
442     ReplaceWithRuntimeCall(node, Runtime::kCreateArrayLiteral);
443   }
444 }
445 
446 
LowerJSCreateLiteralObject(Node * node)447 void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
448   CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
449   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
450   node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
451   node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
452   node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
453 
454   // Use the FastCloneShallowObject builtin only for shallow boilerplates
455   // without elements up to the number of properties that the stubs can handle.
456   if ((p.flags() & ObjectLiteral::kShallowProperties) != 0 &&
457       p.length() <=
458           ConstructorBuiltinsAssembler::kMaximumClonedShallowObjectProperties) {
459     Callable callable =
460         CodeFactory::FastCloneShallowObject(isolate(), p.length());
461     ReplaceWithStubCall(node, callable, flags);
462   } else {
463     ReplaceWithRuntimeCall(node, Runtime::kCreateObjectLiteral);
464   }
465 }
466 
467 
LowerJSCreateLiteralRegExp(Node * node)468 void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
469   CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
470   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
471   Callable callable = CodeFactory::FastCloneRegExp(isolate());
472   Node* literal_index = jsgraph()->SmiConstant(p.index());
473   Node* literal_flags = jsgraph()->SmiConstant(p.flags());
474   Node* pattern = jsgraph()->HeapConstant(p.constant());
475   node->InsertInput(graph()->zone(), 1, literal_index);
476   node->InsertInput(graph()->zone(), 2, pattern);
477   node->InsertInput(graph()->zone(), 3, literal_flags);
478   ReplaceWithStubCall(node, callable, flags);
479 }
480 
481 
LowerJSCreateCatchContext(Node * node)482 void JSGenericLowering::LowerJSCreateCatchContext(Node* node) {
483   const CreateCatchContextParameters& parameters =
484       CreateCatchContextParametersOf(node->op());
485   node->InsertInput(zone(), 0,
486                     jsgraph()->HeapConstant(parameters.catch_name()));
487   node->InsertInput(zone(), 2,
488                     jsgraph()->HeapConstant(parameters.scope_info()));
489   ReplaceWithRuntimeCall(node, Runtime::kPushCatchContext);
490 }
491 
LowerJSCreateWithContext(Node * node)492 void JSGenericLowering::LowerJSCreateWithContext(Node* node) {
493   Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
494   node->InsertInput(zone(), 1, jsgraph()->HeapConstant(scope_info));
495   ReplaceWithRuntimeCall(node, Runtime::kPushWithContext);
496 }
497 
LowerJSCreateBlockContext(Node * node)498 void JSGenericLowering::LowerJSCreateBlockContext(Node* node) {
499   Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
500   node->InsertInput(zone(), 0, jsgraph()->HeapConstant(scope_info));
501   ReplaceWithRuntimeCall(node, Runtime::kPushBlockContext);
502 }
503 
504 
LowerJSCreateScriptContext(Node * node)505 void JSGenericLowering::LowerJSCreateScriptContext(Node* node) {
506   Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
507   node->InsertInput(zone(), 1, jsgraph()->HeapConstant(scope_info));
508   ReplaceWithRuntimeCall(node, Runtime::kNewScriptContext);
509 }
510 
LowerJSConstruct(Node * node)511 void JSGenericLowering::LowerJSConstruct(Node* node) {
512   ConstructParameters const& p = ConstructParametersOf(node->op());
513   int const arg_count = static_cast<int>(p.arity() - 2);
514   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
515   Callable callable = CodeFactory::Construct(isolate());
516   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
517       isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
518   Node* stub_code = jsgraph()->HeapConstant(callable.code());
519   Node* stub_arity = jsgraph()->Int32Constant(arg_count);
520   Node* new_target = node->InputAt(arg_count + 1);
521   Node* receiver = jsgraph()->UndefinedConstant();
522   node->RemoveInput(arg_count + 1);  // Drop new target.
523   node->InsertInput(zone(), 0, stub_code);
524   node->InsertInput(zone(), 2, new_target);
525   node->InsertInput(zone(), 3, stub_arity);
526   node->InsertInput(zone(), 4, receiver);
527   NodeProperties::ChangeOp(node, common()->Call(desc));
528 }
529 
LowerJSConstructWithSpread(Node * node)530 void JSGenericLowering::LowerJSConstructWithSpread(Node* node) {
531   ConstructWithSpreadParameters const& p =
532       ConstructWithSpreadParametersOf(node->op());
533   int const arg_count = static_cast<int>(p.arity() - 2);
534   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
535   Callable callable = CodeFactory::ConstructWithSpread(isolate());
536   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
537       isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
538   Node* stub_code = jsgraph()->HeapConstant(callable.code());
539   Node* stub_arity = jsgraph()->Int32Constant(arg_count);
540   Node* new_target = node->InputAt(arg_count + 1);
541   Node* receiver = jsgraph()->UndefinedConstant();
542   node->RemoveInput(arg_count + 1);  // Drop new target.
543   node->InsertInput(zone(), 0, stub_code);
544   node->InsertInput(zone(), 2, new_target);
545   node->InsertInput(zone(), 3, stub_arity);
546   node->InsertInput(zone(), 4, receiver);
547   NodeProperties::ChangeOp(node, common()->Call(desc));
548 }
549 
LowerJSCallForwardVarargs(Node * node)550 void JSGenericLowering::LowerJSCallForwardVarargs(Node* node) {
551   CallForwardVarargsParameters p = CallForwardVarargsParametersOf(node->op());
552   Callable callable = CodeFactory::CallForwardVarargs(isolate());
553   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
554   if (p.tail_call_mode() == TailCallMode::kAllow) {
555     flags |= CallDescriptor::kSupportsTailCalls;
556   }
557   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
558       isolate(), zone(), callable.descriptor(), 1, flags);
559   Node* stub_code = jsgraph()->HeapConstant(callable.code());
560   Node* start_index = jsgraph()->Uint32Constant(p.start_index());
561   node->InsertInput(zone(), 0, stub_code);
562   node->InsertInput(zone(), 2, start_index);
563   NodeProperties::ChangeOp(node, common()->Call(desc));
564 }
565 
LowerJSCall(Node * node)566 void JSGenericLowering::LowerJSCall(Node* node) {
567   CallParameters const& p = CallParametersOf(node->op());
568   int const arg_count = static_cast<int>(p.arity() - 2);
569   ConvertReceiverMode const mode = p.convert_mode();
570   Callable callable = CodeFactory::Call(isolate(), mode);
571   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
572   if (p.tail_call_mode() == TailCallMode::kAllow) {
573     flags |= CallDescriptor::kSupportsTailCalls;
574   }
575   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
576       isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
577   Node* stub_code = jsgraph()->HeapConstant(callable.code());
578   Node* stub_arity = jsgraph()->Int32Constant(arg_count);
579   node->InsertInput(zone(), 0, stub_code);
580   node->InsertInput(zone(), 2, stub_arity);
581   NodeProperties::ChangeOp(node, common()->Call(desc));
582 }
583 
LowerJSCallWithSpread(Node * node)584 void JSGenericLowering::LowerJSCallWithSpread(Node* node) {
585   CallWithSpreadParameters const& p = CallWithSpreadParametersOf(node->op());
586   int const arg_count = static_cast<int>(p.arity() - 2);
587   Callable callable = CodeFactory::CallWithSpread(isolate());
588   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
589   CallDescriptor* desc = 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->InsertInput(zone(), 0, stub_code);
594   node->InsertInput(zone(), 2, stub_arity);
595   NodeProperties::ChangeOp(node, common()->Call(desc));
596 }
597 
LowerJSCallRuntime(Node * node)598 void JSGenericLowering::LowerJSCallRuntime(Node* node) {
599   const CallRuntimeParameters& p = CallRuntimeParametersOf(node->op());
600   ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity()));
601 }
602 
LowerJSConvertReceiver(Node * node)603 void JSGenericLowering::LowerJSConvertReceiver(Node* node) {
604   ReplaceWithRuntimeCall(node, Runtime::kConvertReceiver);
605 }
606 
LowerJSForInNext(Node * node)607 void JSGenericLowering::LowerJSForInNext(Node* node) {
608   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
609   Callable callable = CodeFactory::ForInNext(isolate());
610   ReplaceWithStubCall(node, callable, flags);
611 }
612 
LowerJSForInPrepare(Node * node)613 void JSGenericLowering::LowerJSForInPrepare(Node* node) {
614   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
615   Callable callable = CodeFactory::ForInPrepare(isolate());
616   ReplaceWithStubCall(node, callable, flags, node->op()->properties(), 3);
617 }
618 
LowerJSLoadMessage(Node * node)619 void JSGenericLowering::LowerJSLoadMessage(Node* node) {
620   UNREACHABLE();  // Eliminated in typed lowering.
621 }
622 
623 
LowerJSStoreMessage(Node * node)624 void JSGenericLowering::LowerJSStoreMessage(Node* node) {
625   UNREACHABLE();  // Eliminated in typed lowering.
626 }
627 
LowerJSLoadModule(Node * node)628 void JSGenericLowering::LowerJSLoadModule(Node* node) {
629   UNREACHABLE();  // Eliminated in typed lowering.
630 }
631 
LowerJSStoreModule(Node * node)632 void JSGenericLowering::LowerJSStoreModule(Node* node) {
633   UNREACHABLE();  // Eliminated in typed lowering.
634 }
635 
LowerJSGeneratorStore(Node * node)636 void JSGenericLowering::LowerJSGeneratorStore(Node* node) {
637   UNREACHABLE();  // Eliminated in typed lowering.
638 }
639 
LowerJSGeneratorRestoreContinuation(Node * node)640 void JSGenericLowering::LowerJSGeneratorRestoreContinuation(Node* node) {
641   UNREACHABLE();  // Eliminated in typed lowering.
642 }
643 
LowerJSGeneratorRestoreRegister(Node * node)644 void JSGenericLowering::LowerJSGeneratorRestoreRegister(Node* node) {
645   UNREACHABLE();  // Eliminated in typed lowering.
646 }
647 
LowerJSStackCheck(Node * node)648 void JSGenericLowering::LowerJSStackCheck(Node* node) {
649   Node* effect = NodeProperties::GetEffectInput(node);
650   Node* control = NodeProperties::GetControlInput(node);
651 
652   Node* limit = graph()->NewNode(
653       machine()->Load(MachineType::Pointer()),
654       jsgraph()->ExternalConstant(
655           ExternalReference::address_of_stack_limit(isolate())),
656       jsgraph()->IntPtrConstant(0), effect, control);
657   Node* pointer = graph()->NewNode(machine()->LoadStackPointer());
658 
659   Node* check = graph()->NewNode(machine()->UintLessThan(), limit, pointer);
660   Node* branch =
661       graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
662 
663   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
664   Node* etrue = effect;
665 
666   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
667   NodeProperties::ReplaceControlInput(node, if_false);
668   Node* efalse = node;
669 
670   Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
671   Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
672 
673   // Wire the new diamond into the graph, {node} can still throw.
674   NodeProperties::ReplaceUses(node, node, ephi, node, node);
675   NodeProperties::ReplaceEffectInput(ephi, efalse, 1);
676 
677   // TODO(mstarzinger): This iteration cuts out the IfSuccess projection from
678   // the node and places it inside the diamond. Come up with a helper method!
679   for (Node* use : node->uses()) {
680     if (use->opcode() == IrOpcode::kIfSuccess) {
681       use->ReplaceUses(merge);
682       merge->ReplaceInput(1, use);
683     }
684   }
685 
686   // Turn the stack check into a runtime call.
687   ReplaceWithRuntimeCall(node, Runtime::kStackGuard);
688 }
689 
LowerJSDebugger(Node * node)690 void JSGenericLowering::LowerJSDebugger(Node* node) {
691   CallDescriptor::Flags flags = FrameStateFlagForCall(node);
692   Callable callable = CodeFactory::HandleDebuggerStatement(isolate());
693   ReplaceWithStubCall(node, callable, flags);
694 }
695 
zone() const696 Zone* JSGenericLowering::zone() const { return graph()->zone(); }
697 
698 
isolate() const699 Isolate* JSGenericLowering::isolate() const { return jsgraph()->isolate(); }
700 
701 
graph() const702 Graph* JSGenericLowering::graph() const { return jsgraph()->graph(); }
703 
704 
common() const705 CommonOperatorBuilder* JSGenericLowering::common() const {
706   return jsgraph()->common();
707 }
708 
709 
machine() const710 MachineOperatorBuilder* JSGenericLowering::machine() const {
711   return jsgraph()->machine();
712 }
713 
714 }  // namespace compiler
715 }  // namespace internal
716 }  // namespace v8
717