Compute static type information for remaining expression types on x64 platform.
Review URL: http://codereview.chromium.org/1751008 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4481 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
931f0a031a
commit
07f68ec357
@ -7047,6 +7047,12 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
|
|||||||
(node->expression()->AsBinaryOperation() != NULL &&
|
(node->expression()->AsBinaryOperation() != NULL &&
|
||||||
node->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
|
node->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
case Token::NOT:
|
||||||
|
case Token::DELETE:
|
||||||
|
case Token::TYPEOF:
|
||||||
|
UNREACHABLE(); // handled above
|
||||||
|
break;
|
||||||
|
|
||||||
case Token::SUB: {
|
case Token::SUB: {
|
||||||
GenericUnaryOpStub stub(Token::SUB, overwrite);
|
GenericUnaryOpStub stub(Token::SUB, overwrite);
|
||||||
Result operand = frame_->Pop();
|
Result operand = frame_->Pop();
|
||||||
@ -7087,11 +7093,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
|
|||||||
__ not_(answer.reg());
|
__ not_(answer.reg());
|
||||||
|
|
||||||
continue_label.Bind(&answer);
|
continue_label.Bind(&answer);
|
||||||
if (operand_info.IsInteger32()) {
|
answer.set_type_info(TypeInfo::Integer32());
|
||||||
answer.set_type_info(TypeInfo::Integer32());
|
|
||||||
} else {
|
|
||||||
answer.set_type_info(TypeInfo::Number());
|
|
||||||
}
|
|
||||||
frame_->Push(&answer);
|
frame_->Push(&answer);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -7121,8 +7123,6 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
// NOT, DELETE, TYPEOF, and VOID are handled outside the
|
|
||||||
// switch.
|
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7333,7 +7333,7 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) {
|
|||||||
__ setcc(overflow, tmp.reg());
|
__ setcc(overflow, tmp.reg());
|
||||||
__ or_(Operand(tmp.reg()), new_value.reg());
|
__ or_(Operand(tmp.reg()), new_value.reg());
|
||||||
__ test(tmp.reg(), Immediate(kSmiTagMask));
|
__ test(tmp.reg(), Immediate(kSmiTagMask));
|
||||||
tmp.Unuse();
|
tmp.Unusec();
|
||||||
deferred->Branch(not_zero);
|
deferred->Branch(not_zero);
|
||||||
} else {
|
} else {
|
||||||
// Otherwise we test separately for overflow and smi tag.
|
// Otherwise we test separately for overflow and smi tag.
|
||||||
|
@ -3117,6 +3117,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
|
|||||||
GenericUnaryOpStub stub(Token::SUB, overwrite);
|
GenericUnaryOpStub stub(Token::SUB, overwrite);
|
||||||
Result operand = frame_->Pop();
|
Result operand = frame_->Pop();
|
||||||
Result answer = frame_->CallStub(&stub, &operand);
|
Result answer = frame_->CallStub(&stub, &operand);
|
||||||
|
answer.set_type_info(TypeInfo::Number());
|
||||||
frame_->Push(&answer);
|
frame_->Push(&answer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3140,6 +3141,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
|
|||||||
frame_->Spill(answer.reg());
|
frame_->Spill(answer.reg());
|
||||||
__ SmiNot(answer.reg(), answer.reg());
|
__ SmiNot(answer.reg(), answer.reg());
|
||||||
continue_label.Bind(&answer);
|
continue_label.Bind(&answer);
|
||||||
|
answer.set_type_info(TypeInfo::Smi());
|
||||||
frame_->Push(&answer);
|
frame_->Push(&answer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3148,6 +3150,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
|
|||||||
// Smi check.
|
// Smi check.
|
||||||
JumpTarget continue_label;
|
JumpTarget continue_label;
|
||||||
Result operand = frame_->Pop();
|
Result operand = frame_->Pop();
|
||||||
|
TypeInfo operand_info = operand.type_info();
|
||||||
operand.ToRegister();
|
operand.ToRegister();
|
||||||
Condition is_smi = masm_->CheckSmi(operand.reg());
|
Condition is_smi = masm_->CheckSmi(operand.reg());
|
||||||
continue_label.Branch(is_smi, &operand);
|
continue_label.Branch(is_smi, &operand);
|
||||||
@ -3156,10 +3159,16 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
|
|||||||
CALL_FUNCTION, 1);
|
CALL_FUNCTION, 1);
|
||||||
|
|
||||||
continue_label.Bind(&answer);
|
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);
|
frame_->Push(&answer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
@ -5720,6 +5729,57 @@ void DeferredInlineBinaryOperation::Generate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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,
|
void CodeGenerator::GenericBinaryOperation(Token::Value op,
|
||||||
StaticType* type,
|
StaticType* type,
|
||||||
OverwriteMode overwrite_mode) {
|
OverwriteMode overwrite_mode) {
|
||||||
@ -5785,6 +5845,8 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
|
|||||||
TypeInfo operands_type =
|
TypeInfo operands_type =
|
||||||
TypeInfo::Combine(left.type_info(), right.type_info());
|
TypeInfo::Combine(left.type_info(), right.type_info());
|
||||||
|
|
||||||
|
TypeInfo result_type = CalculateTypeInfo(operands_type, op, right, left);
|
||||||
|
|
||||||
Result answer;
|
Result answer;
|
||||||
if (left_is_non_smi_constant || right_is_non_smi_constant) {
|
if (left_is_non_smi_constant || right_is_non_smi_constant) {
|
||||||
GenericBinaryOpStub stub(op,
|
GenericBinaryOpStub stub(op,
|
||||||
@ -5815,56 +5877,6 @@ void CodeGenerator::GenericBinaryOperation(Token::Value 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);
|
answer.set_type_info(result_type);
|
||||||
frame_->Push(&answer);
|
frame_->Push(&answer);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user