Fix error in static type information computation for bitwise shift.
authorwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 22 Apr 2010 09:02:10 +0000 (09:02 +0000)
committerwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 22 Apr 2010 09:02:10 +0000 (09:02 +0000)
Review URL: http://codereview.chromium.org/1756007

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

src/ia32/codegen-ia32.cc
src/x64/codegen-x64.cc
test/mjsunit/smi-ops.js

index 0ffe29a..95dbcd4 100644 (file)
@@ -1180,16 +1180,23 @@ static TypeInfo CalculateTypeInfo(TypeInfo operands_type,
     case Token::SAR:
       if (left.is_smi()) return TypeInfo::Smi();
       // Result is a smi if we shift by a constant >= 1, otherwise an integer32.
+      // Shift amount is masked with 0x1F (ECMA standard 11.7.2).
       return (right.is_constant() && right.handle()->IsSmi()
-                     && Smi::cast(*right.handle())->value() >= 1)
+              && (Smi::cast(*right.handle())->value() & 0x1F)  >= 1)
           ? TypeInfo::Smi()
           : TypeInfo::Integer32();
     case Token::SHR:
-      // Result is a smi if we shift by a constant >= 2, otherwise an integer32.
-      return (right.is_constant() && right.handle()->IsSmi()
-                     && Smi::cast(*right.handle())->value() >= 2)
-          ? TypeInfo::Smi()
-          : TypeInfo::Integer32();
+      // Result is a smi if we shift by a constant >= 2, an integer32 if
+      // we shift by 1, and an unsigned 32-bit integer if we shift by 0.
+      if (right.is_constant() && right.handle()->IsSmi()) {
+        int shift_amount = Smi::cast(*right.handle())->value() & 0x1F;
+        if (shift_amount > 1) {
+          return TypeInfo::Smi();
+        } else if (shift_amount > 0) {
+          return TypeInfo::Integer32();
+        }
+      }
+      return TypeInfo::Number();
     case Token::ADD:
       if (operands_type.IsSmi()) {
         // The Integer32 range is big enough to take the sum of any two Smis.
index d14b390..4fac89a 100644 (file)
@@ -5840,9 +5840,9 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
       result_type = TypeInfo::Smi();
       break;
     case Token::SHR:
-      // Result of x >>> y is always a smi if y >= 1, otherwise a number.
+      // Result of x >>> y is always a smi if masked y >= 1, otherwise a number.
       result_type = (right.is_constant() && right.handle()->IsSmi()
-                     && Smi::cast(*right.handle())->value() >= 1)
+                     && (Smi::cast(*right.handle())->value() & 0x1F) >= 1)
           ? TypeInfo::Smi()
           : TypeInfo::Number();
       break;
index 39b4894..9f18790 100644 (file)
@@ -669,3 +669,12 @@ intConversion();
 function shiftByZero(n) { return n << 0; }
 
 assertEquals(3, shiftByZero(3.1415));
+
+// Verify that the static type information of x >>> 32 is computed correctly.
+function LogicalShiftRightByMultipleOf32(x) {
+  x = x >>> 32;
+  return x + x;
+}
+
+assertEquals(4589934592, LogicalShiftRightByMultipleOf32(-2000000000));
+assertEquals(4589934592, LogicalShiftRightByMultipleOf32(-2000000000));