| 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-stubs.h" | 5 #include "src/code-stubs.h" |
| 6 #include "src/compiler/common-operator.h" | 6 #include "src/compiler/common-operator.h" |
| 7 #include "src/compiler/graph-inl.h" | 7 #include "src/compiler/graph-inl.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" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 class LoadICStubShim : public HydrogenCodeStub { | 22 class LoadICStubShim : public HydrogenCodeStub { |
| 23 public: | 23 public: |
| 24 LoadICStubShim(Isolate* isolate, ContextualMode contextual_mode) | 24 LoadICStubShim(Isolate* isolate, ContextualMode contextual_mode) |
| 25 : HydrogenCodeStub(isolate), contextual_mode_(contextual_mode) {} | 25 : HydrogenCodeStub(isolate), contextual_mode_(contextual_mode) {} |
| 26 | 26 |
| 27 virtual Handle<Code> GenerateCode() OVERRIDE { | 27 virtual Handle<Code> GenerateCode() OVERRIDE { |
| 28 ExtraICState extra_state = LoadIC::ComputeExtraICState(contextual_mode_); | 28 ExtraICState extra_state = LoadIC::ComputeExtraICState(contextual_mode_); |
| 29 return LoadIC::initialize_stub(isolate(), extra_state); | 29 return LoadIC::initialize_stub(isolate(), extra_state); |
| 30 } | 30 } |
| 31 | 31 |
| 32 virtual void InitializeInterfaceDescriptor( | 32 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { |
| 33 CodeStubInterfaceDescriptor* descriptor) OVERRIDE { | 33 return LoadDescriptor(isolate()); |
| 34 LoadDescriptor call_descriptor(isolate()); | |
| 35 descriptor->Initialize(MajorKey(), call_descriptor); | |
| 36 } | 34 } |
| 37 | 35 |
| 38 private: | 36 private: |
| 39 virtual Major MajorKey() const OVERRIDE { return NoCache; } | 37 virtual Major MajorKey() const OVERRIDE { return NoCache; } |
| 40 virtual bool UseSpecialCache() OVERRIDE { return true; } | 38 virtual bool UseSpecialCache() OVERRIDE { return true; } |
| 41 | 39 |
| 42 ContextualMode contextual_mode_; | 40 ContextualMode contextual_mode_; |
| 43 }; | 41 }; |
| 44 | 42 |
| 45 | 43 |
| 46 // TODO(mstarzinger): This is a temporary shim to be able to call an IC stub | 44 // TODO(mstarzinger): This is a temporary shim to be able to call an IC stub |
| 47 // which doesn't have an interface descriptor yet. It mimics a hydrogen code | 45 // which doesn't have an interface descriptor yet. It mimics a hydrogen code |
| 48 // stub for the underlying IC stub code. | 46 // stub for the underlying IC stub code. |
| 49 class KeyedLoadICStubShim : public HydrogenCodeStub { | 47 class KeyedLoadICStubShim : public HydrogenCodeStub { |
| 50 public: | 48 public: |
| 51 explicit KeyedLoadICStubShim(Isolate* isolate) : HydrogenCodeStub(isolate) {} | 49 explicit KeyedLoadICStubShim(Isolate* isolate) : HydrogenCodeStub(isolate) {} |
| 52 | 50 |
| 53 virtual Handle<Code> GenerateCode() OVERRIDE { | 51 virtual Handle<Code> GenerateCode() OVERRIDE { |
| 54 return isolate()->builtins()->KeyedLoadIC_Initialize(); | 52 return isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 55 } | 53 } |
| 56 | 54 |
| 57 virtual void InitializeInterfaceDescriptor( | 55 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { |
| 58 CodeStubInterfaceDescriptor* descriptor) OVERRIDE { | 56 return LoadDescriptor(isolate()); |
| 59 LoadDescriptor call_descriptor(isolate()); | |
| 60 descriptor->Initialize(MajorKey(), call_descriptor); | |
| 61 } | 57 } |
| 62 | 58 |
| 63 private: | 59 private: |
| 64 virtual Major MajorKey() const OVERRIDE { return NoCache; } | 60 virtual Major MajorKey() const OVERRIDE { return NoCache; } |
| 65 virtual bool UseSpecialCache() OVERRIDE { return true; } | 61 virtual bool UseSpecialCache() OVERRIDE { return true; } |
| 66 }; | 62 }; |
| 67 | 63 |
| 68 | 64 |
| 69 // TODO(mstarzinger): This is a temporary shim to be able to call an IC stub | 65 // TODO(mstarzinger): This is a temporary shim to be able to call an IC stub |
| 70 // which doesn't have an interface descriptor yet. It mimics a hydrogen code | 66 // which doesn't have an interface descriptor yet. It mimics a hydrogen code |
| 71 // stub for the underlying IC stub code. | 67 // stub for the underlying IC stub code. |
| 72 class StoreICStubShim : public HydrogenCodeStub { | 68 class StoreICStubShim : public HydrogenCodeStub { |
| 73 public: | 69 public: |
| 74 StoreICStubShim(Isolate* isolate, StrictMode strict_mode) | 70 StoreICStubShim(Isolate* isolate, StrictMode strict_mode) |
| 75 : HydrogenCodeStub(isolate), strict_mode_(strict_mode) {} | 71 : HydrogenCodeStub(isolate), strict_mode_(strict_mode) {} |
| 76 | 72 |
| 77 virtual Handle<Code> GenerateCode() OVERRIDE { | 73 virtual Handle<Code> GenerateCode() OVERRIDE { |
| 78 return StoreIC::initialize_stub(isolate(), strict_mode_); | 74 return StoreIC::initialize_stub(isolate(), strict_mode_); |
| 79 } | 75 } |
| 80 | 76 |
| 81 virtual void InitializeInterfaceDescriptor( | 77 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { |
| 82 CodeStubInterfaceDescriptor* descriptor) OVERRIDE { | 78 return StoreDescriptor(isolate()); |
| 83 StoreDescriptor call_descriptor(isolate()); | |
| 84 descriptor->Initialize(MajorKey(), call_descriptor); | |
| 85 } | 79 } |
| 86 | 80 |
| 87 private: | 81 private: |
| 88 virtual Major MajorKey() const OVERRIDE { return NoCache; } | 82 virtual Major MajorKey() const OVERRIDE { return NoCache; } |
| 89 virtual bool UseSpecialCache() OVERRIDE { return true; } | 83 virtual bool UseSpecialCache() OVERRIDE { return true; } |
| 90 | 84 |
| 91 StrictMode strict_mode_; | 85 StrictMode strict_mode_; |
| 92 }; | 86 }; |
| 93 | 87 |
| 94 | 88 |
| 95 // TODO(mstarzinger): This is a temporary shim to be able to call an IC stub | 89 // TODO(mstarzinger): This is a temporary shim to be able to call an IC stub |
| 96 // which doesn't have an interface descriptor yet. It mimics a hydrogen code | 90 // which doesn't have an interface descriptor yet. It mimics a hydrogen code |
| 97 // stub for the underlying IC stub code. | 91 // stub for the underlying IC stub code. |
| 98 class KeyedStoreICStubShim : public HydrogenCodeStub { | 92 class KeyedStoreICStubShim : public HydrogenCodeStub { |
| 99 public: | 93 public: |
| 100 KeyedStoreICStubShim(Isolate* isolate, StrictMode strict_mode) | 94 KeyedStoreICStubShim(Isolate* isolate, StrictMode strict_mode) |
| 101 : HydrogenCodeStub(isolate), strict_mode_(strict_mode) {} | 95 : HydrogenCodeStub(isolate), strict_mode_(strict_mode) {} |
| 102 | 96 |
| 103 virtual Handle<Code> GenerateCode() OVERRIDE { | 97 virtual Handle<Code> GenerateCode() OVERRIDE { |
| 104 return strict_mode_ == SLOPPY | 98 return strict_mode_ == SLOPPY |
| 105 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 99 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 106 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 100 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 107 } | 101 } |
| 108 | 102 |
| 109 virtual void InitializeInterfaceDescriptor( | 103 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { |
| 110 CodeStubInterfaceDescriptor* descriptor) OVERRIDE { | 104 return StoreDescriptor(isolate()); |
| 111 StoreDescriptor call_descriptor(isolate()); | |
| 112 descriptor->Initialize(MajorKey(), call_descriptor); | |
| 113 } | 105 } |
| 114 | 106 |
| 115 private: | 107 private: |
| 116 virtual Major MajorKey() const OVERRIDE { return NoCache; } | 108 virtual Major MajorKey() const OVERRIDE { return NoCache; } |
| 117 virtual bool UseSpecialCache() OVERRIDE { return true; } | 109 virtual bool UseSpecialCache() OVERRIDE { return true; } |
| 118 | 110 |
| 119 StrictMode strict_mode_; | 111 StrictMode strict_mode_; |
| 120 }; | 112 }; |
| 121 | 113 |
| 122 | 114 |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 if (OperatorProperties::HasFrameStateInput(node->op())) { | 254 if (OperatorProperties::HasFrameStateInput(node->op())) { |
| 263 result |= CallDescriptor::kNeedsFrameState; | 255 result |= CallDescriptor::kNeedsFrameState; |
| 264 } | 256 } |
| 265 return result; | 257 return result; |
| 266 } | 258 } |
| 267 | 259 |
| 268 | 260 |
| 269 void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token, | 261 void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token, |
| 270 bool pure) { | 262 bool pure) { |
| 271 BinaryOpICStub stub(isolate(), Token::ADD); // TODO(mstarzinger): Hack. | 263 BinaryOpICStub stub(isolate(), Token::ADD); // TODO(mstarzinger): Hack. |
| 272 CodeStubInterfaceDescriptor d(&stub); | 264 CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor(); |
| 273 bool has_frame_state = OperatorProperties::HasFrameStateInput(node->op()); | 265 bool has_frame_state = OperatorProperties::HasFrameStateInput(node->op()); |
| 274 CallDescriptor* desc_compare = linkage()->GetStubCallDescriptor( | 266 CallDescriptor* desc_compare = linkage()->GetStubCallDescriptor( |
| 275 &d, 0, CallDescriptor::kPatchableCallSiteWithNop | FlagsForNode(node)); | 267 d, 0, CallDescriptor::kPatchableCallSiteWithNop | FlagsForNode(node)); |
| 276 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), token); | 268 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), token); |
| 277 NodeVector inputs(zone()); | 269 NodeVector inputs(zone()); |
| 278 inputs.reserve(node->InputCount() + 1); | 270 inputs.reserve(node->InputCount() + 1); |
| 279 inputs.push_back(CodeConstant(ic)); | 271 inputs.push_back(CodeConstant(ic)); |
| 280 inputs.push_back(NodeProperties::GetValueInput(node, 0)); | 272 inputs.push_back(NodeProperties::GetValueInput(node, 0)); |
| 281 inputs.push_back(NodeProperties::GetValueInput(node, 1)); | 273 inputs.push_back(NodeProperties::GetValueInput(node, 1)); |
| 282 inputs.push_back(NodeProperties::GetContextInput(node)); | 274 inputs.push_back(NodeProperties::GetContextInput(node)); |
| 283 if (pure) { | 275 if (pure) { |
| 284 // A pure (strict) comparison doesn't have an effect, control or frame | 276 // A pure (strict) comparison doesn't have an effect, control or frame |
| 285 // state. But for the graph, we need to add control and effect inputs. | 277 // state. But for the graph, we need to add control and effect inputs. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 312 } | 304 } |
| 313 node->TrimInputCount(dest); | 305 node->TrimInputCount(dest); |
| 314 } | 306 } |
| 315 | 307 |
| 316 ReplaceWithRuntimeCall(node, Runtime::kBooleanize); | 308 ReplaceWithRuntimeCall(node, Runtime::kBooleanize); |
| 317 } | 309 } |
| 318 | 310 |
| 319 | 311 |
| 320 void JSGenericLowering::ReplaceWithStubCall(Node* node, HydrogenCodeStub* stub, | 312 void JSGenericLowering::ReplaceWithStubCall(Node* node, HydrogenCodeStub* stub, |
| 321 CallDescriptor::Flags flags) { | 313 CallDescriptor::Flags flags) { |
| 322 CodeStubInterfaceDescriptor d(stub); | 314 CallInterfaceDescriptor d = stub->GetCallInterfaceDescriptor(); |
| 323 CallDescriptor* desc = | 315 CallDescriptor* desc = |
| 324 linkage()->GetStubCallDescriptor(&d, 0, flags | FlagsForNode(node)); | 316 linkage()->GetStubCallDescriptor(d, 0, flags | FlagsForNode(node)); |
| 325 Node* stub_code = CodeConstant(stub->GetCode()); | 317 Node* stub_code = CodeConstant(stub->GetCode()); |
| 326 PatchInsertInput(node, 0, stub_code); | 318 PatchInsertInput(node, 0, stub_code); |
| 327 PatchOperator(node, common()->Call(desc)); | 319 PatchOperator(node, common()->Call(desc)); |
| 328 } | 320 } |
| 329 | 321 |
| 330 | 322 |
| 331 void JSGenericLowering::ReplaceWithBuiltinCall(Node* node, | 323 void JSGenericLowering::ReplaceWithBuiltinCall(Node* node, |
| 332 Builtins::JavaScript id, | 324 Builtins::JavaScript id, |
| 333 int nargs) { | 325 int nargs) { |
| 334 CallFunctionStub stub(isolate(), nargs - 1, NO_CALL_FUNCTION_FLAGS); | 326 CallFunctionStub stub(isolate(), nargs - 1, NO_CALL_FUNCTION_FLAGS); |
| 335 CodeStubInterfaceDescriptor d(&stub); | 327 CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor(); |
| 336 CallDescriptor* desc = linkage()->GetStubCallDescriptor(&d, nargs); | 328 CallDescriptor* desc = linkage()->GetStubCallDescriptor(d, nargs); |
| 337 // TODO(mstarzinger): Accessing the builtins object this way prevents sharing | 329 // TODO(mstarzinger): Accessing the builtins object this way prevents sharing |
| 338 // of code across native contexts. Fix this by loading from given context. | 330 // of code across native contexts. Fix this by loading from given context. |
| 339 Handle<JSFunction> function( | 331 Handle<JSFunction> function( |
| 340 JSFunction::cast(info()->context()->builtins()->javascript_builtin(id))); | 332 JSFunction::cast(info()->context()->builtins()->javascript_builtin(id))); |
| 341 Node* stub_code = CodeConstant(stub.GetCode()); | 333 Node* stub_code = CodeConstant(stub.GetCode()); |
| 342 Node* function_node = FunctionConstant(function); | 334 Node* function_node = FunctionConstant(function); |
| 343 PatchInsertInput(node, 0, stub_code); | 335 PatchInsertInput(node, 0, stub_code); |
| 344 PatchInsertInput(node, 1, function_node); | 336 PatchInsertInput(node, 1, function_node); |
| 345 PatchOperator(node, common()->Call(desc)); | 337 PatchOperator(node, common()->Call(desc)); |
| 346 } | 338 } |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 450 ReplaceWithBuiltinCall(node, Builtins::IN, 2); | 442 ReplaceWithBuiltinCall(node, Builtins::IN, 2); |
| 451 return node; | 443 return node; |
| 452 } | 444 } |
| 453 | 445 |
| 454 | 446 |
| 455 Node* JSGenericLowering::LowerJSInstanceOf(Node* node) { | 447 Node* JSGenericLowering::LowerJSInstanceOf(Node* node) { |
| 456 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( | 448 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( |
| 457 InstanceofStub::kReturnTrueFalseObject | | 449 InstanceofStub::kReturnTrueFalseObject | |
| 458 InstanceofStub::kArgsInRegisters); | 450 InstanceofStub::kArgsInRegisters); |
| 459 InstanceofStub stub(isolate(), flags); | 451 InstanceofStub stub(isolate(), flags); |
| 460 CodeStubInterfaceDescriptor d(&stub); | 452 CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor(); |
| 461 CallDescriptor* desc = linkage()->GetStubCallDescriptor(&d, 0); | 453 CallDescriptor* desc = linkage()->GetStubCallDescriptor(d, 0); |
| 462 Node* stub_code = CodeConstant(stub.GetCode()); | 454 Node* stub_code = CodeConstant(stub.GetCode()); |
| 463 PatchInsertInput(node, 0, stub_code); | 455 PatchInsertInput(node, 0, stub_code); |
| 464 PatchOperator(node, common()->Call(desc)); | 456 PatchOperator(node, common()->Call(desc)); |
| 465 return node; | 457 return node; |
| 466 } | 458 } |
| 467 | 459 |
| 468 | 460 |
| 469 Node* JSGenericLowering::LowerJSLoadContext(Node* node) { | 461 Node* JSGenericLowering::LowerJSLoadContext(Node* node) { |
| 470 ContextAccess access = OpParameter<ContextAccess>(node); | 462 ContextAccess access = OpParameter<ContextAccess>(node); |
| 471 // TODO(mstarzinger): Use simplified operators instead of machine operators | 463 // TODO(mstarzinger): Use simplified operators instead of machine operators |
| (...skipping 27 matching lines...) Expand all Loading... |
| 499 node->ReplaceInput(2, NodeProperties::GetValueInput(node, 1)); | 491 node->ReplaceInput(2, NodeProperties::GetValueInput(node, 1)); |
| 500 node->ReplaceInput(1, Int32Constant(Context::SlotOffset(access.index()))); | 492 node->ReplaceInput(1, Int32Constant(Context::SlotOffset(access.index()))); |
| 501 PatchOperator(node, machine()->Store(kMachAnyTagged, kFullWriteBarrier)); | 493 PatchOperator(node, machine()->Store(kMachAnyTagged, kFullWriteBarrier)); |
| 502 return node; | 494 return node; |
| 503 } | 495 } |
| 504 | 496 |
| 505 | 497 |
| 506 Node* JSGenericLowering::LowerJSCallConstruct(Node* node) { | 498 Node* JSGenericLowering::LowerJSCallConstruct(Node* node) { |
| 507 int arity = OpParameter<int>(node); | 499 int arity = OpParameter<int>(node); |
| 508 CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS); | 500 CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS); |
| 509 CodeStubInterfaceDescriptor d(&stub); | 501 CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor(); |
| 510 CallDescriptor* desc = | 502 CallDescriptor* desc = |
| 511 linkage()->GetStubCallDescriptor(&d, arity, FlagsForNode(node)); | 503 linkage()->GetStubCallDescriptor(d, arity, FlagsForNode(node)); |
| 512 Node* stub_code = CodeConstant(stub.GetCode()); | 504 Node* stub_code = CodeConstant(stub.GetCode()); |
| 513 Node* construct = NodeProperties::GetValueInput(node, 0); | 505 Node* construct = NodeProperties::GetValueInput(node, 0); |
| 514 PatchInsertInput(node, 0, stub_code); | 506 PatchInsertInput(node, 0, stub_code); |
| 515 PatchInsertInput(node, 1, Int32Constant(arity - 1)); | 507 PatchInsertInput(node, 1, Int32Constant(arity - 1)); |
| 516 PatchInsertInput(node, 2, construct); | 508 PatchInsertInput(node, 2, construct); |
| 517 PatchInsertInput(node, 3, jsgraph()->UndefinedConstant()); | 509 PatchInsertInput(node, 3, jsgraph()->UndefinedConstant()); |
| 518 PatchOperator(node, common()->Call(desc)); | 510 PatchOperator(node, common()->Call(desc)); |
| 519 return node; | 511 return node; |
| 520 } | 512 } |
| 521 | 513 |
| 522 | 514 |
| 523 Node* JSGenericLowering::LowerJSCallFunction(Node* node) { | 515 Node* JSGenericLowering::LowerJSCallFunction(Node* node) { |
| 524 CallParameters p = OpParameter<CallParameters>(node); | 516 CallParameters p = OpParameter<CallParameters>(node); |
| 525 CallFunctionStub stub(isolate(), p.arity - 2, p.flags); | 517 CallFunctionStub stub(isolate(), p.arity - 2, p.flags); |
| 526 CodeStubInterfaceDescriptor d(&stub); | 518 CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor(); |
| 527 CallDescriptor* desc = | 519 CallDescriptor* desc = |
| 528 linkage()->GetStubCallDescriptor(&d, p.arity - 1, FlagsForNode(node)); | 520 linkage()->GetStubCallDescriptor(d, p.arity - 1, FlagsForNode(node)); |
| 529 Node* stub_code = CodeConstant(stub.GetCode()); | 521 Node* stub_code = CodeConstant(stub.GetCode()); |
| 530 PatchInsertInput(node, 0, stub_code); | 522 PatchInsertInput(node, 0, stub_code); |
| 531 PatchOperator(node, common()->Call(desc)); | 523 PatchOperator(node, common()->Call(desc)); |
| 532 return node; | 524 return node; |
| 533 } | 525 } |
| 534 | 526 |
| 535 | 527 |
| 536 Node* JSGenericLowering::LowerJSCallRuntime(Node* node) { | 528 Node* JSGenericLowering::LowerJSCallRuntime(Node* node) { |
| 537 Runtime::FunctionId function = OpParameter<Runtime::FunctionId>(node); | 529 Runtime::FunctionId function = OpParameter<Runtime::FunctionId>(node); |
| 538 int arity = OperatorProperties::GetValueInputCount(node->op()); | 530 int arity = OperatorProperties::GetValueInputCount(node->op()); |
| 539 ReplaceWithRuntimeCall(node, function, arity); | 531 ReplaceWithRuntimeCall(node, function, arity); |
| 540 return node; | 532 return node; |
| 541 } | 533 } |
| 542 | 534 |
| 543 } // namespace compiler | 535 } // namespace compiler |
| 544 } // namespace internal | 536 } // namespace internal |
| 545 } // namespace v8 | 537 } // namespace v8 |
| OLD | NEW |