Skip to content

Commit 2fcc9bd

Browse files
liamappelbeCommit Queue
authored andcommitted
[ VM / Service ] Add librariesAlreadyCompiled to getSourceReport RPC
The goal is to have the flutter test framework skip compilation of libraries it's already seen. See option 3 from this doc: https://docs.google.com/document/d/193DKN1DmbHdphhbC8RngdkSafHQGF2QEmf-qDxqSIrk/edit#heading=h.fn9090oeqrk3 Change-Id: Ia76bbb35df22dee6e9f8b32f90bbf2ef2fa18913 TEST=source_report_libraries_already_compiled_test.dart Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/321660 Reviewed-by: Ben Konyi <bkonyi@google.com> Commit-Queue: Liam Appelbe <liama@google.com>
1 parent 685af75 commit 2fcc9bd

File tree

13 files changed

+263
-28
lines changed

13 files changed

+263
-28
lines changed

pkg/vm_service/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 12.0.0
2+
- Update to version `4.13` of the spec.
3+
- Add optional `librariesAlreadyCompiled` parameter to `getSourceReport` RPC.
4+
15
## 11.10.0
26
- Add `wsUri` property to `VmService`. If set, this property can be used to associate
37
a `VmService` instance to its targeted VM service based on its URI.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version=4.12
1+
version=4.14

pkg/vm_service/lib/src/vm_service.dart

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export 'snapshot_graph.dart'
2828
HeapSnapshotObjectNoData,
2929
HeapSnapshotObjectNullData;
3030

31-
const String vmServiceVersion = '4.12.0';
31+
const String vmServiceVersion = '4.13.0';
3232

3333
/// @optional
3434
const String optional = 'optional';
@@ -975,6 +975,15 @@ abstract class VmServiceInterface {
975975
/// filter strings. For example, pass `["package:foo/"]` to only include
976976
/// scripts from the foo package.
977977
///
978+
/// The `librariesAlreadyCompiled` parameter overrides the `forceCompilation`
979+
/// parameter on a per-library basis, setting it to `false` for any libary in
980+
/// this list. This is useful for cases where multiple `getSourceReport` RPCs
981+
/// are sent with `forceCompilation` enabled, to avoid recompiling the same
982+
/// libraries repeatedly. To use this parameter, enable `forceCompilation`,
983+
/// cache the results of each `getSourceReport` RPC, and pass all the
984+
/// libraries mentioned in the `SourceReport` to subsequent RPCs in the
985+
/// `librariesAlreadyCompiled`.
986+
///
978987
/// If `isolateId` refers to an isolate which has exited, then the `Collected`
979988
/// [Sentinel] is returned.
980989
///
@@ -991,6 +1000,7 @@ abstract class VmServiceInterface {
9911000
bool? forceCompile,
9921001
bool? reportLines,
9931002
List<String>? libraryFilters,
1003+
List<String>? librariesAlreadyCompiled,
9941004
});
9951005

