Removing LookupTransition from LookupRealNamedProperty and related utility functions.

Callsites now have to manually lookup transitions if required. This
avoids unnecessary overhead of looking up transitions when we don't need
them. This also allows us to use IsFound() in many places where
IsProperty() was required previously.

Review URL: https://chromiumcodereview.appspot.com/10779012

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12098 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
verwaest@chromium.org 2012-07-16 14:47:28 +00:00
parent 11e5c9e281
commit 3b5a6ef2e7
7 changed files with 71 additions and 67 deletions

View File

@ -2175,7 +2175,7 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
LookupResult result(isolate());
to->LocalLookup(descs->GetKey(i), &result);
// If the property is already there we skip it
if (result.IsProperty()) continue;
if (result.IsFound()) continue;
HandleScope inner;
ASSERT(!to->HasFastProperties());
// Add to dictionary.
@ -2208,7 +2208,7 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
// If the property is already there we skip it.
LookupResult result(isolate());
to->LocalLookup(String::cast(raw_key), &result);
if (result.IsProperty()) continue;
if (result.IsFound()) continue;
// Set the property.
Handle<String> key = Handle<String>(String::cast(raw_key));
Handle<Object> value = Handle<Object>(properties->ValueAt(i));

View File

@ -445,14 +445,14 @@ static void LookupForRead(Handle<Object> object,
}
holder->LocalLookupRealNamedProperty(*name, lookup);
if (lookup->IsProperty()) {
if (lookup->IsFound()) {
ASSERT(!lookup->IsInterceptor());
return;
}
Handle<Object> proto(holder->GetPrototype());
if (proto->IsNull()) {
lookup->NotFound();
ASSERT(!lookup->IsFound());
return;
}
@ -533,7 +533,7 @@ MaybeObject* CallICBase::LoadFunction(State state,
LookupResult lookup(isolate());
LookupForRead(object, name, &lookup);
if (!lookup.IsProperty()) {
if (!lookup.IsFound()) {
// If the object does not have the requested property, check which
// exception we need to throw.
return IsContextual(object)
@ -900,7 +900,7 @@ MaybeObject* LoadIC::Load(State state,
LookupForRead(object, name, &lookup);
// If we did not find a property, check if we need to throw an exception.
if (!lookup.IsProperty()) {
if (!lookup.IsFound()) {
if (IsContextual(object)) {
return ReferenceError("not_defined", name);
}
@ -1166,7 +1166,7 @@ MaybeObject* KeyedLoadIC::Load(State state,
LookupForRead(object, name, &lookup);
// If we did not find a property, check if we need to throw an exception.
if (!lookup.IsProperty() && IsContextual(object)) {
if (!lookup.IsFound() && IsContextual(object)) {
return ReferenceError("not_defined", name);
}
@ -1317,6 +1317,9 @@ static bool LookupForWrite(Handle<JSObject> receiver,
Handle<String> name,
LookupResult* lookup) {
receiver->LocalLookup(*name, lookup);
if (!lookup->IsFound()) {
receiver->map()->LookupTransition(*receiver, *name, lookup);
}
if (!StoreICableLookup(lookup)) {
// 2nd chance: There can be accessors somewhere in the prototype chain. Note
// that we explicitly exclude native accessors for now, because the stubs

View File

@ -406,13 +406,11 @@ PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
} else {
result->holder()->LocalLookupRealNamedProperty(name, &r);
}
if (r.IsProperty()) {
return GetPropertyAttributeWithFailedAccessCheck(receiver,
&r,
name,
continue_search);
}
break;
if (!r.IsFound()) break;
return GetPropertyAttributeWithFailedAccessCheck(receiver,
&r,
name,
continue_search);
}
case HANDLER:
@ -1747,9 +1745,10 @@ MaybeObject* JSObject::SetPropertyPostInterceptor(
// Check local property, ignore interceptor.
LookupResult result(GetIsolate());
LocalLookupRealNamedProperty(name, &result);
if (!result.IsFound()) map()->LookupTransition(this, name, &result);
if (result.IsFound()) {
// An existing property, a map transition or a null descriptor was
// found. Use set property to handle all these cases.
// An existing property or a map transition was found. Use set property to
// handle all these cases.
return SetProperty(&result, name, value, attributes, strict_mode);
}
bool done = false;
@ -1914,6 +1913,9 @@ MaybeObject* JSReceiver::SetProperty(String* name,
JSReceiver::StoreFromKeyed store_mode) {
LookupResult result(GetIsolate());
LocalLookup(name, &result);
if (!result.IsFound()) {
map()->LookupTransition(JSObject::cast(this), name, &result);
}
return SetProperty(&result, name, value, attributes, strict_mode, store_mode);
}
@ -2354,7 +2356,7 @@ void JSObject::LocalLookupRealNamedProperty(String* name,
}
if (HasFastProperties()) {
map()->LookupTransitionOrDescriptor(this, name, result);
map()->LookupDescriptor(this, name, result);
// A property or a map transition was found. We return all of these result
// types because LocalLookupRealNamedProperty is used when setting
// properties where map transitions are handled.
@ -2394,7 +2396,7 @@ void JSObject::LocalLookupRealNamedProperty(String* name,
void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) {
LocalLookupRealNamedProperty(name, result);
if (result->IsProperty()) return;
if (result->IsFound()) return;
LookupRealNamedPropertyInPrototypes(name, result);
}
@ -2410,8 +2412,8 @@ void JSObject::LookupRealNamedPropertyInPrototypes(String* name,
return result->HandlerResult(JSProxy::cast(pt));
}
JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
ASSERT(!(result->IsProperty() && result->type() == INTERCEPTOR));
if (result->IsProperty()) return;
ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR));
if (result->IsFound()) return;
}
result->NotFound();
}
@ -2933,6 +2935,7 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
Isolate* isolate = GetIsolate();
LookupResult result(isolate);
LocalLookup(name, &result);
if (!result.IsFound()) map()->LookupTransition(this, name, &result);
// Check access rights if needed.
if (IsAccessCheckNeeded()) {
if (!isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
@ -3021,7 +3024,7 @@ PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
// Check local property, ignore interceptor.
LookupResult result(GetIsolate());
LocalLookupRealNamedProperty(name, &result);
if (result.IsProperty()) return result.GetAttributes();
if (result.IsFound()) return result.GetAttributes();
if (continue_search) {
// Continue searching via the prototype chain.
@ -3114,7 +3117,7 @@ PropertyAttributes JSReceiver::GetPropertyAttribute(JSReceiver* receiver,
receiver, result, name, continue_search);
}
}
if (result->IsProperty()) {
if (result->IsFound()) {
switch (result->type()) {
case NORMAL: // fall through
case FIELD:
@ -3700,7 +3703,7 @@ MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name,
// Check local property, ignore interceptor.
LookupResult result(GetIsolate());
LocalLookupRealNamedProperty(name, &result);
if (!result.IsProperty()) return GetHeap()->true_value();
if (!result.IsFound()) return GetHeap()->true_value();
// Normalize object if needed.
Object* obj;
@ -3849,7 +3852,7 @@ MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
} else {
LookupResult result(isolate);
LocalLookup(name, &result);
if (!result.IsProperty()) return isolate->heap()->true_value();
if (!result.IsFound()) return isolate->heap()->true_value();
// Ignore attributes if forcing a deletion.
if (result.IsDontDelete() && mode != FORCE_DELETION) {
if (mode == STRICT_DELETION) {
@ -4199,21 +4202,22 @@ void JSReceiver::LocalLookup(String* name, LookupResult* result) {
}
void JSReceiver::Lookup(String* name, LookupResult* result) {
void JSReceiver::Lookup(String* name,
LookupResult* result) {
// Ecma-262 3rd 8.6.2.4
Heap* heap = GetHeap();
for (Object* current = this;
current != heap->null_value();
current = JSObject::cast(current)->GetPrototype()) {
JSReceiver::cast(current)->LocalLookup(name, result);
if (result->IsProperty()) return;
if (result->IsFound()) return;
}
result->NotFound();
}
// Search object and its prototype chain for callback properties.
void JSObject::LookupCallback(String* name, LookupResult* result) {
void JSObject::LookupCallbackProperty(String* name, LookupResult* result) {
Heap* heap = GetHeap();
for (Object* current = this;
current != heap->null_value() && current->IsJSObject();
@ -4384,8 +4388,8 @@ bool JSObject::CanSetCallback(String* name) {
// to be overwritten because allowing overwriting could potentially
// cause security problems.
LookupResult callback_result(GetIsolate());
LookupCallback(name, &callback_result);
if (callback_result.IsProperty()) {
LookupCallbackProperty(name, &callback_result);
if (callback_result.IsFound()) {
Object* obj = callback_result.GetCallbackObject();
if (obj->IsAccessorInfo() &&
AccessorInfo::cast(obj)->prohibits_overwriting()) {
@ -4693,23 +4697,22 @@ MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) {
break;
}
{ MaybeObject* maybe_ok =
SetElementCallback(index, info, info->property_attributes());
if (maybe_ok->IsFailure()) return maybe_ok;
}
MaybeObject* maybe_ok =
SetElementCallback(index, info, info->property_attributes());
if (maybe_ok->IsFailure()) return maybe_ok;
} else {
// Lookup the name.
LookupResult result(isolate);
LocalLookup(name, &result);
// 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.IsProperty() && (result.IsReadOnly() || result.IsDontDelete())) {
if (result.IsFound() && (result.IsReadOnly() || result.IsDontDelete())) {
return isolate->heap()->undefined_value();
}
{ MaybeObject* maybe_ok =
SetPropertyCallback(name, info, info->property_attributes());
if (maybe_ok->IsFailure()) return maybe_ok;
}
MaybeObject* maybe_ok =
SetPropertyCallback(name, info, info->property_attributes());
if (maybe_ok->IsFailure()) return maybe_ok;
}
return this;
@ -4755,7 +4758,7 @@ Object* JSObject::LookupAccessor(String* name, AccessorComponent component) {
obj = JSReceiver::cast(obj)->GetPrototype()) {
LookupResult result(heap->isolate());
JSReceiver::cast(obj)->LocalLookup(name, &result);
if (result.IsProperty()) {
if (result.IsFound()) {
if (result.IsReadOnly()) return heap->undefined_value();
if (result.IsPropertyCallbacks()) {
Object* obj = result.GetCallbackObject();
@ -7641,7 +7644,7 @@ bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) {
LookupResult result(heap->isolate());
String* name = GetThisPropertyAssignmentName(i);
receiver->LocalLookup(name, &result);
if (result.IsProperty()) {
if (result.IsFound()) {
switch (result.type()) {
case NORMAL:
case FIELD:
@ -10174,7 +10177,7 @@ MaybeObject* JSObject::GetPropertyPostInterceptor(
// Check local property in holder, ignore interceptor.
LookupResult result(GetIsolate());
LocalLookupRealNamedProperty(name, &result);
if (result.IsProperty()) {
if (result.IsFound()) {
return GetProperty(receiver, &result, name, attributes);
}
// Continue searching via the prototype chain.
@ -10192,7 +10195,7 @@ MaybeObject* JSObject::GetLocalPropertyPostInterceptor(
// Check local property in holder, ignore interceptor.
LookupResult result(GetIsolate());
LocalLookupRealNamedProperty(name, &result);
if (result.IsProperty()) {
if (result.IsFound()) {
return GetProperty(receiver, &result, name, attributes);
}
return GetHeap()->undefined_value();
@ -10251,7 +10254,7 @@ bool JSObject::HasRealNamedProperty(String* key) {
LookupResult result(isolate);
LocalLookupRealNamedProperty(key, &result);
return result.IsProperty() && !result.IsInterceptor();
return result.IsFound() && !result.IsInterceptor();
}

View File

@ -1876,7 +1876,7 @@ class JSObject: public JSReceiver {
void LookupRealNamedPropertyInPrototypes(String* name, LookupResult* result);
MUST_USE_RESULT MaybeObject* SetElementWithCallbackSetterInPrototypes(
uint32_t index, Object* value, bool* found, StrictModeFlag strict_mode);
void LookupCallback(String* name, LookupResult* result);
void LookupCallbackProperty(String* name, LookupResult* result);
// Returns the number of properties on this object filtering out properties
// with the specified attributes (ignoring interceptors).

View File

@ -2300,11 +2300,12 @@ String* V8HeapExplorer::GetConstructorName(JSObject* object) {
Object* constructor_prop = NULL;
LookupResult result(heap->isolate());
object->LocalLookupRealNamedProperty(heap->constructor_symbol(), &result);
if (result.IsProperty()) {
constructor_prop = result.GetLazyValue();
}
if (!result.IsFound()) return object->constructor_name();
constructor_prop = result.GetLazyValue();
if (constructor_prop->IsJSFunction()) {
Object* maybe_name = JSFunction::cast(constructor_prop)->shared()->name();
Object* maybe_name =
JSFunction::cast(constructor_prop)->shared()->name();
if (maybe_name->IsString()) {
String* name = String::cast(maybe_name);
if (name->length() > 0) return name;

View File

@ -953,13 +953,13 @@ static void GetOwnPropertyImplementation(JSObject* obj,
LookupResult* result) {
obj->LocalLookupRealNamedProperty(name, result);
if (!result->IsProperty()) {
Object* proto = obj->GetPrototype();
if (proto->IsJSObject() &&
JSObject::cast(proto)->map()->is_hidden_prototype())
GetOwnPropertyImplementation(JSObject::cast(proto),
name, result);
}
if (result->IsFound()) return;
Object* proto = obj->GetPrototype();
if (proto->IsJSObject() &&
JSObject::cast(proto)->map()->is_hidden_prototype())
GetOwnPropertyImplementation(JSObject::cast(proto),
name, result);
}
@ -1373,14 +1373,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
Object* obj = *global;
do {
JSObject::cast(obj)->LocalLookup(*name, &lookup);
if (lookup.IsProperty()) break;
if (lookup.IsFound()) break;
obj = obj->GetPrototype();
} while (obj->IsJSObject() &&
JSObject::cast(obj)->map()->is_hidden_prototype());
} else {
global->Lookup(*name, &lookup);
}
if (lookup.IsProperty()) {
if (lookup.IsFound()) {
// We found an existing property. Unless it was an interceptor
// that claims the property is absent, skip this declaration.
if (!lookup.IsInterceptor()) continue;
@ -1416,10 +1416,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
LanguageMode language_mode = DeclareGlobalsLanguageMode::decode(flags);
if (!lookup.IsProperty() || is_function || is_module) {
if (!lookup.IsFound() || is_function || is_module) {
// If the local property exists, check that we can reconfigure it
// as required for function declarations.
if (lookup.IsProperty() && lookup.IsDontDelete()) {
if (lookup.IsFound() && lookup.IsDontDelete()) {
if (lookup.IsReadOnly() || lookup.IsDontEnum() ||
lookup.IsPropertyCallbacks()) {
return ThrowRedeclarationError(
@ -1634,7 +1634,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
// We use SetLocalPropertyIgnoreAttributes instead
LookupResult lookup(isolate);
global->LocalLookup(*name, &lookup);
if (!lookup.IsProperty()) {
if (!lookup.IsFound()) {
return global->SetLocalPropertyIgnoreAttributes(*name,
*value,
attributes);
@ -4558,7 +4558,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
// map. The current version of SetObjectProperty does not handle attributes
// correctly in the case where a property is a field and is reset with
// new attributes.
if (result.IsProperty() &&
if (result.IsFound() &&
(attr != result.GetAttributes() || result.IsPropertyCallbacks())) {
// New attributes - normalize to avoid writing to instance descriptor
if (js_object->IsJSGlobalProxy()) {
@ -10421,7 +10421,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
for (int i = 0; i < length; i++) {
LookupResult result(isolate);
jsproto->LocalLookup(*name, &result);
if (result.IsProperty()) {
if (result.IsFound()) {
// LookupResult is not GC safe as it holds raw object pointers.
// GC can happen later in this code so put the required fields into
// local variables using handles when required for later use.
@ -10478,7 +10478,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
LookupResult result(isolate);
obj->Lookup(*name, &result);
if (result.IsProperty()) {
if (result.IsFound()) {
return DebugLookupResultValue(isolate->heap(), *obj, *name, &result, NULL);
}
return isolate->heap()->undefined_value();

View File

@ -1361,11 +1361,8 @@ void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
Handle<String> name,
LookupResult* lookup) {
holder->LocalLookupRealNamedProperty(*name, lookup);
if (lookup->IsProperty()) return;
lookup->NotFound();
if (lookup->IsFound()) return;
if (holder->GetPrototype()->IsNull()) return;
holder->GetPrototype()->Lookup(*name, lookup);
}