(node->expression()->AsBinaryOperation() != NULL &&
node->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
switch (op) {
+ case Token::NOT:
+ case Token::DELETE:
+ case Token::TYPEOF:
+ UNREACHABLE(); // handled above
+ break;
+
case Token::SUB: {
GenericUnaryOpStub stub(Token::SUB, overwrite);
Result operand = frame_->Pop();
__ not_(answer.reg());
continue_label.Bind(&answer);
- if (operand_info.IsInteger32()) {
- answer.set_type_info(TypeInfo::Integer32());
- } else {
- answer.set_type_info(TypeInfo::Number());
- }
+ answer.set_type_info(TypeInfo::Integer32());
frame_->Push(&answer);
}
break;
break;
}
default:
- // NOT, DELETE, TYPEOF, and VOID are handled outside the
- // switch.
UNREACHABLE();
}
}
__ setcc(overflow, tmp.reg());
__ or_(Operand(tmp.reg()), new_value.reg());
__ test(tmp.reg(), Immediate(kSmiTagMask));
- tmp.Unuse();
+ tmp.Unusec();
deferred->Branch(not_zero);
} else {
// Otherwise we test separately for overflow and smi tag.
GenericUnaryOpStub stub(Token::SUB, overwrite);
Result operand = frame_->Pop();
Result answer = frame_->CallStub(&stub, &operand);
+ answer.set_type_info(TypeInfo::Number());
frame_->Push(&answer);
break;
}
frame_->Spill(answer.reg());
__ SmiNot(answer.reg(), answer.reg());
continue_label.Bind(&answer);
+ answer.set_type_info(TypeInfo::Smi());
frame_->Push(&answer);
break;
}
// Smi check.
JumpTarget continue_label;
Result operand = frame_->Pop();
+ TypeInfo operand_info = operand.type_info();
operand.ToRegister();
Condition is_smi = masm_->CheckSmi(operand.reg());
continue_label.Branch(is_smi, &operand);
CALL_FUNCTION, 1);
continue_label.Bind(&answer);
+ if (operand_info.IsSmi()) {
+ answer.set_type_info(TypeInfo::Smi());
+ } else if (operand_info.IsInteger32()) {
+ answer.set_type_info(TypeInfo::Integer32());
+ } else {
+ answer.set_type_info(TypeInfo::Number());
+ }
frame_->Push(&answer);
break;
}
-
default:
UNREACHABLE();
}
}
+static TypeInfo CalculateTypeInfo(TypeInfo operands_type,
+ Token::Value op,
+ const Result& right,
+ const Result& left) {
+ // Set TypeInfo of result according to the operation performed.
+ // We rely on the fact that smis have a 32 bit payload on x64.
+ STATIC_ASSERT(kSmiValueSize == 32);
+ switch (op) {
+ case Token::COMMA:
+ return right.type_info();
+ case Token::OR:
+ case Token::AND:
+ // Result type can be either of the two input types.
+ return operands_type;
+ case Token::BIT_OR:
+ case Token::BIT_XOR:
+ case Token::BIT_AND:
+ // Result is always a smi.
+ return TypeInfo::Smi();
+ case Token::SAR:
+ case Token::SHL:
+ // Result is always a smi.
+ return TypeInfo::Smi();
+ case Token::SHR:
+ // Result of x >>> y is always a smi if masked y >= 1, otherwise a number.
+ return (right.is_constant() && right.handle()->IsSmi()
+ && (Smi::cast(*right.handle())->value() & 0x1F) >= 1)
+ ? TypeInfo::Smi()
+ : TypeInfo::Number();
+ case Token::ADD:
+ if (operands_type.IsNumber()) {
+ return TypeInfo::Number();
+ } else if (left.type_info().IsString() || right.type_info().IsString()) {
+ return TypeInfo::String();
+ } else {
+ return TypeInfo::Unknown();
+ }
+ case Token::SUB:
+ case Token::MUL:
+ case Token::DIV:
+ case Token::MOD:
+ // Result is always a number.
+ return TypeInfo::Number();
+ default:
+ UNREACHABLE();
+ }
+ UNREACHABLE();
+ return TypeInfo::Unknown();
+}
+
+
void CodeGenerator::GenericBinaryOperation(Token::Value op,
StaticType* type,
OverwriteMode overwrite_mode) {
TypeInfo operands_type =
TypeInfo::Combine(left.type_info(), right.type_info());
+ TypeInfo result_type = CalculateTypeInfo(operands_type, op, right, left);
+
Result answer;
if (left_is_non_smi_constant || right_is_non_smi_constant) {
GenericBinaryOpStub stub(op,
}
}
- // Set TypeInfo of result according to the operation performed.
- // We rely on the fact that smis have a 32 bit payload on x64.
- ASSERT(kSmiValueSize == 32);
- TypeInfo result_type = TypeInfo::Unknown();
- switch (op) {
- case Token::COMMA:
- result_type = right.type_info();
- break;
- case Token::OR:
- case Token::AND:
- // Result type can be either of the two input types.
- result_type = operands_type;
- break;
- case Token::BIT_OR:
- case Token::BIT_XOR:
- case Token::BIT_AND:
- // Result is always a smi.
- result_type = TypeInfo::Smi();
- break;
- case Token::SAR:
- case Token::SHL:
- // Result is always a smi.
- result_type = TypeInfo::Smi();
- break;
- case Token::SHR:
- // Result of x >>> y is always a smi if masked y >= 1, otherwise a number.
- result_type = (right.is_constant() && right.handle()->IsSmi()
- && (Smi::cast(*right.handle())->value() & 0x1F) >= 1)
- ? TypeInfo::Smi()
- : TypeInfo::Number();
- break;
- case Token::ADD:
- if (operands_type.IsNumber()) {
- result_type = TypeInfo::Number();
- } else if (operands_type.IsString()) {
- result_type = TypeInfo::String();
- } else {
- result_type = TypeInfo::Unknown();
- }
- break;
- case Token::SUB:
- case Token::MUL:
- case Token::DIV:
- case Token::MOD:
- // Result is always a number.
- result_type = TypeInfo::Number();
- break;
- default:
- UNREACHABLE();
- }
answer.set_type_info(result_type);
frame_->Push(&answer);
}