mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[ VM / Service ] Add UserTag support to C-API and send UserTagChanged
events on Developer stream. Also removes intrinsic implementations for UserTag_makeCurrent to allow for service events to be sent on UserTag change. TEST=DartAPI_UserTags,pkg/vm_service/test/user_tag_changed_test.dart Change-Id: I5dc9ee77c0048590d3c6e33a652eee5bc3bf522a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/204440 Commit-Queue: Ben Konyi <bkonyi@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
parent
dc1804fff4
commit
3a4b3514bc
|
@ -159,6 +159,7 @@ String assertEventKind(String obj) {
|
|||
if (obj == "ServiceUnregistered") return obj;
|
||||
if (obj == "TimelineEvents") return obj;
|
||||
if (obj == "TimelineStreamSubscriptionsUpdate") return obj;
|
||||
if (obj == "UserTagChanged") return obj;
|
||||
if (obj == "VMFlagUpdate") return obj;
|
||||
if (obj == "VMUpdate") return obj;
|
||||
if (obj == "WriteEvent") return obj;
|
||||
|
|
|
@ -1 +1 @@
|
|||
version=3.47
|
||||
version=3.48
|
||||
|
|
|
@ -26,7 +26,7 @@ export 'snapshot_graph.dart'
|
|||
HeapSnapshotObjectNoData,
|
||||
HeapSnapshotObjectNullData;
|
||||
|
||||
const String vmServiceVersion = '3.47.0';
|
||||
const String vmServiceVersion = '3.48.0';
|
||||
|
||||
/// @optional
|
||||
const String optional = 'optional';
|
||||
|
@ -1150,6 +1150,7 @@ abstract class VmServiceInterface {
|
|||
/// Debug | PauseStart, PauseExit, PauseBreakpoint, PauseInterrupted,
|
||||
/// PauseException, PausePostRequest, Resume, BreakpointAdded,
|
||||
/// BreakpointResolved, BreakpointRemoved, BreakpointUpdated, Inspect, None
|
||||
/// Profiler | UserTagChanged
|
||||
/// GC | GC
|
||||
/// Extension | Extension
|
||||
/// Timeline | TimelineEvents, TimelineStreamsSubscriptionUpdate
|
||||
|
@ -1690,6 +1691,9 @@ class VmService implements VmServiceInterface {
|
|||
// PauseStart, PauseExit, PauseBreakpoint, PauseInterrupted, PauseException, PausePostRequest, Resume, BreakpointAdded, BreakpointResolved, BreakpointRemoved, BreakpointUpdated, Inspect, None
|
||||
Stream<Event> get onDebugEvent => _getEventController('Debug').stream;
|
||||
|
||||
// UserTagChanged
|
||||
Stream<Event> get onProfilerEvent => _getEventController('Profiler').stream;
|
||||
|
||||
// GC
|
||||
Stream<Event> get onGCEvent => _getEventController('GC').stream;
|
||||
|
||||
|
@ -2384,6 +2388,7 @@ class EventStreams {
|
|||
static const String kVM = 'VM';
|
||||
static const String kIsolate = 'Isolate';
|
||||
static const String kDebug = 'Debug';
|
||||
static const String kProfiler = 'Profiler';
|
||||
static const String kGC = 'GC';
|
||||
static const String kExtension = 'Extension';
|
||||
static const String kTimeline = 'Timeline';
|
||||
|
@ -2496,6 +2501,9 @@ class EventKind {
|
|||
/// Notification that a Service has been removed from the Service Protocol
|
||||
/// from another client.
|
||||
static const String kServiceUnregistered = 'ServiceUnregistered';
|
||||
|
||||
/// Notification that the UserTag for an isolate has been changed.
|
||||
static const String kUserTagChanged = 'UserTagChanged';
|
||||
}
|
||||
|
||||
/// Adding new values to `InstanceKind` is considered a backwards compatible
|
||||
|
@ -3885,6 +3893,14 @@ class Event extends Response {
|
|||
@optional
|
||||
bool? last;
|
||||
|
||||
/// The current UserTag label.
|
||||
@optional
|
||||
String? updatedTag;
|
||||
|
||||
/// The previous UserTag label.
|
||||
@optional
|
||||
String? previousTag;
|
||||
|
||||
/// Binary data associated with the event.
|
||||
///
|
||||
/// This is provided for the event kinds:
|
||||
|
@ -3917,6 +3933,8 @@ class Event extends Response {
|
|||
this.flag,
|
||||
this.newValue,
|
||||
this.last,
|
||||
this.updatedTag,
|
||||
this.previousTag,
|
||||
this.data,
|
||||
});
|
||||
|
||||
|
@ -3959,6 +3977,8 @@ class Event extends Response {
|
|||
flag = json['flag'];
|
||||
newValue = json['newValue'];
|
||||
last = json['last'];
|
||||
updatedTag = json['updatedTag'];
|
||||
previousTag = json['previousTag'];
|
||||
data = json['data'];
|
||||
}
|
||||
|
||||
|
@ -3998,6 +4018,8 @@ class Event extends Response {
|
|||
_setIfNotNull(json, 'flag', flag);
|
||||
_setIfNotNull(json, 'newValue', newValue);
|
||||
_setIfNotNull(json, 'last', last);
|
||||
_setIfNotNull(json, 'updatedTag', updatedTag);
|
||||
_setIfNotNull(json, 'previousTag', previousTag);
|
||||
_setIfNotNull(json, 'data', data);
|
||||
return json;
|
||||
}
|
||||
|
|
|
@ -346,7 +346,7 @@ class _ServiceTesterRunner {
|
|||
completer!.complete(vmIsolates.first);
|
||||
completer = null;
|
||||
}
|
||||
return await (completer!.future as FutureOr<IsolateRef>);
|
||||
return (await completer!.future) as IsolateRef;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
62
pkg/vm_service/test/user_tag_changed_test.dart
Normal file
62
pkg/vm_service/test/user_tag_changed_test.dart
Normal file
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) 2021, 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 'dart:developer';
|
||||
|
||||
import 'package:async/async.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vm_service/vm_service.dart';
|
||||
|
||||
import 'common/service_test_common.dart';
|
||||
import 'common/test_helper.dart';
|
||||
|
||||
void testMain() {
|
||||
final tag = UserTag('Foo');
|
||||
final origTag = tag.makeCurrent();
|
||||
origTag.makeCurrent();
|
||||
}
|
||||
|
||||
late StreamQueue<Event> stream;
|
||||
|
||||
var tests = <IsolateTest>[
|
||||
hasPausedAtStart,
|
||||
(VmService service, IsolateRef isolate) async {
|
||||
await service.streamListen(EventStreams.kProfiler);
|
||||
stream = StreamQueue(
|
||||
service.onProfilerEvent.transform(
|
||||
SingleSubscriptionTransformer<Event, Event>(),
|
||||
),
|
||||
);
|
||||
},
|
||||
resumeIsolate,
|
||||
hasStoppedAtExit,
|
||||
(VmService service, IsolateRef isolate) async {
|
||||
await service.streamCancel(EventStreams.kProfiler);
|
||||
expect(await stream.hasNext, true);
|
||||
|
||||
var event = await stream.next;
|
||||
expect(event.kind, EventKind.kUserTagChanged);
|
||||
expect(event.updatedTag, 'Foo');
|
||||
expect(event.previousTag, 'Default');
|
||||
|
||||
expect(await stream.hasNext, true);
|
||||
event = await stream.next;
|
||||
expect(event.kind, EventKind.kUserTagChanged);
|
||||
expect(event.updatedTag, 'Default');
|
||||
expect(event.previousTag, 'Foo');
|
||||
},
|
||||
resumeIsolate,
|
||||
(VmService service, IsolateRef isolate) async {
|
||||
expect(await stream.hasNext, false);
|
||||
}
|
||||
];
|
||||
|
||||
main([args = const <String>[]]) async => await runIsolateTests(
|
||||
args,
|
||||
tests,
|
||||
'user_tag_changed_test.dart',
|
||||
pause_on_start: true,
|
||||
pause_on_exit: true,
|
||||
testeeConcurrent: testMain,
|
||||
);
|
|
@ -496,4 +496,53 @@ Dart_IsolateRunnableLatencyMetric(Dart_Isolate isolate); // Microsecond
|
|||
DART_EXPORT int64_t
|
||||
Dart_IsolateRunnableHeapSizeMetric(Dart_Isolate isolate); // Byte
|
||||
|
||||
/*
|
||||
* ========
|
||||
* UserTags
|
||||
* ========
|
||||
*/
|
||||
|
||||
/*
|
||||
* Gets the current isolate's currently set UserTag instance.
|
||||
*
|
||||
* \return The currently set UserTag instance.
|
||||
*/
|
||||
DART_EXPORT Dart_Handle Dart_GetCurrentUserTag();
|
||||
|
||||
/*
|
||||
* Gets the current isolate's default UserTag instance.
|
||||
*
|
||||
* \return The default UserTag with label 'Default'
|
||||
*/
|
||||
DART_EXPORT Dart_Handle Dart_GetDefaultUserTag();
|
||||
|
||||
/*
|
||||
* Creates a new UserTag instance.
|
||||
*
|
||||
* \param label The name of the new UserTag.
|
||||
*
|
||||
* \return The newly created UserTag instance or an error handle.
|
||||
*/
|
||||
DART_EXPORT Dart_Handle Dart_NewUserTag(const char* label);
|
||||
|
||||
/*
|
||||
* Updates the current isolate's UserTag to a new value.
|
||||
*
|
||||
* \param user_tag The UserTag to be set as the current UserTag.
|
||||
*
|
||||
* \return The previously set UserTag instance or an error handle.
|
||||
*/
|
||||
DART_EXPORT Dart_Handle Dart_SetCurrentUserTag(Dart_Handle user_tag);
|
||||
|
||||
/*
|
||||
* Returns the label of a given UserTag instance.
|
||||
*
|
||||
* \param user_tag The UserTag from which the label will be retrieved.
|
||||
*
|
||||
* \return The UserTag's label. NULL if the user_tag is invalid. The caller is
|
||||
* responsible for freeing the returned label.
|
||||
*/
|
||||
DART_WARN_UNUSED_RESULT DART_EXPORT char* Dart_GetUserTagLabel(
|
||||
Dart_Handle user_tag);
|
||||
|
||||
#endif // RUNTIME_INCLUDE_DART_TOOLS_API_H_
|
||||
|
|
|
@ -29,12 +29,7 @@ DEFINE_NATIVE_ENTRY(UserTag_label, 0, 1) {
|
|||
|
||||
DEFINE_NATIVE_ENTRY(UserTag_makeCurrent, 0, 1) {
|
||||
const UserTag& self = UserTag::CheckedHandle(zone, arguments->NativeArgAt(0));
|
||||
if (FLAG_trace_intrinsified_natives) {
|
||||
OS::PrintErr("UserTag_makeCurrent: %s\n", self.ToCString());
|
||||
}
|
||||
const UserTag& old = UserTag::Handle(zone, isolate->current_tag());
|
||||
self.MakeActive();
|
||||
return old.ptr();
|
||||
return self.MakeActive();
|
||||
}
|
||||
|
||||
DEFINE_NATIVE_ENTRY(UserTag_defaultTag, 0, 0) {
|
||||
|
|
|
@ -12,7 +12,7 @@ var tests = <VMTest>[
|
|||
final result = await vm.invokeRpcNoUpgrade('getVersion', {});
|
||||
expect(result['type'], 'Version');
|
||||
expect(result['major'], 3);
|
||||
expect(result['minor'], 47);
|
||||
expect(result['minor'], 48);
|
||||
expect(result['_privateMajor'], 0);
|
||||
expect(result['_privateMinor'], 0);
|
||||
},
|
||||
|
|
|
@ -9,10 +9,10 @@ import 'test_helper.dart';
|
|||
|
||||
var tests = <VMTest>[
|
||||
(VM vm) async {
|
||||
var result = await vm.invokeRpcNoUpgrade('getVersion', {});
|
||||
final result = await vm.invokeRpcNoUpgrade('getVersion', {});
|
||||
expect(result['type'], equals('Version'));
|
||||
expect(result['major'], equals(3));
|
||||
expect(result['minor'], equals(47));
|
||||
expect(result['minor'], equals(48));
|
||||
expect(result['_privateMajor'], equals(0));
|
||||
expect(result['_privateMinor'], equals(0));
|
||||
},
|
||||
|
|
|
@ -2020,24 +2020,6 @@ void AsmIntrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
|
|||
__ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
|
||||
}
|
||||
|
||||
// On stack: user tag (+0).
|
||||
void AsmIntrinsifier::UserTag_makeCurrent(Assembler* assembler,
|
||||
Label* normal_ir_body) {
|
||||
// R1: Isolate.
|
||||
__ LoadIsolate(R1);
|
||||
// R0: Current user tag.
|
||||
__ ldr(R0, Address(R1, target::Isolate::current_tag_offset()));
|
||||
// R2: UserTag.
|
||||
__ ldr(R2, Address(SP, +0 * target::kWordSize));
|
||||
// Set target::Isolate::current_tag_.
|
||||
__ str(R2, Address(R1, target::Isolate::current_tag_offset()));
|
||||
// R2: UserTag's tag.
|
||||
__ ldr(R2, FieldAddress(R2, target::UserTag::tag_offset()));
|
||||
// Set target::Isolate::user_tag_.
|
||||
__ str(R2, Address(R1, target::Isolate::user_tag_offset()));
|
||||
__ Ret();
|
||||
}
|
||||
|
||||
void AsmIntrinsifier::UserTag_defaultTag(Assembler* assembler,
|
||||
Label* normal_ir_body) {
|
||||
__ LoadIsolate(R0);
|
||||
|
|
|
@ -2224,24 +2224,6 @@ void AsmIntrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
|
|||
__ br(R1);
|
||||
}
|
||||
|
||||
// On stack: user tag (+0).
|
||||
void AsmIntrinsifier::UserTag_makeCurrent(Assembler* assembler,
|
||||
Label* normal_ir_body) {
|
||||
// R1: Isolate.
|
||||
__ LoadIsolate(R1);
|
||||
// R0: Current user tag.
|
||||
__ ldr(R0, Address(R1, target::Isolate::current_tag_offset()));
|
||||
// R2: UserTag.
|
||||
__ ldr(R2, Address(SP, +0 * target::kWordSize));
|
||||
// Set target::Isolate::current_tag_.
|
||||
__ str(R2, Address(R1, target::Isolate::current_tag_offset()));
|
||||
// R2: UserTag's tag.
|
||||
__ ldr(R2, FieldAddress(R2, target::UserTag::tag_offset()));
|
||||
// Set target::Isolate::user_tag_.
|
||||
__ str(R2, Address(R1, target::Isolate::user_tag_offset()));
|
||||
__ ret();
|
||||
}
|
||||
|
||||
void AsmIntrinsifier::UserTag_defaultTag(Assembler* assembler,
|
||||
Label* normal_ir_body) {
|
||||
__ LoadIsolate(R0);
|
||||
|
|
|
@ -2009,24 +2009,6 @@ void AsmIntrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
|
|||
__ jmp(FieldAddress(EAX, target::Function::entry_point_offset()));
|
||||
}
|
||||
|
||||
// On stack: user tag (+1), return-address (+0).
|
||||
void AsmIntrinsifier::UserTag_makeCurrent(Assembler* assembler,
|
||||
Label* normal_ir_body) {
|
||||
// EDI: Isolate.
|
||||
__ LoadIsolate(EDI);
|
||||
// EAX: Current user tag.
|
||||
__ movl(EAX, Address(EDI, target::Isolate::current_tag_offset()));
|
||||
// EAX: UserTag.
|
||||
__ movl(EBX, Address(ESP, +1 * target::kWordSize));
|
||||
// Set target::Isolate::current_tag_.
|
||||
__ movl(Address(EDI, target::Isolate::current_tag_offset()), EBX);
|
||||
// EAX: UserTag's tag.
|
||||
__ movl(EBX, FieldAddress(EBX, target::UserTag::tag_offset()));
|
||||
// Set target::Isolate::user_tag_.
|
||||
__ movl(Address(EDI, target::Isolate::user_tag_offset()), EBX);
|
||||
__ ret();
|
||||
}
|
||||
|
||||
void AsmIntrinsifier::UserTag_defaultTag(Assembler* assembler,
|
||||
Label* normal_ir_body) {
|
||||
__ LoadIsolate(EAX);
|
||||
|
|
|
@ -2086,24 +2086,6 @@ void AsmIntrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
|
|||
__ jmp(RDI);
|
||||
}
|
||||
|
||||
// On stack: user tag (+1), return-address (+0).
|
||||
void AsmIntrinsifier::UserTag_makeCurrent(Assembler* assembler,
|
||||
Label* normal_ir_body) {
|
||||
// RBX: Isolate.
|
||||
__ LoadIsolate(RBX);
|
||||
// RAX: Current user tag.
|
||||
__ movq(RAX, Address(RBX, target::Isolate::current_tag_offset()));
|
||||
// R10: UserTag.
|
||||
__ movq(R10, Address(RSP, +1 * target::kWordSize));
|
||||
// Set Isolate::current_tag_.
|
||||
__ movq(Address(RBX, target::Isolate::current_tag_offset()), R10);
|
||||
// R10: UserTag's tag.
|
||||
__ movq(R10, FieldAddress(R10, target::UserTag::tag_offset()));
|
||||
// Set Isolate::user_tag_.
|
||||
__ movq(Address(RBX, target::Isolate::user_tag_offset()), R10);
|
||||
__ ret();
|
||||
}
|
||||
|
||||
void AsmIntrinsifier::UserTag_defaultTag(Assembler* assembler,
|
||||
Label* normal_ir_body) {
|
||||
__ LoadIsolate(RAX);
|
||||
|
|
|
@ -377,7 +377,6 @@ namespace dart {
|
|||
GRAPH_MATH_LIB_INTRINSIC_LIST(V) \
|
||||
|
||||
#define DEVELOPER_LIB_INTRINSIC_LIST(V) \
|
||||
V(_UserTag, makeCurrent, UserTag_makeCurrent, 0x5bd9b88e) \
|
||||
V(::, _getDefaultTag, UserTag_defaultTag, 0x6c19c8a5) \
|
||||
V(::, _getCurrentTag, Profiler_getCurrentTag, 0x70ead08e) \
|
||||
V(::, _isDartStreamEnabled, Timeline_isDartStreamEnabled, 0xc97aafb3) \
|
||||
|
|
|
@ -7011,4 +7011,53 @@ DART_EXPORT void Dart_PrepareToAbort() {
|
|||
OS::PrepareToAbort();
|
||||
}
|
||||
|
||||
DART_EXPORT Dart_Handle Dart_GetCurrentUserTag() {
|
||||
Thread* thread = Thread::Current();
|
||||
CHECK_ISOLATE(thread->isolate());
|
||||
DARTSCOPE(thread);
|
||||
Isolate* isolate = thread->isolate();
|
||||
return Api::NewHandle(thread, isolate->current_tag());
|
||||
}
|
||||
|
||||
DART_EXPORT Dart_Handle Dart_GetDefaultUserTag() {
|
||||
Thread* thread = Thread::Current();
|
||||
CHECK_ISOLATE(thread->isolate());
|
||||
DARTSCOPE(thread);
|
||||
Isolate* isolate = thread->isolate();
|
||||
return Api::NewHandle(thread, isolate->default_tag());
|
||||
}
|
||||
|
||||
DART_EXPORT Dart_Handle Dart_NewUserTag(const char* label) {
|
||||
Thread* thread = Thread::Current();
|
||||
CHECK_ISOLATE(thread->isolate());
|
||||
DARTSCOPE(thread);
|
||||
if (label == nullptr) {
|
||||
return Api::NewError(
|
||||
"Dart_NewUserTag expects argument 'label' to be non-null");
|
||||
}
|
||||
const String& value = String::Handle(String::New(label));
|
||||
return Api::NewHandle(thread, UserTag::New(value));
|
||||
}
|
||||
|
||||
DART_EXPORT Dart_Handle Dart_SetCurrentUserTag(Dart_Handle user_tag) {
|
||||
Thread* thread = Thread::Current();
|
||||
CHECK_ISOLATE(thread->isolate());
|
||||
DARTSCOPE(thread);
|
||||
const UserTag& tag = Api::UnwrapUserTagHandle(Z, user_tag);
|
||||
if (tag.IsNull()) {
|
||||
RETURN_TYPE_ERROR(Z, user_tag, UserTag);
|
||||
}
|
||||
return Api::NewHandle(thread, tag.MakeActive());
|
||||
}
|
||||
|
||||
DART_EXPORT char* Dart_GetUserTagLabel(Dart_Handle user_tag) {
|
||||
DARTSCOPE(Thread::Current());
|
||||
const UserTag& tag = Api::UnwrapUserTagHandle(Z, user_tag);
|
||||
if (tag.IsNull()) {
|
||||
return nullptr;
|
||||
}
|
||||
const String& label = String::Handle(Z, tag.label());
|
||||
return Utils::StrDup(label.ToCString());
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
|
|
|
@ -9363,6 +9363,52 @@ TEST_CASE(Dart_SetFfiNativeResolver_DoesNotResolve) {
|
|||
"Invalid argument(s): Couldn't resolve function: 'DoesNotResolve'");
|
||||
}
|
||||
|
||||
TEST_CASE(DartAPI_UserTags) {
|
||||
Dart_Handle default_tag = Dart_GetDefaultUserTag();
|
||||
EXPECT_VALID(default_tag);
|
||||
|
||||
auto default_label =
|
||||
Utils::CStringUniquePtr(Dart_GetUserTagLabel(default_tag), std::free);
|
||||
EXPECT_STREQ(default_label.get(), "Default");
|
||||
|
||||
Dart_Handle current_tag = Dart_GetCurrentUserTag();
|
||||
EXPECT(Dart_IdentityEquals(default_tag, current_tag));
|
||||
|
||||
auto current_label =
|
||||
Utils::CStringUniquePtr(Dart_GetUserTagLabel(current_tag), std::free);
|
||||
EXPECT_STREQ(default_label.get(), current_label.get());
|
||||
|
||||
Dart_Handle new_tag = Dart_NewUserTag("Foo");
|
||||
EXPECT_VALID(new_tag);
|
||||
|
||||
auto new_tag_label =
|
||||
Utils::CStringUniquePtr(Dart_GetUserTagLabel(new_tag), std::free);
|
||||
EXPECT_STREQ(new_tag_label.get(), "Foo");
|
||||
|
||||
Dart_Handle old_tag = Dart_SetCurrentUserTag(new_tag);
|
||||
EXPECT_VALID(old_tag);
|
||||
|
||||
auto old_label =
|
||||
Utils::CStringUniquePtr(Dart_GetUserTagLabel(old_tag), std::free);
|
||||
EXPECT_STREQ(old_label.get(), default_label.get());
|
||||
|
||||
current_tag = Dart_GetCurrentUserTag();
|
||||
EXPECT(Dart_IdentityEquals(new_tag, current_tag));
|
||||
|
||||
current_label =
|
||||
Utils::CStringUniquePtr(Dart_GetUserTagLabel(current_tag), std::free);
|
||||
EXPECT_STREQ(current_label.get(), new_tag_label.get());
|
||||
|
||||
EXPECT(Dart_GetUserTagLabel(Dart_Null()) == nullptr);
|
||||
|
||||
EXPECT_ERROR(Dart_NewUserTag(nullptr),
|
||||
"Dart_NewUserTag expects argument 'label' to be non-null");
|
||||
|
||||
EXPECT_ERROR(
|
||||
Dart_SetCurrentUserTag(Dart_Null()),
|
||||
"Dart_SetCurrentUserTag expects argument 'user_tag' to be non-null");
|
||||
}
|
||||
|
||||
#endif // !PRODUCT
|
||||
|
||||
} // namespace dart
|
||||
|
|
|
@ -25690,10 +25690,25 @@ const char* MirrorReference::ToCString() const {
|
|||
return "_MirrorReference";
|
||||
}
|
||||
|
||||
void UserTag::MakeActive() const {
|
||||
UserTagPtr UserTag::MakeActive() const {
|
||||
Isolate* isolate = Isolate::Current();
|
||||
ASSERT(isolate != NULL);
|
||||
UserTag& old = UserTag::Handle(isolate->current_tag());
|
||||
isolate->set_current_tag(*this);
|
||||
|
||||
#if !defined(PRODUCT)
|
||||
// Notify VM service clients that the current UserTag has changed.
|
||||
if (Service::profiler_stream.enabled()) {
|
||||
ServiceEvent event(ServiceEvent::kUserTagChanged);
|
||||
String& name = String::Handle(old.label());
|
||||
event.set_previous_tag(name.ToCString());
|
||||
name ^= label();
|
||||
event.set_updated_tag(name.ToCString());
|
||||
Service::HandleEvent(&event);
|
||||
}
|
||||
#endif // !defined(PRODUCT)
|
||||
|
||||
return old.ptr();
|
||||
}
|
||||
|
||||
UserTagPtr UserTag::New(const String& label, Heap::Space space) {
|
||||
|
|
|
@ -11559,7 +11559,7 @@ class UserTag : public Instance {
|
|||
|
||||
StringPtr label() const { return untag()->label(); }
|
||||
|
||||
void MakeActive() const;
|
||||
UserTagPtr MakeActive() const;
|
||||
|
||||
static intptr_t InstanceSize() {
|
||||
return RoundedAllocationSize(sizeof(UntaggedUserTag));
|
||||
|
|
|
@ -4605,7 +4605,7 @@ ISOLATE_UNIT_TEST_CASE(PrintJSONPrimitives) {
|
|||
"vmName\":\"\",\"location\":{\"type\":\"SourceLocation\",\"script\":{"
|
||||
"\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:"
|
||||
"developer-patch\\/profiler.dart\",\"_kind\":\"kernel\"},\"tokenPos\":"
|
||||
"414,\"endTokenPos\":672},\"library\":{\"type\":\"@Library\","
|
||||
"414,\"endTokenPos\":628},\"library\":{\"type\":\"@Library\","
|
||||
"\"fixedId\":true,\"id\":\"\",\"name\":\"dart.developer\",\"uri\":"
|
||||
"\"dart:developer\"}},"
|
||||
// Handle non-zero identity hash.
|
||||
|
|
|
@ -128,16 +128,18 @@ StreamInfo Service::heapsnapshot_stream("HeapSnapshot");
|
|||
StreamInfo Service::logging_stream("Logging");
|
||||
StreamInfo Service::extension_stream("Extension");
|
||||
StreamInfo Service::timeline_stream("Timeline");
|
||||
StreamInfo Service::profiler_stream("Profiler");
|
||||
|
||||
const uint8_t* Service::dart_library_kernel_ = NULL;
|
||||
intptr_t Service::dart_library_kernel_len_ = 0;
|
||||
|
||||
static StreamInfo* const streams_[] = {
|
||||
&Service::vm_stream, &Service::isolate_stream,
|
||||
&Service::debug_stream, &Service::gc_stream,
|
||||
&Service::echo_stream, &Service::heapsnapshot_stream,
|
||||
&Service::logging_stream, &Service::extension_stream,
|
||||
&Service::timeline_stream};
|
||||
&Service::vm_stream, &Service::isolate_stream,
|
||||
&Service::debug_stream, &Service::gc_stream,
|
||||
&Service::echo_stream, &Service::heapsnapshot_stream,
|
||||
&Service::logging_stream, &Service::extension_stream,
|
||||
&Service::timeline_stream, &Service::profiler_stream,
|
||||
};
|
||||
|
||||
bool Service::ListenStream(const char* stream_id) {
|
||||
if (FLAG_trace_service) {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
namespace dart {
|
||||
|
||||
#define SERVICE_PROTOCOL_MAJOR_VERSION 3
|
||||
#define SERVICE_PROTOCOL_MINOR_VERSION 47
|
||||
#define SERVICE_PROTOCOL_MINOR_VERSION 48
|
||||
|
||||
class Array;
|
||||
class EmbedderServiceHandler;
|
||||
|
@ -171,6 +171,7 @@ class Service : public AllStatic {
|
|||
static StreamInfo logging_stream;
|
||||
static StreamInfo extension_stream;
|
||||
static StreamInfo timeline_stream;
|
||||
static StreamInfo profiler_stream;
|
||||
|
||||
static bool ListenStream(const char* stream_id);
|
||||
static void CancelStream(const char* stream_id);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Dart VM Service Protocol 3.47
|
||||
# Dart VM Service Protocol 3.48
|
||||
|
||||
> Please post feedback to the [observatory-discuss group][discuss-list]
|
||||
|
||||
This document describes of _version 3.47_ of the Dart VM Service Protocol. This
|
||||
This document describes of _version 3.48_ 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.
|
||||
|
@ -1477,6 +1477,7 @@ streamId | event types provided
|
|||
VM | VMUpdate, VMFlagUpdate
|
||||
Isolate | IsolateStart, IsolateRunnable, IsolateExit, IsolateUpdate, IsolateReload, ServiceExtensionAdded
|
||||
Debug | PauseStart, PauseExit, PauseBreakpoint, PauseInterrupted, PauseException, PausePostRequest, Resume, BreakpointAdded, BreakpointResolved, BreakpointRemoved, BreakpointUpdated, Inspect, None
|
||||
Profiler | UserTagChanged
|
||||
GC | GC
|
||||
Extension | Extension
|
||||
Timeline | TimelineEvents, TimelineStreamsSubscriptionUpdate
|
||||
|
@ -2154,6 +2155,12 @@ class Event extends Response {
|
|||
// This is provided for the event kinds:
|
||||
// HeapSnapshot
|
||||
bool last [optional];
|
||||
|
||||
// The current UserTag label.
|
||||
string updatedTag [optional];
|
||||
|
||||
// The previous UserTag label.
|
||||
string previousTag [optional];
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -2264,6 +2271,9 @@ enum EventKind {
|
|||
// Notification that a Service has been removed from the Service Protocol
|
||||
// from another client.
|
||||
ServiceUnregistered,
|
||||
|
||||
// Notification that the UserTag for an isolate has been changed.
|
||||
UserTagChanged,
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -4058,5 +4068,6 @@ version | comments
|
|||
3.45 | Added `setBreakpointState` RPC and `BreakpointUpdated` event kind.
|
||||
3.46 | Moved `sourceLocation` property into reference types for `Class`, `Field`, and `Function`.
|
||||
3.47 | Added `shows` and `hides` properties to `LibraryDependency`.
|
||||
3.48 | Added `Profiler` stream, `UserTagChanged` event kind, and `updatedTag` and `previousTag` properties to `Event`.
|
||||
|
||||
[discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
|
||||
|
|
|
@ -28,22 +28,24 @@ ServiceEvent::ServiceEvent(IsolateGroup* isolate_group,
|
|||
: isolate_(isolate),
|
||||
isolate_group_(isolate_group),
|
||||
kind_(event_kind),
|
||||
flag_name_(NULL),
|
||||
flag_new_value_(NULL),
|
||||
embedder_kind_(NULL),
|
||||
embedder_stream_id_(NULL),
|
||||
breakpoint_(NULL),
|
||||
top_frame_(NULL),
|
||||
timeline_event_block_(NULL),
|
||||
extension_rpc_(NULL),
|
||||
exception_(NULL),
|
||||
reload_error_(NULL),
|
||||
spawn_token_(NULL),
|
||||
spawn_error_(NULL),
|
||||
flag_name_(nullptr),
|
||||
flag_new_value_(nullptr),
|
||||
previous_tag_(nullptr),
|
||||
updated_tag_(nullptr),
|
||||
embedder_kind_(nullptr),
|
||||
embedder_stream_id_(nullptr),
|
||||
breakpoint_(nullptr),
|
||||
top_frame_(nullptr),
|
||||
timeline_event_block_(nullptr),
|
||||
extension_rpc_(nullptr),
|
||||
exception_(nullptr),
|
||||
reload_error_(nullptr),
|
||||
spawn_token_(nullptr),
|
||||
spawn_error_(nullptr),
|
||||
at_async_jump_(false),
|
||||
inspectee_(NULL),
|
||||
gc_stats_(NULL),
|
||||
bytes_(NULL),
|
||||
inspectee_(nullptr),
|
||||
gc_stats_(nullptr),
|
||||
bytes_(nullptr),
|
||||
bytes_length_(0),
|
||||
timestamp_(OS::GetCurrentTimeMillis()) {
|
||||
// We should never generate events for the vm isolate as it is never reported
|
||||
|
@ -137,6 +139,8 @@ const char* ServiceEvent::KindAsCString() const {
|
|||
return "TimelineEvents";
|
||||
case kTimelineStreamSubscriptionsUpdate:
|
||||
return "TimelineStreamSubscriptionsUpdate";
|
||||
case kUserTagChanged:
|
||||
return "UserTagChanged";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return "Unknown";
|
||||
|
@ -187,11 +191,14 @@ const StreamInfo* ServiceEvent::stream_info() const {
|
|||
return &Service::timeline_stream;
|
||||
|
||||
case kEmbedder:
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
case kUserTagChanged:
|
||||
return &Service::profiler_stream;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,6 +220,10 @@ void ServiceEvent::PrintJSON(JSONStream* js) const {
|
|||
// For backwards compatibility, "new_value" is also provided.
|
||||
jsobj.AddProperty("newValue", flag_new_value());
|
||||
}
|
||||
if (kind() == kUserTagChanged) {
|
||||
jsobj.AddProperty("previousTag", previous_tag());
|
||||
jsobj.AddProperty("updatedTag", updated_tag());
|
||||
}
|
||||
if (kind() == kIsolateReload) {
|
||||
if (reload_error_ == NULL) {
|
||||
jsobj.AddProperty("status", "success");
|
||||
|
|
|
@ -60,6 +60,8 @@ class ServiceEvent {
|
|||
// Sent when SetVMTimelineFlags is called.
|
||||
kTimelineStreamSubscriptionsUpdate,
|
||||
|
||||
kUserTagChanged,
|
||||
|
||||
kIllegal,
|
||||
};
|
||||
|
||||
|
@ -111,6 +113,14 @@ class ServiceEvent {
|
|||
const char* flag_new_value() const { return flag_new_value_; }
|
||||
void set_flag_new_value(const char* value) { flag_new_value_ = value; }
|
||||
|
||||
const char* previous_tag() const { return previous_tag_; }
|
||||
void set_previous_tag(const char* previous_tag) {
|
||||
previous_tag_ = previous_tag;
|
||||
}
|
||||
|
||||
const char* updated_tag() const { return updated_tag_; }
|
||||
void set_updated_tag(const char* updated_tag) { updated_tag_ = updated_tag; }
|
||||
|
||||
const char* embedder_kind() const { return embedder_kind_; }
|
||||
|
||||
const char* KindAsCString() const;
|
||||
|
@ -217,6 +227,8 @@ class ServiceEvent {
|
|||
EventKind kind_;
|
||||
const char* flag_name_;
|
||||
const char* flag_new_value_;
|
||||
const char* previous_tag_;
|
||||
const char* updated_tag_;
|
||||
const char* embedder_kind_;
|
||||
const char* embedder_stream_id_;
|
||||
Breakpoint* breakpoint_;
|
||||
|
|
|
@ -18,7 +18,6 @@ class UserTag {
|
|||
class _UserTag implements UserTag {
|
||||
factory _UserTag(String label) native "UserTag_new";
|
||||
String get label native "UserTag_label";
|
||||
@pragma("vm:recognized", "asm-intrinsic")
|
||||
UserTag makeCurrent() native "UserTag_makeCurrent";
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue