Revision: 10600
Author:   [email protected]
Date:     Fri Feb  3 05:37:13 2012
Log:      Removed IsTransitionType predicate.

With the upcoming changes to CALLBACKS properties, a predicate on the transition type alone doesn't make sense anymore: For CALLBACKS one has to look into the
property's value to decide, and there is even the possibility of having a an
accessor function *and* a transition in the same property.

I am not completely happy with some parts of this CL, because they contain
redundant code, but given the various representations we currently have for
property type/value pairs, I can see no easy way around that. Perhaps one can improve this a bit in a different CL, the current diversity really, really hurts
productivity...

As a bonus, this CL includes a few minor things:

 * CaseClause::RecordTypeFeedback has been cleaned up and it handles the
NULL_DESCRIPTOR case correctly now. Under some (very unlikely) circumstances, we previously missed some opportunities for monomorphic calls. In general, it
   is rather unfortunate that NULL_DESCRIPTOR "shines through", it is just a
   hack for the inability to remove a descriptor entry during GC, something
   callers shouldn't have to be aware of.

* DescriptorArray::CopyInsert has been cleaned up a bit, preparing it for later
   CALLBACKS-related changes.

 * LookupResult::Print is now more informative for CONSTANT_TRANSITION.

Review URL: https://chromiumcodereview.appspot.com/9320066
http://code.google.com/p/v8/source/detail?r=10600

Modified:
 /branches/bleeding_edge/src/ast.cc
 /branches/bleeding_edge/src/objects-inl.h
 /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/ast.cc  Wed Jan 25 08:31:25 2012
+++ /branches/bleeding_edge/src/ast.cc  Fri Feb  3 05:37:13 2012
@@ -730,33 +730,32 @@


 bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) {
-  // If there is an interceptor, we can't compute the target for
-  // a direct call.
+ // If there is an interceptor, we can't compute the target for a direct call.
   if (type->has_named_interceptor()) return false;

   if (check_type_ == RECEIVER_MAP_CHECK) {
-    // For primitive checks the holder is set up to point to the
-    // corresponding prototype object, i.e. one step of the algorithm
-    // below has been already performed.
-    // For non-primitive checks we clear it to allow computing targets
-    // for polymorphic calls.
+ // For primitive checks the holder is set up to point to the corresponding + // prototype object, i.e. one step of the algorithm below has been already
+    // performed. For non-primitive checks we clear it to allow computing
+    // targets for polymorphic calls.
     holder_ = Handle<JSObject>::null();
   }
+  LookupResult lookup(type->GetIsolate());
   while (true) {
-    LookupResult lookup(type->GetIsolate());
     type->LookupInDescriptors(NULL, *name, &lookup);
-    // If the function wasn't found directly in the map, we start
-    // looking upwards through the prototype chain.
-    if ((!lookup.IsFound() || IsTransitionType(lookup.type()))
-        && type->prototype()->IsJSObject()) {
-      holder_ = Handle<JSObject>(JSObject::cast(type->prototype()));
-      type = Handle<Map>(holder()->map());
-    } else if (lookup.IsFound() && lookup.type() == CONSTANT_FUNCTION) {
- target_ = Handle<JSFunction>(lookup.GetConstantFunctionFromMap(*type));
-      return true;
-    } else {
+    // For properties we know the target iff we have a constant function.
+    if (lookup.IsFound() && lookup.IsProperty()) {
+      if (lookup.type() == CONSTANT_FUNCTION) {
+ target_ = Handle<JSFunction>(lookup.GetConstantFunctionFromMap(*type));
+        return true;
+      }
       return false;
     }
+ // If we reach the end of the prototype chain, we don't know the target.
+    if (!type->prototype()->IsJSObject()) return false;
+    // Go up the prototype chain, recording where we are currently.
+    holder_ = Handle<JSObject>(JSObject::cast(type->prototype()));
+    type = Handle<Map>(holder()->map());
   }
 }

=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Fri Jan 27 08:09:20 2012
+++ /branches/bleeding_edge/src/objects-inl.h   Fri Feb  3 05:37:13 2012
@@ -1991,8 +1991,28 @@
 }


