Commit 480fbfeb authored by dslomov@chromium.org's avatar dslomov@chromium.org

harmony-scoping: Implement StoreIC handler for stores to global contexts.

R=ishell@chromium.org, adamk@chromium.org, rossberg@chromium.org, verwaest@chromium.org
BUG=v8:2198
LOG=N

Review URL: https://codereview.chromium.org/712973002

Cr-Commit-Position: refs/heads/master@{#25264}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25264 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent e13996e9
...@@ -518,13 +518,7 @@ HValue* CodeStubGraphBuilder<LoadGlobalContextFieldStub>::BuildCodeStub() { ...@@ -518,13 +518,7 @@ HValue* CodeStubGraphBuilder<LoadGlobalContextFieldStub>::BuildCodeStub() {
int context_index = casted_stub()->context_index(); int context_index = casted_stub()->context_index();
int slot_index = casted_stub()->slot_index(); int slot_index = casted_stub()->slot_index();
HValue* native_context = BuildGetNativeContext(); HValue* global_context = BuildGetGlobalContext(context_index);
HValue* global_context_table = Add<HLoadNamedField>(
native_context, static_cast<HValue*>(NULL),
HObjectAccess::ForContextSlot(Context::GLOBAL_CONTEXT_TABLE_INDEX));
HValue* global_context =
Add<HLoadNamedField>(global_context_table, static_cast<HValue*>(NULL),
HObjectAccess::ForGlobalContext(context_index));
return Add<HLoadNamedField>(global_context, static_cast<HValue*>(NULL), return Add<HLoadNamedField>(global_context, static_cast<HValue*>(NULL),
HObjectAccess::ForContextSlot(slot_index)); HObjectAccess::ForContextSlot(slot_index));
} }
...@@ -535,6 +529,24 @@ Handle<Code> LoadGlobalContextFieldStub::GenerateCode() { ...@@ -535,6 +529,24 @@ Handle<Code> LoadGlobalContextFieldStub::GenerateCode() {
} }
template <>
HValue* CodeStubGraphBuilder<StoreGlobalContextFieldStub>::BuildCodeStub() {
int context_index = casted_stub()->context_index();
int slot_index = casted_stub()->slot_index();
HValue* global_context = BuildGetGlobalContext(context_index);
Add<HStoreNamedField>(global_context,
HObjectAccess::ForContextSlot(slot_index),
GetParameter(2), STORE_TO_INITIALIZED_ENTRY);
return GetParameter(2);
}
Handle<Code> StoreGlobalContextFieldStub::GenerateCode() {
return DoGenerateCode(this);
}
template <> template <>
HValue* CodeStubGraphBuilder<LoadFastElementStub>::BuildCodeStub() { HValue* CodeStubGraphBuilder<LoadFastElementStub>::BuildCodeStub() {
HInstruction* load = BuildUncheckedMonomorphicElementAccess( HInstruction* load = BuildUncheckedMonomorphicElementAccess(
......
...@@ -77,6 +77,7 @@ namespace internal { ...@@ -77,6 +77,7 @@ namespace internal {
V(NumberToString) \ V(NumberToString) \
V(RegExpConstructResult) \ V(RegExpConstructResult) \
V(StoreFastElement) \ V(StoreFastElement) \
V(StoreGlobalContextField) \
V(StringAdd) \ V(StringAdd) \
V(ToBoolean) \ V(ToBoolean) \
V(TransitionElementsKind) \ V(TransitionElementsKind) \
...@@ -2017,10 +2018,10 @@ class DoubleToIStub : public PlatformCodeStub { ...@@ -2017,10 +2018,10 @@ class DoubleToIStub : public PlatformCodeStub {
}; };
class LoadGlobalContextFieldStub : public HandlerStub { class GlobalContextFieldStub : public HandlerStub {
public: public:
LoadGlobalContextFieldStub( GlobalContextFieldStub(Isolate* isolate,
Isolate* isolate, const GlobalContextTable::LookupResult* lookup_result) const GlobalContextTable::LookupResult* lookup_result)
: HandlerStub(isolate) { : HandlerStub(isolate) {
DCHECK(Accepted(lookup_result)); DCHECK(Accepted(lookup_result));
set_sub_minor_key(ContextIndexBits::encode(lookup_result->context_index) | set_sub_minor_key(ContextIndexBits::encode(lookup_result->context_index) |
...@@ -2045,15 +2046,35 @@ class LoadGlobalContextFieldStub : public HandlerStub { ...@@ -2045,15 +2046,35 @@ class LoadGlobalContextFieldStub : public HandlerStub {
class SlotIndexBits class SlotIndexBits
: public BitField<int, kContextIndexBits, kSlotIndexBits> {}; : public BitField<int, kContextIndexBits, kSlotIndexBits> {};
virtual Code::Kind kind() const { return Code::LOAD_IC; }
virtual Code::StubType GetStubType() OVERRIDE { return Code::FAST; } virtual Code::StubType GetStubType() OVERRIDE { return Code::FAST; }
DEFINE_CODE_STUB_BASE(GlobalContextFieldStub, HandlerStub);
};
virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
return ContextOnlyDescriptor(isolate());
}
DEFINE_HANDLER_CODE_STUB(LoadGlobalContextField, HandlerStub); class LoadGlobalContextFieldStub : public GlobalContextFieldStub {
public:
LoadGlobalContextFieldStub(
Isolate* isolate, const GlobalContextTable::LookupResult* lookup_result)
: GlobalContextFieldStub(isolate, lookup_result) {}
private:
virtual Code::Kind kind() const OVERRIDE { return Code::LOAD_IC; }
DEFINE_HANDLER_CODE_STUB(LoadGlobalContextField, GlobalContextFieldStub);
};
class StoreGlobalContextFieldStub : public GlobalContextFieldStub {
public:
StoreGlobalContextFieldStub(
Isolate* isolate, const GlobalContextTable::LookupResult* lookup_result)
: GlobalContextFieldStub(isolate, lookup_result) {}
private:
virtual Code::Kind kind() const OVERRIDE { return Code::STORE_IC; }
DEFINE_HANDLER_CODE_STUB(StoreGlobalContextField, GlobalContextFieldStub);
}; };
......
...@@ -3133,6 +3133,16 @@ HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) { ...@@ -3133,6 +3133,16 @@ HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) {
} }
HInstruction* HGraphBuilder::BuildGetGlobalContext(int context_index) {
HValue* native_context = BuildGetNativeContext();
HValue* global_context_table = Add<HLoadNamedField>(
native_context, static_cast<HValue*>(NULL),
HObjectAccess::ForContextSlot(Context::GLOBAL_CONTEXT_TABLE_INDEX));
return Add<HLoadNamedField>(global_context_table, static_cast<HValue*>(NULL),
HObjectAccess::ForGlobalContext(context_index));
}
HInstruction* HGraphBuilder::BuildGetNativeContext() { HInstruction* HGraphBuilder::BuildGetNativeContext() {
// Get the global context, then the native context // Get the global context, then the native context
HValue* global_object = Add<HLoadNamedField>( HValue* global_object = Add<HLoadNamedField>(
...@@ -6522,6 +6532,24 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( ...@@ -6522,6 +6532,24 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
HValue* value, HValue* value,
BailoutId ast_id) { BailoutId ast_id) {
Handle<GlobalObject> global(current_info()->global_object()); Handle<GlobalObject> global(current_info()->global_object());
if (FLAG_harmony_scoping) {
Handle<GlobalContextTable> global_contexts(
global->native_context()->global_context_table());
GlobalContextTable::LookupResult lookup;
if (GlobalContextTable::Lookup(global_contexts, var->name(), &lookup)) {
Handle<Context> global_context =
GlobalContextTable::GetContext(global_contexts, lookup.context_index);
HStoreNamedField* instr = Add<HStoreNamedField>(
Add<HConstant>(global_context),
HObjectAccess::ForContextSlot(lookup.slot_index), value);
USE(instr);
DCHECK(instr->HasObservableSideEffects());
Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
return;
}
}
LookupIterator it(global, var->name(), LookupIterator::OWN_SKIP_INTERCEPTOR); LookupIterator it(global, var->name(), LookupIterator::OWN_SKIP_INTERCEPTOR);
GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE); GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE);
if (type == kUseCell) { if (type == kUseCell) {
......
...@@ -1878,6 +1878,7 @@ class HGraphBuilder { ...@@ -1878,6 +1878,7 @@ class HGraphBuilder {
HInstruction* BuildGetNativeContext(HValue* closure); HInstruction* BuildGetNativeContext(HValue* closure);
HInstruction* BuildGetNativeContext(); HInstruction* BuildGetNativeContext();
HInstruction* BuildGetGlobalContext(int context_index);
HInstruction* BuildGetArrayFunction(); HInstruction* BuildGetArrayFunction();
protected: protected:
......
...@@ -1396,6 +1396,13 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name, ...@@ -1396,6 +1396,13 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
if (lookup_result.mode == CONST) { if (lookup_result.mode == CONST) {
return TypeError("harmony_const_assign", object, name); return TypeError("harmony_const_assign", object, name);
} }
if (FLAG_use_ic &&
StoreGlobalContextFieldStub::Accepted(&lookup_result)) {
StoreGlobalContextFieldStub stub(isolate(), &lookup_result);
PatchCache(name, stub.GetCode());
}
global_context->set(lookup_result.slot_index, *value); global_context->set(lookup_result.slot_index, *value);
return value; return value;
} }
......
...@@ -1008,7 +1008,7 @@ TEST(CrossScriptStaticLookupUndeclared) { ...@@ -1008,7 +1008,7 @@ TEST(CrossScriptStaticLookupUndeclared) {
} }
TEST(CrossScriptICs) { TEST(CrossScriptLoadICs) {
i::FLAG_harmony_scoping = true; i::FLAG_harmony_scoping = true;
i::FLAG_allow_natives_syntax = true; i::FLAG_allow_natives_syntax = true;
...@@ -1062,3 +1062,81 @@ TEST(CrossScriptICs) { ...@@ -1062,3 +1062,81 @@ TEST(CrossScriptICs) {
Number::New(CcTest::isolate(), 5)); Number::New(CcTest::isolate(), 5));
} }
} }
TEST(CrossScriptStoreICs) {
i::FLAG_harmony_scoping = true;
i::FLAG_allow_natives_syntax = true;
HandleScope handle_scope(CcTest::isolate());
{
SimpleContext context;
context.Check(
"var global = this;"
"x = 15;"
"function f(v) { x = v; }"
"function g(v) { x = v; }"
"f(10); x",
EXPECT_RESULT, Number::New(CcTest::isolate(), 10));
context.Check(
"'use strict';"
"let x = 5;"
"f(7); x",
EXPECT_RESULT, Number::New(CcTest::isolate(), 7));
context.Check("global.x", EXPECT_RESULT,
Number::New(CcTest::isolate(), 10));
for (int k = 0; k < 3; k++) {
context.Check("g(31); x", EXPECT_RESULT,
Number::New(CcTest::isolate(), 31));
}
context.Check("global.x", EXPECT_RESULT,
Number::New(CcTest::isolate(), 10));
for (int k = 0; k < 3; k++) {
context.Check("f(32); x", EXPECT_RESULT,
Number::New(CcTest::isolate(), 32));
}
context.Check("global.x", EXPECT_RESULT,
Number::New(CcTest::isolate(), 10));
context.Check("%OptimizeFunctionOnNextCall(g); g(18); x", EXPECT_RESULT,
Number::New(CcTest::isolate(), 18));
context.Check("global.x", EXPECT_RESULT,
Number::New(CcTest::isolate(), 10));
context.Check("%OptimizeFunctionOnNextCall(f); f(33); x", EXPECT_RESULT,
Number::New(CcTest::isolate(), 33));
context.Check("global.x", EXPECT_RESULT,
Number::New(CcTest::isolate(), 10));
}
{
SimpleContext context;
context.Check(
"var global = this;"
"x = 15;"
"function f(v) { x = v; }"
"f(10); x",
EXPECT_RESULT, Number::New(CcTest::isolate(), 10));
for (int k = 0; k < 3; k++) {
context.Check("f(18); x", EXPECT_RESULT,
Number::New(CcTest::isolate(), 18));
}
context.Check("%OptimizeFunctionOnNextCall(f); f(20); x", EXPECT_RESULT,
Number::New(CcTest::isolate(), 20));
context.Check(
"'use strict';"
"let x = 5;"
"f(8); x",
EXPECT_RESULT, Number::New(CcTest::isolate(), 8));
context.Check("global.x", EXPECT_RESULT,
Number::New(CcTest::isolate(), 20));
for (int k = 0; k < 3; k++) {
context.Check("f(13); x", EXPECT_RESULT,
Number::New(CcTest::isolate(), 13));
}
context.Check("global.x", EXPECT_RESULT,
Number::New(CcTest::isolate(), 20));
context.Check("%OptimizeFunctionOnNextCall(f); f(41); x", EXPECT_RESULT,
Number::New(CcTest::isolate(), 41));
context.Check("global.x", EXPECT_RESULT,
Number::New(CcTest::isolate(), 20));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment