OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/code-factory.h" | 5 #include "src/code-factory.h" |
6 #include "src/code-stubs.h" | 6 #include "src/code-stubs.h" |
7 #include "src/compiler/common-operator.h" | 7 #include "src/compiler/common-operator.h" |
8 #include "src/compiler/js-generic-lowering.h" | 8 #include "src/compiler/js-generic-lowering.h" |
9 #include "src/compiler/machine-operator.h" | 9 #include "src/compiler/machine-operator.h" |
10 #include "src/compiler/node-aux-data-inl.h" | 10 #include "src/compiler/node-aux-data-inl.h" |
11 #include "src/compiler/node-matchers.h" | 11 #include "src/compiler/node-matchers.h" |
12 #include "src/compiler/node-properties.h" | 12 #include "src/compiler/node-properties.h" |
13 #include "src/compiler/operator-properties.h" | 13 #include "src/compiler/operator-properties.h" |
14 #include "src/unique.h" | 14 #include "src/unique.h" |
15 | 15 |
16 namespace v8 { | 16 namespace v8 { |
17 namespace internal { | 17 namespace internal { |
18 namespace compiler { | 18 namespace compiler { |
19 | 19 |
20 JSGenericLowering::JSGenericLowering(CompilationInfo* info, JSGraph* jsgraph) | 20 JSGenericLowering::JSGenericLowering(bool is_typing_enabled, JSGraph* jsgraph) |
21 : info_(info), | 21 : is_typing_enabled_(is_typing_enabled), jsgraph_(jsgraph) {} |
22 jsgraph_(jsgraph), | |
23 linkage_(new (jsgraph->zone()) Linkage(jsgraph->zone(), info)) {} | |
24 | 22 |
25 | 23 |
26 void JSGenericLowering::PatchOperator(Node* node, const Operator* op) { | 24 void JSGenericLowering::PatchOperator(Node* node, const Operator* op) { |
27 node->set_op(op); | 25 node->set_op(op); |
28 } | 26 } |
29 | 27 |
30 | 28 |
31 void JSGenericLowering::PatchInsertInput(Node* node, int index, Node* input) { | 29 void JSGenericLowering::PatchInsertInput(Node* node, int index, Node* input) { |
32 node->InsertInput(zone(), index, input); | 30 node->InsertInput(zone(), index, input); |
33 } | 31 } |
34 | 32 |
35 | 33 |
36 Reduction JSGenericLowering::Reduce(Node* node) { | 34 Reduction JSGenericLowering::Reduce(Node* node) { |
37 switch (node->opcode()) { | 35 switch (node->opcode()) { |
38 #define DECLARE_CASE(x) \ | 36 #define DECLARE_CASE(x) \ |
39 case IrOpcode::k##x: \ | 37 case IrOpcode::k##x: \ |
40 Lower##x(node); \ | 38 Lower##x(node); \ |
41 break; | 39 break; |
42 JS_OP_LIST(DECLARE_CASE) | 40 JS_OP_LIST(DECLARE_CASE) |
43 #undef DECLARE_CASE | 41 #undef DECLARE_CASE |
44 case IrOpcode::kBranch: | 42 case IrOpcode::kBranch: |
45 // TODO(mstarzinger): If typing is enabled then simplified lowering will | 43 // TODO(mstarzinger): If typing is enabled then simplified lowering will |
46 // have inserted the correct ChangeBoolToBit, otherwise we need to perform | 44 // have inserted the correct ChangeBoolToBit, otherwise we need to perform |
47 // poor-man's representation inference here and insert manual change. | 45 // poor-man's representation inference here and insert manual change. |
48 if (!info()->is_typing_enabled()) { | 46 if (!is_typing_enabled_) { |
49 Node* condition = node->InputAt(0); | 47 Node* condition = node->InputAt(0); |
50 if (condition->opcode() != IrOpcode::kAlways) { | 48 if (condition->opcode() != IrOpcode::kAlways) { |
51 Node* test = graph()->NewNode(machine()->WordEqual(), condition, | 49 Node* test = graph()->NewNode(machine()->WordEqual(), condition, |
52 jsgraph()->TrueConstant()); | 50 jsgraph()->TrueConstant()); |
53 node->ReplaceInput(0, test); | 51 node->ReplaceInput(0, test); |
54 } | 52 } |
55 break; | 53 break; |
56 } | 54 } |
57 // Fall-through. | 55 // Fall-through. |
58 default: | 56 default: |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 if (OperatorProperties::HasFrameStateInput(node->op())) { | 121 if (OperatorProperties::HasFrameStateInput(node->op())) { |
124 result |= CallDescriptor::kNeedsFrameState; | 122 result |= CallDescriptor::kNeedsFrameState; |
125 } | 123 } |
126 return result; | 124 return result; |
127 } | 125 } |
128 | 126 |
129 | 127 |
130 void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token) { | 128 void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token) { |
131 Callable callable = CodeFactory::CompareIC(isolate(), token); | 129 Callable callable = CodeFactory::CompareIC(isolate(), token); |
132 bool has_frame_state = OperatorProperties::HasFrameStateInput(node->op()); | 130 bool has_frame_state = OperatorProperties::HasFrameStateInput(node->op()); |
133 CallDescriptor* desc_compare = linkage()->GetStubCallDescriptor( | 131 CallDescriptor* desc_compare = Linkage::GetStubCallDescriptor( |
134 callable.descriptor(), 0, | 132 isolate(), zone(), callable.descriptor(), 0, |
135 CallDescriptor::kPatchableCallSiteWithNop | FlagsForNode(node)); | 133 CallDescriptor::kPatchableCallSiteWithNop | FlagsForNode(node)); |
136 NodeVector inputs(zone()); | 134 NodeVector inputs(zone()); |
137 inputs.reserve(node->InputCount() + 1); | 135 inputs.reserve(node->InputCount() + 1); |
138 inputs.push_back(jsgraph()->HeapConstant(callable.code())); | 136 inputs.push_back(jsgraph()->HeapConstant(callable.code())); |
139 inputs.push_back(NodeProperties::GetValueInput(node, 0)); | 137 inputs.push_back(NodeProperties::GetValueInput(node, 0)); |
140 inputs.push_back(NodeProperties::GetValueInput(node, 1)); | 138 inputs.push_back(NodeProperties::GetValueInput(node, 1)); |
141 inputs.push_back(NodeProperties::GetContextInput(node)); | 139 inputs.push_back(NodeProperties::GetContextInput(node)); |
142 if (node->op()->HasProperty(Operator::kPure)) { | 140 if (node->op()->HasProperty(Operator::kPure)) { |
143 // A pure (strict) comparison doesn't have an effect, control or frame | 141 // A pure (strict) comparison doesn't have an effect, control or frame |
144 // state. But for the graph, we need to add control and effect inputs. | 142 // state. But for the graph, we need to add control and effect inputs. |
(...skipping 20 matching lines...) Expand all Loading... |
165 node->RemoveInput(NodeProperties::FirstFrameStateIndex(node)); | 163 node->RemoveInput(NodeProperties::FirstFrameStateIndex(node)); |
166 } | 164 } |
167 | 165 |
168 ReplaceWithRuntimeCall(node, Runtime::kBooleanize); | 166 ReplaceWithRuntimeCall(node, Runtime::kBooleanize); |
169 } | 167 } |
170 | 168 |
171 | 169 |
172 void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable, | 170 void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable, |
173 CallDescriptor::Flags flags) { | 171 CallDescriptor::Flags flags) { |
174 Operator::Properties properties = node->op()->properties(); | 172 Operator::Properties properties = node->op()->properties(); |
175 CallDescriptor* desc = linkage()->GetStubCallDescriptor( | 173 CallDescriptor* desc = |
176 callable.descriptor(), 0, flags | FlagsForNode(node), properties); | 174 Linkage::GetStubCallDescriptor(isolate(), zone(), callable.descriptor(), |
| 175 0, flags | FlagsForNode(node), properties); |
177 Node* stub_code = jsgraph()->HeapConstant(callable.code()); | 176 Node* stub_code = jsgraph()->HeapConstant(callable.code()); |
178 PatchInsertInput(node, 0, stub_code); | 177 PatchInsertInput(node, 0, stub_code); |
179 PatchOperator(node, common()->Call(desc)); | 178 PatchOperator(node, common()->Call(desc)); |
180 } | 179 } |
181 | 180 |
182 | 181 |
183 void JSGenericLowering::ReplaceWithBuiltinCall(Node* node, | 182 void JSGenericLowering::ReplaceWithBuiltinCall(Node* node, |
184 Builtins::JavaScript id, | 183 Builtins::JavaScript id, |
185 int nargs) { | 184 int nargs) { |
186 Operator::Properties properties = node->op()->properties(); | 185 Operator::Properties properties = node->op()->properties(); |
187 Callable callable = | 186 Callable callable = |
188 CodeFactory::CallFunction(isolate(), nargs - 1, NO_CALL_FUNCTION_FLAGS); | 187 CodeFactory::CallFunction(isolate(), nargs - 1, NO_CALL_FUNCTION_FLAGS); |
189 CallDescriptor* desc = linkage()->GetStubCallDescriptor( | 188 CallDescriptor* desc = |
190 callable.descriptor(), nargs, FlagsForNode(node), properties); | 189 Linkage::GetStubCallDescriptor(isolate(), zone(), callable.descriptor(), |
| 190 nargs, FlagsForNode(node), properties); |
191 Node* global_object = graph()->NewNode( | 191 Node* global_object = graph()->NewNode( |
192 machine()->Load(kMachAnyTagged), NodeProperties::GetContextInput(node), | 192 machine()->Load(kMachAnyTagged), NodeProperties::GetContextInput(node), |
193 jsgraph()->IntPtrConstant( | 193 jsgraph()->IntPtrConstant( |
194 Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)), | 194 Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)), |
195 NodeProperties::GetEffectInput(node), graph()->start()); | 195 NodeProperties::GetEffectInput(node), graph()->start()); |
196 Node* builtins_object = graph()->NewNode( | 196 Node* builtins_object = graph()->NewNode( |
197 machine()->Load(kMachAnyTagged), global_object, | 197 machine()->Load(kMachAnyTagged), global_object, |
198 jsgraph()->IntPtrConstant(GlobalObject::kBuiltinsOffset - kHeapObjectTag), | 198 jsgraph()->IntPtrConstant(GlobalObject::kBuiltinsOffset - kHeapObjectTag), |
199 NodeProperties::GetEffectInput(node), graph()->start()); | 199 NodeProperties::GetEffectInput(node), graph()->start()); |
200 Node* function = graph()->NewNode( | 200 Node* function = graph()->NewNode( |
201 machine()->Load(kMachAnyTagged), builtins_object, | 201 machine()->Load(kMachAnyTagged), builtins_object, |
202 jsgraph()->IntPtrConstant(JSBuiltinsObject::OffsetOfFunctionWithId(id) - | 202 jsgraph()->IntPtrConstant(JSBuiltinsObject::OffsetOfFunctionWithId(id) - |
203 kHeapObjectTag), | 203 kHeapObjectTag), |
204 NodeProperties::GetEffectInput(node), graph()->start()); | 204 NodeProperties::GetEffectInput(node), graph()->start()); |
205 Node* stub_code = jsgraph()->HeapConstant(callable.code()); | 205 Node* stub_code = jsgraph()->HeapConstant(callable.code()); |
206 PatchInsertInput(node, 0, stub_code); | 206 PatchInsertInput(node, 0, stub_code); |
207 PatchInsertInput(node, 1, function); | 207 PatchInsertInput(node, 1, function); |
208 PatchOperator(node, common()->Call(desc)); | 208 PatchOperator(node, common()->Call(desc)); |
209 } | 209 } |
210 | 210 |
211 | 211 |
212 void JSGenericLowering::ReplaceWithRuntimeCall(Node* node, | 212 void JSGenericLowering::ReplaceWithRuntimeCall(Node* node, |
213 Runtime::FunctionId f, | 213 Runtime::FunctionId f, |
214 int nargs_override) { | 214 int nargs_override) { |
215 Operator::Properties properties = node->op()->properties(); | 215 Operator::Properties properties = node->op()->properties(); |
216 const Runtime::Function* fun = Runtime::FunctionForId(f); | 216 const Runtime::Function* fun = Runtime::FunctionForId(f); |
217 int nargs = (nargs_override < 0) ? fun->nargs : nargs_override; | 217 int nargs = (nargs_override < 0) ? fun->nargs : nargs_override; |
218 CallDescriptor* desc = | 218 CallDescriptor* desc = |
219 linkage()->GetRuntimeCallDescriptor(f, nargs, properties); | 219 Linkage::GetRuntimeCallDescriptor(zone(), f, nargs, properties); |
220 Node* ref = jsgraph()->ExternalConstant(ExternalReference(f, isolate())); | 220 Node* ref = jsgraph()->ExternalConstant(ExternalReference(f, isolate())); |
221 Node* arity = jsgraph()->Int32Constant(nargs); | 221 Node* arity = jsgraph()->Int32Constant(nargs); |
222 PatchInsertInput(node, 0, jsgraph()->CEntryStubConstant(fun->result_size)); | 222 PatchInsertInput(node, 0, jsgraph()->CEntryStubConstant(fun->result_size)); |
223 PatchInsertInput(node, nargs + 1, ref); | 223 PatchInsertInput(node, nargs + 1, ref); |
224 PatchInsertInput(node, nargs + 2, arity); | 224 PatchInsertInput(node, nargs + 2, arity); |
225 PatchOperator(node, common()->Call(desc)); | 225 PatchOperator(node, common()->Call(desc)); |
226 } | 226 } |
227 | 227 |
228 | 228 |
229 void JSGenericLowering::LowerJSUnaryNot(Node* node) { | 229 void JSGenericLowering::LowerJSUnaryNot(Node* node) { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 ReplaceWithBuiltinCall(node, Builtins::IN, 2); | 311 ReplaceWithBuiltinCall(node, Builtins::IN, 2); |
312 } | 312 } |
313 | 313 |
314 | 314 |
315 void JSGenericLowering::LowerJSInstanceOf(Node* node) { | 315 void JSGenericLowering::LowerJSInstanceOf(Node* node) { |
316 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( | 316 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( |
317 InstanceofStub::kReturnTrueFalseObject | | 317 InstanceofStub::kReturnTrueFalseObject | |
318 InstanceofStub::kArgsInRegisters); | 318 InstanceofStub::kArgsInRegisters); |
319 InstanceofStub stub(isolate(), flags); | 319 InstanceofStub stub(isolate(), flags); |
320 CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor(); | 320 CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor(); |
321 CallDescriptor* desc = | 321 CallDescriptor* desc = Linkage::GetStubCallDescriptor(isolate(), zone(), d, 0, |
322 linkage()->GetStubCallDescriptor(d, 0, FlagsForNode(node)); | 322 FlagsForNode(node)); |
323 Node* stub_code = jsgraph()->HeapConstant(stub.GetCode()); | 323 Node* stub_code = jsgraph()->HeapConstant(stub.GetCode()); |
324 PatchInsertInput(node, 0, stub_code); | 324 PatchInsertInput(node, 0, stub_code); |
325 PatchOperator(node, common()->Call(desc)); | 325 PatchOperator(node, common()->Call(desc)); |
326 } | 326 } |
327 | 327 |
328 | 328 |
329 void JSGenericLowering::LowerJSLoadContext(Node* node) { | 329 void JSGenericLowering::LowerJSLoadContext(Node* node) { |
330 const ContextAccess& access = ContextAccessOf(node->op()); | 330 const ContextAccess& access = ContextAccessOf(node->op()); |
331 for (size_t i = 0; i < access.depth(); ++i) { | 331 for (size_t i = 0; i < access.depth(); ++i) { |
332 node->ReplaceInput( | 332 node->ReplaceInput( |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 Unique<String> name = OpParameter<Unique<String>>(node); | 367 Unique<String> name = OpParameter<Unique<String>>(node); |
368 PatchInsertInput(node, 0, jsgraph()->HeapConstant(name)); | 368 PatchInsertInput(node, 0, jsgraph()->HeapConstant(name)); |
369 ReplaceWithRuntimeCall(node, Runtime::kPushCatchContext); | 369 ReplaceWithRuntimeCall(node, Runtime::kPushCatchContext); |
370 } | 370 } |
371 | 371 |
372 | 372 |
373 void JSGenericLowering::LowerJSCallConstruct(Node* node) { | 373 void JSGenericLowering::LowerJSCallConstruct(Node* node) { |
374 int arity = OpParameter<int>(node); | 374 int arity = OpParameter<int>(node); |
375 CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS); | 375 CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS); |
376 CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor(); | 376 CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor(); |
377 CallDescriptor* desc = | 377 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
378 linkage()->GetStubCallDescriptor(d, arity, FlagsForNode(node)); | 378 isolate(), zone(), d, arity, FlagsForNode(node)); |
379 Node* stub_code = jsgraph()->HeapConstant(stub.GetCode()); | 379 Node* stub_code = jsgraph()->HeapConstant(stub.GetCode()); |
380 Node* construct = NodeProperties::GetValueInput(node, 0); | 380 Node* construct = NodeProperties::GetValueInput(node, 0); |
381 PatchInsertInput(node, 0, stub_code); | 381 PatchInsertInput(node, 0, stub_code); |
382 PatchInsertInput(node, 1, jsgraph()->Int32Constant(arity - 1)); | 382 PatchInsertInput(node, 1, jsgraph()->Int32Constant(arity - 1)); |
383 PatchInsertInput(node, 2, construct); | 383 PatchInsertInput(node, 2, construct); |
384 PatchInsertInput(node, 3, jsgraph()->UndefinedConstant()); | 384 PatchInsertInput(node, 3, jsgraph()->UndefinedConstant()); |
385 PatchOperator(node, common()->Call(desc)); | 385 PatchOperator(node, common()->Call(desc)); |
386 } | 386 } |
387 | 387 |
388 | 388 |
(...skipping 22 matching lines...) Expand all Loading... |
411 | 411 |
412 // TODO(titzer): total hack to share function context constants. | 412 // TODO(titzer): total hack to share function context constants. |
413 // Remove this when the JSGraph canonicalizes heap constants. | 413 // Remove this when the JSGraph canonicalizes heap constants. |
414 Node* context = node->InputAt(index); | 414 Node* context = node->InputAt(index); |
415 HeapObjectMatcher<Context> context_const(context); | 415 HeapObjectMatcher<Context> context_const(context); |
416 if (!context_const.HasValue() || | 416 if (!context_const.HasValue() || |
417 *(context_const.Value().handle()) != function->context()) { | 417 *(context_const.Value().handle()) != function->context()) { |
418 context = jsgraph()->HeapConstant(Handle<Context>(function->context())); | 418 context = jsgraph()->HeapConstant(Handle<Context>(function->context())); |
419 } | 419 } |
420 node->ReplaceInput(index, context); | 420 node->ReplaceInput(index, context); |
421 CallDescriptor* desc = | 421 CallDescriptor* desc = Linkage::GetJSCallDescriptor( |
422 linkage()->GetJSCallDescriptor(1 + arg_count, FlagsForNode(node)); | 422 zone(), false, 1 + arg_count, FlagsForNode(node)); |
423 PatchOperator(node, common()->Call(desc)); | 423 PatchOperator(node, common()->Call(desc)); |
424 return true; | 424 return true; |
425 } | 425 } |
426 | 426 |
427 | 427 |
428 void JSGenericLowering::LowerJSCallFunction(Node* node) { | 428 void JSGenericLowering::LowerJSCallFunction(Node* node) { |
429 // Fast case: call function directly. | 429 // Fast case: call function directly. |
430 if (TryLowerDirectJSCall(node)) return; | 430 if (TryLowerDirectJSCall(node)) return; |
431 | 431 |
432 // General case: CallFunctionStub. | 432 // General case: CallFunctionStub. |
433 const CallFunctionParameters& p = CallFunctionParametersOf(node->op()); | 433 const CallFunctionParameters& p = CallFunctionParametersOf(node->op()); |
434 int arg_count = static_cast<int>(p.arity() - 2); | 434 int arg_count = static_cast<int>(p.arity() - 2); |
435 CallFunctionStub stub(isolate(), arg_count, p.flags()); | 435 CallFunctionStub stub(isolate(), arg_count, p.flags()); |
436 CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor(); | 436 CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor(); |
437 CallDescriptor* desc = linkage()->GetStubCallDescriptor( | 437 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
438 d, static_cast<int>(p.arity() - 1), FlagsForNode(node)); | 438 isolate(), zone(), d, static_cast<int>(p.arity() - 1), |
| 439 FlagsForNode(node)); |
439 Node* stub_code = jsgraph()->HeapConstant(stub.GetCode()); | 440 Node* stub_code = jsgraph()->HeapConstant(stub.GetCode()); |
440 PatchInsertInput(node, 0, stub_code); | 441 PatchInsertInput(node, 0, stub_code); |
441 PatchOperator(node, common()->Call(desc)); | 442 PatchOperator(node, common()->Call(desc)); |
442 } | 443 } |
443 | 444 |
444 | 445 |
445 void JSGenericLowering::LowerJSCallRuntime(Node* node) { | 446 void JSGenericLowering::LowerJSCallRuntime(Node* node) { |
446 const CallRuntimeParameters& p = CallRuntimeParametersOf(node->op()); | 447 const CallRuntimeParameters& p = CallRuntimeParametersOf(node->op()); |
447 ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity())); | 448 ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity())); |
448 } | 449 } |
449 | 450 |
450 } // namespace compiler | 451 } // namespace compiler |
451 } // namespace internal | 452 } // namespace internal |
452 } // namespace v8 | 453 } // namespace v8 |
OLD | NEW |