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:
parent
37a50a8059
commit
d4dae20a12
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user