Skip to content

Commit 34e41dd

Browse files
mosuemCommit Queue
authored andcommitted
[record_use] Record instances in calls
So that calls with const instances as arguments can be recorded. Tested: pkg/vm/testcases/transformations/record_use/* Change-Id: I918e7486b2772bb6d014abb9f01f4347e24ac0b1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/436300 Commit-Queue: Moritz Sümmermann <[email protected]> Reviewed-by: Daco Harkes <[email protected]>
1 parent eb0c7ed commit 34e41dd

10 files changed

+306
-10
lines changed

pkg/vm/lib/transformations/record_use/record_instance.dart

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,15 +81,7 @@ class InstanceRecorder {
8181
ast.InstanceConstant constant,
8282
) => InstanceReference(
8383
location: expression.location!.recordLocation(_source, exactLocation),
84-
instanceConstant: _fieldsFromConstant(constant),
84+
instanceConstant: evaluateInstanceConstant(constant),
8585
loadingUnit: loadingUnitForNode(expression, _loadingUnits).toString(),
8686
);
87-
88-
InstanceConstant _fieldsFromConstant(ast.InstanceConstant constant) =>
89-
InstanceConstant(
90-
fields: constant.fieldValues.map(
91-
(key, value) =>
92-
MapEntry(key.asField.name.text, evaluateConstant(value)),
93-
),
94-
);
9587
}

pkg/vm/lib/transformations/record_use/record_use.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,9 @@ Constant evaluateConstant(ast.Constant constant) => switch (constant) {
129129
ast.ListConstant() => ListConstant(
130130
constant.entries.map(evaluateConstant).toList(),
131131
),
132+
ast.InstanceConstant() => evaluateInstanceConstant(constant),
132133
// The following are not supported, but theoretically could be, so they
133134
// are listed explicitly here.
134-
ast.InstanceConstant() => _unsupported('InstanceConstant'),
135135
ast.AuxiliaryConstant() => _unsupported('AuxiliaryConstant'),
136136
ast.SetConstant() => _unsupported('SetConstant'),
137137
ast.RecordConstant() => _unsupported('RecordConstant'),
@@ -151,6 +151,14 @@ Constant evaluateLiteral(ast.BasicLiteral expression) => switch (expression) {
151151
ast.BasicLiteral() => _unsupported(expression.runtimeType.toString()),
152152
};
153153

154+
InstanceConstant evaluateInstanceConstant(ast.InstanceConstant constant) =>
155+
InstanceConstant(
156+
fields: constant.fieldValues.map(
157+
(key, value) =>
158+
MapEntry(key.asField.name.text, evaluateConstant(value)),
159+
),
160+
);
161+
154162
Never _unsupported(String constantType) =>
155163
throw UnsupportedError('$constantType is not supported for recording.');
156164

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) 2025, 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 'package:meta/meta.dart' show RecordUse;
6+
7+
void main() {
8+
doSomething();
9+
}
10+
11+
@MyClass(A.a)
12+
void doSomething() {
13+
print('a');
14+
}
15+
16+
@RecordUse()
17+
class MyClass {
18+
final A a;
19+
20+
const MyClass(this.a);
21+
}
22+
23+
enum A { a, b }
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
library #lib;
2+
import self as self;
3+
import "package:meta/meta.dart" as meta;
4+
import "dart:core" as core;
5+
6+
import "package:meta/meta.dart" show RecordUse;
7+
8+
@#C1
9+
class MyClass extends core::Object /*hasConstConstructor*/ {
10+
11+
[@vm.inferred-type.metadata=#lib::A (value: const #lib::A{dart.core::_Enum.index: 0, dart.core::_Enum._name: "a"})]
12+
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]
13+
final field self::A a;
14+
}
15+
class A extends core::_Enum /*isEnum*/ {
16+
17+
[@vm.inferred-return-type.metadata=!]
18+
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]
19+
method core::_enumToString() → core::String
20+
return "A.${[@vm.direct-call.metadata=dart.core::_Enum._name] this.{core::_Enum::_name}{core::String}}";
21+
}
22+
23+
[@vm.inferred-return-type.metadata=dart.core::Null? (value: null)]
24+
static method main() → void {
25+
self::doSomething();
26+
}
27+
28+
[@vm.inferred-return-type.metadata=dart.core::Null? (value: null)]
29+
@#C5
30+
static method doSomething() → void {
31+
core::print("a");
32+
}
33+
constants {
34+
#C1 = meta::RecordUse {}
35+
#C2 = 0
36+
#C3 = "a"
37+
#C4 = self::A {index:#C2, _name:#C3}
38+
#C5 = self::MyClass {a:#C4}
39+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{
2+
"metadata": {
3+
"comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
4+
"version": "0.2.0"
5+
},
6+
"constants": [
7+
{
8+
"type": "int",
9+
"value": 0
10+
},
11+
{
12+
"type": "String",
13+
"value": "a"
14+
},
15+
{
16+
"type": "Instance",
17+
"value": {
18+
"index": 0,
19+
"_name": 1
20+
}
21+
},
22+
{
23+
"type": "Instance",
24+
"value": {
25+
"a": 2
26+
}
27+
}
28+
],
29+
"locations": [
30+
{
31+
"uri": "record_enum.dart"
32+
}
33+
],
34+
"recordings": [
35+
{
36+
"definition": {
37+
"identifier": {
38+
"uri": "record_enum.dart",
39+
"name": "MyClass"
40+
},
41+
"loading_unit": "1"
42+
},
43+
"instances": [
44+
{
45+
"constant_index": 3,
46+
"loading_unit": "1",
47+
"@": 0
48+
}
49+
]
50+
}
51+
]
52+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
library #lib;
2+
import self as self;
3+
import "package:meta/meta.dart" as meta;
4+
import "dart:core" as core;
5+
6+
import "package:meta/meta.dart" show RecordUse;
7+
8+
@#C1
9+
class MyClass extends core::Object /*hasConstConstructor*/ {
10+
11+
[@vm.inferred-type.metadata=#lib::A (value: const #lib::A{#lib::A.i: 42})]
12+
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]
13+
final field self::A a;
14+
}
15+
class A extends core::Object /*hasConstConstructor*/ {
16+
17+
[@vm.inferred-type.metadata=dart.core::_Smi (value: 42)]
18+
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]
19+
[@vm.unboxing-info.metadata=()->i]
20+
final field core::int i;
21+
}
22+
23+
[@vm.inferred-return-type.metadata=dart.core::Null? (value: null)]
24+
static method main() → void {
25+
self::doSomething();
26+
}
27+
28+
[@vm.inferred-return-type.metadata=dart.core::Null? (value: null)]
29+
@#C4
30+
static method doSomething() → void {
31+
core::print("a");
32+
}
33+
constants {
34+
#C1 = meta::RecordUse {}
35+
#C2 = 42
36+
#C3 = self::A {i:#C2}
37+
#C4 = self::MyClass {a:#C3}
38+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"metadata": {
3+
"comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
4+
"version": "0.2.0"
5+
},
6+
"constants": [
7+
{
8+
"type": "int",
9+
"value": 42
10+
},
11+
{
12+
"type": "Instance",
13+
"value": {
14+
"i": 0
15+
}
16+
},
17+
{
18+
"type": "Instance",
19+
"value": {
20+
"a": 1
21+
}
22+
}
23+
],
24+
"locations": [
25+
{
26+
"uri": "record_instance_constant.dart"
27+
}
28+
],
29+
"recordings": [
30+
{
31+
"definition": {
32+
"identifier": {
33+
"uri": "record_instance_constant.dart",
34+
"name": "MyClass"
35+
},
36+
"loading_unit": "1"
37+
},
38+
"instances": [
39+
{
40+
"constant_index": 2,
41+
"loading_unit": "1",
42+
"@": 0
43+
}
44+
]
45+
}
46+
]
47+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) 2025, 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 'package:meta/meta.dart' show RecordUse;
6+
7+
void main() {
8+
doSomething();
9+
}
10+
11+
@MyClass(const A())
12+
void doSomething() {
13+
print('a');
14+
}
15+
16+
@RecordUse()
17+
class MyClass {
18+
final A a;
19+
20+
const MyClass(this.a);
21+
}
22+
23+
class A {
24+
const A();
25+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
library #lib;
2+
import self as self;
3+
import "package:meta/meta.dart" as meta;
4+
import "dart:core" as core;
5+
6+
import "package:meta/meta.dart" show RecordUse;
7+
8+
@#C1
9+
class MyClass extends core::Object /*hasConstConstructor*/ {
10+
11+
[@vm.inferred-type.metadata=#lib::A (value: const #lib::A{})]
12+
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]
13+
final field self::A a;
14+
}
15+
class A extends core::Object /*hasConstConstructor*/ {
16+
}
17+
18+
[@vm.inferred-return-type.metadata=dart.core::Null? (value: null)]
19+
static method main() → void {
20+
self::doSomething();
21+
}
22+
23+
[@vm.inferred-return-type.metadata=dart.core::Null? (value: null)]
24+
@#C3
25+
static method doSomething() → void {
26+
core::print("a");
27+
}
28+
constants {
29+
#C1 = meta::RecordUse {}
30+
#C2 = self::A {}
31+
#C3 = self::MyClass {a:#C2}
32+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"metadata": {
3+
"comment": "Recorded usages of objects tagged with a `RecordUse` annotation",
4+
"version": "0.2.0"
5+
},
6+
"constants": [
7+
{
8+
"type": "Instance"
9+
},
10+
{
11+
"type": "Instance",
12+
"value": {
13+
"a": 0
14+
}
15+
}
16+
],
17+
"locations": [
18+
{
19+
"uri": "record_instance_constant_empty.dart"
20+
}
21+
],
22+
"recordings": [
23+
{
24+
"definition": {
25+
"identifier": {
26+
"uri": "record_instance_constant_empty.dart",
27+
"name": "MyClass"
28+
},
29+
"loading_unit": "1"
30+
},
31+
"instances": [
32+
{
33+
"constant_index": 1,
34+
"loading_unit": "1",
35+
"@": 0
36+
}
37+
]
38+
}
39+
]
40+
}

0 commit comments

Comments
 (0)