Remove relocation lock.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 16 Apr 2013 11:00:02 +0000 (11:00 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 16 Apr 2013 11:00:02 +0000 (11:00 +0000)
Freeze HValue hash codes that are based on object addresses.

R=svenpanne@chromium.org
BUG=

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14273 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/handles-inl.h
src/heap.cc
src/heap.h
src/hydrogen-instructions.cc
src/hydrogen-instructions.h
src/hydrogen.cc
src/hydrogen.h
src/mark-compact.cc

index b763c86..bb11311 100644 (file)
@@ -59,7 +59,6 @@ inline bool Handle<T>::is_identical_to(const Handle<T> other) const {
   if (FLAG_enable_slow_asserts) {
     Isolate* isolate = Isolate::Current();
     CHECK(isolate->AllowHandleDereference() ||
-          Heap::RelocationLock::IsLocked(isolate->heap()) ||
           !isolate->optimizing_compiler_thread()->IsOptimizerThread());
   }
 #endif  // DEBUG
index 7eb6881..697261f 100644 (file)
@@ -162,8 +162,7 @@ Heap::Heap()
 #endif
       promotion_queue_(this),
       configured_(false),
-      chunks_queued_for_free_(NULL),
-      relocation_mutex_(NULL) {
+      chunks_queued_for_free_(NULL) {
   // Allow build-time customization of the max semispace size. Building
   // V8 with snapshots and a non-default max semispace size is much
   // easier if you can define it as part of the build environment.
@@ -1294,8 +1293,6 @@ class ScavengeWeakObjectRetainer : public WeakObjectRetainer {
 
 
 void Heap::Scavenge() {
-  RelocationLock relocation_lock(this);
-
 #ifdef VERIFY_HEAP
   if (FLAG_verify_heap) VerifyNonPointerSpacePointers();
 #endif
@@ -6628,11 +6625,6 @@ bool Heap::SetUp() {
 
   store_buffer()->SetUp();
 
-  if (FLAG_parallel_recompilation) relocation_mutex_ = OS::CreateMutex();
-#ifdef DEBUG
-  relocation_mutex_locked_ = false;
-#endif  // DEBUG
-
   return true;
 }
 
@@ -6735,8 +6727,6 @@ void Heap::TearDown() {
   incremental_marking()->TearDown();
 
   isolate_->memory_allocator()->TearDown();
-
-  delete relocation_mutex_;
 }
 
 
index 5f54b6c..7b4b70d 100644 (file)
@@ -1846,38 +1846,6 @@ class Heap {
 
   void CheckpointObjectStats();
 
-  // We don't use a ScopedLock here since we want to lock the heap
-  // only when FLAG_parallel_recompilation is true.
-  class RelocationLock {
-   public:
-    explicit RelocationLock(Heap* heap) : heap_(heap) {
-      if (FLAG_parallel_recompilation) {
-        heap_->relocation_mutex_->Lock();
-#ifdef DEBUG
-        heap_->relocation_mutex_locked_ = true;
-#endif  // DEBUG
-      }
-    }
-
-    ~RelocationLock() {
-      if (FLAG_parallel_recompilation) {
-#ifdef DEBUG
-        heap_->relocation_mutex_locked_ = false;
-#endif  // DEBUG
-        heap_->relocation_mutex_->Unlock();
-      }
-    }
-
-#ifdef DEBUG
-    static bool IsLocked(Heap* heap) {
-      return heap->relocation_mutex_locked_;
-    }
-#endif  // DEBUG
-
-   private:
-    Heap* heap_;
-  };
-
  private:
   Heap();
 
@@ -2347,11 +2315,6 @@ class Heap {
 
   MemoryChunk* chunks_queued_for_free_;
 
-  Mutex* relocation_mutex_;
-#ifdef DEBUG
-  bool relocation_mutex_locked_;
-#endif  // DEBUG;
-
   friend class Factory;
   friend class GCTracer;
   friend class DisallowAllocationFailure;
index 36d1e11..60a6912 100644 (file)
@@ -1584,10 +1584,10 @@ void HCheckMaps::SetSideEffectDominator(GVNFlag side_effect,
   // for which the map is known.
   if (HasNoUses() && dominator->IsStoreNamedField()) {
     HStoreNamedField* store = HStoreNamedField::cast(dominator);
-    Handle<Map> map = store->transition();
-    if (map.is_null() || store->object() != value()) return;
+    UniqueValueId map_unique_id = store->transition_unique_id();
+    if (!map_unique_id.IsInitialized() || store->object() != value()) return;
     for (int i = 0; i < map_set()->length(); i++) {
-      if (map.is_identical_to(map_set()->at(i))) {
+      if (map_unique_id == map_unique_ids_.at(i)) {
         DeleteAndReplaceWith(NULL);
         return;
       }
@@ -2047,6 +2047,7 @@ static bool IsInteger32(double value) {
 
 HConstant::HConstant(Handle<Object> handle, Representation r)
   : handle_(handle),
+    unique_id_(),
     has_int32_value_(false),
     has_double_value_(false),
     is_internalized_string_(false),
@@ -2075,11 +2076,13 @@ HConstant::HConstant(Handle<Object> handle, Representation r)
 
 
 HConstant::HConstant(Handle<Object> handle,
+                     UniqueValueId unique_id,
                      Representation r,
                      HType type,
                      bool is_internalize_string,
                      bool boolean_value)
     : handle_(handle),
+      unique_id_(unique_id),
       has_int32_value_(false),
       has_double_value_(false),
       is_internalized_string_(is_internalize_string),
@@ -2095,7 +2098,9 @@ HConstant::HConstant(Handle<Object> handle,
 HConstant::HConstant(int32_t integer_value,
                      Representation r,
                      Handle<Object> optional_handle)
-    : has_int32_value_(true),
+    : handle_(optional_handle),
+      unique_id_(),
+      has_int32_value_(true),
       has_double_value_(true),
       is_internalized_string_(false),
       boolean_value_(integer_value != 0),
@@ -2108,7 +2113,9 @@ HConstant::HConstant(int32_t integer_value,
 HConstant::HConstant(double double_value,
                      Representation r,
                      Handle<Object> optional_handle)
-    : has_int32_value_(IsInteger32(double_value)),
+    : handle_(optional_handle),
+      unique_id_(),
+      has_int32_value_(IsInteger32(double_value)),
       has_double_value_(true),
       is_internalized_string_(false),
       boolean_value_(double_value != 0 && !isnan(double_value)),
@@ -2133,8 +2140,12 @@ HConstant* HConstant::CopyToRepresentation(Representation r, Zone* zone) const {
   if (has_int32_value_) return new(zone) HConstant(int32_value_, r, handle_);
   if (has_double_value_) return new(zone) HConstant(double_value_, r, handle_);
   ASSERT(!handle_.is_null());
-  return new(zone) HConstant(
-      handle_, r, type_from_value_, is_internalized_string_, boolean_value_);
+  return new(zone) HConstant(handle_,
+                             unique_id_,
+                             r,
+                             type_from_value_,
+                             is_internalized_string_,
+                             boolean_value_);
 }
 
 
@@ -2459,6 +2470,8 @@ HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
                                                        Zone* zone)
     : types_(Min(types->length(), kMaxLoadPolymorphism), zone),
       name_(name),
+      types_unique_ids_(0, zone),
+      name_unique_id_(),
       need_generic_(false) {
   SetOperandAt(0, context);
   SetOperandAt(1, object);
@@ -2525,15 +2538,39 @@ HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
 }
 
 
+void HCheckMaps::FinalizeUniqueValueId() {
+  if (!map_unique_ids_.is_empty()) return;
+  Zone* zone = block()->zone();
+  map_unique_ids_.Initialize(map_set_.length(), zone);
+  for (int i = 0; i < map_set_.length(); i++) {
+    map_unique_ids_.Add(UniqueValueId(map_set_.at(i)), zone);
+  }
+}
+
+
+void HLoadNamedFieldPolymorphic::FinalizeUniqueValueId() {
+  if (!types_unique_ids_.is_empty()) return;
+  Zone* zone = block()->zone();
+  types_unique_ids_.Initialize(types_.length(), zone);
+  for (int i = 0; i < types_.length(); i++) {
+    types_unique_ids_.Add(UniqueValueId(types_.at(i)), zone);
+  }
+  name_unique_id_ = UniqueValueId(name_);
+}
+
+
 bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) {
+  ASSERT_EQ(types_.length(), types_unique_ids_.length());
   HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value);
-  if (types_.length() != other->types()->length()) return false;
-  if (!name_.is_identical_to(other->name())) return false;
+  if (name_unique_id_ != other->name_unique_id_) return false;
+  if (types_unique_ids_.length() != other->types_unique_ids_.length()) {
+    return false;
+  }
   if (need_generic_ != other->need_generic_) return false;
-  for (int i = 0; i < types_.length(); i++) {
+  for (int i = 0; i < types_unique_ids_.length(); i++) {
     bool found = false;
-    for (int j = 0; j < types_.length(); j++) {
-      if (types_.at(j).is_identical_to(other->types()->at(i))) {
+    for (int j = 0; j < types_unique_ids_.length(); j++) {
+      if (types_unique_ids_.at(j) == other->types_unique_ids_.at(i)) {
         found = true;
         break;
       }
index ae118a1..6853dfe 100644 (file)
@@ -234,14 +234,6 @@ class LChunkBuilder;
   virtual Opcode opcode() const { return HValue::k##type; }
 
 
-#ifdef DEBUG
-#define ASSERT_ALLOCATION_DISABLED                                       \
-  ASSERT(isolate()->optimizing_compiler_thread()->IsOptimizerThread() || \
-         !isolate()->heap()->IsAllocationAllowed())
-#else
-#define ASSERT_ALLOCATION_DISABLED do {} while (0)
-#endif
-
 class Range: public ZoneObject {
  public:
   Range()
@@ -364,6 +356,48 @@ class Representation {
 };
 
 
+class UniqueValueId {
+ public:
+  UniqueValueId() : raw_address_(NULL) { }
+
+  explicit UniqueValueId(Object* object) {
+    raw_address_ = reinterpret_cast<Address>(object);
+    ASSERT(IsInitialized());
+  }
+
+  explicit UniqueValueId(Handle<Object> handle) {
+    static const Address kEmptyHandleSentinel = reinterpret_cast<Address>(1);
+    if (handle.is_null()) {
+      raw_address_ = kEmptyHandleSentinel;
+    } else {
+      raw_address_ = reinterpret_cast<Address>(*handle);
+      ASSERT_NE(kEmptyHandleSentinel, raw_address_);
+    }
+    ASSERT(IsInitialized());
+  }
+
+  bool IsInitialized() const { return raw_address_ != NULL; }
+
+  bool operator==(const UniqueValueId& other) const {
+    ASSERT(IsInitialized() && other.IsInitialized());
+    return raw_address_ == other.raw_address_;
+  }
+
+  bool operator!=(const UniqueValueId& other) const {
+    ASSERT(IsInitialized() && other.IsInitialized());
+    return raw_address_ != other.raw_address_;
+  }
+
+  intptr_t Hashcode() const {
+    ASSERT(IsInitialized());
+    return reinterpret_cast<intptr_t>(raw_address_);
+  }
+
+ private:
+  Address raw_address_;
+};
+
+
 class HType {
  public:
   HType() : type_(kUninitialized) { }
@@ -1057,6 +1091,9 @@ class HValue: public ZoneObject {
   bool Equals(HValue* other);
   virtual intptr_t Hashcode();
 
+  // Compute unique ids upfront that is safe wrt GC and parallel recompilation.
+  virtual void FinalizeUniqueValueId() { }
+
   // Printing support.
   virtual void PrintTo(StringStream* stream) = 0;
   void PrintNameTo(StringStream* stream);
@@ -2643,7 +2680,8 @@ class HLoadExternalArrayPointer: public HUnaryOperation {
 class HCheckMaps: public HTemplateInstruction<2> {
  public:
   HCheckMaps(HValue* value, Handle<Map> map, Zone* zone,
-             HValue* typecheck = NULL) {
+             HValue* typecheck = NULL)
+      : map_unique_ids_(0, zone) {
     SetOperandAt(0, value);
     // If callers don't depend on a typecheck, they can pass in NULL. In that
     // case we use a copy of the |value| argument as a dummy value.
@@ -2655,7 +2693,8 @@ class HCheckMaps: public HTemplateInstruction<2> {
     SetGVNFlag(kDependsOnElementsKind);
     map_set()->Add(map, zone);
   }
-  HCheckMaps(HValue* value, SmallMapList* maps, Zone* zone) {
+  HCheckMaps(HValue* value, SmallMapList* maps, Zone* zone)
+      : map_unique_ids_(0, zone) {
     SetOperandAt(0, value);
     SetOperandAt(1, value);
     set_representation(Representation::Tagged());
@@ -2702,28 +2741,36 @@ class HCheckMaps: public HTemplateInstruction<2> {
   HValue* value() { return OperandAt(0); }
   SmallMapList* map_set() { return &map_set_; }
 
+  virtual void FinalizeUniqueValueId();
+
   DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
 
  protected:
   virtual bool DataEquals(HValue* other) {
+    ASSERT_EQ(map_set_.length(), map_unique_ids_.length());
     HCheckMaps* b = HCheckMaps::cast(other);
     // Relies on the fact that map_set has been sorted before.
-    if (map_set()->length() != b->map_set()->length()) return false;
-    for (int i = 0; i < map_set()->length(); i++) {
-      if (!map_set()->at(i).is_identical_to(b->map_set()->at(i))) return false;
+    if (map_unique_ids_.length() != b->map_unique_ids_.length()) {
+      return false;
+    }
+    for (int i = 0; i < map_unique_ids_.length(); i++) {
+      if (map_unique_ids_.at(i) != b->map_unique_ids_.at(i)) {
+        return false;
+      }
     }
     return true;
   }
 
  private:
   SmallMapList map_set_;
+  ZoneList<UniqueValueId> map_unique_ids_;
 };
 
 
 class HCheckFunction: public HUnaryOperation {
  public:
   HCheckFunction(HValue* value, Handle<JSFunction> function)
-      : HUnaryOperation(value), target_(function) {
+      : HUnaryOperation(value), target_(function), target_unique_id_() {
     set_representation(Representation::Tagged());
     SetFlag(kUseGVN);
     target_in_new_space_ = Isolate::Current()->heap()->InNewSpace(*function);
@@ -2739,6 +2786,10 @@ class HCheckFunction: public HUnaryOperation {
   virtual void Verify();
 #endif
 
+  virtual void FinalizeUniqueValueId() {
+    target_unique_id_ = UniqueValueId(target_);
+  }
+
   Handle<JSFunction> target() const { return target_; }
   bool target_in_new_space() const { return target_in_new_space_; }
 
@@ -2747,11 +2798,12 @@ class HCheckFunction: public HUnaryOperation {
  protected:
   virtual bool DataEquals(HValue* other) {
     HCheckFunction* b = HCheckFunction::cast(other);
-    return target_.is_identical_to(b->target());
+    return target_unique_id_ == b->target_unique_id_;
   }
 
  private:
   Handle<JSFunction> target_;
+  UniqueValueId target_unique_id_;
   bool target_in_new_space_;
 };
 
@@ -2856,7 +2908,11 @@ class HCheckPrototypeMaps: public HTemplateInstruction<0> {
  public:
   HCheckPrototypeMaps(Handle<JSObject> prototype,
                       Handle<JSObject> holder,
-                      Zone* zone) : prototypes_(2, zone), maps_(2, zone) {
+                      Zone* zone)
+      : prototypes_(2, zone),
+        maps_(2, zone),
+        first_prototype_unique_id_(),
+        last_prototype_unique_id_() {
     SetFlag(kUseGVN);
     SetGVNFlag(kDependsOnMaps);
     // Keep a list of all objects on the prototype chain up to the holder
@@ -2882,18 +2938,13 @@ class HCheckPrototypeMaps: public HTemplateInstruction<0> {
   virtual void PrintDataTo(StringStream* stream);
 
   virtual intptr_t Hashcode() {
-    ASSERT_ALLOCATION_DISABLED;
-    // Dereferencing to use the object's raw address for hashing is safe.
-    HandleDereferenceGuard allow_handle_deref(isolate(),
-                                              HandleDereferenceGuard::ALLOW);
-    SLOW_ASSERT(Heap::RelocationLock::IsLocked(isolate()->heap()) ||
-                !isolate()->optimizing_compiler_thread()->IsOptimizerThread());
-    intptr_t hash = 0;
-    for (int i = 0; i < prototypes_.length(); i++) {
-      hash = 17 * hash + reinterpret_cast<intptr_t>(*prototypes_[i]);
-      hash = 17 * hash + reinterpret_cast<intptr_t>(*maps_[i]);
-    }
-    return hash;
+    return first_prototype_unique_id_.Hashcode() * 17 +
+           last_prototype_unique_id_.Hashcode();
+  }
+
+  virtual void FinalizeUniqueValueId() {
+    first_prototype_unique_id_ = UniqueValueId(prototypes_.first());
+    last_prototype_unique_id_ = UniqueValueId(prototypes_.last());
   }
 
   bool CanOmitPrototypeChecks() {
@@ -2906,22 +2957,15 @@ class HCheckPrototypeMaps: public HTemplateInstruction<0> {
  protected:
   virtual bool DataEquals(HValue* other) {
     HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
-#ifdef DEBUG
-    if (prototypes_.length() != b->prototypes()->length()) return false;
-    for (int i = 0; i < prototypes_.length(); i++) {
-      if (!prototypes_[i].is_identical_to(b->prototypes()->at(i))) return false;
-      if (!maps_[i].is_identical_to(b->maps()->at(i))) return false;
-    }
-    return true;
-#else
-    return prototypes_.first().is_identical_to(b->prototypes()->first()) &&
-           prototypes_.last().is_identical_to(b->prototypes()->last());
-#endif  // DEBUG
+    return first_prototype_unique_id_ == b->first_prototype_unique_id_ &&
+           last_prototype_unique_id_ == b->last_prototype_unique_id_;
   }
 
  private:
   ZoneList<Handle<JSObject> > prototypes_;
   ZoneList<Handle<Map> > maps_;
+  UniqueValueId first_prototype_unique_id_;
+  UniqueValueId last_prototype_unique_id_;
 };
 
 
@@ -3176,6 +3220,7 @@ class HConstant: public HTemplateInstruction<0> {
             Representation r,
             Handle<Object> optional_handle = Handle<Object>::null());
   HConstant(Handle<Object> handle,
+            UniqueValueId unique_id,
             Representation r,
             HType type,
             bool is_internalized_string,
@@ -3189,8 +3234,6 @@ class HConstant: public HTemplateInstruction<0> {
     return handle_;
   }
 
-  bool InOldSpace() const { return !HEAP->InNewSpace(*handle_); }
-
   bool IsSpecialDouble() const {
     return has_double_value_ &&
         (BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) ||
@@ -3210,20 +3253,17 @@ class HConstant: public HTemplateInstruction<0> {
     }
 
     ASSERT(!handle_.is_null());
+    HandleDereferenceGuard allow_dereference_for_immovable_check(
+        isolate(), HandleDereferenceGuard::ALLOW);
     Heap* heap = isolate()->heap();
-    // We should have handled minus_zero_value and nan_value in the
-    // has_double_value_ clause above.
-    // Dereferencing is safe to compare against immovable singletons.
-    HandleDereferenceGuard allow_handle_deref(isolate(),
-                                              HandleDereferenceGuard::ALLOW);
-    ASSERT(*handle_ != heap->minus_zero_value());
-    ASSERT(*handle_ != heap->nan_value());
-    return *handle_ == heap->undefined_value() ||
-           *handle_ == heap->null_value() ||
-           *handle_ == heap->true_value() ||
-           *handle_ == heap->false_value() ||
-           *handle_ == heap->the_hole_value() ||
-           *handle_ == heap->empty_string();
+    ASSERT(unique_id_ != UniqueValueId(heap->minus_zero_value()));
+    ASSERT(unique_id_ != UniqueValueId(heap->nan_value()));
+    return unique_id_ == UniqueValueId(heap->undefined_value()) ||
+           unique_id_ == UniqueValueId(heap->null_value()) ||
+           unique_id_ == UniqueValueId(heap->true_value()) ||
+           unique_id_ == UniqueValueId(heap->false_value()) ||
+           unique_id_ == UniqueValueId(heap->the_hole_value()) ||
+           unique_id_ == UniqueValueId(heap->empty_string());
   }
 
   virtual Representation RequiredInputRepresentation(int index) {
@@ -3293,24 +3333,21 @@ class HConstant: public HTemplateInstruction<0> {
   }
 
   virtual intptr_t Hashcode() {
-    ASSERT_ALLOCATION_DISABLED;
-    intptr_t hash;
-
     if (has_int32_value_) {
-      hash = static_cast<intptr_t>(int32_value_);
+      return static_cast<intptr_t>(int32_value_);
     } else if (has_double_value_) {
-      hash = static_cast<intptr_t>(BitCast<int64_t>(double_value_));
+      return static_cast<intptr_t>(BitCast<int64_t>(double_value_));
     } else {
       ASSERT(!handle_.is_null());
-      // Dereferencing to use the object's raw address for hashing is safe.
-      HandleDereferenceGuard allow_handle_deref(isolate(),
-                                                HandleDereferenceGuard::ALLOW);
-      SLOW_ASSERT(Heap::RelocationLock::IsLocked(isolate()->heap()) ||
-                 !isolate()->optimizing_compiler_thread()->IsOptimizerThread());
-      hash = reinterpret_cast<intptr_t>(*handle_);
+      return unique_id_.Hashcode();
     }
+  }
 
-    return hash;
+  virtual void FinalizeUniqueValueId() {
+    if (!has_double_value_) {
+      ASSERT(!handle_.is_null());
+      unique_id_ = UniqueValueId(handle_);
+    }
   }
 
 #ifdef DEBUG
@@ -3334,7 +3371,7 @@ class HConstant: public HTemplateInstruction<0> {
     } else {
       ASSERT(!handle_.is_null());
       return !other_constant->handle_.is_null() &&
-          handle_.is_identical_to(other_constant->handle_);
+             unique_id_ == other_constant->unique_id_;
     }
   }
 
@@ -3348,6 +3385,7 @@ class HConstant: public HTemplateInstruction<0> {
   // constant is non-numeric, handle_ always points to a valid
   // constant HeapObject.
   Handle<Object> handle_;
+  UniqueValueId unique_id_;
 
   // We store the HConstant in the most specific form safely possible.
   // The two flags, has_int32_value_ and has_double_value_ tell us if
@@ -4759,7 +4797,7 @@ class HUnknownOSRValue: public HTemplateInstruction<0> {
 class HLoadGlobalCell: public HTemplateInstruction<0> {
  public:
   HLoadGlobalCell(Handle<JSGlobalPropertyCell> cell, PropertyDetails details)
-      : cell_(cell), details_(details) {
+      : cell_(cell), details_(details), unique_id_() {
     set_representation(Representation::Tagged());
     SetFlag(kUseGVN);
     SetGVNFlag(kDependsOnGlobalVars);
@@ -4771,13 +4809,11 @@ class HLoadGlobalCell: public HTemplateInstruction<0> {
   virtual void PrintDataTo(StringStream* stream);
 
   virtual intptr_t Hashcode() {
-    ASSERT_ALLOCATION_DISABLED;
-    // Dereferencing to use the object's raw address for hashing is safe.
-    HandleDereferenceGuard allow_handle_deref(isolate(),
-                                              HandleDereferenceGuard::ALLOW);
-    SLOW_ASSERT(Heap::RelocationLock::IsLocked(isolate()->heap()) ||
-               !isolate()->optimizing_compiler_thread()->IsOptimizerThread());
-    return reinterpret_cast<intptr_t>(*cell_);
+    return unique_id_.Hashcode();
+  }
+
+  virtual void FinalizeUniqueValueId() {
+    unique_id_ = UniqueValueId(cell_);
   }
 
   virtual Representation RequiredInputRepresentation(int index) {
@@ -4789,7 +4825,7 @@ class HLoadGlobalCell: public HTemplateInstruction<0> {
  protected:
   virtual bool DataEquals(HValue* other) {
     HLoadGlobalCell* b = HLoadGlobalCell::cast(other);
-    return cell_.is_identical_to(b->cell());
+    return unique_id_ == b->unique_id_;
   }
 
  private:
@@ -4797,6 +4833,7 @@ class HLoadGlobalCell: public HTemplateInstruction<0> {
 
   Handle<JSGlobalPropertyCell> cell_;
   PropertyDetails details_;
+  UniqueValueId unique_id_;
 };
 
 
@@ -5255,12 +5292,16 @@ class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
 
   static const int kMaxLoadPolymorphism = 4;
 
+  virtual void FinalizeUniqueValueId();
+
  protected:
   virtual bool DataEquals(HValue* value);
 
  private:
   SmallMapList types_;
   Handle<String> name_;
+  ZoneList<UniqueValueId> types_unique_ids_;
+  UniqueValueId name_unique_id_;
   bool need_generic_;
 };
 
@@ -5524,6 +5565,7 @@ class HStoreNamedField: public HTemplateInstruction<2> {
       : name_(name),
         is_in_object_(in_object),
         offset_(offset),
+        transition_unique_id_(),
         new_space_dominator_(NULL) {
     SetOperandAt(0, obj);
     SetOperandAt(1, val);
@@ -5554,6 +5596,7 @@ class HStoreNamedField: public HTemplateInstruction<2> {
   bool is_in_object() const { return is_in_object_; }
   int offset() const { return offset_; }
   Handle<Map> transition() const { return transition_; }
+  UniqueValueId transition_unique_id() const { return transition_unique_id_; }
   void set_transition(Handle<Map> map) { transition_ = map; }
   HValue* new_space_dominator() const { return new_space_dominator_; }
 
@@ -5566,11 +5609,16 @@ class HStoreNamedField: public HTemplateInstruction<2> {
     return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
   }
 
+  virtual void FinalizeUniqueValueId() {
+    transition_unique_id_ = UniqueValueId(transition_);
+  }
+
  private:
   Handle<String> name_;
   bool is_in_object_;
   int offset_;
   Handle<Map> transition_;
+  UniqueValueId transition_unique_id_;
   HValue* new_space_dominator_;
 };
 
@@ -5771,6 +5819,8 @@ class HTransitionElementsKind: public HTemplateInstruction<2> {
                           Handle<Map> transitioned_map)
       : original_map_(original_map),
         transitioned_map_(transitioned_map),
+        original_map_unique_id_(),
+        transitioned_map_unique_id_(),
         from_kind_(original_map->elements_kind()),
         to_kind_(transitioned_map->elements_kind()) {
     SetOperandAt(0, object);
@@ -5801,18 +5851,25 @@ class HTransitionElementsKind: public HTemplateInstruction<2> {
 
   virtual void PrintDataTo(StringStream* stream);
 
+  virtual void FinalizeUniqueValueId() {
+    original_map_unique_id_ = UniqueValueId(original_map_);
+    transitioned_map_unique_id_ = UniqueValueId(transitioned_map_);
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
 
  protected:
   virtual bool DataEquals(HValue* other) {
     HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
-    return original_map_.is_identical_to(instr->original_map()) &&
-        transitioned_map_.is_identical_to(instr->transitioned_map());
+    return original_map_unique_id_ == instr->original_map_unique_id_ &&
+           transitioned_map_unique_id_ == instr->transitioned_map_unique_id_;
   }
 
  private:
   Handle<Map> original_map_;
   Handle<Map> transitioned_map_;
+  UniqueValueId original_map_unique_id_;
+  UniqueValueId transitioned_map_unique_id_;
   ElementsKind from_kind_;
   ElementsKind to_kind_;
 };
index 9bfc110..ee6e346 100644 (file)
@@ -517,7 +517,6 @@ class ReachabilityAnalyzer BASE_EMBEDDED {
 
 void HGraph::Verify(bool do_full_verify) const {
   // Allow dereferencing for debug mode verification.
-  Heap::RelocationLock(isolate()->heap());
   HandleDereferenceGuard allow_handle_deref(isolate(),
                                             HandleDereferenceGuard::ALLOW);
   for (int i = 0; i < blocks_.length(); i++) {
@@ -619,6 +618,7 @@ HConstant* HGraph::GetConstant##Name() {                                       \
   if (!constant_##name##_.is_set()) {                                          \
     HConstant* constant = new(zone()) HConstant(                               \
         isolate()->factory()->name##_value(),                                  \
+        UniqueValueId(isolate()->heap()->name##_value()),                      \
         Representation::Tagged(),                                              \
         htype,                                                                 \
         false,                                                                 \
@@ -880,6 +880,7 @@ HGraph* HGraphBuilder::CreateGraph() {
   HPhase phase("H_Block building", isolate());
   set_current_block(graph()->entry_block());
   if (!BuildGraph()) return NULL;
+  graph()->FinalizeUniqueValueIds();
   return graph_;
 }
 
@@ -1696,6 +1697,19 @@ HBasicBlock* HGraph::CreateBasicBlock() {
 }
 
 
+void HGraph::FinalizeUniqueValueIds() {
+  AssertNoAllocation no_gc;
+  ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread());
+  for (int i = 0; i < blocks()->length(); ++i) {
+    for (HInstruction* instr = blocks()->at(i)->first();
+        instr != NULL;
+        instr = instr->next()) {
+      instr->FinalizeUniqueValueId();
+    }
+  }
+}
+
+
 void HGraph::Canonicalize() {
   if (!FLAG_use_canonicalizing) return;
   HPhase phase("H_Canonicalize", this);
@@ -4327,8 +4341,6 @@ bool HOptimizedGraphBuilder::BuildGraph() {
 void HGraph::GlobalValueNumbering() {
   // Perform common subexpression elimination and loop-invariant code motion.
   if (FLAG_use_gvn) {
-    // We use objects' raw addresses for identification, so they must not move.
-    Heap::RelocationLock relocation_lock(isolate()->heap());
     HPhase phase("H_Global value numbering", this);
     HGlobalValueNumberer gvn(this, info());
     bool removed_side_effects = gvn.Analyze();
index 0d5f5c9..3dbca3c 100644 (file)
@@ -260,6 +260,7 @@ class HGraph: public ZoneObject {
   HBasicBlock* entry_block() const { return entry_block_; }
   HEnvironment* start_environment() const { return start_environment_; }
 
+  void FinalizeUniqueValueIds();
   void InitializeInferredTypes();
   void InsertTypeConversions();
   void MergeRemovableSimulates();
index 63263ba..f49179f 100644 (file)
@@ -3125,8 +3125,6 @@ void MarkCompactCollector::ProcessInvalidatedCode(ObjectVisitor* visitor) {
 
 
 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
-  Heap::RelocationLock relocation_lock(heap());
-
   bool code_slots_filtering_required;
   { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE);
     code_slots_filtering_required = MarkInvalidatedCode();