Revision: 20494
Author:   [email protected]
Date:     Fri Apr  4 04:49:07 2014 UTC
Log: Get rid of the TRANSITION PropertyType and consistently use CanHoldValue().

[email protected]

Review URL: https://codereview.chromium.org/223193005
http://code.google.com/p/v8/source/detail?r=20494

Modified:
 /branches/bleeding_edge/src/bootstrapper.cc
 /branches/bleeding_edge/src/heap-snapshot-generator.cc
 /branches/bleeding_edge/src/ic.cc
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects-printer.cc
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/property-details.h
 /branches/bleeding_edge/src/property.cc
 /branches/bleeding_edge/src/property.h
 /branches/bleeding_edge/src/runtime.cc

=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Thu Apr  3 12:41:37 2014 UTC
+++ /branches/bleeding_edge/src/bootstrapper.cc Fri Apr  4 04:49:07 2014 UTC
@@ -2464,7 +2464,6 @@
           // Do not occur since the from object has fast properties.
         case HANDLER:
         case INTERCEPTOR:
-        case TRANSITION:
         case NONEXISTENT:
// No element in instance descriptors have proxy or interceptor type.
           UNREACHABLE();
=======================================
--- /branches/bleeding_edge/src/heap-snapshot-generator.cc Thu Apr 3 16:32:59 2014 UTC +++ /branches/bleeding_edge/src/heap-snapshot-generator.cc Fri Apr 4 04:49:07 2014 UTC
@@ -1671,7 +1671,6 @@
         case HANDLER:  // only in lookup results, not in descriptors
         case INTERCEPTOR:  // only in lookup results, not in descriptors
           break;
-        case TRANSITION:
         case NONEXISTENT:
           UNREACHABLE();
           break;
=======================================
--- /branches/bleeding_edge/src/ic.cc   Thu Apr  3 12:27:24 2014 UTC
+++ /branches/bleeding_edge/src/ic.cc   Fri Apr  4 04:49:07 2014 UTC
@@ -1167,9 +1167,7 @@
// chain check. This avoids a double lookup, but requires us to pass in the
   // receiver when trying to fetch extra information from the transition.
   receiver->map()->LookupTransition(*holder, *name, lookup);
-  if (!lookup->IsTransition()) return false;
-  PropertyDetails target_details = lookup->GetTransitionDetails();
-  if (target_details.IsReadOnly()) return false;
+  if (!lookup->IsTransition() || lookup->IsReadOnly()) return false;

   // If the value that's being stored does not fit in the field that the
// instance would transition to, create a new transition that fits the value.
@@ -1178,7 +1176,7 @@
// Ensure the instance and its map were migrated before trying to update the
   // transition target.
   ASSERT(!receiver->map()->is_deprecated());
