mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[vm, service] Remove unsafe querying across threads during Isolate::PrintJSON.
Note this would be unsafe even if under a safepoint operation because not all of the queried threads participate in safepoints. TEST=tsan Bug: https://github.com/dart-lang/sdk/issues/44304 Bug: https://github.com/dart-lang/sdk/issues/44385 Change-Id: I8156e8c6049165e5c53b66c3391f3e8a496ddaaf Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/175000 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Aprelev <aam@google.com> Reviewed-by: Ben Konyi <bkonyi@google.com>
This commit is contained in:
parent
bae438c033
commit
e3a9d70591
|
@ -22,8 +22,6 @@ var tests = <VMTest>[
|
|||
expect(result.pauseOnExit, isFalse);
|
||||
expect(result.pauseEvent.type, 'Event');
|
||||
expect(result.error, isNull);
|
||||
expect(result.json['_numZoneHandles'], isPositive);
|
||||
expect(result.json['_numScopedHandles'], isPositive);
|
||||
expect(result.rootLib, isNotNull);
|
||||
expect(result.libraries.length, isPositive);
|
||||
expect(result.libraries[0], isNotNull);
|
||||
|
|
|
@ -50,14 +50,12 @@ part 'src/models/objects/single_target_cache.dart';
|
|||
part 'src/models/objects/source_location.dart';
|
||||
part 'src/models/objects/subtype_test_cache.dart';
|
||||
part 'src/models/objects/target.dart';
|
||||
part 'src/models/objects/thread.dart';
|
||||
part 'src/models/objects/timeline.dart';
|
||||
part 'src/models/objects/timeline_event.dart';
|
||||
part 'src/models/objects/type_arguments.dart';
|
||||
part 'src/models/objects/unknown.dart';
|
||||
part 'src/models/objects/unlinked_call.dart';
|
||||
part 'src/models/objects/vm.dart';
|
||||
part 'src/models/objects/zone.dart';
|
||||
|
||||
part 'src/models/repositories/allocation_profile.dart';
|
||||
part 'src/models/repositories/breakpoint.dart';
|
||||
|
|
|
@ -116,7 +116,6 @@ class IsolateViewElement extends CustomElement implements Renderable {
|
|||
void render() {
|
||||
final uptime = new DateTime.now().difference(_isolate.startTime!);
|
||||
final libraries = _isolate.libraries!.toList();
|
||||
final List<M.Thread> threads = _isolate.threads!.toList();
|
||||
children = <Element>[
|
||||
navBar(<Element>[
|
||||
new NavTopMenuElement(queue: _r.queue).element,
|
||||
|
@ -256,26 +255,6 @@ class IsolateViewElement extends CustomElement implements Renderable {
|
|||
..classes = ['memberValue']
|
||||
..text = '${_isolate.extensionRPCs}'
|
||||
],
|
||||
new DivElement()
|
||||
..classes = ['memberItem']
|
||||
..children = <Element>[
|
||||
new DivElement()
|
||||
..classes = ['memberName']
|
||||
..text = 'allocated zone handle count',
|
||||
new DivElement()
|
||||
..classes = ['memberValue']
|
||||
..text = '${_isolate.numZoneHandles}'
|
||||
],
|
||||
new DivElement()
|
||||
..classes = ['memberItem']
|
||||
..children = <Element>[
|
||||
new DivElement()
|
||||
..classes = ['memberName']
|
||||
..text = 'allocated scoped handle count',
|
||||
new DivElement()
|
||||
..classes = ['memberValue']
|
||||
..text = '${_isolate.numScopedHandles}'
|
||||
],
|
||||
new DivElement()
|
||||
..classes = ['memberItem']
|
||||
..children = <Element>[
|
||||
|
@ -289,19 +268,6 @@ class IsolateViewElement extends CustomElement implements Renderable {
|
|||
..text = 'object store'
|
||||
]
|
||||
],
|
||||
new DivElement()
|
||||
..classes = ['memberItem']
|
||||
..children = <Element>[
|
||||
new DivElement()
|
||||
..classes = ['memberName']
|
||||
..text = 'zone capacity high watermark'
|
||||
..title = '''The maximum amount of native zone memory
|
||||
allocated by the isolate over it\'s life.''',
|
||||
new DivElement()
|
||||
..classes = ['memberValue']
|
||||
..text = Utils.formatSize(_isolate.zoneHighWatermark)
|
||||
..title = '${_isolate.zoneHighWatermark}B'
|
||||
],
|
||||
new BRElement(),
|
||||
new DivElement()
|
||||
..classes = ['memberItem']
|
||||
|
@ -324,21 +290,6 @@ class IsolateViewElement extends CustomElement implements Renderable {
|
|||
.element
|
||||
]
|
||||
],
|
||||
new DivElement()
|
||||
..classes = ['memberItem']
|
||||
..children = <Element>[
|
||||
new DivElement()
|
||||
..classes = ['memberName']
|
||||
..text = 'threads (${threads.length})',
|
||||
new DivElement()
|
||||
..classes = ['memberValue']
|
||||
..children = <Element>[
|
||||
(new CurlyBlockElement(queue: _r.queue)
|
||||
..content =
|
||||
threads.map<Element>(_populateThreadInfo))
|
||||
.element
|
||||
]
|
||||
]
|
||||
],
|
||||
new HRElement(),
|
||||
new EvalBoxElement(_isolate, _isolate.rootLibrary!, _objects, _eval,
|
||||
|
@ -360,31 +311,6 @@ class IsolateViewElement extends CustomElement implements Renderable {
|
|||
];
|
||||
}
|
||||
|
||||
DivElement _populateThreadInfo(M.Thread t) {
|
||||
return new DivElement()
|
||||
..classes = ['indent']
|
||||
..children = <Element>[
|
||||
new SpanElement()..text = '${t.id} ',
|
||||
(new CurlyBlockElement(queue: _r.queue)
|
||||
..content = <Element>[
|
||||
new DivElement()
|
||||
..classes = ['indent']
|
||||
..text = 'kind ${t.kindString}',
|
||||
new DivElement()
|
||||
..classes = ['indent']
|
||||
..title = '${t.zoneHighWatermark}B'
|
||||
..text = 'zone capacity high watermark '
|
||||
'${Utils.formatSize(t.zoneHighWatermark)}',
|
||||
new DivElement()
|
||||
..classes = ['indent']
|
||||
..title = '${t.zoneCapacity}B'
|
||||
..text = 'current zone capacity ' +
|
||||
'${Utils.formatSize(t.zoneCapacity)}',
|
||||
])
|
||||
.element
|
||||
];
|
||||
}
|
||||
|
||||
Future _loadExtraData() async {
|
||||
_function = null;
|
||||
_rootScript = null;
|
||||
|
|
|
@ -57,20 +57,6 @@ abstract class Isolate extends IsolateRef {
|
|||
/// [optional] The error that is causing this isolate to exit, if applicable.
|
||||
Error? get error;
|
||||
|
||||
/// The list of threads associated with this isolate.
|
||||
Iterable<Thread>? get threads;
|
||||
|
||||
/// The maximum amount of zone memory in bytes allocated by the isolate in
|
||||
/// all threads at a given time. Calculated using the high watermarks of each
|
||||
/// thread alive when a thread is unscheduled.
|
||||
int? get zoneHighWatermark;
|
||||
|
||||
/// The number of zone handles currently held by this isolate.
|
||||
int? get numZoneHandles;
|
||||
|
||||
/// The number of scoped handles currently held by this isolate.
|
||||
int? get numScopedHandles;
|
||||
|
||||
/// The current pause on exception mode for this isolate.
|
||||
//ExceptionPauseMode get exceptionPauseMode;
|
||||
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
// Copyright (c) 2016, 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.
|
||||
|
||||
part of models;
|
||||
|
||||
enum ThreadKind {
|
||||
unknownTask,
|
||||
mutatorTask,
|
||||
compilerTask,
|
||||
sweeperTask,
|
||||
markerTask,
|
||||
finalizerTask
|
||||
}
|
||||
|
||||
abstract class Thread {
|
||||
/// The id associated with the thread on creation.
|
||||
String? get id;
|
||||
|
||||
/// The task type associated with the thread.
|
||||
ThreadKind? get kind;
|
||||
|
||||
String? get kindString;
|
||||
|
||||
/// The maximum amount of zone memory in bytes allocated by a thread at a
|
||||
/// given time throughout the entire life of the thread.
|
||||
int? get zoneHighWatermark;
|
||||
|
||||
/// The current Zone capacity available to this thread.
|
||||
int? get zoneCapacity;
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
// Copyright (c) 2016, 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.
|
||||
|
||||
part of models;
|
||||
|
||||
abstract class Zone {
|
||||
/// The total amount of memory in bytes allocated in the zone, including
|
||||
/// memory that is not actually being used.
|
||||
int get capacity;
|
||||
|
||||
/// The total amount of memory in bytes actually used in the zone.
|
||||
int get used;
|
||||
}
|
|
@ -238,9 +238,6 @@ abstract class ServiceObject implements M.ObjectRef {
|
|||
case 'SourceLocation':
|
||||
obj = new SourceLocation._empty(owner);
|
||||
break;
|
||||
case '_Thread':
|
||||
obj = new Thread._empty(owner);
|
||||
break;
|
||||
case 'UnresolvedSourceLocation':
|
||||
obj = new UnresolvedSourceLocation._empty(owner);
|
||||
break;
|
||||
|
@ -1617,18 +1614,6 @@ class Isolate extends ServiceObjectOwner implements M.Isolate {
|
|||
DartError? error;
|
||||
SnapshotReader? _snapshotFetch;
|
||||
|
||||
List<Thread> get threads => _threads;
|
||||
final List<Thread> _threads = <Thread>[];
|
||||
|
||||
int get zoneHighWatermark => _zoneHighWatermark;
|
||||
int _zoneHighWatermark = 0;
|
||||
|
||||
int get numZoneHandles => _numZoneHandles;
|
||||
int _numZoneHandles = 0;
|
||||
|
||||
int get numScopedHandles => _numScopedHandles;
|
||||
int _numScopedHandles = 0;
|
||||
|
||||
bool? isSystemIsolate;
|
||||
|
||||
void _loadHeapSnapshot(ServiceEvent event) {
|
||||
|
@ -1731,23 +1716,6 @@ class Isolate extends ServiceObjectOwner implements M.Isolate {
|
|||
if (map['extensionRPCs'] != null) {
|
||||
for (String e in map['extensionRPCs']) extensionRPCs.add(e);
|
||||
}
|
||||
|
||||
threads.clear();
|
||||
if (map['_threads'] != null) {
|
||||
for (Thread t in map['_threads']) threads.add(t);
|
||||
}
|
||||
|
||||
int currentZoneHighWatermark = 0;
|
||||
for (var i = 0; i < threads.length; i++) {
|
||||
currentZoneHighWatermark += threads[i].zoneHighWatermark!;
|
||||
}
|
||||
|
||||
if (currentZoneHighWatermark > _zoneHighWatermark) {
|
||||
_zoneHighWatermark = currentZoneHighWatermark;
|
||||
}
|
||||
|
||||
_numZoneHandles = map['_numZoneHandles'];
|
||||
_numScopedHandles = map['_numScopedHandles'];
|
||||
}
|
||||
|
||||
Future<TagProfile> updateTagProfile() {
|
||||
|
@ -3285,60 +3253,6 @@ class Sentinel extends ServiceObject implements M.Sentinel {
|
|||
String get shortName => valueAsString;
|
||||
}
|
||||
|
||||
class Thread extends ServiceObject implements M.Thread {
|
||||
M.ThreadKind? get kind => _kind;
|
||||
M.ThreadKind? _kind;
|
||||
String? get kindString => _kindString;
|
||||
String? _kindString;
|
||||
int? get zoneHighWatermark => _zoneHighWatermark;
|
||||
int? _zoneHighWatermark;
|
||||
int? get zoneCapacity => _zoneCapacity;
|
||||
int? _zoneCapacity;
|
||||
|
||||
Thread._empty(ServiceObjectOwner? owner) : super._empty(owner);
|
||||
|
||||
void _update(Map map, bool mapIsRef) {
|
||||
String rawKind = map['kind'];
|
||||
|
||||
switch (rawKind) {
|
||||
case "kUnknownTask":
|
||||
_kind = M.ThreadKind.unknownTask;
|
||||
_kindString = 'unknown';
|
||||
break;
|
||||
case "kMutatorTask":
|
||||
_kind = M.ThreadKind.mutatorTask;
|
||||
_kindString = 'mutator';
|
||||
break;
|
||||
case "kCompilerTask":
|
||||
_kind = M.ThreadKind.compilerTask;
|
||||
_kindString = 'compiler';
|
||||
break;
|
||||
case "kSweeperTask":
|
||||
_kind = M.ThreadKind.sweeperTask;
|
||||
_kindString = 'sweeper';
|
||||
break;
|
||||
case "kMarkerTask":
|
||||
_kind = M.ThreadKind.markerTask;
|
||||
_kindString = 'marker';
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
_zoneHighWatermark = int.parse(map['_zoneHighWatermark']);
|
||||
_zoneCapacity = int.parse(map['_zoneCapacity']);
|
||||
}
|
||||
}
|
||||
|
||||
class Zone implements M.Zone {
|
||||
int get capacity => _capacity;
|
||||
int _capacity;
|
||||
int get used => _used;
|
||||
int _used;
|
||||
|
||||
Zone(this._capacity, this._used);
|
||||
}
|
||||
|
||||
class Field extends HeapObject implements M.Field {
|
||||
// Library or Class.
|
||||
HeapObject? dartOwner;
|
||||
|
|
|
@ -183,14 +183,12 @@ observatory_sources = [
|
|||
"lib/src/models/objects/source_location.dart",
|
||||
"lib/src/models/objects/subtype_test_cache.dart",
|
||||
"lib/src/models/objects/target.dart",
|
||||
"lib/src/models/objects/thread.dart",
|
||||
"lib/src/models/objects/timeline.dart",
|
||||
"lib/src/models/objects/timeline_event.dart",
|
||||
"lib/src/models/objects/type_arguments.dart",
|
||||
"lib/src/models/objects/unknown.dart",
|
||||
"lib/src/models/objects/unlinked_call.dart",
|
||||
"lib/src/models/objects/vm.dart",
|
||||
"lib/src/models/objects/zone.dart",
|
||||
"lib/src/models/repositories/allocation_profile.dart",
|
||||
"lib/src/models/repositories/breakpoint.dart",
|
||||
"lib/src/models/repositories/class.dart",
|
||||
|
|
|
@ -25,8 +25,6 @@ var tests = <VMTest>[
|
|||
expect(result['pauseOnExit'], isFalse);
|
||||
expect(result['pauseEvent']['type'], equals('Event'));
|
||||
expect(result['error'], isNull);
|
||||
expect(result['_numZoneHandles'], isPositive);
|
||||
expect(result['_numScopedHandles'], isPositive);
|
||||
expect(result['rootLib']['type'], equals('@Library'));
|
||||
expect(result['libraries'].length, isPositive);
|
||||
expect(result['libraries'][0]['type'], equals('@Library'));
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
// Copyright (c) 2016, 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.
|
||||
|
||||
import 'package:observatory/service_io.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'test_helper.dart';
|
||||
|
||||
var tests = <VMTest>[
|
||||
(VM vm) async {
|
||||
// Just iterate over all the isolates to confirm they have
|
||||
// the correct fields needed to examine zone memory usage.
|
||||
for (Isolate isolate in new List.from(vm.isolates)) {
|
||||
await isolate.reload();
|
||||
expect(isolate.zoneHighWatermark, isA<int>());
|
||||
expect(isolate.threads, isNotNull);
|
||||
List<Thread> threads = isolate.threads;
|
||||
|
||||
for (Thread thread in threads) {
|
||||
expect(thread.type, equals('_Thread'));
|
||||
expect(thread.id, isNotNull);
|
||||
expect(thread.kind, isNotNull);
|
||||
expect(thread.zoneHighWatermark, isA<int>());
|
||||
expect(thread.zoneCapacity, isA<int>());
|
||||
}
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
main(args) async => runVMTests(args, tests);
|
|
@ -70,8 +70,6 @@ Future<Null> testeeBefore() async {
|
|||
Expect.isFalse(result['pauseOnExit']);
|
||||
Expect.equals(result['pauseEvent']['type'], 'Event');
|
||||
Expect.isNull(result['error']);
|
||||
Expect.isTrue(result['_numZoneHandles'] > 0);
|
||||
Expect.isTrue(result['_numScopedHandles'] > 0);
|
||||
Expect.equals(result['rootLib']['type'], '@Library');
|
||||
Expect.isTrue(result['libraries'].length > 0);
|
||||
Expect.equals(result['libraries'][0]['type'], '@Library');
|
||||
|
|
|
@ -50,14 +50,12 @@ part 'src/models/objects/single_target_cache.dart';
|
|||
part 'src/models/objects/source_location.dart';
|
||||
part 'src/models/objects/subtype_test_cache.dart';
|
||||
part 'src/models/objects/target.dart';
|
||||
part 'src/models/objects/thread.dart';
|
||||
part 'src/models/objects/timeline.dart';
|
||||
part 'src/models/objects/timeline_event.dart';
|
||||
part 'src/models/objects/type_arguments.dart';
|
||||
part 'src/models/objects/unknown.dart';
|
||||
part 'src/models/objects/unlinked_call.dart';
|
||||
part 'src/models/objects/vm.dart';
|
||||
part 'src/models/objects/zone.dart';
|
||||
|
||||
part 'src/models/repositories/allocation_profile.dart';
|
||||
part 'src/models/repositories/breakpoint.dart';
|
||||
|
|
|
@ -116,7 +116,6 @@ class IsolateViewElement extends CustomElement implements Renderable {
|
|||
void render() {
|
||||
final uptime = new DateTime.now().difference(_isolate.startTime);
|
||||
final libraries = _isolate.libraries.toList();
|
||||
final List<M.Thread> threads = _isolate.threads;
|
||||
children = <Element>[
|
||||
navBar(<Element>[
|
||||
new NavTopMenuElement(queue: _r.queue).element,
|
||||
|
@ -256,26 +255,6 @@ class IsolateViewElement extends CustomElement implements Renderable {
|
|||
..classes = ['memberValue']
|
||||
..text = '${_isolate.extensionRPCs}'
|
||||
],
|
||||
new DivElement()
|
||||
..classes = ['memberItem']
|
||||
..children = <Element>[
|
||||
new DivElement()
|
||||
..classes = ['memberName']
|
||||
..text = 'allocated zone handle count',
|
||||
new DivElement()
|
||||
..classes = ['memberValue']
|
||||
..text = '${_isolate.numZoneHandles}'
|
||||
],
|
||||
new DivElement()
|
||||
..classes = ['memberItem']
|
||||
..children = <Element>[
|
||||
new DivElement()
|
||||
..classes = ['memberName']
|
||||
..text = 'allocated scoped handle count',
|
||||
new DivElement()
|
||||
..classes = ['memberValue']
|
||||
..text = '${_isolate.numScopedHandles}'
|
||||
],
|
||||
new DivElement()
|
||||
..classes = ['memberItem']
|
||||
..children = <Element>[
|
||||
|
@ -289,19 +268,6 @@ class IsolateViewElement extends CustomElement implements Renderable {
|
|||
..text = 'object store'
|
||||
]
|
||||
],
|
||||
new DivElement()
|
||||
..classes = ['memberItem']
|
||||
..children = <Element>[
|
||||
new DivElement()
|
||||
..classes = ['memberName']
|
||||
..text = 'zone capacity high watermark'
|
||||
..title = '''The maximum amount of native zone memory
|
||||
allocated by the isolate over it\'s life.''',
|
||||
new DivElement()
|
||||
..classes = ['memberValue']
|
||||
..text = Utils.formatSize(_isolate.zoneHighWatermark)
|
||||
..title = '${_isolate.zoneHighWatermark}B'
|
||||
],
|
||||
new BRElement(),
|
||||
new DivElement()
|
||||
..classes = ['memberItem']
|
||||
|
@ -324,21 +290,6 @@ class IsolateViewElement extends CustomElement implements Renderable {
|
|||
.element
|
||||
]
|
||||
],
|
||||
new DivElement()
|
||||
..classes = ['memberItem']
|
||||
..children = <Element>[
|
||||
new DivElement()
|
||||
..classes = ['memberName']
|
||||
..text = 'threads (${threads.length})',
|
||||
new DivElement()
|
||||
..classes = ['memberValue']
|
||||
..children = <Element>[
|
||||
(new CurlyBlockElement(queue: _r.queue)
|
||||
..content =
|
||||
threads.map<Element>(_populateThreadInfo))
|
||||
.element
|
||||
]
|
||||
]
|
||||
],
|
||||
new HRElement(),
|
||||
new EvalBoxElement(_isolate, _isolate.rootLibrary, _objects, _eval,
|
||||
|
@ -360,31 +311,6 @@ class IsolateViewElement extends CustomElement implements Renderable {
|
|||
];
|
||||
}
|
||||
|
||||
DivElement _populateThreadInfo(M.Thread t) {
|
||||
return new DivElement()
|
||||
..classes = ['indent']
|
||||
..children = <Element>[
|
||||
new SpanElement()..text = '${t.id} ',
|
||||
(new CurlyBlockElement(queue: _r.queue)
|
||||
..content = <Element>[
|
||||
new DivElement()
|
||||
..classes = ['indent']
|
||||
..text = 'kind ${t.kindString}',
|
||||
new DivElement()
|
||||
..classes = ['indent']
|
||||
..title = '${t.zoneHighWatermark}B'
|
||||
..text = 'zone capacity high watermark '
|
||||
'${Utils.formatSize(t.zoneHighWatermark)}',
|
||||
new DivElement()
|
||||
..classes = ['indent']
|
||||
..title = '${t.zoneCapacity}B'
|
||||
..text = 'current zone capacity ' +
|
||||
'${Utils.formatSize(t.zoneCapacity)}',
|
||||
])
|
||||
.element
|
||||
];
|
||||
}
|
||||
|
||||
Future _loadExtraData() async {
|
||||
_function = null;
|
||||
_rootScript = null;
|
||||
|
|
|
@ -57,20 +57,6 @@ abstract class Isolate extends IsolateRef {
|
|||
/// [optional] The error that is causing this isolate to exit, if applicable.
|
||||
Error get error;
|
||||
|
||||
/// The list of threads associated with this isolate.
|
||||
Iterable<Thread> get threads;
|
||||
|
||||
/// The maximum amount of zone memory in bytes allocated by the isolate in
|
||||
/// all threads at a given time. Calculated using the high watermarks of each
|
||||
/// thread alive when a thread is unscheduled.
|
||||
int get zoneHighWatermark;
|
||||
|
||||
/// The number of zone handles currently held by this isolate.
|
||||
int get numZoneHandles;
|
||||
|
||||
/// The number of scoped handles currently held by this isolate.
|
||||
int get numScopedHandles;
|
||||
|
||||
/// The current pause on exception mode for this isolate.
|
||||
//ExceptionPauseMode get exceptionPauseMode;
|
||||
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
// Copyright (c) 2016, 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.
|
||||
|
||||
part of models;
|
||||
|
||||
enum ThreadKind {
|
||||
unknownTask,
|
||||
mutatorTask,
|
||||
compilerTask,
|
||||
sweeperTask,
|
||||
markerTask,
|
||||
finalizerTask
|
||||
}
|
||||
|
||||
abstract class Thread {
|
||||
/// The id associated with the thread on creation.
|
||||
String get id;
|
||||
|
||||
/// The task type associated with the thread.
|
||||
ThreadKind get kind;
|
||||
|
||||
String get kindString;
|
||||
|
||||
/// The maximum amount of zone memory in bytes allocated by a thread at a
|
||||
/// given time throughout the entire life of the thread.
|
||||
int get zoneHighWatermark;
|
||||
|
||||
/// The current Zone capacity available to this thread.
|
||||
int get zoneCapacity;
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
// Copyright (c) 2016, 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.
|
||||
|
||||
part of models;
|
||||
|
||||
abstract class Zone {
|
||||
/// The total amount of memory in bytes allocated in the zone, including
|
||||
/// memory that is not actually being used.
|
||||
int get capacity;
|
||||
|
||||
/// The total amount of memory in bytes actually used in the zone.
|
||||
int get used;
|
||||
}
|
|
@ -241,9 +241,6 @@ abstract class ServiceObject implements M.ObjectRef {
|
|||
case 'SourceLocation':
|
||||
obj = new SourceLocation._empty(owner);
|
||||
break;
|
||||
case '_Thread':
|
||||
obj = new Thread._empty(owner);
|
||||
break;
|
||||
case 'UnresolvedSourceLocation':
|
||||
obj = new UnresolvedSourceLocation._empty(owner);
|
||||
break;
|
||||
|
@ -1628,18 +1625,6 @@ class Isolate extends ServiceObjectOwner implements M.Isolate {
|
|||
DartError error;
|
||||
SnapshotReader _snapshotFetch;
|
||||
|
||||
List<Thread> get threads => _threads;
|
||||
final List<Thread> _threads = <Thread>[];
|
||||
|
||||
int get zoneHighWatermark => _zoneHighWatermark;
|
||||
int _zoneHighWatermark = 0;
|
||||
|
||||
int get numZoneHandles => _numZoneHandles;
|
||||
int _numZoneHandles;
|
||||
|
||||
int get numScopedHandles => _numScopedHandles;
|
||||
int _numScopedHandles;
|
||||
|
||||
bool isSystemIsolate;
|
||||
|
||||
void _loadHeapSnapshot(ServiceEvent event) {
|
||||
|
@ -1742,23 +1727,6 @@ class Isolate extends ServiceObjectOwner implements M.Isolate {
|
|||
if (map['extensionRPCs'] != null) {
|
||||
for (String e in map['extensionRPCs']) extensionRPCs.add(e);
|
||||
}
|
||||
|
||||
threads.clear();
|
||||
if (map['_threads'] != null) {
|
||||
for (Thread t in map['_threads']) threads.add(t);
|
||||
}
|
||||
|
||||
int currentZoneHighWatermark = 0;
|
||||
for (var i = 0; i < threads.length; i++) {
|
||||
currentZoneHighWatermark += threads[i].zoneHighWatermark;
|
||||
}
|
||||
|
||||
if (currentZoneHighWatermark > _zoneHighWatermark) {
|
||||
_zoneHighWatermark = currentZoneHighWatermark;
|
||||
}
|
||||
|
||||
_numZoneHandles = map['_numZoneHandles'];
|
||||
_numScopedHandles = map['_numScopedHandles'];
|
||||
}
|
||||
|
||||
Future<TagProfile> updateTagProfile() {
|
||||
|
@ -3298,60 +3266,6 @@ class Sentinel extends ServiceObject implements M.Sentinel {
|
|||
String get shortName => valueAsString;
|
||||
}
|
||||
|
||||
class Thread extends ServiceObject implements M.Thread {
|
||||
M.ThreadKind get kind => _kind;
|
||||
M.ThreadKind _kind;
|
||||
String get kindString => _kindString;
|
||||
String _kindString;
|
||||
int get zoneHighWatermark => _zoneHighWatermark;
|
||||
int _zoneHighWatermark;
|
||||
int get zoneCapacity => _zoneCapacity;
|
||||
int _zoneCapacity;
|
||||
|
||||
Thread._empty(ServiceObjectOwner owner) : super._empty(owner);
|
||||
|
||||
void _update(Map map, bool mapIsRef) {
|
||||
String rawKind = map['kind'];
|
||||
|
||||
switch (rawKind) {
|
||||
case "kUnknownTask":
|
||||
_kind = M.ThreadKind.unknownTask;
|
||||
_kindString = 'unknown';
|
||||
break;
|
||||
case "kMutatorTask":
|
||||
_kind = M.ThreadKind.mutatorTask;
|
||||
_kindString = 'mutator';
|
||||
break;
|
||||
case "kCompilerTask":
|
||||
_kind = M.ThreadKind.compilerTask;
|
||||
_kindString = 'compiler';
|
||||
break;
|
||||
case "kSweeperTask":
|
||||
_kind = M.ThreadKind.sweeperTask;
|
||||
_kindString = 'sweeper';
|
||||
break;
|
||||
case "kMarkerTask":
|
||||
_kind = M.ThreadKind.markerTask;
|
||||
_kindString = 'marker';
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
_zoneHighWatermark = int.parse(map['_zoneHighWatermark']);
|
||||
_zoneCapacity = int.parse(map['_zoneCapacity']);
|
||||
}
|
||||
}
|
||||
|
||||
class Zone implements M.Zone {
|
||||
int get capacity => _capacity;
|
||||
int _capacity;
|
||||
int get used => _used;
|
||||
int _used;
|
||||
|
||||
Zone(this._capacity, this._used);
|
||||
}
|
||||
|
||||
class Field extends HeapObject implements M.Field {
|
||||
// Library or Class.
|
||||
HeapObject dartOwner;
|
||||
|
|
|
@ -183,14 +183,12 @@ observatory_sources = [
|
|||
"lib/src/models/objects/source_location.dart",
|
||||
"lib/src/models/objects/subtype_test_cache.dart",
|
||||
"lib/src/models/objects/target.dart",
|
||||
"lib/src/models/objects/thread.dart",
|
||||
"lib/src/models/objects/timeline.dart",
|
||||
"lib/src/models/objects/timeline_event.dart",
|
||||
"lib/src/models/objects/type_arguments.dart",
|
||||
"lib/src/models/objects/unknown.dart",
|
||||
"lib/src/models/objects/unlinked_call.dart",
|
||||
"lib/src/models/objects/vm.dart",
|
||||
"lib/src/models/objects/zone.dart",
|
||||
"lib/src/models/repositories/allocation_profile.dart",
|
||||
"lib/src/models/repositories/breakpoint.dart",
|
||||
"lib/src/models/repositories/class.dart",
|
||||
|
|
|
@ -23,8 +23,6 @@ var tests = <VMTest>[
|
|||
expect(result['pauseOnExit'], isFalse);
|
||||
expect(result['pauseEvent']['type'], equals('Event'));
|
||||
expect(result['error'], isNull);
|
||||
expect(result['_numZoneHandles'], isPositive);
|
||||
expect(result['_numScopedHandles'], isPositive);
|
||||
expect(result['rootLib']['type'], equals('@Library'));
|
||||
expect(result['libraries'].length, isPositive);
|
||||
expect(result['libraries'][0]['type'], equals('@Library'));
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
// Copyright (c) 2016, 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.
|
||||
|
||||
import 'package:observatory_2/service_io.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'test_helper.dart';
|
||||
|
||||
var tests = <VMTest>[
|
||||
(VM vm) async {
|
||||
// Just iterate over all the isolates to confirm they have
|
||||
// the correct fields needed to examine zone memory usage.
|
||||
for (Isolate isolate in new List.from(vm.isolates)) {
|
||||
await isolate.reload();
|
||||
expect(isolate.zoneHighWatermark, isA<int>());
|
||||
expect(isolate.threads, isNotNull);
|
||||
List<Thread> threads = isolate.threads;
|
||||
|
||||
for (Thread thread in threads) {
|
||||
expect(thread.type, equals('_Thread'));
|
||||
expect(thread.id, isNotNull);
|
||||
expect(thread.kind, isNotNull);
|
||||
expect(thread.zoneHighWatermark, isA<int>());
|
||||
expect(thread.zoneCapacity, isA<int>());
|
||||
}
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
main(args) async => runVMTests(args, tests);
|
|
@ -70,8 +70,6 @@ Future<Null> testeeBefore() async {
|
|||
Expect.isFalse(result['pauseOnExit']);
|
||||
Expect.equals(result['pauseEvent']['type'], 'Event');
|
||||
Expect.isNull(result['error']);
|
||||
Expect.isTrue(result['_numZoneHandles'] > 0);
|
||||
Expect.isTrue(result['_numScopedHandles'] > 0);
|
||||
Expect.equals(result['rootLib']['type'], '@Library');
|
||||
Expect.isTrue(result['libraries'].length > 0);
|
||||
Expect.equals(result['libraries'][0]['type'], '@Library');
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -561,8 +561,6 @@ Thread* IsolateGroup::ScheduleThreadLocked(MonitorLocker* ml,
|
|||
// Now get a free Thread structure.
|
||||
ASSERT(thread != nullptr);
|
||||
|
||||
thread->ResetHighWatermark();
|
||||
|
||||
// Set up other values and set the TLS value.
|
||||
thread->isolate_ = nullptr;
|
||||
thread->isolate_group_ = this;
|
||||
|
@ -3049,12 +3047,6 @@ void Isolate::PrintJSON(JSONStream* stream, bool ref) {
|
|||
jsobj.AddProperty("rootLib", lib);
|
||||
}
|
||||
|
||||
intptr_t zone_handle_count = thread_registry()->CountZoneHandles(this);
|
||||
intptr_t scoped_handle_count = thread_registry()->CountScopedHandles(this);
|
||||
|
||||
jsobj.AddProperty("_numZoneHandles", zone_handle_count);
|
||||
jsobj.AddProperty("_numScopedHandles", scoped_handle_count);
|
||||
|
||||
if (FLAG_profiler) {
|
||||
JSONObject tagCounters(&jsobj, "_tagCounters");
|
||||
vm_tag_counters()->PrintToJSONObject(&tagCounters);
|
||||
|
@ -3114,8 +3106,6 @@ void Isolate::PrintJSON(JSONStream* stream, bool ref) {
|
|||
}
|
||||
}
|
||||
|
||||
jsobj.AddProperty("_threads", thread_registry());
|
||||
|
||||
{
|
||||
JSONObject isolate_group(&jsobj, "isolate_group");
|
||||
group()->PrintToJSONObject(&isolate_group, /*ref=*/true);
|
||||
|
|
|
@ -348,16 +348,6 @@ void JSONStream::PrintValue(IsolateGroup* isolate_group, bool ref) {
|
|||
isolate_group->PrintJSON(this, ref);
|
||||
}
|
||||
|
||||
void JSONStream::PrintValue(ThreadRegistry* reg) {
|
||||
PrintCommaIfNeeded();
|
||||
reg->PrintJSON(this);
|
||||
}
|
||||
|
||||
void JSONStream::PrintValue(Thread* thread) {
|
||||
PrintCommaIfNeeded();
|
||||
thread->PrintJSON(this);
|
||||
}
|
||||
|
||||
void JSONStream::PrintValue(const TimelineEvent* timeline_event) {
|
||||
PrintCommaIfNeeded();
|
||||
timeline_event->PrintJSON(this);
|
||||
|
@ -408,16 +398,6 @@ void JSONStream::PrintProperty(const char* name, Isolate* isolate) {
|
|||
PrintValue(isolate);
|
||||
}
|
||||
|
||||
void JSONStream::PrintProperty(const char* name, ThreadRegistry* reg) {
|
||||
PrintPropertyName(name);
|
||||
PrintValue(reg);
|
||||
}
|
||||
|
||||
void JSONStream::PrintProperty(const char* name, Thread* thread) {
|
||||
PrintPropertyName(name);
|
||||
PrintValue(thread);
|
||||
}
|
||||
|
||||
void JSONStream::PrintProperty(const char* name,
|
||||
const TimelineEvent* timeline_event) {
|
||||
PrintPropertyName(name);
|
||||
|
|
|
@ -205,8 +205,6 @@ class JSONStream : ValueObject {
|
|||
void PrintValue(MessageQueue* queue);
|
||||
void PrintValue(Isolate* isolate, bool ref = true);
|
||||
void PrintValue(IsolateGroup* isolate, bool ref = true);
|
||||
void PrintValue(ThreadRegistry* reg);
|
||||
void PrintValue(Thread* thread);
|
||||
void PrintValue(const TimelineEvent* timeline_event);
|
||||
void PrintValue(const TimelineEventBlock* timeline_event_block);
|
||||
void PrintValueVM(bool ref = true);
|
||||
|
@ -261,8 +259,6 @@ class JSONStream : ValueObject {
|
|||
void PrintProperty(const char* name, Metric* metric);
|
||||
void PrintProperty(const char* name, MessageQueue* queue);
|
||||
void PrintProperty(const char* name, Isolate* isolate);
|
||||
void PrintProperty(const char* name, ThreadRegistry* reg);
|
||||
void PrintProperty(const char* name, Thread* thread);
|
||||
void PrintProperty(const char* name, Zone* zone);
|
||||
void PrintProperty(const char* name, const TimelineEvent* timeline_event);
|
||||
void PrintProperty(const char* name,
|
||||
|
@ -377,12 +373,6 @@ class JSONObject : public ValueObject {
|
|||
void AddProperty(const char* name, Isolate* isolate) const {
|
||||
stream_->PrintProperty(name, isolate);
|
||||
}
|
||||
void AddProperty(const char* name, ThreadRegistry* reg) const {
|
||||
stream_->PrintProperty(name, reg);
|
||||
}
|
||||
void AddProperty(const char* name, Thread* thread) const {
|
||||
stream_->PrintProperty(name, thread);
|
||||
}
|
||||
void AddProperty(const char* name, Zone* zone) const {
|
||||
stream_->PrintProperty(name, zone);
|
||||
}
|
||||
|
@ -443,8 +433,6 @@ class JSONArray : public ValueObject {
|
|||
void AddValue(IsolateGroup* isolate_group, bool ref = true) const {
|
||||
stream_->PrintValue(isolate_group, ref);
|
||||
}
|
||||
void AddValue(ThreadRegistry* reg) const { stream_->PrintValue(reg); }
|
||||
void AddValue(Thread* thread) const { stream_->PrintValue(thread); }
|
||||
void AddValue(Breakpoint* bpt) const { stream_->PrintValue(bpt); }
|
||||
void AddValue(TokenPosition tp) const { stream_->PrintValue(tp); }
|
||||
void AddValue(const ServiceEvent* event) const { stream_->PrintValue(event); }
|
||||
|
|
|
@ -214,19 +214,6 @@ void Thread::InitVMConstants() {
|
|||
#undef REUSABLE_HANDLE_ALLOCATION
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
// Collect information about each individual zone associated with this thread.
|
||||
void Thread::PrintJSON(JSONStream* stream) const {
|
||||
JSONObject jsobj(stream);
|
||||
jsobj.AddProperty("type", "_Thread");
|
||||
jsobj.AddPropertyF("id", "threads/%" Pd "",
|
||||
OSThread::ThreadIdToIntPtr(os_thread()->trace_id()));
|
||||
jsobj.AddProperty("kind", TaskKindToCString(task_kind()));
|
||||
jsobj.AddPropertyF("_zoneHighWatermark", "%" Pu "", zone_high_watermark());
|
||||
jsobj.AddPropertyF("_zoneCapacity", "%" Pu "", current_zone_capacity());
|
||||
}
|
||||
#endif
|
||||
|
||||
GrowableObjectArrayPtr Thread::pending_functions() {
|
||||
if (pending_functions_ == GrowableObjectArray::null()) {
|
||||
pending_functions_ = GrowableObjectArray::New(Heap::kOld);
|
||||
|
|
|
@ -95,45 +95,6 @@ void ThreadRegistry::ReleaseMarkingStacks() {
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void ThreadRegistry::PrintJSON(JSONStream* stream) const {
|
||||
MonitorLocker ml(threads_lock());
|
||||
JSONArray threads(stream);
|
||||
Thread* current = active_list_;
|
||||
while (current != NULL) {
|
||||
threads.AddValue(current);
|
||||
current = current->next_;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
intptr_t ThreadRegistry::CountZoneHandles(Isolate* isolate_of_interest) const {
|
||||
MonitorLocker ml(threads_lock());
|
||||
intptr_t count = 0;
|
||||
Thread* current = active_list_;
|
||||
while (current != NULL) {
|
||||
if (current->isolate() == isolate_of_interest) {
|
||||
count += current->CountZoneHandles();
|
||||
}
|
||||
current = current->next_;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
intptr_t ThreadRegistry::CountScopedHandles(
|
||||
Isolate* isolate_of_interest) const {
|
||||
MonitorLocker ml(threads_lock());
|
||||
intptr_t count = 0;
|
||||
Thread* current = active_list_;
|
||||
while (current != NULL) {
|
||||
if (current->isolate() == isolate_of_interest) {
|
||||
count += current->CountScopedHandles();
|
||||
}
|
||||
current = current->next_;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void ThreadRegistry::AddToActiveListLocked(Thread* thread) {
|
||||
ASSERT(thread != NULL);
|
||||
ASSERT(threads_lock()->IsOwnedByCurrentThread());
|
||||
|
|
|
@ -37,9 +37,6 @@ class ThreadRegistry {
|
|||
void PrintJSON(JSONStream* stream) const;
|
||||
#endif
|
||||
|
||||
intptr_t CountZoneHandles(Isolate* isolate_of_interest) const;
|
||||
intptr_t CountScopedHandles(Isolate* isolate_of_interest) const;
|
||||
|
||||
private:
|
||||
Thread* active_list() const { return active_list_; }
|
||||
Monitor* threads_lock() const { return &threads_lock_; }
|
||||
|
|
|
@ -50,9 +50,6 @@ class ThreadState : public BaseThread {
|
|||
|
||||
void IncrementMemoryCapacity(uintptr_t value) {
|
||||
current_zone_capacity_ += value;
|
||||
if (current_zone_capacity_ > zone_high_watermark_) {
|
||||
zone_high_watermark_ = current_zone_capacity_;
|
||||
}
|
||||
}
|
||||
|
||||
void DecrementMemoryCapacity(uintptr_t value) {
|
||||
|
@ -61,9 +58,6 @@ class ThreadState : public BaseThread {
|
|||
}
|
||||
|
||||
uintptr_t current_zone_capacity() const { return current_zone_capacity_; }
|
||||
uintptr_t zone_high_watermark() const { return zone_high_watermark_; }
|
||||
|
||||
void ResetHighWatermark() { zone_high_watermark_ = current_zone_capacity_; }
|
||||
|
||||
StackResource* top_resource() const { return top_resource_; }
|
||||
void set_top_resource(StackResource* value) { top_resource_ = value; }
|
||||
|
@ -101,7 +95,6 @@ class ThreadState : public BaseThread {
|
|||
OSThread* os_thread_ = nullptr;
|
||||
Zone* zone_ = nullptr;
|
||||
uintptr_t current_zone_capacity_ = 0;
|
||||
uintptr_t zone_high_watermark_ = 0;
|
||||
StackResource* top_resource_ = nullptr;
|
||||
LongJumpScope* long_jump_base_ = nullptr;
|
||||
|
||||
|
|
|
@ -313,37 +313,6 @@ ISOLATE_UNIT_TEST_CASE(ManySimpleTasksWithZones) {
|
|||
done_count = 0;
|
||||
}
|
||||
|
||||
// Get the information for the current isolate.
|
||||
// We only need to check the current isolate since all tasks are spawned
|
||||
// inside this single isolate.
|
||||
JSONStream stream;
|
||||
isolate->PrintJSON(&stream, false);
|
||||
const char* json = stream.ToCString();
|
||||
|
||||
Thread* current_thread = Thread::Current();
|
||||
|
||||
// Confirm all expected entries are in the JSON output.
|
||||
for (intptr_t i = 0; i < kTaskCount; i++) {
|
||||
Thread* thread = threads[i];
|
||||
StackZone stack_zone(current_thread);
|
||||
Zone* current_zone = current_thread->zone();
|
||||
|
||||
// Check the thread exists and is the correct size.
|
||||
char* thread_info_buf = OS::SCreate(
|
||||
current_zone,
|
||||
"\"type\":\"_Thread\","
|
||||
"\"id\":\"threads\\/%" Pd
|
||||
"\","
|
||||
"\"kind\":\"%s\","
|
||||
"\"_zoneHighWatermark\":\"%" Pu
|
||||
"\","
|
||||
"\"_zoneCapacity\":\"%" Pu "\"",
|
||||
OSThread::ThreadIdToIntPtr(thread->os_thread()->trace_id()),
|
||||
Thread::TaskKindToCString(thread->task_kind()),
|
||||
thread->zone_high_watermark(), thread->current_zone_capacity());
|
||||
EXPECT_SUBSTRING(thread_info_buf, json);
|
||||
}
|
||||
|
||||
// Unblock the tasks so they can finish.
|
||||
{
|
||||
MonitorLocker sync_ml(&sync);
|
||||
|
|
Loading…
Reference in a new issue