Revision: 25259
Author: [email protected]
Date: Tue Nov 11 11:16:30 2014 UTC
Log: harmony-scoping: Implement LoadIC handler for loads from global
contexts.
[email protected], [email protected], [email protected],
[email protected]
BUG=v8:2198
LOG=N
Review URL: https://codereview.chromium.org/696783005
https://code.google.com/p/v8/source/detail?r=25259
Modified:
/branches/bleeding_edge/src/code-stubs-hydrogen.cc
/branches/bleeding_edge/src/code-stubs.h
/branches/bleeding_edge/src/contexts.h
/branches/bleeding_edge/src/hydrogen-instructions.cc
/branches/bleeding_edge/src/hydrogen-instructions.h
/branches/bleeding_edge/src/hydrogen.cc
/branches/bleeding_edge/src/ic/ic.cc
/branches/bleeding_edge/test/cctest/test-decls.cc
=======================================
--- /branches/bleeding_edge/src/code-stubs-hydrogen.cc Tue Nov 11 10:24:52
2014 UTC
+++ /branches/bleeding_edge/src/code-stubs-hydrogen.cc Tue Nov 11 11:16:30
2014 UTC
@@ -511,6 +511,28 @@
Handle<Code> CreateAllocationSiteStub::GenerateCode() {
return DoGenerateCode(this);
}
+
+
+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 <>
=======================================
--- /branches/bleeding_edge/src/code-stubs.h Mon Nov 10 10:48:38 2014 UTC
+++ /branches/bleeding_edge/src/code-stubs.h Tue Nov 11 11:16:30 2014 UTC
@@ -69,6 +69,7 @@
V(InternalArrayNoArgumentConstructor) \
V(InternalArraySingleArgumentConstructor) \
V(KeyedLoadGeneric) \
+ V(LoadGlobalContextField) \
V(LoadDictionaryElement) \
V(LoadFastElement) \
V(MegamorphicLoad) \
@@ -2016,6 +2017,46 @@
};
+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,
=======================================
--- /branches/bleeding_edge/src/contexts.h Mon Nov 10 18:03:50 2014 UTC
+++ /branches/bleeding_edge/src/contexts.h Tue Nov 11 11:16:30 2014 UTC
@@ -229,8 +229,14 @@
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);
};
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.cc Mon Nov 10
15:24:58 2014 UTC
+++ /branches/bleeding_edge/src/hydrogen-instructions.cc Tue Nov 11
11:16:30 2014 UTC
@@ -4643,6 +4643,14 @@
DCHECK_EQ(offset, Context::SlotOffset(index) + kHeapObjectTag);
return HObjectAccess(portion, offset, Representation::Tagged());
}
+
+
+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) {
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Tue Nov 11 10:24:52
2014 UTC
+++ /branches/bleeding_edge/src/hydrogen-instructions.h Tue Nov 11 11:16:30
2014 UTC
@@ -6276,6 +6276,8 @@
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());
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc Tue Nov 11 10:24:52 2014 UTC
+++ /branches/bleeding_edge/src/hydrogen.cc Tue Nov 11 11:16:30 2014 UTC
@@ -5376,6 +5376,22 @@
}
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);
=======================================
--- /branches/bleeding_edge/src/ic/ic.cc Fri Nov 7 16:29:13 2014 UTC
+++ /branches/bleeding_edge/src/ic/ic.cc Tue Nov 11 11:16:30 2014 UTC
@@ -670,6 +670,10 @@
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);
=======================================
--- /branches/bleeding_edge/test/cctest/test-decls.cc Mon Nov 10 10:46:37
2014 UTC
+++ /branches/bleeding_edge/test/cctest/test-decls.cc Tue Nov 11 11:16:30
2014 UTC
@@ -988,7 +988,7 @@
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 @@
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));
+ }
+}
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.