| Index: src/x64/codegen-x64.cc
|
| ===================================================================
|
| --- src/x64/codegen-x64.cc (revision 4480)
|
| +++ src/x64/codegen-x64.cc (working copy)
|
| @@ -3117,6 +3117,7 @@
|
| 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;
|
| }
|
| @@ -3140,6 +3141,7 @@
|
| frame_->Spill(answer.reg());
|
| __ SmiNot(answer.reg(), answer.reg());
|
| continue_label.Bind(&answer);
|
| + answer.set_type_info(TypeInfo::Smi());
|
| frame_->Push(&answer);
|
| break;
|
| }
|
| @@ -3148,6 +3150,7 @@
|
| // 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);
|
| @@ -3156,10 +3159,16 @@
|
| 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();
|
| }
|
| @@ -5720,6 +5729,57 @@
|
| }
|
|
|
|
|
| +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) {
|
| @@ -5785,6 +5845,8 @@
|
| 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,
|
| @@ -5815,56 +5877,6 @@
|
| }
|
| }
|
|
|
| - // 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);
|
| }
|
|
|