| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/service.h" | 5 #include "vm/service.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 #include "include/dart_native_api.h" | 8 #include "include/dart_native_api.h" |
| 9 #include "platform/globals.h" | 9 #include "platform/globals.h" |
| 10 | 10 |
| (...skipping 948 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 959 InvokeMethod(isolate, msg_instance, true); | 959 InvokeMethod(isolate, msg_instance, true); |
| 960 } | 960 } |
| 961 | 961 |
| 962 | 962 |
| 963 void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) { | 963 void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) { |
| 964 ASSERT(isolate != NULL); | 964 ASSERT(isolate != NULL); |
| 965 InvokeMethod(isolate, msg); | 965 InvokeMethod(isolate, msg); |
| 966 } | 966 } |
| 967 | 967 |
| 968 | 968 |
| 969 static void Finalizer(void* isolate_callback_data, |
| 970 Dart_WeakPersistentHandle handle, |
| 971 void* buffer) { |
| 972 free(buffer); |
| 973 } |
| 974 |
| 975 |
| 969 void Service::SendEvent(const char* stream_id, | 976 void Service::SendEvent(const char* stream_id, |
| 970 const char* event_type, | 977 const char* event_type, |
| 971 const Object& event_message) { | 978 uint8_t* bytes, |
| 979 intptr_t bytes_length) { |
| 972 Thread* thread = Thread::Current(); | 980 Thread* thread = Thread::Current(); |
| 973 Isolate* isolate = thread->isolate(); | 981 Isolate* isolate = thread->isolate(); |
| 974 ASSERT(isolate != NULL); | 982 ASSERT(isolate != NULL); |
| 975 ASSERT(!ServiceIsolate::IsServiceIsolateDescendant(isolate)); | 983 ASSERT(!ServiceIsolate::IsServiceIsolateDescendant(isolate)); |
| 976 if (!ServiceIsolate::IsRunning()) { | |
| 977 return; | |
| 978 } | |
| 979 HANDLESCOPE(thread); | |
| 980 | 984 |
| 981 const Array& list = Array::Handle(Array::New(2)); | |
| 982 ASSERT(!list.IsNull()); | |
| 983 const String& stream_id_str = String::Handle(String::New(stream_id)); | |
| 984 list.SetAt(0, stream_id_str); | |
| 985 list.SetAt(1, event_message); | |
| 986 | |
| 987 // Push the event to port_. | |
| 988 uint8_t* data = NULL; | |
| 989 MessageWriter writer(&data, &allocator, false); | |
| 990 writer.WriteMessage(list); | |
| 991 intptr_t len = writer.BytesWritten(); | |
| 992 if (FLAG_trace_service) { | 985 if (FLAG_trace_service) { |
| 993 OS::Print("vm-service: Pushing ServiceEvent(isolate='%s', kind='%s'," | 986 OS::Print("vm-service: Pushing ServiceEvent(isolate='%s', kind='%s'," |
| 994 " len=%" Pd ") to stream %s\n", | 987 " len=%" Pd ") to stream %s\n", |
| 995 isolate->name(), event_type, len, stream_id); | 988 isolate->name(), event_type, bytes_length, stream_id); |
| 996 } | 989 } |
| 997 // TODO(turnidge): For now we ignore failure to send an event. Revisit? | 990 |
| 998 PortMap::PostMessage( | 991 bool result; |
| 999 new Message(ServiceIsolate::Port(), data, len, Message::kNormalPriority)); | 992 { |
| 993 TransitionVMToNative transition(thread); |
| 994 Dart_CObject cbytes; |
| 995 cbytes.type = Dart_CObject_kExternalTypedData; |
| 996 cbytes.value.as_external_typed_data.type = Dart_TypedData_kUint8; |
| 997 cbytes.value.as_external_typed_data.length = bytes_length; |
| 998 cbytes.value.as_external_typed_data.data = bytes; |
| 999 cbytes.value.as_external_typed_data.peer = bytes; |
| 1000 cbytes.value.as_external_typed_data.callback = Finalizer; |
| 1001 |
| 1002 Dart_CObject cstream_id; |
| 1003 cstream_id.type = Dart_CObject_kString; |
| 1004 cstream_id.value.as_string = const_cast<char*>(stream_id); |
| 1005 |
| 1006 Dart_CObject* elements[2]; |
| 1007 elements[0] = &cstream_id; |
| 1008 elements[1] = &cbytes; |
| 1009 Dart_CObject message; |
| 1010 message.type = Dart_CObject_kArray; |
| 1011 message.value.as_array.length = 2; |
| 1012 message.value.as_array.values = elements; |
| 1013 result = Dart_PostCObject(ServiceIsolate::Port(), &message); |
| 1014 } |
| 1015 |
| 1016 if (!result) { |
| 1017 free(bytes); |
| 1018 } |
| 1000 } | 1019 } |
| 1001 | 1020 |
| 1002 | 1021 |
| 1003 // TODO(turnidge): Rewrite this method to use Post_CObject instead. | |
| 1004 void Service::SendEventWithData(const char* stream_id, | 1022 void Service::SendEventWithData(const char* stream_id, |
| 1005 const char* event_type, | 1023 const char* event_type, |
| 1006 const String& meta, | 1024 const char* metadata, |
| 1025 intptr_t metadata_size, |
| 1007 const uint8_t* data, | 1026 const uint8_t* data, |
| 1008 intptr_t size) { | 1027 intptr_t data_size) { |
| 1009 // Bitstream: [meta data size (big-endian 64 bit)] [meta data (UTF-8)] [data] | 1028 // Bitstream: [metadata size (big-endian 64 bit)] [metadata (UTF-8)] [data] |
| 1010 const intptr_t meta_bytes = Utf8::Length(meta); | 1029 const intptr_t total_bytes = sizeof(uint64_t) + metadata_size + data_size; |
| 1011 const intptr_t total_bytes = sizeof(uint64_t) + meta_bytes + size; | 1030 |
| 1012 const TypedData& message = TypedData::Handle( | 1031 uint8_t* message = static_cast<uint8_t*>(malloc(total_bytes)); |
| 1013 TypedData::New(kTypedDataUint8ArrayCid, total_bytes)); | |
| 1014 intptr_t offset = 0; | 1032 intptr_t offset = 0; |
| 1015 // TODO(koda): Rename these methods SetHostUint64, etc. | 1033 |
| 1016 message.SetUint64(0, Utils::HostToBigEndian64(meta_bytes)); | 1034 // Metadata size. |
| 1035 reinterpret_cast<uint64_t*>(message)[0] = |
| 1036 Utils::HostToBigEndian64(metadata_size); |
| 1017 offset += sizeof(uint64_t); | 1037 offset += sizeof(uint64_t); |
| 1018 { | 1038 |
| 1019 NoSafepointScope no_safepoint; | 1039 // Metadata. |
| 1020 meta.ToUTF8(static_cast<uint8_t*>(message.DataAddr(offset)), meta_bytes); | 1040 memmove(&message[offset], metadata, metadata_size); |
| 1021 offset += meta_bytes; | 1041 offset += metadata_size; |
| 1022 } | 1042 |
| 1023 // TODO(koda): It would be nice to avoid this copy (requires changes to | 1043 // Data. |
| 1024 // MessageWriter code). | 1044 memmove(&message[offset], data, data_size); |
| 1025 { | 1045 offset += data_size; |
| 1026 NoSafepointScope no_safepoint; | 1046 |
| 1027 memmove(message.DataAddr(offset), data, size); | |
| 1028 offset += size; | |
| 1029 } | |
| 1030 ASSERT(offset == total_bytes); | 1047 ASSERT(offset == total_bytes); |
| 1031 SendEvent(stream_id, event_type, message); | 1048 SendEvent(stream_id, event_type, message, total_bytes); |
| 1032 } | 1049 } |
| 1033 | 1050 |
| 1034 | 1051 |
| 1035 static void ReportPauseOnConsole(ServiceEvent* event) { | 1052 static void ReportPauseOnConsole(ServiceEvent* event) { |
| 1036 const char* name = event->isolate()->debugger_name(); | 1053 const char* name = event->isolate()->debugger_name(); |
| 1037 switch (event->kind()) { | 1054 switch (event->kind()) { |
| 1038 case ServiceEvent::kPauseStart: | 1055 case ServiceEvent::kPauseStart: |
| 1039 OS::PrintErr( | 1056 OS::PrintErr( |
| 1040 "vm-service: isolate '%s' has no debugger attached and is paused at " | 1057 "vm-service: isolate '%s' has no debugger attached and is paused at " |
| 1041 "start.", name); | 1058 "start.", name); |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1402 event.AddProperty("type", "Event"); | 1419 event.AddProperty("type", "Event"); |
| 1403 event.AddProperty("kind", "_Echo"); | 1420 event.AddProperty("kind", "_Echo"); |
| 1404 event.AddProperty("isolate", isolate); | 1421 event.AddProperty("isolate", isolate); |
| 1405 if (text != NULL) { | 1422 if (text != NULL) { |
| 1406 event.AddProperty("text", text); | 1423 event.AddProperty("text", text); |
| 1407 } | 1424 } |
| 1408 event.AddPropertyTimeMillis("timestamp", OS::GetCurrentTimeMillis()); | 1425 event.AddPropertyTimeMillis("timestamp", OS::GetCurrentTimeMillis()); |
| 1409 } | 1426 } |
| 1410 } | 1427 } |
| 1411 } | 1428 } |
| 1412 const String& message = String::Handle(String::New(js.ToCString())); | |
| 1413 uint8_t data[] = {0, 128, 255}; | 1429 uint8_t data[] = {0, 128, 255}; |
| 1414 SendEventWithData(echo_stream.id(), "_Echo", message, data, sizeof(data)); | 1430 SendEventWithData(echo_stream.id(), "_Echo", |
| 1431 js.buffer()->buf(), js.buffer()->length(), |
| 1432 data, sizeof(data)); |
| 1415 } | 1433 } |
| 1416 | 1434 |
| 1417 | 1435 |
| 1418 static bool TriggerEchoEvent(Thread* thread, JSONStream* js) { | 1436 static bool TriggerEchoEvent(Thread* thread, JSONStream* js) { |
| 1419 if (Service::echo_stream.enabled()) { | 1437 if (Service::echo_stream.enabled()) { |
| 1420 Service::SendEchoEvent(thread->isolate(), js->LookupParam("text")); | 1438 Service::SendEchoEvent(thread->isolate(), js->LookupParam("text")); |
| 1421 } | 1439 } |
| 1422 JSONObject jsobj(js); | 1440 JSONObject jsobj(js); |
| 1423 return HandleCommonEcho(&jsobj, js); | 1441 return HandleCommonEcho(&jsobj, js); |
| 1424 } | 1442 } |
| (...skipping 1909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3334 event.AddProperty("isolate", thread->isolate()); | 3352 event.AddProperty("isolate", thread->isolate()); |
| 3335 event.AddPropertyTimeMillis("timestamp", OS::GetCurrentTimeMillis()); | 3353 event.AddPropertyTimeMillis("timestamp", OS::GetCurrentTimeMillis()); |
| 3336 | 3354 |
| 3337 event.AddProperty("chunkIndex", i); | 3355 event.AddProperty("chunkIndex", i); |
| 3338 event.AddProperty("chunkCount", num_chunks); | 3356 event.AddProperty("chunkCount", num_chunks); |
| 3339 event.AddProperty("nodeCount", node_count); | 3357 event.AddProperty("nodeCount", node_count); |
| 3340 } | 3358 } |
| 3341 } | 3359 } |
| 3342 } | 3360 } |
| 3343 | 3361 |
| 3344 const String& message = String::Handle(String::New(js.ToCString())); | |
| 3345 | |
| 3346 uint8_t* chunk_start = buffer + (i * kChunkSize); | 3362 uint8_t* chunk_start = buffer + (i * kChunkSize); |
| 3347 intptr_t chunk_size = (i + 1 == num_chunks) | 3363 intptr_t chunk_size = (i + 1 == num_chunks) |
| 3348 ? stream.bytes_written() - (i * kChunkSize) | 3364 ? stream.bytes_written() - (i * kChunkSize) |
| 3349 : kChunkSize; | 3365 : kChunkSize; |
| 3350 | 3366 |
| 3351 SendEventWithData(graph_stream.id(), "_Graph", message, | 3367 SendEventWithData(graph_stream.id(), "_Graph", |
| 3368 js.buffer()->buf(), js.buffer()->length(), |
| 3352 chunk_start, chunk_size); | 3369 chunk_start, chunk_size); |
| 3353 } | 3370 } |
| 3354 } | 3371 } |
| 3355 | 3372 |
| 3356 | 3373 |
| 3357 void Service::SendInspectEvent(Isolate* isolate, const Object& inspectee) { | 3374 void Service::SendInspectEvent(Isolate* isolate, const Object& inspectee) { |
| 3358 if (!Service::debug_stream.enabled()) { | 3375 if (!Service::debug_stream.enabled()) { |
| 3359 return; | 3376 return; |
| 3360 } | 3377 } |
| 3361 ServiceEvent event(isolate, ServiceEvent::kInspect); | 3378 ServiceEvent event(isolate, ServiceEvent::kInspect); |
| (...skipping 785 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4147 if (strcmp(method_name, method.name) == 0) { | 4164 if (strcmp(method_name, method.name) == 0) { |
| 4148 return &method; | 4165 return &method; |
| 4149 } | 4166 } |
| 4150 } | 4167 } |
| 4151 return NULL; | 4168 return NULL; |
| 4152 } | 4169 } |
| 4153 | 4170 |
| 4154 #endif // !PRODUCT | 4171 #endif // !PRODUCT |
| 4155 | 4172 |
| 4156 } // namespace dart | 4173 } // namespace dart |
| OLD | NEW |