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