diff --git a/runtime/observatory/lib/src/elements/instance_ref.dart b/runtime/observatory/lib/src/elements/instance_ref.dart index 25615d9d3d0..adfc6bd716a 100644 --- a/runtime/observatory/lib/src/elements/instance_ref.dart +++ b/runtime/observatory/lib/src/elements/instance_ref.dart @@ -204,6 +204,8 @@ class InstanceRefElement extends CustomElement implements Renderable { case M.InstanceKind.mirrorReference: case M.InstanceKind.weakProperty: case M.InstanceKind.finalizer: + case M.InstanceKind.nativeFinalizer: + case M.InstanceKind.finalizerEntry: case M.InstanceKind.weakReference: case M.InstanceKind.record: return [ @@ -225,6 +227,9 @@ class InstanceRefElement extends CustomElement implements Renderable { case M.InstanceKind.weakReference: case M.InstanceKind.weakProperty: case M.InstanceKind.recordType: + case M.InstanceKind.finalizer: + case M.InstanceKind.nativeFinalizer: + case M.InstanceKind.finalizerEntry: return true; case M.InstanceKind.list: case M.InstanceKind.map: @@ -273,6 +278,14 @@ class InstanceRefElement extends CustomElement implements Renderable { queue: _r.queue) ]); } + if (_loadedInstance!.closureReceiver != null) { + members.add(new DivElement() + ..children = [ + new SpanElement()..text = 'receiver = ', + anyRef(_isolate, _loadedInstance!.closureReceiver, _objects, + queue: _r.queue) + ]); + } return members; } case M.InstanceKind.plainInstance: @@ -370,6 +383,33 @@ class InstanceRefElement extends CustomElement implements Renderable { if (i + 1 != fields.length) new BRElement(), ] ]; + case M.InstanceKind.finalizer: + return [ + new SpanElement()..text = 'callback = ', + anyRef(_isolate, _loadedInstance!.callback!, _objects, + queue: _r.queue), + new BRElement(), + new SpanElement()..text = 'allEntries = ', + anyRef(_isolate, _loadedInstance!.allEntries!, _objects, + queue: _r.queue), + ]; + case M.InstanceKind.nativeFinalizer: + return [ + new SpanElement()..text = 'allEntries = ', + anyRef(_isolate, _loadedInstance!.allEntries!, _objects, + queue: _r.queue), + ]; + case M.InstanceKind.finalizerEntry: + return [ + new SpanElement()..text = 'value = ', + anyRef(_isolate, _loadedInstance!.value!, _objects, queue: _r.queue), + new BRElement(), + new SpanElement()..text = 'detach = ', + anyRef(_isolate, _loadedInstance!.detach!, _objects, queue: _r.queue), + new BRElement(), + new SpanElement()..text = 'token = ', + anyRef(_isolate, _loadedInstance!.token!, _objects, queue: _r.queue), + ]; default: return []; } diff --git a/runtime/observatory/lib/src/elements/instance_view.dart b/runtime/observatory/lib/src/elements/instance_view.dart index 01777ddf68d..de4365d5e77 100644 --- a/runtime/observatory/lib/src/elements/instance_view.dart +++ b/runtime/observatory/lib/src/elements/instance_view.dart @@ -245,6 +245,9 @@ class InstanceViewElement extends CustomElement implements Renderable { if (_instance.closureContext != null) { members.add(member('closure context', _instance.closureContext)); } + if (_instance.closureReceiver != null) { + members.add(member('closure receiver', _instance.closureReceiver)); + } if (_instance.kind == M.InstanceKind.closure) { late ButtonElement btn; members.add(new DivElement() @@ -463,6 +466,21 @@ class InstanceViewElement extends CustomElement implements Renderable { members.add(member('value', _instance.value)); } + if (_instance.kind == M.InstanceKind.finalizer) { + members.add(member('callback', _instance.callback)); + members.add(member('allEntries', _instance.allEntries)); + } + + if (_instance.kind == M.InstanceKind.nativeFinalizer) { + members.add(member('callback', _instance.allEntries)); + } + + if (_instance.kind == M.InstanceKind.finalizerEntry) { + members.add(member('value', _instance.value)); + members.add(member('detach', _instance.detach)); + members.add(member('token', _instance.token)); + } + return members; } diff --git a/runtime/observatory/lib/src/models/objects/instance.dart b/runtime/observatory/lib/src/models/objects/instance.dart index 522dc1cf2d5..708f6a08e06 100644 --- a/runtime/observatory/lib/src/models/objects/instance.dart +++ b/runtime/observatory/lib/src/models/objects/instance.dart @@ -137,6 +137,12 @@ enum InstanceKind { /// An instance of Finalizer finalizer, + /// An instance of NativeFinalizer + nativeFinalizer, + + /// An instance of FinalizerEntry + finalizerEntry, + /// An instance of WeakReference weakReference, @@ -285,6 +291,12 @@ abstract class InstanceRef extends ObjectRef { /// Provided for instance kinds: /// Closure ContextRef? get closureContext; + + /// [optional] The receiver associated with a tear-off Closure instance. + /// + /// Provided for instance kinds: + /// Closure + InstanceRef? get closureReceiver; } abstract class Instance extends Object implements InstanceRef { @@ -460,6 +472,24 @@ abstract class Instance extends Object implements InstanceRef { /// Provided for instance kinds: /// RegExp InstanceRef? get twoByteBytecode; + + /// [optional] The callback associated with a Finalizer instance. + /// + /// Provided for instance kinds: + /// Finalizer + InstanceRef? get callback; + + /// [optional] The callback associated with a Finalizer instance. + /// + /// Provided for instance kinds: + /// Finalizer + /// NativeFinalizer + InstanceRef? get allEntries; + + /// Provided for instance kinds: + /// FinalizerEntry + InstanceRef? get detach; + InstanceRef? get token; } abstract class BoundField { diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart index 6cf4ee7bc82..38d6168b700 100644 --- a/runtime/observatory/lib/src/service/object.dart +++ b/runtime/observatory/lib/src/service/object.dart @@ -2816,6 +2816,10 @@ M.InstanceKind stringToInstanceKind(String s) { return M.InstanceKind.record; case 'Finalizer': return M.InstanceKind.finalizer; + case 'NativeFinalizer': + return M.InstanceKind.nativeFinalizer; + case 'FinalizerEntry': + return M.InstanceKind.finalizerEntry; case 'WeakReference': return M.InstanceKind.weakReference; case 'UserTag': @@ -2872,6 +2876,7 @@ class Instance extends HeapObject implements M.Instance { bool? valueAsStringIsTruncated; ServiceFunction? closureFunction; // If a closure. Context? closureContext; // If a closure. + Instance? closureReceiver; // If a closure. int? length; // If a List, Map or TypedData. int? count; int? offset; @@ -2900,6 +2905,10 @@ class Instance extends HeapObject implements M.Instance { Instance? twoByteBytecode; // If a RegExp. bool? isCaseSensitive; // If a RegExp. bool? isMultiLine; // If a RegExp. + Instance? callback; // If a Finalizer. + Instance? allEntries; // If a Finalizer or NativeFinalizer. + Instance? detach; // If a FinalizerEntry. + Instance? token; // If a FinalizerEntry. bool get isAbstractType => M.isAbstractType(kind); bool get isNull => kind == M.InstanceKind.vNull; @@ -2956,6 +2965,7 @@ class Instance extends HeapObject implements M.Instance { // Coerce absence to false. valueAsStringIsTruncated = map['valueAsStringIsTruncated'] == true; closureFunction = map['closureFunction']; + closureReceiver = map['closureReceiver']; name = map['name']?.toString(); if (map['label'] != null) { name = map['label']; @@ -2984,6 +2994,10 @@ class Instance extends HeapObject implements M.Instance { twoByteFunction = isCompiled ? map['_twoByteFunction'] : null; oneByteBytecode = map['_oneByteBytecode']; twoByteBytecode = map['_twoByteBytecode']; + callback = map['callback']; + allEntries = map['allEntries']; + detach = map['detach']; + token = map['token']; if (map['fields'] != null) { var fields = []; @@ -3080,7 +3094,12 @@ class Instance extends HeapObject implements M.Instance { referent = map['mirrorReferent']; target = map['target']; key = map['propertyKey']; - value = map['propertyValue']; + if (map['propertyValue'] != null) { + value = map['propertyValue']; // Ephemeron. + } + if (map['value'] != null) { + value = map['value']; // Finalizer entry. + } activationBreakpoint = map['_activationBreakpoint']; // We are fully loaded. diff --git a/runtime/observatory/tests/ui/inspector.dart b/runtime/observatory/tests/ui/inspector.dart index 1322d65ee5d..b54e1a1cd75 100644 --- a/runtime/observatory/tests/ui/inspector.dart +++ b/runtime/observatory/tests/ui/inspector.dart @@ -9,6 +9,7 @@ library manual_inspector_test; +import 'dart:ffi'; import 'dart:isolate'; import 'dart:mirrors'; import 'dart:developer'; @@ -47,11 +48,13 @@ class Node { var blockCopying; var blockFull; var blockFullWithChain; + var blockTearOff; var blockType; var boundedType; var capability; var expando; var finalizer; + var finalizerNative; var finalizerEntry; var float32x4; var float64; @@ -161,13 +164,16 @@ class Node { blockCopying = genCopyingBlock(); blockFull = genFullBlock(); blockFullWithChain = genFullBlockWithChain(); + blockTearOff = main; blockType = blockClean.runtimeType; boundedType = extractPrivateField( reflect(new B()).type.typeVariables.single, '_reflectee'); + capability = new Capability(); expando = new Expando("expando-name"); expando[array] = 'The weakly associated value'; finalizer = Finalizer((_){}); finalizer.attach(this, this); + finalizerNative = NativeFinalizer(Pointer.fromAddress(0)); float32x4 = new Float32x4(0.0, -1.0, 3.14, 2e28); float64 = 3.14; float64x2 = new Float64x2(0.0, 3.14);