Line data Source code
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 :
25 2035351 : CallDescriptor::Flags FrameStateFlagForCall(Node* node) {
26 2035351 : return OperatorProperties::HasFrameStateInput(node->op())
27 : ? CallDescriptor::kNeedsFrameState
28 2035355 : : CallDescriptor::kNoFlags;
29 : }
30 :
31 : } // namespace
32 :
33 790604 : JSGenericLowering::JSGenericLowering(JSGraph* jsgraph) : jsgraph_(jsgraph) {}
34 :
35 790602 : JSGenericLowering::~JSGenericLowering() {}
36 :
37 :
38 38951986 : Reduction JSGenericLowering::Reduce(Node* node) {
39 38951986 : switch (node->opcode()) {
40 : #define DECLARE_CASE(x) \
41 : case IrOpcode::k##x: \
42 : Lower##x(node); \
43 : break;
44 30839 : 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 117596 : REPLACE_STUB_CALL(Add)
60 59572 : REPLACE_STUB_CALL(Subtract)
61 72824 : REPLACE_STUB_CALL(Multiply)
62 50200 : REPLACE_STUB_CALL(Divide)
63 2148 : REPLACE_STUB_CALL(Modulus)
64 7960 : REPLACE_STUB_CALL(BitwiseAnd)
65 6512 : REPLACE_STUB_CALL(BitwiseOr)
66 3704 : REPLACE_STUB_CALL(BitwiseXor)
67 5528 : REPLACE_STUB_CALL(ShiftLeft)
68 2232 : REPLACE_STUB_CALL(ShiftRight)
69 1372 : REPLACE_STUB_CALL(ShiftRightLogical)
70 93908 : REPLACE_STUB_CALL(LessThan)
71 4945 : REPLACE_STUB_CALL(LessThanOrEqual)
72 24556 : REPLACE_STUB_CALL(GreaterThan)
73 12312 : REPLACE_STUB_CALL(GreaterThanOrEqual)
74 19264 : REPLACE_STUB_CALL(HasProperty)
75 40936 : REPLACE_STUB_CALL(Equal)
76 1084 : REPLACE_STUB_CALL(ToInteger)
77 932 : REPLACE_STUB_CALL(ToLength)
78 9576 : REPLACE_STUB_CALL(ToNumber)
79 5484 : REPLACE_STUB_CALL(ToName)
80 188 : REPLACE_STUB_CALL(ToObject)
81 10420 : REPLACE_STUB_CALL(ToString)
82 : #undef REPLACE_STUB_CALL
83 :
84 1072204 : void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
85 : CallDescriptor::Flags flags) {
86 1072204 : ReplaceWithStubCall(node, callable, flags, node->op()->properties());
87 1072206 : }
88 :
89 1224355 : void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
90 : CallDescriptor::Flags flags,
91 : Operator::Properties properties,
92 1224355 : int result_size) {
93 : const CallInterfaceDescriptor& descriptor = callable.descriptor();
94 : CallDescriptor* desc = Linkage::GetStubCallDescriptor(
95 : isolate(), zone(), descriptor, descriptor.GetStackParameterCount(), flags,
96 2448710 : properties, MachineType::AnyTagged(), result_size);
97 1224355 : Node* stub_code = jsgraph()->HeapConstant(callable.code());
98 1224355 : node->InsertInput(zone(), 0, stub_code);
99 1224357 : NodeProperties::ChangeOp(node, common()->Call(desc));
100 1224357 : }
101 :
102 :
103 1788160 : void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
104 : Runtime::FunctionId f,
105 2682244 : int nargs_override) {
106 894082 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
107 894082 : Operator::Properties properties = node->op()->properties();
108 894082 : const Runtime::Function* fun = Runtime::FunctionForId(f);
109 894079 : int nargs = (nargs_override < 0) ? fun->nargs : nargs_override;
110 : CallDescriptor* desc =
111 894079 : Linkage::GetRuntimeCallDescriptor(zone(), f, nargs, properties, flags);
112 1788164 : Node* ref = jsgraph()->ExternalConstant(ExternalReference(f, isolate()));
113 894081 : Node* arity = jsgraph()->Int32Constant(nargs);
114 2682242 : node->InsertInput(zone(), 0, jsgraph()->CEntryStubConstant(fun->result_size));
115 1788160 : node->InsertInput(zone(), nargs + 1, ref);
116 1788164 : node->InsertInput(zone(), nargs + 2, arity);
117 894079 : NodeProperties::ChangeOp(node, common()->Call(desc));
118 894080 : }
119 :
120 128043 : void JSGenericLowering::LowerJSStrictEqual(Node* node) {
121 : // The === operator doesn't need the current context.
122 128043 : NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
123 128043 : Callable callable = CodeFactory::StrictEqual(isolate());
124 128043 : node->RemoveInput(4); // control
125 : ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags,
126 128043 : Operator::kEliminatable);
127 128043 : }
128 :
129 1382 : void JSGenericLowering::LowerJSToBoolean(Node* node) {
130 : // The ToBoolean conversion doesn't need the current context.
131 1382 : NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
132 1382 : Callable callable = CodeFactory::ToBoolean(isolate());
133 2764 : node->AppendInput(zone(), graph()->start());
134 : ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
135 1382 : Operator::kEliminatable);
136 1382 : }
137 :
138 2833 : void JSGenericLowering::LowerJSClassOf(Node* node) {
139 : // The %_ClassOf intrinsic doesn't need the current context.
140 2833 : NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
141 2833 : Callable callable = CodeFactory::ClassOf(isolate());
142 5666 : node->AppendInput(zone(), graph()->start());
143 : ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
144 2833 : Operator::kEliminatable);
145 2833 : }
146 :
147 18594 : void JSGenericLowering::LowerJSTypeOf(Node* node) {
148 : // The typeof operator doesn't need the current context.
149 18594 : NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
150 18594 : Callable callable = CodeFactory::Typeof(isolate());
151 37188 : node->AppendInput(zone(), graph()->start());
152 : ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
153 : Operator::kEliminatable);
154 18594 : }
155 :
156 :
157 222412 : void JSGenericLowering::LowerJSLoadProperty(Node* node) {
158 73577 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
159 73577 : const PropertyAccess& p = PropertyAccessOf(node->op());
160 73577 : Node* frame_state = NodeProperties::GetFrameStateInput(node);
161 73577 : Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
162 147154 : node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
163 73577 : if (outer_state->opcode() != IrOpcode::kFrameState) {
164 71896 : Callable callable = CodeFactory::KeyedLoadIC(isolate());
165 71896 : ReplaceWithStubCall(node, callable, flags);
166 : } else {
167 1681 : Callable callable = CodeFactory::KeyedLoadICInOptimizedCode(isolate());
168 1681 : Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
169 1681 : node->InsertInput(zone(), 3, vector);
170 1681 : ReplaceWithStubCall(node, callable, flags);
171 : }
172 73577 : }
173 :
174 :
175 1564132 : void JSGenericLowering::LowerJSLoadNamed(Node* node) {
176 390646 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
177 390646 : NamedAccess const& p = NamedAccessOf(node->op());
178 390646 : Node* frame_state = NodeProperties::GetFrameStateInput(node);
179 390646 : Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
180 781292 : node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
181 781292 : node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
182 390646 : if (outer_state->opcode() != IrOpcode::kFrameState) {
183 389098 : Callable callable = CodeFactory::LoadIC(isolate());
184 389098 : ReplaceWithStubCall(node, callable, flags);
185 : } else {
186 1548 : Callable callable = CodeFactory::LoadICInOptimizedCode(isolate());
187 1548 : Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
188 1548 : node->InsertInput(zone(), 3, vector);
189 1548 : ReplaceWithStubCall(node, callable, flags);
190 : }
191 390646 : }
192 :
193 :
194 385464 : void JSGenericLowering::LowerJSLoadGlobal(Node* node) {
195 96359 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
196 192718 : const LoadGlobalParameters& p = LoadGlobalParametersOf(node->op());
197 96359 : Node* frame_state = NodeProperties::GetFrameStateInput(node);
198 96359 : Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
199 192718 : node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.name()));
200 192718 : node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.feedback().index()));
201 96359 : if (outer_state->opcode() != IrOpcode::kFrameState) {
202 96331 : Callable callable = CodeFactory::LoadGlobalIC(isolate(), p.typeof_mode());
203 96331 : ReplaceWithStubCall(node, callable, flags);
204 : } else {
205 : Callable callable =
206 28 : CodeFactory::LoadGlobalICInOptimizedCode(isolate(), p.typeof_mode());
207 28 : Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
208 28 : node->InsertInput(zone(), 2, vector);
209 28 : ReplaceWithStubCall(node, callable, flags);
210 : }
211 96359 : }
212 :
213 107808 : void JSGenericLowering::LowerJSStoreProperty(Node* node) {
214 35780 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
215 71560 : PropertyAccess const& p = PropertyAccessOf(node->op());
216 35780 : Node* frame_state = NodeProperties::GetFrameStateInput(node);
217 35780 : Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
218 71560 : node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
219 35780 : if (outer_state->opcode() != IrOpcode::kFrameState) {
220 35312 : Callable callable = CodeFactory::KeyedStoreIC(isolate(), p.language_mode());
221 35312 : ReplaceWithStubCall(node, callable, flags);
222 : } else {
223 : Callable callable =
224 468 : CodeFactory::KeyedStoreICInOptimizedCode(isolate(), p.language_mode());
225 468 : Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
226 468 : node->InsertInput(zone(), 4, vector);
227 468 : ReplaceWithStubCall(node, callable, flags);
228 : }
229 35780 : }
230 :
231 241524 : void JSGenericLowering::LowerJSStoreNamed(Node* node) {
232 60375 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
233 120750 : NamedAccess const& p = NamedAccessOf(node->op());
234 60375 : Node* frame_state = NodeProperties::GetFrameStateInput(node);
235 60375 : Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
236 120750 : node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
237 120750 : node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
238 60375 : if (outer_state->opcode() != IrOpcode::kFrameState) {
239 60351 : Callable callable = CodeFactory::StoreIC(isolate(), p.language_mode());
240 60351 : ReplaceWithStubCall(node, callable, flags);
241 : } else {
242 : Callable callable =
243 24 : CodeFactory::StoreICInOptimizedCode(isolate(), p.language_mode());
244 24 : Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
245 24 : node->InsertInput(zone(), 4, vector);
246 24 : ReplaceWithStubCall(node, callable, flags);
247 : }
248 60375 : }
249 :
250 137782 : void JSGenericLowering::LowerJSStoreNamedOwn(Node* node) {
251 34425 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
252 34425 : StoreNamedOwnParameters const& p = StoreNamedOwnParametersOf(node->op());
253 34425 : Node* frame_state = NodeProperties::GetFrameStateInput(node);
254 34425 : Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
255 68850 : node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
256 68850 : node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
257 34425 : if (outer_state->opcode() != IrOpcode::kFrameState) {
258 34343 : Callable callable = CodeFactory::StoreOwnIC(isolate());
259 34343 : ReplaceWithStubCall(node, callable, flags);
260 : } else {
261 82 : Callable callable = CodeFactory::StoreOwnICInOptimizedCode(isolate());
262 82 : Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
263 82 : node->InsertInput(zone(), 4, vector);
264 82 : ReplaceWithStubCall(node, callable, flags);
265 : }
266 34425 : }
267 :
268 107030 : void JSGenericLowering::LowerJSStoreGlobal(Node* node) {
269 17837 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
270 35674 : const StoreGlobalParameters& p = StoreGlobalParametersOf(node->op());
271 17837 : Node* frame_state = NodeProperties::GetFrameStateInput(node);
272 17837 : Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
273 17837 : Node* context = NodeProperties::GetContextInput(node);
274 17837 : Node* effect = NodeProperties::GetEffectInput(node);
275 17837 : Node* control = NodeProperties::GetControlInput(node);
276 : // Load global object from the context.
277 : Node* native_context = effect =
278 : graph()->NewNode(machine()->Load(MachineType::AnyTagged()), context,
279 : jsgraph()->IntPtrConstant(
280 : Context::SlotOffset(Context::NATIVE_CONTEXT_INDEX)),
281 35674 : effect, control);
282 : Node* global = effect = graph()->NewNode(
283 : machine()->Load(MachineType::AnyTagged()), native_context,
284 : jsgraph()->IntPtrConstant(Context::SlotOffset(Context::EXTENSION_INDEX)),
285 35674 : effect, control);
286 17837 : NodeProperties::ReplaceEffectInput(node, effect);
287 17837 : node->InsertInput(zone(), 0, global);
288 35674 : node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
289 35674 : node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
290 17837 : if (outer_state->opcode() != IrOpcode::kFrameState) {
291 : Callable callable =
292 17829 : CodeFactory::StoreGlobalIC(isolate(), p.language_mode());
293 17829 : ReplaceWithStubCall(node, callable, flags);
294 : } else {
295 : Callable callable =
296 8 : CodeFactory::StoreGlobalICInOptimizedCode(isolate(), p.language_mode());
297 8 : Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
298 8 : node->InsertInput(zone(), 4, vector);
299 8 : ReplaceWithStubCall(node, callable, flags);
300 : }
301 17837 : }
302 :
303 132270 : void JSGenericLowering::LowerJSStoreDataPropertyInLiteral(Node* node) {
304 44090 : FeedbackParameter const& p = FeedbackParameterOf(node->op());
305 44090 : node->InsertInputs(zone(), 4, 2);
306 44090 : node->ReplaceInput(4, jsgraph()->HeapConstant(p.feedback().vector()));
307 88180 : node->ReplaceInput(5, jsgraph()->SmiConstant(p.feedback().index()));
308 44090 : ReplaceWithRuntimeCall(node, Runtime::kDefineDataPropertyInLiteral);
309 44090 : }
310 :
311 2127 : void JSGenericLowering::LowerJSDeleteProperty(Node* node) {
312 2127 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
313 : Callable callable =
314 2127 : Builtins::CallableFor(isolate(), Builtins::kDeleteProperty);
315 2127 : ReplaceWithStubCall(node, callable, flags);
316 2127 : }
317 :
318 74 : void JSGenericLowering::LowerJSGetSuperConstructor(Node* node) {
319 74 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
320 74 : Callable callable = CodeFactory::GetSuperConstructor(isolate());
321 74 : ReplaceWithStubCall(node, callable, flags);
322 74 : }
323 :
324 965 : void JSGenericLowering::LowerJSInstanceOf(Node* node) {
325 965 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
326 965 : Callable callable = CodeFactory::InstanceOf(isolate());
327 965 : ReplaceWithStubCall(node, callable, flags);
328 965 : }
329 :
330 47 : void JSGenericLowering::LowerJSOrdinaryHasInstance(Node* node) {
331 47 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
332 47 : Callable callable = CodeFactory::OrdinaryHasInstance(isolate());
333 47 : ReplaceWithStubCall(node, callable, flags);
334 47 : }
335 :
336 0 : void JSGenericLowering::LowerJSLoadContext(Node* node) {
337 0 : UNREACHABLE(); // Eliminated in typed lowering.
338 : }
339 :
340 :
341 0 : void JSGenericLowering::LowerJSStoreContext(Node* node) {
342 0 : UNREACHABLE(); // Eliminated in typed lowering.
343 : }
344 :
345 :
346 58 : void JSGenericLowering::LowerJSCreate(Node* node) {
347 58 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
348 58 : Callable callable = CodeFactory::FastNewObject(isolate());
349 58 : ReplaceWithStubCall(node, callable, flags);
350 58 : }
351 :
352 :
353 3 : void JSGenericLowering::LowerJSCreateArguments(Node* node) {
354 3 : CreateArgumentsType const type = CreateArgumentsTypeOf(node->op());
355 3 : switch (type) {
356 : case CreateArgumentsType::kMappedArguments:
357 3 : ReplaceWithRuntimeCall(node, Runtime::kNewSloppyArguments_Generic);
358 3 : break;
359 : case CreateArgumentsType::kUnmappedArguments:
360 0 : ReplaceWithRuntimeCall(node, Runtime::kNewStrictArguments);
361 0 : break;
362 : case CreateArgumentsType::kRestParameter:
363 0 : ReplaceWithRuntimeCall(node, Runtime::kNewRestParameter);
364 0 : break;
365 : }
366 3 : }
367 :
368 :
369 6448 : void JSGenericLowering::LowerJSCreateArray(Node* node) {
370 3224 : CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
371 3224 : int const arity = static_cast<int>(p.arity());
372 : Handle<AllocationSite> const site = p.site();
373 : Node* new_target = node->InputAt(1);
374 : Node* type_info = site.is_null() ? jsgraph()->UndefinedConstant()
375 6448 : : jsgraph()->HeapConstant(site);
376 3224 : node->RemoveInput(1);
377 6448 : node->InsertInput(zone(), 1 + arity, new_target);
378 6448 : node->InsertInput(zone(), 2 + arity, type_info);
379 3224 : ReplaceWithRuntimeCall(node, Runtime::kNewArray, arity + 3);
380 3224 : }
381 :
382 :
383 736420 : void JSGenericLowering::LowerJSCreateClosure(Node* node) {
384 376799 : CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
385 184105 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
386 : Handle<SharedFunctionInfo> const shared_info = p.shared_info();
387 368210 : node->InsertInput(zone(), 0, jsgraph()->HeapConstant(shared_info));
388 :
389 : // Use the FastNewClosurebuiltin only for functions allocated in new
390 : // space.
391 184105 : if (p.pretenure() == NOT_TENURED) {
392 175516 : Callable callable = CodeFactory::FastNewClosure(isolate());
393 : node->InsertInput(zone(), 1,
394 351032 : jsgraph()->HeapConstant(p.feedback().vector()));
395 351032 : node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
396 175516 : ReplaceWithStubCall(node, callable, flags);
397 : } else {
398 : node->InsertInput(zone(), 1,
399 17178 : jsgraph()->HeapConstant(p.feedback().vector()));
400 17178 : node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
401 : ReplaceWithRuntimeCall(node, (p.pretenure() == TENURED)
402 : ? Runtime::kNewClosure_Tenured
403 8589 : : Runtime::kNewClosure);
404 : }
405 184105 : }
406 :
407 :
408 846 : void JSGenericLowering::LowerJSCreateFunctionContext(Node* node) {
409 423 : const CreateFunctionContextParameters& parameters =
410 423 : CreateFunctionContextParametersOf(node->op());
411 : int slot_count = parameters.slot_count();
412 : ScopeType scope_type = parameters.scope_type();
413 423 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
414 :
415 423 : if (slot_count <= ConstructorBuiltins::MaximumFunctionContextSlots()) {
416 : Callable callable =
417 846 : CodeFactory::FastNewFunctionContext(isolate(), scope_type);
418 846 : node->InsertInput(zone(), 1, jsgraph()->Int32Constant(slot_count));
419 423 : ReplaceWithStubCall(node, callable, flags);
420 : } else {
421 0 : node->InsertInput(zone(), 1, jsgraph()->SmiConstant(scope_type));
422 0 : ReplaceWithRuntimeCall(node, Runtime::kNewFunctionContext);
423 : }
424 423 : }
425 :
426 :
427 0 : void JSGenericLowering::LowerJSCreateIterResultObject(Node* node) {
428 0 : ReplaceWithRuntimeCall(node, Runtime::kCreateIterResultObject);
429 0 : }
430 :
431 0 : void JSGenericLowering::LowerJSCreateKeyValueArray(Node* node) {
432 0 : ReplaceWithRuntimeCall(node, Runtime::kCreateKeyValueArray);
433 0 : }
434 :
435 62694 : void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
436 81566 : CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
437 20605 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
438 20605 : node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
439 41210 : node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
440 :
441 : // Use the FastCloneShallowArray builtin only for shallow boilerplates without
442 : // properties up to the number of elements that the stubs can handle.
443 40356 : if ((p.flags() & ArrayLiteral::kShallowElements) != 0 &&
444 : p.length() < ConstructorBuiltins::kMaximumClonedShallowArrayElements) {
445 : Callable callable = CodeFactory::FastCloneShallowArray(
446 19726 : isolate(), DONT_TRACK_ALLOCATION_SITE);
447 19726 : ReplaceWithStubCall(node, callable, flags);
448 : } else {
449 879 : node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
450 879 : ReplaceWithRuntimeCall(node, Runtime::kCreateArrayLiteral);
451 : }
452 20605 : }
453 :
454 :
455 190148 : void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
456 220161 : CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
457 47537 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
458 47537 : node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
459 95074 : node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
460 47537 : node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
461 :
462 : // Use the FastCloneShallowObject builtin only for shallow boilerplates
463 : // without elements up to the number of properties that the stubs can handle.
464 62549 : if ((p.flags() & ObjectLiteral::kShallowProperties) != 0 &&
465 : p.length() <=
466 : ConstructorBuiltins::kMaximumClonedShallowObjectProperties) {
467 : Callable callable =
468 15001 : CodeFactory::FastCloneShallowObject(isolate(), p.length());
469 15001 : ReplaceWithStubCall(node, callable, flags);
470 : } else {
471 32536 : ReplaceWithRuntimeCall(node, Runtime::kCreateObjectLiteral);
472 : }
473 47537 : }
474 :
475 :
476 39500 : void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
477 29625 : CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
478 9875 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
479 9875 : Callable callable = CodeFactory::FastCloneRegExp(isolate());
480 : Node* literal_index = jsgraph()->SmiConstant(p.index());
481 : Node* literal_flags = jsgraph()->SmiConstant(p.flags());
482 9875 : Node* pattern = jsgraph()->HeapConstant(p.constant());
483 9875 : node->InsertInput(graph()->zone(), 1, literal_index);
484 9875 : node->InsertInput(graph()->zone(), 2, pattern);
485 9875 : node->InsertInput(graph()->zone(), 3, literal_flags);
486 9875 : ReplaceWithStubCall(node, callable, flags);
487 9875 : }
488 :
489 :
490 0 : void JSGenericLowering::LowerJSCreateCatchContext(Node* node) {
491 : const CreateCatchContextParameters& parameters =
492 0 : CreateCatchContextParametersOf(node->op());
493 : node->InsertInput(zone(), 0,
494 0 : jsgraph()->HeapConstant(parameters.catch_name()));
495 : node->InsertInput(zone(), 2,
496 0 : jsgraph()->HeapConstant(parameters.scope_info()));
497 0 : ReplaceWithRuntimeCall(node, Runtime::kPushCatchContext);
498 0 : }
499 :
500 0 : void JSGenericLowering::LowerJSCreateWithContext(Node* node) {
501 0 : Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
502 0 : node->InsertInput(zone(), 1, jsgraph()->HeapConstant(scope_info));
503 0 : ReplaceWithRuntimeCall(node, Runtime::kPushWithContext);
504 0 : }
505 :
506 0 : void JSGenericLowering::LowerJSCreateBlockContext(Node* node) {
507 0 : Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
508 0 : node->InsertInput(zone(), 0, jsgraph()->HeapConstant(scope_info));
509 0 : ReplaceWithRuntimeCall(node, Runtime::kPushBlockContext);
510 0 : }
511 :
512 :
513 0 : void JSGenericLowering::LowerJSCreateScriptContext(Node* node) {
514 0 : Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
515 0 : node->InsertInput(zone(), 1, jsgraph()->HeapConstant(scope_info));
516 0 : ReplaceWithRuntimeCall(node, Runtime::kNewScriptContext);
517 0 : }
518 :
519 27048 : void JSGenericLowering::LowerJSConstruct(Node* node) {
520 6762 : ConstructParameters const& p = ConstructParametersOf(node->op());
521 6762 : int const arg_count = static_cast<int>(p.arity() - 2);
522 6762 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
523 6762 : Callable callable = CodeFactory::Construct(isolate());
524 : CallDescriptor* desc = Linkage::GetStubCallDescriptor(
525 20286 : isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
526 6762 : Node* stub_code = jsgraph()->HeapConstant(callable.code());
527 6762 : Node* stub_arity = jsgraph()->Int32Constant(arg_count);
528 : Node* new_target = node->InputAt(arg_count + 1);
529 6762 : Node* receiver = jsgraph()->UndefinedConstant();
530 6762 : node->RemoveInput(arg_count + 1); // Drop new target.
531 6762 : node->InsertInput(zone(), 0, stub_code);
532 6762 : node->InsertInput(zone(), 2, new_target);
533 6762 : node->InsertInput(zone(), 3, stub_arity);
534 6762 : node->InsertInput(zone(), 4, receiver);
535 6762 : NodeProperties::ChangeOp(node, common()->Call(desc));
536 6762 : }
537 :
538 988 : void JSGenericLowering::LowerJSConstructWithSpread(Node* node) {
539 247 : SpreadWithArityParameter const& p = SpreadWithArityParameterOf(node->op());
540 247 : int const arg_count = static_cast<int>(p.arity() - 2);
541 247 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
542 247 : Callable callable = CodeFactory::ConstructWithSpread(isolate());
543 : CallDescriptor* desc = Linkage::GetStubCallDescriptor(
544 741 : isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
545 247 : Node* stub_code = jsgraph()->HeapConstant(callable.code());
546 247 : Node* stub_arity = jsgraph()->Int32Constant(arg_count);
547 : Node* new_target = node->InputAt(arg_count + 1);
548 247 : Node* receiver = jsgraph()->UndefinedConstant();
549 247 : node->RemoveInput(arg_count + 1); // Drop new target.
550 247 : node->InsertInput(zone(), 0, stub_code);
551 247 : node->InsertInput(zone(), 2, new_target);
552 247 : node->InsertInput(zone(), 3, stub_arity);
553 247 : node->InsertInput(zone(), 4, receiver);
554 247 : NodeProperties::ChangeOp(node, common()->Call(desc));
555 247 : }
556 :
557 75 : void JSGenericLowering::LowerJSCallForwardVarargs(Node* node) {
558 25 : CallForwardVarargsParameters p = CallForwardVarargsParametersOf(node->op());
559 25 : Callable callable = CodeFactory::CallForwardVarargs(isolate());
560 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
561 25 : if (p.tail_call_mode() == TailCallMode::kAllow) {
562 : flags |= CallDescriptor::kSupportsTailCalls;
563 : }
564 : CallDescriptor* desc = Linkage::GetStubCallDescriptor(
565 50 : isolate(), zone(), callable.descriptor(), 1, flags);
566 25 : Node* stub_code = jsgraph()->HeapConstant(callable.code());
567 : Node* start_index = jsgraph()->Uint32Constant(p.start_index());
568 25 : node->InsertInput(zone(), 0, stub_code);
569 25 : node->InsertInput(zone(), 2, start_index);
570 25 : NodeProperties::ChangeOp(node, common()->Call(desc));
571 25 : }
572 :
573 55671 : void JSGenericLowering::LowerJSCall(Node* node) {
574 37114 : CallParameters const& p = CallParametersOf(node->op());
575 18557 : int const arg_count = static_cast<int>(p.arity() - 2);
576 : ConvertReceiverMode const mode = p.convert_mode();
577 18557 : Callable callable = CodeFactory::Call(isolate(), mode);
578 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
579 18557 : if (p.tail_call_mode() == TailCallMode::kAllow) {
580 : flags |= CallDescriptor::kSupportsTailCalls;
581 : }
582 : CallDescriptor* desc = Linkage::GetStubCallDescriptor(
583 55671 : isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
584 18557 : Node* stub_code = jsgraph()->HeapConstant(callable.code());
585 18557 : Node* stub_arity = jsgraph()->Int32Constant(arg_count);
586 18557 : node->InsertInput(zone(), 0, stub_code);
587 18557 : node->InsertInput(zone(), 2, stub_arity);
588 18557 : NodeProperties::ChangeOp(node, common()->Call(desc));
589 18557 : }
590 :
591 525 : void JSGenericLowering::LowerJSCallWithSpread(Node* node) {
592 175 : SpreadWithArityParameter const& p = SpreadWithArityParameterOf(node->op());
593 175 : int const arg_count = static_cast<int>(p.arity() - 2);
594 175 : Callable callable = CodeFactory::CallWithSpread(isolate());
595 175 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
596 : CallDescriptor* desc = Linkage::GetStubCallDescriptor(
597 525 : isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
598 175 : Node* stub_code = jsgraph()->HeapConstant(callable.code());
599 175 : Node* stub_arity = jsgraph()->Int32Constant(arg_count);
600 175 : node->InsertInput(zone(), 0, stub_code);
601 175 : node->InsertInput(zone(), 2, stub_arity);
602 175 : NodeProperties::ChangeOp(node, common()->Call(desc));
603 175 : }
604 :
605 335651 : void JSGenericLowering::LowerJSCallRuntime(Node* node) {
606 671302 : const CallRuntimeParameters& p = CallRuntimeParametersOf(node->op());
607 671302 : ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity()));
608 335651 : }
609 :
610 0 : void JSGenericLowering::LowerJSConvertReceiver(Node* node) {
611 0 : ReplaceWithRuntimeCall(node, Runtime::kConvertReceiver);
612 0 : }
613 :
614 0 : void JSGenericLowering::LowerJSForInNext(Node* node) {
615 0 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
616 0 : Callable callable = CodeFactory::ForInNext(isolate());
617 0 : ReplaceWithStubCall(node, callable, flags);
618 0 : }
619 :
620 2598 : void JSGenericLowering::LowerJSForInPrepare(Node* node) {
621 1299 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
622 1299 : Callable callable = CodeFactory::ForInPrepare(isolate());
623 1299 : ReplaceWithStubCall(node, callable, flags, node->op()->properties(), 3);
624 1299 : }
625 :
626 0 : void JSGenericLowering::LowerJSLoadMessage(Node* node) {
627 0 : UNREACHABLE(); // Eliminated in typed lowering.
628 : }
629 :
630 :
631 0 : void JSGenericLowering::LowerJSStoreMessage(Node* node) {
632 0 : UNREACHABLE(); // Eliminated in typed lowering.
633 : }
634 :
635 0 : void JSGenericLowering::LowerJSLoadModule(Node* node) {
636 0 : UNREACHABLE(); // Eliminated in typed lowering.
637 : }
638 :
639 0 : void JSGenericLowering::LowerJSStoreModule(Node* node) {
640 0 : UNREACHABLE(); // Eliminated in typed lowering.
641 : }
642 :
643 0 : void JSGenericLowering::LowerJSGeneratorStore(Node* node) {
644 0 : UNREACHABLE(); // Eliminated in typed lowering.
645 : }
646 :
647 0 : void JSGenericLowering::LowerJSGeneratorRestoreContinuation(Node* node) {
648 0 : UNREACHABLE(); // Eliminated in typed lowering.
649 : }
650 :
651 0 : void JSGenericLowering::LowerJSGeneratorRestoreRegister(Node* node) {
652 0 : UNREACHABLE(); // Eliminated in typed lowering.
653 : }
654 :
655 1407328 : void JSGenericLowering::LowerJSStackCheck(Node* node) {
656 469109 : Node* effect = NodeProperties::GetEffectInput(node);
657 469110 : Node* control = NodeProperties::GetControlInput(node);
658 :
659 : Node* limit = graph()->NewNode(
660 : machine()->Load(MachineType::Pointer()),
661 : jsgraph()->ExternalConstant(
662 : ExternalReference::address_of_stack_limit(isolate())),
663 1876439 : jsgraph()->IntPtrConstant(0), effect, control);
664 469110 : Node* pointer = graph()->NewNode(machine()->LoadStackPointer());
665 :
666 469110 : Node* check = graph()->NewNode(machine()->UintLessThan(), limit, pointer);
667 : Node* branch =
668 469109 : graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
669 :
670 469109 : Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
671 : Node* etrue = effect;
672 :
673 469110 : Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
674 469110 : NodeProperties::ReplaceControlInput(node, if_false);
675 : Node* efalse = if_false = node;
676 :
677 469110 : Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
678 469110 : Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
679 :
680 : // Wire the new diamond into the graph, {node} can still throw.
681 469110 : NodeProperties::ReplaceUses(node, node, ephi, merge, merge);
682 469110 : NodeProperties::ReplaceControlInput(merge, if_false, 1);
683 469108 : NodeProperties::ReplaceEffectInput(ephi, efalse, 1);
684 :
685 : // This iteration cuts out potential {IfSuccess} or {IfException} projection
686 : // uses of the original node and places them inside the diamond, so that we
687 : // can change the original {node} into the slow-path runtime call.
688 3301405 : for (Edge edge : merge->use_edges()) {
689 1416148 : if (!NodeProperties::IsControlEdge(edge)) continue;
690 4248447 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
691 10813 : NodeProperties::ReplaceUses(edge.from(), nullptr, nullptr, merge);
692 21626 : NodeProperties::ReplaceControlInput(merge, edge.from(), 1);
693 10813 : edge.UpdateTo(node);
694 : }
695 4248450 : if (edge.from()->opcode() == IrOpcode::kIfException) {
696 10813 : NodeProperties::ReplaceEffectInput(edge.from(), node);
697 10813 : edge.UpdateTo(node);
698 : }
699 : }
700 :
701 : // Turn the stack check into a runtime call.
702 469109 : ReplaceWithRuntimeCall(node, Runtime::kStackGuard);
703 469109 : }
704 :
705 1080 : void JSGenericLowering::LowerJSDebugger(Node* node) {
706 1080 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
707 1080 : Callable callable = CodeFactory::HandleDebuggerStatement(isolate());
708 1080 : ReplaceWithStubCall(node, callable, flags);
709 1080 : }
710 :
711 8257449 : Zone* JSGenericLowering::zone() const { return graph()->zone(); }
712 :
713 :
714 3863434 : Isolate* JSGenericLowering::isolate() const { return jsgraph()->isolate(); }
715 :
716 :
717 12075619 : Graph* JSGenericLowering::graph() const { return jsgraph()->graph(); }
718 :
719 :
720 4489750 : CommonOperatorBuilder* JSGenericLowering::common() const {
721 4489750 : return jsgraph()->common();
722 : }
723 :
724 :
725 1443004 : MachineOperatorBuilder* JSGenericLowering::machine() const {
726 1443004 : return jsgraph()->machine();
727 : }
728 :
729 : } // namespace compiler
730 : } // namespace internal
731 : } // namespace v8
|