From: mstarzinger@chromium.org Date: Tue, 5 Aug 2014 13:32:26 +0000 (+0000) Subject: Implement lowering of JS[Load,Store][Property,Named] to ICs. X-Git-Tag: upstream/4.7.83~7826 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e7c87c420a555069fe7958367c62995d3ab38b4f;p=platform%2Fupstream%2Fv8.git Implement lowering of JS[Load,Store][Property,Named] to ICs. R=titzer@chromium.org Review URL: https://codereview.chromium.org/439263004 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22877 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc index f4d4d3a..3ae5aa4 100644 --- a/src/compiler/ast-graph-builder.cc +++ b/src/compiler/ast-graph-builder.cc @@ -1795,14 +1795,6 @@ Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value, switch (variable->location()) { case Variable::UNALLOCATED: { // Global var, const, or let variable. - if (!info()->is_native()) { - // TODO(turbofan): This special case is needed only because we don't - // use StoreICs yet. Remove this once StoreNamed is lowered to an IC. - Node* name = jsgraph()->Constant(variable->name()); - Node* strict = jsgraph()->Constant(strict_mode()); - Operator* op = javascript()->Runtime(Runtime::kStoreLookupSlot, 4); - return NewNode(op, value, current_context(), name, strict); - } Node* global = BuildLoadGlobalObject(); PrintableUnique name = MakeUnique(variable->name()); Operator* op = javascript()->StoreNamed(name); diff --git a/src/compiler/js-generic-lowering.cc b/src/compiler/js-generic-lowering.cc index f87006f..8b230c9 100644 --- a/src/compiler/js-generic-lowering.cc +++ b/src/compiler/js-generic-lowering.cc @@ -29,6 +29,132 @@ static CodeStubInterfaceDescriptor* GetInterfaceDescriptor(Isolate* isolate, } +// TODO(mstarzinger): This is a temporary shim to be able to call an IC stub +// which doesn't have an interface descriptor yet. It mimics a hydrogen code +// stub for the underlying IC stub code. +class LoadICStubShim : public HydrogenCodeStub { + public: + LoadICStubShim(Isolate* isolate, ContextualMode contextual_mode) + : HydrogenCodeStub(isolate), contextual_mode_(contextual_mode) { + i::compiler::GetInterfaceDescriptor(isolate, this); + } + + virtual Handle GenerateCode() V8_OVERRIDE { + ExtraICState extra_state = LoadIC::ComputeExtraICState(contextual_mode_); + return LoadIC::initialize_stub(isolate(), extra_state); + } + + virtual void InitializeInterfaceDescriptor( + CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE { + Register registers[] = { InterfaceDescriptor::ContextRegister(), + LoadIC::ReceiverRegister(), + LoadIC::NameRegister() }; + descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); + } + + private: + virtual Major MajorKey() const V8_OVERRIDE { return NoCache; } + virtual int NotMissMinorKey() const V8_OVERRIDE { return 0; } + virtual bool UseSpecialCache() V8_OVERRIDE { return true; } + + ContextualMode contextual_mode_; +}; + + +// TODO(mstarzinger): This is a temporary shim to be able to call an IC stub +// which doesn't have an interface descriptor yet. It mimics a hydrogen code +// stub for the underlying IC stub code. +class KeyedLoadICStubShim : public HydrogenCodeStub { + public: + explicit KeyedLoadICStubShim(Isolate* isolate) : HydrogenCodeStub(isolate) { + i::compiler::GetInterfaceDescriptor(isolate, this); + } + + virtual Handle GenerateCode() V8_OVERRIDE { + return isolate()->builtins()->KeyedLoadIC_Initialize(); + } + + virtual void InitializeInterfaceDescriptor( + CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE { + Register registers[] = { InterfaceDescriptor::ContextRegister(), + KeyedLoadIC::ReceiverRegister(), + KeyedLoadIC::NameRegister() }; + descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); + } + + private: + virtual Major MajorKey() const V8_OVERRIDE { return NoCache; } + virtual int NotMissMinorKey() const V8_OVERRIDE { return 0; } + virtual bool UseSpecialCache() V8_OVERRIDE { return true; } +}; + + +// TODO(mstarzinger): This is a temporary shim to be able to call an IC stub +// which doesn't have an interface descriptor yet. It mimics a hydrogen code +// stub for the underlying IC stub code. +class StoreICStubShim : public HydrogenCodeStub { + public: + StoreICStubShim(Isolate* isolate, StrictMode strict_mode) + : HydrogenCodeStub(isolate), strict_mode_(strict_mode) { + i::compiler::GetInterfaceDescriptor(isolate, this); + } + + virtual Handle GenerateCode() V8_OVERRIDE { + return StoreIC::initialize_stub(isolate(), strict_mode_); + } + + virtual void InitializeInterfaceDescriptor( + CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE { + Register registers[] = { InterfaceDescriptor::ContextRegister(), + StoreIC::ReceiverRegister(), + StoreIC::NameRegister(), + StoreIC::ValueRegister() }; + descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); + } + + private: + virtual Major MajorKey() const V8_OVERRIDE { return NoCache; } + virtual int NotMissMinorKey() const V8_OVERRIDE { return 0; } + virtual bool UseSpecialCache() V8_OVERRIDE { return true; } + + StrictMode strict_mode_; +}; + + +// TODO(mstarzinger): This is a temporary shim to be able to call an IC stub +// which doesn't have an interface descriptor yet. It mimics a hydrogen code +// stub for the underlying IC stub code. +class KeyedStoreICStubShim : public HydrogenCodeStub { + public: + KeyedStoreICStubShim(Isolate* isolate, StrictMode strict_mode) + : HydrogenCodeStub(isolate), strict_mode_(strict_mode) { + i::compiler::GetInterfaceDescriptor(isolate, this); + } + + virtual Handle GenerateCode() V8_OVERRIDE { + return strict_mode_ == SLOPPY + ? isolate()->builtins()->KeyedStoreIC_Initialize() + : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); + } + + virtual void InitializeInterfaceDescriptor( + CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE { + Register registers[] = { InterfaceDescriptor::ContextRegister(), + KeyedStoreIC::ReceiverRegister(), + KeyedStoreIC::NameRegister(), + KeyedStoreIC::ValueRegister() }; + descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); + } + + private: + virtual Major MajorKey() const V8_OVERRIDE { return NoCache; } + virtual int NotMissMinorKey() const V8_OVERRIDE { return 0; } + virtual bool UseSpecialCache() V8_OVERRIDE { return true; } + + StrictMode strict_mode_; +}; + + JSGenericLowering::JSGenericLowering(CompilationInfo* info, JSGraph* jsgraph, MachineOperatorBuilder* machine, SourcePositionTable* source_positions) @@ -296,23 +422,19 @@ Node* JSGenericLowering::LowerJSToObject(Node* node) { Node* JSGenericLowering::LowerJSLoadProperty(Node* node) { - if (FLAG_compiled_keyed_generic_loads) { - KeyedLoadGenericStub stub(isolate()); - ReplaceWithICStubCall(node, &stub); - } else { - ReplaceWithRuntimeCall(node, Runtime::kKeyedGetProperty); - } + KeyedLoadICStubShim stub(isolate()); + ReplaceWithICStubCall(node, &stub); return node; } Node* JSGenericLowering::LowerJSLoadNamed(Node* node) { - Node* key = - jsgraph()->HeapConstant(OpParameter >(node)); - PatchInsertInput(node, 1, key); - // TODO(mstarzinger): We cannot yet use KeyedLoadGenericElementStub here, - // because named interceptors would not fire correctly yet. - ReplaceWithRuntimeCall(node, Runtime::kGetProperty); + PrintableUnique key = OpParameter >(node); + // TODO(mstarzinger): The ContextualMode needs to be carried along in the + // operator to use JSLoadNamed for global variable loads. + LoadICStubShim stub(isolate(), NOT_CONTEXTUAL); + PatchInsertInput(node, 1, jsgraph()->HeapConstant(key)); + ReplaceWithICStubCall(node, &stub); return node; } @@ -321,21 +443,20 @@ Node* JSGenericLowering::LowerJSStoreProperty(Node* node) { // TODO(mstarzinger): The strict_mode needs to be carried along in the // operator so that graphs are fully compositional for inlining. StrictMode strict_mode = info()->strict_mode(); - PatchInsertInput(node, 3, SmiConstant(strict_mode)); - ReplaceWithRuntimeCall(node, Runtime::kSetProperty, 4); + KeyedStoreICStubShim stub(isolate(), strict_mode); + ReplaceWithICStubCall(node, &stub); return node; } Node* JSGenericLowering::LowerJSStoreNamed(Node* node) { + PrintableUnique key = OpParameter >(node); // TODO(mstarzinger): The strict_mode needs to be carried along in the // operator so that graphs are fully compositional for inlining. StrictMode strict_mode = info()->strict_mode(); - Node* key = - jsgraph()->HeapConstant(OpParameter >(node)); - PatchInsertInput(node, 1, key); - PatchInsertInput(node, 3, SmiConstant(strict_mode)); - ReplaceWithRuntimeCall(node, Runtime::kSetProperty, 4); + StoreICStubShim stub(isolate(), strict_mode); + PatchInsertInput(node, 1, jsgraph()->HeapConstant(key)); + ReplaceWithICStubCall(node, &stub); return node; }