blob: 15ce908a1ce68d16870fb3ce040cfb2cd9c163bb [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:
48 // TODO(mstarzinger): If typing is enabled then simplified lowering will
49 // have inserted the correct ChangeBoolToBit, otherwise we need to perform
50 // poor-man's representation inference here and insert manual change.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000051 if (!is_typing_enabled_) {
52 Node* condition = node->InputAt(0);
53 Node* test = graph()->NewNode(machine()->WordEqual(), condition,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040054 jsgraph()->TrueConstant());
55 node->ReplaceInput(0, test);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040056 }
57 // Fall-through.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058 default:
59 // Nothing to see.
60 return NoChange();
61 }
62 return Changed(node);
63}
64
65
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066#define REPLACE_BINARY_OP_IC_CALL(Op, token) \
67 void JSGenericLowering::Lower##Op(Node* node) { \
68 BinaryOperationParameters const& p = \
69 BinaryOperationParametersOf(node->op()); \
70 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node); \
71 ReplaceWithStubCall(node, \
72 CodeFactory::BinaryOpIC(isolate(), token, \
73 strength(p.language_mode())), \
74 CallDescriptor::kPatchableCallSiteWithNop | flags); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000075 }
76REPLACE_BINARY_OP_IC_CALL(JSBitwiseOr, Token::BIT_OR)
77REPLACE_BINARY_OP_IC_CALL(JSBitwiseXor, Token::BIT_XOR)
78REPLACE_BINARY_OP_IC_CALL(JSBitwiseAnd, Token::BIT_AND)
79REPLACE_BINARY_OP_IC_CALL(JSShiftLeft, Token::SHL)
80REPLACE_BINARY_OP_IC_CALL(JSShiftRight, Token::SAR)
81REPLACE_BINARY_OP_IC_CALL(JSShiftRightLogical, Token::SHR)
82REPLACE_BINARY_OP_IC_CALL(JSAdd, Token::ADD)
83REPLACE_BINARY_OP_IC_CALL(JSSubtract, Token::SUB)
84REPLACE_BINARY_OP_IC_CALL(JSMultiply, Token::MUL)
85REPLACE_BINARY_OP_IC_CALL(JSDivide, Token::DIV)
86REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD)
87#undef REPLACE_BINARY_OP_IC_CALL
88
89
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090// These ops are not language mode dependent; we arbitrarily pass Strength::WEAK
91// here.
92#define REPLACE_COMPARE_IC_CALL(op, token) \
93 void JSGenericLowering::Lower##op(Node* node) { \
94 ReplaceWithCompareIC(node, token, Strength::WEAK); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000095 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040096REPLACE_COMPARE_IC_CALL(JSEqual, Token::EQ)
97REPLACE_COMPARE_IC_CALL(JSNotEqual, Token::NE)
98REPLACE_COMPARE_IC_CALL(JSStrictEqual, Token::EQ_STRICT)
99REPLACE_COMPARE_IC_CALL(JSStrictNotEqual, Token::NE_STRICT)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000100#undef REPLACE_COMPARE_IC_CALL
101
102
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000103#define REPLACE_COMPARE_IC_CALL_WITH_LANGUAGE_MODE(op, token) \
104 void JSGenericLowering::Lower##op(Node* node) { \
105 ReplaceWithCompareIC(node, token, \
106 strength(OpParameter<LanguageMode>(node))); \
107 }
108REPLACE_COMPARE_IC_CALL_WITH_LANGUAGE_MODE(JSLessThan, Token::LT)
109REPLACE_COMPARE_IC_CALL_WITH_LANGUAGE_MODE(JSGreaterThan, Token::GT)
110REPLACE_COMPARE_IC_CALL_WITH_LANGUAGE_MODE(JSLessThanOrEqual, Token::LTE)
111REPLACE_COMPARE_IC_CALL_WITH_LANGUAGE_MODE(JSGreaterThanOrEqual, Token::GTE)
112#undef REPLACE_COMPARE_IC_CALL_WITH_LANGUAGE_MODE
113
114
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115#define REPLACE_RUNTIME_CALL(op, fun) \
116 void JSGenericLowering::Lower##op(Node* node) { \
117 ReplaceWithRuntimeCall(node, fun); \
118 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000119REPLACE_RUNTIME_CALL(JSCreateFunctionContext, Runtime::kNewFunctionContext)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000120REPLACE_RUNTIME_CALL(JSCreateWithContext, Runtime::kPushWithContext)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000121REPLACE_RUNTIME_CALL(JSCreateModuleContext, Runtime::kPushModuleContext)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000122REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000123#undef REPLACE_RUNTIME
124
125
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000126static CallDescriptor::Flags FlagsForNode(Node* node) {
127 CallDescriptor::Flags result = CallDescriptor::kNoFlags;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000128 if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000129 result |= CallDescriptor::kNeedsFrameState;
130 }
131 return result;
132}
133
134
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000135void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token,
136 Strength str) {
137 Callable callable = CodeFactory::CompareIC(isolate(), token, str);
138
139 // Create a new call node asking a CompareIC for help.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000140 NodeVector inputs(zone());
141 inputs.reserve(node->InputCount() + 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400142 inputs.push_back(jsgraph()->HeapConstant(callable.code()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000143 inputs.push_back(NodeProperties::GetValueInput(node, 0));
144 inputs.push_back(NodeProperties::GetValueInput(node, 1));
145 inputs.push_back(NodeProperties::GetContextInput(node));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000146 // Some comparisons (StrictEqual) don't have an effect, control or frame
147 // state inputs, so handle those cases here.
148 if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) {
149 inputs.push_back(NodeProperties::GetFrameStateInput(node, 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151 Node* effect = (node->op()->EffectInputCount() > 0)
152 ? NodeProperties::GetEffectInput(node)
153 : graph()->start();
154 inputs.push_back(effect);
155 Node* control = (node->op()->ControlInputCount() > 0)
156 ? NodeProperties::GetControlInput(node)
157 : graph()->start();
158 inputs.push_back(control);
159 CallDescriptor* desc_compare = Linkage::GetStubCallDescriptor(
160 isolate(), zone(), callable.descriptor(), 0,
161 CallDescriptor::kPatchableCallSiteWithNop | FlagsForNode(node),
162 Operator::kNoProperties, MachineType::IntPtr());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000163 Node* compare =
164 graph()->NewNode(common()->Call(desc_compare),
165 static_cast<int>(inputs.size()), &inputs.front());
166
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000167 // Decide how the return value from the above CompareIC can be converted into
168 // a JavaScript boolean oddball depending on the given token.
169 Node* false_value = jsgraph()->FalseConstant();
170 Node* true_value = jsgraph()->TrueConstant();
171 const Operator* op = nullptr;
172 switch (token) {
173 case Token::EQ: // a == 0
174 case Token::EQ_STRICT:
175 op = machine()->WordEqual();
176 break;
177 case Token::NE: // a != 0 becomes !(a == 0)
178 case Token::NE_STRICT:
179 op = machine()->WordEqual();
180 std::swap(true_value, false_value);
181 break;
182 case Token::LT: // a < 0
183 op = machine()->IntLessThan();
184 break;
185 case Token::GT: // a > 0 becomes !(a <= 0)
186 op = machine()->IntLessThanOrEqual();
187 std::swap(true_value, false_value);
188 break;
189 case Token::LTE: // a <= 0
190 op = machine()->IntLessThanOrEqual();
191 break;
192 case Token::GTE: // a >= 0 becomes !(a < 0)
193 op = machine()->IntLessThan();
194 std::swap(true_value, false_value);
195 break;
196 default:
197 UNREACHABLE();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000198 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000199 Node* booleanize = graph()->NewNode(op, compare, jsgraph()->ZeroConstant());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000200
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000201 // Finally patch the original node to select a boolean.
202 NodeProperties::ReplaceUses(node, node, compare, compare, compare);
203 node->TrimInputCount(3);
204 node->ReplaceInput(0, booleanize);
205 node->ReplaceInput(1, true_value);
206 node->ReplaceInput(2, false_value);
207 NodeProperties::ChangeOp(node,
208 common()->Select(MachineRepresentation::kTagged));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209}
210
211
212void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
213 CallDescriptor::Flags flags) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400214 Operator::Properties properties = node->op()->properties();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000215 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
216 isolate(), zone(), callable.descriptor(), 0, flags, properties);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400217 Node* stub_code = jsgraph()->HeapConstant(callable.code());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 node->InsertInput(zone(), 0, stub_code);
219 NodeProperties::ChangeOp(node, common()->Call(desc));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000220}
221
222
223void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
224 Runtime::FunctionId f,
225 int nargs_override) {
226 Operator::Properties properties = node->op()->properties();
227 const Runtime::Function* fun = Runtime::FunctionForId(f);
228 int nargs = (nargs_override < 0) ? fun->nargs : nargs_override;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000229 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
230 zone(), f, nargs, properties, CallDescriptor::kNeedsFrameState);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400231 Node* ref = jsgraph()->ExternalConstant(ExternalReference(f, isolate()));
232 Node* arity = jsgraph()->Int32Constant(nargs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233 node->InsertInput(zone(), 0, jsgraph()->CEntryStubConstant(fun->result_size));
234 node->InsertInput(zone(), nargs + 1, ref);
235 node->InsertInput(zone(), nargs + 2, arity);
236 NodeProperties::ChangeOp(node, common()->Call(desc));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000237}
238
239
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240void JSGenericLowering::LowerJSTypeOf(Node* node) {
241 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
242 Callable callable = CodeFactory::Typeof(isolate());
243 ReplaceWithStubCall(node, callable, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000244}
245
246
247void JSGenericLowering::LowerJSToBoolean(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000248 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
249 Callable callable = CodeFactory::ToBoolean(isolate());
250 ReplaceWithStubCall(node, callable,
251 CallDescriptor::kPatchableCallSite | flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000252}
253
254
255void JSGenericLowering::LowerJSToNumber(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000256 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000257 Callable callable = CodeFactory::ToNumber(isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000258 ReplaceWithStubCall(node, callable, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000259}
260
261
262void JSGenericLowering::LowerJSToString(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000263 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
264 Callable callable = CodeFactory::ToString(isolate());
265 ReplaceWithStubCall(node, callable, flags);
266}
267
268
269void JSGenericLowering::LowerJSToName(Node* node) {
270 ReplaceWithRuntimeCall(node, Runtime::kToName);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000271}
272
273
274void JSGenericLowering::LowerJSToObject(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000275 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
276 Callable callable = CodeFactory::ToObject(isolate());
277 ReplaceWithStubCall(node, callable, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000278}
279
280
281void JSGenericLowering::LowerJSLoadProperty(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000282 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
283 const PropertyAccess& p = PropertyAccessOf(node->op());
284 Callable callable = CodeFactory::KeyedLoadICInOptimizedCode(
285 isolate(), p.language_mode(), UNINITIALIZED);
286 node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
287 ReplaceWithStubCall(node, callable, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000288}
289
290
291void JSGenericLowering::LowerJSLoadNamed(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000292 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
293 NamedAccess const& p = NamedAccessOf(node->op());
294 Callable callable = CodeFactory::LoadICInOptimizedCode(
295 isolate(), NOT_INSIDE_TYPEOF, p.language_mode(), UNINITIALIZED);
296 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
297 node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
298 ReplaceWithStubCall(node, callable, flags);
299}
300
301
302void JSGenericLowering::LowerJSLoadGlobal(Node* node) {
303 Node* context = NodeProperties::GetContextInput(node);
304 Node* effect = NodeProperties::GetEffectInput(node);
305 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
306 const LoadGlobalParameters& p = LoadGlobalParametersOf(node->op());
307 Callable callable = CodeFactory::LoadICInOptimizedCode(
308 isolate(), p.typeof_mode(), SLOPPY, UNINITIALIZED);
309 // Load global object from the context.
310 Node* native_context =
311 graph()->NewNode(machine()->Load(MachineType::AnyTagged()), context,
312 jsgraph()->IntPtrConstant(
313 Context::SlotOffset(Context::NATIVE_CONTEXT_INDEX)),
314 effect, graph()->start());
315 Node* global = graph()->NewNode(
316 machine()->Load(MachineType::AnyTagged()), native_context,
317 jsgraph()->IntPtrConstant(Context::SlotOffset(Context::EXTENSION_INDEX)),
318 effect, graph()->start());
319 node->InsertInput(zone(), 0, global);
320 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
321 node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
322 ReplaceWithStubCall(node, callable, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000323}
324
325
326void JSGenericLowering::LowerJSStoreProperty(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
328 PropertyAccess const& p = PropertyAccessOf(node->op());
329 LanguageMode language_mode = p.language_mode();
330 Callable callable = CodeFactory::KeyedStoreICInOptimizedCode(
331 isolate(), language_mode, UNINITIALIZED);
332 DCHECK(p.feedback().index() != -1);
333 node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
334 ReplaceWithStubCall(node, callable,
335 CallDescriptor::kPatchableCallSite | flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000336}
337
338
339void JSGenericLowering::LowerJSStoreNamed(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000340 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
341 NamedAccess const& p = NamedAccessOf(node->op());
342 Callable callable = CodeFactory::StoreICInOptimizedCode(
343 isolate(), p.language_mode(), UNINITIALIZED);
344 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
345 DCHECK(p.feedback().index() != -1);
346 node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
347 ReplaceWithStubCall(node, callable,
348 CallDescriptor::kPatchableCallSite | flags);
349}
350
351
352void JSGenericLowering::LowerJSStoreGlobal(Node* node) {
353 Node* context = NodeProperties::GetContextInput(node);
354 Node* effect = NodeProperties::GetEffectInput(node);
355 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
356 const StoreGlobalParameters& p = StoreGlobalParametersOf(node->op());
357 Callable callable = CodeFactory::StoreICInOptimizedCode(
358 isolate(), p.language_mode(), UNINITIALIZED);
359 // Load global object from the context.
360 Node* native_context =
361 graph()->NewNode(machine()->Load(MachineType::AnyTagged()), context,
362 jsgraph()->IntPtrConstant(
363 Context::SlotOffset(Context::NATIVE_CONTEXT_INDEX)),
364 effect, graph()->start());
365 Node* global = graph()->NewNode(
366 machine()->Load(MachineType::AnyTagged()), native_context,
367 jsgraph()->IntPtrConstant(Context::SlotOffset(Context::EXTENSION_INDEX)),
368 effect, graph()->start());
369 node->InsertInput(zone(), 0, global);
370 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
371 DCHECK(p.feedback().index() != -1);
372 node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
373 ReplaceWithStubCall(node, callable,
374 CallDescriptor::kPatchableCallSite | flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000375}
376
377
378void JSGenericLowering::LowerJSDeleteProperty(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000379 LanguageMode language_mode = OpParameter<LanguageMode>(node);
380 ReplaceWithRuntimeCall(node, is_strict(language_mode)
381 ? Runtime::kDeleteProperty_Strict
382 : Runtime::kDeleteProperty_Sloppy);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000383}
384
385
386void JSGenericLowering::LowerJSHasProperty(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000387 ReplaceWithRuntimeCall(node, Runtime::kHasProperty);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388}
389
390
391void JSGenericLowering::LowerJSInstanceOf(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000392 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
393 Callable callable = CodeFactory::InstanceOf(isolate());
394 ReplaceWithStubCall(node, callable, flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000395}
396
397
398void JSGenericLowering::LowerJSLoadContext(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400399 const ContextAccess& access = ContextAccessOf(node->op());
400 for (size_t i = 0; i < access.depth(); ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000401 node->ReplaceInput(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000402 0, graph()->NewNode(machine()->Load(MachineType::AnyTagged()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400403 NodeProperties::GetValueInput(node, 0),
404 jsgraph()->Int32Constant(
405 Context::SlotOffset(Context::PREVIOUS_INDEX)),
406 NodeProperties::GetEffectInput(node),
407 graph()->start()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000408 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400409 node->ReplaceInput(1, jsgraph()->Int32Constant(Context::SlotOffset(
410 static_cast<int>(access.index()))));
411 node->AppendInput(zone(), graph()->start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000412 NodeProperties::ChangeOp(node, machine()->Load(MachineType::AnyTagged()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413}
414
415
416void JSGenericLowering::LowerJSStoreContext(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400417 const ContextAccess& access = ContextAccessOf(node->op());
418 for (size_t i = 0; i < access.depth(); ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000419 node->ReplaceInput(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000420 0, graph()->NewNode(machine()->Load(MachineType::AnyTagged()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400421 NodeProperties::GetValueInput(node, 0),
422 jsgraph()->Int32Constant(
423 Context::SlotOffset(Context::PREVIOUS_INDEX)),
424 NodeProperties::GetEffectInput(node),
425 graph()->start()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000426 }
427 node->ReplaceInput(2, NodeProperties::GetValueInput(node, 1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400428 node->ReplaceInput(1, jsgraph()->Int32Constant(Context::SlotOffset(
429 static_cast<int>(access.index()))));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000430 NodeProperties::ChangeOp(
431 node, machine()->Store(StoreRepresentation(MachineRepresentation::kTagged,
432 kFullWriteBarrier)));
433}
434
435
436void JSGenericLowering::LowerJSLoadDynamic(Node* node) {
437 const DynamicAccess& access = DynamicAccessOf(node->op());
438 Runtime::FunctionId function_id =
439 (access.typeof_mode() == NOT_INSIDE_TYPEOF)
440 ? Runtime::kLoadLookupSlot
441 : Runtime::kLoadLookupSlotNoReferenceError;
442 Node* projection = graph()->NewNode(common()->Projection(0), node);
443 NodeProperties::ReplaceUses(node, projection, node, node, node);
444 node->RemoveInput(NodeProperties::FirstValueIndex(node));
445 node->InsertInput(zone(), 1, jsgraph()->Constant(access.name()));
446 ReplaceWithRuntimeCall(node, function_id);
447 projection->ReplaceInput(0, node);
448}
449
450
451void JSGenericLowering::LowerJSCreate(Node* node) {
452 ReplaceWithRuntimeCall(node, Runtime::kNewObject);
453}
454
455
456void JSGenericLowering::LowerJSCreateArguments(Node* node) {
457 const CreateArgumentsParameters& p = CreateArgumentsParametersOf(node->op());
458 switch (p.type()) {
459 case CreateArgumentsParameters::kMappedArguments:
460 ReplaceWithRuntimeCall(node, Runtime::kNewSloppyArguments_Generic);
461 break;
462 case CreateArgumentsParameters::kUnmappedArguments:
463 ReplaceWithRuntimeCall(node, Runtime::kNewStrictArguments_Generic);
464 break;
465 case CreateArgumentsParameters::kRestArray:
466 node->InsertInput(zone(), 1, jsgraph()->Constant(p.start_index()));
467 ReplaceWithRuntimeCall(node, Runtime::kNewRestArguments_Generic);
468 break;
469 }
470}
471
472
473void JSGenericLowering::LowerJSCreateArray(Node* node) {
474 CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
475 int const arity = static_cast<int>(p.arity());
476 Node* new_target = node->InputAt(1);
477 // TODO(turbofan): We embed the AllocationSite from the Operator at this
478 // point, which we should not do once we want to both consume the feedback
479 // but at the same time shared the optimized code across native contexts,
480 // as the AllocationSite is associated with a single native context (it's
481 // stored in the type feedback vector after all). Once we go for cross
482 // context code generation, we should somehow find a way to get to the
483 // allocation site for the actual native context at runtime.
484 Node* type_info = p.site().is_null() ? jsgraph()->UndefinedConstant()
485 : jsgraph()->HeapConstant(p.site());
486 node->RemoveInput(1);
487 node->InsertInput(zone(), 1 + arity, new_target);
488 node->InsertInput(zone(), 2 + arity, type_info);
489 ReplaceWithRuntimeCall(node, Runtime::kNewArray, arity + 3);
490}
491
492
493void JSGenericLowering::LowerJSCreateClosure(Node* node) {
494 CreateClosureParameters p = CreateClosureParametersOf(node->op());
495 node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.shared_info()));
496 ReplaceWithRuntimeCall(node, (p.pretenure() == TENURED)
497 ? Runtime::kNewClosure_Tenured
498 : Runtime::kNewClosure);
499}
500
501
502void JSGenericLowering::LowerJSCreateIterResultObject(Node* node) {
503 ReplaceWithRuntimeCall(node, Runtime::kCreateIterResultObject);
504}
505
506
507void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
508 CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
509 node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
510 node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
511 node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
512 ReplaceWithRuntimeCall(node, Runtime::kCreateArrayLiteral);
513}
514
515
516void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
517 CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
518 node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
519 node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
520 node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
521 ReplaceWithRuntimeCall(node, Runtime::kCreateObjectLiteral);
522}
523
524
525void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
526 CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
527 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
528 Callable callable = CodeFactory::FastCloneRegExp(isolate());
529 Node* literal_index = jsgraph()->SmiConstant(p.index());
530 Node* literal_flags = jsgraph()->SmiConstant(p.flags());
531 Node* pattern = jsgraph()->HeapConstant(p.constant());
532 node->InsertInput(graph()->zone(), 1, literal_index);
533 node->InsertInput(graph()->zone(), 2, pattern);
534 node->InsertInput(graph()->zone(), 3, literal_flags);
535 ReplaceWithStubCall(node, callable, flags);
536}
537
538
539void JSGenericLowering::LowerJSCreateCatchContext(Node* node) {
540 Handle<String> name = OpParameter<Handle<String>>(node);
541 node->InsertInput(zone(), 0, jsgraph()->HeapConstant(name));
542 ReplaceWithRuntimeCall(node, Runtime::kPushCatchContext);
543}
544
545
546void JSGenericLowering::LowerJSCreateBlockContext(Node* node) {
547 Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
548 node->InsertInput(zone(), 0, jsgraph()->HeapConstant(scope_info));
549 ReplaceWithRuntimeCall(node, Runtime::kPushBlockContext);
550}
551
552
553void JSGenericLowering::LowerJSCreateScriptContext(Node* node) {
554 Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
555 node->InsertInput(zone(), 1, jsgraph()->HeapConstant(scope_info));
556 ReplaceWithRuntimeCall(node, Runtime::kNewScriptContext);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000557}
558
559
560void JSGenericLowering::LowerJSCallConstruct(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000561 CallConstructParameters const& p = CallConstructParametersOf(node->op());
562 int const arg_count = static_cast<int>(p.arity() - 2);
563 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
564 Callable callable = CodeFactory::Construct(isolate());
565 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
566 isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
567 Node* stub_code = jsgraph()->HeapConstant(callable.code());
568 Node* stub_arity = jsgraph()->Int32Constant(arg_count);
569 Node* new_target = node->InputAt(arg_count + 1);
570 Node* receiver = jsgraph()->UndefinedConstant();
571 node->RemoveInput(arg_count + 1); // Drop new target.
572 node->InsertInput(zone(), 0, stub_code);
573 node->InsertInput(zone(), 2, new_target);
574 node->InsertInput(zone(), 3, stub_arity);
575 node->InsertInput(zone(), 4, receiver);
576 NodeProperties::ChangeOp(node, common()->Call(desc));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400577}
578
579
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000580void JSGenericLowering::LowerJSCallFunction(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000581 CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
582 int const arg_count = static_cast<int>(p.arity() - 2);
583 ConvertReceiverMode const mode = p.convert_mode();
584 Callable callable = CodeFactory::Call(isolate(), mode);
585 CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
586 if (p.tail_call_mode() == TailCallMode::kAllow) {
587 flags |= CallDescriptor::kSupportsTailCalls;
588 }
589 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
590 isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
591 Node* stub_code = jsgraph()->HeapConstant(callable.code());
592 Node* stub_arity = jsgraph()->Int32Constant(arg_count);
593 node->InsertInput(zone(), 0, stub_code);
594 node->InsertInput(zone(), 2, stub_arity);
595 NodeProperties::ChangeOp(node, common()->Call(desc));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000596}
597
598
599void JSGenericLowering::LowerJSCallRuntime(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400600 const CallRuntimeParameters& p = CallRuntimeParametersOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000601 AdjustFrameStatesForCall(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400602 ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000603}
604
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000605
606void JSGenericLowering::LowerJSForInDone(Node* node) {
607 ReplaceWithRuntimeCall(node, Runtime::kForInDone);
608}
609
610
611void JSGenericLowering::LowerJSForInNext(Node* node) {
612 ReplaceWithRuntimeCall(node, Runtime::kForInNext);
613}
614
615
616void JSGenericLowering::LowerJSForInPrepare(Node* node) {
617 Node* object = NodeProperties::GetValueInput(node, 0);
618 Node* context = NodeProperties::GetContextInput(node);
619 Node* effect = NodeProperties::GetEffectInput(node);
620 Node* control = NodeProperties::GetControlInput(node);
621 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
622
623 // Get the set of properties to enumerate.
624 Runtime::Function const* function =
625 Runtime::FunctionForId(Runtime::kGetPropertyNamesFast);
626 CallDescriptor const* descriptor = Linkage::GetRuntimeCallDescriptor(
627 zone(), function->function_id, 1, Operator::kNoProperties,
628 CallDescriptor::kNeedsFrameState);
629 Node* cache_type = effect = graph()->NewNode(
630 common()->Call(descriptor),
631 jsgraph()->CEntryStubConstant(function->result_size), object,
632 jsgraph()->ExternalConstant(function->function_id),
633 jsgraph()->Int32Constant(1), context, frame_state, effect, control);
634 control = graph()->NewNode(common()->IfSuccess(), cache_type);
635
636 Node* object_map = effect = graph()->NewNode(
637 machine()->Load(MachineType::AnyTagged()), object,
638 jsgraph()->IntPtrConstant(HeapObject::kMapOffset - kHeapObjectTag),
639 effect, control);
640 Node* cache_type_map = effect = graph()->NewNode(
641 machine()->Load(MachineType::AnyTagged()), cache_type,
642 jsgraph()->IntPtrConstant(HeapObject::kMapOffset - kHeapObjectTag),
643 effect, control);
644 Node* meta_map = jsgraph()->HeapConstant(isolate()->factory()->meta_map());
645
646 // If we got a map from the GetPropertyNamesFast runtime call, we can do a
647 // fast modification check. Otherwise, we got a fixed array, and we have to
648 // perform a slow check on every iteration.
649 Node* check0 =
650 graph()->NewNode(machine()->WordEqual(), cache_type_map, meta_map);
651 Node* branch0 =
652 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
653
654 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
655 Node* cache_array_true0;
656 Node* cache_length_true0;
657 Node* cache_type_true0;
658 Node* etrue0;
659 {
660 // Enum cache case.
661 Node* cache_type_enum_length = etrue0 = graph()->NewNode(
662 machine()->Load(MachineType::Uint32()), cache_type,
663 jsgraph()->IntPtrConstant(Map::kBitField3Offset - kHeapObjectTag),
664 effect, if_true0);
665 cache_type_enum_length =
666 graph()->NewNode(machine()->Word32And(), cache_type_enum_length,
667 jsgraph()->Uint32Constant(Map::EnumLengthBits::kMask));
668
669 Node* check1 =
670 graph()->NewNode(machine()->Word32Equal(), cache_type_enum_length,
671 jsgraph()->Int32Constant(0));
672 Node* branch1 =
673 graph()->NewNode(common()->Branch(BranchHint::kTrue), check1, if_true0);
674
675 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
676 Node* cache_array_true1;
677 Node* etrue1;
678 {
679 // No properties to enumerate.
680 cache_array_true1 =
681 jsgraph()->HeapConstant(isolate()->factory()->empty_fixed_array());
682 etrue1 = etrue0;
683 }
684
685 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
686 Node* cache_array_false1;
687 Node* efalse1;
688 {
689 // Load the enumeration cache from the instance descriptors of {object}.
690 Node* object_map_descriptors = efalse1 = graph()->NewNode(
691 machine()->Load(MachineType::AnyTagged()), object_map,
692 jsgraph()->IntPtrConstant(Map::kDescriptorsOffset - kHeapObjectTag),
693 etrue0, if_false1);
694 Node* object_map_enum_cache = efalse1 = graph()->NewNode(
695 machine()->Load(MachineType::AnyTagged()), object_map_descriptors,
696 jsgraph()->IntPtrConstant(DescriptorArray::kEnumCacheOffset -
697 kHeapObjectTag),
698 efalse1, if_false1);
699 cache_array_false1 = efalse1 = graph()->NewNode(
700 machine()->Load(MachineType::AnyTagged()), object_map_enum_cache,
701 jsgraph()->IntPtrConstant(
702 DescriptorArray::kEnumCacheBridgeCacheOffset - kHeapObjectTag),
703 efalse1, if_false1);
704 }
705
706 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
707 etrue0 =
708 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0);
709 cache_array_true0 =
710 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
711 cache_array_true1, cache_array_false1, if_true0);
712
713 cache_length_true0 = graph()->NewNode(
714 machine()->WordShl(),
715 machine()->Is64()
716 ? graph()->NewNode(machine()->ChangeUint32ToUint64(),
717 cache_type_enum_length)
718 : cache_type_enum_length,
719 jsgraph()->Int32Constant(kSmiShiftSize + kSmiTagSize));
720 cache_type_true0 = cache_type;
721 }
722
723 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
724 Node* cache_array_false0;
725 Node* cache_length_false0;
726 Node* cache_type_false0;
727 Node* efalse0;
728 {
729 // FixedArray case.
730 cache_type_false0 = jsgraph()->OneConstant(); // Smi means slow check
731 cache_array_false0 = cache_type;
732 cache_length_false0 = efalse0 = graph()->NewNode(
733 machine()->Load(MachineType::AnyTagged()), cache_array_false0,
734 jsgraph()->IntPtrConstant(FixedArray::kLengthOffset - kHeapObjectTag),
735 effect, if_false0);
736 }
737
738 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
739 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
740 Node* cache_array =
741 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
742 cache_array_true0, cache_array_false0, control);
743 Node* cache_length =
744 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
745 cache_length_true0, cache_length_false0, control);
746 cache_type =
747 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
748 cache_type_true0, cache_type_false0, control);
749
750 for (auto edge : node->use_edges()) {
751 if (NodeProperties::IsEffectEdge(edge)) {
752 edge.UpdateTo(effect);
753 } else if (NodeProperties::IsControlEdge(edge)) {
754 Node* const use = edge.from();
755 if (use->opcode() == IrOpcode::kIfSuccess) {
756 use->ReplaceUses(control);
757 use->Kill();
758 } else if (use->opcode() == IrOpcode::kIfException) {
759 edge.UpdateTo(cache_type_true0);
760 } else {
761 UNREACHABLE();
762 }
763 } else {
764 Node* const use = edge.from();
765 DCHECK(NodeProperties::IsValueEdge(edge));
766 DCHECK_EQ(IrOpcode::kProjection, use->opcode());
767 switch (ProjectionIndexOf(use->op())) {
768 case 0:
769 use->ReplaceUses(cache_type);
770 break;
771 case 1:
772 use->ReplaceUses(cache_array);
773 break;
774 case 2:
775 use->ReplaceUses(cache_length);
776 break;
777 default:
778 UNREACHABLE();
779 break;
780 }
781 use->Kill();
782 }
783 }
784}
785
786
787void JSGenericLowering::LowerJSForInStep(Node* node) {
788 ReplaceWithRuntimeCall(node, Runtime::kForInStep);
789}
790
791
792void JSGenericLowering::LowerJSLoadMessage(Node* node) {
793 ExternalReference message_address =
794 ExternalReference::address_of_pending_message_obj(isolate());
795 node->RemoveInput(NodeProperties::FirstContextIndex(node));
796 node->InsertInput(zone(), 0, jsgraph()->ExternalConstant(message_address));
797 node->InsertInput(zone(), 1, jsgraph()->IntPtrConstant(0));
798 NodeProperties::ChangeOp(node, machine()->Load(MachineType::AnyTagged()));
799}
800
801
802void JSGenericLowering::LowerJSStoreMessage(Node* node) {
803 ExternalReference message_address =
804 ExternalReference::address_of_pending_message_obj(isolate());
805 node->RemoveInput(NodeProperties::FirstContextIndex(node));
806 node->InsertInput(zone(), 0, jsgraph()->ExternalConstant(message_address));
807 node->InsertInput(zone(), 1, jsgraph()->IntPtrConstant(0));
808 StoreRepresentation representation(MachineRepresentation::kTagged,
809 kNoWriteBarrier);
810 NodeProperties::ChangeOp(node, machine()->Store(representation));
811}
812
813
814void JSGenericLowering::LowerJSYield(Node* node) { UNIMPLEMENTED(); }
815
816
817void JSGenericLowering::LowerJSStackCheck(Node* node) {
818 Node* effect = NodeProperties::GetEffectInput(node);
819 Node* control = NodeProperties::GetControlInput(node);
820
821 Node* limit = graph()->NewNode(
822 machine()->Load(MachineType::Pointer()),
823 jsgraph()->ExternalConstant(
824 ExternalReference::address_of_stack_limit(isolate())),
825 jsgraph()->IntPtrConstant(0), effect, control);
826 Node* pointer = graph()->NewNode(machine()->LoadStackPointer());
827
828 Node* check = graph()->NewNode(machine()->UintLessThan(), limit, pointer);
829 Node* branch =
830 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
831
832 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
833 Node* etrue = effect;
834
835 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
836 NodeProperties::ReplaceControlInput(node, if_false);
837 Node* efalse = node;
838
839 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
840 Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
841
842 // Wire the new diamond into the graph, {node} can still throw.
843 NodeProperties::ReplaceUses(node, node, ephi, node, node);
844 NodeProperties::ReplaceEffectInput(ephi, efalse, 1);
845
846 // TODO(mstarzinger): This iteration cuts out the IfSuccess projection from
847 // the node and places it inside the diamond. Come up with a helper method!
848 for (Node* use : node->uses()) {
849 if (use->opcode() == IrOpcode::kIfSuccess) {
850 use->ReplaceUses(merge);
851 merge->ReplaceInput(1, use);
852 }
853 }
854
855 // Turn the stack check into a runtime call.
856 ReplaceWithRuntimeCall(node, Runtime::kStackGuard);
857}
858
859
860Zone* JSGenericLowering::zone() const { return graph()->zone(); }
861
862
863Isolate* JSGenericLowering::isolate() const { return jsgraph()->isolate(); }
864
865
866Graph* JSGenericLowering::graph() const { return jsgraph()->graph(); }
867
868
869CommonOperatorBuilder* JSGenericLowering::common() const {
870 return jsgraph()->common();
871}
872
873
874MachineOperatorBuilder* JSGenericLowering::machine() const {
875 return jsgraph()->machine();
876}
877
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000878} // namespace compiler
879} // namespace internal
880} // namespace v8