Fix ICs for slow objects with native accessor.
authormstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 16 Jul 2012 09:53:32 +0000 (09:53 +0000)
committermstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 16 Jul 2012 09:53:32 +0000 (09:53 +0000)
This prevents creation of LoadICs or StoreICs for native callbacks on
objects in dictionary mode. Those ICs fail if the accessor is installed
on the receiver itself and also lead to bogus type feedback.

R=danno@chromium.org
BUG=chromium:137002
TEST=test/test-api/Regress137002[a,b]

Review URL: https://chromiumcodereview.appspot.com/10781011

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12088 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/ic.cc
test/cctest/test-api.cc

index a6b7a1d..69a3f2a 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -989,6 +989,7 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
         if (callback->IsAccessorInfo()) {
           Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback);
           if (v8::ToCData<Address>(info->getter()) == 0) return;
+          if (!receiver->HasFastProperties()) return;
           if (!info->IsCompatibleReceiver(*receiver)) return;
           code = isolate()->stub_cache()->ComputeLoadCallback(
               name, receiver, holder, info);
@@ -1265,6 +1266,7 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup,
         Handle<AccessorInfo> callback =
             Handle<AccessorInfo>::cast(callback_object);
         if (v8::ToCData<Address>(callback->getter()) == 0) return;
+        if (!receiver->HasFastProperties()) return;
         if (!callback->IsCompatibleReceiver(*receiver)) return;
         code = isolate()->stub_cache()->ComputeKeyedLoadCallback(
             name, receiver, holder, callback);
@@ -1484,6 +1486,7 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
       if (callback->IsAccessorInfo()) {
         Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback);
         if (v8::ToCData<Address>(info->setter()) == 0) return;
+        if (!receiver->HasFastProperties()) return;
         ASSERT(info->IsCompatibleReceiver(*receiver));
         code = isolate()->stub_cache()->ComputeStoreCallback(
             name, receiver, info, strict_mode);
index 2296072..136832c 100644 (file)
@@ -16813,3 +16813,46 @@ TEST(TryFinallyMessage) {
     CHECK_EQ(6, message->GetLineNumber());
   }
 }
+
+
+THREADED_TEST(Regress137002a) {
+  i::FLAG_allow_natives_syntax = true;
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  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("function f(x) { return x.foo; }"
+             "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
+             "obj.__proto__ = null;"
+             "f(obj); f(obj); f({});"
+             "%OptimizeFunctionOnNextCall(f);"
+             "var result = f(obj);");
+  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
+}
+
+
+THREADED_TEST(Regress137002b) {
+  i::FLAG_allow_natives_syntax = true;
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetAccessor(v8_str("foo"),
+                     GetterWhichReturns42,
+                     SetterWhichSetsYOnThisTo23);
+  context->Global()->Set(v8_str("obj"), templ->NewInstance());
+
+  // 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);"
+             "obj.__proto__ = null;"
+             "f(obj); f(obj); delete obj.foo;"
+             "var result = f(obj);");
+  CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
+}