Commit 0f6d0d28 authored by rossberg@chromium.org's avatar rossberg@chromium.org

Fix and clean up treatment of hidden prototypes.

R=mstarzinger@chromium.org
BUG=

Review URL: https://codereview.chromium.org/11413068

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13012 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent bfbca55d
......@@ -1966,7 +1966,7 @@ MaybeObject* JSReceiver::SetProperty(String* name,
StrictModeFlag strict_mode,
JSReceiver::StoreFromKeyed store_mode) {
LookupResult result(GetIsolate());
LocalLookup(name, &result);
LocalLookup(name, &result, true);
if (!result.IsFound()) {
map()->LookupTransition(JSObject::cast(this), name, &result);
}
......@@ -3020,7 +3020,7 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
EnqueueChangeRecord(self, "new", name, old_value);
} else {
LookupResult new_lookup(isolate);
self->LocalLookup(*name, &new_lookup);
self->LocalLookup(*name, &new_lookup, true);
ASSERT(!new_lookup.GetLazyValue()->IsTheHole());
if (!new_lookup.GetLazyValue()->SameValue(*old_value)) {
EnqueueChangeRecord(self, "updated", name, old_value);
......@@ -3062,7 +3062,7 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
AssertNoContextChange ncc;
Isolate* isolate = GetIsolate();
LookupResult lookup(isolate);
LocalLookup(name_raw, &lookup);
LocalLookup(name_raw, &lookup, true);
if (!lookup.IsFound()) map()->LookupTransition(this, name_raw, &lookup);
// Check access rights if needed.
if (IsAccessCheckNeeded()) {
......@@ -3169,7 +3169,7 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
EnqueueChangeRecord(self, "new", name, old_value);
} else {
LookupResult new_lookup(isolate);
self->LocalLookup(*name, &new_lookup);
self->LocalLookup(*name, &new_lookup, true);
ASSERT(!new_lookup.GetLazyValue()->IsTheHole());
if (old_value->IsTheHole() ||
new_lookup.GetAttributes() != old_attributes) {
......@@ -3316,7 +3316,7 @@ PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) {
}
// Named property.
LookupResult lookup(GetIsolate());
LocalLookup(name, &lookup);
LocalLookup(name, &lookup, true);
return GetPropertyAttributeForResult(this, &lookup, name, false);
}
......@@ -4218,7 +4218,7 @@ MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
}
LookupResult lookup(isolate);
LocalLookup(name, &lookup);
LocalLookup(name, &lookup, true);
if (!lookup.IsFound()) return isolate->heap()->true_value();
// Ignore attributes if forcing a deletion.
if (lookup.IsDontDelete() && mode != FORCE_DELETION) {
......@@ -4548,7 +4548,8 @@ AccessorDescriptor* Map::FindAccessor(String* name) {
}
void JSReceiver::LocalLookup(String* name, LookupResult* result) {
void JSReceiver::LocalLookup(
String* name, LookupResult* result, bool search_hidden_prototypes) {
ASSERT(name->IsString());
Heap* heap = GetHeap();
......@@ -4557,7 +4558,8 @@ void JSReceiver::LocalLookup(String* name, LookupResult* result) {
Object* proto = GetPrototype();
if (proto->IsNull()) return result->NotFound();
ASSERT(proto->IsJSGlobalObject());
return JSReceiver::cast(proto)->LocalLookup(name, result);
return JSReceiver::cast(proto)->LocalLookup(
name, result, search_hidden_prototypes);
}
if (IsJSProxy()) {
......@@ -4587,6 +4589,14 @@ void JSReceiver::LocalLookup(String* name, LookupResult* result) {
}
js_object->LocalLookupRealNamedProperty(name, result);
if (result->IsFound() || !search_hidden_prototypes) return;
Object* proto = js_object->GetPrototype();
if (!proto->IsJSReceiver()) return;
JSReceiver* receiver = JSReceiver::cast(proto);
if (receiver->map()->is_hidden_prototype()) {
receiver->LocalLookup(name, result, search_hidden_prototypes);
}
}
......@@ -4596,7 +4606,7 @@ void JSReceiver::Lookup(String* name, LookupResult* result) {
for (Object* current = this;
current != heap->null_value();
current = JSObject::cast(current)->GetPrototype()) {
JSReceiver::cast(current)->LocalLookup(name, result);
JSReceiver::cast(current)->LocalLookup(name, result, false);
if (result->IsFound()) return;
}
result->NotFound();
......@@ -4918,7 +4928,7 @@ MaybeObject* JSObject::DefineAccessor(String* name_raw,
}
} else {
LookupResult lookup(isolate);
LocalLookup(*name, &lookup);
LocalLookup(*name, &lookup, true);
preexists = lookup.IsProperty();
if (preexists) old_value = handle(lookup.GetLazyValue(), isolate);
}
......@@ -5116,7 +5126,7 @@ MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) {
} else {
// Lookup the name.
LookupResult result(isolate);
LocalLookup(name, &result);
LocalLookup(name, &result, true);
// ES5 forbids turning a property into an accessor if it's not
// configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5).
if (result.IsFound() && (result.IsReadOnly() || result.IsDontDelete())) {
......@@ -9630,7 +9640,7 @@ PropertyType JSObject::GetLocalPropertyType(String* name) {
return GetLocalElementType(index);
}
LookupResult lookup(GetIsolate());
LocalLookup(name, &lookup);
LocalLookup(name, &lookup, true);
return lookup.type();
}
......
......@@ -1516,7 +1516,8 @@ class JSReceiver: public HeapObject {
// Lookup a property. If found, the result is valid and has
// detailed information.
void LocalLookup(String* name, LookupResult* result);
void LocalLookup(String* name, LookupResult* result,
bool search_hidden_prototypes = false);
void Lookup(String* name, LookupResult* result);
protected:
......
......@@ -1034,7 +1034,7 @@ static AccessCheckResult CheckPropertyAccess(
}
LookupResult lookup(obj->GetIsolate());
obj->LocalLookup(name, &lookup);
obj->LocalLookup(name, &lookup, true);
if (!lookup.IsProperty()) return ACCESS_ABSENT;
if (CheckGenericAccess<Object*>(
......@@ -1290,13 +1290,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
// Do the lookup locally only, see ES5 erratum.
LookupResult lookup(isolate);
if (FLAG_es52_globals) {
Object* obj = *global;
do {
JSObject::cast(obj)->LocalLookup(*name, &lookup);
if (lookup.IsFound()) break;
obj = obj->GetPrototype();
} while (obj->IsJSObject() &&
JSObject::cast(obj)->map()->is_hidden_prototype());
global->LocalLookup(*name, &lookup, true);
} else {
global->Lookup(*name, &lookup);
}
......@@ -1320,7 +1314,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
}
LookupResult lookup(isolate);
global->LocalLookup(*name, &lookup);
global->LocalLookup(*name, &lookup, true);
// Compute the property attributes. According to ECMA-262,
// the property must be non-configurable except in eval.
......@@ -1499,27 +1493,20 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
// the whole chain of hidden prototypes to do a 'local' lookup.
Object* object = global;
LookupResult lookup(isolate);
while (object->IsJSObject() &&
JSObject::cast(object)->map()->is_hidden_prototype()) {
JSObject* raw_holder = JSObject::cast(object);
raw_holder->LocalLookup(*name, &lookup);
if (lookup.IsInterceptor()) {
HandleScope handle_scope(isolate);
Handle<JSObject> holder(raw_holder);
PropertyAttributes intercepted = holder->GetPropertyAttribute(*name);
// Update the raw pointer in case it's changed due to GC.
raw_holder = *holder;
if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
// Found an interceptor that's not read only.
if (assign) {
return raw_holder->SetProperty(
&lookup, *name, args[2], attributes, strict_mode_flag);
} else {
return isolate->heap()->undefined_value();
}
JSObject::cast(object)->LocalLookup(*name, &lookup, true);
if (lookup.IsInterceptor()) {
HandleScope handle_scope(isolate);
PropertyAttributes intercepted =
lookup.holder()->GetPropertyAttribute(*name);
if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
// Found an interceptor that's not read only.
if (assign) {
return lookup.holder()->SetProperty(
&lookup, *name, args[2], attributes, strict_mode_flag);
} else {
return isolate->heap()->undefined_value();
}
}
object = raw_holder->GetPrototype();
}
// Reload global in case the loop above performed a GC.
......
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