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