Index: src/hydrogen-instructions.h |
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h |
index fb6fe29ed6bdbd7a87be40825fa1ee0a4de246ac..875b631595d3893e3e168285c0158e1572c33aac 100644 |
--- a/src/hydrogen-instructions.h |
+++ b/src/hydrogen-instructions.h |
@@ -2453,20 +2453,42 @@ class HArgumentsObject: public HTemplateInstruction<0> { |
class HConstant: public HTemplateInstruction<0> { |
public: |
HConstant(Handle<Object> handle, Representation r); |
+ HConstant(int32_t value, Representation r); |
+ HConstant(double value, Representation r); |
- Handle<Object> handle() const { return handle_; } |
+ Handle<Object> handle() { |
+ if (handle_.is_null()) { |
+ handle_ = FACTORY->NewNumber(double_value_, TENURED); |
+ } |
+ ASSERT(has_int32_value_ || !handle_->IsSmi()); |
+ return handle_; |
+ } |
bool InOldSpace() const { return !HEAP->InNewSpace(*handle_); } |
bool ImmortalImmovable() const { |
+ if (has_int32_value_) { |
+ return false; |
+ } |
+ if (has_double_value_) { |
+ if (BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) || |
+ isnan(double_value_)) { |
+ return true; |
+ } |
+ return false; |
+ } |
+ |
+ ASSERT(!handle_.is_null()); |
Heap* heap = HEAP; |
+ // We should have handled minus_zero_value and nan_value in the |
+ // has_double_value_ clause above. |
+ ASSERT(*handle_ != heap->minus_zero_value()); |
+ ASSERT(*handle_ != heap->nan_value()); |
if (*handle_ == heap->undefined_value()) return true; |
if (*handle_ == heap->null_value()) return true; |
if (*handle_ == heap->true_value()) return true; |
if (*handle_ == heap->false_value()) return true; |
if (*handle_ == heap->the_hole_value()) return true; |
- if (*handle_ == heap->minus_zero_value()) return true; |
- if (*handle_ == heap->nan_value()) return true; |
if (*handle_ == heap->empty_string()) return true; |
return false; |
} |
@@ -2476,18 +2498,14 @@ class HConstant: public HTemplateInstruction<0> { |
} |
virtual bool IsConvertibleToInteger() const { |
- if (handle_->IsSmi()) return true; |
- if (handle_->IsHeapNumber() && |
- (HeapNumber::cast(*handle_)->value() == |
- static_cast<double>(NumberToInt32(*handle_)))) return true; |
- return false; |
+ return has_int32_value_; |
} |
virtual bool EmitAtUses() { return !representation().IsDouble(); } |
virtual HValue* Canonicalize(); |
virtual void PrintDataTo(StringStream* stream); |
virtual HType CalculateInferredType(); |
- bool IsInteger() const { return handle_->IsSmi(); } |
+ bool IsInteger() { return handle()->IsSmi(); } |
HConstant* CopyToRepresentation(Representation r, Zone* zone) const; |
HConstant* CopyToTruncatedInt32(Zone* zone) const; |
bool HasInteger32Value() const { return has_int32_value_; } |
@@ -2500,24 +2518,31 @@ class HConstant: public HTemplateInstruction<0> { |
ASSERT(HasDoubleValue()); |
return double_value_; |
} |
- bool HasNumberValue() const { return has_int32_value_ || has_double_value_; } |
+ bool HasNumberValue() const { return has_double_value_; } |
int32_t NumberValueAsInteger32() const { |
ASSERT(HasNumberValue()); |
- if (has_int32_value_) return int32_value_; |
- return DoubleToInt32(double_value_); |
+ // Irrespective of whether a numeric HConstant can be safely |
+ // represented as an int32, we store the (in some cases lossy) |
+ // representation of the number in int32_value_. |
+ return int32_value_; |
} |
- bool HasStringValue() const { return handle_->IsString(); } |
- bool ToBoolean() const; |
+ bool ToBoolean(); |
virtual intptr_t Hashcode() { |
ASSERT(!HEAP->allow_allocation(false)); |
- intptr_t hash = reinterpret_cast<intptr_t>(*handle()); |
- // Prevent smis from having fewer hash values when truncated to |
- // the least significant bits. |
- const int kShiftSize = kSmiShiftSize + kSmiTagSize; |
- STATIC_ASSERT(kShiftSize != 0); |
- return hash ^ (hash >> kShiftSize); |
+ intptr_t hash; |
+ |
+ if (has_int32_value_) { |
+ hash = static_cast<intptr_t>(int32_value_); |
+ } else if (has_double_value_) { |
+ hash = static_cast<intptr_t>(BitCast<int64_t>(double_value_)); |
+ } else { |
+ ASSERT(!handle_.is_null()); |
+ hash = reinterpret_cast<intptr_t>(*handle_); |
+ } |
+ |
+ return hash; |
} |
#ifdef DEBUG |
@@ -2531,15 +2556,32 @@ class HConstant: public HTemplateInstruction<0> { |
virtual bool DataEquals(HValue* other) { |
HConstant* other_constant = HConstant::cast(other); |
- return handle().is_identical_to(other_constant->handle()); |
+ if (has_int32_value_) { |
+ return other_constant->has_int32_value_ && |
+ int32_value_ == other_constant->int32_value_; |
+ } else if (has_double_value_) { |
+ return other_constant->has_double_value_ && |
+ BitCast<int64_t>(double_value_) == |
+ BitCast<int64_t>(other_constant->double_value_); |
+ } else { |
+ ASSERT(!handle_.is_null()); |
+ return !other_constant->handle_.is_null() && |
+ *handle_ == *other_constant->handle_; |
+ } |
} |
private: |
+ // If this is a numerical constant, handle_ either points to to the |
+ // HeapObject the constant originated from or is null. If the |
+ // constant is non-numeric, handle_ always points to a valid |
+ // constant HeapObject. |
Handle<Object> handle_; |
- // The following two values represent the int32 and the double value of the |
- // given constant if there is a lossless conversion between the constant |
- // and the specific representation. |
+ // We store the HConstant in the most specific form safely possible. |
+ // The two flags, has_int32_value_ and has_double_value_ tell us if |
+ // int32_value_ and double_value_ hold valid, safe representations |
+ // of the constant. has_int32_value_ implies has_double_value_ but |
+ // not the converse. |
bool has_int32_value_ : 1; |
bool has_double_value_ : 1; |
int32_t int32_value_; |