| 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 |