Index: src/hydrogen-instructions.cc |
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc |
index d44e90ac04101799d3a6aa3b37178b430140f4fe..ff4a55638e90deac64ed1af00b378d967ab9730d 100644 |
--- a/src/hydrogen-instructions.cc |
+++ b/src/hydrogen-instructions.cc |
@@ -999,7 +999,7 @@ HValue* HCheckInstanceType::Canonicalize() { |
} |
if (check_ == IS_SYMBOL && |
value()->IsConstant() && |
- HConstant::cast(value())->handle()->IsSymbol()) { |
+ HConstant::cast(value())->IsSymbol()) { |
return NULL; |
} |
return this; |
@@ -1384,33 +1384,135 @@ HConstant::HConstant(Handle<Object> handle, Representation r) |
: handle_(handle), |
has_int32_value_(false), |
has_double_value_(false), |
- int32_value_(0), |
- double_value_(0) { |
+ handle_was_smi_(handle->IsSmi()), |
+ is_string_(false), |
+ is_symbol_(false), |
+ is_boolean_(false) { |
set_representation(r); |
SetFlag(kUseGVN); |
- if (handle_->IsNumber()) { |
+ |
+ // We try to use the fact that we've already checked if the handle |
+ // is a Smi. |
+ if (handle_was_smi_) { |
+ has_int32_value_ = true; |
+ has_double_value_ = true; |
+ int32_value_ = Smi::cast(*handle)->value(); |
+ double_value_ = FastI2D(int32_value_); |
+ } else if (handle_->IsHeapNumber()) { |
double n = handle_->Number(); |
double roundtrip_value = static_cast<double>(static_cast<int32_t>(n)); |
- has_int32_value_ = BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(n); |
- if (has_int32_value_) int32_value_ = static_cast<int32_t>(n); |
+ has_int32_value_ = BitCast<int64_t>(roundtrip_value) == |
+ BitCast<int64_t>(n); |
+ |
+ int32_value_ = DoubleToInt32(n); |
double_value_ = n; |
has_double_value_ = true; |
+ } else { |
+ is_string_ = handle->IsString(); |
+ is_symbol_ = !is_string_ && handle->IsSymbol(); |
+ is_boolean_ = !is_symbol_ && !is_string_ && handle->IsBoolean(); |
+ } |
+} |
+ |
+ |
+HConstant::HConstant(int32_t integer_value, Representation r, |
+ Handle<Object> handle) |
+ : handle_(handle), |
+ has_int32_value_(true), |
+ has_double_value_(true), |
+ is_string_(false), |
+ is_symbol_(false), |
+ is_boolean_(false) { |
+ set_representation(r); |
+ SetFlag(kUseGVN); |
+ int32_value_ = integer_value; |
+ double_value_ = FastI2D(integer_value); |
+ if (handle.is_null()) { |
+ // If we can safely represent this integer in 31 bits and we don't |
+ // have a Handle to the HeapObject, we pretend it originated from |
+ // a Smi. This is okay because when we _do_ create a HeapObject |
+ // for this HConstant, it will be a Smi. |
+ handle_was_smi_ = Smi::IsValid(static_cast<intptr_t>(integer_value)); |
+ } else { |
+ handle_was_smi_ = handle->IsSmi(); |
+ } |
+} |
+ |
+ |
+HConstant::HConstant(double double_value, Representation r, |
+ Handle<Object> handle) |
+ : handle_(handle), |
+ has_int32_value_(false), |
+ has_double_value_(true), |
+ handle_was_smi_(false), |
+ is_string_(false), |
+ is_symbol_(false), |
+ is_boolean_(false), |
+ int32_value_(DoubleToInt32(double_value)), |
+ double_value_(double_value) { |
+ set_representation(r); |
+ SetFlag(kUseGVN); |
+ double roundtrip_value = static_cast<double>( |
+ static_cast<int32_t>(double_value)); |
+ has_int32_value_ = BitCast<int64_t>(roundtrip_value) == |
+ BitCast<int64_t>(double_value); |
+ if (handle.is_null()) { |
+ handle_was_smi_ = has_int32_value_ && Smi::IsValid(static_cast<intptr_t>( |
+ int32_value_)); |
+ } else { |
+ handle_was_smi_ = handle->IsSmi(); |
+ } |
+} |
+ |
+ |
+void HConstant::EnsureHasHandle(Factory* factory) { |
+ if (handle_.is_null()) { |
+ ASSERT(has_int32_value_ || has_double_value_); |
+ if (has_int32_value_) { |
+ handle_ = factory->NewNumberFromInt(int32_value_, TENURED); |
+ ASSERT(handle_->IsSmi() || !handle_was_smi_); |
+ } else { |
+ handle_ = factory->NewNumber(double_value_, TENURED); |
+ } |
} |
} |
HConstant* HConstant::CopyToRepresentation(Representation r, Zone* zone) const { |
- if (r.IsInteger32() && !has_int32_value_) return NULL; |
- if (r.IsDouble() && !has_double_value_) return NULL; |
- return new(zone) HConstant(handle_, r); |
+ if (has_int32_value_) { |
+ return new(zone) HConstant(int32_value_, r, handle_); |
+ } else if (has_double_value_) { |
+ // A double can be safely converted only to a HeapNumber. If it |
+ // was possible to store this double as a integer, we'd have done |
+ // that and has_int32_value_ would be true. |
+ if (r.IsInteger32()) { |
+ return NULL; |
+ } else { |
+ return new(zone) HConstant(double_value_, r, handle_); |
+ } |
+ } else { |
+ // A generic tagged value cannot be safely converted to any other |
+ // representation. |
+ if (r.IsTagged()) { |
+ return new(zone) HConstant(handle_, r); |
+ } else { |
+ return NULL; |
+ } |
+ } |
} |
HConstant* HConstant::CopyToTruncatedInt32(Zone* zone) const { |
- if (!has_double_value_) return NULL; |
- int32_t truncated = NumberToInt32(*handle_); |
- return new(zone) HConstant(FACTORY->NewNumberFromInt(truncated), |
- Representation::Integer32()); |
+ if (has_int32_value_) { |
+ return new(zone) HConstant(int32_value_, Representation::Integer32(), |
+ handle_); |
+ } else if (has_double_value_) { |
+ return new(zone) HConstant(DoubleToInt32(double_value_), |
+ Representation::Integer32(), |
+ Handle<Object>::null()); |
+ } else { |
+ return NULL; |
+ } |
} |
@@ -1432,7 +1534,13 @@ bool HConstant::ToBoolean() const { |
} |
void HConstant::PrintDataTo(StringStream* stream) { |
- handle()->ShortPrint(stream); |
+ if (has_int32_value_) { |
+ stream->Add("%d ", int32_value_); |
+ } else if (has_double_value_) { |
+ stream->Add("%lf ", double_value_); |
+ } else { |
+ handle()->ShortPrint(stream); |
+ } |
} |
@@ -2077,7 +2185,9 @@ HType HPhi::CalculateInferredType() { |
HType HConstant::CalculateInferredType() { |
- return HType::TypeFromValue(handle_); |
+ if (handle_was_smi_) return HType::Smi(); |
+ if (has_int32_value_ || has_double_value_) return HType::HeapNumber(); |
+ return HType::TypeFromValue(Handle<Object>(handle_)); |
} |
@@ -2273,12 +2383,13 @@ bool HStoreKeyedFastDoubleElement::NeedsCanonicalization() { |
} |
-#define H_CONSTANT_INT32(val) \ |
-new(zone) HConstant(FACTORY->NewNumberFromInt(val, TENURED), \ |
- Representation::Integer32()) |
+#define H_CONSTANT_INT32(val) \ |
+new(zone) HConstant(static_cast<int32_t>(val), \ |
+ Representation::Integer32(), \ |
+ Handle<Object>::null()) |
+ |
#define H_CONSTANT_DOUBLE(val) \ |
-new(zone) HConstant(FACTORY->NewNumber(val, TENURED), \ |
- Representation::Double()) |
+new(zone) HConstant(val, Representation::Double(), Handle<Object>::null()) |
#define DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HInstr, op) \ |
HInstruction* HInstr::New##HInstr(Zone* zone, \ |