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) {
// 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));
}
}
+// 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);
F(NumberToInteger, 1) \
F(NumberToJSUint32, 1) \
F(NumberToJSInt32, 1) \
+ F(NumberToSmi, 1) \
\
/* Arithmetic operations */ \
F(NumberAdd, 2) \
--- /dev/null
+// 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");
+})();
+
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");
+