Skip to content

Commit 2b0b80d

Browse files
jakobkummerowCommit Bot
authored andcommitted
Reland "Fixes for size_t LookupIterator"
This is a reland of e1ad9b8 Original change's description: > Fixes for size_t LookupIterator > > Fixing some fallout from c968607 > 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/+/1932839 Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/master@{#65162}
1 parent 825f65d commit 2b0b80d

15 files changed

Lines changed: 169 additions & 59 deletions

File tree

src/codegen/code-stub-assembler.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9766,6 +9766,13 @@ TNode<IntPtrT> CodeStubAssembler::TryToIntptr(
97669766
TNode<IntPtrT> int_value = ChangeFloat64ToIntPtr(value);
97679767
GotoIfNot(Float64Equal(value, RoundIntPtrToFloat64(int_value)),
97689768
if_not_intptr);
9769+
if (Is64()) {
9770+
// TODO(jkummerow): Investigate whether we can drop support for
9771+
// negative indices.
9772+
GotoIfNot(IsInRange(int_value, static_cast<intptr_t>(-kMaxSafeInteger),
9773+
static_cast<intptr_t>(kMaxSafeIntegerUint64)),
9774+
if_not_intptr);
9775+
}
97699776
var_intptr_key = int_value;
97709777
Goto(&done);
97719778
}

src/codegen/code-stub-assembler.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,13 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
941941
Int32Constant(higher_limit - lower_limit));
942942
}
943943

944+
TNode<BoolT> IsInRange(TNode<WordT> value, intptr_t lower_limit,
945+
intptr_t higher_limit) {
946+
DCHECK_LE(lower_limit, higher_limit);
947+
return UintPtrLessThanOrEqual(IntPtrSub(value, IntPtrConstant(lower_limit)),
948+
IntPtrConstant(higher_limit - lower_limit));
949+
}
950+
944951
#if DEBUG
945952
void Bind(Label* label, AssemblerDebugInfo debug_info);
946953
#endif // DEBUG

