Commit e4d18396 authored by dslomov@chromium.org's avatar dslomov@chromium.org

harmony-scoping: Implement LoadIC handler for loads from 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/696783005

Cr-Commit-Position: refs/heads/master@{#25259}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25259 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent c5a49296
......@@ -513,6 +513,28 @@ Handle<Code> CreateAllocationSiteStub::GenerateCode() {
}
template <>
HValue* CodeStubGraphBuilder<LoadGlobalContextFieldStub>::BuildCodeStub() {
int context_index = casted_stub()->context_index();
int slot_index = casted_stub()->slot_index();
HValue* native_context = BuildGetNativeContext();
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),
HObjectAccess::ForContextSlot(slot_index));
}
Handle<Code> LoadGlobalContextFieldStub::GenerateCode() {
return DoGenerateCode(this);
}
template <>
HValue* CodeStubGraphBuilder<LoadFastElementStub>::BuildCodeStub() {
HInstruction* load = BuildUncheckedMonomorphicElementAccess(
......
......@@ -69,6 +69,7 @@ namespace internal {
V(InternalArrayNoArgumentConstructor) \
V(InternalArraySingleArgumentConstructor) \
V(KeyedLoadGeneric) \
V(LoadGlobalContextField) \
V(LoadDictionaryElement) \
V(LoadFastElement) \
V(MegamorphicLoad) \
......@@ -2016,6 +2017,46 @@ class DoubleToIStub : public PlatformCodeStub {
};
class LoadGlobalContextFieldStub : public HandlerStub {
public:
LoadGlobalContextFieldStub(
Isolate* isolate, const GlobalContextTable::LookupResult* lookup_result)
: HandlerStub(isolate) {
DCHECK(Accepted(lookup_result));
set_sub_minor_key(ContextIndexBits::encode(lookup_result->context_index) |
SlotIndexBits::encode(lookup_result->slot_index));
}
int context_index() const {
return ContextIndexBits::decode(sub_minor_key());
}
int slot_index() const { return SlotIndexBits::decode(sub_minor_key()); }
static bool Accepted(const GlobalContextTable::LookupResult* lookup_result) {
return ContextIndexBits::is_valid(lookup_result->context_index) &&
SlotIndexBits::is_valid(lookup_result->slot_index);
}
private:
static const int kContextIndexBits = 13;
static const int kSlotIndexBits = 13;
class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {};
class SlotIndexBits
: public BitField<int, kContextIndexBits, kSlotIndexBits> {};
virtual Code::Kind kind() const { return Code::LOAD_IC; }
virtual Code::StubType GetStubType() OVERRIDE { return Code::FAST; }
virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
return ContextOnlyDescriptor(isolate());
}
DEFINE_HANDLER_CODE_STUB(LoadGlobalContextField, HandlerStub);
};
class LoadFastElementStub : public HydrogenCodeStub {
public:
LoadFastElementStub(Isolate* isolate, bool is_js_array,
......
......@@ -229,8 +229,14 @@ class GlobalContextTable : public FixedArray {
static Handle<GlobalContextTable> Extend(Handle<GlobalContextTable> table,
Handle<Context> global_context);
static int GetContextOffset(int context_index) {
return kFirstContextOffset + context_index * kPointerSize;
}
private:
static const int kUsedSlot = 0;
static const int kFirstContextOffset =
FixedArray::kHeaderSize + (kUsedSlot + 1) * kPointerSize;
DISALLOW_IMPLICIT_CONSTRUCTORS(GlobalContextTable);
};
......
......@@ -4645,6 +4645,14 @@ HObjectAccess HObjectAccess::ForContextSlot(int index) {
}
HObjectAccess HObjectAccess::ForGlobalContext(int index) {
DCHECK(index >= 0);
Portion portion = kInobject;
int offset = GlobalContextTable::GetContextOffset(index);
return HObjectAccess(portion, offset, Representation::Tagged());
}
HObjectAccess HObjectAccess::ForJSArrayOffset(int offset) {
DCHECK(offset >= 0);
Portion portion = kInobject;
......
......@@ -6276,6 +6276,8 @@ class HObjectAccess FINAL {
static HObjectAccess ForContextSlot(int index);
static HObjectAccess ForGlobalContext(int index);
// Create an access to the backing store of an object.
static HObjectAccess ForBackingStoreOffset(int offset,
Representation representation = Representation::Tagged());
......
......@@ -5376,6 +5376,22 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
}
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, variable->name(),
&lookup)) {
Handle<Context> global_context = GlobalContextTable::GetContext(
global_contexts, lookup.context_index);
HInstruction* result = New<HLoadNamedField>(
Add<HConstant>(global_context), static_cast<HValue*>(NULL),
HObjectAccess::ForContextSlot(lookup.slot_index));
return ast_context()->ReturnInstruction(result, expr->id());
}
}
LookupIterator it(global, variable->name(),
LookupIterator::OWN_SKIP_INTERCEPTOR);
GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD);
......
......@@ -670,6 +670,10 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
GlobalContextTable::LookupResult lookup_result;
if (GlobalContextTable::Lookup(global_contexts, str_name, &lookup_result)) {
if (use_ic && LoadGlobalContextFieldStub::Accepted(&lookup_result)) {
LoadGlobalContextFieldStub stub(isolate(), &lookup_result);
PatchCache(name, stub.GetCode());
}
return FixedArray::get(GlobalContextTable::GetContext(
global_contexts, lookup_result.context_index),
lookup_result.slot_index);
......
......@@ -988,7 +988,7 @@ TEST(CrossScriptStaticLookupUndeclared) {
context.Check(
"function f(o) { return x; }"
"function g(o) { x = 15; }"
"function g(v) { x = v; }"
"function h(o) { return typeof x; }",
EXPECT_RESULT, Undefined(CcTest::isolate()));
context.Check("h({})", EXPECT_RESULT, undefined_string);
......@@ -999,10 +999,66 @@ TEST(CrossScriptStaticLookupUndeclared) {
EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
context.Check(
"'use strict';"
"g({});x",
"g(15);x",
EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
context.Check("h({})", EXPECT_RESULT, number_string);
context.Check("f({})", EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
context.Check("h({})", EXPECT_RESULT, number_string);
}
}
TEST(CrossScriptICs) {
i::FLAG_harmony_scoping = true;
i::FLAG_allow_natives_syntax = true;
HandleScope handle_scope(CcTest::isolate());
{
SimpleContext context;
context.Check(
"x = 15;"
"function f() { return x; }"
"function g() { return x; }"
"f()",
EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
context.Check(
"'use strict';"
"let x = 5;"
"f()",
EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
for (int k = 0; k < 3; k++) {
context.Check("g()", EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
}
for (int k = 0; k < 3; k++) {
context.Check("f()", EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
}
context.Check("%OptimizeFunctionOnNextCall(g); g()", EXPECT_RESULT,
Number::New(CcTest::isolate(), 5));
context.Check("%OptimizeFunctionOnNextCall(f); f()", EXPECT_RESULT,
Number::New(CcTest::isolate(), 5));
}
{
SimpleContext context;
context.Check(
"x = 15;"
"function f() { return x; }"
"f()",
EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
for (int k = 0; k < 3; k++) {
context.Check("f()", EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
}
context.Check("%OptimizeFunctionOnNextCall(f); f()", EXPECT_RESULT,
Number::New(CcTest::isolate(), 15));
context.Check(
"'use strict';"
"let x = 5;"
"f()",
EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
for (int k = 0; k < 3; k++) {
context.Check("f()", EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
}
context.Check("%OptimizeFunctionOnNextCall(f); f()", EXPECT_RESULT,
Number::New(CcTest::isolate(), 5));
}
}
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