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.

Reply via email to