-  if (!value->FitsRepresentation(target_details.representation())) {
+  if (!lookup->CanHoldValue(value)) {
     Handle<Map> target(lookup->GetTransitionTarget());
     Map::GeneralizeRepresentation(
         target, target->LastAdded(),
@@ -1327,93 +1325,94 @@
   Handle<JSObject> holder(lookup->holder());
   // Handlers do not use strict mode.
   StoreStubCompiler compiler(isolate(), SLOPPY, kind());
-  switch (lookup->type()) {
-    case FIELD:
-      return compiler.CompileStoreField(receiver, lookup, name);
-    case TRANSITION: {
-      // Explicitly pass in the receiver map since LookupForWrite may have
-      // stored something else than the receiver in the holder.
-      Handle<Map> transition(lookup->GetTransitionTarget());
-      PropertyDetails details = transition->GetLastDescriptorDetails();
+  if (lookup->IsTransition()) {
+    // Explicitly pass in the receiver map since LookupForWrite may have
+    // stored something else than the receiver in the holder.
+    Handle<Map> transition(lookup->GetTransitionTarget());
+    PropertyDetails details = lookup->GetPropertyDetails();

- if (details.type() == CALLBACKS || details.attributes() != NONE) break;
-
+    if (details.type() != CALLBACKS && details.attributes() == NONE) {
       return compiler.CompileStoreTransition(
           receiver, lookup, transition, name);
     }
-    case NORMAL:
-      if (kind() == Code::KEYED_STORE_IC) break;
-      if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) {
- // The stub generated for the global object picks the value directly
-        // from the property cell. So the property must be directly on the
-        // global object.
-        Handle<GlobalObject> global = receiver->IsJSGlobalProxy()
-            ? handle(GlobalObject::cast(receiver->GetPrototype()))
-            : Handle<GlobalObject>::cast(receiver);
- Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate()); - Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value);
-        StoreGlobalStub stub(
-            union_type->IsConstant(), receiver->IsJSGlobalProxy());
-        Handle<Code> code = stub.GetCodeCopyFromTemplate(
-            isolate(), global, cell);
- // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
-        HeapObject::UpdateMapCodeCache(receiver, name, code);
-        return code;
-      }
-      ASSERT(holder.is_identical_to(receiver));
-      return isolate()->builtins()->StoreIC_Normal();
-    case CALLBACKS: {
-      Handle<Object> callback(lookup->GetCallbackObject(), isolate());
-      if (callback->IsExecutableAccessorInfo()) {
-        Handle<ExecutableAccessorInfo> info =
-            Handle<ExecutableAccessorInfo>::cast(callback);
-        if (v8::ToCData<Address>(info->setter()) == 0) break;
-        if (!holder->HasFastProperties()) break;
-        if (!info->IsCompatibleReceiver(*receiver)) break;
-        return compiler.CompileStoreCallback(receiver, holder, name, info);
-      } else if (callback->IsAccessorPair()) {
-        Handle<Object> setter(
-            Handle<AccessorPair>::cast(callback)->setter(), isolate());
-        if (!setter->IsJSFunction()) break;
-        if (holder->IsGlobalObject()) break;
-        if (!holder->HasFastProperties()) break;
-        Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
-        CallOptimization call_optimization(function);
-        if (call_optimization.is_simple_api_call() &&
-            call_optimization.IsCompatibleReceiver(receiver, holder)) {
-          return compiler.CompileStoreCallback(
-              receiver, holder, name, call_optimization);
+  } else {
+    switch (lookup->type()) {
+      case FIELD:
+        return compiler.CompileStoreField(receiver, lookup, name);
+      case NORMAL:
+        if (kind() == Code::KEYED_STORE_IC) break;
+        if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) {
+ // The stub generated for the global object picks the value directly + // from the property cell. So the property must be directly on the
+          // global object.
+          Handle<GlobalObject> global = receiver->IsJSGlobalProxy()
+              ? handle(GlobalObject::cast(receiver->GetPrototype()))
+              : Handle<GlobalObject>::cast(receiver);
+ Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate()); + Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value);
+          StoreGlobalStub stub(
+              union_type->IsConstant(), receiver->IsJSGlobalProxy());
+          Handle<Code> code = stub.GetCodeCopyFromTemplate(
+              isolate(), global, cell);
+ // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
+          HeapObject::UpdateMapCodeCache(receiver, name, code);
+          return code;
+        }
+        ASSERT(holder.is_identical_to(receiver));
+        return isolate()->builtins()->StoreIC_Normal();
+      case CALLBACKS: {
+        Handle<Object> callback(lookup->GetCallbackObject(), isolate());
+        if (callback->IsExecutableAccessorInfo()) {
+          Handle<ExecutableAccessorInfo> info =
+              Handle<ExecutableAccessorInfo>::cast(callback);
+          if (v8::ToCData<Address>(info->setter()) == 0) break;
+          if (!holder->HasFastProperties()) break;
+          if (!info->IsCompatibleReceiver(*receiver)) break;
+ return compiler.CompileStoreCallback(receiver, holder, name, info);
+        } else if (callback->IsAccessorPair()) {
+          Handle<Object> setter(
+              Handle<AccessorPair>::cast(callback)->setter(), isolate());
+          if (!setter->IsJSFunction()) break;
+          if (holder->IsGlobalObject()) break;
+          if (!holder->HasFastProperties()) break;
+          Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
+          CallOptimization call_optimization(function);
+          if (call_optimization.is_simple_api_call() &&
+              call_optimization.IsCompatibleReceiver(receiver, holder)) {
+            return compiler.CompileStoreCallback(
+                receiver, holder, name, call_optimization);
+          }
+          return compiler.CompileStoreViaSetter(
+              receiver, holder, name, Handle<JSFunction>::cast(setter));
+        }
+        // TODO(dcarney): Handle correctly.
+        if (callback->IsDeclaredAccessorInfo()) break;
+        ASSERT(callback->IsForeign());
+
+        // Use specialized code for setting the length of arrays with fast
+ // properties. Slow properties might indicate redefinition of the length
+        // property.
+        if (receiver->IsJSArray() &&
+            name->Equals(isolate()->heap()->length_string()) &&
+            Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
+            receiver->HasFastProperties()) {
+          return compiler.CompileStoreArrayLength(receiver, lookup, name);
         }
-        return compiler.CompileStoreViaSetter(
-            receiver, holder, name, Handle<JSFunction>::cast(setter));
-      }
-      // TODO(dcarney): Handle correctly.
-      if (callback->IsDeclaredAccessorInfo()) break;
-      ASSERT(callback->IsForeign());

-      // Use specialized code for setting the length of arrays with fast
- // properties. Slow properties might indicate redefinition of the length
-      // property.
-      if (receiver->IsJSArray() &&
-          name->Equals(isolate()->heap()->length_string()) &&
-          Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
-          receiver->HasFastProperties()) {
-        return compiler.CompileStoreArrayLength(receiver, lookup, name);
+        // No IC support for old-style native accessors.
+        break;
       }
-
-      // No IC support for old-style native accessors.
-      break;
+      case INTERCEPTOR:
+        if (kind() == Code::KEYED_STORE_IC) break;
+        ASSERT(HasInterceptorSetter(*holder));
+        return compiler.CompileStoreInterceptor(receiver, name);
+      case CONSTANT:
+        break;
+      case NONEXISTENT:
+      case HANDLER:
+        UNREACHABLE();
+        break;
     }
-    case INTERCEPTOR:
-      if (kind() == Code::KEYED_STORE_IC) break;
-      ASSERT(HasInterceptorSetter(*holder));
-      return compiler.CompileStoreInterceptor(receiver, name);
-    case CONSTANT:
-      break;
-    case NONEXISTENT:
-    case HANDLER:
-      UNREACHABLE();
-      break;
   }
   return slow_stub();
 }
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Thu Apr  3 12:27:24 2014 UTC
+++ /branches/bleeding_edge/src/objects-inl.h   Fri Apr  4 04:49:07 2014 UTC
@@ -2629,15 +2629,9 @@
 void Map::LookupTransition(JSObject* holder,
                            Name* name,
                            LookupResult* result) {
-  if (HasTransitionArray()) {
-    TransitionArray* transition_array = transitions();
-    int number = transition_array->Search(name);
-    if (number != TransitionArray::kNotFound) {
-      return result->TransitionResult(
-          holder, transition_array->GetTarget(number));
-    }
-  }
-  result->NotFound();
+  int transition_index = this->SearchTransition(name);
+ if (transition_index == TransitionArray::kNotFound) return result->NotFound();
+  result->TransitionResult(holder, this->GetTransition(transition_index));
 }


@@ -4902,6 +4896,12 @@
 Map* Map::GetTransition(int transition_index) {
   return transitions()->GetTarget(transition_index);
 }
+
+
+int Map::SearchTransition(Name* name) {
+  if (HasTransitionArray()) return transitions()->Search(name);
+  return TransitionArray::kNotFound;
+}


 MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) {
=======================================
--- /branches/bleeding_edge/src/objects-printer.cc Mon Mar 17 08:31:21 2014 UTC +++ /branches/bleeding_edge/src/objects-printer.cc Fri Apr 4 04:49:07 2014 UTC
@@ -271,7 +271,6 @@
         case HANDLER:  // only in lookup results, not in descriptors
         case INTERCEPTOR:  // only in lookup results, not in descriptors
         // There are no transitions in the descriptor array.
-        case TRANSITION:
         case NONEXISTENT:
           UNREACHABLE();
           break;
@@ -428,7 +427,6 @@
         case NORMAL:
         case HANDLER:
         case INTERCEPTOR:
-        case TRANSITION:
         case NONEXISTENT:
           UNREACHABLE();
           break;
@@ -1223,7 +1221,6 @@
       case NORMAL:
       case HANDLER:
       case INTERCEPTOR:
-      case TRANSITION:
       case NONEXISTENT:
         UNREACHABLE();
         break;
=======================================
--- /branches/bleeding_edge/src/objects.cc      Thu Apr  3 12:27:24 2014 UTC
+++ /branches/bleeding_edge/src/objects.cc      Fri Apr  4 04:49:07 2014 UTC
@@ -670,7 +670,6 @@
       }

       case HANDLER:
