Improve handling of unary plus.

Simple strategy: Transform unary plus into multiplication by one directly in the
parser and remove it from the Hydrogen graph later. This gives correct type
feedback without any special stub for it.

BUG=v8:2527

Review URL: https://codereview.chromium.org/13902013

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14306 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
svenpanne@chromium.org 2013-04-17 12:47:15 +00:00
parent f4b9b3b32c
commit 0d8b7f7608
9 changed files with 27 additions and 66 deletions

View File

@ -3976,18 +3976,6 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
break;
}
case Token::ADD: {
Comment cmt(masm_, "[ UnaryOperation (ADD)");
VisitForAccumulatorValue(expr->expression());
Label no_conversion;
__ JumpIfSmi(result_register(), &no_conversion);
ToNumberStub convert_stub;
__ CallStub(&convert_stub);
__ bind(&no_conversion);
context()->Plug(result_register());
break;
}
case Token::SUB:
EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
break;

View File

@ -1436,6 +1436,21 @@ HValue* HSub::Canonicalize() {
}
// TODO(svenpanne) Use this in other Canonicalize() functions.
static bool IsIdentityOperation(HValue* arg1, HValue* arg2, int32_t identity) {
return arg1->representation().IsSpecialization() &&
arg2->IsInteger32Constant() &&
arg2->GetInteger32Constant() == identity;
}
HValue* HMul::Canonicalize() {
if (IsIdentityOperation(left(), right(), 1)) return left();
if (IsIdentityOperation(right(), left(), 1)) return right();
return this;
}
HValue* HChange::Canonicalize() {
return (from().Equals(to())) ? value() : this;
}

View File

@ -4401,6 +4401,8 @@ class HMul: public HArithmeticBinaryOperation {
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
virtual HValue* Canonicalize();
// Only commutative if it is certain that not two objects are multiplicated.
virtual bool IsCommutative() const {
return !representation().IsTagged();

View File

@ -9160,7 +9160,6 @@ void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
case Token::DELETE: return VisitDelete(expr);
case Token::VOID: return VisitVoid(expr);
case Token::TYPEOF: return VisitTypeof(expr);
case Token::ADD: return VisitAdd(expr);
case Token::SUB: return VisitSub(expr);
case Token::BIT_NOT: return VisitBitNot(expr);
case Token::NOT: return VisitNot(expr);
@ -9218,21 +9217,6 @@ void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
}
void HOptimizedGraphBuilder::VisitAdd(UnaryOperation* expr) {
CHECK_ALIVE(VisitForValue(expr->expression()));
HValue* value = Pop();
HValue* context = environment()->LookupContext();
HInstruction* instr =
HMul::New(zone(), context, value, graph()->GetConstant1());
if (instr->IsBinaryOperation()) {
// Since we don't have type feedback, we must be cautious/pessimistic.
HBinaryOperation::cast(instr)->set_observed_input_representation(
Representation::Tagged(), Representation::Tagged());
}
return ast_context()->ReturnInstruction(instr, expr->id());
}
void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
CHECK_ALIVE(VisitForValue(expr->expression()));
HValue* value = Pop();

View File

@ -1267,7 +1267,6 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
void VisitDelete(UnaryOperation* expr);
void VisitVoid(UnaryOperation* expr);
void VisitTypeof(UnaryOperation* expr);
void VisitAdd(UnaryOperation* expr);
void VisitSub(UnaryOperation* expr);
void VisitBitNot(UnaryOperation* expr);
void VisitNot(UnaryOperation* expr);

View File

@ -3967,18 +3967,6 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
break;
}
case Token::ADD: {
Comment cmt(masm_, "[ UnaryOperation (ADD)");
VisitForAccumulatorValue(expr->expression());
Label no_conversion;
__ JumpIfSmi(result_register(), &no_conversion);
ToNumberStub convert_stub;
__ CallStub(&convert_stub);
__ bind(&no_conversion);
context()->Plug(result_register());
break;
}
case Token::SUB:
EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
break;

View File

@ -3995,19 +3995,6 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
break;
}
case Token::ADD: {
Comment cmt(masm_, "[ UnaryOperation (ADD)");
VisitForAccumulatorValue(expr->expression());
Label no_conversion;
__ JumpIfSmi(result_register(), &no_conversion);
__ mov(a0, result_register());
ToNumberStub convert_stub;
__ CallStub(&convert_stub);
__ bind(&no_conversion);
context()->Plug(result_register());
break;
}
case Token::SUB:
EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
break;

View File

@ -3286,6 +3286,16 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
}
}
// Desugar '+foo' into 'foo*1', this enables the collection of type feedback
// without any special stub and the multiplication is removed later in
// Crankshaft's canonicalization pass.
if (op == Token::ADD) {
return factory()->NewBinaryOperation(Token::MUL,
expression,
factory()->NewNumberLiteral(1),
position);
}
return factory()->NewUnaryOperation(op, expression, position);
} else if (Token::IsCountOp(op)) {

View File

@ -3968,18 +3968,6 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
break;
}
case Token::ADD: {
Comment cmt(masm_, "[ UnaryOperation (ADD)");
VisitForAccumulatorValue(expr->expression());
Label no_conversion;
__ JumpIfSmi(result_register(), &no_conversion);
ToNumberStub convert_stub;
__ CallStub(&convert_stub);
__ bind(&no_conversion);
context()->Plug(result_register());
break;
}
case Token::SUB:
EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
break;