| Index: src/hydrogen-instructions.h | 
| diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h | 
| index 7acec8bcd5ebc3e2e0757d312ee591f5e5174e72..befc228d919dafa1303c7dd1b54b5f4ab9e3b3cb 100644 | 
| --- a/src/hydrogen-instructions.h | 
| +++ b/src/hydrogen-instructions.h | 
| @@ -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() | 
| @@ -1057,6 +1049,10 @@ class HValue: public ZoneObject { | 
| bool Equals(HValue* other); | 
| virtual intptr_t Hashcode(); | 
|  | 
| +  // Some instructions' hash code is dependent on object addresses and are not | 
| +  // safe regarding GC and parallel recompilation.  Compute the hash upfront. | 
| +  virtual void FinalizeUniqueId() { } | 
| + | 
| // Printing support. | 
| virtual void PrintTo(StringStream* stream) = 0; | 
| void PrintNameTo(StringStream* stream); | 
| @@ -2643,7 +2639,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_raw_addresses_(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 +2652,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_raw_addresses_(0, zone) { | 
| SetOperandAt(0, value); | 
| SetOperandAt(1, value); | 
| set_representation(Representation::Tagged()); | 
| @@ -2702,28 +2700,36 @@ class HCheckMaps: public HTemplateInstruction<2> { | 
| HValue* value() { return OperandAt(0); } | 
| SmallMapList* map_set() { return &map_set_; } | 
|  | 
| +  virtual void FinalizeUniqueId(); | 
| + | 
| DECLARE_CONCRETE_INSTRUCTION(CheckMaps) | 
|  | 
| protected: | 
| virtual bool DataEquals(HValue* other) { | 
| +    ASSERT_EQ(map_set_.length(), map_raw_addresses_.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_raw_addresses_.length() != b->map_raw_addresses_.length()) { | 
| +      return false; | 
| +    } | 
| +    for (int i = 0; i < map_raw_addresses_.length(); i++) { | 
| +      if (map_raw_addresses_.at(i) != b->map_raw_addresses_.at(i)) { | 
| +        return false; | 
| +      } | 
| } | 
| return true; | 
| } | 
|  | 
| private: | 
| SmallMapList map_set_; | 
| +  ZoneList<Address> map_raw_addresses_; | 
| }; | 
|  | 
|  | 
| class HCheckFunction: public HUnaryOperation { | 
| public: | 
| HCheckFunction(HValue* value, Handle<JSFunction> function) | 
| -      : HUnaryOperation(value), target_(function) { | 
| +      : HUnaryOperation(value), target_(function), raw_address_(NULL) { | 
| set_representation(Representation::Tagged()); | 
| SetFlag(kUseGVN); | 
| target_in_new_space_ = Isolate::Current()->heap()->InNewSpace(*function); | 
| @@ -2739,6 +2745,13 @@ class HCheckFunction: public HUnaryOperation { | 
| virtual void Verify(); | 
| #endif | 
|  | 
| +  virtual void FinalizeUniqueId() { | 
| +    // Raw address may have already been collected. | 
| +    ASSERT(raw_address_ == NULL || | 
| +           raw_address_ == reinterpret_cast<Address>(*target_)); | 
| +    raw_address_ = reinterpret_cast<Address>(*target_); | 
| +  } | 
| + | 
| Handle<JSFunction> target() const { return target_; } | 
| bool target_in_new_space() const { return target_in_new_space_; } | 
|  | 
| @@ -2747,11 +2760,13 @@ class HCheckFunction: public HUnaryOperation { | 
| protected: | 
| virtual bool DataEquals(HValue* other) { | 
| HCheckFunction* b = HCheckFunction::cast(other); | 
| -    return target_.is_identical_to(b->target()); | 
| +    ASSERT_NE(NULL, raw_address_); | 
| +    return raw_address_ == b->raw_address_; | 
| } | 
|  | 
| private: | 
| Handle<JSFunction> target_; | 
| +  Address raw_address_; | 
| bool target_in_new_space_; | 
| }; | 
|  | 
| @@ -2856,7 +2871,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_raw_address_(NULL), | 
| +        last_prototype_raw_address_(NULL) { | 
| SetFlag(kUseGVN); | 
| SetGVNFlag(kDependsOnMaps); | 
| // Keep a list of all objects on the prototype chain up to the holder | 
| @@ -2882,18 +2901,23 @@ 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; | 
| +    ASSERT_NE(NULL, last_prototype_raw_address_); | 
| +    return reinterpret_cast<intptr_t>(first_prototype_raw_address_) * 17 + | 
| +        reinterpret_cast<intptr_t>(last_prototype_raw_address_); | 
| +  } | 
| + | 
| +  virtual void FinalizeUniqueId() { | 
| +    // Raw addresses may have already been collected. | 
| +    ASSERT(first_prototype_raw_address_ == 0 || | 
| +           first_prototype_raw_address_ == | 
| +               reinterpret_cast<Address>(*prototypes_.first())); | 
| +    first_prototype_raw_address_ = | 
| +        reinterpret_cast<Address>(*prototypes_.first()); | 
| +    ASSERT(last_prototype_raw_address_ == 0 || | 
| +           last_prototype_raw_address_ == | 
| +               reinterpret_cast<Address>(*prototypes_.last())); | 
| +    last_prototype_raw_address_ = | 
| +        reinterpret_cast<Address>(*prototypes_.last()); | 
| } | 
|  | 
| bool CanOmitPrototypeChecks() { | 
| @@ -2906,22 +2930,16 @@ 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 | 
| +    ASSERT_NE(NULL, first_prototype_raw_address_); | 
| +    return first_prototype_raw_address_ == b->first_prototype_raw_address_ && | 
| +           last_prototype_raw_address_ == b->last_prototype_raw_address_; | 
| } | 
|  | 
| private: | 
| ZoneList<Handle<JSObject> > prototypes_; | 
| ZoneList<Handle<Map> > maps_; | 
| +  Address first_prototype_raw_address_; | 
| +  Address last_prototype_raw_address_; | 
| }; | 
|  | 
|  | 
| @@ -3176,6 +3194,7 @@ class HConstant: public HTemplateInstruction<0> { | 
| Representation r, | 
| Handle<Object> optional_handle = Handle<Object>::null()); | 
| HConstant(Handle<Object> handle, | 
| +            Address raw_address, | 
| Representation r, | 
| HType type, | 
| bool is_internalized_string, | 
| @@ -3189,8 +3208,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 +3227,19 @@ class HConstant: public HTemplateInstruction<0> { | 
| } | 
|  | 
| ASSERT(!handle_.is_null()); | 
| +    HandleDereferenceGuard allow_dereference_for_immovable_check( | 
| +        isolate(), HandleDereferenceGuard::ALLOW); | 
| +    ASSERT_NE(NULL, raw_address_); | 
| +    Object* obj = reinterpret_cast<Object*>(raw_address_); | 
| 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(obj != heap->minus_zero_value()); | 
| +    ASSERT(obj != heap->nan_value()); | 
| +    return obj == heap->undefined_value() || | 
| +           obj == heap->null_value() || | 
| +           obj == heap->true_value() || | 
| +           obj == heap->false_value() || | 
| +           obj == heap->the_hole_value() || | 
| +           obj == heap->empty_string(); | 
| } | 
|  | 
| virtual Representation RequiredInputRepresentation(int index) { | 
| @@ -3293,24 +3309,25 @@ 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_); | 
| +      ASSERT_NE(NULL, raw_address_); | 
| +      return reinterpret_cast<intptr_t>(raw_address_); | 
| } | 
| +  } | 
|  | 
| -    return hash; | 
| +  virtual void FinalizeUniqueId() { | 
| +    if (!has_double_value_) { | 
| +      ASSERT(!handle_.is_null()); | 
| +      // Raw address may have already been collected. | 
| +      ASSERT(raw_address_ == NULL || | 
| +             raw_address_ == reinterpret_cast<Address>(*handle_)); | 
| +      raw_address_ = reinterpret_cast<Address>(*handle_); | 
| +    } | 
| } | 
|  | 
| #ifdef DEBUG | 
| @@ -3333,8 +3350,9 @@ class HConstant: public HTemplateInstruction<0> { | 
| BitCast<int64_t>(other_constant->double_value_); | 
| } else { | 
| ASSERT(!handle_.is_null()); | 
| +      ASSERT_NE(NULL, raw_address_); | 
| return !other_constant->handle_.is_null() && | 
| -          handle_.is_identical_to(other_constant->handle_); | 
| +             raw_address_ == other_constant->raw_address_; | 
| } | 
| } | 
|  | 
| @@ -3358,7 +3376,12 @@ class HConstant: public HTemplateInstruction<0> { | 
| bool has_double_value_ : 1; | 
| bool is_internalized_string_ : 1;  // TODO(yangguo): make this part of HType. | 
| bool boolean_value_ : 1; | 
| -  int32_t int32_value_; | 
| +  // An extra hash code is only necessary if the value is not a number. | 
| +  // So has_double_value_ governs how to interpret the union. | 
| +  union { | 
| +    int32_t int32_value_; | 
| +    Address raw_address_; | 
| +  }; | 
| double double_value_; | 
| HType type_from_value_; | 
| }; | 
| @@ -4759,7 +4782,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_(0) { | 
| set_representation(Representation::Tagged()); | 
| SetFlag(kUseGVN); | 
| SetGVNFlag(kDependsOnGlobalVars); | 
| @@ -4771,13 +4794,15 @@ 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_); | 
| +    ASSERT_NE(0, unique_id_); | 
| +    return unique_id_; | 
| +  } | 
| + | 
| +  virtual void FinalizeUniqueId() { | 
| +    // Raw address may have already been collected. | 
| +    ASSERT(unique_id_ == 0 || | 
| +           unique_id_ == reinterpret_cast<intptr_t>(*cell_)); | 
| +    unique_id_ = reinterpret_cast<intptr_t>(*cell_); | 
| } | 
|  | 
| virtual Representation RequiredInputRepresentation(int index) { | 
| @@ -4789,7 +4814,8 @@ class HLoadGlobalCell: public HTemplateInstruction<0> { | 
| protected: | 
| virtual bool DataEquals(HValue* other) { | 
| HLoadGlobalCell* b = HLoadGlobalCell::cast(other); | 
| -    return cell_.is_identical_to(b->cell()); | 
| +    ASSERT_NE(0, unique_id_); | 
| +    return unique_id_ == b->unique_id_; | 
| } | 
|  | 
| private: | 
| @@ -4797,6 +4823,7 @@ class HLoadGlobalCell: public HTemplateInstruction<0> { | 
|  | 
| Handle<JSGlobalPropertyCell> cell_; | 
| PropertyDetails details_; | 
| +  intptr_t unique_id_; | 
| }; | 
|  | 
|  | 
| @@ -5256,12 +5283,16 @@ class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> { | 
|  | 
| static const int kMaxLoadPolymorphism = 4; | 
|  | 
| +  virtual void FinalizeUniqueId(); | 
| + | 
| protected: | 
| virtual bool DataEquals(HValue* value); | 
|  | 
| private: | 
| SmallMapList types_; | 
| Handle<String> name_; | 
| +  ZoneList<Address> types_raw_address_; | 
| +  Address name_raw_address_; | 
| bool need_generic_; | 
| }; | 
|  | 
| @@ -5525,6 +5556,7 @@ class HStoreNamedField: public HTemplateInstruction<2> { | 
| : name_(name), | 
| is_in_object_(in_object), | 
| offset_(offset), | 
| +        transition_raw_address_(NULL), | 
| new_space_dominator_(NULL) { | 
| SetOperandAt(0, obj); | 
| SetOperandAt(1, val); | 
| @@ -5555,6 +5587,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_; } | 
| +  Address transition_raw_address() const { return transition_raw_address_; } | 
| void set_transition(Handle<Map> map) { transition_ = map; } | 
| HValue* new_space_dominator() const { return new_space_dominator_; } | 
|  | 
| @@ -5567,11 +5600,20 @@ class HStoreNamedField: public HTemplateInstruction<2> { | 
| return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); | 
| } | 
|  | 
| +  virtual void FinalizeUniqueId() { | 
| +    if (transition_.is_null()) return; | 
| +    // Raw address may have already been collected. | 
| +    ASSERT(transition_raw_address_ == NULL || | 
| +           transition_raw_address_ == reinterpret_cast<Address>(*transition_)); | 
| +    transition_raw_address_ = reinterpret_cast<Address>(*transition_); | 
| +  } | 
| + | 
| private: | 
| Handle<String> name_; | 
| bool is_in_object_; | 
| int offset_; | 
| Handle<Map> transition_; | 
| +  Address transition_raw_address_; | 
| HValue* new_space_dominator_; | 
| }; | 
|  | 
| @@ -5772,6 +5814,8 @@ class HTransitionElementsKind: public HTemplateInstruction<2> { | 
| Handle<Map> transitioned_map) | 
| : original_map_(original_map), | 
| transitioned_map_(transitioned_map), | 
| +        original_map_raw_address_(NULL), | 
| +        transitioned_map_raw_address_(NULL), | 
| from_kind_(original_map->elements_kind()), | 
| to_kind_(transitioned_map->elements_kind()) { | 
| SetOperandAt(0, object); | 
| @@ -5802,18 +5846,35 @@ class HTransitionElementsKind: public HTemplateInstruction<2> { | 
|  | 
| virtual void PrintDataTo(StringStream* stream); | 
|  | 
| +  virtual void FinalizeUniqueId() { | 
| +    // Raw addresses may have already been collected. | 
| +    ASSERT(original_map_raw_address_ == NULL || | 
| +           original_map_raw_address_ == | 
| +               reinterpret_cast<Address>(*original_map_)); | 
| +    ASSERT(transitioned_map_raw_address_ == NULL || | 
| +           transitioned_map_raw_address_ == | 
| +               reinterpret_cast<Address>(*transitioned_map_)); | 
| +    original_map_raw_address_ = reinterpret_cast<Address>(*original_map_); | 
| +    transitioned_map_raw_address_ = | 
| +        reinterpret_cast<Address>(*transitioned_map_); | 
| +  } | 
| + | 
| DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind) | 
|  | 
| protected: | 
| virtual bool DataEquals(HValue* other) { | 
| +    ASSERT_NE(NULL, original_map_raw_address_); | 
| +    ASSERT_NE(NULL, transitioned_map_raw_address_); | 
| 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_raw_address_ == instr->original_map_raw_address_ && | 
| +        transitioned_map_raw_address_ == instr->transitioned_map_raw_address_; | 
| } | 
|  | 
| private: | 
| Handle<Map> original_map_; | 
| Handle<Map> transitioned_map_; | 
| +  Address original_map_raw_address_; | 
| +  Address transitioned_map_raw_address_; | 
| ElementsKind from_kind_; | 
| ElementsKind to_kind_; | 
| }; | 
|  |