Fix fuzzer-found error where left and right were the same register in bitops.
authorerik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 10 Aug 2010 12:30:14 +0000 (12:30 +0000)
committererik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 10 Aug 2010 12:30:14 +0000 (12:30 +0000)
Review URL: http://codereview.chromium.org/3115004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5231 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/ia32/codegen-ia32.cc
src/ia32/virtual-frame-ia32.h
test/mjsunit/regress/bitops-register-alias.js [new file with mode: 0644]

index e557138..021f038 100644 (file)
@@ -1055,6 +1055,7 @@ class DeferredInlineBinaryOperation: public DeferredCode {
       : op_(op), dst_(dst), left_(left), right_(right),
         left_info_(left_info), right_info_(right_info), mode_(mode) {
     set_comment("[ DeferredInlineBinaryOperation");
+    ASSERT(!left.is(right));
   }
 
   virtual void Generate();
@@ -1844,16 +1845,15 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr,
     frame_->Spill(eax);
     frame_->Spill(edx);
     // DeferredInlineBinaryOperation requires all the registers that it is
-    // told about to be spilled.
-    frame_->Spill(left->reg());
-    frame_->Spill(right->reg());
+    // told about to be spilled and distinct.
+    Result distinct_right = frame_->MakeDistinctAndSpilled(left, right);
 
     // Check that left and right are smi tagged.
     DeferredInlineBinaryOperation* deferred =
         new DeferredInlineBinaryOperation(op,
                                           (op == Token::DIV) ? eax : edx,
                                           left->reg(),
-                                          right->reg(),
+                                          distinct_right.reg(),
                                           left_type_info,
                                           right_type_info,
                                           overwrite_mode);
@@ -1946,7 +1946,8 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr,
     // We will modify right, it must be spilled.
     frame_->Spill(ecx);
     // DeferredInlineBinaryOperation requires all the registers that it is told
-    // about to be spilled.
+    // about to be spilled and distinct.  We know that right is ecx and left is
+    // not ecx.
     frame_->Spill(left->reg());
 
     // Use a fresh answer register to avoid spilling the left operand.
@@ -2021,8 +2022,7 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr,
   right->ToRegister();
   // DeferredInlineBinaryOperation requires all the registers that it is told
   // about to be spilled.
-  frame_->Spill(left->reg());
-  frame_->Spill(right->reg());
+  Result distinct_right = frame_->MakeDistinctAndSpilled(left, right);
   // A newly allocated register answer is used to hold the answer.  The
   // registers containing left and right are not modified so they don't
   // need to be spilled in the fast case.
@@ -2034,7 +2034,7 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr,
       new DeferredInlineBinaryOperation(op,
                                         answer.reg(),
                                         left->reg(),
-                                        right->reg(),
+                                        distinct_right.reg(),
                                         left_type_info,
                                         right_type_info,
                                         overwrite_mode);
index e00626b..b9faa46 100644 (file)
@@ -139,6 +139,22 @@ class VirtualFrame: public ZoneObject {
     if (is_used(reg)) SpillElementAt(register_location(reg));
   }
 
+  // Make the two registers distinct and spill them.  Returns the second
+  // register.  If the registers were not distinct then it returns the new
+  // second register.
+  Result MakeDistinctAndSpilled(Result* left, Result* right) {
+    Spill(left->reg());
+    Spill(right->reg());
+    if (left->reg().is(right->reg())) {
+      RegisterAllocator* allocator = cgen()->allocator();
+      Result fresh = allocator->Allocate();
+      ASSERT(fresh.is_valid());
+      masm()->mov(fresh.reg(), right->reg());
+      return fresh;
+    }
+    return *right;
+  }
+
   // Spill all occurrences of an arbitrary register if possible.  Return the
   // register spilled or no_reg if it was not possible to free any register
   // (ie, they all have frame-external references).
diff --git a/test/mjsunit/regress/bitops-register-alias.js b/test/mjsunit/regress/bitops-register-alias.js
new file mode 100644 (file)
index 0000000..389255d
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that the code generator can cope with left and right being in
+// the same register for bitops.
+function f() { for (var i = 10; i < 100; i++) { return i | i; } }
+assertEquals(10, f());