Chromium Code Reviews| Index: src/hydrogen-instructions.cc |
| diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc |
| index 2d4b82bf16ba1efe84bbc0915111921069ad9384..788dd67e5e5ab9b71bfe2b3c92349d3faf474e1a 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" |
| @@ -2755,7 +2756,7 @@ HInstruction* HInstr::New##HInstr(Zone* zone, \ |
| HValue* context, \ |
| HValue* left, \ |
| HValue* right) { \ |
| - 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())) { \ |
| @@ -2777,11 +2778,177 @@ DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HSub, -) |
| #undef DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR |
| +HInstruction* HStringAdd::NewHStringAdd(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::NewHStringCharFromCode(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::NewHStringLength(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::NewHUnaryMathOperation( |
| + 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)) { // +Inifinity and -Infinity. |
|
Jakob Kummerow
2013/02/20 15:31:04
nit: "Inifinity" sounds nice, but has an "i" too m
Yang
2013/02/20 17:51:15
Done.
|
| + 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: |
| + if (d >= -0.5 && d < 0.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); |
|
Jakob Kummerow
2013/02/20 15:31:04
I'm not convinced having this "fast path" is worth
Yang
2013/02/20 17:51:15
This is not a fast path, but for correctness. The
|
| + 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::NewHPower(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::NewHMathMinMax(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) { |
|
Jakob Kummerow
2013/02/20 15:31:04
nit: double space
|
| + 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::NewHMod(Zone* zone, |
| HValue* context, |
| HValue* left, |
| HValue* right) { |
| - 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->HasInteger32Value() && c_right->HasInteger32Value()) { |
| @@ -2805,7 +2972,7 @@ HInstruction* HDiv::NewHDiv(Zone* zone, |
| 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 +2982,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); |
| } |
| } |
| } |
| @@ -2827,7 +2998,7 @@ HInstruction* HBitwise::NewHBitwise(Zone* zone, |
| HValue* context, |
| HValue* left, |
| HValue* right) { |
| - 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())) { |
| @@ -2860,7 +3031,7 @@ HInstruction* HInstr::New##HInstr(Zone* zone, \ |
| HValue* context, \ |
| HValue* left, \ |
| HValue* right) { \ |
| - 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())) { \ |
| @@ -2883,7 +3054,7 @@ HInstruction* HShr::NewHShr(Zone* zone, |
| HValue* context, |
| HValue* left, |
| HValue* right) { |
| - 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())) { |