Skip to content

Commit c9f3aca

Browse files
mkustermannCommit Queue
authored and
Commit Queue
committed
[vm] Ensure we only enqueue maps/sets to be rehashed if we know it got copied successfully
Closes #51226 TEST=vm/dart{,_2}/regress_51226_test Change-Id: I1da2dfe45863d5f1004efde3a4ecaae89ffd62fa Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/280469 Reviewed-by: Ryan Macnak <[email protected]> Commit-Queue: Martin Kustermann <[email protected]>
1 parent 5cff200 commit c9f3aca

File tree

3 files changed

+84
-1
lines changed

3 files changed

+84
-1
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:isolate';
6+
7+
import 'package:expect/expect.dart';
8+
9+
main() async {
10+
// Make large objects whose objects object can be copied in fast path but backing
11+
// store cannot.
12+
final foo = Foo();
13+
final objects = <dynamic>{};
14+
for (int i = 0; i < 1024 * 1024; ++i) {
15+
objects.add(i);
16+
}
17+
// Ensure there's at least one element that needs re-hashing when copying.
18+
objects.add(foo);
19+
foo.hashQueries = 0;
20+
21+
final copyOfFoo = (await copy(objects)).last as Foo;
22+
Expect.equals(1, copyOfFoo.hashQueries);
23+
}
24+
25+
Future<T> copy<T>(T value) async {
26+
final rp = ReceivePort();
27+
final sp = rp.sendPort;
28+
sp.send(value);
29+
return (await rp.first) as T;
30+
}
31+
32+
class Foo {
33+
int hashQueries = 0;
34+
35+
int get hashCode {
36+
hashQueries++;
37+
return super.hashCode;
38+
}
39+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
// @dart=2.9
6+
7+
import 'dart:isolate';
8+
9+
import 'package:expect/expect.dart';
10+
11+
main() async {
12+
// Make large objects whose objects object can be copied in fast path but backing
13+
// store cannot.
14+
final foo = Foo();
15+
final objects = <dynamic>{};
16+
for (int i = 0; i < 1024 * 1024; ++i) {
17+
objects.add(i);
18+
}
19+
// Ensure there's at least one element that needs re-hashing when copying.
20+
objects.add(foo);
21+
foo.hashQueries = 0;
22+
23+
final copyOfFoo = (await copy(objects)).last as Foo;
24+
Expect.equals(1, copyOfFoo.hashQueries);
25+
}
26+
27+
Future<T> copy<T>(T value) async {
28+
final rp = ReceivePort();
29+
final sp = rp.sendPort;
30+
sp.send(value);
31+
return (await rp.first) as T;
32+
}
33+
34+
class Foo {
35+
int hashQueries = 0;
36+
37+
int get hashCode {
38+
hashQueries++;
39+
return super.hashCode;
40+
}
41+
}

runtime/vm/object_graph_copy.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1476,7 +1476,6 @@ class ObjectCopy : public Base {
14761476
to_untagged->hash_mask_ = Smi::New(0);
14771477
to_untagged->index_ = TypedData::RawCast(Object::null());
14781478
to_untagged->deleted_keys_ = Smi::New(0);
1479-
Base::EnqueueObjectToRehash(to);
14801479
}
14811480

14821481
// From this point on we shouldn't use the raw pointers, since GC might
@@ -1499,6 +1498,10 @@ class ObjectCopy : public Base {
14991498
Base::StoreCompressedPointersNoBarrier(
15001499
from, to, OFFSET_OF(UntaggedLinkedHashBase, used_data_),
15011500
OFFSET_OF(UntaggedLinkedHashBase, used_data_));
1501+
1502+
if (Base::exception_msg_ == nullptr && needs_rehashing) {
1503+
Base::EnqueueObjectToRehash(to);
1504+
}
15021505
}
15031506

15041507
void CopyMap(typename Types::Map from, typename Types::Map to) {

0 commit comments

Comments
 (0)