blob: 105298e392d329b2982a08990d3f59d69639b15f [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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/code-factory.h"
6#include "src/code-stubs.h"
7#include "src/compiler/common-operator.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/compiler/js-generic-lowering.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/compiler/js-graph.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/compiler/machine-operator.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040011#include "src/compiler/node-matchers.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012#include "src/compiler/node-properties.h"
13#include "src/compiler/operator-properties.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014
15namespace v8 {
16namespace internal {
17namespace compiler {
18
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019static CallDescriptor::Flags AdjustFrameStatesForCall(Node* node) {
20 int count = OperatorProperties::GetFrameStateInputCount(node->op());
21 if (count > 1) {
22 int index = NodeProperties::FirstFrameStateIndex(node) + 1;
23 do {
24 node->RemoveInput(index);
25 } while (--count > 1);
26 }
27 return count > 0 ? CallDescriptor::kNeedsFrameState
28 : CallDescriptor::kNoFlags;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029}
30
Ben Murdochc5610432016-08-08 18:44:38 +010031JSGenericLowering::JSGenericLowering(JSGraph* jsgraph) : jsgraph_(jsgraph) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032
33JSGenericLowering::~JSGenericLowering() {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034
35
Ben Murdochb8a8cc12014-11-26 15:28:44 +000036Reduction JSGenericLowering::Reduce(Node* node) {
37 switch (node->opcode()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040038#define DECLARE_CASE(x) \
39 case IrOpcode::k##x: \
40 Lower##x(node); \
41 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000042 JS_OP_LIST(DECLARE_CASE)
43#undef DECLARE_CASE
44 default:
45 // Nothing to see.
46 return NoChange();
47 }
48 return Changed(node);
49}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050#define REPLACE_RUNTIME_CALL(op, fun) \
51 void JSGenericLowering::Lower##op(Node* node) { \
52 ReplaceWithRuntimeCall(node, fun); \
53 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000054REPLACE_RUNTIME_CALL(JSCreateWithContext, Runtime::kPushWithContext)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000055REPLACE_RUNTIME_CALL(JSCreateModuleContext, Runtime::kPushModuleContext)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver)
Ben Murdoch097c5b22016-05-18 11:27:45 +010057#undef REPLACE_RUNTIME_CALL
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058
Ben Murdochda12d292016-06-02 14:46:10 +010059#define REPLACE_STUB_CALL(Name) \
60 void JSGenericLowering::LowerJS##Name(Node* node) { \
61 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node); \
62 Callable callable = CodeFactory::Name(isolate()); \
63 ReplaceWithStubCall(node, callable, flags); \
64 }
65REPLACE_STUB_CALL(Add)
66REPLACE_STUB_CALL(Subtract)
Ben Murdochc5610432016-08-08 18:44:38 +010067REPLACE_STUB_CALL(Multiply)
68REPLACE_STUB_CALL(Divide)
69REPLACE_STUB_CALL(Modulus)
Ben Murdochda12d292016-06-02 14:46:10 +010070REPLACE_STUB_CALL(BitwiseAnd)
71REPLACE_STUB_CALL(BitwiseOr)
72REPLACE_STUB_CALL(BitwiseXor)
Ben Murdochc5610432016-08-08 18:44:38 +010073REPLACE_STUB_CALL(ShiftLeft)
74REPLACE_STUB_CALL(ShiftRight)
75REPLACE_STUB_CALL(ShiftRightLogical)
Ben Murdochda12d292016-06-02 14:46:10 +010076REPLACE_STUB_CALL(LessThan)
77REPLACE_STUB_CALL(LessThanOrEqual)
78REPLACE_STUB_CALL(GreaterThan)
79REPLACE_STUB_CALL(GreaterThanOrEqual)
Ben Murdochc5610432016-08-08 18:44:38 +010080REPLACE_STUB_CALL(HasProperty)
Ben Murdochda12d292016-06-02 14:46:10 +010081REPLACE_STUB_CALL(Equal)
82REPLACE_STUB_CALL(NotEqual)
Ben Murdochda12d292016-06-02 14:46:10 +010083REPLACE_STUB_CALL(ToInteger)
84REPLACE_STUB_CALL(ToLength)
85REPLACE_STUB_CALL(ToNumber)
86REPLACE_STUB_CALL(ToName)
87REPLACE_STUB_CALL(ToObject)
88REPLACE_STUB_CALL(ToString)
89#undef REPLACE_STUB_CALL
90
Ben Murdochb8a8cc12014-11-26 15:28:44 +000091void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
92 CallDescriptor::Flags flags) {
Ben Murdochc5610432016-08-08 18:44:38 +010093 ReplaceWithStubCall(node, callable, flags, node->op()->properties());
94}
95
96void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
97 CallDescriptor::Flags flags,
98 Operator::Properties properties) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000099 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
100 isolate(), zone(), callable.descriptor(), 0, flags, properties);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400101 Node* stub_code = jsgraph()->HeapConstant(callable.code());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000102 node->InsertInput(zone(), 0, stub_code);
103 NodeProperties::ChangeOp(node, common()->Call(desc));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104}
105
106
107void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
108 Runtime::FunctionId f,
109 int nargs_override) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100110 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000111 Operator::Properties properties = node->op()->properties();
112 const Runtime::Function* fun = Runtime::FunctionForId(f);
113 int nargs = (nargs_override < 0) ? fun->nargs : nargs_override;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100114 CallDescriptor* desc =
115 Linkage::GetRuntimeCallDescriptor(zone(), f, nargs, properties, flags);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400116 Node* ref = jsgraph()->ExternalConstant(ExternalReference(f, isolate()));
117 Node* arity = jsgraph()->Int32Constant(nargs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000118 node->InsertInput(zone(), 0, jsgraph()->CEntryStubConstant(fun->result_size));
119 node->InsertInput(zone(), nargs + 1, ref);
120 node->InsertInput(zone(), nargs + 2, arity);
121 NodeProperties::ChangeOp(node, common()->Call(desc));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000122}
123
Ben Murdochc5610432016-08-08 18:44:38 +0100124void JSGenericLowering::LowerJSStrictEqual(Node* node) {
125 Callable callable = CodeFactory::StrictEqual(isolate());
126 node->AppendInput(zone(), graph()->start());
127 ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags,
128 Operator::kEliminatable);
129}
130
131void JSGenericLowering::LowerJSStrictNotEqual(Node* node) {
132 Callable callable = CodeFactory::StrictNotEqual(isolate());
133 node->AppendInput(zone(), graph()->start());
134 ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags,
135 Operator::kEliminatable);
136}
137
138void JSGenericLowering::LowerJSToBoolean(Node* node) {
139 Callable callable = CodeFactory::ToBoolean(isolate());
140 node->AppendInput(zone(), graph()->start());
141 ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
142 Operator::kEliminatable);
143}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000144
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145void JSGenericLowering::LowerJSTypeOf(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000146 Callable callable = CodeFactory::Typeof(isolate());
Ben Murdochc5610432016-08-08 18:44:38 +0100147 node->AppendInput(zone(), graph()->start());
148 ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
149 Operator::kEliminatable);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150}
151
152
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000153void JSGenericLowering::LowerJSLoadProperty(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100154 Node* closure = NodeProperties::GetValueInput(node, 2);
155 Node* effect = NodeProperties::GetEffectInput(node);
156 Node* control = NodeProperties::GetControlInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
158 const PropertyAccess& p = PropertyAccessOf(node->op());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100159 Callable callable =
160 CodeFactory::KeyedLoadICInOptimizedCode(isolate(), UNINITIALIZED);
161 // Load the type feedback vector from the closure.
162 Node* shared_info = effect = graph()->NewNode(
163 machine()->Load(MachineType::AnyTagged()), closure,
164 jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
165 kHeapObjectTag),
166 effect, control);
167 Node* vector = effect = graph()->NewNode(
168 machine()->Load(MachineType::AnyTagged()), shared_info,
169 jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
170 kHeapObjectTag),
171 effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172 node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100173 node->ReplaceInput(3, vector);
174 node->ReplaceInput(6, effect);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175 ReplaceWithStubCall(node, callable, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000176}
177
178
179void JSGenericLowering::LowerJSLoadNamed(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100180 Node* closure = NodeProperties::GetValueInput(node, 1);
181 Node* effect = NodeProperties::GetEffectInput(node);
182 Node* control = NodeProperties::GetControlInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000183 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
184 NamedAccess const& p = NamedAccessOf(node->op());
185 Callable callable = CodeFactory::LoadICInOptimizedCode(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100186 isolate(), NOT_INSIDE_TYPEOF, UNINITIALIZED);
187 // Load the type feedback vector from the closure.
188 Node* shared_info = effect = graph()->NewNode(
189 machine()->Load(MachineType::AnyTagged()), closure,
190 jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
191 kHeapObjectTag),
192 effect, control);
193 Node* vector = effect = graph()->NewNode(
194 machine()->Load(MachineType::AnyTagged()), shared_info,
195 jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
196 kHeapObjectTag),
197 effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
199 node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100200 node->ReplaceInput(3, vector);
201 node->ReplaceInput(6, effect);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000202 ReplaceWithStubCall(node, callable, flags);
203}
204
205
206void JSGenericLowering::LowerJSLoadGlobal(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100207 Node* closure = NodeProperties::GetValueInput(node, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208 Node* context = NodeProperties::GetContextInput(node);
209 Node* effect = NodeProperties::GetEffectInput(node);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100210 Node* control = NodeProperties::GetControlInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
212 const LoadGlobalParameters& p = LoadGlobalParametersOf(node->op());
213 Callable callable = CodeFactory::LoadICInOptimizedCode(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100214 isolate(), p.typeof_mode(), UNINITIALIZED);
215 // Load the type feedback vector from the closure.
216 Node* shared_info = effect = graph()->NewNode(
217 machine()->Load(MachineType::AnyTagged()), closure,
218 jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
219 kHeapObjectTag),
220 effect, control);
221 Node* vector = effect = graph()->NewNode(
222 machine()->Load(MachineType::AnyTagged()), shared_info,
223 jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
224 kHeapObjectTag),
225 effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000226 // Load global object from the context.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100227 Node* native_context = effect =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000228 graph()->NewNode(machine()->Load(MachineType::AnyTagged()), context,
229 jsgraph()->IntPtrConstant(
230 Context::SlotOffset(Context::NATIVE_CONTEXT_INDEX)),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100231 effect, control);
232 Node* global = effect = graph()->NewNode(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233 machine()->Load(MachineType::AnyTagged()), native_context,
234 jsgraph()->IntPtrConstant(Context::SlotOffset(Context::EXTENSION_INDEX)),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100235 effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000236 node->InsertInput(zone(), 0, global);
237 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
238 node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100239 node->ReplaceInput(3, vector);
240 node->ReplaceInput(6, effect);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000241 ReplaceWithStubCall(node, callable, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242}
243
244
245void JSGenericLowering::LowerJSStoreProperty(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100246 Node* closure = NodeProperties::GetValueInput(node, 3);
247 Node* effect = NodeProperties::GetEffectInput(node);
248 Node* control = NodeProperties::GetControlInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000249 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
250 PropertyAccess const& p = PropertyAccessOf(node->op());
251 LanguageMode language_mode = p.language_mode();
252 Callable callable = CodeFactory::KeyedStoreICInOptimizedCode(
253 isolate(), language_mode, UNINITIALIZED);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100254 // Load the type feedback vector from the closure.
255 Node* shared_info = effect = graph()->NewNode(
256 machine()->Load(MachineType::AnyTagged()), closure,
257 jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
258 kHeapObjectTag),
259 effect, control);
260 Node* vector = effect = graph()->NewNode(
261 machine()->Load(MachineType::AnyTagged()), shared_info,
262 jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
263 kHeapObjectTag),
264 effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000265 node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100266 node->ReplaceInput(4, vector);
267 node->ReplaceInput(7, effect);
268 ReplaceWithStubCall(node, callable, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269}
270
271
272void JSGenericLowering::LowerJSStoreNamed(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100273 Node* closure = NodeProperties::GetValueInput(node, 2);
274 Node* effect = NodeProperties::GetEffectInput(node);
275 Node* control = NodeProperties::GetControlInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000276 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
277 NamedAccess const& p = NamedAccessOf(node->op());
278 Callable callable = CodeFactory::StoreICInOptimizedCode(
279 isolate(), p.language_mode(), UNINITIALIZED);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100280 // Load the type feedback vector from the closure.
281 Node* shared_info = effect = graph()->NewNode(
282 machine()->Load(MachineType::AnyTagged()), closure,
283 jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
284 kHeapObjectTag),
285 effect, control);
286 Node* vector = effect = graph()->NewNode(
287 machine()->Load(MachineType::AnyTagged()), shared_info,
288 jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
289 kHeapObjectTag),
290 effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000291 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000292 node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100293 node->ReplaceInput(4, vector);
294 node->ReplaceInput(7, effect);
295 ReplaceWithStubCall(node, callable, flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000296}
297
298
299void JSGenericLowering::LowerJSStoreGlobal(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100300 Node* closure = NodeProperties::GetValueInput(node, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 Node* context = NodeProperties::GetContextInput(node);
302 Node* effect = NodeProperties::GetEffectInput(node);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100303 Node* control = NodeProperties::GetControlInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000304 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
305 const StoreGlobalParameters& p = StoreGlobalParametersOf(node->op());
306 Callable callable = CodeFactory::StoreICInOptimizedCode(
307 isolate(), p.language_mode(), UNINITIALIZED);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100308 // Load the type feedback vector from the closure.
309 Node* shared_info = effect = graph()->NewNode(
310 machine()->Load(MachineType::AnyTagged()), closure,
311 jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
312 kHeapObjectTag),
313 effect, control);
314 Node* vector = effect = graph()->NewNode(
315 machine()->Load(MachineType::AnyTagged()), shared_info,
316 jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
317 kHeapObjectTag),
318 effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000319 // Load global object from the context.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100320 Node* native_context = effect =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000321 graph()->NewNode(machine()->Load(MachineType::AnyTagged()), context,
322 jsgraph()->IntPtrConstant(
323 Context::SlotOffset(Context::NATIVE_CONTEXT_INDEX)),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100324 effect, control);
325 Node* global = effect = graph()->NewNode(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000326 machine()->Load(MachineType::AnyTagged()), native_context,
327 jsgraph()->IntPtrConstant(Context::SlotOffset(Context::EXTENSION_INDEX)),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100328 effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000329 node->InsertInput(zone(), 0, global);
330 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000331 node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100332 node->ReplaceInput(4, vector);
333 node->ReplaceInput(7, effect);
334 ReplaceWithStubCall(node, callable, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000335}
336
337
338void JSGenericLowering::LowerJSDeleteProperty(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000339 LanguageMode language_mode = OpParameter<LanguageMode>(node);
340 ReplaceWithRuntimeCall(node, is_strict(language_mode)
341 ? Runtime::kDeleteProperty_Strict
342 : Runtime::kDeleteProperty_Sloppy);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000343}
344
345
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000346void JSGenericLowering::LowerJSInstanceOf(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000347 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
348 Callable callable = CodeFactory::InstanceOf(isolate());
349 ReplaceWithStubCall(node, callable, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000350}
351
352
353void JSGenericLowering::LowerJSLoadContext(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400354 const ContextAccess& access = ContextAccessOf(node->op());
355 for (size_t i = 0; i < access.depth(); ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000356 node->ReplaceInput(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000357 0, graph()->NewNode(machine()->Load(MachineType::AnyTagged()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400358 NodeProperties::GetValueInput(node, 0),
359 jsgraph()->Int32Constant(
360 Context::SlotOffset(Context::PREVIOUS_INDEX)),
361 NodeProperties::GetEffectInput(node),
362 graph()->start()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000363 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400364 node->ReplaceInput(1, jsgraph()->Int32Constant(Context::SlotOffset(
365 static_cast<int>(access.index()))));
366 node->AppendInput(zone(), graph()->start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000367 NodeProperties::ChangeOp(node, machine()->Load(MachineType::AnyTagged()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000368}
369
370
371void JSGenericLowering::LowerJSStoreContext(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400372 const ContextAccess& access = ContextAccessOf(node->op());
373 for (size_t i = 0; i < access.depth(); ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000374 node->ReplaceInput(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000375 0, graph()->NewNode(machine()->Load(MachineType::AnyTagged()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400376 NodeProperties::GetValueInput(node, 0),
377 jsgraph()->Int32Constant(
378 Context::SlotOffset(Context::PREVIOUS_INDEX)),
379 NodeProperties::GetEffectInput(node),
380 graph()->start()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000381 }
382 node->ReplaceInput(2, NodeProperties::GetValueInput(node, 1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400383 node->ReplaceInput(1, jsgraph()->Int32Constant(Context::SlotOffset(
384 static_cast<int>(access.index()))));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000385 NodeProperties::ChangeOp(
386 node, machine()->Store(StoreRepresentation(MachineRepresentation::kTagged,
387 kFullWriteBarrier)));
388}
389
390
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000391void JSGenericLowering::LowerJSCreate(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100392 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
393 Callable callable = CodeFactory::FastNewObject(isolate());
394 ReplaceWithStubCall(node, callable, flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000395}
396
397
398void JSGenericLowering::LowerJSCreateArguments(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100399 CreateArgumentsType const type = CreateArgumentsTypeOf(node->op());
400 switch (type) {
401 case CreateArgumentsType::kMappedArguments:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000402 ReplaceWithRuntimeCall(node, Runtime::kNewSloppyArguments_Generic);
403 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100404 case CreateArgumentsType::kUnmappedArguments:
405 ReplaceWithRuntimeCall(node, Runtime::kNewStrictArguments);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000406 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100407 case CreateArgumentsType::kRestParameter:
408 ReplaceWithRuntimeCall(node, Runtime::kNewRestParameter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000409 break;
410 }
411}
412
413
414void JSGenericLowering::LowerJSCreateArray(Node* node) {
415 CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
416 int const arity = static_cast<int>(p.arity());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100417 Handle<AllocationSite> const site = p.site();
418
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000419 // TODO(turbofan): We embed the AllocationSite from the Operator at this
420 // point, which we should not do once we want to both consume the feedback
421 // but at the same time shared the optimized code across native contexts,
422 // as the AllocationSite is associated with a single native context (it's
423 // stored in the type feedback vector after all). Once we go for cross
424 // context code generation, we should somehow find a way to get to the
425 // allocation site for the actual native context at runtime.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100426 if (!site.is_null()) {
427 // Reduce {node} to the appropriate ArrayConstructorStub backend.
428 // Note that these stubs "behave" like JSFunctions, which means they
429 // expect a receiver on the stack, which they remove. We just push
430 // undefined for the receiver.
431 ElementsKind elements_kind = site->GetElementsKind();
432 AllocationSiteOverrideMode override_mode =
433 (AllocationSite::GetMode(elements_kind) == TRACK_ALLOCATION_SITE)
434 ? DISABLE_ALLOCATION_SITES
435 : DONT_OVERRIDE;
436 if (arity == 0) {
437 ArrayNoArgumentConstructorStub stub(isolate(), elements_kind,
438 override_mode);
439 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
440 isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 1,
441 CallDescriptor::kNeedsFrameState);
442 node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
443 node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site));
444 node->InsertInput(graph()->zone(), 3, jsgraph()->UndefinedConstant());
445 NodeProperties::ChangeOp(node, common()->Call(desc));
446 } else if (arity == 1) {
447 // TODO(bmeurer): Optimize for the 0 length non-holey case?
448 ArraySingleArgumentConstructorStub stub(
449 isolate(), GetHoleyElementsKind(elements_kind), override_mode);
450 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
451 isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 2,
452 CallDescriptor::kNeedsFrameState);
453 node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
454 node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site));
455 node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(1));
456 node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
457 NodeProperties::ChangeOp(node, common()->Call(desc));
458 } else {
459 ArrayNArgumentsConstructorStub stub(isolate(), elements_kind,
460 override_mode);
461 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
462 isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(),
463 arity + 1, CallDescriptor::kNeedsFrameState);
464 node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
465 node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site));
466 node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(arity));
467 node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
468 NodeProperties::ChangeOp(node, common()->Call(desc));
469 }
470 } else {
471 Node* new_target = node->InputAt(1);
472 Node* type_info = site.is_null() ? jsgraph()->UndefinedConstant()
473 : jsgraph()->HeapConstant(site);
474 node->RemoveInput(1);
475 node->InsertInput(zone(), 1 + arity, new_target);
476 node->InsertInput(zone(), 2 + arity, type_info);
477 ReplaceWithRuntimeCall(node, Runtime::kNewArray, arity + 3);
478 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000479}
480
481
482void JSGenericLowering::LowerJSCreateClosure(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100483 CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
484 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
485 Handle<SharedFunctionInfo> const shared_info = p.shared_info();
486 node->InsertInput(zone(), 0, jsgraph()->HeapConstant(shared_info));
487
488 // Use the FastNewClosureStub that allocates in new space only for nested
489 // functions that don't need literals cloning.
490 if (p.pretenure() == NOT_TENURED && shared_info->num_literals() == 0) {
491 Callable callable = CodeFactory::FastNewClosure(
492 isolate(), shared_info->language_mode(), shared_info->kind());
493 ReplaceWithStubCall(node, callable, flags);
494 } else {
495 ReplaceWithRuntimeCall(node, (p.pretenure() == TENURED)
496 ? Runtime::kNewClosure_Tenured
497 : Runtime::kNewClosure);
498 }
499}
500
501
502void JSGenericLowering::LowerJSCreateFunctionContext(Node* node) {
503 int const slot_count = OpParameter<int>(node->op());
504 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
505
506 // Use the FastNewContextStub only for function contexts up maximum size.
507 if (slot_count <= FastNewContextStub::kMaximumSlots) {
508 Callable callable = CodeFactory::FastNewContext(isolate(), slot_count);
509 ReplaceWithStubCall(node, callable, flags);
510 } else {
511 ReplaceWithRuntimeCall(node, Runtime::kNewFunctionContext);
512 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000513}
514
515
516void JSGenericLowering::LowerJSCreateIterResultObject(Node* node) {
517 ReplaceWithRuntimeCall(node, Runtime::kCreateIterResultObject);
518}
519
520
521void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
522 CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100523 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000524 node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
525 node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100526
527 // Use the FastCloneShallowArrayStub only for shallow boilerplates up to the
528 // initial length limit for arrays with "fast" elements kind.
529 if ((p.flags() & ArrayLiteral::kShallowElements) != 0 &&
Ben Murdochda12d292016-06-02 14:46:10 +0100530 p.length() < JSArray::kInitialMaxFastElementArray) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100531 Callable callable = CodeFactory::FastCloneShallowArray(isolate());
532 ReplaceWithStubCall(node, callable, flags);
533 } else {
534 node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
535 ReplaceWithRuntimeCall(node, Runtime::kCreateArrayLiteral);
536 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000537}
538
539
540void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
541 CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100542 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000543 node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
544 node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
545 node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100546
547 // Use the FastCloneShallowObjectStub only for shallow boilerplates without
548 // elements up to the number of properties that the stubs can handle.
549 if ((p.flags() & ObjectLiteral::kShallowProperties) != 0 &&
Ben Murdochda12d292016-06-02 14:46:10 +0100550 p.length() <= FastCloneShallowObjectStub::kMaximumClonedProperties) {
551 Callable callable =
552 CodeFactory::FastCloneShallowObject(isolate(), p.length());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100553 ReplaceWithStubCall(node, callable, flags);
554 } else {
555 ReplaceWithRuntimeCall(node, Runtime::kCreateObjectLiteral);
556 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000557}
558
559
560void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
561 CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
562 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
563 Callable callable = CodeFactory::FastCloneRegExp(isolate());
564 Node* literal_index = jsgraph()->SmiConstant(p.index());
565 Node* literal_flags = jsgraph()->SmiConstant(p.flags());
566 Node* pattern = jsgraph()->HeapConstant(p.constant());
567 node->InsertInput(graph()->zone(), 1, literal_index);
568 node->InsertInput(graph()->zone(), 2, pattern);
569 node->InsertInput(graph()->zone(), 3, literal_flags);
570 ReplaceWithStubCall(node, callable, flags);
571}
572
573
574void JSGenericLowering::LowerJSCreateCatchContext(Node* node) {
575 Handle<String> name = OpParameter<Handle<String>>(node);
576 node->InsertInput(zone(), 0, jsgraph()->HeapConstant(name));
577 ReplaceWithRuntimeCall(node, Runtime::kPushCatchContext);
578}
579
580
581void JSGenericLowering::LowerJSCreateBlockContext(Node* node) {
582 Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
583 node->InsertInput(zone(), 0, jsgraph()->HeapConstant(scope_info));
584 ReplaceWithRuntimeCall(node, Runtime::kPushBlockContext);
585}
586
587
588void JSGenericLowering::LowerJSCreateScriptContext(Node* node) {
589 Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
590 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(scope_info));
591 ReplaceWithRuntimeCall(node, Runtime::kNewScriptContext);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000592}
593
594
595void JSGenericLowering::LowerJSCallConstruct(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000596 CallConstructParameters const& p = CallConstructParametersOf(node->op());
597 int const arg_count = static_cast<int>(p.arity() - 2);
598 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
599 Callable callable = CodeFactory::Construct(isolate());
600 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
601 isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
602 Node* stub_code = jsgraph()->HeapConstant(callable.code());
603 Node* stub_arity = jsgraph()->Int32Constant(arg_count);
604 Node* new_target = node->InputAt(arg_count + 1);
605 Node* receiver = jsgraph()->UndefinedConstant();
606 node->RemoveInput(arg_count + 1); // Drop new target.
607 node->InsertInput(zone(), 0, stub_code);
608 node->InsertInput(zone(), 2, new_target);
609 node->InsertInput(zone(), 3, stub_arity);
610 node->InsertInput(zone(), 4, receiver);
611 NodeProperties::ChangeOp(node, common()->Call(desc));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400612}
613
614
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000615void JSGenericLowering::LowerJSCallFunction(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000616 CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
617 int const arg_count = static_cast<int>(p.arity() - 2);
618 ConvertReceiverMode const mode = p.convert_mode();
619 Callable callable = CodeFactory::Call(isolate(), mode);
620 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
621 if (p.tail_call_mode() == TailCallMode::kAllow) {
622 flags |= CallDescriptor::kSupportsTailCalls;
623 }
624 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
625 isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
626 Node* stub_code = jsgraph()->HeapConstant(callable.code());
627 Node* stub_arity = jsgraph()->Int32Constant(arg_count);
628 node->InsertInput(zone(), 0, stub_code);
629 node->InsertInput(zone(), 2, stub_arity);
630 NodeProperties::ChangeOp(node, common()->Call(desc));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000631}
632
633
634void JSGenericLowering::LowerJSCallRuntime(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400635 const CallRuntimeParameters& p = CallRuntimeParametersOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000636 AdjustFrameStatesForCall(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400637 ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000638}
639
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000640
641void JSGenericLowering::LowerJSForInDone(Node* node) {
642 ReplaceWithRuntimeCall(node, Runtime::kForInDone);
643}
644
645
646void JSGenericLowering::LowerJSForInNext(Node* node) {
647 ReplaceWithRuntimeCall(node, Runtime::kForInNext);
648}
649
650
651void JSGenericLowering::LowerJSForInPrepare(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100652 ReplaceWithRuntimeCall(node, Runtime::kForInPrepare);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000653}
654
655
656void JSGenericLowering::LowerJSForInStep(Node* node) {
657 ReplaceWithRuntimeCall(node, Runtime::kForInStep);
658}
659
660
661void JSGenericLowering::LowerJSLoadMessage(Node* node) {
662 ExternalReference message_address =
663 ExternalReference::address_of_pending_message_obj(isolate());
664 node->RemoveInput(NodeProperties::FirstContextIndex(node));
665 node->InsertInput(zone(), 0, jsgraph()->ExternalConstant(message_address));
666 node->InsertInput(zone(), 1, jsgraph()->IntPtrConstant(0));
667 NodeProperties::ChangeOp(node, machine()->Load(MachineType::AnyTagged()));
668}
669
670
671void JSGenericLowering::LowerJSStoreMessage(Node* node) {
672 ExternalReference message_address =
673 ExternalReference::address_of_pending_message_obj(isolate());
674 node->RemoveInput(NodeProperties::FirstContextIndex(node));
675 node->InsertInput(zone(), 0, jsgraph()->ExternalConstant(message_address));
676 node->InsertInput(zone(), 1, jsgraph()->IntPtrConstant(0));
677 StoreRepresentation representation(MachineRepresentation::kTagged,
678 kNoWriteBarrier);
679 NodeProperties::ChangeOp(node, machine()->Store(representation));
680}
681
682
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000683void JSGenericLowering::LowerJSStackCheck(Node* node) {
684 Node* effect = NodeProperties::GetEffectInput(node);
685 Node* control = NodeProperties::GetControlInput(node);
686
687 Node* limit = graph()->NewNode(
688 machine()->Load(MachineType::Pointer()),
689 jsgraph()->ExternalConstant(
690 ExternalReference::address_of_stack_limit(isolate())),
691 jsgraph()->IntPtrConstant(0), effect, control);
692 Node* pointer = graph()->NewNode(machine()->LoadStackPointer());
693
694 Node* check = graph()->NewNode(machine()->UintLessThan(), limit, pointer);
695 Node* branch =
696 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
697
698 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
699 Node* etrue = effect;
700
701 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
702 NodeProperties::ReplaceControlInput(node, if_false);
703 Node* efalse = node;
704
705 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
706 Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
707
708 // Wire the new diamond into the graph, {node} can still throw.
709 NodeProperties::ReplaceUses(node, node, ephi, node, node);
710 NodeProperties::ReplaceEffectInput(ephi, efalse, 1);
711
712 // TODO(mstarzinger): This iteration cuts out the IfSuccess projection from
713 // the node and places it inside the diamond. Come up with a helper method!
714 for (Node* use : node->uses()) {
715 if (use->opcode() == IrOpcode::kIfSuccess) {
716 use->ReplaceUses(merge);
717 merge->ReplaceInput(1, use);
718 }
719 }
720
721 // Turn the stack check into a runtime call.
722 ReplaceWithRuntimeCall(node, Runtime::kStackGuard);
723}
724
725
726Zone* JSGenericLowering::zone() const { return graph()->zone(); }
727
728
729Isolate* JSGenericLowering::isolate() const { return jsgraph()->isolate(); }
730
731
732Graph* JSGenericLowering::graph() const { return jsgraph()->graph(); }
733
734
735CommonOperatorBuilder* JSGenericLowering::common() const {
736 return jsgraph()->common();
737}
738
739
740MachineOperatorBuilder* JSGenericLowering::machine() const {
741 return jsgraph()->machine();
742}
743
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000744} // namespace compiler
745} // namespace internal
746} // namespace v8