Revision: 10034
Author: [email protected]
Date: Mon Nov 21 02:18:47 2011
Log: Propagate and combine constants in Hydrogen
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/8473002
http://code.google.com/p/v8/source/detail?r=10034
Modified:
/branches/bleeding_edge/src/factory.cc
/branches/bleeding_edge/src/factory.h
/branches/bleeding_edge/src/heap-inl.h
/branches/bleeding_edge/src/heap.h
/branches/bleeding_edge/src/hydrogen-instructions.cc
/branches/bleeding_edge/src/hydrogen-instructions.h
/branches/bleeding_edge/src/hydrogen.cc
=======================================
--- /branches/bleeding_edge/src/factory.cc Wed Nov 9 04:47:15 2011
+++ /branches/bleeding_edge/src/factory.cc Mon Nov 21 02:18:47 2011
@@ -546,17 +546,19 @@
}
-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);
}
=======================================
--- /branches/bleeding_edge/src/factory.h Thu Nov 3 03:36:55 2011
+++ /branches/bleeding_edge/src/factory.h Mon Nov 21 02:18:47 2011
@@ -231,8 +231,10 @@
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.
=======================================
--- /branches/bleeding_edge/src/heap-inl.h Thu Nov 17 09:05:12 2011
+++ /branches/bleeding_edge/src/heap-inl.h Mon Nov 21 02:18:47 2011
@@ -229,19 +229,21 @@
}
-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);
}
=======================================
--- /branches/bleeding_edge/src/heap.h Wed Nov 9 06:04:56 2011
+++ /branches/bleeding_edge/src/heap.h Mon Nov 21 02:18:47 2011
@@ -837,13 +837,15 @@
// 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
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.cc Thu Nov 17
05:57:55 2011
+++ /branches/bleeding_edge/src/hydrogen-instructions.cc Mon Nov 21
02:18:47 2011
@@ -1892,6 +1892,167 @@
}
return NULL;
}
+
+
+#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) {
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Thu Nov 17 05:57:55
2011
+++ /branches/bleeding_edge/src/hydrogen-instructions.h Mon Nov 21 02:18:47
2011
@@ -2328,6 +2328,12 @@
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 @@
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 @@
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
+ static HInstruction* NewHSub(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right);
+
DECLARE_CONCRETE_INSTRUCTION(Sub)
protected:
@@ -3035,6 +3051,11 @@
virtual bool IsCommutative() const {
return !representation().IsTagged();
}
+
+ static HInstruction* NewHMul(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Mul)
@@ -3064,6 +3085,11 @@
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 @@
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
+
+ static HInstruction* NewHDiv(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right);
+
DECLARE_CONCRETE_INSTRUCTION(Div)
protected:
@@ -3104,6 +3136,12 @@
Token::Value op() const { return op_; }
virtual bool IsCommutative() const { return true; }
+
+ static HInstruction* NewHBitwise(Zone* zone,
+ Token::Value op,
+ HValue* context,
+ HValue* left,
+ HValue* right);
DECLARE_CONCRETE_INSTRUCTION(Bitwise)
@@ -3126,6 +3164,11 @@
virtual Range* InferRange();
+ static HInstruction* NewHShl(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right);
+
DECLARE_CONCRETE_INSTRUCTION(Shl)
protected:
@@ -3140,6 +3183,11 @@
virtual Range* InferRange();
+ static HInstruction* NewHShr(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right);
+
DECLARE_CONCRETE_INSTRUCTION(Shr)
protected:
@@ -3154,6 +3202,11 @@
virtual Range* InferRange();
+ static HInstruction* NewHSar(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right);
+
DECLARE_CONCRETE_INSTRUCTION(Sar)
protected:
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc Thu Nov 17 05:57:55 2011
+++ /branches/bleeding_edge/src/hydrogen.cc Mon Nov 21 02:18:47 2011
@@ -5678,34 +5678,34 @@
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();
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev