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,
}
Handle<Object> Factory::NewNumberFromInt(int value) {
Handle<Object> Factory::NewNumberFromInt(int32_t value,
PretenureFlag pretenure) {
CALL_HEAP_FUNCTION(
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(
isolate(),
isolate()->heap()->NumberFromUint32(value), Object);
isolate()->heap()->NumberFromUint32(value, pretenure), Object);
}
......
......@@ -231,8 +231,10 @@ class Factory {
Handle<Object> NewNumber(double value,
PretenureFlag pretenure = NOT_TENURED);
Handle<Object> NewNumberFromInt(int value);
Handle<Object> NewNumberFromUint(uint32_t value);
Handle<Object> NewNumberFromInt(int32_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
// structures in the heap.
......
......@@ -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);
// 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)) {
return Smi::FromInt((int32_t)value);
}
// Bypass NumberFromDouble to avoid various redundant checks.
return AllocateHeapNumber(FastUI2D(value));
return AllocateHeapNumber(FastUI2D(value), pretenure);
}
......
......@@ -837,13 +837,15 @@ class Heap {
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed.
// 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.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed.
// 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.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
......
......@@ -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) {
key()->PrintNameTo(stream);
stream->Add(" ");
......
......@@ -2328,6 +2328,12 @@ class HConstant: public HTemplateInstruction<0> {
ASSERT(HasDoubleValue());
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 ToBoolean() const;
......@@ -2993,6 +2999,11 @@ class HAdd: public HArithmeticBinaryOperation {
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
static HInstruction* NewHAdd(Zone* zone,
HValue* context,
HValue* left,
HValue* right);
virtual HType CalculateInferredType();
DECLARE_CONCRETE_INSTRUCTION(Add)
......@@ -3013,6 +3024,11 @@ class HSub: public HArithmeticBinaryOperation {
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
static HInstruction* NewHSub(Zone* zone,
HValue* context,
HValue* left,
HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Sub)
protected:
......@@ -3036,6 +3052,11 @@ class HMul: public HArithmeticBinaryOperation {
return !representation().IsTagged();
}
static HInstruction* NewHMul(Zone* zone,
HValue* context,
HValue* left,
HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Mul)
protected:
......@@ -3064,6 +3085,11 @@ class HMod: public HArithmeticBinaryOperation {
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
static HInstruction* NewHMod(Zone* zone,
HValue* context,
HValue* left,
HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Mod)
protected:
......@@ -3083,6 +3109,12 @@ class HDiv: public HArithmeticBinaryOperation {
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
static HInstruction* NewHDiv(Zone* zone,
HValue* context,
HValue* left,
HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Div)
protected:
......@@ -3105,6 +3137,12 @@ class HBitwise: public HBitwiseBinaryOperation {
virtual bool IsCommutative() const { return true; }
static HInstruction* NewHBitwise(Zone* zone,
Token::Value op,
HValue* context,
HValue* left,
HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Bitwise)
protected:
......@@ -3126,6 +3164,11 @@ class HShl: public HBitwiseBinaryOperation {
virtual Range* InferRange();
static HInstruction* NewHShl(Zone* zone,
HValue* context,
HValue* left,
HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Shl)
protected:
......@@ -3140,6 +3183,11 @@ class HShr: public HBitwiseBinaryOperation {
virtual Range* InferRange();
static HInstruction* NewHShr(Zone* zone,
HValue* context,
HValue* left,
HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Shr)
protected:
......@@ -3154,6 +3202,11 @@ class HSar: public HBitwiseBinaryOperation {
virtual Range* InferRange();
static HInstruction* NewHSar(Zone* zone,
HValue* context,
HValue* left,
HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Sar)
protected:
......
......@@ -5678,34 +5678,34 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
AddInstruction(HCheckInstanceType::NewIsString(right));
instr = new(zone()) HStringAdd(context, left, right);
} else {
instr = new(zone()) HAdd(context, left, right);
instr = HAdd::NewHAdd(zone(), context, left, right);
}
break;
case Token::SUB:
instr = new(zone()) HSub(context, left, right);
instr = HSub::NewHSub(zone(), context, left, right);
break;
case Token::MUL:
instr = new(zone()) HMul(context, left, right);
instr = HMul::NewHMul(zone(), context, left, right);
break;
case Token::MOD:
instr = new(zone()) HMod(context, left, right);
instr = HMod::NewHMod(zone(), context, left, right);
break;
case Token::DIV:
instr = new(zone()) HDiv(context, left, right);
instr = HDiv::NewHDiv(zone(), context, left, right);
break;
case Token::BIT_XOR:
case Token::BIT_AND:
case Token::BIT_OR:
instr = new(zone()) HBitwise(expr->op(), context, left, right);
instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right);
break;
case Token::SAR:
instr = new(zone()) HSar(context, left, right);
instr = HSar::NewHSar(zone(), context, left, right);
break;
case Token::SHR:
instr = new(zone()) HShr(context, left, right);
instr = HShr::NewHShr(zone(), context, left, right);
break;
case Token::SHL:
instr = new(zone()) HShl(context, left, right);
instr = HShl::NewHShl(zone(), context, left, right);
break;
default:
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