Fix: make string indexing work with Infinity.
NumberToUint32 that I was trying to use maps -0 to +0 (as desired) but also maps +/-Infinity to +0, which made +/-Infinity a valid string index. I fixed it by introducing a new runtime function with the right semantics. TEST=LayoutTests/fast/js/char-at.html,mjsunit/string-charat.js Review URL: http://codereview.chromium.org/2223003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4734 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
ad0e38909f
commit
64bc39a726
@ -9284,11 +9284,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
__ Push(object_, index_, result_);
|
||||
__ push(index_); // Consumed by runtime conversion function.
|
||||
if (index_flags_ == STRING_INDEX_IS_NUMBER) {
|
||||
// Strictly speaking, NumberToInteger should be called here, but
|
||||
// our string lengths don't exceed 32 bits and using ToUint32 maps
|
||||
// -0 to 0, which is what is required by the spec when accessing
|
||||
// strings.
|
||||
__ CallRuntime(Runtime::kNumberToJSUint32, 1);
|
||||
__ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
|
||||
} else {
|
||||
ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
|
||||
// NumberToSmi discards numbers that are not exact integers.
|
||||
|
@ -12655,11 +12655,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
__ push(result_);
|
||||
__ push(index_); // Consumed by runtime conversion function.
|
||||
if (index_flags_ == STRING_INDEX_IS_NUMBER) {
|
||||
// Strictly speaking, NumberToInteger should be called here, but
|
||||
// our string lengths don't exceed 32 bits and using ToUint32 maps
|
||||
// -0 to 0, which is what is required by the spec when accessing
|
||||
// strings.
|
||||
__ CallRuntime(Runtime::kNumberToJSUint32, 1);
|
||||
__ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
|
||||
} else {
|
||||
ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
|
||||
// NumberToSmi discards numbers that are not exact integers.
|
||||
|
@ -5287,6 +5287,25 @@ static Object* Runtime_NumberToInteger(Arguments args) {
|
||||
}
|
||||
|
||||
|
||||
static Object* Runtime_NumberToIntegerMapMinusZero(Arguments args) {
|
||||
NoHandleAllocation ha;
|
||||
ASSERT(args.length() == 1);
|
||||
|
||||
CONVERT_DOUBLE_CHECKED(number, args[0]);
|
||||
|
||||
// We do not include 0 so that we don't have to treat +0 / -0 cases.
|
||||
if (number > 0 && number <= Smi::kMaxValue) {
|
||||
return Smi::FromInt(static_cast<int>(number));
|
||||
}
|
||||
|
||||
double double_value = DoubleToInteger(number);
|
||||
// Map both -0 and +0 to +0.
|
||||
if (double_value == 0) double_value = 0;
|
||||
|
||||
return Heap::NumberFromDouble(double_value);
|
||||
}
|
||||
|
||||
|
||||
static Object* Runtime_NumberToJSUint32(Arguments args) {
|
||||
NoHandleAllocation ha;
|
||||
ASSERT(args.length() == 1);
|
||||
|
@ -102,6 +102,7 @@ namespace internal {
|
||||
F(NumberToString, 1, 1) \
|
||||
F(NumberToStringSkipCache, 1, 1) \
|
||||
F(NumberToInteger, 1, 1) \
|
||||
F(NumberToIntegerMapMinusZero, 1, 1) \
|
||||
F(NumberToJSUint32, 1, 1) \
|
||||
F(NumberToJSInt32, 1, 1) \
|
||||
F(NumberToSmi, 1, 1) \
|
||||
|
@ -10935,11 +10935,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
__ push(result_);
|
||||
__ push(index_); // Consumed by runtime conversion function.
|
||||
if (index_flags_ == STRING_INDEX_IS_NUMBER) {
|
||||
// Strictly speaking, NumberToInteger should be called here, but
|
||||
// our string lengths don't exceed 32 bits and using ToUint32 maps
|
||||
// -0 to 0, which is what is required by the spec when accessing
|
||||
// strings.
|
||||
__ CallRuntime(Runtime::kNumberToJSUint32, 1);
|
||||
__ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
|
||||
} else {
|
||||
ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
|
||||
// NumberToSmi discards numbers that are not exact integers.
|
||||
|
@ -41,6 +41,8 @@ function basicTest() {
|
||||
assertEquals("", s.charAt(-1));
|
||||
assertEquals("", s.charAt(4));
|
||||
assertEquals("", s.charAt(slowIndexOutOfRange));
|
||||
assertEquals("", s.charAt(1/0));
|
||||
assertEquals("", s.charAt(-1/0));
|
||||
assertEquals("t", s.charAt(0));
|
||||
assertEquals("t", s.charAt(-0.0));
|
||||
assertEquals("t", s.charAt(0.4));
|
||||
@ -67,6 +69,8 @@ function basicTest() {
|
||||
assertTrue(isNaN(s.charCodeAt(-1)));
|
||||
assertTrue(isNaN(s.charCodeAt(4)));
|
||||
assertTrue(isNaN(s.charCodeAt(slowIndexOutOfRange)));
|
||||
assertTrue(isNaN(s.charCodeAt(1/0)));
|
||||
assertTrue(isNaN(s.charCodeAt(-1/0)));
|
||||
}
|
||||
basicTest();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user