Revision: 5123
Author: [email protected]
Date: Fri Jul 23 02:05:46 2010
Log: Use static type information when creating the inlined code for
comparison operators.
Review URL: http://codereview.chromium.org/3017025
http://code.google.com/p/v8/source/detail?r=5123
Modified:
/branches/bleeding_edge/src/ia32/codegen-ia32.cc
/branches/bleeding_edge/src/ia32/codegen-ia32.h
/branches/bleeding_edge/src/x64/codegen-x64.cc
/branches/bleeding_edge/src/x64/codegen-x64.h
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Jul 23 01:25:48
2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Jul 23 02:05:46
2010
@@ -1443,6 +1443,51 @@
frame_->Push(Handle<Object>(answer_object));
return true;
}
+
+
+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,
@@ -2735,42 +2780,46 @@
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);
-
- // 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);
+ JumpIfBothSmiUsingTypeInfo(left_side.reg(), right_side.reg(),
+ left_side.type_info(),
right_side.type_info(),
+ &is_smi);
+
+ 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);
+ }
+
+ // 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);
+ }
}
- // 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();
-
- 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);
+ }
}
}
}
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.h Fri Jul 16 04:21:08 2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.h Fri Jul 23 02:05:46 2010
@@ -519,6 +519,17 @@
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.
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc Fri Jul 23 01:25:48 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc Fri Jul 23 02:05:46 2010
@@ -1199,6 +1199,46 @@
frame_->Push(Handle<Object>(answer_object));
return true;
}
+
+
+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,
@@ -2242,37 +2282,47 @@
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);
-
- // 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);
+ // In-line check for comparing two smis.
+ JumpIfBothSmiUsingTypeInfo(left_side.reg(), right_side.reg(),
+ left_side.type_info(),
right_side.type_info(),
+ &is_smi);
+
+ 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);
+ }
+
+ // 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);
+ }
}
- // 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();
-
- 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);
+ }
}
}
}
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.h Wed Jul 21 04:52:57 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.h Fri Jul 23 02:05:46 2010
@@ -492,6 +492,15 @@
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.
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev