Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index 627dec94790809db19d4472d1da3061265589494..5f7bc76652f78f1a9f203f1d6a35b518320a3299 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -3122,7 +3122,7 @@ void HGraph::RestoreActualValues() { |
| } |
| -void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { |
| +void HGraphBuilder::PushAndAdd(HInstruction* instr) { |
| Push(instr); |
| AddInstruction(instr); |
| } |
| @@ -7488,8 +7488,8 @@ void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) { |
| void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { |
| CHECK_ALIVE(VisitForValue(expr->expression())); |
| - HValue* value = Pop(); |
| Handle<Type> operand_type = expr->expression()->bounds().lower; |
| + HValue* value = TruncateToNumber(Pop(), &operand_type); |
| HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB); |
| return ast_context()->ReturnInstruction(instr, expr->id()); |
| } |
| @@ -7497,8 +7497,8 @@ void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { |
| void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
| CHECK_ALIVE(VisitForValue(expr->expression())); |
| - HValue* value = Pop(); |
| Handle<Type> operand_type = expr->expression()->bounds().lower; |
| + HValue* value = TruncateToNumber(Pop(), &operand_type); |
| HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::BIT_NOT); |
| return ast_context()->ReturnInstruction(instr, expr->id()); |
| } |
| @@ -7829,6 +7829,41 @@ bool CanBeZero(HValue* right) { |
| } |
| +HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { |
| + if (value->IsConstant()) { |
| + HConstant* constant = HConstant::cast(value); |
| + HConstant* number = constant->CopyToTruncatedNumber(zone()); |
| + if (number != NULL) { |
| + *expected = handle(Type::Number(), isolate()); |
| + return AddInstruction(number); |
| + } |
| + return value; |
| + } |
| + |
| + Handle<Type> expected_type = *expected; |
| + Representation rep = Representation::FromType(expected_type); |
| + if (!rep.IsTagged()) return value; |
| + |
| + // If our type feedback suggests that we can non-observably truncate to number |
| + // we introduce the appropriate check here. This avoids 'value' having a |
| + // tagged representation later on. |
| + if (expected_type->Is(Type::Oddball())) { |
| + // TODO(olivf) The BinaryOpStub only records undefined. It might pay off to |
| + // also record booleans and convert them to 0/1 here. |
| + IfBuilder if_nan(this); |
| + if_nan.If<HCompareObjectEqAndBranch>(value, |
| + graph()->GetConstantUndefined()); |
| + if_nan.Then(); |
| + Push(Add<HConstant>(OS::nan_value(), Representation::Double())); |
|
Jakob Kummerow
2013/07/22 07:43:47
Stack height mismatches at basic block joins are a
oliv
2013/07/22 13:56:43
Done.
|
| + if_nan.ElseDeopt(); |
| + if_nan.End(); |
| + return Pop(); |
| + } |
| + |
| + return value; |
| +} |
| + |
| + |
| HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( |
| BinaryOperation* expr, |
| HValue* left, |
| @@ -7842,6 +7877,14 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( |
| Representation right_rep = Representation::FromType(right_type); |
| Representation result_rep = Representation::FromType(result_type); |
| + if (expr->op() != Token::ADD || |
| + (left->type().IsNoString() && right->type().IsNoString())) { |
| + // For addition we can only truncate the arguments to number if we can |
| + // prove that we will not end up in string concatenation mode. |
| + left = TruncateToNumber(left, &left_type); |
| + right = TruncateToNumber(right, &right_type); |
| + } |
| + |
| if (left_type->Is(Type::None())) { |
| AddSoftDeoptimize(); |
| // TODO(rossberg): we should be able to get rid of non-continuous defaults. |