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

Reply via email to