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 2033470 : CallDescriptor::Flags FrameStateFlagForCall(Node* node) {
26 2033470 : return OperatorProperties::HasFrameStateInput(node->op())
27 : ? CallDescriptor::kNeedsFrameState
28 2033474 : : CallDescriptor::kNoFlags;
29 : }
30 :
31 : } // namespace
32 :
33 789184 : JSGenericLowering::JSGenericLowering(JSGraph* jsgraph) : jsgraph_(jsgraph) {}
34 :
35 789184 : JSGenericLowering::~JSGenericLowering() {}
36 :
37 :
38 38936358 : Reduction JSGenericLowering::Reduce(Node* node) {
39 38936358 : switch (node->opcode()) {
40 : #define DECLARE_CASE(x) \
41 : case IrOpcode::k##x: \
42 : Lower##x(node); \
43 : break;
44 30821 : 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 117532 : REPLACE_STUB_CALL(Add)
60 59344 : REPLACE_STUB_CALL(Subtract)
61 72816 : REPLACE_STUB_CALL(Multiply)
62 49712 : REPLACE_STUB_CALL(Divide)
63 2148 : REPLACE_STUB_CALL(Modulus)
64 7920 : REPLACE_STUB_CALL(BitwiseAnd)
65 6520 : REPLACE_STUB_CALL(BitwiseOr)
66 3672 : REPLACE_STUB_CALL(BitwiseXor)
67 5500 : REPLACE_STUB_CALL(ShiftLeft)
68 2224 : REPLACE_STUB_CALL(ShiftRight)
69 1368 : REPLACE_STUB_CALL(ShiftRightLogical)
70 93704 : REPLACE_STUB_CALL(LessThan)
71 4944 : REPLACE_STUB_CALL(LessThanOrEqual)
72 24540 : REPLACE_STUB_CALL(GreaterThan)
73 12280 : REPLACE_STUB_CALL(GreaterThanOrEqual)
74 19264 : REPLACE_STUB_CALL(HasProperty)
75 40872 : REPLACE_STUB_CALL(Equal)
76 1076 : REPLACE_STUB_CALL(ToInteger)
77 928 : REPLACE_STUB_CALL(ToLength)
78 9512 : REPLACE_STUB_CALL(ToNumber)
79 5484 : REPLACE_STUB_CALL(ToName)
80 188 : REPLACE_STUB_CALL(ToObject)
81 10376 : REPLACE_STUB_CALL(ToString)
82 : #undef REPLACE_STUB_CALL
83 :
84 1070749 : void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
85 : CallDescriptor::Flags flags) {
86 1070749 : ReplaceWithStubCall(node, callable, flags, node->op()->properties());
87 1070748 : }
88 :
89 1222776 : void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
90 : CallDescriptor::Flags flags,
91 : Operator::Properties properties,
92 1222776 : int result_size) {
93 : const CallInterfaceDescriptor& descriptor = callable.descriptor();
94 : CallDescriptor* desc = Linkage::GetStubCallDescriptor(
95 : isolate(), zone(), descriptor, descriptor.GetStackParameterCount(), flags,
96 2445552 : properties, MachineType::AnyTagged(), result_size);
97 1222776 : Node* stub_code = jsgraph()->HeapConstant(callable.code());
98 1222775 : node->InsertInput(zone(), 0, stub_code);
99 1222775 : NodeProperties::ChangeOp(node, common()->Call(desc));
100 1222775 : }
101 :
102 :
103 1787284 : void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
104 : Runtime::FunctionId f,
105 2680936 : int nargs_override) {
106 893644 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
107 893644 : Operator::Properties properties = node->op()->properties();
108 893644 : const Runtime::Function* fun = Runtime::FunctionForId(f);
109 893641 : int nargs = (nargs_override < 0) ? fun->nargs : nargs_override;
110 : CallDescriptor* desc =
111 893641 : Linkage::GetRuntimeCallDescriptor(zone(), f, nargs, properties, flags);
112 1787288 : Node* ref = jsgraph()->ExternalConstant(ExternalReference(f, isolate()));
113 893646 : Node* arity = jsgraph()->Int32Constant(nargs);
114 2680934 : node->InsertInput(zone(), 0, jsgraph()->CEntryStubConstant(fun->result_size));
115 1787290 : node->InsertInput(zone(), nargs + 1, ref);
116 1787292 : node->InsertInput(zone(), nargs + 2, arity);
117 893643 : NodeProperties::ChangeOp(node, common()->Call(desc));
118 893646 : }
119 :
120 127954 : void JSGenericLowering::LowerJSStrictEqual(Node* node) {
121 : // The === operator doesn't need the current context.
122 127954 : NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
123 127954 : Callable callable = CodeFactory::StrictEqual(isolate());
124 127954 : node->RemoveInput(4); // control
125 : ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags,
126 127954 : Operator::kEliminatable);
127 127954 : }
128 :
129 1368 : void JSGenericLowering::LowerJSToBoolean(Node* node) {
130 : // The ToBoolean conversion doesn't need the current context.
131 1368 : NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
132 1368 : Callable callable = CodeFactory::ToBoolean(isolate());
133 2736 : node->AppendInput(zone(), graph()->start());
134 : ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
135 1368 : Operator::kEliminatable);
136 1368 : }
137 :
138 2822 : void JSGenericLowering::LowerJSClassOf(Node* node) {
139 : // The %_ClassOf intrinsic doesn't need the current context.
140 2822 : NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
141 2822 : Callable callable = CodeFactory::ClassOf(isolate());
142 5644 : node->AppendInput(zone(), graph()->start());
143 : ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
144 2822 : Operator::kEliminatable);
145 2822 : }
146 :
147 18586 : void JSGenericLowering::LowerJSTypeOf(Node* node) {
148 : // The typeof operator doesn't need the current context.
149 18586 : NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
150 18586 : Callable callable = CodeFactory::Typeof(isolate());
151 37172 : node->AppendInput(zone(), graph()->start());
152 : ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
153 : Operator::kEliminatable);
154 18586 : }
155 :
156 :
157 221896 : void JSGenericLowering::LowerJSLoadProperty(Node* node) {
158 73407 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
159 73407 : const PropertyAccess& p = PropertyAccessOf(node->op());
160 73407 : Node* frame_state = NodeProperties::GetFrameStateInput(node);
161 73407 : Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
162 146814 : node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
163 73407 : if (outer_state->opcode() != IrOpcode::kFrameState) {
164 71732 : Callable callable = CodeFactory::KeyedLoadIC(isolate());
165 71732 : ReplaceWithStubCall(node, callable, flags);
166 : } else {
167 1675 : Callable callable = CodeFactory::KeyedLoadICInOptimizedCode(isolate());
168 1675 : Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
169 1675 : node->InsertInput(zone(), 3, vector);
170 1675 : ReplaceWithStubCall(node, callable, flags);
171 : }
172 73407 : }
173 :
174 :
175 1561585 : void JSGenericLowering::LowerJSLoadNamed(Node* node) {
176 390009 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
177 390009 : NamedAccess const& p = NamedAccessOf(node->op());
178 390009 : Node* frame_state = NodeProperties::GetFrameStateInput(node);
179 390009 : Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
180 780018 : node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
181 780018 : node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
182 390009 : if (outer_state->opcode() != IrOpcode::kFrameState) {
183 388460 : Callable callable = CodeFactory::LoadIC(isolate());
184 388460 : ReplaceWithStubCall(node, callable, flags);
185 : } else {
186 1549 : Callable callable = CodeFactory::LoadICInOptimizedCode(isolate());
187 1549 : Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
188 1549 : node->InsertInput(zone(), 3, vector);
189 1549 : ReplaceWithStubCall(node, callable, flags);
190 : }
191 390009 : }
192 :
193 :
194 385236 : void JSGenericLowering::LowerJSLoadGlobal(Node* node) {
195 96302 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
196 192604 : const LoadGlobalParameters& p = LoadGlobalParametersOf(node->op());
197 96302 : Node* frame_state = NodeProperties::GetFrameStateInput(node);
198 96302 : Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
199 192604 : node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.name()));
200 192604 : node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.feedback().index()));
201 96302 : if (outer_state->opcode() != IrOpcode::kFrameState) {
202 96274 : Callable callable = CodeFactory::LoadGlobalIC(isolate(), p.typeof_mode());
203 96274 : 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 96302 : }
212 :
213 107703 : void JSGenericLowering::LowerJSStoreProperty(Node* node) {
214 35746 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
215 71492 : PropertyAccess const& p = PropertyAccessOf(node->op());
216 35746 : Node* frame_state = NodeProperties::GetFrameStateInput(node);
217 35746 : Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
218 71492 : node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
219 35746 : if (outer_state->opcode() != IrOpcode::kFrameState) {
220 35281 : Callable callable = CodeFactory::KeyedStoreIC(isolate(), p.language_mode());
221 35281 : ReplaceWithStubCall(node, callable, flags);
222 : } else {
223 : Callable callable =
224 465 : CodeFactory::KeyedStoreICInOptimizedCode(isolate(), p.language_mode());
225 465 : Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
226 465 : node->InsertInput(zone(), 4, vector);
227 465 : ReplaceWithStubCall(node, callable, flags);
228 : }
229 35746 : }
230 :
231 241062 : void JSGenericLowering::LowerJSStoreNamed(Node* node) {
232 60260 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
233 120520 : NamedAccess const& p = NamedAccessOf(node->op());
234 60260 : Node* frame_state = NodeProperties::GetFrameStateInput(node);
235 60260 : Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
236 120520 : node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
237 120520 : node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
238 60260 : if (outer_state->opcode() != IrOpcode::kFrameState) {
239 60238 : Callable callable = CodeFactory::StoreIC(isolate(), p.language_mode());
240 60238 : ReplaceWithStubCall(node, callable, flags);
241 : } else {
242 : Callable callable =
243 22 : CodeFactory::StoreICInOptimizedCode(isolate(), p.language_mode());
244 22 : Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
245 22 : node->InsertInput(zone(), 4, vector);
246 22 : ReplaceWithStubCall(node, callable, flags);
247 : }
248 60260 : }
249 :
250 137690 : void JSGenericLowering::LowerJSStoreNamedOwn(Node* node) {
251 34402 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
252 34402 : StoreNamedOwnParameters const& p = StoreNamedOwnParametersOf(node->op());
253 34402 : Node* frame_state = NodeProperties::GetFrameStateInput(node);
254 34402 : Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
255 68804 : node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
256 68804 : node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
257 34402 : if (outer_state->opcode() != IrOpcode::kFrameState) {
258 34320 : Callable callable = CodeFactory::StoreOwnIC(isolate());
259 34320 : 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 34402 : }
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 2144 : void JSGenericLowering::LowerJSDeleteProperty(Node* node) {
312 2144 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
313 : Callable callable =
314 2144 : Builtins::CallableFor(isolate(), Builtins::kDeleteProperty);
315 2144 : ReplaceWithStubCall(node, callable, flags);
316 2144 : }
317 :
318 70 : void JSGenericLowering::LowerJSGetSuperConstructor(Node* node) {
319 70 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
320 70 : Callable callable = CodeFactory::GetSuperConstructor(isolate());
321 70 : ReplaceWithStubCall(node, callable, flags);
322 70 : }
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 57 : void JSGenericLowering::LowerJSCreate(Node* node) {
347 57 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
348 57 : Callable callable = CodeFactory::FastNewObject(isolate());
349 57 : ReplaceWithStubCall(node, callable, flags);
350 57 : }
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 6418 : void JSGenericLowering::LowerJSCreateArray(Node* node) {
370 3209 : CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
371 3209 : 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 6418 : : jsgraph()->HeapConstant(site);
376 3209 : node->RemoveInput(1);
377 6418 : node->InsertInput(zone(), 1 + arity, new_target);
378 6418 : node->InsertInput(zone(), 2 + arity, type_info);
379 3209 : ReplaceWithRuntimeCall(node, Runtime::kNewArray, arity + 3);
380 3209 : }
381 :
382 :
383 736020 : void JSGenericLowering::LowerJSCreateClosure(Node* node) {
384 376572 : CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
385 184005 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
386 : Handle<SharedFunctionInfo> const shared_info = p.shared_info();
387 368010 : node->InsertInput(zone(), 0, jsgraph()->HeapConstant(shared_info));
388 :
389 : // Use the FastNewClosurebuiltin only for functions allocated in new
390 : // space.
391 184005 : if (p.pretenure() == NOT_TENURED) {
392 175443 : Callable callable = CodeFactory::FastNewClosure(isolate());
393 : node->InsertInput(zone(), 1,
394 350886 : jsgraph()->HeapConstant(p.feedback().vector()));
395 350886 : node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
396 175443 : ReplaceWithStubCall(node, callable, flags);
397 : } else {
398 : node->InsertInput(zone(), 1,
399 17124 : jsgraph()->HeapConstant(p.feedback().vector()));
400 17124 : node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
401 : ReplaceWithRuntimeCall(node, (p.pretenure() == TENURED)
402 : ? Runtime::kNewClosure_Tenured
403 8562 : : Runtime::kNewClosure);
404 : }
405 184005 : }
406 :
407 :
408 844 : void JSGenericLowering::LowerJSCreateFunctionContext(Node* node) {
409 422 : const CreateFunctionContextParameters& parameters =
410 422 : CreateFunctionContextParametersOf(node->op());
411 : int slot_count = parameters.slot_count();
412 : ScopeType scope_type = parameters.scope_type();
413 422 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
414 :
415 422 : if (slot_count <= ConstructorBuiltins::MaximumFunctionContextSlots()) {
416 : Callable callable =
417 844 : CodeFactory::FastNewFunctionContext(isolate(), scope_type);
418 844 : node->InsertInput(zone(), 1, jsgraph()->Int32Constant(slot_count));
419 422 : ReplaceWithStubCall(node, callable, flags);
420 : } else {
421 0 : node->InsertInput(zone(), 1, jsgraph()->SmiConstant(scope_type));
422 0 : ReplaceWithRuntimeCall(node, Runtime::kNewFunctionContext);
423 : }
424 422 : }
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 62690 : void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
436 81556 : CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
437 20603 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
438 20603 : node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
439 41206 : 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 40350 : if ((p.flags() & ArrayLiteral::kShallowElements) != 0 &&
444 : p.length() < ConstructorBuiltins::kMaximumClonedShallowArrayElements) {
445 : Callable callable = CodeFactory::FastCloneShallowArray(
446 19722 : isolate(), DONT_TRACK_ALLOCATION_SITE);
447 19722 : ReplaceWithStubCall(node, callable, flags);
448 : } else {
449 881 : node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
450 881 : ReplaceWithRuntimeCall(node, Runtime::kCreateArrayLiteral);
451 : }
452 20603 : }
453 :
454 :
455 190032 : void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
456 220035 : CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
457 47508 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
458 47508 : node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
459 95016 : node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
460 47508 : 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 62515 : if ((p.flags() & ObjectLiteral::kShallowProperties) != 0 &&
465 : p.length() <=
466 : ConstructorBuiltins::kMaximumClonedShallowObjectProperties) {
467 : Callable callable =
468 14996 : CodeFactory::FastCloneShallowObject(isolate(), p.length());
469 14996 : ReplaceWithStubCall(node, callable, flags);
470 : } else {
471 32512 : ReplaceWithRuntimeCall(node, Runtime::kCreateObjectLiteral);
472 : }
473 47508 : }
474 :
475 :
476 39472 : void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
477 29604 : CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
478 9868 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
479 9868 : Callable callable = CodeFactory::FastCloneRegExp(isolate());
480 : Node* literal_index = jsgraph()->SmiConstant(p.index());
481 : Node* literal_flags = jsgraph()->SmiConstant(p.flags());
482 9868 : Node* pattern = jsgraph()->HeapConstant(p.constant());
483 9868 : node->InsertInput(graph()->zone(), 1, literal_index);
484 9868 : node->InsertInput(graph()->zone(), 2, pattern);
485 9868 : node->InsertInput(graph()->zone(), 3, literal_flags);
486 9868 : ReplaceWithStubCall(node, callable, flags);
487 9868 : }
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 27132 : void JSGenericLowering::LowerJSConstruct(Node* node) {
520 6783 : ConstructParameters const& p = ConstructParametersOf(node->op());
521 6783 : int const arg_count = static_cast<int>(p.arity() - 2);
522 6783 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
523 6783 : Callable callable = CodeFactory::Construct(isolate());
524 : CallDescriptor* desc = Linkage::GetStubCallDescriptor(
525 20349 : isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
526 6783 : Node* stub_code = jsgraph()->HeapConstant(callable.code());
527 6783 : Node* stub_arity = jsgraph()->Int32Constant(arg_count);
528 : Node* new_target = node->InputAt(arg_count + 1);
529 6783 : Node* receiver = jsgraph()->UndefinedConstant();
530 6783 : node->RemoveInput(arg_count + 1); // Drop new target.
531 6783 : node->InsertInput(zone(), 0, stub_code);
532 6783 : node->InsertInput(zone(), 2, new_target);
533 6783 : node->InsertInput(zone(), 3, stub_arity);
534 6783 : node->InsertInput(zone(), 4, receiver);
535 6783 : NodeProperties::ChangeOp(node, common()->Call(desc));
536 6783 : }
537 :
538 956 : void JSGenericLowering::LowerJSConstructWithSpread(Node* node) {
539 239 : SpreadWithArityParameter const& p = SpreadWithArityParameterOf(node->op());
540 239 : int const arg_count = static_cast<int>(p.arity() - 2);
541 239 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
542 239 : Callable callable = CodeFactory::ConstructWithSpread(isolate());
543 : CallDescriptor* desc = Linkage::GetStubCallDescriptor(
544 717 : isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
545 239 : Node* stub_code = jsgraph()->HeapConstant(callable.code());
546 239 : Node* stub_arity = jsgraph()->Int32Constant(arg_count);
547 : Node* new_target = node->InputAt(arg_count + 1);
548 239 : Node* receiver = jsgraph()->UndefinedConstant();
549 239 : node->RemoveInput(arg_count + 1); // Drop new target.
550 239 : node->InsertInput(zone(), 0, stub_code);
551 239 : node->InsertInput(zone(), 2, new_target);
552 239 : node->InsertInput(zone(), 3, stub_arity);
553 239 : node->InsertInput(zone(), 4, receiver);
554 239 : NodeProperties::ChangeOp(node, common()->Call(desc));
555 239 : }
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 55821 : void JSGenericLowering::LowerJSCall(Node* node) {
574 37214 : CallParameters const& p = CallParametersOf(node->op());
575 18607 : int const arg_count = static_cast<int>(p.arity() - 2);
576 : ConvertReceiverMode const mode = p.convert_mode();
577 18607 : Callable callable = CodeFactory::Call(isolate(), mode);
578 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
579 18607 : if (p.tail_call_mode() == TailCallMode::kAllow) {
580 : flags |= CallDescriptor::kSupportsTailCalls;
581 : }
582 : CallDescriptor* desc = Linkage::GetStubCallDescriptor(
583 55821 : isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
584 18607 : Node* stub_code = jsgraph()->HeapConstant(callable.code());
585 18607 : Node* stub_arity = jsgraph()->Int32Constant(arg_count);
586 18607 : node->InsertInput(zone(), 0, stub_code);
587 18607 : node->InsertInput(zone(), 2, stub_arity);
588 18607 : NodeProperties::ChangeOp(node, common()->Call(desc));
589 18607 : }
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 335953 : void JSGenericLowering::LowerJSCallRuntime(Node* node) {
606 671906 : const CallRuntimeParameters& p = CallRuntimeParametersOf(node->op());
607 671906 : ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity()));
608 335953 : }
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 2594 : void JSGenericLowering::LowerJSForInPrepare(Node* node) {
621 1297 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
622 1297 : Callable callable = CodeFactory::ForInPrepare(isolate());
623 1297 : ReplaceWithStubCall(node, callable, flags, node->op()->properties(), 3);
624 1297 : }
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 1405302 : void JSGenericLowering::LowerJSStackCheck(Node* node) {
656 468433 : Node* effect = NodeProperties::GetEffectInput(node);
657 468436 : 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 1873739 : jsgraph()->IntPtrConstant(0), effect, control);
664 468436 : Node* pointer = graph()->NewNode(machine()->LoadStackPointer());
665 :
666 468435 : Node* check = graph()->NewNode(machine()->UintLessThan(), limit, pointer);
667 : Node* branch =
668 468436 : graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
669 :
670 468436 : Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
671 : Node* etrue = effect;
672 :
673 468435 : Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
674 468436 : NodeProperties::ReplaceControlInput(node, if_false);
675 : Node* efalse = if_false = node;
676 :
677 468435 : Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
678 468435 : Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
679 :
680 : // Wire the new diamond into the graph, {node} can still throw.
681 468435 : NodeProperties::ReplaceUses(node, node, ephi, merge, merge);
682 468435 : NodeProperties::ReplaceControlInput(merge, if_false, 1);
683 468434 : 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 3296229 : for (Edge edge : merge->use_edges()) {
689 1413897 : if (!NodeProperties::IsControlEdge(edge)) continue;
690 4241703 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
691 10885 : NodeProperties::ReplaceUses(edge.from(), nullptr, nullptr, merge);
692 21770 : NodeProperties::ReplaceControlInput(merge, edge.from(), 1);
693 10885 : edge.UpdateTo(node);
694 : }
695 4241700 : if (edge.from()->opcode() == IrOpcode::kIfException) {
696 10885 : NodeProperties::ReplaceEffectInput(edge.from(), node);
697 10885 : edge.UpdateTo(node);
698 : }
699 : }
700 :
701 : // Turn the stack check into a runtime call.
702 468435 : ReplaceWithRuntimeCall(node, Runtime::kStackGuard);
703 468435 : }
704 :
705 1071 : void JSGenericLowering::LowerJSDebugger(Node* node) {
706 1071 : CallDescriptor::Flags flags = FrameStateFlagForCall(node);
707 1071 : Callable callable = CodeFactory::HandleDebuggerStatement(isolate());
708 1071 : ReplaceWithStubCall(node, callable, flags);
709 1071 : }
710 :
711 8250427 : Zone* JSGenericLowering::zone() const { return graph()->zone(); }
712 :
713 :
714 3859289 : Isolate* JSGenericLowering::isolate() const { return jsgraph()->isolate(); }
715 :
716 :
717 12063178 : Graph* JSGenericLowering::graph() const { return jsgraph()->graph(); }
718 :
719 :
720 4484424 : CommonOperatorBuilder* JSGenericLowering::common() const {
721 4484424 : return jsgraph()->common();
722 : }
723 :
724 :
725 1440980 : MachineOperatorBuilder* JSGenericLowering::machine() const {
726 1440980 : return jsgraph()->machine();
727 : }
728 :
729 : } // namespace compiler
730 : } // namespace internal
731 : } // namespace v8
|