blob: 1f12579ec7cc7ec9506d38c577b8c610a61e0749 [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
31
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032JSGenericLowering::JSGenericLowering(bool is_typing_enabled, JSGraph* jsgraph)
33 : is_typing_enabled_(is_typing_enabled), jsgraph_(jsgraph) {}
34
35
36JSGenericLowering::~JSGenericLowering() {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000037
38
Ben Murdochb8a8cc12014-11-26 15:28:44 +000039Reduction JSGenericLowering::Reduce(Node* node) {
40 switch (node->opcode()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040041#define DECLARE_CASE(x) \
42 case IrOpcode::k##x: \
43 Lower##x(node); \
44 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000045 JS_OP_LIST(DECLARE_CASE)
46#undef DECLARE_CASE
Emily Bernierd0a1eb72015-03-24 16:35:39 -040047 case IrOpcode::kBranch:
Ben Murdochda12d292016-06-02 14:46:10 +010048 case IrOpcode::kDeoptimizeIf:
49 case IrOpcode::kDeoptimizeUnless:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040050 // TODO(mstarzinger): If typing is enabled then simplified lowering will
51 // have inserted the correct ChangeBoolToBit, otherwise we need to perform
52 // poor-man's representation inference here and insert manual change.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053 if (!is_typing_enabled_) {
54 Node* condition = node->InputAt(0);
55 Node* test = graph()->NewNode(machine()->WordEqual(), condition,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040056 jsgraph()->TrueConstant());
57 node->ReplaceInput(0, test);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040058 }
59 // Fall-through.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000060 default:
61 // Nothing to see.
62 return NoChange();
63 }
64 return Changed(node);
65}
66
Ben Murdoch097c5b22016-05-18 11:27:45 +010067#define REPLACE_BINARY_OP_IC_CALL(Op, token) \
68 void JSGenericLowering::Lower##Op(Node* node) { \
69 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node); \
70 ReplaceWithStubCall(node, CodeFactory::BinaryOpIC(isolate(), token), \
71 CallDescriptor::kPatchableCallSiteWithNop | flags); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000072 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000073REPLACE_BINARY_OP_IC_CALL(JSShiftLeft, Token::SHL)
74REPLACE_BINARY_OP_IC_CALL(JSShiftRight, Token::SAR)
75REPLACE_BINARY_OP_IC_CALL(JSShiftRightLogical, Token::SHR)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000076REPLACE_BINARY_OP_IC_CALL(JSMultiply, Token::MUL)
77REPLACE_BINARY_OP_IC_CALL(JSDivide, Token::DIV)
78REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD)
79#undef REPLACE_BINARY_OP_IC_CALL
80
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081#define REPLACE_RUNTIME_CALL(op, fun) \
82 void JSGenericLowering::Lower##op(Node* node) { \
83 ReplaceWithRuntimeCall(node, fun); \
84 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000085REPLACE_RUNTIME_CALL(JSCreateWithContext, Runtime::kPushWithContext)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000086REPLACE_RUNTIME_CALL(JSCreateModuleContext, Runtime::kPushModuleContext)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver)
Ben Murdoch097c5b22016-05-18 11:27:45 +010088#undef REPLACE_RUNTIME_CALL
Ben Murdochb8a8cc12014-11-26 15:28:44 +000089
Ben Murdochda12d292016-06-02 14:46:10 +010090#define REPLACE_STUB_CALL(Name) \
91 void JSGenericLowering::LowerJS##Name(Node* node) { \
92 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node); \
93 Callable callable = CodeFactory::Name(isolate()); \
94 ReplaceWithStubCall(node, callable, flags); \
95 }
96REPLACE_STUB_CALL(Add)
97REPLACE_STUB_CALL(Subtract)
98REPLACE_STUB_CALL(BitwiseAnd)
99REPLACE_STUB_CALL(BitwiseOr)
100REPLACE_STUB_CALL(BitwiseXor)
101REPLACE_STUB_CALL(LessThan)
102REPLACE_STUB_CALL(LessThanOrEqual)
103REPLACE_STUB_CALL(GreaterThan)
104REPLACE_STUB_CALL(GreaterThanOrEqual)
105REPLACE_STUB_CALL(Equal)
106REPLACE_STUB_CALL(NotEqual)
107REPLACE_STUB_CALL(StrictEqual)
108REPLACE_STUB_CALL(StrictNotEqual)
109REPLACE_STUB_CALL(ToBoolean)
110REPLACE_STUB_CALL(ToInteger)
111REPLACE_STUB_CALL(ToLength)
112REPLACE_STUB_CALL(ToNumber)
113REPLACE_STUB_CALL(ToName)
114REPLACE_STUB_CALL(ToObject)
115REPLACE_STUB_CALL(ToString)
116#undef REPLACE_STUB_CALL
117
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
119 CallDescriptor::Flags flags) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400120 Operator::Properties properties = node->op()->properties();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000121 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
122 isolate(), zone(), callable.descriptor(), 0, flags, properties);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400123 Node* stub_code = jsgraph()->HeapConstant(callable.code());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000124 node->InsertInput(zone(), 0, stub_code);
125 NodeProperties::ChangeOp(node, common()->Call(desc));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000126}
127
128
129void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
130 Runtime::FunctionId f,
131 int nargs_override) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100132 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000133 Operator::Properties properties = node->op()->properties();
134 const Runtime::Function* fun = Runtime::FunctionForId(f);
135 int nargs = (nargs_override < 0) ? fun->nargs : nargs_override;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100136 CallDescriptor* desc =
137 Linkage::GetRuntimeCallDescriptor(zone(), f, nargs, properties, flags);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400138 Node* ref = jsgraph()->ExternalConstant(ExternalReference(f, isolate()));
139 Node* arity = jsgraph()->Int32Constant(nargs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140 node->InsertInput(zone(), 0, jsgraph()->CEntryStubConstant(fun->result_size));
141 node->InsertInput(zone(), nargs + 1, ref);
142 node->InsertInput(zone(), nargs + 2, arity);
143 NodeProperties::ChangeOp(node, common()->Call(desc));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000144}
145
146
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147void JSGenericLowering::LowerJSTypeOf(Node* node) {
148 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
149 Callable callable = CodeFactory::Typeof(isolate());
150 ReplaceWithStubCall(node, callable, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000151}
152
153
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000154void JSGenericLowering::LowerJSLoadProperty(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100155 Node* closure = NodeProperties::GetValueInput(node, 2);
156 Node* effect = NodeProperties::GetEffectInput(node);
157 Node* control = NodeProperties::GetControlInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000158 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
159 const PropertyAccess& p = PropertyAccessOf(node->op());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100160 Callable callable =
161 CodeFactory::KeyedLoadICInOptimizedCode(isolate(), UNINITIALIZED);
162 // Load the type feedback vector from the closure.
163 Node* shared_info = effect = graph()->NewNode(
164 machine()->Load(MachineType::AnyTagged()), closure,
165 jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
166 kHeapObjectTag),
167 effect, control);
168 Node* vector = effect = graph()->NewNode(
169 machine()->Load(MachineType::AnyTagged()), shared_info,
170 jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
171 kHeapObjectTag),
172 effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000173 node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100174 node->ReplaceInput(3, vector);
175 node->ReplaceInput(6, effect);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000176 ReplaceWithStubCall(node, callable, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000177}
178
179
180void JSGenericLowering::LowerJSLoadNamed(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100181 Node* closure = NodeProperties::GetValueInput(node, 1);
182 Node* effect = NodeProperties::GetEffectInput(node);
183 Node* control = NodeProperties::GetControlInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
185 NamedAccess const& p = NamedAccessOf(node->op());
186 Callable callable = CodeFactory::LoadICInOptimizedCode(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100187 isolate(), NOT_INSIDE_TYPEOF, UNINITIALIZED);
188 // Load the type feedback vector from the closure.
189 Node* shared_info = effect = graph()->NewNode(
190 machine()->Load(MachineType::AnyTagged()), closure,
191 jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
192 kHeapObjectTag),
193 effect, control);
194 Node* vector = effect = graph()->NewNode(
195 machine()->Load(MachineType::AnyTagged()), shared_info,
196 jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
197 kHeapObjectTag),
198 effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000199 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
200 node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100201 node->ReplaceInput(3, vector);
202 node->ReplaceInput(6, effect);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 ReplaceWithStubCall(node, callable, flags);
204}
205
206
207void JSGenericLowering::LowerJSLoadGlobal(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100208 Node* closure = NodeProperties::GetValueInput(node, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000209 Node* context = NodeProperties::GetContextInput(node);
210 Node* effect = NodeProperties::GetEffectInput(node);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100211 Node* control = NodeProperties::GetControlInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
213 const LoadGlobalParameters& p = LoadGlobalParametersOf(node->op());
214 Callable callable = CodeFactory::LoadICInOptimizedCode(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100215 isolate(), p.typeof_mode(), UNINITIALIZED);
216 // Load the type feedback vector from the closure.
217 Node* shared_info = effect = graph()->NewNode(
218 machine()->Load(MachineType::AnyTagged()), closure,
219 jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
220 kHeapObjectTag),
221 effect, control);
222 Node* vector = effect = graph()->NewNode(
223 machine()->Load(MachineType::AnyTagged()), shared_info,
224 jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
225 kHeapObjectTag),
226 effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000227 // Load global object from the context.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100228 Node* native_context = effect =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000229 graph()->NewNode(machine()->Load(MachineType::AnyTagged()), context,
230 jsgraph()->IntPtrConstant(
231 Context::SlotOffset(Context::NATIVE_CONTEXT_INDEX)),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100232 effect, control);
233 Node* global = effect = graph()->NewNode(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234 machine()->Load(MachineType::AnyTagged()), native_context,
235 jsgraph()->IntPtrConstant(Context::SlotOffset(Context::EXTENSION_INDEX)),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100236 effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000237 node->InsertInput(zone(), 0, global);
238 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
239 node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100240 node->ReplaceInput(3, vector);
241 node->ReplaceInput(6, effect);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 ReplaceWithStubCall(node, callable, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243}
244
245
246void JSGenericLowering::LowerJSStoreProperty(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100247 Node* closure = NodeProperties::GetValueInput(node, 3);
248 Node* effect = NodeProperties::GetEffectInput(node);
249 Node* control = NodeProperties::GetControlInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000250 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
251 PropertyAccess const& p = PropertyAccessOf(node->op());
252 LanguageMode language_mode = p.language_mode();
253 Callable callable = CodeFactory::KeyedStoreICInOptimizedCode(
254 isolate(), language_mode, UNINITIALIZED);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100255 // Load the type feedback vector from the closure.
256 Node* shared_info = effect = graph()->NewNode(
257 machine()->Load(MachineType::AnyTagged()), closure,
258 jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
259 kHeapObjectTag),
260 effect, control);
261 Node* vector = effect = graph()->NewNode(
262 machine()->Load(MachineType::AnyTagged()), shared_info,
263 jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
264 kHeapObjectTag),
265 effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000266 node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100267 node->ReplaceInput(4, vector);
268 node->ReplaceInput(7, effect);
269 ReplaceWithStubCall(node, callable, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000270}
271
272
273void JSGenericLowering::LowerJSStoreNamed(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100274 Node* closure = NodeProperties::GetValueInput(node, 2);
275 Node* effect = NodeProperties::GetEffectInput(node);
276 Node* control = NodeProperties::GetControlInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000277 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
278 NamedAccess const& p = NamedAccessOf(node->op());
279 Callable callable = CodeFactory::StoreICInOptimizedCode(
280 isolate(), p.language_mode(), UNINITIALIZED);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100281 // Load the type feedback vector from the closure.
282 Node* shared_info = effect = graph()->NewNode(
283 machine()->Load(MachineType::AnyTagged()), closure,
284 jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
285 kHeapObjectTag),
286 effect, control);
287 Node* vector = effect = graph()->NewNode(
288 machine()->Load(MachineType::AnyTagged()), shared_info,
289 jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
290 kHeapObjectTag),
291 effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000292 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000293 node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100294 node->ReplaceInput(4, vector);
295 node->ReplaceInput(7, effect);
296 ReplaceWithStubCall(node, callable, flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000297}
298
299
300void JSGenericLowering::LowerJSStoreGlobal(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100301 Node* closure = NodeProperties::GetValueInput(node, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000302 Node* context = NodeProperties::GetContextInput(node);
303 Node* effect = NodeProperties::GetEffectInput(node);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100304 Node* control = NodeProperties::GetControlInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000305 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
306 const StoreGlobalParameters& p = StoreGlobalParametersOf(node->op());
307 Callable callable = CodeFactory::StoreICInOptimizedCode(
308 isolate(), p.language_mode(), UNINITIALIZED);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100309 // Load the type feedback vector from the closure.
310 Node* shared_info = effect = graph()->NewNode(
311 machine()->Load(MachineType::AnyTagged()), closure,
312 jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
313 kHeapObjectTag),
314 effect, control);
315 Node* vector = effect = graph()->NewNode(
316 machine()->Load(MachineType::AnyTagged()), shared_info,
317 jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
318 kHeapObjectTag),
319 effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000320 // Load global object from the context.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100321 Node* native_context = effect =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000322 graph()->NewNode(machine()->Load(MachineType::AnyTagged()), context,
323 jsgraph()->IntPtrConstant(
324 Context::SlotOffset(Context::NATIVE_CONTEXT_INDEX)),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100325 effect, control);
326 Node* global = effect = graph()->NewNode(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327 machine()->Load(MachineType::AnyTagged()), native_context,
328 jsgraph()->IntPtrConstant(Context::SlotOffset(Context::EXTENSION_INDEX)),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100329 effect, control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000330 node->InsertInput(zone(), 0, global);
331 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000332 node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100333 node->ReplaceInput(4, vector);
334 node->ReplaceInput(7, effect);
335 ReplaceWithStubCall(node, callable, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000336}
337
338
339void JSGenericLowering::LowerJSDeleteProperty(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000340 LanguageMode language_mode = OpParameter<LanguageMode>(node);
341 ReplaceWithRuntimeCall(node, is_strict(language_mode)
342 ? Runtime::kDeleteProperty_Strict
343 : Runtime::kDeleteProperty_Sloppy);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000344}
345
346
347void JSGenericLowering::LowerJSHasProperty(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000348 ReplaceWithRuntimeCall(node, Runtime::kHasProperty);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000349}
350
351
352void JSGenericLowering::LowerJSInstanceOf(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000353 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
354 Callable callable = CodeFactory::InstanceOf(isolate());
355 ReplaceWithStubCall(node, callable, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000356}
357
358
359void JSGenericLowering::LowerJSLoadContext(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400360 const ContextAccess& access = ContextAccessOf(node->op());
361 for (size_t i = 0; i < access.depth(); ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000362 node->ReplaceInput(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000363 0, graph()->NewNode(machine()->Load(MachineType::AnyTagged()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400364 NodeProperties::GetValueInput(node, 0),
365 jsgraph()->Int32Constant(
366 Context::SlotOffset(Context::PREVIOUS_INDEX)),
367 NodeProperties::GetEffectInput(node),
368 graph()->start()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000369 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400370 node->ReplaceInput(1, jsgraph()->Int32Constant(Context::SlotOffset(
371 static_cast<int>(access.index()))));
372 node->AppendInput(zone(), graph()->start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000373 NodeProperties::ChangeOp(node, machine()->Load(MachineType::AnyTagged()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000374}
375
376
377void JSGenericLowering::LowerJSStoreContext(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400378 const ContextAccess& access = ContextAccessOf(node->op());
379 for (size_t i = 0; i < access.depth(); ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000380 node->ReplaceInput(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000381 0, graph()->NewNode(machine()->Load(MachineType::AnyTagged()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400382 NodeProperties::GetValueInput(node, 0),
383 jsgraph()->Int32Constant(
384 Context::SlotOffset(Context::PREVIOUS_INDEX)),
385 NodeProperties::GetEffectInput(node),
386 graph()->start()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000387 }
388 node->ReplaceInput(2, NodeProperties::GetValueInput(node, 1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400389 node->ReplaceInput(1, jsgraph()->Int32Constant(Context::SlotOffset(
390 static_cast<int>(access.index()))));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000391 NodeProperties::ChangeOp(
392 node, machine()->Store(StoreRepresentation(MachineRepresentation::kTagged,
393 kFullWriteBarrier)));
394}
395
396
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000397void JSGenericLowering::LowerJSCreate(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100398 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
399 Callable callable = CodeFactory::FastNewObject(isolate());
400 ReplaceWithStubCall(node, callable, flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000401}
402
403
404void JSGenericLowering::LowerJSCreateArguments(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100405 CreateArgumentsType const type = CreateArgumentsTypeOf(node->op());
406 switch (type) {
407 case CreateArgumentsType::kMappedArguments:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000408 ReplaceWithRuntimeCall(node, Runtime::kNewSloppyArguments_Generic);
409 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100410 case CreateArgumentsType::kUnmappedArguments:
411 ReplaceWithRuntimeCall(node, Runtime::kNewStrictArguments);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000412 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100413 case CreateArgumentsType::kRestParameter:
414 ReplaceWithRuntimeCall(node, Runtime::kNewRestParameter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000415 break;
416 }
417}
418
419
420void JSGenericLowering::LowerJSCreateArray(Node* node) {
421 CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
422 int const arity = static_cast<int>(p.arity());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100423 Handle<AllocationSite> const site = p.site();
424
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000425 // TODO(turbofan): We embed the AllocationSite from the Operator at this
426 // point, which we should not do once we want to both consume the feedback
427 // but at the same time shared the optimized code across native contexts,
428 // as the AllocationSite is associated with a single native context (it's
429 // stored in the type feedback vector after all). Once we go for cross
430 // context code generation, we should somehow find a way to get to the
431 // allocation site for the actual native context at runtime.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100432 if (!site.is_null()) {
433 // Reduce {node} to the appropriate ArrayConstructorStub backend.
434 // Note that these stubs "behave" like JSFunctions, which means they
435 // expect a receiver on the stack, which they remove. We just push
436 // undefined for the receiver.
437 ElementsKind elements_kind = site->GetElementsKind();
438 AllocationSiteOverrideMode override_mode =
439 (AllocationSite::GetMode(elements_kind) == TRACK_ALLOCATION_SITE)
440 ? DISABLE_ALLOCATION_SITES
441 : DONT_OVERRIDE;
442 if (arity == 0) {
443 ArrayNoArgumentConstructorStub stub(isolate(), elements_kind,
444 override_mode);
445 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
446 isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 1,
447 CallDescriptor::kNeedsFrameState);
448 node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
449 node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site));
450 node->InsertInput(graph()->zone(), 3, jsgraph()->UndefinedConstant());
451 NodeProperties::ChangeOp(node, common()->Call(desc));
452 } else if (arity == 1) {
453 // TODO(bmeurer): Optimize for the 0 length non-holey case?
454 ArraySingleArgumentConstructorStub stub(
455 isolate(), GetHoleyElementsKind(elements_kind), override_mode);
456 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
457 isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 2,
458 CallDescriptor::kNeedsFrameState);
459 node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
460 node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site));
461 node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(1));
462 node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
463 NodeProperties::ChangeOp(node, common()->Call(desc));
464 } else {
465 ArrayNArgumentsConstructorStub stub(isolate(), elements_kind,
466 override_mode);
467 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
468 isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(),
469 arity + 1, CallDescriptor::kNeedsFrameState);
470 node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
471 node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site));
472 node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(arity));
473 node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
474 NodeProperties::ChangeOp(node, common()->Call(desc));
475 }
476 } else {
477 Node* new_target = node->InputAt(1);
478 Node* type_info = site.is_null() ? jsgraph()->UndefinedConstant()
479 : jsgraph()->HeapConstant(site);
480 node->RemoveInput(1);
481 node->InsertInput(zone(), 1 + arity, new_target);
482 node->InsertInput(zone(), 2 + arity, type_info);
483 ReplaceWithRuntimeCall(node, Runtime::kNewArray, arity + 3);
484 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000485}
486
487
488void JSGenericLowering::LowerJSCreateClosure(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100489 CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
490 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
491 Handle<SharedFunctionInfo> const shared_info = p.shared_info();
492 node->InsertInput(zone(), 0, jsgraph()->HeapConstant(shared_info));
493
494 // Use the FastNewClosureStub that allocates in new space only for nested
495 // functions that don't need literals cloning.
496 if (p.pretenure() == NOT_TENURED && shared_info->num_literals() == 0) {
497 Callable callable = CodeFactory::FastNewClosure(
498 isolate(), shared_info->language_mode(), shared_info->kind());
499 ReplaceWithStubCall(node, callable, flags);
500 } else {
501 ReplaceWithRuntimeCall(node, (p.pretenure() == TENURED)
502 ? Runtime::kNewClosure_Tenured
503 : Runtime::kNewClosure);
504 }
505}
506
507
508void JSGenericLowering::LowerJSCreateFunctionContext(Node* node) {
509 int const slot_count = OpParameter<int>(node->op());
510 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
511
512 // Use the FastNewContextStub only for function contexts up maximum size.
513 if (slot_count <= FastNewContextStub::kMaximumSlots) {
514 Callable callable = CodeFactory::FastNewContext(isolate(), slot_count);
515 ReplaceWithStubCall(node, callable, flags);
516 } else {
517 ReplaceWithRuntimeCall(node, Runtime::kNewFunctionContext);
518 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000519}
520
521
522void JSGenericLowering::LowerJSCreateIterResultObject(Node* node) {
523 ReplaceWithRuntimeCall(node, Runtime::kCreateIterResultObject);
524}
525
526
527void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
528 CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100529 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000530 node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
531 node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100532
533 // Use the FastCloneShallowArrayStub only for shallow boilerplates up to the
534 // initial length limit for arrays with "fast" elements kind.
535 if ((p.flags() & ArrayLiteral::kShallowElements) != 0 &&
Ben Murdochda12d292016-06-02 14:46:10 +0100536 p.length() < JSArray::kInitialMaxFastElementArray) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100537 Callable callable = CodeFactory::FastCloneShallowArray(isolate());
538 ReplaceWithStubCall(node, callable, flags);
539 } else {
540 node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
541 ReplaceWithRuntimeCall(node, Runtime::kCreateArrayLiteral);
542 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000543}
544
545
546void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
547 CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100548 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000549 node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
550 node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
551 node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100552
553 // Use the FastCloneShallowObjectStub only for shallow boilerplates without
554 // elements up to the number of properties that the stubs can handle.
555 if ((p.flags() & ObjectLiteral::kShallowProperties) != 0 &&
Ben Murdochda12d292016-06-02 14:46:10 +0100556 p.length() <= FastCloneShallowObjectStub::kMaximumClonedProperties) {
557 Callable callable =
558 CodeFactory::FastCloneShallowObject(isolate(), p.length());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100559 ReplaceWithStubCall(node, callable, flags);
560 } else {
561 ReplaceWithRuntimeCall(node, Runtime::kCreateObjectLiteral);
562 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000563}
564
565
566void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
567 CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
568 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
569 Callable callable = CodeFactory::FastCloneRegExp(isolate());
570 Node* literal_index = jsgraph()->SmiConstant(p.index());
571 Node* literal_flags = jsgraph()->SmiConstant(p.flags());
572 Node* pattern = jsgraph()->HeapConstant(p.constant());
573 node->InsertInput(graph()->zone(), 1, literal_index);
574 node->InsertInput(graph()->zone(), 2, pattern);
575 node->InsertInput(graph()->zone(), 3, literal_flags);
576 ReplaceWithStubCall(node, callable, flags);
577}
578
579
580void JSGenericLowering::LowerJSCreateCatchContext(Node* node) {
581 Handle<String> name = OpParameter<Handle<String>>(node);
582 node->InsertInput(zone(), 0, jsgraph()->HeapConstant(name));
583 ReplaceWithRuntimeCall(node, Runtime::kPushCatchContext);
584}
585
586
587void JSGenericLowering::LowerJSCreateBlockContext(Node* node) {
588 Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
589 node->InsertInput(zone(), 0, jsgraph()->HeapConstant(scope_info));
590 ReplaceWithRuntimeCall(node, Runtime::kPushBlockContext);
591}
592
593
594void JSGenericLowering::LowerJSCreateScriptContext(Node* node) {
595 Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
596 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(scope_info));
597 ReplaceWithRuntimeCall(node, Runtime::kNewScriptContext);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000598}
599
600
601void JSGenericLowering::LowerJSCallConstruct(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000602 CallConstructParameters const& p = CallConstructParametersOf(node->op());
603 int const arg_count = static_cast<int>(p.arity() - 2);
604 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
605 Callable callable = CodeFactory::Construct(isolate());
606 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
607 isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
608 Node* stub_code = jsgraph()->HeapConstant(callable.code());
609 Node* stub_arity = jsgraph()->Int32Constant(arg_count);
610 Node* new_target = node->InputAt(arg_count + 1);
611 Node* receiver = jsgraph()->UndefinedConstant();
612 node->RemoveInput(arg_count + 1); // Drop new target.
613 node->InsertInput(zone(), 0, stub_code);
614 node->InsertInput(zone(), 2, new_target);
615 node->InsertInput(zone(), 3, stub_arity);
616 node->InsertInput(zone(), 4, receiver);
617 NodeProperties::ChangeOp(node, common()->Call(desc));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400618}
619
620
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000621void JSGenericLowering::LowerJSCallFunction(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000622 CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
623 int const arg_count = static_cast<int>(p.arity() - 2);
624 ConvertReceiverMode const mode = p.convert_mode();
625 Callable callable = CodeFactory::Call(isolate(), mode);
626 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
627 if (p.tail_call_mode() == TailCallMode::kAllow) {
628 flags |= CallDescriptor::kSupportsTailCalls;
629 }
630 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
631 isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
632 Node* stub_code = jsgraph()->HeapConstant(callable.code());
633 Node* stub_arity = jsgraph()->Int32Constant(arg_count);
634 node->InsertInput(zone(), 0, stub_code);
635 node->InsertInput(zone(), 2, stub_arity);
636 NodeProperties::ChangeOp(node, common()->Call(desc));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000637}
638
639
640void JSGenericLowering::LowerJSCallRuntime(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400641 const CallRuntimeParameters& p = CallRuntimeParametersOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000642 AdjustFrameStatesForCall(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400643 ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000644}
645
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000646
647void JSGenericLowering::LowerJSForInDone(Node* node) {
648 ReplaceWithRuntimeCall(node, Runtime::kForInDone);
649}
650
651
652void JSGenericLowering::LowerJSForInNext(Node* node) {
653 ReplaceWithRuntimeCall(node, Runtime::kForInNext);
654}
655
656
657void JSGenericLowering::LowerJSForInPrepare(Node* node) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100658 ReplaceWithRuntimeCall(node, Runtime::kForInPrepare);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000659}
660
661
662void JSGenericLowering::LowerJSForInStep(Node* node) {
663 ReplaceWithRuntimeCall(node, Runtime::kForInStep);
664}
665
666
667void JSGenericLowering::LowerJSLoadMessage(Node* node) {
668 ExternalReference message_address =
669 ExternalReference::address_of_pending_message_obj(isolate());
670 node->RemoveInput(NodeProperties::FirstContextIndex(node));
671 node->InsertInput(zone(), 0, jsgraph()->ExternalConstant(message_address));
672 node->InsertInput(zone(), 1, jsgraph()->IntPtrConstant(0));
673 NodeProperties::ChangeOp(node, machine()->Load(MachineType::AnyTagged()));
674}
675
676
677void JSGenericLowering::LowerJSStoreMessage(Node* node) {
678 ExternalReference message_address =
679 ExternalReference::address_of_pending_message_obj(isolate());
680 node->RemoveInput(NodeProperties::FirstContextIndex(node));
681 node->InsertInput(zone(), 0, jsgraph()->ExternalConstant(message_address));
682 node->InsertInput(zone(), 1, jsgraph()->IntPtrConstant(0));
683 StoreRepresentation representation(MachineRepresentation::kTagged,
684 kNoWriteBarrier);
685 NodeProperties::ChangeOp(node, machine()->Store(representation));
686}
687
688
689void JSGenericLowering::LowerJSYield(Node* node) { UNIMPLEMENTED(); }
690
691
692void JSGenericLowering::LowerJSStackCheck(Node* node) {
693 Node* effect = NodeProperties::GetEffectInput(node);
694 Node* control = NodeProperties::GetControlInput(node);
695
696 Node* limit = graph()->NewNode(
697 machine()->Load(MachineType::Pointer()),
698 jsgraph()->ExternalConstant(
699 ExternalReference::address_of_stack_limit(isolate())),
700 jsgraph()->IntPtrConstant(0), effect, control);
701 Node* pointer = graph()->NewNode(machine()->LoadStackPointer());
702
703 Node* check = graph()->NewNode(machine()->UintLessThan(), limit, pointer);
704 Node* branch =
705 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
706
707 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
708 Node* etrue = effect;
709
710 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
711 NodeProperties::ReplaceControlInput(node, if_false);
712 Node* efalse = node;
713
714 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
715 Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
716
717 // Wire the new diamond into the graph, {node} can still throw.
718 NodeProperties::ReplaceUses(node, node, ephi, node, node);
719 NodeProperties::ReplaceEffectInput(ephi, efalse, 1);
720
721 // TODO(mstarzinger): This iteration cuts out the IfSuccess projection from
722 // the node and places it inside the diamond. Come up with a helper method!
723 for (Node* use : node->uses()) {
724 if (use->opcode() == IrOpcode::kIfSuccess) {
725 use->ReplaceUses(merge);
726 merge->ReplaceInput(1, use);
727 }
728 }
729
730 // Turn the stack check into a runtime call.
731 ReplaceWithRuntimeCall(node, Runtime::kStackGuard);
732}
733
734
735Zone* JSGenericLowering::zone() const { return graph()->zone(); }
736
737
738Isolate* JSGenericLowering::isolate() const { return jsgraph()->isolate(); }
739
740
741Graph* JSGenericLowering::graph() const { return jsgraph()->graph(); }
742
743
744CommonOperatorBuilder* JSGenericLowering::common() const {
745 return jsgraph()->common();
746}
747
748
749MachineOperatorBuilder* JSGenericLowering::machine() const {
750 return jsgraph()->machine();
751}
752
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000753} // namespace compiler
754} // namespace internal
755} // namespace v8