src/compiler/effect-control-linearizer.cc

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ class EffectControlLinearizer {
214214
Node* BuildCheckedFloat64ToInt64(CheckForMinusZeroMode mode,
215215
const FeedbackSource& feedback, Node* value,
216216
Node* frame_state);
217+
Node* BuildCheckedFloat64ToIndex(const FeedbackSource& feedback, Node* value,
218+
Node* frame_state);
217219
Node* BuildCheckedHeapNumberOrOddballToFloat64(CheckTaggedInputMode mode,
218220
const FeedbackSource& feedback,
219221
Node* value,
@@ -2429,6 +2431,31 @@ Node* EffectControlLinearizer::BuildCheckedFloat64ToInt32(
24292431
return value32;
24302432
}
24312433

2434+
Node* EffectControlLinearizer::BuildCheckedFloat64ToIndex(
2435+
const FeedbackSource& feedback, Node* value, Node* frame_state) {
2436+
if (machine()->Is64()) {
2437+
Node* value64 = __ ChangeFloat64ToInt64(value);
2438+
Node* check_same = __ Float64Equal(value, __ ChangeInt64ToFloat64(value64));
2439+
__ DeoptimizeIfNot(DeoptimizeReason::kLostPrecisionOrNaN, feedback,
2440+
check_same, frame_state);
2441+
Node* check_max =
2442+
__ IntLessThan(value64, __ Int64Constant(kMaxSafeInteger));
2443+
__ DeoptimizeIfNot(DeoptimizeReason::kNotAnArrayIndex, feedback, check_max,
2444+
frame_state);
2445+
Node* check_min =
2446+
__ IntLessThan(__ Int64Constant(-kMaxSafeInteger), value64);
2447+
__ DeoptimizeIfNot(DeoptimizeReason::kNotAnArrayIndex, feedback, check_min,
2448+
frame_state);
2449+
return value64;
2450+
} else {
2451+
Node* value32 = __ RoundFloat64ToInt32(value);
2452+
Node* check_same = __ Float64Equal(value, __ ChangeInt32ToFloat64(value32));
2453+
__ DeoptimizeIfNot(DeoptimizeReason::kLostPrecisionOrNaN, feedback,
2454+
check_same, frame_state);
2455+
return value32;
2456+
}
2457+
}
2458+
24322459
Node* EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node,
24332460
Node* frame_state) {
24342461
const CheckMinusZeroParameters& params =
@@ -2500,17 +2527,15 @@ Node* EffectControlLinearizer::LowerCheckedTaggedToArrayIndex(
25002527
__ Goto(&done, ChangeSmiToIntPtr(value));
25012528

25022529
// In the non-Smi case, check the heap numberness, load the number and convert
2503-
// to int32.
2530+
// to integer.
25042531
__ Bind(&if_not_smi);
25052532
auto if_not_heap_number = __ MakeDeferredLabel();
25062533
Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
25072534
Node* is_heap_number = __ TaggedEqual(value_map, __ HeapNumberMapConstant());
25082535
__ GotoIfNot(is_heap_number, &if_not_heap_number);
25092536

25102537
Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
2511-
number =
2512-
BuildCheckedFloat64ToInt32(CheckForMinusZeroMode::kDontCheckForMinusZero,
2513-
params.feedback(), number, frame_state);
2538+
number = BuildCheckedFloat64ToIndex(params.feedback(), number, frame_state);
25142539
__ Goto(&done, number);
25152540

25162541
__ Bind(&if_not_heap_number);

src/ic/ic.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,8 +1203,8 @@ KeyType TryConvertKey(Handle<Object> key, Isolate* isolate, intptr_t* index_out,
12031203
}
12041204
if (key->IsHeapNumber()) {
12051205
double num = HeapNumber::cast(*key).value();
1206-
if (!(num >= std::numeric_limits<intptr_t>::min())) return kBailout;
1207-
if (num > std::numeric_limits<intptr_t>::max()) return kBailout;
1206+
if (!(num >= -kMaxSafeInteger)) return kBailout;
1207+
if (num > kMaxSafeInteger) return kBailout;
12081208
*index_out = static_cast<intptr_t>(num);
12091209
if (*index_out != num) return kBailout;
12101210
return kIntPtr;

src/json/json-parser.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ JsonString JsonParser<Char>::ScanJsonPropertyKey(JsonContinuation* cont) {
362362
uint32_t index = first - '0';
363363
while (true) {
364364
cursor_ = std::find_if(cursor_ + 1, end_, [&index](Char c) {
365-
return !TryAddIndexChar(&index, c);
365+
return !TryAddArrayIndexChar(&index, c);
366366
});
367367

368368
if (CurrentCharacter() == '"') {
@@ -374,7 +374,7 @@ JsonString JsonParser<Char>::ScanJsonPropertyKey(JsonContinuation* cont) {
374374
}
375375

376376
if (CurrentCharacter() == '\\' && NextCharacter() == 'u') {
377-
if (TryAddIndexChar(&index, ScanUnicodeCharacter())) continue;
377+
if (TryAddArrayIndexChar(&index, ScanUnicodeCharacter())) continue;
378378
}
379379

380380
break;

src/objects/lookup-inl.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,18 @@ LookupIterator::LookupIterator(Isolate* isolate, Handle<Object> receiver,
7171
receiver_(receiver),
7272
initial_holder_(holder),
7373
index_(index) {
74+
DCHECK_NE(index, kInvalidIndex);
7475
// If we're not looking at a TypedArray, we will need the key represented
7576
// as an internalized string.
76-
if (index_ > JSArray::kMaxArrayIndex && !receiver->IsJSTypedArray()) {
77+
if (index_ > JSArray::kMaxArrayIndex && !holder->IsJSTypedArray()) {
7778
if (key_as_string.is_null()) {
7879
key_as_string = isolate->factory()->SizeToString(index_);
7980
}
8081
name_ = isolate->factory()->InternalizeName(key_as_string);
82+
} else if (!key_as_string.is_null() &&
83+
key_as_string->IsInternalizedString()) {
84+
// Even for TypedArrays: if we have a name, keep it. ICs will need it.
85+
name_ = key_as_string;
8186
}
8287
Start<true>();
8388
}

src/objects/name.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,13 @@ class Name : public TorqueGeneratedName<Name, PrimitiveHeapObject> {
9595
// Maximum number of characters to consider when trying to convert a string
9696
// value into an array index.
9797
static const int kMaxArrayIndexSize = 10;
98-
// Maximum number of characters that might be parsed into a size_t:
99-
// 10 characters per 32 bits of size_t width.
100-
// We choose this as large as possible (rather than MAX_SAFE_INTEGER range)
101-
// because TypedArray accesses will treat all string keys that are
102-
// canonical representations of numbers in the range [MAX_SAFE_INTEGER ..
103-
// size_t::max] as out-of-bounds accesses, and we can handle those in the
104-
// fast path if we tag them as such (see kIsNotIntegerIndexMask).
105-
static const int kMaxIntegerIndexSize = 10 * (sizeof(size_t) / 4);
98+
// Maximum number of characters in a string that can possibly be an
99+
// "integer index" in the spec sense, i.e. a canonical representation of a
100+
// number in the range up to MAX_SAFE_INTEGER. We parse these into a size_t,
101+
// so the size of that type also factors in as a limit: 10 characters per
102+
// 32 bits of size_t width.
103+
static const int kMaxIntegerIndexSize =
104+
std::min(16, int{10 * (sizeof(size_t) / 4)});
106105

107106
// For strings which are array indexes the hash value has the string length
108107
// mixed into the hash, mainly to avoid a hash value of zero which would be

src/objects/objects-inl.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -823,9 +823,11 @@ bool Object::ToIntegerIndex(size_t* index) const {
823823
if (IsHeapNumber()) {
824824
double num = HeapNumber::cast(*this).value();
825825
if (!(num >= 0)) return false; // Negation to catch NaNs.
826-
// We must exclude the max size_t, because the LookupIterator uses that
827-
// as the "invalid index" sentinel.
828-
if (num >= std::numeric_limits<size_t>::max()) return false;
826+
constexpr double max =
827+
std::min(kMaxSafeInteger,
828+
// The maximum size_t is reserved as "invalid" sentinel.
829+
static_cast<double>(std::numeric_limits<size_t>::max() - 1));
830+
if (num > max) return false;
829831
size_t result = static_cast<size_t>(num);
830832
if (num != result) return false; // Conversion lost fractional precision.
831833
*index = result;

src/objects/string.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1397,7 +1397,8 @@ bool String::SlowAsIntegerIndex(size_t* index) {
13971397
}
13981398
if (length == 0 || length > kMaxIntegerIndexSize) return false;
13991399
StringCharacterStream stream(*this);
1400-
return StringToIndex(&stream, index);
1400+
return StringToIndex<StringCharacterStream, size_t, kToIntegerIndex>(&stream,
1401+
index);
14011402
}
14021403

14031404
void String::PrintOn(FILE* file) {

src/runtime/runtime-object.cc

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -270,21 +270,23 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
270270
HandleScope scope(isolate);
271271
Handle<Object> property = args.at(1);
272272

273+
// The spec says we must look at the key first, which is why we can't
274+
// use LookupIterator::PropertyOrElement here but have to duplicate its
275+
// functionality instead.
273276
Handle<Name> key;
274-
uint32_t index;
275-
bool key_is_array_index = property->ToArrayIndex(&index);
276-
277-
if (!key_is_array_index) {
277+
size_t index;
278+
bool key_is_index = property->ToIntegerIndex(&index);
279+
if (!key_is_index) {
278280
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
279281
Object::ToName(isolate, property));
280-
key_is_array_index = key->AsArrayIndex(&index);
282+
key_is_index = key->AsIntegerIndex(&index);
281283
}
282284

283285
Handle<Object> object = args.at(0);
284286

285287
if (object->IsJSModuleNamespace()) {
286288
if (key.is_null()) {
287-
DCHECK(key_is_array_index);
289+
DCHECK(key_is_index);
288290
// Namespace objects can't have indexed properties.
289291
return ReadOnlyRoots(isolate).false_value();
290292
}
@@ -304,8 +306,8 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
304306
{
305307
LookupIterator::Configuration c = LookupIterator::OWN_SKIP_INTERCEPTOR;
306308
LookupIterator it =
307-
key_is_array_index ? LookupIterator(isolate, js_obj, index, js_obj, c)
308-
: LookupIterator(js_obj, key, js_obj, c);
309+
key_is_index ? LookupIterator(isolate, js_obj, index, js_obj, c)
310+
: LookupIterator(js_obj, key, js_obj, c);
309311
Maybe<bool> maybe = JSReceiver::HasProperty(&it);
310312
if (maybe.IsNothing()) return ReadOnlyRoots(isolate).exception();
311313
DCHECK(!isolate->has_pending_exception());
@@ -314,14 +316,15 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
314316

315317
Map map = js_obj->map();
316318
if (!map.IsJSGlobalProxyMap() &&
317-
(key_is_array_index ? !map.has_indexed_interceptor()
318-
: !map.has_named_interceptor())) {
319+
(key_is_index && index <= JSArray::kMaxArrayIndex
320+
? !map.has_indexed_interceptor()
321+
: !map.has_named_interceptor())) {
319322
return ReadOnlyRoots(isolate).false_value();
320323
}
321324

322325
// Slow case.
323326
LookupIterator::Configuration c = LookupIterator::OWN;
324-
LookupIterator it = key_is_array_index
327+
LookupIterator it = key_is_index
325328
? LookupIterator(isolate, js_obj, index, js_obj, c)
326329
: LookupIterator(js_obj, key, js_obj, c);
327330

@@ -332,19 +335,18 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
332335

333336
} else if (object->IsJSProxy()) {
334337
if (key.is_null()) {
335-
DCHECK(key_is_array_index);
336-
key = isolate->factory()->Uint32ToString(index);
338+
DCHECK(key_is_index);
339+
key = isolate->factory()->SizeToString(index);
337340
}
338-
339341
Maybe<bool> result =
340342
JSReceiver::HasOwnProperty(Handle<JSProxy>::cast(object), key);
341343
if (result.IsNothing()) return ReadOnlyRoots(isolate).exception();
342344
return isolate->heap()->ToBoolean(result.FromJust());
343345

344346
} else if (object->IsString()) {
345347
return isolate->heap()->ToBoolean(
346-
key_is_array_index
347-
? index < static_cast<uint32_t>(String::cast(*object).length())
348+
key_is_index
349+
? index < static_cast<size_t>(String::cast(*object).length())
348350
: key->Equals(ReadOnlyRoots(isolate).length_string()));
349351
} else if (object->IsNullOrUndefined(isolate)) {
350352
THROW_NEW_ERROR_RETURN_FAILURE(

0 commit comments

Comments
 (0)