Revision: 11396
Author:   [email protected]
Date:     Fri Apr 20 03:21:08 2012
Log:      Fix bug in forced-deletion of globals.

When inling functions across contexts in optimized code and using
ForceDelete from the API to delete a DontDelete global property we
can end up returning the hole value instead of throwing a ReferenceError
as expected after accessing a deleted global variable.

BUG=v8:2092
TEST=test/cctest/test-api/InlinedFunctionAcrossContexts
Review URL: https://chromiumcodereview.appspot.com/10035060
http://code.google.com/p/v8/source/detail?r=11396

Modified:
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/test/cctest/test-api.cc

=======================================
--- /branches/bleeding_edge/src/api.cc  Wed Apr 18 08:51:34 2012
+++ /branches/bleeding_edge/src/api.cc  Fri Apr 20 03:21:08 2012
@@ -2813,9 +2813,13 @@
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);

- // When turning on access checks for a global object deoptimize all functions
-  // as optimized code does not always handle access checks.
-  i::Deoptimizer::DeoptimizeGlobalObject(*self);
+  // When deleting a property on the global object using ForceDelete
+  // deoptimize all functions as optimized code does not check for the hole
+  // value with DontDelete properties.  We have to deoptimize all contexts
+  // because of possible cross-context inlined functions.
+  if (self->IsJSGlobalProxy() || self->IsGlobalObject()) {
+    i::Deoptimizer::DeoptimizeAll();
+  }

   EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc     Wed Apr 18 10:49:53 2012
+++ /branches/bleeding_edge/test/cctest/test-api.cc     Fri Apr 20 03:21:08 2012
@@ -12374,6 +12374,46 @@
   // sentinel.
   CHECK_EQ(5, CompileRun("f()")->Int32Value());
 }
+
+
+TEST(InlinedFunctionAcrossContexts) {
+  i::FLAG_allow_natives_syntax = true;
+  v8::HandleScope outer_scope;
+  v8::Persistent<v8::Context> ctx1 = v8::Context::New();
+  v8::Persistent<v8::Context> ctx2 = v8::Context::New();
+  ctx1->Enter();
+
+  {
+    v8::HandleScope inner_scope;
+    CompileRun("var G = 42; function foo() { return G; }");
+    v8::Local<v8::Value> foo = ctx1->Global()->Get(v8_str("foo"));
+    ctx2->Enter();
+    ctx2->Global()->Set(v8_str("o"), foo);
+    v8::Local<v8::Value> res = CompileRun(
+        "function f() { return o(); }"
+        "for (var i = 0; i < 10; ++i) f();"
+        "%OptimizeFunctionOnNextCall(f);"
+        "f();");
+    CHECK_EQ(42, res->Int32Value());
+    ctx2->Exit();
+    v8::Handle<v8::String> G_property = v8::String::New("G");
+    CHECK(ctx1->Global()->ForceDelete(G_property));
+    ctx2->Enter();
+    ExpectString(
+        "(function() {"
+        "  try {"
+        "    return f();"
+        "  } catch(e) {"
+        "    return e.toString();"
+        "  }"
+        " })()",
+        "ReferenceError: G is not defined");
+    ctx2->Exit();
+    ctx1->Exit();
+    ctx1.Dispose();
+  }
+  ctx2.Dispose();
+}


 v8::Persistent<Context> calling_context0;
@@ -16407,4 +16447,3 @@
 TEST(PrimaryStubCache) {
   StubCacheHelper(false);
 }
-

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

Reply via email to