Chromium Code Reviews| Index: src/hydrogen-instructions.h |
| diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h |
| index 7acec8bcd5ebc3e2e0757d312ee591f5e5174e72..b4a4a932292be74ce8ae46176aec4fd356ef2373 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 FinalizeHashcode() { } |
| + |
| // Printing support. |
| virtual void PrintTo(StringStream* stream) = 0; |
| void PrintNameTo(StringStream* stream); |
| @@ -2856,7 +2852,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_(NULL), |
| + last_prototype_(NULL) { |
| SetFlag(kUseGVN); |
| SetGVNFlag(kDependsOnMaps); |
| // Keep a list of all objects on the prototype chain up to the holder |
| @@ -2882,18 +2882,18 @@ 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, first_prototype_); |
| + return reinterpret_cast<intptr_t>(first_prototype_) * 17 + |
| + reinterpret_cast<intptr_t>(last_prototype_); |
| + } |
| + |
| + virtual void FinalizeHashcode() { |
| + ASSERT(first_prototype_ == 0 || |
| + first_prototype_ == reinterpret_cast<Address>(*prototypes_.first())); |
| + first_prototype_ = reinterpret_cast<Address>(*prototypes_.first()); |
| + ASSERT(last_prototype_ == 0 || |
| + last_prototype_ == reinterpret_cast<Address>(*prototypes_.last())); |
| + last_prototype_ = reinterpret_cast<Address>(*prototypes_.last()); |
| } |
| bool CanOmitPrototypeChecks() { |
| @@ -2906,22 +2906,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(0, first_prototype_); |
| + return first_prototype_ == b->first_prototype_ && |
| + last_prototype_ == b->last_prototype_; |
| } |
| private: |
| ZoneList<Handle<JSObject> > prototypes_; |
| ZoneList<Handle<Map> > maps_; |
| + Address first_prototype_; |
| + Address last_prototype_; |
| }; |
| @@ -3176,6 +3170,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 +3184,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) || |
| @@ -3211,19 +3204,16 @@ class HConstant: public HTemplateInstruction<0> { |
| ASSERT(!handle_.is_null()); |
| 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(); |
| + // The raw address is sufficient to compare against root list entries. |
| + Object* obj = reinterpret_cast<Object*>(raw_address_); |
| + 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 +3283,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 FinalizeHashcode() { |
| + if (!has_double_value_) { |
|
Sven Panne
2013/04/12 11:30:53
What about has_int32_value_?
Yang
2013/04/15 13:55:31
Done.
|
| + ASSERT(!handle_.is_null()); |
| + // Hash code has not been set, or already set to the same value. |
| + ASSERT(raw_address_ == NULL || |
| + raw_address_ == reinterpret_cast<Address>(*handle_)); |
| + raw_address_ = reinterpret_cast<Address>(*handle_); |
| + } |
| } |
| #ifdef DEBUG |
| @@ -3333,8 +3324,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 +3350,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. |
|
Sven Panne
2013/04/12 11:30:53
This is a bit obscure. Wouldn't it be better if we
Yang
2013/04/15 13:55:31
Skipping this comment as discussed offline.
|
| + union { |
| + int32_t int32_value_; |
| + Address raw_address_; |
| + }; |
| double double_value_; |
| HType type_from_value_; |
| }; |
| @@ -4759,7 +4756,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), hash_code_(0) { |
| set_representation(Representation::Tagged()); |
| SetFlag(kUseGVN); |
| SetGVNFlag(kDependsOnGlobalVars); |
| @@ -4771,13 +4768,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, hash_code_); |
| + return hash_code_; |
| + } |
| + |
| + virtual void FinalizeHashcode() { |
| + // Hash code has not been set, or already set to the same value. |
| + ASSERT(hash_code_ == 0 || |
| + hash_code_ == reinterpret_cast<intptr_t>(*cell_)); |
| + hash_code_ = reinterpret_cast<intptr_t>(*cell_); |
| } |
| virtual Representation RequiredInputRepresentation(int index) { |
| @@ -4789,7 +4788,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, hash_code_); |
| + return hash_code_ == b->hash_code_; |
| } |
| private: |
| @@ -4797,6 +4797,7 @@ class HLoadGlobalCell: public HTemplateInstruction<0> { |
| Handle<JSGlobalPropertyCell> cell_; |
| PropertyDetails details_; |
| + intptr_t hash_code_; |
|
Sven Panne
2013/04/12 11:30:53
Renaming this to something like 'unique_id_' makes
Yang
2013/04/15 13:55:31
Done.
|
| }; |