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;
}
+// 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;
}
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();
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);
}
-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();
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);
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;
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;
}
}
+ // 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)) {
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;