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())) { |