From: erik.corry@gmail.com Date: Tue, 10 Aug 2010 12:30:14 +0000 (+0000) Subject: Fix fuzzer-found error where left and right were the same register in bitops. X-Git-Tag: upstream/4.7.83~21387 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bdfdf8bee97ccdc993c1aa706ab4bfc0572b7ab2;p=platform%2Fupstream%2Fv8.git Fix fuzzer-found error where left and right were the same register in bitops. Review URL: http://codereview.chromium.org/3115004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5231 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index e557138..021f038 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -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); diff --git a/src/ia32/virtual-frame-ia32.h b/src/ia32/virtual-frame-ia32.h index e00626b..b9faa46 100644 --- a/src/ia32/virtual-frame-ia32.h +++ b/src/ia32/virtual-frame-ia32.h @@ -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 index 0000000..389255d --- /dev/null +++ b/test/mjsunit/regress/bitops-register-alias.js @@ -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());