Skip to content

Commit 560b35a

Browse files
RoyCommit Queue
authored andcommitted
[vm] Adding owner_class field to Function and Field objects.
TEST=vm/dart/analyze_snapshot_binary_test Change-Id: I6ea4630a3be7074c63910e1904381b04e37e6e90 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/431705 Reviewed-by: Slava Egorov <[email protected]> Reviewed-by: Martin Kustermann <[email protected]> Auto-Submit: Roy Tu <[email protected]> Commit-Queue: Martin Kustermann <[email protected]>
1 parent 3aa600d commit 560b35a

File tree

3 files changed

+88
-20
lines changed

3 files changed

+88
-20
lines changed

runtime/tests/vm/dart/analyze_snapshot_binary_test.dart

Lines changed: 67 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -204,14 +204,14 @@ Future<void> testAOT(
204204
);
205205

206206
// Ensure instance fields of classes are reported.
207-
final baseClass =
208-
objects[classnames.entries
209-
.singleWhere((e) => e.value == 'FieldTestBase')
210-
.key];
211-
final subClass =
212-
objects[classnames.entries
213-
.singleWhere((e) => e.value == 'FieldTestSub')
214-
.key];
207+
final baseClassId = classnames.entries
208+
.singleWhere((e) => e.value == 'FieldTestBase')
209+
.key;
210+
final baseClass = objects[baseClassId];
211+
final subClassId = classnames.entries
212+
.singleWhere((e) => e.value == 'FieldTestSub')
213+
.key;
214+
final subClass = objects[subClassId];
215215
final baseFieldIds = baseClass['fields'];
216216
final baseFields = [for (final int id in baseFieldIds) objects[id]];
217217
final baseSlots = baseClass['instance_slots']
@@ -222,7 +222,7 @@ Future<void> testAOT(
222222
final subSlots = subClass['instance_slots'];
223223

224224
// We have:
225-
// class Base {
225+
// class FieldTestBase {
226226
// static int baseS0 = int.parse('1');
227227
// static int baseS1 = int.parse('2');
228228
// int base0;
@@ -233,12 +233,22 @@ Future<void> testAOT(
233233
// }
234234
//
235235
// This static field is never tree shaken.
236-
expectField(baseFields[0], name: 'baseS0', flags: ['static']);
237-
expectField(baseFields[1], name: 'baseS1', flags: ['static']);
236+
expectField(
237+
baseFields[0],
238+
name: 'baseS0',
239+
flags: ['static'],
240+
ownerClass: baseClassId,
241+
);
242+
expectField(
243+
baseFields[1],
244+
name: 'baseS1',
245+
flags: ['static'],
246+
ownerClass: baseClassId,
247+
);
238248

239249
// Neighboring static fields should always be one word away
240-
final int staticFieldOffset0 = baseFields[0]["static_field_offset"];
241-
final int staticFieldOffset1 = baseFields[1]["static_field_offset"];
250+
final int staticFieldOffset0 = baseFields[0]['static_field_offset'];
251+
final int staticFieldOffset1 = baseFields[1]['static_field_offset'];
242252
Expect.equals(staticFieldOffset1 - staticFieldOffset0, wordSize);
243253

244254
if (isProduct) {
@@ -277,25 +287,29 @@ Future<void> testAOT(
277287
expectField(
278288
baseFields[2],
279289
name: 'base0',
290+
ownerClass: baseClassId,
280291
isReference: false,
281292
unboxedType: 'int',
282293
);
283294
expectField(
284295
baseFields[3],
285296
name: 'base1',
297+
ownerClass: baseClassId,
286298
isReference: false,
287299
unboxedType: 'double',
288300
);
289-
expectField(baseFields[4], name: 'base2');
301+
expectField(baseFields[4], name: 'base2', ownerClass: baseClassId);
290302
expectField(
291303
baseFields[5],
292304
name: 'base3',
305+
ownerClass: baseClassId,
293306
isReference: false,
294307
unboxedType: 'Float32x4',
295308
);
296309
expectField(
297310
baseFields[6],
298311
name: 'base4',
312+
ownerClass: baseClassId,
299313
isReference: false,
300314
unboxedType: 'Float64x2',
301315
);
@@ -336,13 +350,23 @@ Future<void> testAOT(
336350
);
337351
}
338352
// We have:
339-
// class Sub<T> extends Base{
353+
// class FieldTestSub<T> extends FieldTestBase{
340354
// late int subL1 = int.parse('1');
341355
// late final double subL2 = double.parse('1.2');
342356
// }
343357
// These late instance fields are never tree shaken.
344-
expectField(subFields[0], name: 'subL1', flags: ['late']);
345-
expectField(subFields[1], name: 'subL2', flags: ['final', 'late']);
358+
expectField(
359+
subFields[0],
360+
name: 'subL1',
361+
flags: ['late'],
362+
ownerClass: subClassId,
363+
);
364+
expectField(
365+
subFields[1],
366+
name: 'subL2',
367+
flags: ['final', 'late'],
368+
ownerClass: subClassId,
369+
);
346370
expectTypeArgumentsSlot(
347371
subSlots[0],
348372
offsetReferences: 1,
@@ -399,6 +423,28 @@ Future<void> testAOT(
399423
}
400424
Expect.isTrue(totalGap < 500);
401425
Expect.isTrue((totalSize + totalGap - textSectionSize) < 500);
426+
427+
// Ensure that functions correctly report their owners
428+
// `forceDrops` removes all Function objects, so we skip the test there
429+
if (!forceDrops) {
430+
final myBaseClass =
431+
objects[classnames.entries
432+
.singleWhere((e) => e.value == 'MyBase')
433+
.key];
434+
final mySubClass =
435+
objects[classnames.entries
436+
.singleWhere((e) => e.value == 'MySub')
437+
.key];
438+
439+
final functions = objects.where((o) => o['type'] == 'Function').toList();
440+
441+
final fooFunc = functions.singleWhere((o) => o['name'] == 'MyBase.foo');
442+
443+
final barFunc = functions.singleWhere((o) => o['name'] == 'MySub.bar');
444+
445+
Expect.equals(fooFunc['owner_class'], myBaseClass['id']);
446+
Expect.equals(barFunc['owner_class'], mySubClass['id']);
447+
}
402448
});
403449
}
404450

@@ -408,8 +454,12 @@ void expectField(
408454
List<String> flags = const [],
409455
bool isReference = true,
410456
String? unboxedType,
457+
int? ownerClass,
411458
}) {
412459
Expect.equals(name, fieldJson['name']);
460+
if (ownerClass != null) {
461+
Expect.equals(ownerClass, fieldJson['owner_class']);
462+
}
413463
Expect.equals(isReference, fieldJson['is_reference']);
414464
Expect.listEquals(flags, fieldJson['flags']);
415465
if (unboxedType != null) {

runtime/tests/vm/dart/analyze_snapshot_program.dart

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,22 @@ final channel2 = MethodChannel("channel2");
1818
const constChannel = MethodChannel("constChannel1");
1919
const constChannel2 = MethodChannel("constChannel2");
2020

21-
class MyBase {}
21+
class MyBase {
22+
@pragma('vm:never-inline')
23+
void foo() => print('foo!');
24+
}
2225

23-
class MyInterface {}
26+
class MyInterface {
27+
@pragma('vm:never-inline')
28+
void bar() => print('bar default!');
29+
}
2430

25-
class MySub extends MyBase implements MyInterface {}
31+
class MySub extends MyBase implements MyInterface {
32+
@pragma('vm:never-inline')
33+
void bar() => print('bar override!');
34+
}
35+
36+
final mySub1 = MySub();
2637

2738
main() {
2839
final mcs = [channel1, channel2, constChannel, constChannel2];
@@ -31,6 +42,9 @@ main() {
3142
}
3243
print('Class: ${MySub()}');
3344

45+
mySub1.foo();
46+
mySub1.bar();
47+
3448
final l = [
3549
FieldTestBase(2, 2.2, null, Float32x4.zero(), Float64x2.zero()),
3650
FieldTestSub<int>(),
@@ -53,6 +67,7 @@ class FieldTestBase {
5367
baseS1++;
5468
}
5569

70+
@pragma('vm:never-inline')
5671
String foo() =>
5772
'Base.foo: [$baseS0, $baseS1, $base0, $base1, $base2, $base3, $base4]';
5873
}
@@ -70,5 +85,6 @@ class FieldTestSub<T> extends FieldTestBase {
7085
Float64x2(2.1, 2.2),
7186
);
7287

88+
@pragma('vm:never-inline')
7389
String foo() => '${super.foo()} Sub<$T>.foo: [$subL1, $subL2]';
7490
}

runtime/vm/analyze_snapshot_api_impl.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ void SnapshotAnalyzer::DumpFunction(const Function& function) {
258258
String::Handle(function.InternalSignature()).ToCString());
259259

260260
js_.PrintProperty("code", GetObjectId(function.CurrentCode()));
261+
js_.PrintProperty("owner_class", GetObjectId(function.Owner()));
261262
if (function.IsClosureFunction()) {
262263
js_.PrintProperty("parent_function",
263264
GetObjectId(function.parent_function()));
@@ -373,6 +374,7 @@ void SnapshotAnalyzer::DumpField(const Field& field) {
373374
js_.PrintProperty("type", "Field");
374375
js_.PrintProperty("name", name.ToCString());
375376
js_.PrintProperty64("type_class", GetObjectId(field.type()));
377+
js_.PrintProperty("owner_class", GetObjectId(field.Owner()));
376378
if (field.is_static()) {
377379
js_.PrintProperty("instance", GetObjectId(field.StaticValue()));
378380
js_.PrintProperty64("static_field_offset",

0 commit comments

Comments
 (0)