Commit d4dae20a authored by ager@chromium.org's avatar ager@chromium.org

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
parent 37a50a80
......@@ -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);
......
......@@ -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";
......
......@@ -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();
......
......@@ -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;
}
......
......@@ -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();
......
......@@ -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);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment