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

Reply via email to