-bool DescriptorArray::IsTransition(int descriptor_number) {
-  return IsTransitionType(GetType(descriptor_number));
+bool DescriptorArray::IsTransitionOnly(int descriptor_number) {
+  switch (GetType(descriptor_number)) {
+    case MAP_TRANSITION:
+    case CONSTANT_TRANSITION:
+    case ELEMENTS_TRANSITION:
+      return true;
+    case CALLBACKS: {
+      Object* value = GetValue(descriptor_number);
+      if (!value->IsAccessorPair()) return false;
+      AccessorPair* accessors = AccessorPair::cast(value);
+      return accessors->getter()->IsMap() && accessors->setter()->IsMap();
+    }
+    case NORMAL:
+    case FIELD:
+    case CONSTANT_FUNCTION:
+    case HANDLER:
+    case INTERCEPTOR:
+    case NULL_DESCRIPTOR:
+      return false;
+  }
+  UNREACHABLE();  // Keep the compiler happy.
+  return false;
 }


=======================================
--- /branches/bleeding_edge/src/objects.cc      Mon Jan 30 06:23:35 2012
+++ /branches/bleeding_edge/src/objects.cc      Fri Feb  3 05:37:13 2012
@@ -1823,7 +1823,7 @@
int new_enumeration_index = 0; // 0 means "Use the next available index."
   if (old_index != -1) {
     // All calls to ReplaceSlowProperty have had all transitions removed.
-    ASSERT(!dictionary->DetailsAt(old_index).IsTransition());
+    ASSERT(!dictionary->ContainsTransition(old_index));
     new_enumeration_index = dictionary->DetailsAt(old_index).index();
   }

@@ -5729,7 +5729,7 @@
   // Conversely, we filter after replacing, so replacing a transition and
   // removing all other transitions is not supported.
   bool remove_transitions = transition_flag == REMOVE_TRANSITIONS;
-  ASSERT(remove_transitions == !descriptor->GetDetails().IsTransition());
+  ASSERT(remove_transitions == !descriptor->ContainsTransition());
   ASSERT(descriptor->GetDetails().type() != NULL_DESCRIPTOR);

   // Ensure the key is a symbol.
@@ -5738,29 +5738,18 @@
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }

-  int transitions = 0;
-  int null_descriptors = 0;
-  if (remove_transitions) {
-    for (int i = 0; i < number_of_descriptors(); i++) {
-      if (IsTransition(i)) transitions++;
-      if (IsNullDescriptor(i)) null_descriptors++;
-    }
-  } else {
-    for (int i = 0; i < number_of_descriptors(); i++) {
-      if (IsNullDescriptor(i)) null_descriptors++;
-    }
-  }
-  int new_size = number_of_descriptors() - transitions - null_descriptors;
+  int new_size = 0;
+  for (int i = 0; i < number_of_descriptors(); i++) {
+    if (IsNullDescriptor(i)) continue;
+    if (remove_transitions && IsTransitionOnly(i)) continue;
+    new_size++;
+  }

   // If key is in descriptor, we replace it in-place when filtering.
   // Count a null descriptor for key as inserted, not replaced.
   int index = Search(descriptor->GetKey());
-  const bool inserting = (index == kNotFound);
-  const bool replacing = !inserting;
+  const bool replacing = (index != kNotFound);
   bool keep_enumeration_index = false;
-  if (inserting) {
-    ++new_size;
-  }
   if (replacing) {
     // We are replacing an existing descriptor.  We keep the enumeration
     // index of a visible property.
@@ -5775,6 +5764,8 @@
      // a transition that will be replaced.  Adjust count in this case.
       ++new_size;
     }
+  } else {
+    ++new_size;
   }

   DescriptorArray* new_descriptors;
@@ -5789,7 +5780,7 @@
// Set the enumeration index in the descriptors and set the enumeration index
   // in the result.
   int enumeration_index = NextEnumerationIndex();
-  if (!descriptor->GetDetails().IsTransition()) {
+  if (!descriptor->ContainsTransition()) {
     if (keep_enumeration_index) {
       descriptor->SetEnumerationIndex(
           PropertyDetails(GetDetails(index)).index());
@@ -5812,7 +5803,7 @@
       break;
     }
     if (IsNullDescriptor(from_index)) continue;
-    if (remove_transitions && IsTransition(from_index)) continue;
+    if (remove_transitions && IsTransitionOnly(from_index)) continue;
     new_descriptors->CopyFrom(to_index++, this, from_index, witness);
   }

@@ -5821,7 +5812,7 @@

   for (; from_index < number_of_descriptors(); from_index++) {
     if (IsNullDescriptor(from_index)) continue;
-    if (remove_transitions && IsTransition(from_index)) continue;
+    if (remove_transitions && IsTransitionOnly(from_index)) continue;
     new_descriptors->CopyFrom(to_index++, this, from_index, witness);
   }

@@ -11131,6 +11122,31 @@
   }
   return kNotFound;
 }
+
+
+bool StringDictionary::ContainsTransition(int entry) {
+  switch (DetailsAt(entry).type()) {
+    case MAP_TRANSITION:
+    case CONSTANT_TRANSITION:
+    case ELEMENTS_TRANSITION:
+      return true;
+    case CALLBACKS: {
+      Object* value = ValueAt(entry);
+      if (!value->IsAccessorPair()) return false;
+      AccessorPair* accessors = AccessorPair::cast(value);
+      return accessors->getter()->IsMap() || accessors->setter()->IsMap();
+    }
+    case NORMAL:
+    case FIELD:
+    case CONSTANT_FUNCTION:
+    case HANDLER:
+    case INTERCEPTOR:
+    case NULL_DESCRIPTOR:
+      return false;
+  }
+  UNREACHABLE();  // Keep the compiler happy.
+  return false;
+}


 template<typename Shape, typename Key>
=======================================
--- /branches/bleeding_edge/src/objects.h       Thu Feb  2 05:41:06 2012
+++ /branches/bleeding_edge/src/objects.h       Fri Feb  3 05:37:13 2012
@@ -2412,7 +2412,7 @@
   inline Object* GetCallbacksObject(int descriptor_number);
   inline AccessorDescriptor* GetCallbacks(int descriptor_number);
   inline bool IsProperty(int descriptor_number);
-  inline bool IsTransition(int descriptor_number);
+  inline bool IsTransitionOnly(int descriptor_number);
   inline bool IsNullDescriptor(int descriptor_number);
   inline bool IsDontEnum(int descriptor_number);

@@ -3038,6 +3038,8 @@
   // Find entry for key, otherwise return kNotFound. Optimized version of
   // HashTable::FindEntry.
   int FindEntry(String* key);
+
+  bool ContainsTransition(int entry);
 };


=======================================
--- /branches/bleeding_edge/src/property-details.h      Wed Nov  9 04:47:15 2011
+++ /branches/bleeding_edge/src/property-details.h      Fri Feb  3 05:37:13 2012
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -73,26 +73,6 @@
 };


-inline bool IsTransitionType(PropertyType type) {
-  switch (type) {
-    case MAP_TRANSITION:
-    case CONSTANT_TRANSITION:
-    case ELEMENTS_TRANSITION:
-      return true;
-    case NORMAL:
-    case FIELD:
-    case CONSTANT_FUNCTION:
-    case CALLBACKS:
-    case HANDLER:
-    case INTERCEPTOR:
-    case NULL_DESCRIPTOR:
-      return false;
-  }
-  UNREACHABLE();  // keep the compiler happy
-  return false;
-}
-
-
 inline bool IsRealProperty(PropertyType type) {
   switch (type) {
     case NORMAL:
@@ -138,12 +118,6 @@
   inline Smi* AsSmi();

   PropertyType type() { return TypeField::decode(value_); }
-
-  bool IsTransition() {
-    PropertyType t = type();
-    ASSERT(t != INTERCEPTOR);
-    return IsTransitionType(t);
-  }

   bool IsProperty() {
     return IsRealProperty(type());
=======================================
--- /branches/bleeding_edge/src/property.cc     Tue Oct 18 04:18:55 2011
+++ /branches/bleeding_edge/src/property.cc     Fri Feb  3 05:37:13 2012
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -91,6 +91,9 @@
       break;
     case CONSTANT_TRANSITION:
       PrintF(out, " -type = constant property transition\n");
+      PrintF(out, " -map:\n");
+      GetTransitionMap()->Print(out);
+      PrintF(out, "\n");
       break;
     case NULL_DESCRIPTOR:
       PrintF(out, " =type = null descriptor\n");
@@ -111,4 +114,28 @@
 #endif


+bool Descriptor::ContainsTransition() {
+  switch (details_.type()) {
+    case MAP_TRANSITION:
+    case CONSTANT_TRANSITION:
+    case ELEMENTS_TRANSITION:
+      return true;
+    case CALLBACKS: {
+      if (!value_->IsAccessorPair()) return false;
+      AccessorPair* accessors = AccessorPair::cast(value_);
+      return accessors->getter()->IsMap() || accessors->setter()->IsMap();
+    }
+    case NORMAL:
+    case FIELD:
+    case CONSTANT_FUNCTION:
+    case HANDLER:
+    case INTERCEPTOR:
+    case NULL_DESCRIPTOR:
+      return false;
+  }
+  UNREACHABLE();  // Keep the compiler happy.
+  return false;
+}
+
+
 } }  // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/property.h      Fri Jan 20 07:10:35 2012
+++ /branches/bleeding_edge/src/property.h      Fri Feb  3 05:37:13 2012
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -70,6 +70,8 @@
     ASSERT(PropertyDetails::IsValidIndex(index));
details_ = PropertyDetails(details_.attributes(), details_.type(), index);
   }
+
+  bool ContainsTransition();

  private:
   String* key_;
@@ -290,7 +292,9 @@

   Map* GetTransitionMap() {
     ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
-    ASSERT(IsTransitionType(type()));
+    ASSERT(type() == MAP_TRANSITION ||
+           type() == ELEMENTS_TRANSITION ||
+           type() == CONSTANT_TRANSITION);
     return Map::cast(GetValue());
   }

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to