Fix issue 186:
authorager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 14 Jan 2009 12:13:26 +0000 (12:13 +0000)
committerager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 14 Jan 2009 12:13:26 +0000 (12:13 +0000)
    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
src/objects-debug.cc
src/objects-inl.h
src/objects.cc
src/objects.h
test/mjsunit/bugs/bug-186.js [deleted file]
test/mjsunit/regress/regress-186.js [new file with mode: 0644]

index ce25d00e45691dad88d45170caf201100245b64c..8d5418782499f47799fb1cc5e58a259647511939 100644 (file)
@@ -794,8 +794,11 @@ void Genesis::CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
     // Create a function for the context extension objects.
     Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
     Handle<JSFunction> 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<String> name = Factory::LookupAsciiSymbol("context_extension");
     context_extension_fun->shared()->set_instance_class_name(*name);
index 1c1ffed811c72cbaa65f46aa566b5392e8f0a06f..6b58f255a8296de636a656f6528abf6ca20a508a 100644 (file)
@@ -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";
index 0bad5a160f5c705f8c61aa3981c98e2b256d2485..01d897d33028f7f69376d670116666bdeb80994d 100644 (file)
@@ -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();
index 9981e4cf5ecea6f53a65944bafdbdc56849ed0ba..0dc9887991ac76ac8e1457c5811219c2a7967709 100644 (file)
@@ -940,6 +940,7 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
       reinterpret_cast<FixedArray*>(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;
   }
index f251a59cd2526c3852afe309886ca878f357030f..60e6d753eeeae24d6889f492923800bb7a5158c9 100644 (file)
@@ -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/bugs/bug-186.js
deleted file mode 100644 (file)
index bde5212..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Make sure that eval can introduce a local variable called __proto__.
-// See http://code.google.com/p/v8/issues/detail?id=186
-
-var setterCalled = false;
-
-var o = {};
-o.__defineSetter__("x", function() { setterCalled = true; });
-
-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");
-}
-
-function testGlobal() {
-  // Assign to the global __proto__ property.
-  eval("__proto__ = o");
-  // Check that the prototype of the global object changed.
-  eval("x = 27");
-  assertTrue(setterCalled, "prototype of global object did not change");
-  setterCalled = false;
-}
-
-testLocal();
-testGlobal();
-
diff --git a/test/mjsunit/regress/regress-186.js b/test/mjsunit/regress/regress-186.js
new file mode 100644 (file)
index 0000000..335869d
--- /dev/null
@@ -0,0 +1,72 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Make sure that eval can introduce a local variable called __proto__.
+// See http://code.google.com/p/v8/issues/detail?id=186
+
+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() {
+  // Assign to the global __proto__ property.
+  eval("__proto__ = o");
+  // Check that the prototype of the global object changed.
+  eval("x = 27");
+  assertTrue(setterCalled, "prototype of global object did not change");
+  setterCalled = false;
+  assertEquals(o, eval("__proto__"));
+}
+
+runTest(testLocal);
+runTest(testConstLocal);
+runTest(testGlobal);
+