-      case TRANSITION:
       case NONEXISTENT:
         UNREACHABLE();
     }
@@ -944,7 +943,6 @@
       RETURN_IF_EMPTY_HANDLE(isolate, value);
       return *value;
     }
-    case TRANSITION:
     case NONEXISTENT:
       UNREACHABLE();
       break;
@@ -3077,7 +3075,6 @@
         return JSProxy::SetPropertyViaPrototypesWithHandler(
             proxy, object, name, value, attributes, strict_mode, done);
       }
-      case TRANSITION:
       case NONEXISTENT:
         UNREACHABLE();
         break;
@@ -3915,7 +3912,7 @@
   // Keep the target CONSTANT if the same value is stored.
   // TODO(verwaest): Also support keeping the placeholder
   // (value->IsUninitialized) as constant.
-  if (!value->FitsRepresentation(details.representation()) ||
+  if (!lookup->CanHoldValue(value) ||
       (details.type() == CONSTANT &&
        descriptors->GetValue(descriptor) != *value)) {
     transition_map = Map::GeneralizeRepresentation(transition_map,
@@ -3948,7 +3945,7 @@
                                Handle<Name> name,
                                Handle<Object> value) {
   Representation representation = lookup->representation();
-  if (!value->FitsRepresentation(representation) ||
+  if (!lookup->CanHoldValue(value) ||
       lookup->type() == CONSTANT) {
     JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()),
                                             lookup->GetDescriptorIndex(),
@@ -4091,34 +4088,35 @@
   // This is a real property that is not read-only, or it is a
// transition or null descriptor and there are no setters in the prototypes.
   Handle<Object> result = value;
-  switch (lookup->type()) {
-    case NORMAL:
-      SetNormalizedProperty(handle(lookup->holder()), lookup, value);
-      break;
-    case FIELD:
-      SetPropertyToField(lookup, name, value);
-      break;
-    case CONSTANT:
-      // Only replace the constant if necessary.
-      if (*value == lookup->GetConstant()) return value;
-      SetPropertyToField(lookup, name, value);
-      break;
-    case CALLBACKS: {
-      Handle<Object> callback_object(lookup->GetCallbackObject(), isolate);
-      return SetPropertyWithCallback(object, callback_object, name, value,
- handle(lookup->holder()), strict_mode);
+  if (lookup->IsTransition()) {
+    result = SetPropertyUsingTransition(handle(lookup->holder()), lookup,
+                                        name, value, attributes);
+  } else {
+    switch (lookup->type()) {
+      case NORMAL:
+        SetNormalizedProperty(handle(lookup->holder()), lookup, value);
+        break;
+      case FIELD:
+        SetPropertyToField(lookup, name, value);
+        break;
+      case CONSTANT:
+        // Only replace the constant if necessary.
+        if (*value == lookup->GetConstant()) return value;
+        SetPropertyToField(lookup, name, value);
+        break;
+      case CALLBACKS: {
+ Handle<Object> callback_object(lookup->GetCallbackObject(), isolate); + return SetPropertyWithCallback(object, callback_object, name, value, + handle(lookup->holder()), strict_mode);
+      }
+      case INTERCEPTOR:
+        result = SetPropertyWithInterceptor(
+ handle(lookup->holder()), name, value, attributes, strict_mode);
+        break;
+      case HANDLER:
+      case NONEXISTENT:
+        UNREACHABLE();
     }
-    case INTERCEPTOR:
- result = SetPropertyWithInterceptor(handle(lookup->holder()), name, value,
-                                          attributes, strict_mode);
-      break;
-    case TRANSITION:
-      result = SetPropertyUsingTransition(handle(lookup->holder()), lookup,
-                                          name, value, attributes);
-      break;
-    case HANDLER:
-    case NONEXISTENT:
-      UNREACHABLE();
   }

   RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
@@ -4216,33 +4214,33 @@
   }

   // Check of IsReadOnly removed from here in clone.
-  switch (lookup.type()) {
-    case NORMAL:
-      ReplaceSlowProperty(object, name, value, attributes);
-      break;
-    case FIELD:
-      SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
-      break;
-    case CONSTANT:
-      // Only replace the constant if necessary.
-      if (lookup.GetAttributes() != attributes ||
-          *value != lookup.GetConstant()) {
+  if (lookup.IsTransition()) {
+    Handle<Object> result = SetPropertyUsingTransition(
+        handle(lookup.holder()), &lookup, name, value, attributes);
+    RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
+  } else {
+    switch (lookup.type()) {
+      case NORMAL:
+        ReplaceSlowProperty(object, name, value, attributes);
+        break;
+      case FIELD:
         SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
-      }
-      break;
-    case CALLBACKS:
-      ConvertAndSetLocalProperty(&lookup, name, value, attributes);
-      break;
-    case TRANSITION: {
-      Handle<Object> result = SetPropertyUsingTransition(
-          handle(lookup.holder()), &lookup, name, value, attributes);
-      RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
-      break;
+        break;
+      case CONSTANT:
+        // Only replace the constant if necessary.
+        if (lookup.GetAttributes() != attributes ||
+            *value != lookup.GetConstant()) {
+ SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
+        }
+        break;
+      case CALLBACKS:
+        ConvertAndSetLocalProperty(&lookup, name, value, attributes);
+        break;
+      case NONEXISTENT:
+      case HANDLER:
+      case INTERCEPTOR:
+        UNREACHABLE();
     }
-    case NONEXISTENT:
-    case HANDLER:
-    case INTERCEPTOR:
-      UNREACHABLE();
   }

   if (is_observed) {
@@ -4386,7 +4384,6 @@
             Handle<JSObject>::cast(receiver),
             name,
             continue_search);
-      case TRANSITION:
       case NONEXISTENT:
         UNREACHABLE();
     }
@@ -4629,7 +4626,6 @@
         break;
       case HANDLER:
       case NORMAL:
-      case TRANSITION:
       case NONEXISTENT:
         UNREACHABLE();
         break;
@@ -5579,11 +5575,11 @@
     }
   }

-  LookupResult result(isolate);
-  Handle<Map> old_map(object->map());
- old_map->LookupTransition(*object, isolate->heap()->frozen_symbol(), &result);
-  if (result.IsTransition()) {
-    Handle<Map> transition_map(result.GetTransitionTarget());
+  Handle<Map> old_map(object->map(), isolate);
+  int transition_index = old_map->SearchTransition(
+      isolate->heap()->frozen_symbol());
+  if (transition_index != TransitionArray::kNotFound) {
+    Handle<Map> transition_map(old_map->GetTransition(transition_index));
     ASSERT(transition_map->has_dictionary_elements());
     ASSERT(transition_map->is_frozen());
     ASSERT(!transition_map->is_extensible());
@@ -5635,22 +5631,19 @@


 void JSObject::SetObserved(Handle<JSObject> object) {
-  ASSERT(!object->map()->is_observed());
   Isolate* isolate = object->GetIsolate();
-
-  LookupResult result(isolate);
-  object->map()->LookupTransition(*object,
-                                  isolate->heap()->observed_symbol(),
-                                  &result);
-
   Handle<Map> new_map;
-  if (result.IsTransition()) {
-    new_map = handle(result.GetTransitionTarget());
+  Handle<Map> old_map(object->map(), isolate);
+  ASSERT(!old_map->is_observed());
+  int transition_index = old_map->SearchTransition(
+      isolate->heap()->observed_symbol());
+  if (transition_index != TransitionArray::kNotFound) {
+    new_map = handle(old_map->GetTransition(transition_index), isolate);
     ASSERT(new_map->is_observed());
-  } else if (object->map()->CanHaveMoreTransitions()) {
-    new_map = Map::CopyForObserved(handle(object->map()));
+  } else if (old_map->CanHaveMoreTransitions()) {
+    new_map = Map::CopyForObserved(old_map);
   } else {
-    new_map = Map::Copy(handle(object->map()));
+    new_map = Map::Copy(old_map);
     new_map->set_is_observed();
   }
   JSObject::MigrateToMap(object, new_map);
=======================================
--- /branches/bleeding_edge/src/objects.h       Thu Apr  3 12:27:24 2014 UTC
+++ /branches/bleeding_edge/src/objects.h       Fri Apr  4 04:49:07 2014 UTC
@@ -6001,6 +6001,7 @@
       Map* transitioned_map);
   inline void SetTransition(int transition_index, Map* target);
   inline Map* GetTransition(int transition_index);
+  inline int SearchTransition(Name* name);

   static Handle<TransitionArray> AddTransition(Handle<Map> map,
                                                Handle<Name> key,
=======================================
--- /branches/bleeding_edge/src/property-details.h Wed Mar 12 10:11:38 2014 UTC +++ /branches/bleeding_edge/src/property-details.h Fri Apr 4 04:49:07 2014 UTC
@@ -77,9 +77,8 @@
   // Only in lookup results, not in descriptors.
   HANDLER                   = 4,
   INTERCEPTOR               = 5,
-  TRANSITION                = 6,
   // Only used as a marker in LookupResult.
-  NONEXISTENT               = 7
+  NONEXISTENT               = 6
 };


=======================================
--- /branches/bleeding_edge/src/property.cc     Tue Apr  1 11:16:13 2014 UTC
+++ /branches/bleeding_edge/src/property.cc     Fri Apr  4 04:49:07 2014 UTC
@@ -29,59 +29,61 @@
   PrintF(out, "LookupResult:\n");
   PrintF(out, " -cacheable = %s\n", IsCacheable() ? "true" : "false");
   PrintF(out, " -attributes = %x\n", GetAttributes());
-  switch (type()) {
-    case NORMAL:
-      PrintF(out, " -type = normal\n");
-      PrintF(out, " -entry = %d", GetDictionaryEntry());
-      break;
-    case CONSTANT:
-      PrintF(out, " -type = constant\n");
-      PrintF(out, " -value:\n");
-      GetConstant()->Print(out);
-      PrintF(out, "\n");
-      break;
-    case FIELD:
-      PrintF(out, " -type = field\n");
-      PrintF(out, " -index = %d", GetFieldIndex().field_index());
-      PrintF(out, "\n");
-      break;
-    case CALLBACKS:
-      PrintF(out, " -type = call backs\n");
-      PrintF(out, " -callback object:\n");
-      GetCallbackObject()->Print(out);
-      break;
-    case HANDLER:
-      PrintF(out, " -type = lookup proxy\n");
-      break;
-    case INTERCEPTOR:
-      PrintF(out, " -type = lookup interceptor\n");
-      break;
-    case TRANSITION:
-      switch (GetTransitionDetails().type()) {
-        case FIELD:
-          PrintF(out, " -type = map transition\n");
-          PrintF(out, " -map:\n");
-          GetTransitionTarget()->Print(out);
-          PrintF(out, "\n");
-          return;
-        case CONSTANT:
-          PrintF(out, " -type = constant property transition\n");
-          PrintF(out, " -map:\n");
-          GetTransitionTarget()->Print(out);
-          PrintF(out, "\n");
-          return;
-        case CALLBACKS:
-          PrintF(out, " -type = callbacks transition\n");
-          PrintF(out, " -callback object:\n");
-          GetCallbackObject()->Print(out);
-          return;
-        default:
-          UNREACHABLE();
-          return;
-      }
-    case NONEXISTENT:
-      UNREACHABLE();
-      break;
+  if (IsTransition()) {
+    switch (type()) {
+      case FIELD:
+        PrintF(out, " -type = map transition\n");
+        PrintF(out, " -map:\n");
+        GetTransitionTarget()->Print(out);
+        PrintF(out, "\n");
+        break;
+      case CONSTANT:
+        PrintF(out, " -type = constant property transition\n");
+        PrintF(out, " -map:\n");
+        GetTransitionTarget()->Print(out);
+        PrintF(out, "\n");
+        break;
+      case CALLBACKS:
+        PrintF(out, " -type = callbacks transition\n");
+        PrintF(out, " -callback object:\n");
+        GetCallbackObject()->Print(out);
+        break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+  } else {
+    switch (type()) {
+      case NORMAL:
+        PrintF(out, " -type = normal\n");
+        PrintF(out, " -entry = %d", GetDictionaryEntry());
+        break;
+      case CONSTANT:
+        PrintF(out, " -type = constant\n");
+        PrintF(out, " -value:\n");
+        GetConstant()->Print(out);
+        PrintF(out, "\n");
+        break;
+      case FIELD:
+        PrintF(out, " -type = field\n");
+        PrintF(out, " -index = %d", GetFieldIndex().field_index());
+        PrintF(out, "\n");
+        break;
+      case CALLBACKS:
+        PrintF(out, " -type = call backs\n");
+        PrintF(out, " -callback object:\n");
+        GetCallbackObject()->Print(out);
+        break;
+      case HANDLER:
+        PrintF(out, " -type = lookup proxy\n");
+        break;
+      case INTERCEPTOR:
+        PrintF(out, " -type = lookup interceptor\n");
+        break;
+      case NONEXISTENT:
+        UNREACHABLE();
+        break;
+    }
   }
 }

=======================================
--- /branches/bleeding_edge/src/property.h      Tue Apr  1 11:16:13 2014 UTC
+++ /branches/bleeding_edge/src/property.h      Fri Apr  4 04:49:07 2014 UTC
@@ -180,16 +180,15 @@

   bool CanHoldValue(Handle<Object> value) {
     if (IsNormal()) return true;
-    ASSERT(!IsTransition());
     return value->FitsRepresentation(details_.representation());
   }

   void TransitionResult(JSObject* holder, Map* target) {
     lookup_type_ = TRANSITION_TYPE;
-    details_ = PropertyDetails(NONE, TRANSITION, Representation::None());
+    number_ = target->LastAdded();
+    details_ = target->instance_descriptors()->GetDetails(number_);
     holder_ = holder;
     transition_ = target;
-    number_ = 0xAAAA;
   }

   void DictionaryResult(JSObject* holder, int entry) {
@@ -239,20 +238,17 @@

   Representation representation() const {
     ASSERT(IsFound());
-    ASSERT(!IsTransition());
     ASSERT(details_.type() != NONEXISTENT);
     return details_.representation();
   }

   PropertyAttributes GetAttributes() const {
-    ASSERT(!IsTransition());
     ASSERT(IsFound());
     ASSERT(details_.type() != NONEXISTENT);
     return details_.attributes();
   }

   PropertyDetails GetPropertyDetails() const {
-    ASSERT(!IsTransition());
     return details_;
   }

@@ -264,38 +260,40 @@
   // Property callbacks does not include transitions to callbacks.
   bool IsPropertyCallbacks() const {
     ASSERT(!(details_.type() == CALLBACKS && !IsFound()));
-    return details_.type() == CALLBACKS;
+    return !IsTransition() && details_.type() == CALLBACKS;
   }

   bool IsReadOnly() const {
     ASSERT(IsFound());
-    ASSERT(!IsTransition());
     ASSERT(details_.type() != NONEXISTENT);
     return details_.IsReadOnly();
   }

   bool IsField() const {
     ASSERT(!(details_.type() == FIELD && !IsFound()));
-    return details_.type() == FIELD;
+    return IsDescriptorOrDictionary() && type() == FIELD;
   }

   bool IsNormal() const {
     ASSERT(!(details_.type() == NORMAL && !IsFound()));
-    return details_.type() == NORMAL;
+    return IsDescriptorOrDictionary() && type() == NORMAL;
   }

   bool IsConstant() const {
     ASSERT(!(details_.type() == CONSTANT && !IsFound()));
-    return details_.type() == CONSTANT;
+    return IsDescriptorOrDictionary() && type() == CONSTANT;
   }

   bool IsConstantFunction() const {
-    return IsConstant() && GetValue()->IsJSFunction();
+    return IsConstant() && GetConstant()->IsJSFunction();
   }

   bool IsDontDelete() const { return details_.IsDontDelete(); }
   bool IsDontEnum() const { return details_.IsDontEnum(); }
   bool IsFound() const { return lookup_type_ != NOT_FOUND; }
+  bool IsDescriptorOrDictionary() const {
+ return lookup_type_ == DESCRIPTOR_TYPE || lookup_type_ == DICTIONARY_TYPE;
+  }
   bool IsTransition() const { return lookup_type_ == TRANSITION_TYPE; }
   bool IsHandler() const { return lookup_type_ == HANDLER_TYPE; }
   bool IsInterceptor() const { return lookup_type_ == INTERCEPTOR_TYPE; }
@@ -306,20 +304,30 @@
   }

   bool IsDataProperty() const {
-    switch (type()) {
-      case FIELD:
-      case NORMAL:
-      case CONSTANT:
-        return true;
-      case CALLBACKS: {
-        Object* callback = GetCallbackObject();
-        return callback->IsAccessorInfo() || callback->IsForeign();
-      }
-      case HANDLER:
-      case INTERCEPTOR:
-      case TRANSITION:
-      case NONEXISTENT:
+    switch (lookup_type_) {
+      case NOT_FOUND:
+      case TRANSITION_TYPE:
+      case HANDLER_TYPE:
+      case INTERCEPTOR_TYPE:
         return false;
+
+      case DESCRIPTOR_TYPE:
+      case DICTIONARY_TYPE:
+        switch (type()) {
+          case FIELD:
+          case NORMAL:
+          case CONSTANT:
+            return true;
+          case CALLBACKS: {
+            Object* callback = GetCallbackObject();
+            return callback->IsAccessorInfo() || callback->IsForeign();
+          }
+          case HANDLER:
+          case INTERCEPTOR:
+          case NONEXISTENT:
+            UNREACHABLE();
+            return false;
+        }
     }
     UNREACHABLE();
     return false;
@@ -329,45 +337,52 @@
   void DisallowCaching() { cacheable_ = false; }

   Object* GetLazyValue() const {
-    switch (type()) {
-      case FIELD:
-        return holder()->RawFastPropertyAt(GetFieldIndex().field_index());
-      case NORMAL: {
-        Object* value;
- value = holder()->property_dictionary()->ValueAt(GetDictionaryEntry());
-        if (holder()->IsGlobalObject()) {
-          value = PropertyCell::cast(value)->value();
+    switch (lookup_type_) {
+      case NOT_FOUND:
+      case TRANSITION_TYPE:
+      case HANDLER_TYPE:
+      case INTERCEPTOR_TYPE:
+        return isolate()->heap()->the_hole_value();
+
+      case DESCRIPTOR_TYPE:
+      case DICTIONARY_TYPE:
+        switch (type()) {
+          case FIELD:
+ return holder()->RawFastPropertyAt(GetFieldIndex().field_index());
+          case NORMAL: {
+            Object* value = holder()->property_dictionary()->ValueAt(
+                GetDictionaryEntry());
+            if (holder()->IsGlobalObject()) {
+              value = PropertyCell::cast(value)->value();
+            }
+            return value;
+          }
+          case CONSTANT:
+            return GetConstant();
+          case CALLBACKS:
+            return isolate()->heap()->the_hole_value();
+          case HANDLER:
+          case INTERCEPTOR:
+          case NONEXISTENT:
+            UNREACHABLE();
+            return NULL;
         }
-        return value;
-      }
-      case CONSTANT:
-        return GetConstant();
-      case CALLBACKS:
-      case HANDLER:
-      case INTERCEPTOR:
-      case TRANSITION:
-      case NONEXISTENT:
-        return isolate()->heap()->the_hole_value();
     }
     UNREACHABLE();
     return NULL;
   }

   Map* GetTransitionTarget() const {
+    ASSERT(IsTransition());
     return transition_;
   }
-
-  PropertyDetails GetTransitionDetails() const {
-    ASSERT(IsTransition());
-    return transition_->GetLastDescriptorDetails();
-  }

   bool IsTransitionToField() const {
-    return IsTransition() && GetTransitionDetails().type() == FIELD;
+    return IsTransition() && details_.type() == FIELD;
   }

   bool IsTransitionToConstant() const {
-    return IsTransition() && GetTransitionDetails().type() == CONSTANT;
+    return IsTransition() && details_.type() == CONSTANT;
   }

   int GetDescriptorIndex() const {
@@ -376,7 +391,8 @@
   }

   PropertyIndex GetFieldIndex() const {
-    ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
+    ASSERT(lookup_type_ == DESCRIPTOR_TYPE ||
+           lookup_type_ == TRANSITION_TYPE);
return PropertyIndex::NewFieldIndex(GetFieldIndexFromMap(holder()->map()));
   }

@@ -409,7 +425,8 @@
   }

   Object* GetCallbackObject() const {
-    ASSERT(type() == CALLBACKS && !IsTransition());
+    ASSERT(!IsTransition());
+    ASSERT(type() == CALLBACKS);
     return GetValue();
   }

@@ -420,6 +437,8 @@
   Object* GetValue() const {
     if (lookup_type_ == DESCRIPTOR_TYPE) {
       return GetValueFromMap(holder()->map());
+    } else if (lookup_type_ == TRANSITION_TYPE) {
+      return GetValueFromMap(transition_);
     }
     // In the dictionary case, the data is held in the value field.
     ASSERT(lookup_type_ == DICTIONARY_TYPE);
@@ -427,13 +446,15 @@
   }

   Object* GetValueFromMap(Map* map) const {
-    ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
+    ASSERT(lookup_type_ == DESCRIPTOR_TYPE ||
+           lookup_type_ == TRANSITION_TYPE);
     ASSERT(number_ < map->NumberOfOwnDescriptors());
     return map->instance_descriptors()->GetValue(number_);
   }

   int GetFieldIndexFromMap(Map* map) const {
-    ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
+    ASSERT(lookup_type_ == DESCRIPTOR_TYPE ||
+           lookup_type_ == TRANSITION_TYPE);
     ASSERT(number_ < map->NumberOfOwnDescriptors());
     return map->instance_descriptors()->GetFieldIndex(number_);
   }
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Thu Apr  3 14:25:59 2014 UTC
+++ /branches/bleeding_edge/src/runtime.cc      Fri Apr  4 04:49:07 2014 UTC
@@ -5217,23 +5217,23 @@
   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
   LookupResult lookup(isolate);
   object->LookupRealNamedProperty(*key, &lookup);
-  if (!lookup.IsFound()) return isolate->heap()->undefined_value();
-  switch (lookup.type()) {
-    case NORMAL:
-      return lookup.holder()->GetNormalizedProperty(&lookup);
-    case FIELD:
-      return lookup.holder()->FastPropertyAt(
-          lookup.representation(),
-          lookup.GetFieldIndex().field_index());
-    case CONSTANT:
-      return lookup.GetConstant();
-    case CALLBACKS:
-    case HANDLER:
-    case INTERCEPTOR:
-    case TRANSITION:
-      return isolate->heap()->undefined_value();
-    case NONEXISTENT:
-      UNREACHABLE();
+  if (lookup.IsFound() && !lookup.IsTransition()) {
+    switch (lookup.type()) {
+      case NORMAL:
+        return lookup.holder()->GetNormalizedProperty(&lookup);
+      case FIELD:
+        return lookup.holder()->FastPropertyAt(
+            lookup.representation(),
+            lookup.GetFieldIndex().field_index());
+      case CONSTANT:
+        return lookup.GetConstant();
+      case CALLBACKS:
+      case HANDLER:
+      case INTERCEPTOR:
+        break;
+      case NONEXISTENT:
+        UNREACHABLE();
+    }
   }
   return isolate->heap()->undefined_value();
 }
@@ -10783,6 +10783,7 @@
                                            LookupResult* result,
                                            bool* caught_exception) {
   Object* value;
+  if (result->IsTransition()) return heap->undefined_value();
   switch (result->type()) {
     case NORMAL:
       value = result->holder()->GetNormalizedProperty(result);
@@ -10826,7 +10827,6 @@
       }
     }
     case INTERCEPTOR:
-    case TRANSITION:
       return heap->undefined_value();
     case HANDLER:
     case NONEXISTENT:

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to