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
This commit is contained in:
ager@chromium.org 2009-01-14 12:13:26 +00:00
parent 37a50a8059
commit d4dae20a12
6 changed files with 40 additions and 5 deletions

View 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);

View 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";

View 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();

View 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;
}

View 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();

View File

@ -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);