Propagate and combine constants in Hydrogen

BUG=none
TEST=none
Review URL: http://codereview.chromium.org/8473002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10034 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent c4dfef94
...@@ -546,17 +546,19 @@ Handle<Object> Factory::NewNumber(double value, ...@@ -546,17 +546,19 @@ Handle<Object> Factory::NewNumber(double value,
} }
Handle<Object> Factory::NewNumberFromInt(int value) { Handle<Object> Factory::NewNumberFromInt(int32_t value,
PretenureFlag pretenure) {
CALL_HEAP_FUNCTION( CALL_HEAP_FUNCTION(
isolate(), isolate(),
isolate()->heap()->NumberFromInt32(value), Object); isolate()->heap()->NumberFromInt32(value, pretenure), Object);
} }
Handle<Object> Factory::NewNumberFromUint(uint32_t value) { Handle<Object> Factory::NewNumberFromUint(uint32_t value,
PretenureFlag pretenure) {
CALL_HEAP_FUNCTION( CALL_HEAP_FUNCTION(
isolate(), isolate(),
isolate()->heap()->NumberFromUint32(value), Object); isolate()->heap()->NumberFromUint32(value, pretenure), Object);
} }
......
...@@ -231,8 +231,10 @@ class Factory { ...@@ -231,8 +231,10 @@ class Factory {
Handle<Object> NewNumber(double value, Handle<Object> NewNumber(double value,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
Handle<Object> NewNumberFromInt(int value); Handle<Object> NewNumberFromInt(int32_t value,
Handle<Object> NewNumberFromUint(uint32_t value); PretenureFlag pretenure = NOT_TENURED);
Handle<Object> NewNumberFromUint(uint32_t value,
PretenureFlag pretenure = NOT_TENURED);
// These objects are used by the api to create env-independent data // These objects are used by the api to create env-independent data
// structures in the heap. // structures in the heap.
......
...@@ -229,19 +229,21 @@ MaybeObject* Heap::AllocateRaw(int size_in_bytes, ...@@ -229,19 +229,21 @@ MaybeObject* Heap::AllocateRaw(int size_in_bytes,
} }
MaybeObject* Heap::NumberFromInt32(int32_t value) { MaybeObject* Heap::NumberFromInt32(
int32_t value, PretenureFlag pretenure) {
if (Smi::IsValid(value)) return Smi::FromInt(value); if (Smi::IsValid(value)) return Smi::FromInt(value);
// Bypass NumberFromDouble to avoid various redundant checks. // Bypass NumberFromDouble to avoid various redundant checks.
return AllocateHeapNumber(FastI2D(value)); return AllocateHeapNumber(FastI2D(value), pretenure);
} }
MaybeObject* Heap::NumberFromUint32(uint32_t value) { MaybeObject* Heap::NumberFromUint32(
uint32_t value, PretenureFlag pretenure) {
if ((int32_t)value >= 0 && Smi::IsValid((int32_t)value)) { if ((int32_t)value >= 0 && Smi::IsValid((int32_t)value)) {
return Smi::FromInt((int32_t)value); return Smi::FromInt((int32_t)value);
} }
// Bypass NumberFromDouble to avoid various redundant checks. // Bypass NumberFromDouble to avoid various redundant checks.
return AllocateHeapNumber(FastUI2D(value)); return AllocateHeapNumber(FastUI2D(value), pretenure);
} }
......
...@@ -837,13 +837,15 @@ class Heap { ...@@ -837,13 +837,15 @@ class Heap {
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT inline MaybeObject* NumberFromInt32(int32_t value); MUST_USE_RESULT inline MaybeObject* NumberFromInt32(
int32_t value, PretenureFlag pretenure = NOT_TENURED);
// Converts an int into either a Smi or a HeapNumber object. // Converts an int into either a Smi or a HeapNumber object.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT inline MaybeObject* NumberFromUint32(uint32_t value); MUST_USE_RESULT inline MaybeObject* NumberFromUint32(
uint32_t value, PretenureFlag pretenure = NOT_TENURED);
// Allocates a new foreign object. // Allocates a new foreign object.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
......
...@@ -1894,6 +1894,167 @@ HValue* HAdd::EnsureAndPropagateNotMinusZero(BitVector* visited) { ...@@ -1894,6 +1894,167 @@ HValue* HAdd::EnsureAndPropagateNotMinusZero(BitVector* visited) {
} }
#define H_CONSTANT_INT32(val) \
new(zone) HConstant(FACTORY->NewNumberFromInt(val, TENURED), \
Representation::Integer32())
#define H_CONSTANT_DOUBLE(val) \
new(zone) HConstant(FACTORY->NewNumber(val, TENURED), \
Representation::Double())
#define DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HInstr, op) \
HInstruction* HInstr::New##HInstr(Zone* zone, \
HValue* context, \
HValue* left, \
HValue* right) { \
if (left->IsConstant() && right->IsConstant()) { \
HConstant* c_left = HConstant::cast(left); \
HConstant* c_right = HConstant::cast(right); \
if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { \
double double_res = c_left->DoubleValue() op c_right->DoubleValue(); \
if (TypeInfo::IsInt32Double(double_res)) { \
return H_CONSTANT_INT32(static_cast<int32_t>(double_res)); \
} \
return H_CONSTANT_DOUBLE(double_res); \
} \
} \
return new(zone) HInstr(context, left, right); \
}
DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HAdd, +)
DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HMul, *)
DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HSub, -)
#undef DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR
HInstruction* HMod::NewHMod(Zone* zone,
HValue* context,
HValue* left,
HValue* right) {
if (left->IsConstant() && right->IsConstant()) {
HConstant* c_left = HConstant::cast(left);
HConstant* c_right = HConstant::cast(right);
if (c_left->HasInteger32Value() && c_right->HasInteger32Value()) {
int32_t dividend = c_left->Integer32Value();
int32_t divisor = c_right->Integer32Value();
if (divisor != 0) {
int32_t res = dividend % divisor;
if ((res == 0) && (dividend < 0)) {
return H_CONSTANT_DOUBLE(-0.0);
}
return H_CONSTANT_INT32(res);
}
}
}
return new(zone) HMod(context, left, right);
}
HInstruction* HDiv::NewHDiv(Zone* zone,
HValue* context,
HValue* left,
HValue* right) {
// If left and right are constant values, try to return a constant value.
if (left->IsConstant() && right->IsConstant()) {
HConstant* c_left = HConstant::cast(left);
HConstant* c_right = HConstant::cast(right);
if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
if (c_right->DoubleValue() != 0) {
double double_res = c_left->DoubleValue() / c_right->DoubleValue();
if (TypeInfo::IsInt32Double(double_res)) {
return H_CONSTANT_INT32(static_cast<int32_t>(double_res));
}
return H_CONSTANT_DOUBLE(double_res);
}
}
}
return new(zone) HDiv(context, left, right);
}
HInstruction* HBitwise::NewHBitwise(Zone* zone,
Token::Value op,
HValue* context,
HValue* left,
HValue* right) {
if (left->IsConstant() && right->IsConstant()) {
HConstant* c_left = HConstant::cast(left);
HConstant* c_right = HConstant::cast(right);
if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
int32_t result;
int32_t v_left = c_left->NumberValueAsInteger32();
int32_t v_right = c_right->NumberValueAsInteger32();
switch (op) {
case Token::BIT_XOR:
result = v_left ^ v_right;
break;
case Token::BIT_AND:
result = v_left & v_right;
break;
case Token::BIT_OR:
result = v_left | v_right;
break;
default:
result = 0; // Please the compiler.
UNREACHABLE();
}
return H_CONSTANT_INT32(result);
}
}
return new(zone) HBitwise(op, context, left, right);
}
#define DEFINE_NEW_H_BITWISE_INSTR(HInstr, result) \
HInstruction* HInstr::New##HInstr(Zone* zone, \
HValue* context, \
HValue* left, \
HValue* right) { \
if (left->IsConstant() && right->IsConstant()) { \
HConstant* c_left = HConstant::cast(left); \
HConstant* c_right = HConstant::cast(right); \
if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { \
return H_CONSTANT_INT32(result); \
} \
} \
return new(zone) HInstr(context, left, right); \
}
DEFINE_NEW_H_BITWISE_INSTR(HSar,
c_left->NumberValueAsInteger32() >> (c_right->NumberValueAsInteger32() & 0x1f))
DEFINE_NEW_H_BITWISE_INSTR(HShl,
c_left->NumberValueAsInteger32() << (c_right->NumberValueAsInteger32() & 0x1f))
#undef DEFINE_NEW_H_BITWISE_INSTR
HInstruction* HShr::NewHShr(Zone* zone,
HValue* context,
HValue* left,
HValue* right) {
if (left->IsConstant() && right->IsConstant()) {
HConstant* c_left = HConstant::cast(left);
HConstant* c_right = HConstant::cast(right);
if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
int32_t left_val = c_left->NumberValueAsInteger32();
int32_t right_val = c_right->NumberValueAsInteger32() & 0x1f;
if ((right_val == 0) && (left_val < 0)) {
return H_CONSTANT_DOUBLE(
static_cast<double>(static_cast<uint32_t>(left_val)));
}
return H_CONSTANT_INT32(static_cast<uint32_t>(left_val) >> right_val);
}
}
return new(zone) HShr(context, left, right);
}
#undef H_CONSTANT_INT32
#undef H_CONSTANT_DOUBLE
void HIn::PrintDataTo(StringStream* stream) { void HIn::PrintDataTo(StringStream* stream) {
key()->PrintNameTo(stream); key()->PrintNameTo(stream);
stream->Add(" "); stream->Add(" ");
......
...@@ -2328,6 +2328,12 @@ class HConstant: public HTemplateInstruction<0> { ...@@ -2328,6 +2328,12 @@ class HConstant: public HTemplateInstruction<0> {
ASSERT(HasDoubleValue()); ASSERT(HasDoubleValue());
return double_value_; return double_value_;
} }
bool HasNumberValue() const { return has_int32_value_ || has_double_value_; }
int32_t NumberValueAsInteger32() const {
ASSERT(HasNumberValue());
if (has_int32_value_) return int32_value_;
return DoubleToInt32(double_value_);
}
bool HasStringValue() const { return handle_->IsString(); } bool HasStringValue() const { return handle_->IsString(); }
bool ToBoolean() const; bool ToBoolean() const;
...@@ -2993,6 +2999,11 @@ class HAdd: public HArithmeticBinaryOperation { ...@@ -2993,6 +2999,11 @@ class HAdd: public HArithmeticBinaryOperation {
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
static HInstruction* NewHAdd(Zone* zone,
HValue* context,
HValue* left,
HValue* right);
virtual HType CalculateInferredType(); virtual HType CalculateInferredType();
DECLARE_CONCRETE_INSTRUCTION(Add) DECLARE_CONCRETE_INSTRUCTION(Add)
...@@ -3013,6 +3024,11 @@ class HSub: public HArithmeticBinaryOperation { ...@@ -3013,6 +3024,11 @@ class HSub: public HArithmeticBinaryOperation {
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
static HInstruction* NewHSub(Zone* zone,
HValue* context,
HValue* left,
HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Sub) DECLARE_CONCRETE_INSTRUCTION(Sub)
protected: protected:
...@@ -3036,6 +3052,11 @@ class HMul: public HArithmeticBinaryOperation { ...@@ -3036,6 +3052,11 @@ class HMul: public HArithmeticBinaryOperation {
return !representation().IsTagged(); return !representation().IsTagged();
} }
static HInstruction* NewHMul(Zone* zone,
HValue* context,
HValue* left,
HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Mul) DECLARE_CONCRETE_INSTRUCTION(Mul)
protected: protected:
...@@ -3064,6 +3085,11 @@ class HMod: public HArithmeticBinaryOperation { ...@@ -3064,6 +3085,11 @@ class HMod: public HArithmeticBinaryOperation {
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
static HInstruction* NewHMod(Zone* zone,
HValue* context,
HValue* left,
HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Mod) DECLARE_CONCRETE_INSTRUCTION(Mod)
protected: protected:
...@@ -3083,6 +3109,12 @@ class HDiv: public HArithmeticBinaryOperation { ...@@ -3083,6 +3109,12 @@ class HDiv: public HArithmeticBinaryOperation {
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
static HInstruction* NewHDiv(Zone* zone,
HValue* context,
HValue* left,
HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Div) DECLARE_CONCRETE_INSTRUCTION(Div)
protected: protected:
...@@ -3105,6 +3137,12 @@ class HBitwise: public HBitwiseBinaryOperation { ...@@ -3105,6 +3137,12 @@ class HBitwise: public HBitwiseBinaryOperation {
virtual bool IsCommutative() const { return true; } virtual bool IsCommutative() const { return true; }
static HInstruction* NewHBitwise(Zone* zone,
Token::Value op,
HValue* context,
HValue* left,
HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Bitwise) DECLARE_CONCRETE_INSTRUCTION(Bitwise)
protected: protected:
...@@ -3126,6 +3164,11 @@ class HShl: public HBitwiseBinaryOperation { ...@@ -3126,6 +3164,11 @@ class HShl: public HBitwiseBinaryOperation {
virtual Range* InferRange(); virtual Range* InferRange();
static HInstruction* NewHShl(Zone* zone,
HValue* context,
HValue* left,
HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Shl) DECLARE_CONCRETE_INSTRUCTION(Shl)
protected: protected:
...@@ -3140,6 +3183,11 @@ class HShr: public HBitwiseBinaryOperation { ...@@ -3140,6 +3183,11 @@ class HShr: public HBitwiseBinaryOperation {
virtual Range* InferRange(); virtual Range* InferRange();
static HInstruction* NewHShr(Zone* zone,
HValue* context,
HValue* left,
HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Shr) DECLARE_CONCRETE_INSTRUCTION(Shr)
protected: protected:
...@@ -3154,6 +3202,11 @@ class HSar: public HBitwiseBinaryOperation { ...@@ -3154,6 +3202,11 @@ class HSar: public HBitwiseBinaryOperation {
virtual Range* InferRange(); virtual Range* InferRange();
static HInstruction* NewHSar(Zone* zone,
HValue* context,
HValue* left,
HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Sar) DECLARE_CONCRETE_INSTRUCTION(Sar)
protected: protected:
......
...@@ -5678,34 +5678,34 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, ...@@ -5678,34 +5678,34 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
AddInstruction(HCheckInstanceType::NewIsString(right)); AddInstruction(HCheckInstanceType::NewIsString(right));
instr = new(zone()) HStringAdd(context, left, right); instr = new(zone()) HStringAdd(context, left, right);
} else { } else {
instr = new(zone()) HAdd(context, left, right); instr = HAdd::NewHAdd(zone(), context, left, right);
} }
break; break;
case Token::SUB: case Token::SUB:
instr = new(zone()) HSub(context, left, right); instr = HSub::NewHSub(zone(), context, left, right);
break; break;
case Token::MUL: case Token::MUL:
instr = new(zone()) HMul(context, left, right); instr = HMul::NewHMul(zone(), context, left, right);
break; break;
case Token::MOD: case Token::MOD:
instr = new(zone()) HMod(context, left, right); instr = HMod::NewHMod(zone(), context, left, right);
break; break;
case Token::DIV: case Token::DIV:
instr = new(zone()) HDiv(context, left, right); instr = HDiv::NewHDiv(zone(), context, left, right);
break; break;
case Token::BIT_XOR: case Token::BIT_XOR:
case Token::BIT_AND: case Token::BIT_AND:
case Token::BIT_OR: case Token::BIT_OR:
instr = new(zone()) HBitwise(expr->op(), context, left, right); instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right);
break; break;
case Token::SAR: case Token::SAR:
instr = new(zone()) HSar(context, left, right); instr = HSar::NewHSar(zone(), context, left, right);
break; break;
case Token::SHR: case Token::SHR:
instr = new(zone()) HShr(context, left, right); instr = HShr::NewHShr(zone(), context, left, right);
break; break;
case Token::SHL: case Token::SHL:
instr = new(zone()) HShl(context, left, right); instr = HShl::NewHShl(zone(), context, left, right);
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment