Revision: 12359
Author:   [email protected]
Date:     Tue Aug 21 04:51:00 2012
Log: Back port r12247 to 3.11 (check holder, not receiver for dict mode).
This also back ports the improved tests from r12264, r12271 and r12311.
Review URL: https://chromiumcodereview.appspot.com/10860062
http://code.google.com/p/v8/source/detail?r=12359

Modified:
 /branches/3.11/src/ic.cc
 /branches/3.11/src/version.cc
 /branches/3.11/test/cctest/test-api.cc

=======================================
--- /branches/3.11/src/ic.cc    Fri Jul 20 04:03:23 2012
+++ /branches/3.11/src/ic.cc    Tue Aug 21 04:51:00 2012
@@ -992,7 +992,7 @@
         if (callback->IsAccessorInfo()) {
           Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback);
           if (v8::ToCData<Address>(info->getter()) == 0) return;
-          if (!receiver->HasFastProperties()) return;
+          if (!holder->HasFastProperties()) return;
           if (!info->IsCompatibleReceiver(*receiver)) return;
           code = isolate()->stub_cache()->ComputeLoadCallback(
               name, receiver, holder, info);
@@ -1000,7 +1000,7 @@
Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter());
           if (!getter->IsJSFunction()) return;
           if (holder->IsGlobalObject()) return;
-          if (!receiver->HasFastProperties()) return;
+          if (!holder->HasFastProperties()) return;
           code = isolate()->stub_cache()->ComputeLoadViaGetter(
               name, receiver, holder, Handle<JSFunction>::cast(getter));
         } else {
@@ -1269,7 +1269,7 @@
         Handle<AccessorInfo> callback =
             Handle<AccessorInfo>::cast(callback_object);
         if (v8::ToCData<Address>(callback->getter()) == 0) return;
-        if (!receiver->HasFastProperties()) return;
+        if (!holder->HasFastProperties()) return;
         if (!callback->IsCompatibleReceiver(*receiver)) return;
         code = isolate()->stub_cache()->ComputeKeyedLoadCallback(
             name, receiver, holder, callback);
@@ -1487,9 +1487,10 @@
     case CALLBACKS: {
       Handle<Object> callback(lookup->GetCallbackObject());
       if (callback->IsAccessorInfo()) {
+        ASSERT(*holder == *receiver);  // LookupForWrite checks this.
         Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback);
         if (v8::ToCData<Address>(info->setter()) == 0) return;
-        if (!receiver->HasFastProperties()) return;
+        if (!holder->HasFastProperties()) return;
         ASSERT(info->IsCompatibleReceiver(*receiver));
         code = isolate()->stub_cache()->ComputeStoreCallback(
             name, receiver, info, strict_mode);
@@ -1497,7 +1498,7 @@
Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter());
         if (!setter->IsJSFunction()) return;
         if (holder->IsGlobalObject()) return;
-        if (!receiver->HasFastProperties()) return;
+        if (!holder->HasFastProperties()) return;
         code = isolate()->stub_cache()->ComputeStoreViaSetter(
             name, receiver, Handle<JSFunction>::cast(setter), strict_mode);
       } else {
=======================================
--- /branches/3.11/src/version.cc       Fri Aug 17 04:09:29 2012
+++ /branches/3.11/src/version.cc       Tue Aug 21 04:51:00 2012
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     11
 #define BUILD_NUMBER      10
-#define PATCH_LEVEL       19
+#define PATCH_LEVEL       20
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
=======================================
--- /branches/3.11/test/cctest/test-api.cc      Fri Jul 20 04:03:23 2012
+++ /branches/3.11/test/cctest/test-api.cc      Tue Aug 21 04:51:00 2012
@@ -14567,6 +14567,8 @@

 static v8::Handle<Value> GetterWhichReturns42(Local<String> name,
                                               const AccessorInfo& info) {
+  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
+  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   return v8_num(42);
 }

@@ -14574,8 +14576,30 @@
 static void SetterWhichSetsYOnThisTo23(Local<String> name,
                                        Local<Value> value,
                                        const AccessorInfo& info) {
+  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
+  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   info.This()->Set(v8_str("y"), v8_num(23));
 }
+
+
+Handle<Value> FooGetInterceptor(Local<String> name,
+                                const AccessorInfo& info) {
+  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
+  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
+  if (!name->Equals(v8_str("foo"))) return Handle<Value>();
+  return v8_num(42);
+}
+
+
+Handle<Value> FooSetInterceptor(Local<String> name,
+                                Local<Value> value,
+                                const AccessorInfo& info) {
+  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
+  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
+  if (!name->Equals(v8_str("foo"))) return Handle<Value>();
+  info.This()->Set(v8_str("y"), v8_num(23));
+  return v8_num(23);
+}


 TEST(SetterOnConstructorPrototype) {
@@ -16811,10 +16835,67 @@
     CHECK_EQ(6, message->GetLineNumber());
   }
 }
+
+
+static void Helper137002(bool do_store,
+                         bool polymorphic,
+                         bool remove_accessor,
+                         bool interceptor) {
+  LocalContext context;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  if (interceptor) {
+    templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor);
+  } else {
+    templ->SetAccessor(v8_str("foo"),
+                       GetterWhichReturns42,
+                       SetterWhichSetsYOnThisTo23);
+  }
+  context->Global()->Set(v8_str("obj"), templ->NewInstance());
+
+  // Turn monomorphic on slow object with native accessor, then turn
+  // polymorphic, finally optimize to create negative lookup and fail.
+  CompileRun(do_store ?
+             "function f(x) { x.foo = void 0; }" :
+             "function f(x) { return x.foo; }");
+  CompileRun("obj.y = void 0;");
+  if (!interceptor) {
+    CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
+  }
+  CompileRun("obj.__proto__ = null;"
+             "f(obj); f(obj); f(obj);");
+  if (polymorphic) {
+    CompileRun("f({});");
+  }
+  CompileRun("obj.y = void 0;"
+             "%OptimizeFunctionOnNextCall(f);");
+  if (remove_accessor) {
+    CompileRun("delete obj.foo;");
+  }
+  CompileRun("var result = f(obj);");
+  if (do_store) {
+    CompileRun("result = obj.y;");
+  }
+  if (remove_accessor && !interceptor) {
+    CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
+  } else {
+    CHECK_EQ(do_store ? 23 : 42,
+             context->Global()->Get(v8_str("result"))->Int32Value());
+  }
+}


 THREADED_TEST(Regress137002a) {
   i::FLAG_allow_natives_syntax = true;
+  i::FLAG_compilation_cache = false;
+  v8::HandleScope scope;
+  for (int i = 0; i < 16; i++) {
+    Helper137002(i & 8, i & 4, i & 2, i & 1);
+  }
+}
+
+
+THREADED_TEST(Regress137002b) {
+  i::FLAG_allow_natives_syntax = true;
   v8::HandleScope scope;
   LocalContext context;
   Local<ObjectTemplate> templ = ObjectTemplate::New();
@@ -16823,19 +16904,65 @@
                      SetterWhichSetsYOnThisTo23);
   context->Global()->Set(v8_str("obj"), templ->NewInstance());

-  // Turn monomorphic on slow object with native accessor, then turn
-  // polymorphic, finally optimize to create negative lookup and fail.
-  CompileRun("function f(x) { return x.foo; }"
-             "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
+  // Turn monomorphic on slow object with native accessor, then just
+  // delete the property and fail.
+  CompileRun("function load(x) { return x.foo; }"
+             "function store(x) { x.foo = void 0; }"
+             "function keyed_load(x, key) { return x[key]; }"
+ // Second version of function has a different source (add void 0) + // so that it does not share code with the first version. This
+             // ensures that the ICs are monomorphic.
+             "function load2(x) { void 0; return x.foo; }"
+             "function store2(x) { void 0; x.foo = void 0; }"
+             "function keyed_load2(x, key) { void 0; return x[key]; }"
+
+             "obj.y = void 0;"
              "obj.__proto__ = null;"
-             "f(obj); f(obj); f({});"
-             "%OptimizeFunctionOnNextCall(f);"
-             "var result = f(obj);");
-  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
+             "var subobj = {};"
+             "subobj.y = void 0;"
+             "subobj.__proto__ = obj;"
+             "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
+
+             // Make the ICs monomorphic.
+             "load(obj); load(obj);"
+             "load2(subobj); load2(subobj);"
+             "store(obj); store(obj);"
+             "store2(subobj); store2(subobj);"
+             "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
+             "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
+
+             // Actually test the shiny new ICs and better not crash. This
+             // serves as a regression test for issue 142088 as well.
+             "load(obj);"
+             "load2(subobj);"
+             "store(obj);"
+             "store2(subobj);"
+             "keyed_load(obj, 'foo');"
+             "keyed_load2(subobj, 'foo');"
+
+             // Delete the accessor.  It better not be called any more now.
+             "delete obj.foo;"
+             "obj.y = void 0;"
+             "subobj.y = void 0;"
+
+             "var load_result = load(obj);"
+             "var load_result2 = load2(subobj);"
+             "var keyed_load_result = keyed_load(obj, 'foo');"
+             "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
+             "store(obj);"
+             "store2(subobj);"
+             "var y_from_obj = obj.y;"
+             "var y_from_subobj = subobj.y;");
+  CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
+  CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
+ CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined()); + CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
+  CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
+  CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
 }


-THREADED_TEST(Regress137002b) {
+THREADED_TEST(Regress142088) {
   i::FLAG_allow_natives_syntax = true;
   v8::HandleScope scope;
   LocalContext context;
@@ -16847,10 +16974,46 @@

   // Turn monomorphic on slow object with native accessor, then just
   // delete the property and fail.
-  CompileRun("function f(x) { return x.foo; }"
-             "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
+  CompileRun("function load(x) { return x.foo; }"
+             "function store(x) { x.foo = void 0; }"
+             "function keyed_load(x, key) { return x[key]; }"
+ // Second version of function has a different source (add void 0) + // so that it does not share code with the first version. This
+             // ensures that the ICs are monomorphic.
+             "function load2(x) { void 0; return x.foo; }"
+             "function store2(x) { void 0; x.foo = void 0; }"
+             "function keyed_load2(x, key) { void 0; return x[key]; }"
+
              "obj.__proto__ = null;"
-             "f(obj); f(obj); delete obj.foo;"
-             "var result = f(obj);");
-  CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
+             "var subobj = {};"
+             "subobj.__proto__ = obj;"
+             "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
+
+             // Make the ICs monomorphic.
+             "load(obj); load(obj);"
+             "load2(subobj); load2(subobj);"
+             "store(obj);"
+             "store2(subobj);"
+             "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
+             "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
+
+             // Delete the accessor.  It better not be called any more now.
+             "delete obj.foo;"
+             "obj.y = void 0;"
+             "subobj.y = void 0;"
+
+             "var load_result = load(obj);"
+             "var load_result2 = load2(subobj);"
+             "var keyed_load_result = keyed_load(obj, 'foo');"
+             "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
+             "store(obj);"
+             "store2(subobj);"
+             "var y_from_obj = obj.y;"
+             "var y_from_subobj = subobj.y;");
+  CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
+  CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
+ CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined()); + CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
+  CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
+  CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
 }

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to