Skip to content

Commit

Permalink
[vm] Implement constant Maps in the VM
Browse files Browse the repository at this point in the history
This CL changes the frontend to emit map and set constants which are
then processed by the constant reader in the VM.

This CL also introduces support for sending the const maps and sets
in messages between isolates and saving it in snapshots.

TEST=tests/language/const/map_test.dart (et al, for lookups)
TEST=tests/lib/isolate/message3_test.dart (et al, for isolate messages)
TEST=tools/test.py -c dartkp (for consts from clustered snapshot)
TEST=tools/test.py -n app_jitk-linux-debug-x64 (for consts from app
     jit snapshots)
TEST=Building the SDK which uses const Maps in clustered snapshots.

Closes: #45908

Change-Id: I1f8150a8aba8298c4e64d2571dd147743526135a
Cq-Include-Trybots: luci.dart.try:analyzer-nnbd-linux-release-try,app-kernel-linux-debug-x64-try,dart-sdk-linux-try,front-end-nnbd-linux-release-x64-try,pkg-linux-debug-try,vm-canary-linux-debug-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-checked-linux-release-x64-try,vm-kernel-linux-debug-x64c-try,vm-kernel-linux-debug-x64-try,vm-kernel-linux-debug-simarm64c-try,vm-kernel-nnbd-linux-release-simarm-try,vm-kernel-optcounter-threshold-linux-release-x64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-tsan-linux-release-x64-try,vm-kernel-tsan-linux-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/203765
Reviewed-by: Martin Kustermann <kustermann@google.com>
  • Loading branch information
