|  | // Copyright (c) 2013, 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. | 
|  |  | 
|  | #ifndef RUNTIME_VM_SERVICE_H_ | 
|  | #define RUNTIME_VM_SERVICE_H_ | 
|  |  | 
|  | #include <atomic> | 
|  |  | 
|  | #include "include/dart_tools_api.h" | 
|  |  | 
|  | #include "vm/allocation.h" | 
|  | #include "vm/object_id_ring.h" | 
|  | #include "vm/os_thread.h" | 
|  | #include "vm/tagged_pointer.h" | 
|  |  | 
|  | namespace dart { | 
|  |  | 
|  | #define SERVICE_PROTOCOL_MAJOR_VERSION 3 | 
|  | #define SERVICE_PROTOCOL_MINOR_VERSION 60 | 
|  |  | 
|  | class Array; | 
|  | class EmbedderServiceHandler; | 
|  | class Error; | 
|  | class GCEvent; | 
|  | class GrowableObjectArray; | 
|  | class Instance; | 
|  | class Isolate; | 
|  | class IsolateGroup; | 
|  | class JSONStream; | 
|  | class JSONObject; | 
|  | class Object; | 
|  | class ServiceEvent; | 
|  | class String; | 
|  |  | 
|  | class ServiceIdZone { | 
|  | public: | 
|  | ServiceIdZone(); | 
|  | virtual ~ServiceIdZone(); | 
|  |  | 
|  | // Returned string will be zone allocated. | 
|  | virtual char* GetServiceId(const Object& obj) = 0; | 
|  |  | 
|  | private: | 
|  | }; | 
|  |  | 
|  | #define ISOLATE_SERVICE_ID_FORMAT_STRING "isolates/%" Pd64 "" | 
|  | #define ISOLATE_GROUP_SERVICE_ID_PREFIX "isolateGroups/" | 
|  | #define ISOLATE_GROUP_SERVICE_ID_FORMAT_STRING                                 \ | 
|  | ISOLATE_GROUP_SERVICE_ID_PREFIX "%" Pu64 "" | 
|  |  | 
|  | class RingServiceIdZone : public ServiceIdZone { | 
|  | public: | 
|  | RingServiceIdZone(); | 
|  | virtual ~RingServiceIdZone(); | 
|  |  | 
|  | void Init(ObjectIdRing* ring, ObjectIdRing::IdPolicy policy); | 
|  |  | 
|  | // Returned string will be zone allocated. | 
|  | virtual char* GetServiceId(const Object& obj); | 
|  |  | 
|  | void set_policy(ObjectIdRing::IdPolicy policy) { policy_ = policy; } | 
|  |  | 
|  | ObjectIdRing::IdPolicy policy() const { return policy_; } | 
|  |  | 
|  | private: | 
|  | ObjectIdRing* ring_; | 
|  | ObjectIdRing::IdPolicy policy_; | 
|  | }; | 
|  |  | 
|  | class StreamInfo { | 
|  | public: | 
|  | explicit StreamInfo(const char* id) | 
|  | : id_(id), enabled_(0), include_private_members_(false) {} | 
|  |  | 
|  | const char* id() const { return id_; } | 
|  |  | 
|  | void set_enabled(bool value) { enabled_ = value ? 1 : 0; } | 
|  | bool enabled() const { return enabled_ != 0; } | 
|  |  | 
|  | void set_include_private_members(bool value) { | 
|  | include_private_members_ = value; | 
|  | } | 
|  | bool include_private_members() const { return include_private_members_; } | 
|  |  | 
|  | // This may get access by multiple threads, but relaxed access is ok. | 
|  | static intptr_t enabled_offset() { return OFFSET_OF(StreamInfo, enabled_); } | 
|  |  | 
|  | private: | 
|  | const char* id_; | 
|  | std::atomic<intptr_t> enabled_; | 
|  | bool include_private_members_; | 
|  | }; | 
|  |  | 
|  | class Service : public AllStatic { | 
|  | public: | 
|  | static void Init(); | 
|  | static void Cleanup(); | 
|  |  | 
|  | // Handles a message which is not directed to an isolate. | 
|  | static ErrorPtr HandleRootMessage(const Array& message); | 
|  |  | 
|  | // Handles a message which is not directed to an isolate and also | 
|  | // expects the parameter keys and values to be actual dart objects. | 
|  | static ErrorPtr HandleObjectRootMessage(const Array& message); | 
|  |  | 
|  | // Handles a message which is directed to a particular isolate. | 
|  | static ErrorPtr HandleIsolateMessage(Isolate* isolate, const Array& message); | 
|  |  | 
|  | static void HandleEvent(ServiceEvent* event, bool enter_safepoint = true); | 
|  |  | 
|  | static void RegisterIsolateEmbedderCallback( | 
|  | const char* name, | 
|  | Dart_ServiceRequestCallback callback, | 
|  | void* user_data); | 
|  |  | 
|  | static void RegisterRootEmbedderCallback(const char* name, | 
|  | Dart_ServiceRequestCallback callback, | 
|  | void* user_data); | 
|  |  | 
|  | static void SetEmbedderInformationCallback( | 
|  | Dart_EmbedderInformationCallback callback); | 
|  |  | 
|  | static void SetEmbedderStreamCallbacks( | 
|  | Dart_ServiceStreamListenCallback listen_callback, | 
|  | Dart_ServiceStreamCancelCallback cancel_callback); | 
|  |  | 
|  | static void SetGetServiceAssetsCallback( | 
|  | Dart_GetVMServiceAssetsArchive get_service_assets); | 
|  |  | 
|  | static void SendEchoEvent(Isolate* isolate, const char* text); | 
|  | static void SendInspectEvent(Isolate* isolate, const Object& inspectee); | 
|  |  | 
|  | static void SendEmbedderEvent(Isolate* isolate, | 
|  | const char* stream_id, | 
|  | const char* event_kind, | 
|  | const uint8_t* bytes, | 
|  | intptr_t bytes_len); | 
|  |  | 
|  | static void SendLogEvent(Isolate* isolate, | 
|  | int64_t sequence_number, | 
|  | int64_t timestamp, | 
|  | intptr_t level, | 
|  | const String& name, | 
|  | const String& message, | 
|  | const Instance& zone, | 
|  | const Object& error, | 
|  | const Instance& stack_trace); | 
|  |  | 
|  | static void SendExtensionEvent(Isolate* isolate, | 
|  | const String& event_kind, | 
|  | const String& event_data); | 
|  |  | 
|  | // Takes ownership of 'data'. | 
|  | static void SendEventWithData(const char* stream_id, | 
|  | const char* event_type, | 
|  | intptr_t reservation, | 
|  | const char* metadata, | 
|  | intptr_t metadata_size, | 
|  | uint8_t* data, | 
|  | intptr_t data_size); | 
|  |  | 
|  | static void PostError(const String& method_name, | 
|  | const Array& parameter_keys, | 
|  | const Array& parameter_values, | 
|  | const Instance& reply_port, | 
|  | const Instance& id, | 
|  | const Error& error); | 
|  |  | 
|  | // Logs the size of the contents of `js` to FLAG_log_service_response_sizes. | 
|  | static void LogResponseSize(const char* method, JSONStream* js); | 
|  |  | 
|  | // Enable/Disable timeline categories. | 
|  | // Returns True if the categories were successfully enabled, False otherwise. | 
|  | static bool EnableTimelineStreams(char* categories_list); | 
|  |  | 
|  | // Well-known streams. | 
|  | static StreamInfo vm_stream; | 
|  | static StreamInfo isolate_stream; | 
|  | static StreamInfo debug_stream; | 
|  | static StreamInfo gc_stream; | 
|  | static StreamInfo echo_stream; | 
|  | static StreamInfo heapsnapshot_stream; | 
|  | static StreamInfo logging_stream; | 
|  | static StreamInfo extension_stream; | 
|  | static StreamInfo timeline_stream; | 
|  | static StreamInfo profiler_stream; | 
|  |  | 
|  | static bool ListenStream(const char* stream_id, bool include_privates); | 
|  | static void CancelStream(const char* stream_id); | 
|  |  | 
|  | static ObjectPtr RequestAssets(); | 
|  |  | 
|  | static Dart_ServiceStreamListenCallback stream_listen_callback() { | 
|  | return stream_listen_callback_; | 
|  | } | 
|  | static Dart_ServiceStreamCancelCallback stream_cancel_callback() { | 
|  | return stream_cancel_callback_; | 
|  | } | 
|  |  | 
|  | static void PrintJSONForEmbedderInformation(JSONObject *jsobj); | 
|  | static void PrintJSONForVM(JSONStream* js, bool ref); | 
|  |  | 
|  | static void CheckForPause(Isolate* isolate, JSONStream* stream); | 
|  |  | 
|  | static int64_t CurrentRSS(); | 
|  | static int64_t MaxRSS(); | 
|  |  | 
|  | static void SetDartLibraryKernelForSources(const uint8_t* kernel_bytes, | 
|  | intptr_t kernel_length); | 
|  | static bool HasDartLibraryKernelForSources() { | 
|  | return (dart_library_kernel_ != NULL); | 
|  | } | 
|  |  | 
|  | static const uint8_t* dart_library_kernel() { return dart_library_kernel_; } | 
|  |  | 
|  | static intptr_t dart_library_kernel_length() { | 
|  | return dart_library_kernel_len_; | 
|  | } | 
|  |  | 
|  | private: | 
|  | static ErrorPtr InvokeMethod(Isolate* isolate, | 
|  | const Array& message, | 
|  | bool parameters_are_dart_objects = false); | 
|  |  | 
|  | static void EmbedderHandleMessage(EmbedderServiceHandler* handler, | 
|  | JSONStream* js); | 
|  |  | 
|  | static EmbedderServiceHandler* FindIsolateEmbedderHandler(const char* name); | 
|  | static EmbedderServiceHandler* FindRootEmbedderHandler(const char* name); | 
|  | static void ScheduleExtensionHandler(const Instance& handler, | 
|  | const String& method_name, | 
|  | const Array& parameter_keys, | 
|  | const Array& parameter_values, | 
|  | const Instance& reply_port, | 
|  | const Instance& id); | 
|  |  | 
|  | // Takes ownership of 'bytes'. | 
|  | static void SendEvent(const char* stream_id, | 
|  | const char* event_type, | 
|  | uint8_t* bytes, | 
|  | intptr_t bytes_length); | 
|  |  | 
|  | static void PostEvent(Isolate* isolate, | 
|  | const char* stream_id, | 
|  | const char* kind, | 
|  | JSONStream* event, | 
|  | bool enter_safepoint); | 
|  |  | 
|  | static void PostEventImpl(Isolate* isolate, | 
|  | const char* stream_id, | 
|  | const char* kind, | 
|  | JSONStream* event); | 
|  |  | 
|  | static ErrorPtr MaybePause(Isolate* isolate, const Error& error); | 
|  |  | 
|  | static EmbedderServiceHandler* isolate_service_handler_head_; | 
|  | static EmbedderServiceHandler* root_service_handler_head_; | 
|  | static Dart_ServiceStreamListenCallback stream_listen_callback_; | 
|  | static Dart_ServiceStreamCancelCallback stream_cancel_callback_; | 
|  | static Dart_GetVMServiceAssetsArchive get_service_assets_callback_; | 
|  | static Dart_EmbedderInformationCallback embedder_information_callback_; | 
|  |  | 
|  | static void* service_response_size_log_file_; | 
|  |  | 
|  | static const uint8_t* dart_library_kernel_; | 
|  | static intptr_t dart_library_kernel_len_; | 
|  | }; | 
|  |  | 
|  | }  // namespace dart | 
|  |  | 
|  | #endif  // RUNTIME_VM_SERVICE_H_ |