If a HeapNumber is the incoming value, it must be converted to Smi before

checking. This is not done in a fast way.


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@679 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
lrn@chromium.org 2008-11-03 13:33:13 +00:00
parent c390485090
commit 4e3bbd8247
6 changed files with 139 additions and 2 deletions

View File

@ -1247,6 +1247,19 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable(
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) {

View File

@ -1623,9 +1623,24 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable(
// 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));
}

View File

@ -2587,6 +2587,26 @@ static Object* Runtime_NumberToJSInt32(Arguments args) {
}
// 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);

View File

@ -84,6 +84,7 @@ namespace v8 { namespace internal {
F(NumberToInteger, 1) \
F(NumberToJSUint32, 1) \
F(NumberToJSInt32, 1) \
F(NumberToSmi, 1) \
\
/* Arithmetic operations */ \
F(NumberAdd, 2) \

View File

@ -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");
})();

View File

@ -224,4 +224,46 @@ assertEquals(2016, f6(64), "largeSwitch.64");
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");