fix nonmasking interceptor ic with interceptor on receiver
authordcarney <dcarney@chromium.org>
Wed, 25 Mar 2015 12:34:01 +0000 (05:34 -0700)
committerCommit bot <commit-bot@chromium.org>
Wed, 25 Mar 2015 12:34:10 +0000 (12:34 +0000)
TBR=verwaest@chromium.org

BUG=

Review URL: https://codereview.chromium.org/1036843002

Cr-Commit-Position: refs/heads/master@{#27436}

src/ic/handler-compiler.cc
test/cctest/test-api-interceptors.cc

index 9c25f0a..f103f8d 100644 (file)
@@ -332,9 +332,13 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor(
   // Reset the holder so further calculations are correct.
   set_holder(holder_orig);
   if (lost_holder_register) {
-    // Reload lost holder register.
-    auto cell = isolate()->factory()->NewWeakCell(holder());
-    __ LoadWeakValue(reg, cell, &miss);
+    if (*it->GetReceiver() == *holder()) {
+      reg = receiver();
+    } else {
+      // Reload lost holder register.
+      auto cell = isolate()->factory()->NewWeakCell(holder());
+      __ LoadWeakValue(reg, cell, &miss);
+    }
   }
   FrontendFooter(it->name(), &miss);
   InterceptorVectorSlotPop(reg);
index 0b060d1..8c2b222 100644 (file)
@@ -3247,3 +3247,66 @@ THREADED_TEST(NonMaskingInterceptorPrototypePropertyIC) {
   ExpectInt32("f(obj)", 239);
   ExpectInt32("f(outer)", 4);
 }
+
+
+namespace {
+
+void DatabaseGetter(Local<Name> name,
+                    const v8::PropertyCallbackInfo<Value>& info) {
+  ApiTestFuzzer::Fuzz();
+  auto context = info.GetIsolate()->GetCurrentContext();
+  Local<v8::Object> db = info.Holder()
+                             ->GetRealNamedProperty(context, v8_str("db"))
+                             .ToLocalChecked()
+                             .As<v8::Object>();
+  if (!db->Has(context, name).FromJust()) return;
+  info.GetReturnValue().Set(db->Get(context, name).ToLocalChecked());
+}
+
+
+void DatabaseSetter(Local<Name> name, Local<Value> value,
+                    const v8::PropertyCallbackInfo<Value>& info) {
+  ApiTestFuzzer::Fuzz();
+  auto context = info.GetIsolate()->GetCurrentContext();
+  if (name->Equals(v8_str("db"))) return;
+  Local<v8::Object> db = info.Holder()
+                             ->GetRealNamedProperty(context, v8_str("db"))
+                             .ToLocalChecked()
+                             .As<v8::Object>();
+  db->Set(context, name, value).FromJust();
+  info.GetReturnValue().Set(value);
+}
+}
+
+
+THREADED_TEST(NonMaskingInterceptorGlobalEvalRegression) {
+  auto isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  LocalContext context;
+
+  auto interceptor_templ = v8::ObjectTemplate::New(isolate);
+  v8::NamedPropertyHandlerConfiguration conf(DatabaseGetter, DatabaseSetter);
+  conf.flags = v8::PropertyHandlerFlags::kNonMasking;
+  interceptor_templ->SetHandler(conf);
+
+  context->Global()->Set(v8_str("intercepted_1"),
+                         interceptor_templ->NewInstance());
+  context->Global()->Set(v8_str("intercepted_2"),
+                         interceptor_templ->NewInstance());
+
+  // Init dbs.
+  CompileRun(
+      "intercepted_1.db = {};"
+      "intercepted_2.db = {};");
+
+  ExpectInt32(
+      "var obj = intercepted_1;"
+      "obj.x = 4;"
+      "eval('obj.x');"
+      "eval('obj.x');"
+      "eval('obj.x');"
+      "obj = intercepted_2;"
+      "obj.x = 9;"
+      "eval('obj.x');",
+      9);
+}