9961006
/// The `getVersion` RPC is used to determine what version of the Service
@@ -1699,6 +1709,7 @@ class VmServerConnection {
16991709
forceCompile: params['forceCompile'],
17001710
reportLines: params['reportLines'],
17011711
libraryFilters: params['libraryFilters'],
1712+
librariesAlreadyCompiled: params['librariesAlreadyCompiled'],
17021713
);
17031714
break;
17041715
case 'getVersion':
@@ -2286,6 +2297,7 @@ class VmService implements VmServiceInterface {
22862297
bool? forceCompile,
22872298
bool? reportLines,
22882299
List<String>? libraryFilters,
2300+
List<String>? librariesAlreadyCompiled,
22892301
}) =>
22902302
_call('getSourceReport', {
22912303
'isolateId': isolateId,
@@ -2296,6 +2308,8 @@ class VmService implements VmServiceInterface {
22962308
if (forceCompile != null) 'forceCompile': forceCompile,
22972309
if (reportLines != null) 'reportLines': reportLines,
22982310
if (libraryFilters != null) 'libraryFilters': libraryFilters,
2311+
if (librariesAlreadyCompiled != null)
2312+
'librariesAlreadyCompiled': librariesAlreadyCompiled,
22992313
});
23002314

23012315
@override

pkg/vm_service/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: vm_service
2-
version: 11.10.0
2+
version: 12.0.0
33
description: >-
44
A library to communicate with a service implementing the Dart VM
55
service protocol.
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
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:io';
6+
import 'dart:developer';
7+
import 'package:test/test.dart';
8+
import 'package:vm_service/vm_service.dart';
9+
import 'common/service_test_common.dart';
10+
import 'common/test_helper.dart';
11+
12+
// ignore_for_file: dead_code
13+
14+
class Class {
15+
void method() {
16+
print("hit");
17+
}
18+
19+
void missed() {
20+
print("miss");
21+
}
22+
}
23+
24+
void unusedFunction() {
25+
print("miss");
26+
}
27+
28+
void testFunction() {
29+
if (true) {
30+
print("hit");
31+
Class().method();
32+
} else {
33+
print("miss");
34+
unusedFunction();
35+
}
36+
debugger();
37+
}
38+
39+
const ignoreHitsBelowThisLine = 39;
40+
41+
const allHits = [15, 16, 28, 30, 31, 36];
42+
final tests = <IsolateTest>[
43+
hasStoppedAtBreakpoint,
44+
librariesAlreadyCompiledTest(false, [], allHits, [33, 34]),
45+
librariesAlreadyCompiledTest(true, [target], allHits, [33, 34]),
46+
librariesAlreadyCompiledTest(true, [], allHits, [19, 20, 24, 25, 33, 34]),
47+
resumeIsolate,
48+
];
49+
50+
final target = Platform.script.toString();
51+
52+
librariesAlreadyCompiledTest(
53+
bool forceCompile,
54+
List<String> librariesAlreadyCompiled,
55+
List<int> expectedHits,
56+
List<int> expectedMisses,
57+
) =>
58+
(VmService service, IsolateRef isolateRef) async {
59+
final isolateId = isolateRef.id!;
60+
61+
final report = await service.getSourceReport(
62+
isolateId,
63+
[SourceReportKind.kCoverage],
64+
forceCompile: forceCompile,
65+
reportLines: true,
66+
librariesAlreadyCompiled: librariesAlreadyCompiled,
67+
);
68+
69+
addLines(List<int>? lines, Set<int> out) {
70+
for (final line in lines ?? []) {
71+
if (line < ignoreHitsBelowThisLine) {
72+
out.add(line);
73+
}
74+
}
75+
}
76+
77+
final hits = <int>{};
78+
final misses = <int>{};
79+
for (final range in report.ranges!) {
80+
if (report.scripts?[range.scriptIndex!].uri == target) {
81+
addLines(range.coverage?.hits, hits);
82+
addLines(range.coverage?.misses, misses);
83+
}
84+
}
85+
86+
expect(hits, unorderedEquals(expectedHits));
87+
expect(misses, unorderedEquals(expectedMisses));
88+
};
89+
90+
main([args = const <String>[]]) async => await runIsolateTests(
91+
args,
92+
tests,
93+
target,
94+
testeeConcurrent: testFunction,
95+
);

runtime/observatory/tests/service/get_version_rpc_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ var tests = <VMTest>[
1212
final result = await vm.invokeRpcNoUpgrade('getVersion', {});
1313
expect(result['type'], 'Version');
1414
expect(result['major'], 4);
15-
expect(result['minor'], 12);
15+
expect(result['minor'], 13);
1616
expect(result['_privateMajor'], 0);
1717
expect(result['_privateMinor'], 0);
1818
},

runtime/observatory_2/tests/service_2/get_version_rpc_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ var tests = <VMTest>[
1212
final result = await vm.invokeRpcNoUpgrade('getVersion', {});
1313
expect(result['type'], equals('Version'));
1414
expect(result['major'], equals(4));
15-
expect(result['minor'], equals(12));
15+
expect(result['minor'], equals(13));
1616
expect(result['_privateMajor'], equals(0));
1717
expect(result['_privateMinor'], equals(0));
1818
},

runtime/vm/service.cc

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3620,12 +3620,12 @@ static void GetInstancesAsList(Thread* thread, JSONStream* js) {
36203620
instances.PrintJSON(js, /*ref=*/true);
36213621
}
36223622

3623-
static intptr_t ParseJSONArray(Thread* thread,
3624-
const char* str,
3625-
const GrowableObjectArray& elements) {
3623+
template <typename Adder>
3624+
static intptr_t ParseJSONCollection(Thread* thread,
3625+
const char* str,
3626+
const Adder& add) {
36263627
ASSERT(str != nullptr);
36273628
ASSERT(thread != nullptr);
3628-
Zone* zone = thread->zone();
36293629
intptr_t n = strlen(str);
36303630
if (n < 2) {
36313631
return -1;
@@ -3640,15 +3640,37 @@ static intptr_t ParseJSONArray(Thread* thread,
36403640
// Empty element
36413641
break;
36423642
}
3643-
String& element = String::Handle(
3644-
zone, String::FromUTF8(reinterpret_cast<const uint8_t*>(&str[start]),
3645-
end - start + 1));
3646-
elements.Add(element);
3643+
add(&str[start], end - start + 1);
36473644
start = end + 3;
36483645
}
36493646
return 0;
36503647
}
36513648

3649+
static intptr_t ParseJSONArray(Thread* thread,
3650+
const char* str,
3651+
const GrowableObjectArray& elements) {
3652+
Zone* zone = thread->zone();
3653+
return ParseJSONCollection(
3654+
thread, str, [zone, &elements](const char* start, intptr_t length) {
3655+
String& element = String::Handle(
3656+
zone,
3657+
String::FromUTF8(reinterpret_cast<const uint8_t*>(start), length));
3658+
elements.Add(element);
3659+
});
3660+
}
3661+
3662+
#if !defined(DART_PRECOMPILED_RUNTIME)
3663+
static intptr_t ParseJSONSet(Thread* thread,
3664+
const char* str,
3665+
ZoneCStringSet* elements) {
3666+
Zone* zone = thread->zone();
3667+
return ParseJSONCollection(
3668+
thread, str, [zone, elements](const char* start, intptr_t length) {
3669+
elements->Insert(zone->MakeCopyOfStringN(start, length));
3670+
});
3671+
}
3672+
#endif
3673+
36523674
static const MethodParameter* const get_ports_params[] = {
36533675
RUNNABLE_ISOLATE_PARAMETER,
36543676
nullptr,
@@ -3778,7 +3800,22 @@ static void GetSourceReport(Thread* thread, JSONStream* js) {
37783800
}
37793801
}
37803802

3781-
SourceReport report(report_set, library_filters, compile_mode, report_lines);
3803+
const char* libraries_already_compiled_param =
3804+
js->LookupParam("librariesAlreadyCompiled");
3805+
Zone* zone = thread->zone();
3806+
ZoneCStringSet* libraries_already_compiled = nullptr;
3807+
if (libraries_already_compiled_param != nullptr) {
3808+
libraries_already_compiled = new (zone) ZoneCStringSet(zone);
3809+
intptr_t libraries_already_compiled_length = ParseJSONSet(
3810+
thread, libraries_already_compiled_param, libraries_already_compiled);
3811+
if (libraries_already_compiled_length < 0) {
3812+
PrintInvalidParamError(js, "libraries_already_compiled");
3813+
return;
3814+
}
3815+
}
3816+
3817+
SourceReport report(report_set, library_filters, libraries_already_compiled,
3818+
compile_mode, report_lines);
37823819
report.PrintJSON(js, script, TokenPosition::Deserialize(start_pos),
37833820
TokenPosition::Deserialize(end_pos));
37843821
#endif // !DART_PRECOMPILED_RUNTIME

runtime/vm/service.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
namespace dart {
1818

1919
#define SERVICE_PROTOCOL_MAJOR_VERSION 4
20-
#define SERVICE_PROTOCOL_MINOR_VERSION 12
20+
#define SERVICE_PROTOCOL_MINOR_VERSION 13
2121

2222
class Array;
2323
class EmbedderServiceHandler;

runtime/vm/service/service.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# Dart VM Service Protocol 4.12
1+
# Dart VM Service Protocol 4.13
22

33
> Please post feedback to the [observatory-discuss group][discuss-list]
44
5-
This document describes of _version 4.12_ of the Dart VM Service Protocol. This
5+
This document describes of _version 4.13_ of the Dart VM Service Protocol. This
66
protocol is used to communicate with a running Dart Virtual Machine.
77

88
To use the Service Protocol, start the VM with the *--observe* flag.
@@ -1214,7 +1214,8 @@ SourceReport|Sentinel getSourceReport(string isolateId,
12141214
int endTokenPos [optional],
12151215
bool forceCompile [optional],
12161216
bool reportLines [optional],
1217-
string[] libraryFilters [optional])
1217+
string[] libraryFilters [optional],
1218+
string[] librariesAlreadyCompiled [optional])
12181219
```
12191220

12201221
The _getSourceReport_ RPC is used to generate a set of reports tied to
@@ -1261,6 +1262,14 @@ for the whole isolate. If it is provided, the _SourceReport_ will only contain
12611262
results from scripts with URIs that start with one of the filter strings. For
12621263
example, pass `["package:foo/"]` to only include scripts from the foo package.
12631264

1265+
The _librariesAlreadyCompiled_ parameter overrides the _forceCompilation_
1266+
parameter on a per-library basis, setting it to _false_ for any libary in this
1267+
list. This is useful for cases where multiple _getSourceReport_ RPCs are sent
1268+
with _forceCompilation_ enabled, to avoid recompiling the same libraries
1269+
repeatedly. To use this parameter, enable _forceCompilation_, cache the results
1270+
of each _getSourceReport_ RPC, and pass all the libraries mentioned in the
1271+
_SourceReport_ to subsequent RPCs in the _librariesAlreadyCompiled_.
1272+
12641273
If _isolateId_ refers to an isolate which has exited, then the
12651274
_Collected_ [Sentinel](#sentinel) is returned.
12661275

@@ -4728,5 +4737,6 @@ version | comments
47284737
4.10 | Deprecated `isSyntheticAsyncContinuation` on `Breakpoint`.
47294738
4.11 | Added `isGetter` and `isSetter` properties to `@Function` and `Function`.
47304739
4.12 | Added `@TypeParameters` and changed `TypeParameters` to extend `Object`.
4740+
4.13 | Added `librariesAlreadyCompiled` to `getSourceReport`.
47314741

47324742
[discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss

0 commit comments

Comments
 (0)