Revision: 17166
Author:   [email protected]
Date:     Fri Oct 11 15:13:12 2013 UTC
Log:      Truncate booleans to 0/1 in truncating t-to-i.

Thanks to [email protected] for discovering the issue.

BUG=
[email protected]

Review URL: https://codereview.chromium.org/26824002
http://code.google.com/p/v8/source/detail?r=17166

Added:
 /branches/bleeding_edge/test/mjsunit/bitwise-operations-bools.js
Modified:
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/code-stubs.cc
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/bitwise-operations-bools.js Fri Oct 11 15:13:12 2013 UTC
@@ -0,0 +1,94 @@
+// Copyright 2013 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 bitwise operations with booleans.
+
+var t = 1;
+
+function testFalseLeftHandSide() {
+  var b;
+  if (t) b = false;
+  assertEquals(b | 1, 1);
+  assertEquals(b & 1, 0);
+  assertEquals(b ^ 1, 1);
+  assertEquals(b << 1, 0);
+  assertEquals(b >> 1, 0);
+  assertEquals(b >>> 1, 0);
+}
+
+function testFalseRightHandSide() {
+  if (t) b = false;
+  assertEquals(1 |   b, 1);
+  assertEquals(1 &   b, 0);
+  assertEquals(1 ^   b, 1);
+  assertEquals(1 <<  b, 1);
+  assertEquals(1 >>  b, 1);
+  assertEquals(1 >>> b, 1);
+}
+
+function testTrueLeftHandSide() {
+  if (t) b = true;
+  assertEquals(b | 1, 1);
+  assertEquals(b & 1, 1);
+  assertEquals(b ^ 1, 0);
+  assertEquals(b << 1, 2);
+  assertEquals(b >> 1, 0);
+  assertEquals(b >>> 1, 0);
+}
+
+function testTrueRightHandSide() {
+  if (t) b = true;
+  assertEquals(1 |   b, 1);
+  assertEquals(1 &   b, 1);
+  assertEquals(1 ^   b, 0);
+  assertEquals(1 <<  b, 2);
+  assertEquals(1 >>  b, 0);
+  assertEquals(1 >>> b, 0);
+}
+
+function testBothSides() {
+  if (t) a = true;
+  if (t) b = false;
+  assertEquals(a |   b, 1);
+  assertEquals(a &   b, 0);
+  assertEquals(a ^   b, 1);
+  assertEquals(a <<  b, 1);
+  assertEquals(a >>  b, 1);
+  assertEquals(a >>> b, 1);
+}
+
+
+testFalseLeftHandSide();
+testFalseRightHandSide();
+testTrueLeftHandSide();
+testTrueRightHandSide();
+testFalseLeftHandSide();
+testFalseRightHandSide();
+testTrueLeftHandSide();
+testTrueRightHandSide();
+testBothSides();
+testBothSides();
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Fri Oct 4 19:04:34 2013 UTC +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Fri Oct 11 15:13:12 2013 UTC
@@ -4970,18 +4970,33 @@
   if (instr->truncating()) {
// Performs a truncating conversion of a floating point number as used by
     // the JS bitwise operations.
-    Label heap_number;
-    __ b(eq, &heap_number);
-    // Check for undefined. Undefined is converted to zero for truncating
-    // conversions.
+    Label no_heap_number, check_bools, check_false;
+    __ b(ne, &no_heap_number);
+    __ TruncateHeapNumberToI(input_reg, scratch2);
+    __ b(&done);
+
+ // Check for Oddballs. Undefined/False is converted to zero and True to one
+    // for truncating conversions.
+    __ bind(&no_heap_number);
     __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
     __ cmp(scratch2, Operand(ip));
-    DeoptimizeIf(ne, instr->environment());
+    __ b(ne, &check_bools);
     __ mov(input_reg, Operand::Zero());
     __ b(&done);

-    __ bind(&heap_number);
-    __ TruncateHeapNumberToI(input_reg, scratch2);
+    __ bind(&check_bools);
+    __ LoadRoot(ip, Heap::kTrueValueRootIndex);
+    __ cmp(scratch2, Operand(ip));
+    __ b(ne, &check_false);
+    __ mov(input_reg, Operand(1));
+    __ b(&done);
+
+    __ bind(&check_false);
+    __ LoadRoot(ip, Heap::kFalseValueRootIndex);
+    __ cmp(scratch2, Operand(ip));
+    DeoptimizeIf(ne, instr->environment());
+    __ mov(input_reg, Operand::Zero());
+    __ b(&done);
   } else {
     // Deoptimize if we don't have a heap number.
     DeoptimizeIf(ne, instr->environment());
=======================================
--- /branches/bleeding_edge/src/code-stubs.cc   Thu Oct 10 14:54:31 2013 UTC
+++ /branches/bleeding_edge/src/code-stubs.cc   Fri Oct 11 15:13:12 2013 UTC
@@ -585,9 +585,9 @@

   if (old_state == GetExtraICState()) {
     // Tagged operations can lead to non-truncating HChanges
-    if (left->IsUndefined()) {
+    if (left->IsUndefined() || left->IsBoolean()) {
       left_state_ = GENERIC;
-    } else if (right->IsUndefined()) {
+    } else if (right->IsUndefined() || right->IsBoolean()) {
       right_state_ = GENERIC;
     } else {
       // Since the fpu is to precise, we might bail out on numbers which
@@ -602,14 +602,17 @@

 void BinaryOpStub::UpdateStatus(Handle<Object> object,
                                 State* state) {
+  bool is_truncating = (op_ == Token::BIT_AND || op_ == Token::BIT_OR ||
+                        op_ == Token::BIT_XOR || op_ == Token::SAR ||
+                        op_ == Token::SHL || op_ == Token::SHR);
   v8::internal::TypeInfo type = v8::internal::TypeInfo::FromValue(object);
+  if (object->IsBoolean() && is_truncating) {
+    // Booleans are converted by truncating by HChange.
+    type = TypeInfo::Integer32();
+  }
   if (object->IsUndefined()) {
     // Undefined will be automatically truncated for us by HChange.
-    type = (op_ == Token::BIT_AND || op_ == Token::BIT_OR ||
-            op_ == Token::BIT_XOR || op_ == Token::SAR ||
-            op_ == Token::SHL || op_ == Token::SHR)
-      ? TypeInfo::Integer32()
-      : TypeInfo::Double();
+    type = is_truncating ? TypeInfo::Integer32() : TypeInfo::Double();
   }
   State int_state = SmiValuesAre32Bits() ? NUMBER : INT32;
   State new_state = NONE;
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Fri Oct 4 19:04:34 2013 UTC +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Fri Oct 11 15:13:12 2013 UTC
@@ -5383,25 +5383,36 @@
 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
   Register input_reg = ToRegister(instr->value());

-
   if (instr->truncating()) {
-    Label heap_number, slow_case;
+    Label no_heap_number, check_bools, check_false;

     // Heap number map check.
     __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
            factory()->heap_number_map());
-    __ j(equal, &heap_number, Label::kNear);
+    __ j(not_equal, &no_heap_number, Label::kNear);
+    __ TruncateHeapNumberToI(input_reg, input_reg);
+    __ jmp(done);

-    // Check for undefined. Undefined is converted to zero for truncating
-    // conversions.
+    __ bind(&no_heap_number);
+ // Check for Oddballs. Undefined/False is converted to zero and True to one
+    // for truncating conversions.
     __ cmp(input_reg, factory()->undefined_value());
+    __ j(not_equal, &check_bools, Label::kNear);
+    __ Set(input_reg, Immediate(0));
+    __ jmp(done);
+
+    __ bind(&check_bools);
+    __ cmp(input_reg, factory()->true_value());
+    __ j(not_equal, &check_false, Label::kNear);
+    __ Set(input_reg, Immediate(1));
+    __ jmp(done);
+
+    __ bind(&check_false);
+    __ cmp(input_reg, factory()->false_value());
     __ RecordComment("Deferred TaggedToI: cannot truncate");
     DeoptimizeIf(not_equal, instr->environment());
-    __ mov(input_reg, 0);
+    __ Set(input_reg, Immediate(0));
     __ jmp(done);
-
-    __ bind(&heap_number);
-    __ TruncateHeapNumberToI(input_reg, input_reg);
   } else {
     Label bailout;
     XMMRegister scratch = (instr->temp() != NULL)
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Fri Oct 4 19:04:34 2013 UTC +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Fri Oct 11 15:13:12 2013 UTC
@@ -4612,24 +4612,38 @@


 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
-  Label heap_number;
   Register input_reg = ToRegister(instr->value());

+  if (instr->truncating()) {
+    Label no_heap_number, check_bools, check_false;

-  if (instr->truncating()) {
     // Heap number map check.
     __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
                    Heap::kHeapNumberMapRootIndex);
-    __ j(equal, &heap_number, Label::kNear);
-    // Check for undefined. Undefined is converted to zero for truncating
-    // conversions.
+    __ j(not_equal, &no_heap_number, Label::kNear);
+    __ TruncateHeapNumberToI(input_reg, input_reg);
+    __ jmp(done);
+
+    __ bind(&no_heap_number);
+ // Check for Oddballs. Undefined/False is converted to zero and True to one
+    // for truncating conversions.
     __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
-    DeoptimizeIf(not_equal, instr->environment());
+    __ j(not_equal, &check_bools, Label::kNear);
     __ Set(input_reg, 0);
     __ jmp(done);

-    __ bind(&heap_number);
-    __ TruncateHeapNumberToI(input_reg, input_reg);
+    __ bind(&check_bools);
+    __ CompareRoot(input_reg, Heap::kTrueValueRootIndex);
+    __ j(not_equal, &check_false, Label::kNear);
+    __ Set(input_reg, 1);
+    __ jmp(done);
+
+    __ bind(&check_false);
+    __ CompareRoot(input_reg, Heap::kFalseValueRootIndex);
+    __ RecordComment("Deferred TaggedToI: cannot truncate");
+    DeoptimizeIf(not_equal, instr->environment());
+    __ Set(input_reg, 0);
+    __ jmp(done);
   } else {
     Label bailout;
     XMMRegister xmm_temp = ToDoubleRegister(instr->temp());

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to