Commit 8bb47c19 authored by whesse@chromium.org's avatar whesse@chromium.org

Use static type information when creating the inlined code for comparison operators.

Review URL: http://codereview.chromium.org/3017025

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5123 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 7d5038a3
......@@ -1445,6 +1445,51 @@ bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) {
}
void CodeGenerator::JumpIfBothSmiUsingTypeInfo(Register left,
Register right,
TypeInfo left_info,
TypeInfo right_info,
JumpTarget* both_smi) {
if (left_info.IsDouble() || left_info.IsString() ||
right_info.IsDouble() || right_info.IsString()) {
// We know that left and right are not both smi. Don't do any tests.
return;
}
if (left.is(right)) {
if (!left_info.IsSmi()) {
__ test(left, Immediate(kSmiTagMask));
both_smi->Branch(zero);
} else {
if (FLAG_debug_code) __ AbortIfNotSmi(left);
both_smi->Jump();
}
} else if (!left_info.IsSmi()) {
if (!right_info.IsSmi()) {
Result temp = allocator_->Allocate();
ASSERT(temp.is_valid());
__ mov(temp.reg(), left);
__ or_(temp.reg(), Operand(right));
__ test(temp.reg(), Immediate(kSmiTagMask));
temp.Unuse();
both_smi->Branch(zero);
} else {
__ test(left, Immediate(kSmiTagMask));
both_smi->Branch(zero);
}
} else {
if (FLAG_debug_code) __ AbortIfNotSmi(left);
if (!right_info.IsSmi()) {
__ test(right, Immediate(kSmiTagMask));
both_smi->Branch(zero);
} else {
if (FLAG_debug_code) __ AbortIfNotSmi(right);
both_smi->Jump();
}
}
}
void CodeGenerator::JumpIfNotBothSmiUsingTypeInfo(Register left,
Register right,
Register scratch,
......@@ -2735,42 +2780,46 @@ void CodeGenerator::Comparison(AstNode* node,
Register right_reg = right_side.reg();
// In-line check for comparing two smis.
Result temp = allocator_->Allocate();
ASSERT(temp.is_valid());
__ mov(temp.reg(), left_side.reg());
__ or_(temp.reg(), Operand(right_side.reg()));
__ test(temp.reg(), Immediate(kSmiTagMask));
temp.Unuse();
is_smi.Branch(zero, taken);
JumpIfBothSmiUsingTypeInfo(left_side.reg(), right_side.reg(),
left_side.type_info(), right_side.type_info(),
&is_smi);
// Inline the equality check if both operands can't be a NaN. If both
// objects are the same they are equal.
if (nan_info == kCantBothBeNaN && cc == equal) {
__ cmp(left_side.reg(), Operand(right_side.reg()));
dest->true_target()->Branch(equal);
}
if (has_valid_frame()) {
// Inline the equality check if both operands can't be a NaN. If both
// objects are the same they are equal.
if (nan_info == kCantBothBeNaN && cc == equal) {
__ cmp(left_side.reg(), Operand(right_side.reg()));
dest->true_target()->Branch(equal);
}
// Inlined number comparison:
if (inline_number_compare) {
GenerateInlineNumberComparison(&left_side, &right_side, cc, dest);
}
// Inlined number comparison:
if (inline_number_compare) {
GenerateInlineNumberComparison(&left_side, &right_side, cc, dest);
}
// End of in-line compare, call out to the compare stub. Don't include
// number comparison in the stub if it was inlined.
CompareStub stub(cc, strict, nan_info, !inline_number_compare);
Result answer = frame_->CallStub(&stub, &left_side, &right_side);
__ test(answer.reg(), Operand(answer.reg()));
answer.Unuse();
dest->true_target()->Branch(cc);
dest->false_target()->Jump();
// End of in-line compare, call out to the compare stub. Don't include
// number comparison in the stub if it was inlined.
CompareStub stub(cc, strict, nan_info, !inline_number_compare);
Result answer = frame_->CallStub(&stub, &left_side, &right_side);
__ test(answer.reg(), Operand(answer.reg()));
answer.Unuse();
if (is_smi.is_linked()) {
dest->true_target()->Branch(cc);
dest->false_target()->Jump();
} else {
dest->Split(cc);
}
}
is_smi.Bind();
left_side = Result(left_reg);
right_side = Result(right_reg);
__ cmp(left_side.reg(), Operand(right_side.reg()));
right_side.Unuse();
left_side.Unuse();
dest->Split(cc);
if (is_smi.is_linked()) {
is_smi.Bind();
left_side = Result(left_reg);
right_side = Result(right_reg);
__ cmp(left_side.reg(), Operand(right_side.reg()));
right_side.Unuse();
left_side.Unuse();
dest->Split(cc);
}
}
}
}
......
......@@ -519,6 +519,17 @@ class CodeGenerator: public AstVisitor {
void GenericBinaryOperation(BinaryOperation* expr,
OverwriteMode overwrite_mode);
// Emits code sequence that jumps to a JumpTarget if the inputs
// are both smis. Cannot be in MacroAssembler because it takes
// advantage of TypeInfo to skip unneeded checks.
// Allocates a temporary register, possibly spilling from the frame,
// if it needs to check both left and right.
void JumpIfBothSmiUsingTypeInfo(Register left,
Register right,
TypeInfo left_info,
TypeInfo right_info,
JumpTarget* both_smi);
// Emits code sequence that jumps to deferred code if the inputs
// are not both smis. Cannot be in MacroAssembler because it takes
// advantage of TypeInfo to skip unneeded checks.
......
......@@ -1201,6 +1201,46 @@ bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) {
}
void CodeGenerator::JumpIfBothSmiUsingTypeInfo(Register left,
Register right,
TypeInfo left_info,
TypeInfo right_info,
JumpTarget* both_smi) {
if (left_info.IsDouble() || left_info.IsString() ||
right_info.IsDouble() || right_info.IsString()) {
// We know that left and right are not both smi. Don't do any tests.
return;
}
if (left.is(right)) {
if (!left_info.IsSmi()) {
Condition is_smi = masm()->CheckSmi(left);
both_smi->Branch(is_smi);
} else {
if (FLAG_debug_code) __ AbortIfNotSmi(left);
both_smi->Jump();
}
} else if (!left_info.IsSmi()) {
if (!right_info.IsSmi()) {
Condition is_smi = masm()->CheckBothSmi(left, right);
both_smi->Branch(is_smi);
} else {
Condition is_smi = masm()->CheckSmi(left);
both_smi->Branch(is_smi);
}
} else {
if (FLAG_debug_code) __ AbortIfNotSmi(left);
if (!right_info.IsSmi()) {
Condition is_smi = masm()->CheckSmi(right);
both_smi->Branch(is_smi);
} else {
if (FLAG_debug_code) __ AbortIfNotSmi(right);
both_smi->Jump();
}
}
}
void CodeGenerator::JumpIfNotSmiUsingTypeInfo(Register reg,
TypeInfo type,
DeferredCode* deferred) {
......@@ -2242,37 +2282,47 @@ void CodeGenerator::Comparison(AstNode* node,
Register left_reg = left_side.reg();
Register right_reg = right_side.reg();
Condition both_smi = masm_->CheckBothSmi(left_reg, right_reg);
is_smi.Branch(both_smi);
// In-line check for comparing two smis.
JumpIfBothSmiUsingTypeInfo(left_side.reg(), right_side.reg(),
left_side.type_info(), right_side.type_info(),
&is_smi);
// Inline the equality check if both operands can't be a NaN. If both
// objects are the same they are equal.
if (nan_info == kCantBothBeNaN && cc == equal) {
__ cmpq(left_side.reg(), right_side.reg());
dest->true_target()->Branch(equal);
}
if (has_valid_frame()) {
// Inline the equality check if both operands can't be a NaN. If both
// objects are the same they are equal.
if (nan_info == kCantBothBeNaN && cc == equal) {
__ cmpq(left_side.reg(), right_side.reg());
dest->true_target()->Branch(equal);
}
// Inlined number comparison:
if (inline_number_compare) {
GenerateInlineNumberComparison(&left_side, &right_side, cc, dest);
}
// Inlined number comparison:
if (inline_number_compare) {
GenerateInlineNumberComparison(&left_side, &right_side, cc, dest);
}
// End of in-line compare, call out to the compare stub. Don't include
// number comparison in the stub if it was inlined.
CompareStub stub(cc, strict, nan_info, !inline_number_compare);
Result answer = frame_->CallStub(&stub, &left_side, &right_side);
__ testq(answer.reg(), answer.reg()); // Sets both zero and sign flags.
answer.Unuse();
dest->true_target()->Branch(cc);
dest->false_target()->Jump();
// End of in-line compare, call out to the compare stub. Don't include
// number comparison in the stub if it was inlined.
CompareStub stub(cc, strict, nan_info, !inline_number_compare);
Result answer = frame_->CallStub(&stub, &left_side, &right_side);
__ testq(answer.reg(), answer.reg()); // Sets both zero and sign flags.
answer.Unuse();
if (is_smi.is_linked()) {
dest->true_target()->Branch(cc);
dest->false_target()->Jump();
} else {
dest->Split(cc);
}
}
is_smi.Bind();
left_side = Result(left_reg);
right_side = Result(right_reg);
__ SmiCompare(left_side.reg(), right_side.reg());
right_side.Unuse();
left_side.Unuse();
dest->Split(cc);
if (is_smi.is_linked()) {
is_smi.Bind();
left_side = Result(left_reg);
right_side = Result(right_reg);
__ SmiCompare(left_side.reg(), right_side.reg());
right_side.Unuse();
left_side.Unuse();
dest->Split(cc);
}
}
}
}
......
......@@ -492,6 +492,15 @@ class CodeGenerator: public AstVisitor {
void GenericBinaryOperation(BinaryOperation* expr,
OverwriteMode overwrite_mode);
// Emits code sequence that jumps to a JumpTarget if the inputs
// are both smis. Cannot be in MacroAssembler because it takes
// advantage of TypeInfo to skip unneeded checks.
void JumpIfBothSmiUsingTypeInfo(Register left,
Register right,
TypeInfo left_info,
TypeInfo right_info,
JumpTarget* both_smi);
// Emits code sequence that jumps to deferred code if the input
// is not a smi. Cannot be in MacroAssembler because it takes
// advantage of TypeInfo to skip unneeded checks.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment