| Index: src/hydrogen-instructions.cc
 | 
| diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
 | 
| index 2d4b82bf16ba1efe84bbc0915111921069ad9384..6cd0fe0a6604eac0c865c2d70e677b1775616431 100644
 | 
| --- a/src/hydrogen-instructions.cc
 | 
| +++ b/src/hydrogen-instructions.cc
 | 
| @@ -27,6 +27,7 @@
 | 
|  
 | 
|  #include "v8.h"
 | 
|  
 | 
| +#include "double.h"
 | 
|  #include "factory.h"
 | 
|  #include "hydrogen.h"
 | 
|  
 | 
| @@ -2751,11 +2752,9 @@ 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()) {                             \
 | 
| +HInstruction* HInstr::New(                                                     \
 | 
| +    Zone* zone, HValue* context, HValue* left, HValue* right) {                \
 | 
| +  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {      \
 | 
|      HConstant* c_left = HConstant::cast(left);                                 \
 | 
|      HConstant* c_right = HConstant::cast(right);                               \
 | 
|      if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {             \
 | 
| @@ -2777,11 +2776,168 @@ 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()) {
 | 
| +HInstruction* HStringAdd::New(
 | 
| +    Zone* zone, HValue* context, HValue* left, HValue* right) {
 | 
| +  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
 | 
| +    HConstant* c_right = HConstant::cast(right);
 | 
| +    HConstant* c_left = HConstant::cast(left);
 | 
| +    if (c_left->HasStringValue() && c_right->HasStringValue()) {
 | 
| +      return new(zone) HConstant(FACTORY->NewConsString(c_left->StringValue(),
 | 
| +                                                        c_right->StringValue()),
 | 
| +                                 Representation::Tagged());
 | 
| +    }
 | 
| +  }
 | 
| +  return new(zone) HStringAdd(context, left, right);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +HInstruction* HStringCharFromCode::New(
 | 
| +    Zone* zone, HValue* context, HValue* char_code) {
 | 
| +  if (FLAG_fold_constants && char_code->IsConstant()) {
 | 
| +    HConstant* c_code = HConstant::cast(char_code);
 | 
| +    if (c_code->HasNumberValue()) {
 | 
| +      if (isfinite(c_code->DoubleValue())) {
 | 
| +        uint32_t code = c_code->NumberValueAsInteger32() & 0xffff;
 | 
| +        return new(zone) HConstant(LookupSingleCharacterStringFromCode(code),
 | 
| +                                   Representation::Tagged());
 | 
| +      }
 | 
| +      return new(zone) HConstant(FACTORY->empty_string(),
 | 
| +                                 Representation::Tagged());
 | 
| +    }
 | 
| +  }
 | 
| +  return new(zone) HStringCharFromCode(context, char_code);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +HInstruction* HStringLength::New(Zone* zone, HValue* string) {
 | 
| +  if (FLAG_fold_constants && string->IsConstant()) {
 | 
| +    HConstant* c_string = HConstant::cast(string);
 | 
| +    if (c_string->HasStringValue()) {
 | 
| +      return H_CONSTANT_INT32(c_string->StringValue()->length());
 | 
| +    }
 | 
| +  }
 | 
| +  return new(zone) HStringLength(string);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +HInstruction* HUnaryMathOperation::New(
 | 
| +    Zone* zone, HValue* context, HValue* value, BuiltinFunctionId op) {
 | 
| +  do {
 | 
| +    if (!FLAG_fold_constants) break;
 | 
| +    if (!value->IsConstant()) break;
 | 
| +    HConstant* constant = HConstant::cast(value);
 | 
| +    if (!constant->HasNumberValue()) break;
 | 
| +    double d = constant->DoubleValue();
 | 
| +    if (isnan(d)) {  // NaN poisons everything.
 | 
| +      return H_CONSTANT_DOUBLE(OS::nan_value());
 | 
| +    }
 | 
| +    if (isinf(d)) {  // +Infinity and -Infinity.
 | 
| +      switch (op) {
 | 
| +        case kMathSin:
 | 
| +        case kMathCos:
 | 
| +        case kMathTan:
 | 
| +          return H_CONSTANT_DOUBLE(OS::nan_value());
 | 
| +        case kMathExp:
 | 
| +          return H_CONSTANT_DOUBLE((d > 0.0) ? d : 0.0);
 | 
| +        case kMathLog:
 | 
| +        case kMathSqrt:
 | 
| +          return H_CONSTANT_DOUBLE((d > 0.0) ? d : OS::nan_value());
 | 
| +        case kMathPowHalf:
 | 
| +        case kMathAbs:
 | 
| +          return H_CONSTANT_DOUBLE((d > 0.0) ? d : -d);
 | 
| +        case kMathRound:
 | 
| +        case kMathFloor:
 | 
| +          return H_CONSTANT_DOUBLE(d);
 | 
| +        default:
 | 
| +          UNREACHABLE();
 | 
| +          break;
 | 
| +      }
 | 
| +    }
 | 
| +    switch (op) {
 | 
| +      case kMathSin:
 | 
| +        return H_CONSTANT_DOUBLE(fast_sin(d));
 | 
| +      case kMathCos:
 | 
| +        return H_CONSTANT_DOUBLE(fast_cos(d));
 | 
| +      case kMathTan:
 | 
| +        return H_CONSTANT_DOUBLE(fast_tan(d));
 | 
| +      case kMathExp:
 | 
| +        return H_CONSTANT_DOUBLE(fast_exp(d));
 | 
| +      case kMathLog:
 | 
| +        return H_CONSTANT_DOUBLE(fast_log(d));
 | 
| +      case kMathSqrt:
 | 
| +        return H_CONSTANT_DOUBLE(fast_sqrt(d));
 | 
| +      case kMathPowHalf:
 | 
| +        return H_CONSTANT_DOUBLE(power_double_double(d, 0.5));
 | 
| +      case kMathAbs:
 | 
| +        return H_CONSTANT_DOUBLE((d >= 0.0) ? d + 0.0 : -d);
 | 
| +      case kMathRound:
 | 
| +        // -0.5 .. -0.0 round to -0.0.
 | 
| +        if ((d >= -0.5 && Double(d).Sign() < 0)) return H_CONSTANT_DOUBLE(-0.0);
 | 
| +        // Doubles are represented as Significant * 2 ^ Exponent. If the
 | 
| +        // Exponent is not negative, the double value is already an integer.
 | 
| +        if (Double(d).Exponent() >= 0) return H_CONSTANT_DOUBLE(d);
 | 
| +        return H_CONSTANT_DOUBLE(floor(d + 0.5));
 | 
| +      case kMathFloor:
 | 
| +        return H_CONSTANT_DOUBLE(floor(d));
 | 
| +      default:
 | 
| +        UNREACHABLE();
 | 
| +        break;
 | 
| +    }
 | 
| +  } while (false);
 | 
| +  return new(zone) HUnaryMathOperation(context, value, op);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +HInstruction* HPower::New(Zone* zone, HValue* left, HValue* right) {
 | 
| +  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
 | 
| +    HConstant* c_left = HConstant::cast(left);
 | 
| +    HConstant* c_right = HConstant::cast(right);
 | 
| +    if (c_left->HasNumberValue() && c_right->HasNumberValue()) {
 | 
| +      double result = power_helper(c_left->DoubleValue(),
 | 
| +                                   c_right->DoubleValue());
 | 
| +      return H_CONSTANT_DOUBLE(isnan(result) ?  OS::nan_value() : result);
 | 
| +    }
 | 
| +  }
 | 
| +  return new(zone) HPower(left, right);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +HInstruction* HMathMinMax::New(
 | 
| +    Zone* zone, HValue* context, HValue* left, HValue* right, Operation op) {
 | 
| +  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
 | 
| +    HConstant* c_left = HConstant::cast(left);
 | 
| +    HConstant* c_right = HConstant::cast(right);
 | 
| +    if (c_left->HasNumberValue() && c_right->HasNumberValue()) {
 | 
| +      double d_left = c_left->DoubleValue();
 | 
| +      double d_right = c_right->DoubleValue();
 | 
| +      if (op == kMathMin) {
 | 
| +        if (d_left > d_right) return H_CONSTANT_DOUBLE(d_right);
 | 
| +        if (d_left < d_right) return H_CONSTANT_DOUBLE(d_left);
 | 
| +        if (d_left == d_right) {
 | 
| +          // Handle +0 and -0.
 | 
| +          return H_CONSTANT_DOUBLE((Double(d_left).Sign() == -1) ? d_left
 | 
| +                                                                 : d_right);
 | 
| +        }
 | 
| +      } else {
 | 
| +        if (d_left < d_right) return H_CONSTANT_DOUBLE(d_right);
 | 
| +        if (d_left > d_right) return H_CONSTANT_DOUBLE(d_left);
 | 
| +        if (d_left == d_right) {
 | 
| +          // Handle +0 and -0.
 | 
| +          return H_CONSTANT_DOUBLE((Double(d_left).Sign() == -1) ? d_right
 | 
| +                                                                 : d_left);
 | 
| +        }
 | 
| +      }
 | 
| +      // All comparisons failed, must be NaN.
 | 
| +      return H_CONSTANT_DOUBLE(OS::nan_value());
 | 
| +    }
 | 
| +  }
 | 
| +  return new(zone) HMathMinMax(context, left, right, op);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +HInstruction* HMod::New(
 | 
| +    Zone* zone, HValue* context, HValue* left, HValue* right) {
 | 
| +  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
 | 
|      HConstant* c_left = HConstant::cast(left);
 | 
|      HConstant* c_right = HConstant::cast(right);
 | 
|      if (c_left->HasInteger32Value() && c_right->HasInteger32Value()) {
 | 
| @@ -2800,12 +2956,10 @@ HInstruction* HMod::NewHMod(Zone* zone,
 | 
|  }
 | 
|  
 | 
|  
 | 
| -HInstruction* HDiv::NewHDiv(Zone* zone,
 | 
| -                            HValue* context,
 | 
| -                            HValue* left,
 | 
| -                            HValue* right) {
 | 
| +HInstruction* HDiv::New(
 | 
| +    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()) {
 | 
| +  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
 | 
|      HConstant* c_left = HConstant::cast(left);
 | 
|      HConstant* c_right = HConstant::cast(right);
 | 
|      if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
 | 
| @@ -2815,6 +2969,10 @@ HInstruction* HDiv::NewHDiv(Zone* zone,
 | 
|            return H_CONSTANT_INT32(static_cast<int32_t>(double_res));
 | 
|          }
 | 
|          return H_CONSTANT_DOUBLE(double_res);
 | 
| +      } else {
 | 
| +        int sign = Double(c_left->DoubleValue()).Sign() *
 | 
| +                   Double(c_right->DoubleValue()).Sign();  // Right could be -0.
 | 
| +        return H_CONSTANT_DOUBLE(sign * V8_INFINITY);
 | 
|        }
 | 
|      }
 | 
|    }
 | 
| @@ -2822,12 +2980,9 @@ HInstruction* HDiv::NewHDiv(Zone* zone,
 | 
|  }
 | 
|  
 | 
|  
 | 
| -HInstruction* HBitwise::NewHBitwise(Zone* zone,
 | 
| -                                    Token::Value op,
 | 
| -                                    HValue* context,
 | 
| -                                    HValue* left,
 | 
| -                                    HValue* right) {
 | 
| -  if (left->IsConstant() && right->IsConstant()) {
 | 
| +HInstruction* HBitwise::New(
 | 
| +    Zone* zone, Token::Value op, HValue* context, HValue* left, HValue* right) {
 | 
| +  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
 | 
|      HConstant* c_left = HConstant::cast(left);
 | 
|      HConstant* c_right = HConstant::cast(right);
 | 
|      if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
 | 
| @@ -2856,11 +3011,9 @@ HInstruction* HBitwise::NewHBitwise(Zone* zone,
 | 
|  
 | 
|  
 | 
|  #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()) {                             \
 | 
| +HInstruction* HInstr::New(                                                     \
 | 
| +    Zone* zone, HValue* context, HValue* left, HValue* right) {                \
 | 
| +  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {      \
 | 
|      HConstant* c_left = HConstant::cast(left);                                 \
 | 
|      HConstant* c_right = HConstant::cast(right);                               \
 | 
|      if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {             \
 | 
| @@ -2879,11 +3032,9 @@ 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()) {
 | 
| +HInstruction* HShr::New(
 | 
| +    Zone* zone, HValue* context, HValue* left, HValue* right) {
 | 
| +  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
 | 
|      HConstant* c_left = HConstant::cast(left);
 | 
|      HConstant* c_right = HConstant::cast(right);
 | 
|      if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
 | 
| 
 |