From d4dae20a124f646e4417ac60d28fe6e76c6c7a32 Mon Sep 17 00:00:00 2001 From: "ager@chromium.org" Date: Wed, 14 Jan 2009 12:13:26 +0000 Subject: [PATCH] Fix issue 186: http://code.google.com/p/v8/issues/detail?id=186 Create a new instance type for context extension objects. Use it to not use the __proto__ accessor for context extension objects. Review URL: http://codereview.chromium.org/18044 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1072 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/bootstrapper.cc | 7 +++++-- src/objects-debug.cc | 3 +++ src/objects-inl.h | 8 +++++++ src/objects.cc | 3 ++- src/objects.h | 3 +++ .../bug-186.js => regress/regress-186.js} | 21 +++++++++++++++++-- 6 files changed, 40 insertions(+), 5 deletions(-) rename test/mjsunit/{bugs/bug-186.js => regress/regress-186.js} (81%) diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index ce25d00e4..8d5418782 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -794,8 +794,11 @@ void Genesis::CreateRoots(v8::Handle global_template, // Create a function for the context extension objects. Handle code = Handle(Builtins::builtin(Builtins::Illegal)); Handle context_extension_fun = - Factory::NewFunction(Factory::empty_symbol(), JS_OBJECT_TYPE, - JSObject::kHeaderSize, code, true); + Factory::NewFunction(Factory::empty_symbol(), + JS_CONTEXT_EXTENSION_OBJECT_TYPE, + JSObject::kHeaderSize, + code, + true); Handle name = Factory::LookupAsciiSymbol("context_extension"); context_extension_fun->shared()->set_instance_class_name(*name); diff --git a/src/objects-debug.cc b/src/objects-debug.cc index 1c1ffed81..6b58f255a 100644 --- a/src/objects-debug.cc +++ b/src/objects-debug.cc @@ -117,6 +117,7 @@ void HeapObject::HeapObjectPrint() { PrintF("filler"); break; case JS_OBJECT_TYPE: // fall through + case JS_CONTEXT_EXTENSION_OBJECT_TYPE: case JS_ARRAY_TYPE: case JS_REGEXP_TYPE: JSObject::cast(this)->JSObjectPrint(); @@ -193,6 +194,7 @@ void HeapObject::HeapObjectVerify() { Oddball::cast(this)->OddballVerify(); break; case JS_OBJECT_TYPE: + case JS_CONTEXT_EXTENSION_OBJECT_TYPE: JSObject::cast(this)->JSObjectVerify(); break; case JS_VALUE_TYPE: @@ -382,6 +384,7 @@ static const char* TypeToString(InstanceType type) { case BYTE_ARRAY_TYPE: return "BYTE_ARRAY"; case FILLER_TYPE: return "FILLER"; case JS_OBJECT_TYPE: return "JS_OBJECT"; + case JS_CONTEXT_EXTENSION_OBJECT_TYPE: return "JS_CONTEXT_EXTENSION_OBJECT"; case ODDBALL_TYPE: return "ODDBALL"; case SHARED_FUNCTION_INFO_TYPE: return "SHARED_FUNCTION_INFO"; case JS_FUNCTION_TYPE: return "JS_FUNCTION"; diff --git a/src/objects-inl.h b/src/objects-inl.h index 0bad5a160..01d897d33 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -328,6 +328,13 @@ bool Object::IsJSObject() { } +bool Object::IsJSContextExtensionObject() { + return IsHeapObject() + && (HeapObject::cast(this)->map()->instance_type() == + JS_CONTEXT_EXTENSION_OBJECT_TYPE); +} + + bool Object::IsMap() { return Object::IsHeapObject() && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE; @@ -1018,6 +1025,7 @@ int JSObject::GetHeaderSize() { case JS_REGEXP_TYPE: return JSValue::kSize; case JS_OBJECT_TYPE: + case JS_CONTEXT_EXTENSION_OBJECT_TYPE: return JSObject::kHeaderSize; default: UNREACHABLE(); diff --git a/src/objects.cc b/src/objects.cc index 9981e4cf5..0dc988799 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -940,6 +940,7 @@ void HeapObject::IterateBody(InstanceType type, int object_size, reinterpret_cast(this)->FixedArrayIterateBody(v); break; case JS_OBJECT_TYPE: + case JS_CONTEXT_EXTENSION_OBJECT_TYPE: case JS_VALUE_TYPE: case JS_ARRAY_TYPE: case JS_REGEXP_TYPE: @@ -2360,7 +2361,7 @@ void JSObject::LocalLookup(String* name, LookupResult* result) { } // Check __proto__ before interceptor. - if (name->Equals(Heap::Proto_symbol())) { + if (name->Equals(Heap::Proto_symbol()) && !IsJSContextExtensionObject()) { result->ConstantResult(this); return; } diff --git a/src/objects.h b/src/objects.h index f251a59cd..60e6d753e 100644 --- a/src/objects.h +++ b/src/objects.h @@ -278,6 +278,7 @@ enum PropertyNormalizationMode { \ V(JS_VALUE_TYPE) \ V(JS_OBJECT_TYPE) \ + V(JS_CONTEXT_EXTENSION_OBJECT_TYPE) \ V(JS_GLOBAL_OBJECT_TYPE) \ V(JS_BUILTINS_OBJECT_TYPE) \ V(JS_GLOBAL_PROXY_TYPE) \ @@ -535,6 +536,7 @@ enum InstanceType { JS_VALUE_TYPE, JS_OBJECT_TYPE, + JS_CONTEXT_EXTENSION_OBJECT_TYPE, JS_GLOBAL_OBJECT_TYPE, JS_BUILTINS_OBJECT_TYPE, JS_GLOBAL_PROXY_TYPE, @@ -622,6 +624,7 @@ class Object BASE_EMBEDDED { inline bool IsOutOfMemoryFailure(); inline bool IsException(); inline bool IsJSObject(); + inline bool IsJSContextExtensionObject(); inline bool IsMap(); inline bool IsFixedArray(); inline bool IsDescriptorArray(); diff --git a/test/mjsunit/bugs/bug-186.js b/test/mjsunit/regress/regress-186.js similarity index 81% rename from test/mjsunit/bugs/bug-186.js rename to test/mjsunit/regress/regress-186.js index bde52127d..335869d6b 100644 --- a/test/mjsunit/bugs/bug-186.js +++ b/test/mjsunit/regress/regress-186.js @@ -33,12 +33,27 @@ var setterCalled = false; var o = {}; o.__defineSetter__("x", function() { setterCalled = true; }); +function runTest(test) { + setterCalled = false; + test(); +} + function testLocal() { // Add property called __proto__ to the extension object. eval("var __proto__ = o"); // Check that the extension object's prototype did not change. eval("var x = 27"); assertFalse(setterCalled, "prototype of extension object changed"); + assertEquals(o, eval("__proto__")); +} + +function testConstLocal() { + // Add const property called __proto__ to the extension object. + eval("const __proto__ = o"); + // Check that the extension object's prototype did not change. + eval("var x = 27"); + assertFalse(setterCalled, "prototype of extension object changed"); + assertEquals(o, eval("__proto__")); } function testGlobal() { @@ -48,8 +63,10 @@ function testGlobal() { eval("x = 27"); assertTrue(setterCalled, "prototype of global object did not change"); setterCalled = false; + assertEquals(o, eval("__proto__")); } -testLocal(); -testGlobal(); +runTest(testLocal); +runTest(testConstLocal); +runTest(testGlobal); -- 2.34.1