Author: [EMAIL PROTECTED]
Date: Mon Nov  3 05:33:13 2008
New Revision: 679

Added:
    branches/bleeding_edge/test/mjsunit/regress/regress-137.js
Modified:
    branches/bleeding_edge/src/codegen-arm.cc
    branches/bleeding_edge/src/codegen-ia32.cc
    branches/bleeding_edge/src/runtime.cc
    branches/bleeding_edge/src/runtime.h
    branches/bleeding_edge/test/mjsunit/switch.js

Log:
If a HeapNumber is the incoming value, it must be converted to Smi before
checking. This is not done in a fast way.


Modified: branches/bleeding_edge/src/codegen-arm.cc
==============================================================================
--- branches/bleeding_edge/src/codegen-arm.cc   (original)
+++ branches/bleeding_edge/src/codegen-arm.cc   Mon Nov  3 05:33:13 2008
@@ -1247,6 +1247,19 @@
    ASSERT(kSmiTag == 0 && kSmiTagSize <= 2);

    __ pop(r0);
+
+  // Test for a Smi value in a HeapNumber.
+  Label is_smi;
+  __ tst(r0, Operand(kSmiTagMask));
+  __ b(eq, &is_smi);
+  __ ldr(r1, MemOperand(r0, HeapObject::kMapOffset - kHeapObjectTag));
+  __ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag));
+  __ cmp(r1, Operand(HEAP_NUMBER_TYPE));
+  __ b(ne, fail_label);
+  __ push(r0);
+  __ CallRuntime(Runtime::kNumberToSmi, 1);
+  __ bind(&is_smi);
+
    if (min_index != 0) {
      // small positive numbers can be immediate operands.
      if (min_index < 0) {

Modified: branches/bleeding_edge/src/codegen-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/codegen-ia32.cc  (original)
+++ branches/bleeding_edge/src/codegen-ia32.cc  Mon Nov  3 05:33:13 2008
@@ -1623,9 +1623,24 @@
    // placeholders, and fill in the addresses after the labels have been
    // bound.

-  frame_->Pop(eax);  // supposed smi
+  frame_->Pop(eax);  // supposed Smi
    // check range of value, if outside [0..length-1] jump to default/end  
label.
    ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
+
+  // Test whether input is a HeapNumber that is really a Smi
+  Label is_smi;
+  __ test(eax, Immediate(kSmiTagMask));
+  __ j(equal, &is_smi);
+  // It's a heap object, not a Smi or a Failure
+  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
+  __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
+  __ cmp(ebx, HEAP_NUMBER_TYPE);
+  __ j(not_equal, fail_label);
+  // eax points to a heap number.
+  __ push(eax);
+  __ CallRuntime(Runtime::kNumberToSmi, 1);
+  __ bind(&is_smi);
+
    if (min_index != 0) {
      __ sub(Operand(eax), Immediate(min_index << kSmiTagSize));
    }

Modified: branches/bleeding_edge/src/runtime.cc
==============================================================================
--- branches/bleeding_edge/src/runtime.cc       (original)
+++ branches/bleeding_edge/src/runtime.cc       Mon Nov  3 05:33:13 2008
@@ -2587,6 +2587,26 @@
  }


+// Converts a Number to a Smi, if possible. Returns NaN if the number is  
not
+// a small integer.
+static Object* Runtime_NumberToSmi(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  Object* obj = args[0];
+  if (obj->IsSmi()) {
+    return obj;
+  }
+  if (obj->IsHeapNumber()) {
+    double value = HeapNumber::cast(obj)->value();
+    int int_value = FastD2I(value);
+    if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
+      return Smi::FromInt(int_value);
+    }
+  }
+  return Heap::nan_value();
+}
+
  static Object* Runtime_NumberAdd(Arguments args) {
    NoHandleAllocation ha;
    ASSERT(args.length() == 2);

Modified: branches/bleeding_edge/src/runtime.h
==============================================================================
--- branches/bleeding_edge/src/runtime.h        (original)
+++ branches/bleeding_edge/src/runtime.h        Mon Nov  3 05:33:13 2008
@@ -84,6 +84,7 @@
    F(NumberToInteger, 1) \
    F(NumberToJSUint32, 1) \
    F(NumberToJSInt32, 1) \
+  F(NumberToSmi, 1) \
    \
    /* Arithmetic operations */ \
    F(NumberAdd, 2) \

Added: branches/bleeding_edge/test/mjsunit/regress/regress-137.js
==============================================================================
--- (empty file)
+++ branches/bleeding_edge/test/mjsunit/regress/regress-137.js  Mon Nov  3  
05:33:13 2008
@@ -0,0 +1,46 @@
+// Copyright 2008 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.
+
+// See <URL:http://code.google.com/p/v8/issues/detail?id=137>
+
+(function () {
+  var strNum = 170;
+  var base = strNum / 16;
+  var rem = strNum % 16;
+  var base = base - (rem / 16);  // base is now HeapNumber with valid Smi  
value.
+
+  switch(base) {
+    case 10: return "A";  // Expected result.
+    case 11: return "B";
+    case 12: return "C";
+    case 13: return "D";
+    case 14: return "E";
+    case 15: return "F";  // Enough cases to trigger fast-case Smi switch.
+  };
+  fail("case 10", "Default case", "Heap number not recognized as Smi  
value");
+})();
+

Modified: branches/bleeding_edge/test/mjsunit/switch.js
==============================================================================
--- branches/bleeding_edge/test/mjsunit/switch.js       (original)
+++ branches/bleeding_edge/test/mjsunit/switch.js       Mon Nov  3 05:33:13 2008
@@ -224,4 +224,46 @@
  assertEquals(4032, f6(128), "largeSwitch.128");
  assertEquals(4222, f6(148), "largeSwitch.148");

-
+
+function f7(value) {
+  switch (value) {
+  case 0: return "0";
+  case -0: return "-0";
+  case 1: case 2: case 3: case 4:  // Dummy fillers.
+  }
+  switch (value) {
+  case 0x3fffffff: return "MaxSmi";
+  case 0x3ffffffe:
+  case 0x3ffffffd:
+  case 0x3ffffffc:
+  case 0x3ffffffb:
+  case 0x3ffffffa:  // Dummy fillers
+  }
+  switch (value) {
+  case -0x40000000: return "MinSmi";
+  case -0x3fffffff:
+  case -0x3ffffffe:
+  case -0x3ffffffd:
+  case -0x3ffffffc:
+  case -0x3ffffffb:  // Dummy fillers
+  }
+  switch (value) {
+  case 10: return "A";
+  case 11:
+  case 12:
+  case 13:
+  case 14:
+  case 15:  // Dummy fillers
+  }
+  return "default";
+}
+
+
+assertEquals("default", f7(0.1), "0-1-switch.double-0.1");
+assertEquals("0", f7(-0), "0-1-switch.double-neg0");
+assertEquals("MaxSmi", f7((1<<30)-1), "0-1-switch.maxsmi");
+assertEquals("MinSmi", f7(-(1<<30)), "0-1-switch.minsmi");
+assertEquals("default", f7(1<<30), "0-1-switch.maxsmi++");
+assertEquals("default", f7(-(1<<30)-1), "0-1-switch.minsmi--");
+assertEquals("A", f7((170/16)-(170%16/16)), "0-1-switch.heapnum");
+

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to