diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md index 23b475aa4b6..bc8009029c1 100644 --- a/pkg/vm_service/CHANGELOG.md +++ b/pkg/vm_service/CHANGELOG.md @@ -1,3 +1,7 @@ +## 11.9.0 +- Update to version `4.12` of the spec. +- Add `TypeParametersRef`; change supertype of `TypeParameters` to `Obj`. + ## 11.8.0 - Update to version `4.11` of the spec. - Add `isGetter` and `isSetter` properties to `FuncRef` and `Func`. diff --git a/pkg/vm_service/java/.gitignore b/pkg/vm_service/java/.gitignore index 9571fd06f44..1d4506cd3e0 100644 --- a/pkg/vm_service/java/.gitignore +++ b/pkg/vm_service/java/.gitignore @@ -139,6 +139,7 @@ src/org/dartlang/vm/service/element/Timestamp.java src/org/dartlang/vm/service/element/TypeArguments.java src/org/dartlang/vm/service/element/TypeArgumentsRef.java src/org/dartlang/vm/service/element/TypeParameters.java +src/org/dartlang/vm/service/element/TypeParametersRef.java src/org/dartlang/vm/service/element/UnresolvedSourceLocation.java src/org/dartlang/vm/service/element/UriList.java src/org/dartlang/vm/service/element/VM.java diff --git a/pkg/vm_service/java/version.properties b/pkg/vm_service/java/version.properties index 7898cb0f218..bfec9fb375d 100644 --- a/pkg/vm_service/java/version.properties +++ b/pkg/vm_service/java/version.properties @@ -1 +1 @@ -version=4.11 +version=4.12 diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart index fb59d07b867..439d2d58434 100644 --- a/pkg/vm_service/lib/src/vm_service.dart +++ b/pkg/vm_service/lib/src/vm_service.dart @@ -28,7 +28,7 @@ export 'snapshot_graph.dart' HeapSnapshotObjectNoData, HeapSnapshotObjectNullData; -const String vmServiceVersion = '4.11.0'; +const String vmServiceVersion = '4.12.0'; /// @optional const String optional = 'optional'; @@ -189,6 +189,7 @@ Map _typeFactories = { 'Timestamp': Timestamp.parse, '@TypeArguments': TypeArgumentsRef.parse, 'TypeArguments': TypeArguments.parse, + '@TypeParameters': TypeParametersRef.parse, 'TypeParameters': TypeParameters.parse, 'UnresolvedSourceLocation': UnresolvedSourceLocation.parse, 'UriList': UriList.parse, @@ -8826,14 +8827,49 @@ class TypeArguments extends Obj implements TypeArgumentsRef { String toString() => '[TypeArguments id: $id, name: $name, types: $types]'; } +/// `TypeParametersRef` is a reference to a `TypeParameters` object. +class TypeParametersRef extends ObjRef { + static TypeParametersRef? parse(Map? json) => + json == null ? null : TypeParametersRef._fromJson(json); + + TypeParametersRef({ + required String id, + }) : super( + id: id, + ); + + TypeParametersRef._fromJson(Map json) + : super._fromJson(json); + + @override + String get type => '@TypeParameters'; + + @override + Map toJson() { + final json = super.toJson(); + json['type'] = type; + return json; + } + + @override + int get hashCode => id.hashCode; + + @override + bool operator ==(Object other) => + other is TypeParametersRef && id == other.id; + + @override + String toString() => '[TypeParametersRef id: $id]'; +} + /// A `TypeParameters` object represents the type argument vector for some /// uninstantiated generic type. -class TypeParameters { +class TypeParameters extends Obj implements TypeParametersRef { static TypeParameters? parse(Map? json) => json == null ? null : TypeParameters._fromJson(json); /// The names of the type parameters. - List? names; + InstanceRef? names; /// The bounds set on each type parameter. TypeArgumentsRef? bounds; @@ -8845,29 +8881,44 @@ class TypeParameters { this.names, this.bounds, this.defaults, - }); + required String id, + }) : super( + id: id, + ); - TypeParameters._fromJson(Map json) { - names = List.from(json['names']); + TypeParameters._fromJson(Map json) : super._fromJson(json) { + names = createServiceObject(json['names'], const ['InstanceRef']) + as InstanceRef?; bounds = createServiceObject(json['bounds'], const ['TypeArgumentsRef']) as TypeArgumentsRef?; defaults = createServiceObject(json['defaults'], const ['TypeArgumentsRef']) as TypeArgumentsRef?; } + @override + String get type => 'TypeParameters'; + + @override Map toJson() { - final json = {}; + final json = super.toJson(); + json['type'] = type; json.addAll({ - 'names': names?.map((f) => f).toList(), + 'names': names?.toJson(), 'bounds': bounds?.toJson(), 'defaults': defaults?.toJson(), }); return json; } + @override + int get hashCode => id.hashCode; + + @override + bool operator ==(Object other) => other is TypeParameters && id == other.id; + @override String toString() => - '[TypeParameters names: $names, bounds: $bounds, defaults: $defaults]'; + '[TypeParameters id: $id, names: $names, bounds: $bounds, defaults: $defaults]'; } /// The `UnresolvedSourceLocation` class is used to refer to an unresolved diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml index 9fb0fbf8b63..f715da2002c 100644 --- a/pkg/vm_service/pubspec.yaml +++ b/pkg/vm_service/pubspec.yaml @@ -1,5 +1,5 @@ name: vm_service -version: 11.8.0 +version: 11.9.0 description: >- A library to communicate with a service implementing the Dart VM service protocol. diff --git a/pkg/vm_service/test/fetch_all_types_test.dart b/pkg/vm_service/test/fetch_all_types_test.dart new file mode 100644 index 00000000000..a6164907275 --- /dev/null +++ b/pkg/vm_service/test/fetch_all_types_test.dart @@ -0,0 +1,32 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// See https://github.com/dart-lang/sdk/issues/52893 + +import 'package:vm_service/vm_service.dart'; + +import 'common/test_helper.dart'; + +var tests = [ + (VmService service, IsolateRef isolateRef) async { + var profile = await service.getAllocationProfile(isolateRef.id!); + for (var entry in profile.members!) { + if (entry.instancesCurrent == 0) continue; + + var classRef = entry.classRef!; + print(classRef); + var instanceSet = + await service.getInstances(isolateRef.id!, classRef.id!, 10); + for (var instance in instanceSet.instances!) { + await service.getObject(isolateRef.id!, instance.id!); + } + } + }, +]; + +main(args) => runIsolateTests( + args, + tests, + 'fetch_all_types_test.dart', + ); diff --git a/runtime/observatory/lib/src/elements/instance_ref.dart b/runtime/observatory/lib/src/elements/instance_ref.dart index 4c5d32cf3c7..25615d9d3d0 100644 --- a/runtime/observatory/lib/src/elements/instance_ref.dart +++ b/runtime/observatory/lib/src/elements/instance_ref.dart @@ -149,6 +149,16 @@ class InstanceRefElement extends CustomElement implements Renderable { new SpanElement()..text = ' (${_instance.pattern!.valueAsString})' ] ]; + case M.InstanceKind.userTag: + return [ + new AnchorElement(href: Uris.inspect(_isolate, object: _instance)) + ..children = [ + new SpanElement() + ..classes = ['emphasize'] + ..text = _instance.clazz!.name, + new SpanElement()..text = ' (${_instance.name})' + ] + ]; case M.InstanceKind.stackTrace: return [ new AnchorElement(href: Uris.inspect(_isolate, object: _instance)) diff --git a/runtime/observatory/lib/src/models/objects/instance.dart b/runtime/observatory/lib/src/models/objects/instance.dart index 79410fa47d1..a777cf896af 100644 --- a/runtime/observatory/lib/src/models/objects/instance.dart +++ b/runtime/observatory/lib/src/models/objects/instance.dart @@ -139,6 +139,9 @@ enum InstanceKind { /// An instance of WeakReference weakReference, + + /// An instance of UserTag + userTag, } bool isTypedData(InstanceKind? kind) { diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart index 87c745c66f7..eea76e1cc51 100644 --- a/runtime/observatory/lib/src/service/object.dart +++ b/runtime/observatory/lib/src/service/object.dart @@ -266,6 +266,24 @@ abstract class ServiceObject implements M.ObjectRef { case 'UnlinkedCall': obj = new UnlinkedCall._empty(owner); break; + case 'ClosureData': + case 'CodeSourceMap': + case 'ContextScope': + case 'ExceptionHandlers': + case 'FfiTrampolineData': + case 'Instructions': + case 'InstructionsSection': + case 'KernelProgramInfo': + case 'LibraryPrefix': + case 'Namespace': + case 'PatchClass': + case 'WeakArray': + obj = new GenericHeapObject._empty(owner); + break; + default: + print('Unknown vmType: $vmType'); + obj = new GenericHeapObject._empty(owner); + break; } break; case 'Event': @@ -286,6 +304,9 @@ abstract class ServiceObject implements M.ObjectRef { case 'TypeArguments': obj = new TypeArguments._empty(owner); break; + case 'TypeParameters': + obj = new GenericHeapObject._empty(owner); + break; case 'Instance': obj = new Instance._empty(owner); break; @@ -427,6 +448,15 @@ abstract class HeapObject extends ServiceObject implements M.Object { } } +class GenericHeapObject extends HeapObject { + GenericHeapObject._empty(ServiceObjectOwner? owner) : super._empty(owner); + + void _update(Map map, bool mapIsRef) { + _upgradeCollection(map, isolate); + super._update(map, mapIsRef); + } +} + class RetainingObject implements M.RetainingObject { int get retainedSize => object.retainedSize!; final HeapObject object; @@ -2788,6 +2818,8 @@ M.InstanceKind stringToInstanceKind(String s) { return M.InstanceKind.finalizer; case 'WeakReference': return M.InstanceKind.weakReference; + case 'UserTag': + return M.InstanceKind.userTag; } var message = 'Unrecognized instance kind: $s'; Logger.root.severe(message); @@ -2885,6 +2917,7 @@ class Instance extends HeapObject implements M.Instance { bool get isRegExp => kind == M.InstanceKind.regExp; bool get isMirrorReference => kind == M.InstanceKind.mirrorReference; bool get isWeakProperty => kind == M.InstanceKind.weakProperty; + bool get isUserTag => kind == M.InstanceKind.userTag; bool get isClosure => kind == M.InstanceKind.closure; bool get isStackTrace => kind == M.InstanceKind.stackTrace; bool get isStackOverflowError { @@ -2926,6 +2959,9 @@ class Instance extends HeapObject implements M.Instance { valueAsStringIsTruncated = map['valueAsStringIsTruncated'] == true; closureFunction = map['closureFunction']; name = map['name']?.toString(); + if (map['label'] != null) { + name = map['label']; + } length = map['length']; pattern = map['pattern']; typeClass = map['typeClass']; @@ -3040,7 +3076,9 @@ class Instance extends HeapObject implements M.Instance { } else { typedElements = null; } - parameterizedClass = map['parameterizedClass']; + if (map['parameterizedClass'] is Class) { + parameterizedClass = map['parameterizedClass']; + } typeArguments = map['typeArguments']; parameterIndex = map['parameterIndex']; bound = map['bound']; @@ -3623,7 +3661,9 @@ class Script extends HeapObject implements M.Script { loadTime = new DateTime.fromMillisecondsSinceEpoch(loadTimeMillis); lineOffset = map['lineOffset']; columnOffset = map['columnOffset']; - _parseTokenPosTable(map['tokenPosTable']); + if (map['tokenPosTable'] != null) { + _parseTokenPosTable(map['tokenPosTable']); + } source = map['source']; _processSource(map['source']); library = map['library']; @@ -3875,21 +3915,18 @@ class PcDescriptor { } } -class PcDescriptors extends ServiceObject implements M.PcDescriptorsRef { - Class? clazz; - int? size; +class PcDescriptors extends HeapObject implements M.PcDescriptorsRef { bool get immutable => true; final List descriptors = []; PcDescriptors._empty(ServiceObjectOwner? owner) : super._empty(owner) {} void _update(Map m, bool mapIsRef) { + _upgradeCollection(m, isolate); + super._update(m, mapIsRef); if (mapIsRef) { return; } - _upgradeCollection(m, isolate); - clazz = m['class']; - size = m['size']; descriptors.clear(); for (var descriptor in m['members']) { var pcOffset = int.parse(descriptor['pcOffset'], radix: 16); @@ -4435,7 +4472,12 @@ class Code extends HeapObject implements M.Code { var tryIndex = descriptor['tryIndex']; var kind = descriptor['kind'].trim(); - var instruction = instructionsByAddressOffset![address - startAddress]; + CodeInstruction? instruction = null; + int addressOffset = address - startAddress; + if ((addressOffset >= 0) && + (addressOffset < instructionsByAddressOffset!.length)) { + instruction = instructionsByAddressOffset![addressOffset]; + } if (instruction != null) { instruction.descriptors .add(new PcDescriptor(pcOffset, deoptId, tokenPos, tryIndex, kind)); diff --git a/runtime/observatory/tests/service/fetch_all_types_test.dart b/runtime/observatory/tests/service/fetch_all_types_test.dart new file mode 100644 index 00000000000..4d6dcf3df32 --- /dev/null +++ b/runtime/observatory/tests/service/fetch_all_types_test.dart @@ -0,0 +1,28 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// See https://github.com/dart-lang/sdk/issues/52893 + +import 'package:observatory/service_io.dart'; +import 'test_helper.dart'; + +var tests = [ + (Isolate isolate) async { + dynamic profile = await isolate.invokeRpc('getAllocationProfile', {}); + for (var entry in profile["members"]) { + if (entry["instancesCurrent"] == 0) continue; + + Class cls = entry["class"]; + print(cls); + dynamic rawInstanceSet = await isolate.invokeRpcNoUpgrade( + 'getInstances', {'objectId': cls.id, 'limit': 10}); + dynamic instanceSet = await isolate.getInstances(cls, 10); + for (var instance in instanceSet.instances) { + await instance.load(); + } + } + }, +]; + +main(args) async => runIsolateTests(args, tests); diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart index 70ef0178207..271739b0fcf 100644 --- a/runtime/observatory/tests/service/get_version_rpc_test.dart +++ b/runtime/observatory/tests/service/get_version_rpc_test.dart @@ -12,7 +12,7 @@ var tests = [ final result = await vm.invokeRpcNoUpgrade('getVersion', {}); expect(result['type'], 'Version'); expect(result['major'], 4); - expect(result['minor'], 11); + expect(result['minor'], 12); expect(result['_privateMajor'], 0); expect(result['_privateMinor'], 0); }, diff --git a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart index dc1110ec946..04748165acc 100644 --- a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart +++ b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart @@ -12,7 +12,7 @@ var tests = [ final result = await vm.invokeRpcNoUpgrade('getVersion', {}); expect(result['type'], equals('Version')); expect(result['major'], equals(4)); - expect(result['minor'], equals(11)); + expect(result['minor'], equals(12)); expect(result['_privateMajor'], equals(0)); expect(result['_privateMinor'], equals(0)); }, diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc index 18b9bc90d75..ee16d5c994a 100644 --- a/runtime/vm/object_service.cc +++ b/runtime/vm/object_service.cc @@ -203,10 +203,12 @@ void Class::PrintImplementationFieldsImpl(const JSONArray& jsarr_fields) const { } void TypeParameters::PrintJSONImpl(JSONStream* stream, bool ref) const { - // Consider making this type public if we decide to expose TypeParameters - // through the protocol. JSONObject jsobj(stream); - jsobj.AddProperty("kind", "_TypeParameters"); + AddCommonObjectProperties(&jsobj, "TypeParameters", ref); + jsobj.AddServiceId(*this); + if (ref) { + return; + } jsobj.AddProperty("flags", Array::Handle(flags())); jsobj.AddProperty("names", Array::Handle(names())); jsobj.AddProperty("bounds", TypeArguments::Handle(bounds())); @@ -736,12 +738,7 @@ void KernelProgramInfo::PrintImplementationFieldsImpl( const JSONArray& jsarr_fields) const {} void Instructions::PrintJSONImpl(JSONStream* stream, bool ref) const { - JSONObject jsobj(stream); - AddCommonObjectProperties(&jsobj, "Object", ref); - jsobj.AddServiceId(*this); - if (ref) { - return; - } + Object::PrintJSONImpl(stream, ref); } void Instructions::PrintImplementationFieldsImpl( diff --git a/runtime/vm/service.h b/runtime/vm/service.h index 8cfa8ed13a8..e1f99140f46 100644 --- a/runtime/vm/service.h +++ b/runtime/vm/service.h @@ -17,7 +17,7 @@ namespace dart { #define SERVICE_PROTOCOL_MAJOR_VERSION 4 -#define SERVICE_PROTOCOL_MINOR_VERSION 11 +#define SERVICE_PROTOCOL_MINOR_VERSION 12 class Array; class EmbedderServiceHandler; diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md index 112d73593a0..715392d4222 100644 --- a/runtime/vm/service/service.md +++ b/runtime/vm/service/service.md @@ -1,8 +1,8 @@ -# Dart VM Service Protocol 4.11 +# Dart VM Service Protocol 4.12 > Please post feedback to the [observatory-discuss group][discuss-list] -This document describes of _version 4.11_ of the Dart VM Service Protocol. This +This document describes of _version 4.12_ of the Dart VM Service Protocol. This protocol is used to communicate with a running Dart Virtual Machine. To use the Service Protocol, start the VM with the *--observe* flag. @@ -4508,9 +4508,16 @@ instantiated generic type. ### TypeParameters ``` -class TypeParameters { +class @TypeParameters extends @Object { +} +``` + +_@TypeParameters_ is a reference to a _TypeParameters_ object. + +``` +class TypeParameters extends Object { // The names of the type parameters. - string[] names; + @Instance names; // The bounds set on each type parameter. @TypeArguments bounds; @@ -4719,5 +4726,6 @@ version | comments 4.9 | Added `isolateGroup` property to `Event`. 4.10 | Deprecated `isSyntheticAsyncContinuation` on `Breakpoint`. 4.11 | Added `isGetter` and `isSetter` properties to `@Function` and `Function`. +4.12 | Added `@TypeParameters` and changed `TypeParameters` to extend `Object`. [discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss