| 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, \
|
|
|