[vm/sdk] Use FinalThreadLocal for Iterable toString.
This allows use of toString in isolategroup-bound callbacks. BUG=https://github.com/dart-lang/sdk/issues/61030. TEST=ci CoreLibraryReviewExempt: effectively vm-only change Change-Id: Iccdc218716cbbe2346aa85bb6134f4129debe057 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/451841 Reviewed-by: Nate Biggs <natebiggs@google.com> Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Lasse Nielsen <lrn@google.com> Reviewed-by: Nate Bosch <nbosch@google.com>
This commit is contained in:
committed by
Commit Queue
parent
aae871a607
commit
2c715e92b6
@@ -27,7 +27,7 @@
|
||||
(i32.const 0)
|
||||
(global.get $global0)
|
||||
(ref.func $"foo tear-off trampoline")
|
||||
(ref.func $"foo tear-off trampoline_299")
|
||||
(ref.func $"foo tear-off trampoline_300")
|
||||
(struct.new $#Vtable-0-2)
|
||||
(i32.const 12)
|
||||
(i32.const 0)
|
||||
@@ -52,7 +52,7 @@
|
||||
(i32.const 0)
|
||||
(global.get $global0)
|
||||
(ref.func $"bar tear-off trampoline")
|
||||
(ref.func $"bar tear-off trampoline_302")
|
||||
(ref.func $"bar tear-off trampoline_303")
|
||||
(struct.new $#Vtable-0-2)
|
||||
(i32.const 12)
|
||||
(i32.const 0)
|
||||
@@ -74,7 +74,7 @@
|
||||
(struct.new $#Closure-0-2))
|
||||
(global $global0 (ref $#DummyStruct) <...>)
|
||||
(func $bar tear-off trampoline (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (result (ref null $#Top)) <...>)
|
||||
(func $bar tear-off trampoline_302 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>)
|
||||
(func $bar tear-off trampoline_303 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>)
|
||||
(func $foo tear-off trampoline (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (result (ref null $#Top)) <...>)
|
||||
(func $foo tear-off trampoline_299 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>)
|
||||
(func $foo tear-off trampoline_300 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>)
|
||||
)
|
||||
@@ -27,7 +27,7 @@
|
||||
(i32.const 0)
|
||||
(global.get $global0)
|
||||
(ref.func $"foo tear-off trampoline")
|
||||
(ref.func $"foo tear-off trampoline_299")
|
||||
(ref.func $"foo tear-off trampoline_300")
|
||||
(struct.new $#Vtable-0-2)
|
||||
(i32.const 12)
|
||||
(i32.const 0)
|
||||
@@ -52,7 +52,7 @@
|
||||
(i32.const 0)
|
||||
(global.get $global0)
|
||||
(ref.func $"bar tear-off trampoline")
|
||||
(ref.func $"bar tear-off trampoline_304")
|
||||
(ref.func $"bar tear-off trampoline_305")
|
||||
(struct.new $#Vtable-0-2)
|
||||
(i32.const 12)
|
||||
(i32.const 0)
|
||||
@@ -74,7 +74,7 @@
|
||||
(struct.new $#Closure-0-2))
|
||||
(global $global0 (ref $#DummyStruct) <...>)
|
||||
(func $bar tear-off trampoline (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (result (ref null $#Top)) <...>)
|
||||
(func $bar tear-off trampoline_304 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>)
|
||||
(func $bar tear-off trampoline_305 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>)
|
||||
(func $foo tear-off trampoline (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (result (ref null $#Top)) <...>)
|
||||
(func $foo tear-off trampoline_299 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>)
|
||||
(func $foo tear-off trampoline_300 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>)
|
||||
)
|
||||
@@ -31,7 +31,7 @@
|
||||
(i32.const 0)
|
||||
(global.get $global0)
|
||||
(ref.func $"foo tear-off dynamic call entry")
|
||||
(ref.func $"foo tear-off trampoline_307")
|
||||
(ref.func $"foo tear-off trampoline_308")
|
||||
(struct.new $#Vtable-0-2)
|
||||
(i32.const 12)
|
||||
(i32.const 0)
|
||||
@@ -57,7 +57,7 @@
|
||||
(i32.const 0)
|
||||
(global.get $global0)
|
||||
(ref.func $"bar tear-off dynamic call entry")
|
||||
(ref.func $"bar tear-off trampoline_313")
|
||||
(ref.func $"bar tear-off trampoline_314")
|
||||
(struct.new $#Vtable-0-2)
|
||||
(i32.const 12)
|
||||
(i32.const 0)
|
||||
@@ -74,7 +74,7 @@
|
||||
(struct.new $#Closure-0-2))
|
||||
(global $global0 (ref $#DummyStruct) <...>)
|
||||
(func $bar tear-off dynamic call entry (param $var0 (ref $#Closure-0-0)) (param $var1 (ref $Array<_Type>)) (param $var2 (ref $Array<Object?>)) (param $var3 (ref $Array<Object?>)) (result (ref null $#Top)) <...>)
|
||||
(func $bar tear-off trampoline_313 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>)
|
||||
(func $bar tear-off trampoline_314 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>)
|
||||
(func $foo tear-off dynamic call entry (param $var0 (ref $#Closure-0-0)) (param $var1 (ref $Array<_Type>)) (param $var2 (ref $Array<Object?>)) (param $var3 (ref $Array<Object?>)) (result (ref null $#Top)) <...>)
|
||||
(func $foo tear-off trampoline_307 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>)
|
||||
(func $foo tear-off trampoline_308 (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref null $#Top)) <...>)
|
||||
)
|
||||
@@ -887,7 +887,7 @@ Map<String, dynamic>? diffToJson(ProgramInfo diff,
|
||||
keepOnlyInputPackage ? key != 'package:input' : key.startsWith('file:'));
|
||||
|
||||
// Rebuild the diff JSON discarding all nodes with size below threshold.
|
||||
const smallChangeThreshold = 16;
|
||||
const smallChangeThreshold = 13;
|
||||
Map<String, dynamic>? discardSmallChanges(Map<String, dynamic> map) {
|
||||
final result = <String, dynamic>{};
|
||||
|
||||
|
||||
@@ -121,3 +121,7 @@ abstract interface class IsolateGroup {
|
||||
static Object _runSync(Object computation) =>
|
||||
throw UnsupportedError("_runSync");
|
||||
}
|
||||
|
||||
final List<Object> _toStringVisiting = [];
|
||||
@patch
|
||||
List<Object> get toStringVisiting => _toStringVisiting;
|
||||
|
||||
@@ -99,3 +99,7 @@ abstract interface class IsolateGroup {
|
||||
static Object _runSync(Object computation) =>
|
||||
throw UnsupportedError("_runSync");
|
||||
}
|
||||
|
||||
final List<Object> _toStringVisiting = [];
|
||||
@patch
|
||||
List<Object> get toStringVisiting => _toStringVisiting;
|
||||
|
||||
@@ -12,6 +12,7 @@ import "dart:core" hide Symbol;
|
||||
import "dart:ffi" show Pointer, Struct, Union, IntPtr, Handle, Void, Native;
|
||||
import "dart:isolate" show SendPort;
|
||||
import "dart:typed_data" show Int32List, Uint8List;
|
||||
import "dart:_vm" show FinalThreadLocal;
|
||||
|
||||
/// These are the additional parts of this patch library:
|
||||
part "class_id_fasta.dart";
|
||||
@@ -482,3 +483,8 @@ abstract interface class IsolateGroup {
|
||||
@Native<Handle Function(Handle)>(symbol: "IsolateGroup_runSync")
|
||||
external static Object _runSync(Object computation);
|
||||
}
|
||||
|
||||
@pragma("vm:shared")
|
||||
final _toStringVisiting = FinalThreadLocal<List<Object>>(() => <Object>[]);
|
||||
@patch
|
||||
List<Object> get toStringVisiting => _toStringVisiting.value;
|
||||
|
||||
@@ -239,3 +239,7 @@ abstract interface class IsolateGroup {
|
||||
static Object _runSync(Object computation) =>
|
||||
throw UnsupportedError("_runSync");
|
||||
}
|
||||
|
||||
final List<Object> _toStringVisiting = [];
|
||||
@patch
|
||||
List<Object> get toStringVisiting => _toStringVisiting;
|
||||
|
||||
@@ -58,6 +58,7 @@ import 'dart:_internal' hide Symbol;
|
||||
import 'dart:math' show Random; // Used by ListMixin.shuffle.
|
||||
|
||||
export 'dart:_internal' show DoubleLinkedQueueEntry;
|
||||
import 'dart:_internal' show isToStringVisiting, toStringVisiting;
|
||||
|
||||
part 'collections.dart';
|
||||
part 'hash_map.dart';
|
||||
|
||||
@@ -153,6 +153,7 @@ library dart.core;
|
||||
import "dart:collection";
|
||||
import "dart:_internal" hide Symbol, LinkedList, LinkedListEntry;
|
||||
import "dart:_internal" as internal show Symbol;
|
||||
import "dart:_internal" show isToStringVisiting, toStringVisiting;
|
||||
import "dart:convert"
|
||||
show
|
||||
ascii,
|
||||
|
||||
@@ -1124,12 +1124,13 @@ const vmIsolateUnsendable = pragma("vm:isolate-unsendable");
|
||||
// Helpers used to detect cycles in collection `toString`s.
|
||||
|
||||
/// A collection used to identify cyclic lists during `toString` calls.
|
||||
final List<Object> toStringVisiting = [];
|
||||
external List<Object> get toStringVisiting;
|
||||
|
||||
/// Check if we are currently visiting [object] in a `toString` call.
|
||||
bool isToStringVisiting(Object object) {
|
||||
for (int i = 0; i < toStringVisiting.length; i++) {
|
||||
if (identical(object, toStringVisiting[i])) return true;
|
||||
final visiting = toStringVisiting;
|
||||
for (int i = 0; i < visiting.length; i++) {
|
||||
if (identical(object, visiting[i])) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ main(List<String> args) {
|
||||
testBase64Decoder();
|
||||
testRandom();
|
||||
testEncoding();
|
||||
testRecursiveToString();
|
||||
|
||||
print("All tests completed :)");
|
||||
}
|
||||
@@ -438,3 +439,16 @@ void testEncoding() {
|
||||
IsolateGroup.runSync(() => Encoding.getByName("utf-8")),
|
||||
);
|
||||
}
|
||||
|
||||
///
|
||||
void testRecursiveToString() {
|
||||
Expect.equals(
|
||||
"[foo, bar, [...], baz]",
|
||||
IsolateGroup.runSync(() {
|
||||
var l = <Object>["foo", "bar"];
|
||||
l.add(l);
|
||||
l.add("baz");
|
||||
return l.toString();
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user