dcharkes committed Sep 6, 2021
1 parent e8e9e1d commit 2b5adb7
Show file tree
Hide file tree
Showing 263 changed files with 1,942 additions and 1,669 deletions.
4 changes: 0 additions & 4 deletions pkg/front_end/lib/src/fasta/source/source_loader.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1589,10 +1589,6 @@ abstract class Map<K, V> extends Iterable {
void operator []=(K key, V value) {}
}
abstract class _ImmutableMap<K, V> implements Map<K, V> {
dynamic _kvPairs;
}
abstract class pragma {
String name;
Object options;
Expand Down
5 changes: 2 additions & 3 deletions pkg/front_end/testcases/agnostic/map.dart.strong.expect
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import "dart:core" as core;

static const field core::List<core::int> a = #C1;
static const field core::List<core::int?> b = #C2;
static const field core::Map<core::List<core::int?>, core::int> c = #C6;
static const field core::Map<core::List<core::int?>, core::int> c = #C5;
static method main() → dynamic {}

constants {
#C1 = <core::int>[]
#C2 = <core::int?>[]
#C3 = 0
#C4 = 1
#C5 = <dynamic>[#C1, #C3, #C2, #C4]
#C6 = core::_ImmutableMap<core::List<core::int?>, core::int> {_kvPairs:#C5}
#C5 = <core::List<core::int?>, core::int>{#C1:#C3, #C2:#C4)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import "dart:core" as core;

static const field core::List<core::int> a = #C1;
static const field core::List<core::int?> b = #C2;
static const field core::Map<core::List<core::int?>, core::int> c = #C6;
static const field core::Map<core::List<core::int?>, core::int> c = #C5;
static method main() → dynamic {}

constants {
#C1 = <core::int>[]
#C2 = <core::int?>[]
#C3 = 0
#C4 = 1
#C5 = <dynamic>[#C1, #C3, #C2, #C4]
#C6 = core::_ImmutableMap<core::List<core::int?>, core::int> {_kvPairs:#C5}
#C5 = <core::List<core::int?>, core::int>{#C1:#C3, #C2:#C4)
}
5 changes: 2 additions & 3 deletions pkg/front_end/testcases/agnostic/map.dart.weak.expect
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import "dart:core" as core;

static const field core::List<core::int> a = #C1;
static const field core::List<core::int?> b = #C2;
static const field core::Map<core::List<core::int?>, core::int> c = #C6;
static const field core::Map<core::List<core::int?>, core::int> c = #C5;
static method main() → dynamic {}

constants {
#C1 = <core::int*>[]
#C2 = <core::int?>[]
#C3 = 0
#C4 = 1
#C5 = <dynamic>[#C1, #C3, #C2, #C4]
#C6 = core::_ImmutableMap<core::List<core::int?>*, core::int*> {_kvPairs:#C5}
#C5 = <core::List<core::int?>*, core::int*>{#C1:#C3, #C2:#C4)
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ static method main() → dynamic
Extra constant evaluation status:
Evaluated: ListLiteral @ org-dartlang-testcase:///map.dart:5:16 -> ListConstant(const <int*>[])
Evaluated: ListLiteral @ org-dartlang-testcase:///map.dart:6:17 -> ListConstant(const <int?>[])
Evaluated: MapLiteral @ org-dartlang-testcase:///map.dart:7:11 -> InstanceConstant(const _ImmutableMap<List<int?>*, int*>{_ImmutableMap._kvPairs: const <dynamic>[const <int*>[], 0, const <int?>[], 1]})
Evaluated: MapLiteral @ org-dartlang-testcase:///map.dart:7:11 -> MapConstant(const <List<int?>*, int*>{const <int*>[]: 0, const <int?>[]: 1})
Extra constant evaluation: evaluated: 3, effectively constant: 3
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import "dart:core" as core;

static const field core::List<core::int> a = #C1;
static const field core::List<core::int?> b = #C2;
static const field core::Map<core::List<core::int?>, core::int> c = #C6;
static const field core::Map<core::List<core::int?>, core::int> c = #C5;
static method main() → dynamic {}

constants {
#C1 = <core::int*>[]
#C2 = <core::int?>[]
#C3 = 0
#C4 = 1
#C5 = <dynamic>[#C1, #C3, #C2, #C4]
#C6 = core::_ImmutableMap<core::List<core::int?>*, core::int*> {_kvPairs:#C5}
#C5 = <core::List<core::int?>*, core::int*>{#C1:#C3, #C2:#C4)
}
7 changes: 2 additions & 5 deletions pkg/front_end/testcases/agnostic/set.dart.strong.expect
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@ import "dart:core" as core;

static const field core::List<core::int> a = #C1;
static const field core::List<core::int?> b = #C2;
static const field core::Set<core::List<core::int?>> c = #C6;
static const field core::Set<core::List<core::int?>> c = #C3;
static method main() → dynamic {}

constants {
#C1 = <core::int>[]
#C2 = <core::int?>[]
#C3 = null
#C4 = <dynamic>[#C1, #C3, #C2, #C3]
#C5 = core::_ImmutableMap<core::List<core::int?>, Null> {_kvPairs:#C4}
#C6 = col::_UnmodifiableSet<core::List<core::int?>> {_map:#C5}
#C3 = <core::List<core::int?>>{#C1, #C2}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@ import "dart:core" as core;

static const field core::List<core::int> a = #C1;
static const field core::List<core::int?> b = #C2;
static const field core::Set<core::List<core::int?>> c = #C6;
static const field core::Set<core::List<core::int?>> c = #C3;
static method main() → dynamic {}

constants {
#C1 = <core::int>[]
#C2 = <core::int?>[]
#C3 = null
#C4 = <dynamic>[#C1, #C3, #C2, #C3]
#C5 = core::_ImmutableMap<core::List<core::int?>, Null> {_kvPairs:#C4}
#C6 = col::_UnmodifiableSet<core::List<core::int?>> {_map:#C5}
#C3 = <core::List<core::int?>>{#C1, #C2}
}
7 changes: 2 additions & 5 deletions pkg/front_end/testcases/agnostic/set.dart.weak.expect
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@ import "dart:core" as core;

static const field core::List<core::int> a = #C1;
static const field core::List<core::int?> b = #C2;
static const field core::Set<core::List<core::int?>> c = #C6;
static const field core::Set<core::List<core::int?>> c = #C3;
static method main() → dynamic {}

constants {
#C1 = <core::int*>[]
#C2 = <core::int?>[]
#C3 = null
#C4 = <dynamic>[#C1, #C3, #C2, #C3]
#C5 = core::_ImmutableMap<core::List<core::int?>*, Null> {_kvPairs:#C4}
#C6 = col::_UnmodifiableSet<core::List<core::int?>*> {_map:#C5}
#C3 = <core::List<core::int?>*>{#C1, #C2}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ static method main() → dynamic
Extra constant evaluation status:
Evaluated: ListLiteral @ org-dartlang-testcase:///set.dart:5:16 -> ListConstant(const <int*>[])
Evaluated: ListLiteral @ org-dartlang-testcase:///set.dart:6:17 -> ListConstant(const <int?>[])
Evaluated: SetLiteral @ org-dartlang-testcase:///set.dart:7:11 -> InstanceConstant(const _UnmodifiableSet<List<int?>*>{_UnmodifiableSet._map: const _ImmutableMap<List<int?>*, Null>{_ImmutableMap._kvPairs: const <dynamic>[const <int*>[], null, const <int?>[], null]}})
Evaluated: SetLiteral @ org-dartlang-testcase:///set.dart:7:11 -> SetConstant(const <List<int?>*>{const <int*>[], const <int?>[]})
Extra constant evaluation: evaluated: 3, effectively constant: 3
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@ import "dart:core" as core;

static const field core::List<core::int> a = #C1;
static const field core::List<core::int?> b = #C2;
static const field core::Set<core::List<core::int?>> c = #C6;
static const field core::Set<core::List<core::int?>> c = #C3;
static method main() → dynamic {}

constants {
#C1 = <core::int*>[]
#C2 = <core::int?>[]
#C3 = null
#C4 = <dynamic>[#C1, #C3, #C2, #C3]
#C5 = core::_ImmutableMap<core::List<core::int?>*, Null> {_kvPairs:#C4}
#C6 = col::_UnmodifiableSet<core::List<core::int?>*> {_map:#C5}
#C3 = <core::List<core::int?>*>{#C1, #C2}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import "package:expect/expect.dart";
static const field core::Object? var1 = #C1;
static const field core::Object? var2 = #C2;
static const field core::Object? var3 = #C3;
static const field core::Map<core::String, core::int> map = #C10;
static const field core::Map<core::String, core::int> map = #C9;
static const field core::Object? var4 = #C2;
static const field core::Object? var5 = #C6;
static const field core::Object? var6 = #C8;
Expand All @@ -17,7 +17,7 @@ static method fn(core::Map<core::Object, core::Object> map, core::Object key)
return map.{core::Map::[]}(key){(core::Object?) → core::Object?};
}
static method fn2() → core::int? {
return (#C13).{core::Map::[]}("key"){(core::Object?) → core::int?};
return (#C11).{core::Map::[]}("key"){(core::Object?) → core::int?};
}
static method main() → void {
exp::Expect::equals(#C1, "val");
Expand All @@ -38,9 +38,7 @@ constants {
#C6 = 3
#C7 = "key3"
#C8 = 4
#C9 = <dynamic>[#C4, #C2, #C5, #C6, #C7, #C8]
#C10 = core::_ImmutableMap<core::String, core::int> {_kvPairs:#C9}
#C11 = "key"
#C12 = <dynamic>[#C11, #C2]
#C13 = core::_ImmutableMap<core::String, core::int> {_kvPairs:#C12}
#C9 = <core::String, core::int>{#C4:#C2, #C5:#C6, #C7:#C8)
#C10 = "key"
#C11 = <core::String, core::int>{#C10:#C2)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import "package:expect/expect.dart";
static const field core::Object? var1 = #C1;
static const field core::Object? var2 = #C2;
static const field core::Object? var3 = #C3;
static const field core::Map<core::String, core::int> map = #C10;
static const field core::Map<core::String, core::int> map = #C9;
static const field core::Object? var4 = #C2;
static const field core::Object? var5 = #C6;
static const field core::Object? var6 = #C8;
Expand All @@ -17,7 +17,7 @@ static method fn(core::Map<core::Object, core::Object> map, core::Object key)
return map.{core::Map::[]}(key){(core::Object?) → core::Object?};
}
static method fn2() → core::int? {
return (#C13).{core::Map::[]}("key"){(core::Object?) → core::int?};
return (#C11).{core::Map::[]}("key"){(core::Object?) → core::int?};
}
static method main() → void {
exp::Expect::equals(#C1, "val");
Expand All @@ -38,9 +38,7 @@ constants {
#C6 = 3
#C7 = "key3"
#C8 = 4
#C9 = <dynamic>[#C4, #C2, #C5, #C6, #C7, #C8]
#C10 = core::_ImmutableMap<core::String, core::int> {_kvPairs:#C9}
#C11 = "key"
#C12 = <dynamic>[#C11, #C2]
#C13 = core::_ImmutableMap<core::String, core::int> {_kvPairs:#C12}
#C9 = <core::String, core::int>{#C4:#C2, #C5:#C6, #C7:#C8)
#C10 = "key"
#C11 = <core::String, core::int>{#C10:#C2)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import "package:expect/expect.dart";
static const field core::Object? var1 = #C1;
static const field core::Object? var2 = #C2;
static const field core::Object? var3 = #C3;
static const field core::Map<core::String, core::int> map = #C10;
static const field core::Map<core::String, core::int> map = #C9;
static const field core::Object? var4 = #C2;
static const field core::Object? var5 = #C6;
static const field core::Object? var6 = #C8;
Expand All @@ -17,7 +17,7 @@ static method fn(core::Map<core::Object, core::Object> map, core::Object key)
return map.{core::Map::[]}(key){(core::Object?) → core::Object?};
}
static method fn2() → core::int? {
return (#C13).{core::Map::[]}("key"){(core::Object?) → core::int?};
return (#C11).{core::Map::[]}("key"){(core::Object?) → core::int?};
}
static method main() → void {
exp::Expect::equals(#C1, "val");
Expand All @@ -38,9 +38,7 @@ constants {
#C6 = 3
#C7 = "key3"
#C8 = 4
#C9 = <dynamic>[#C4, #C2, #C5, #C6, #C7, #C8]
#C10 = core::_ImmutableMap<core::String*, core::int*> {_kvPairs:#C9}
#C11 = "key"
#C12 = <dynamic>[#C11, #C2]
#C13 = core::_ImmutableMap<core::String*, core::int*> {_kvPairs:#C12}
#C9 = <core::String*, core::int*>{#C4:#C2, #C5:#C6, #C7:#C8)
#C10 = "key"
#C11 = <core::String*, core::int*>{#C10:#C2)
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ static method main() → void


Extra constant evaluation status:
Evaluated: MapLiteral @ org-dartlang-testcase:///const_functions_map.dart:9:17 -> InstanceConstant(const _ImmutableMap<Object*, Object*>{_ImmutableMap._kvPairs: const <dynamic>["key", "val"]})
Evaluated: MapLiteral @ org-dartlang-testcase:///const_functions_map.dart:11:17 -> InstanceConstant(const _ImmutableMap<Object*, Object*>{_ImmutableMap._kvPairs: const <dynamic>["key", 2]})
Evaluated: MapLiteral @ org-dartlang-testcase:///const_functions_map.dart:13:17 -> InstanceConstant(const _ImmutableMap<Object*, Object*>{_ImmutableMap._kvPairs: const <dynamic>["key", 2]})
Evaluated: MapLiteral @ org-dartlang-testcase:///const_functions_map.dart:15:13 -> InstanceConstant(const _ImmutableMap<String*, int*>{_ImmutableMap._kvPairs: const <dynamic>["key1", 2, "key2", 3, "key3", 4]})
Evaluated: StaticGet @ org-dartlang-testcase:///const_functions_map.dart:16:17 -> InstanceConstant(const _ImmutableMap<String*, int*>{_ImmutableMap._kvPairs: const <dynamic>["key1", 2, "key2", 3, "key3", 4]})
Evaluated: StaticGet @ org-dartlang-testcase:///const_functions_map.dart:17:17 -> InstanceConstant(const _ImmutableMap<String*, int*>{_ImmutableMap._kvPairs: const <dynamic>["key1", 2, "key2", 3, "key3", 4]})
Evaluated: StaticGet @ org-dartlang-testcase:///const_functions_map.dart:18:17 -> InstanceConstant(const _ImmutableMap<String*, int*>{_ImmutableMap._kvPairs: const <dynamic>["key1", 2, "key2", 3, "key3", 4]})
Evaluated: MapLiteral @ org-dartlang-testcase:///const_functions_map.dart:9:17 -> MapConstant(const <Object*, Object*>{"key": "val"})
Evaluated: MapLiteral @ org-dartlang-testcase:///const_functions_map.dart:11:17 -> MapConstant(const <Object*, Object*>{"key": 2})
Evaluated: MapLiteral @ org-dartlang-testcase:///const_functions_map.dart:13:17 -> MapConstant(const <Object*, Object*>{"key": 2})
Evaluated: MapLiteral @ org-dartlang-testcase:///const_functions_map.dart:15:13 -> MapConstant(const <String*, int*>{"key1": 2, "key2": 3, "key3": 4})
Evaluated: StaticGet @ org-dartlang-testcase:///const_functions_map.dart:16:17 -> MapConstant(const <String*, int*>{"key1": 2, "key2": 3, "key3": 4})
Evaluated: StaticGet @ org-dartlang-testcase:///const_functions_map.dart:17:17 -> MapConstant(const <String*, int*>{"key1": 2, "key2": 3, "key3": 4})
Evaluated: StaticGet @ org-dartlang-testcase:///const_functions_map.dart:18:17 -> MapConstant(const <String*, int*>{"key1": 2, "key2": 3, "key3": 4})
Extra constant evaluation: evaluated: 14, effectively constant: 7
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import "package:expect/expect.dart";
static const field core::Object? var1 = #C1;
static const field core::Object? var2 = #C2;
static const field core::Object? var3 = #C3;
static const field core::Map<core::String, core::int> map = #C10;
static const field core::Map<core::String, core::int> map = #C9;
static const field core::Object? var4 = #C2;
static const field core::Object? var5 = #C6;
static const field core::Object? var6 = #C8;
Expand All @@ -17,7 +17,7 @@ static method fn(core::Map<core::Object, core::Object> map, core::Object key)
return map.{core::Map::[]}(key){(core::Object?) → core::Object?};
}
static method fn2() → core::int? {
return (#C13).{core::Map::[]}("key"){(core::Object?) → core::int?};
return (#C11).{core::Map::[]}("key"){(core::Object?) → core::int?};
}
static method main() → void {
exp::Expect::equals(#C1, "val");
Expand All @@ -38,9 +38,7 @@ constants {
#C6 = 3
#C7 = "key3"
#C8 = 4
#C9 = <dynamic>[#C4, #C2, #C5, #C6, #C7, #C8]
#C10 = core::_ImmutableMap<core::String*, core::int*> {_kvPairs:#C9}
#C11 = "key"
#C12 = <dynamic>[#C11, #C2]
#C13 = core::_ImmutableMap<core::String*, core::int*> {_kvPairs:#C12}
#C9 = <core::String*, core::int*>{#C4:#C2, #C5:#C6, #C7:#C8)
#C10 = "key"
#C11 = <core::String*, core::int*>{#C10:#C2)
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,35 +23,34 @@ extension FunctionApplier on core::Function {
static method m<X extends core::Object? = dynamic>(self::m::X% x) → core::List<self::m::X%>
return <self::m::X%>[x];
static method FunctionApplier|applyAndPrint(lowered final core::Function #this, core::List<core::Object?> positionalArguments) → void
return core::print(core::Function::apply(#this, positionalArguments, #C2));
return core::print(core::Function::apply(#this, positionalArguments, #C1));
static method FunctionApplier|get#applyAndPrint(lowered final core::Function #this) → (core::List<core::Object?>) → void
return (core::List<core::Object?> positionalArguments) → void => self::FunctionApplier|applyAndPrint(#this, positionalArguments);
static method test() → dynamic {
(#C4).{core::Object::toString}(){() → core::String};
(#C3).{core::Object::toString}(){() → core::String};
}
static method main() → void {
self::A<dynamic> a = new self::A::•<dynamic>();
self::FunctionApplier|applyAndPrint(a.{self::A::m}{<X extends core::Object? = dynamic>(X%) → core::List<X%>}<core::int>, <core::Object?>[2]);
self::FunctionApplier|applyAndPrint(a.{self::A::m}{<X extends core::Object? = dynamic>(X%) → core::List<X%>}<core::String>, <core::Object?>["three"]);
self::FunctionApplier|applyAndPrint(#C6, <core::Object?>[2]);
self::FunctionApplier|applyAndPrint(#C7, <core::Object?>["three"]);
self::FunctionApplier|applyAndPrint(#C9, <core::Object?>[2]);
self::FunctionApplier|applyAndPrint(#C10, <core::Object?>["three"]);
self::FunctionApplier|applyAndPrint(#C6, <core::Object?>[2]);
self::FunctionApplier|applyAndPrint(#C7, <core::Object?>["three"]);
self::FunctionApplier|applyAndPrint(#C5, <core::Object?>[2]);
self::FunctionApplier|applyAndPrint(#C6, <core::Object?>["three"]);
self::FunctionApplier|applyAndPrint(#C8, <core::Object?>[2]);
self::FunctionApplier|applyAndPrint(#C9, <core::Object?>["three"]);
self::FunctionApplier|applyAndPrint(#C5, <core::Object?>[2]);
self::FunctionApplier|applyAndPrint(#C6, <core::Object?>["three"]);
(#C2).{core::Object::toString}(){() → core::String};
(#C3).{core::Object::toString}(){() → core::String};
(#C4).{core::Object::toString}(){() → core::String};
}

constants {
#C1 = <dynamic>[]
#C2 = core::_ImmutableMap<core::Symbol, dynamic> {_kvPairs:#C1}
#C3 = constructor-tearoff self::A::named
#C4 = instantiation self::A::named <core::int>
#C5 = static-tearoff self::A::n
#C6 = instantiation self::A::n <core::int>
#C7 = instantiation self::A::n <core::String>
#C8 = static-tearoff self::m
#C9 = instantiation self::m <core::int>
#C10 = instantiation self::m <core::String>
#C1 = <core::Symbol, dynamic>{)
#C2 = constructor-tearoff self::A::named
#C3 = instantiation self::A::named <core::int>
#C4 = static-tearoff self::A::n
#C5 = instantiation self::A::n <core::int>
#C6 = instantiation self::A::n <core::String>
#C7 = static-tearoff self::m
#C8 = instantiation self::m <core::int>
#C9 = instantiation self::m <core::String>
}

0 comments on commit 2b5adb7

Please sign in to comment.