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:
parent
c390485090
commit
4e3bbd8247
@ -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) {
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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) \
|
||||
|
46
test/mjsunit/regress/regress-137.js
Normal file
46
test/mjsunit/regress/regress-137.js
Normal 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");
|
||||
})();
|
||||
|
@ -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");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user