Index: src/hydrogen-instructions.h |
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h |
index 7acec8bcd5ebc3e2e0757d312ee591f5e5174e72..555d8d2f103c73da072ca690ddb82cbd35df954a 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) || |
@@ -3210,20 +3203,19 @@ class HConstant: public HTemplateInstruction<0> { |
} |
ASSERT(!handle_.is_null()); |
+ HandleDereferenceGuard allow_dereference_for_immovable_check( |
+ isolate(), HandleDereferenceGuard::ALLOW); |
+ CHECK_NE(NULL, raw_address_); |
Sven Panne
2013/04/12 13:47:02
ASSERT_NE
|
+ 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 +3285,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_) { |
+ 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 +3326,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 +3352,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 +4758,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 +4770,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 FinalizeHashcode() { |
+ // Hash code has not been set, or already set to the same value. |
+ 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 +4790,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 +4799,7 @@ class HLoadGlobalCell: public HTemplateInstruction<0> { |
Handle<JSGlobalPropertyCell> cell_; |
PropertyDetails details_; |
+ intptr_t unique_id_; |
}; |