Commit 2b0b80d2 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

Reland "Fixes for size_t LookupIterator"

This is a reland of e1ad9b89

Original change's description:
> Fixes for size_t LookupIterator
>
> Fixing some fallout from c968607e
> aka r65078
>
> Bug: chromium:1026729,chromium:1026856,chromium:1026909,chromium:1026974
> Change-Id: I98a4466595fbf1635af403ab58842977882c0453
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1930907
> Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
> Reviewed-by: Toon Verwaest <verwaest@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#65158}

Tbr: verwaest@chromium.org,mstarzinger@chromium.org
Bug: chromium:1026729, chromium:1026856, chromium:1026909, chromium:1026974
Change-Id: I66695f05c4910c46f3c75209e14135075721f2cf
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1932839Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65162}
parent 825f65d3
...@@ -9766,6 +9766,13 @@ TNode<IntPtrT> CodeStubAssembler::TryToIntptr( ...@@ -9766,6 +9766,13 @@ TNode<IntPtrT> CodeStubAssembler::TryToIntptr(
TNode<IntPtrT> int_value = ChangeFloat64ToIntPtr(value); TNode<IntPtrT> int_value = ChangeFloat64ToIntPtr(value);
GotoIfNot(Float64Equal(value, RoundIntPtrToFloat64(int_value)), GotoIfNot(Float64Equal(value, RoundIntPtrToFloat64(int_value)),
if_not_intptr); if_not_intptr);
if (Is64()) {
// TODO(jkummerow): Investigate whether we can drop support for
// negative indices.
GotoIfNot(IsInRange(int_value, static_cast<intptr_t>(-kMaxSafeInteger),
static_cast<intptr_t>(kMaxSafeIntegerUint64)),
if_not_intptr);
}
var_intptr_key = int_value; var_intptr_key = int_value;
Goto(&done); Goto(&done);
} }
......
...@@ -941,6 +941,13 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -941,6 +941,13 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
Int32Constant(higher_limit - lower_limit)); Int32Constant(higher_limit - lower_limit));
} }
TNode<BoolT> IsInRange(TNode<WordT> value, intptr_t lower_limit,
intptr_t higher_limit) {
DCHECK_LE(lower_limit, higher_limit);
return UintPtrLessThanOrEqual(IntPtrSub(value, IntPtrConstant(lower_limit)),
IntPtrConstant(higher_limit - lower_limit));
}
#if DEBUG #if DEBUG
void Bind(Label* label, AssemblerDebugInfo debug_info); void Bind(Label* label, AssemblerDebugInfo debug_info);
#endif // DEBUG #endif // DEBUG
......
...@@ -214,6 +214,8 @@ class EffectControlLinearizer { ...@@ -214,6 +214,8 @@ class EffectControlLinearizer {
Node* BuildCheckedFloat64ToInt64(CheckForMinusZeroMode mode, Node* BuildCheckedFloat64ToInt64(CheckForMinusZeroMode mode,
const FeedbackSource& feedback, Node* value, const FeedbackSource& feedback, Node* value,
Node* frame_state); Node* frame_state);
Node* BuildCheckedFloat64ToIndex(const FeedbackSource& feedback, Node* value,
Node* frame_state);
Node* BuildCheckedHeapNumberOrOddballToFloat64(CheckTaggedInputMode mode, Node* BuildCheckedHeapNumberOrOddballToFloat64(CheckTaggedInputMode mode,
const FeedbackSource& feedback, const FeedbackSource& feedback,
Node* value, Node* value,
...@@ -2429,6 +2431,31 @@ Node* EffectControlLinearizer::BuildCheckedFloat64ToInt32( ...@@ -2429,6 +2431,31 @@ Node* EffectControlLinearizer::BuildCheckedFloat64ToInt32(
return value32; return value32;
} }
Node* EffectControlLinearizer::BuildCheckedFloat64ToIndex(
const FeedbackSource& feedback, Node* value, Node* frame_state) {
if (machine()->Is64()) {
Node* value64 = __ ChangeFloat64ToInt64(value);
Node* check_same = __ Float64Equal(value, __ ChangeInt64ToFloat64(value64));
__ DeoptimizeIfNot(DeoptimizeReason::kLostPrecisionOrNaN, feedback,
check_same, frame_state);
Node* check_max =
__ IntLessThan(value64, __ Int64Constant(kMaxSafeInteger));
__ DeoptimizeIfNot(DeoptimizeReason::kNotAnArrayIndex, feedback, check_max,
frame_state);
Node* check_min =
__ IntLessThan(__ Int64Constant(-kMaxSafeInteger), value64);
__ DeoptimizeIfNot(DeoptimizeReason::kNotAnArrayIndex, feedback, check_min,
frame_state);
return value64;
} else {
Node* value32 = __ RoundFloat64ToInt32(value);
Node* check_same = __ Float64Equal(value, __ ChangeInt32ToFloat64(value32));
__ DeoptimizeIfNot(DeoptimizeReason::kLostPrecisionOrNaN, feedback,
check_same, frame_state);
return value32;
}
}
Node* EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node, Node* EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node,
Node* frame_state) { Node* frame_state) {
const CheckMinusZeroParameters& params = const CheckMinusZeroParameters& params =
...@@ -2500,7 +2527,7 @@ Node* EffectControlLinearizer::LowerCheckedTaggedToArrayIndex( ...@@ -2500,7 +2527,7 @@ Node* EffectControlLinearizer::LowerCheckedTaggedToArrayIndex(
__ Goto(&done, ChangeSmiToIntPtr(value)); __ Goto(&done, ChangeSmiToIntPtr(value));
// In the non-Smi case, check the heap numberness, load the number and convert // In the non-Smi case, check the heap numberness, load the number and convert
// to int32. // to integer.
__ Bind(&if_not_smi); __ Bind(&if_not_smi);
auto if_not_heap_number = __ MakeDeferredLabel(); auto if_not_heap_number = __ MakeDeferredLabel();
Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
...@@ -2508,9 +2535,7 @@ Node* EffectControlLinearizer::LowerCheckedTaggedToArrayIndex( ...@@ -2508,9 +2535,7 @@ Node* EffectControlLinearizer::LowerCheckedTaggedToArrayIndex(
__ GotoIfNot(is_heap_number, &if_not_heap_number); __ GotoIfNot(is_heap_number, &if_not_heap_number);
Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
number = number = BuildCheckedFloat64ToIndex(params.feedback(), number, frame_state);
BuildCheckedFloat64ToInt32(CheckForMinusZeroMode::kDontCheckForMinusZero,
params.feedback(), number, frame_state);
__ Goto(&done, number); __ Goto(&done, number);
__ Bind(&if_not_heap_number); __ Bind(&if_not_heap_number);
......
...@@ -1203,8 +1203,8 @@ KeyType TryConvertKey(Handle<Object> key, Isolate* isolate, intptr_t* index_out, ...@@ -1203,8 +1203,8 @@ KeyType TryConvertKey(Handle<Object> key, Isolate* isolate, intptr_t* index_out,
} }
if (key->IsHeapNumber()) { if (key->IsHeapNumber()) {
double num = HeapNumber::cast(*key).value(); double num = HeapNumber::cast(*key).value();
if (!(num >= std::numeric_limits<intptr_t>::min())) return kBailout; if (!(num >= -kMaxSafeInteger)) return kBailout;
if (num > std::numeric_limits<intptr_t>::max()) return kBailout; if (num > kMaxSafeInteger) return kBailout;
*index_out = static_cast<intptr_t>(num); *index_out = static_cast<intptr_t>(num);
if (*index_out != num) return kBailout; if (*index_out != num) return kBailout;
return kIntPtr; return kIntPtr;
......
...@@ -362,7 +362,7 @@ JsonString JsonParser<Char>::ScanJsonPropertyKey(JsonContinuation* cont) { ...@@ -362,7 +362,7 @@ JsonString JsonParser<Char>::ScanJsonPropertyKey(JsonContinuation* cont) {
uint32_t index = first - '0'; uint32_t index = first - '0';
while (true) { while (true) {
cursor_ = std::find_if(cursor_ + 1, end_, [&index](Char c) { cursor_ = std::find_if(cursor_ + 1, end_, [&index](Char c) {
return !TryAddIndexChar(&index, c); return !TryAddArrayIndexChar(&index, c);
}); });
if (CurrentCharacter() == '"') { if (CurrentCharacter() == '"') {
...@@ -374,7 +374,7 @@ JsonString JsonParser<Char>::ScanJsonPropertyKey(JsonContinuation* cont) { ...@@ -374,7 +374,7 @@ JsonString JsonParser<Char>::ScanJsonPropertyKey(JsonContinuation* cont) {
} }
if (CurrentCharacter() == '\\' && NextCharacter() == 'u') { if (CurrentCharacter() == '\\' && NextCharacter() == 'u') {
if (TryAddIndexChar(&index, ScanUnicodeCharacter())) continue; if (TryAddArrayIndexChar(&index, ScanUnicodeCharacter())) continue;
} }
break; break;
......
...@@ -71,13 +71,18 @@ LookupIterator::LookupIterator(Isolate* isolate, Handle<Object> receiver, ...@@ -71,13 +71,18 @@ LookupIterator::LookupIterator(Isolate* isolate, Handle<Object> receiver,
receiver_(receiver), receiver_(receiver),
initial_holder_(holder), initial_holder_(holder),
index_(index) { index_(index) {
DCHECK_NE(index, kInvalidIndex);
// If we're not looking at a TypedArray, we will need the key represented // If we're not looking at a TypedArray, we will need the key represented
// as an internalized string. // as an internalized string.
if (index_ > JSArray::kMaxArrayIndex && !receiver->IsJSTypedArray()) { if (index_ > JSArray::kMaxArrayIndex && !holder->IsJSTypedArray()) {
if (key_as_string.is_null()) { if (key_as_string.is_null()) {
key_as_string = isolate->factory()->SizeToString(index_); key_as_string = isolate->factory()->SizeToString(index_);
} }
name_ = isolate->factory()->InternalizeName(key_as_string); name_ = isolate->factory()->InternalizeName(key_as_string);
} else if (!key_as_string.is_null() &&
key_as_string->IsInternalizedString()) {
// Even for TypedArrays: if we have a name, keep it. ICs will need it.
name_ = key_as_string;
} }
Start<true>(); Start<true>();
} }
......
...@@ -95,14 +95,13 @@ class Name : public TorqueGeneratedName<Name, PrimitiveHeapObject> { ...@@ -95,14 +95,13 @@ class Name : public TorqueGeneratedName<Name, PrimitiveHeapObject> {
// Maximum number of characters to consider when trying to convert a string // Maximum number of characters to consider when trying to convert a string
// value into an array index. // value into an array index.
static const int kMaxArrayIndexSize = 10; static const int kMaxArrayIndexSize = 10;
// Maximum number of characters that might be parsed into a size_t: // Maximum number of characters in a string that can possibly be an
// 10 characters per 32 bits of size_t width. // "integer index" in the spec sense, i.e. a canonical representation of a
// We choose this as large as possible (rather than MAX_SAFE_INTEGER range) // number in the range up to MAX_SAFE_INTEGER. We parse these into a size_t,
// because TypedArray accesses will treat all string keys that are // so the size of that type also factors in as a limit: 10 characters per
// canonical representations of numbers in the range [MAX_SAFE_INTEGER .. // 32 bits of size_t width.
// size_t::max] as out-of-bounds accesses, and we can handle those in the static const int kMaxIntegerIndexSize =
// fast path if we tag them as such (see kIsNotIntegerIndexMask). std::min(16, int{10 * (sizeof(size_t) / 4)});
static const int kMaxIntegerIndexSize = 10 * (sizeof(size_t) / 4);
// For strings which are array indexes the hash value has the string length // For strings which are array indexes the hash value has the string length
// mixed into the hash, mainly to avoid a hash value of zero which would be // mixed into the hash, mainly to avoid a hash value of zero which would be
......
...@@ -823,9 +823,11 @@ bool Object::ToIntegerIndex(size_t* index) const { ...@@ -823,9 +823,11 @@ bool Object::ToIntegerIndex(size_t* index) const {
if (IsHeapNumber()) { if (IsHeapNumber()) {
double num = HeapNumber::cast(*this).value(); double num = HeapNumber::cast(*this).value();
if (!(num >= 0)) return false; // Negation to catch NaNs. if (!(num >= 0)) return false; // Negation to catch NaNs.
// We must exclude the max size_t, because the LookupIterator uses that constexpr double max =
// as the "invalid index" sentinel. std::min(kMaxSafeInteger,
if (num >= std::numeric_limits<size_t>::max()) return false; // The maximum size_t is reserved as "invalid" sentinel.
static_cast<double>(std::numeric_limits<size_t>::max() - 1));
if (num > max) return false;
size_t result = static_cast<size_t>(num); size_t result = static_cast<size_t>(num);
if (num != result) return false; // Conversion lost fractional precision. if (num != result) return false; // Conversion lost fractional precision.
*index = result; *index = result;
......
...@@ -1397,7 +1397,8 @@ bool String::SlowAsIntegerIndex(size_t* index) { ...@@ -1397,7 +1397,8 @@ bool String::SlowAsIntegerIndex(size_t* index) {
} }
if (length == 0 || length > kMaxIntegerIndexSize) return false; if (length == 0 || length > kMaxIntegerIndexSize) return false;
StringCharacterStream stream(*this); StringCharacterStream stream(*this);
return StringToIndex(&stream, index); return StringToIndex<StringCharacterStream, size_t, kToIntegerIndex>(&stream,
index);
} }
void String::PrintOn(FILE* file) { void String::PrintOn(FILE* file) {
......
...@@ -270,21 +270,23 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) { ...@@ -270,21 +270,23 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
HandleScope scope(isolate); HandleScope scope(isolate);
Handle<Object> property = args.at(1); Handle<Object> property = args.at(1);
// The spec says we must look at the key first, which is why we can't
// use LookupIterator::PropertyOrElement here but have to duplicate its
// functionality instead.
Handle<Name> key; Handle<Name> key;
uint32_t index; size_t index;
bool key_is_array_index = property->ToArrayIndex(&index); bool key_is_index = property->ToIntegerIndex(&index);
if (!key_is_index) {
if (!key_is_array_index) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key, ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
Object::ToName(isolate, property)); Object::ToName(isolate, property));
key_is_array_index = key->AsArrayIndex(&index); key_is_index = key->AsIntegerIndex(&index);
} }
Handle<Object> object = args.at(0); Handle<Object> object = args.at(0);
if (object->IsJSModuleNamespace()) { if (object->IsJSModuleNamespace()) {
if (key.is_null()) { if (key.is_null()) {
DCHECK(key_is_array_index); DCHECK(key_is_index);
// Namespace objects can't have indexed properties. // Namespace objects can't have indexed properties.
return ReadOnlyRoots(isolate).false_value(); return ReadOnlyRoots(isolate).false_value();
} }
...@@ -304,8 +306,8 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) { ...@@ -304,8 +306,8 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
{ {
LookupIterator::Configuration c = LookupIterator::OWN_SKIP_INTERCEPTOR; LookupIterator::Configuration c = LookupIterator::OWN_SKIP_INTERCEPTOR;
LookupIterator it = LookupIterator it =
key_is_array_index ? LookupIterator(isolate, js_obj, index, js_obj, c) key_is_index ? LookupIterator(isolate, js_obj, index, js_obj, c)
: LookupIterator(js_obj, key, js_obj, c); : LookupIterator(js_obj, key, js_obj, c);
Maybe<bool> maybe = JSReceiver::HasProperty(&it); Maybe<bool> maybe = JSReceiver::HasProperty(&it);
if (maybe.IsNothing()) return ReadOnlyRoots(isolate).exception(); if (maybe.IsNothing()) return ReadOnlyRoots(isolate).exception();
DCHECK(!isolate->has_pending_exception()); DCHECK(!isolate->has_pending_exception());
...@@ -314,14 +316,15 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) { ...@@ -314,14 +316,15 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
Map map = js_obj->map(); Map map = js_obj->map();
if (!map.IsJSGlobalProxyMap() && if (!map.IsJSGlobalProxyMap() &&
(key_is_array_index ? !map.has_indexed_interceptor() (key_is_index && index <= JSArray::kMaxArrayIndex
: !map.has_named_interceptor())) { ? !map.has_indexed_interceptor()
: !map.has_named_interceptor())) {
return ReadOnlyRoots(isolate).false_value(); return ReadOnlyRoots(isolate).false_value();
} }
// Slow case. // Slow case.
LookupIterator::Configuration c = LookupIterator::OWN; LookupIterator::Configuration c = LookupIterator::OWN;
LookupIterator it = key_is_array_index LookupIterator it = key_is_index
? LookupIterator(isolate, js_obj, index, js_obj, c) ? LookupIterator(isolate, js_obj, index, js_obj, c)
: LookupIterator(js_obj, key, js_obj, c); : LookupIterator(js_obj, key, js_obj, c);
...@@ -332,10 +335,9 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) { ...@@ -332,10 +335,9 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
} else if (object->IsJSProxy()) { } else if (object->IsJSProxy()) {
if (key.is_null()) { if (key.is_null()) {
DCHECK(key_is_array_index); DCHECK(key_is_index);
key = isolate->factory()->Uint32ToString(index); key = isolate->factory()->SizeToString(index);
} }
Maybe<bool> result = Maybe<bool> result =
JSReceiver::HasOwnProperty(Handle<JSProxy>::cast(object), key); JSReceiver::HasOwnProperty(Handle<JSProxy>::cast(object), key);
if (result.IsNothing()) return ReadOnlyRoots(isolate).exception(); if (result.IsNothing()) return ReadOnlyRoots(isolate).exception();
...@@ -343,8 +345,8 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) { ...@@ -343,8 +345,8 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
} else if (object->IsString()) { } else if (object->IsString()) {
return isolate->heap()->ToBoolean( return isolate->heap()->ToBoolean(
key_is_array_index key_is_index
? index < static_cast<uint32_t>(String::cast(*object).length()) ? index < static_cast<size_t>(String::cast(*object).length())
: key->Equals(ReadOnlyRoots(isolate).length_string())); : key->Equals(ReadOnlyRoots(isolate).length_string()));
} else if (object->IsNullOrUndefined(isolate)) { } else if (object->IsNullOrUndefined(isolate)) {
THROW_NEW_ERROR_RETURN_FAILURE( THROW_NEW_ERROR_RETURN_FAILURE(
......
...@@ -60,16 +60,15 @@ uint32_t StringHasher::HashSequentialString(const char_t* chars_raw, int length, ...@@ -60,16 +60,15 @@ uint32_t StringHasher::HashSequentialString(const char_t* chars_raw, int length,
DCHECK_IMPLIES(0 < length, chars != nullptr); DCHECK_IMPLIES(0 < length, chars != nullptr);
if (length >= 1) { if (length >= 1) {
if (IsDecimalDigit(chars[0]) && (length == 1 || chars[0] != '0')) { if (IsDecimalDigit(chars[0]) && (length == 1 || chars[0] != '0')) {
uint32_t index = 0;
if (length <= String::kMaxArrayIndexSize) { if (length <= String::kMaxArrayIndexSize) {
// Possible array index; try to compute the array index hash. // Possible array index; try to compute the array index hash.
index = chars[0] - '0'; uint32_t index = chars[0] - '0';
int i = 1; int i = 1;
do { do {
if (i == length) { if (i == length) {
return MakeArrayIndexHash(index, length); return MakeArrayIndexHash(index, length);
} }
} while (TryAddIndexChar(&index, chars[i++])); } while (TryAddArrayIndexChar(&index, chars[i++]));
} }
// The following block wouldn't do anything on 32-bit platforms, // The following block wouldn't do anything on 32-bit platforms,
// because kMaxArrayIndexSize == kMaxIntegerIndexSize there, and // because kMaxArrayIndexSize == kMaxIntegerIndexSize there, and
...@@ -85,10 +84,11 @@ uint32_t StringHasher::HashSequentialString(const char_t* chars_raw, int length, ...@@ -85,10 +84,11 @@ uint32_t StringHasher::HashSequentialString(const char_t* chars_raw, int length,
// if there are non-digit characters. // if there are non-digit characters.
uint32_t is_integer_index = 0; uint32_t is_integer_index = 0;
uint32_t running_hash = static_cast<uint32_t>(seed); uint32_t running_hash = static_cast<uint32_t>(seed);
uint64_t index_big = index; uint64_t index_big = 0;
const uchar* end = &chars[length]; const uchar* end = &chars[length];
while (chars != end) { while (chars != end) {
if (is_integer_index == 0 && !TryAddIndexChar(&index_big, *chars)) { if (is_integer_index == 0 &&
!TryAddIntegerIndexChar(&index_big, *chars)) {
is_integer_index = String::kIsNotIntegerIndexMask; is_integer_index = String::kIsNotIntegerIndexMask;
} }
running_hash = AddCharacterCore(running_hash, *chars++); running_hash = AddCharacterCore(running_hash, *chars++);
......
...@@ -33,7 +33,7 @@ class TimedScope { ...@@ -33,7 +33,7 @@ class TimedScope {
}; };
template <typename Char> template <typename Char>
bool TryAddIndexChar(uint32_t* index, Char c) { bool TryAddArrayIndexChar(uint32_t* index, Char c) {
if (!IsDecimalDigit(c)) return false; if (!IsDecimalDigit(c)) return false;
int d = c - '0'; int d = c - '0';
// The maximum index is 4294967294; for the computation below to not // The maximum index is 4294967294; for the computation below to not
...@@ -46,19 +46,14 @@ bool TryAddIndexChar(uint32_t* index, Char c) { ...@@ -46,19 +46,14 @@ bool TryAddIndexChar(uint32_t* index, Char c) {
} }
template <typename Char> template <typename Char>
bool TryAddIndexChar(uint64_t* index, Char c) { bool TryAddIntegerIndexChar(uint64_t* index, Char c) {
if (!IsDecimalDigit(c)) return false; if (!IsDecimalDigit(c)) return false;
int d = c - '0'; int d = c - '0';
// The maximum uint64_t is 18446744073709551615; for the computation below to
// not exceed that, the previous index value must be <= 1844674407370955161
// if d <= 5, or <= 1844674407370955160 if d >= 6. The (d+2)>>3 computation
// is a branch-free way to express that.
if (*index > 1844674407370955161ull - ((d + 2) >> 3)) return false;
*index = (*index) * 10 + d; *index = (*index) * 10 + d;
return true; return (*index <= kMaxSafeIntegerUint64);
} }
template <typename Stream, typename index_t> template <typename Stream, typename index_t, enum ToIndexMode mode>
bool StringToIndex(Stream* stream, index_t* index) { bool StringToIndex(Stream* stream, index_t* index) {
uint16_t ch = stream->GetNext(); uint16_t ch = stream->GetNext();
...@@ -76,14 +71,16 @@ bool StringToIndex(Stream* stream, index_t* index) { ...@@ -76,14 +71,16 @@ bool StringToIndex(Stream* stream, index_t* index) {
while (stream->HasMore()) { while (stream->HasMore()) {
// Clang on Mac doesn't think that size_t and uint*_t should be // Clang on Mac doesn't think that size_t and uint*_t should be
// implicitly convertible. // implicitly convertible.
if (sizeof(index_t) == 8) { if (sizeof(result) == 8) {
if (!TryAddIndexChar(reinterpret_cast<uint64_t*>(&result), DCHECK_EQ(kToIntegerIndex, mode);
stream->GetNext())) { if (!TryAddIntegerIndexChar(reinterpret_cast<uint64_t*>(&result),
stream->GetNext())) {
return false; return false;
} }
} else { } else {
if (!TryAddIndexChar(reinterpret_cast<uint32_t*>(&result), // Either mode is fine here.
stream->GetNext())) if (!TryAddArrayIndexChar(reinterpret_cast<uint32_t*>(&result),
stream->GetNext()))
return false; return false;
} }
} }
......
...@@ -632,8 +632,11 @@ bool DoubleToBoolean(double d); ...@@ -632,8 +632,11 @@ bool DoubleToBoolean(double d);
template <typename Char> template <typename Char>
bool TryAddIndexChar(uint32_t* index, Char c); bool TryAddIndexChar(uint32_t* index, Char c);
enum ToIndexMode { kToArrayIndex, kToIntegerIndex };
// {index_t} is meant to be {uint32_t} or {size_t}. // {index_t} is meant to be {uint32_t} or {size_t}.
template <typename Stream, typename index_t> template <typename Stream, typename index_t,
enum ToIndexMode mode = kToArrayIndex>
bool StringToIndex(Stream* stream, index_t* index); bool StringToIndex(Stream* stream, index_t* index);
// Returns the current stack top. Works correctly with ASAN and SafeStack. // Returns the current stack top. Works correctly with ASAN and SafeStack.
......
...@@ -1922,12 +1922,14 @@ TEST(HashArrayIndexStrings) { ...@@ -1922,12 +1922,14 @@ TEST(HashArrayIndexStrings) {
#if V8_TARGET_ARCH_32_BIT #if V8_TARGET_ARCH_32_BIT
{"4294967295", false, 0, false, 0}, // Valid length but not index. {"4294967295", false, 0, false, 0}, // Valid length but not index.
{"4294967296", false, 0, false, 0}, {"4294967296", false, 0, false, 0},
{"18446744073709551615", false, 0, false, 0}, {"9007199254740991", false, 0, false, 0},
#else #else
{"4294967295", false, 0, true, 4294967295u}, {"4294967295", false, 0, true, 4294967295u},
{"4294967296", false, 0, true, 4294967296ull}, {"4294967296", false, 0, true, 4294967296ull},
{"18446744073709551615", false, 0, true, 18446744073709551615ull}, {"9007199254740991", false, 0, true, 9007199254740991ull},
#endif #endif
{"9007199254740992", false, 0, false, 0},
{"18446744073709551615", false, 0, false, 0},
{"18446744073709551616", false, 0, false, 0} {"18446744073709551616", false, 0, false, 0}
}; };
for (int i = 0, n = arraysize(tests); i < n; i++) { for (int i = 0, n = arraysize(tests); i < n; i++) {
......
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
// crbug.com/1026974
(function() {
function store(obj, key) {
obj[key] = 10;
}
%PrepareFunctionForOptimization(store);
for (let i = 0; i < 3; i++) {
let obj = {}
store(obj, 1152921506754330624);
assertEquals(["1152921506754330600"], Object.keys(obj));
}
})();
(function() {
function store(obj, key) {
obj[key] = 10;
}
%PrepareFunctionForOptimization(store);
for (let i = 0; i < 3; i++) {
let obj2 = new Int32Array(0);
store(obj2, 1152921506754330624);
assertEquals([], Object.keys(obj2));
store(obj2, "1152921506754330624");
assertEquals(["1152921506754330624"], Object.keys(obj2));
}
})();
// crbug.com/1026729
(function() {
let key = 0xFFFFFFFF;
let object = {};
assertFalse(object.hasOwnProperty(key));
let proxy = new Proxy({}, {});
assertFalse(proxy.hasOwnProperty(key));
})();
// crbug.com/1026909
(function() {
function load(obj, key) {
return obj[key];
}
%PrepareFunctionForOptimization(load);
const array = new Float64Array();
assertEquals(undefined, load(array, 'monomorphic'));
assertEquals(undefined, load(array, '4294967296'));
})();
// crbug.com/1026856
(function() {
let key = 0xFFFFFFFF;
let receiver = new Int32Array();
var value = {};
var target = {};
Reflect.set(target, key, value, receiver);
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment