Removing LookupTransition from LookupRealNamedProperty and related utility functions.
authorverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 16 Jul 2012 14:47:28 +0000 (14:47 +0000)
committerverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 16 Jul 2012 14:47:28 +0000 (14:47 +0000)
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

src/bootstrapper.cc
src/ic.cc
src/objects.cc
src/objects.h
src/profile-generator.cc
src/runtime.cc
src/stub-cache.cc

index 349c540..3d54187 100644 (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));
index 2f74eee..5b71e40 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -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
index 1a3500c..ccb56cc 100644 (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();
 }
 
 
index fcffd25..24d86fd 100644 (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).
index a33e904..9a91ad6 100644 (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;
index fc0cce1..f672534 100644 (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();
index 9adf3cb..b118b36 100644 (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);
 }