| 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/debugger.h" |
| 6 #include "vm/heap_histogram.h" |
| 5 #include "vm/isolate.h" | 7 #include "vm/isolate.h" |
| 6 #include "vm/message.h" | 8 #include "vm/message.h" |
| 7 #include "vm/object.h" | 9 #include "vm/object.h" |
| 8 #include "vm/port.h" | 10 #include "vm/port.h" |
| 9 #include "vm/service.h" | 11 #include "vm/service.h" |
| 10 | 12 |
| 11 namespace dart { | 13 namespace dart { |
| 12 | 14 |
| 15 typedef RawString* (*ServiceMessageHandler)(Isolate* isolate); |
| 16 |
| 17 struct ServiceMessageHandlerEntry { |
| 18 const char* command; |
| 19 ServiceMessageHandler handler; |
| 20 }; |
| 21 |
| 22 static ServiceMessageHandler FindServiceMessageHandler(const char* command); |
| 23 |
| 24 |
| 13 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { | 25 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { |
| 14 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); | 26 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); |
| 15 return reinterpret_cast<uint8_t*>(new_ptr); | 27 return reinterpret_cast<uint8_t*>(new_ptr); |
| 16 } | 28 } |
| 17 | 29 |
| 18 | 30 |
| 19 static void PostReply(const String& reply, Dart_Port reply_port) { | 31 static void PostReply(const String& reply, Dart_Port reply_port) { |
| 20 uint8_t* data = NULL; | 32 uint8_t* data = NULL; |
| 21 MessageWriter writer(&data, &allocator); | 33 MessageWriter writer(&data, &allocator); |
| 22 writer.WriteMessage(reply); | 34 writer.WriteMessage(reply); |
| 23 PortMap::PostMessage(new Message(reply_port, Message::kIllegalPort, data, | 35 PortMap::PostMessage(new Message(reply_port, Message::kIllegalPort, data, |
| 24 writer.BytesWritten(), | 36 writer.BytesWritten(), |
| 25 Message::kNormalPriority)); | 37 Message::kNormalPriority)); |
| 26 } | 38 } |
| 27 | 39 |
| 28 | 40 |
| 29 static RawString* HandleIdMessage(Isolate* isolate, Dart_Port reply_port) { | 41 void Service::HandleServiceMessage(Isolate* isolate, Dart_Port reply_port, |
| 42 const Instance& msg) { |
| 43 ASSERT(isolate != NULL); |
| 44 ASSERT(reply_port != ILLEGAL_PORT); |
| 45 ASSERT(!msg.IsNull()); |
| 46 ASSERT(msg.IsGrowableObjectArray()); |
| 47 |
| 48 { |
| 49 StackZone zone(isolate); |
| 50 HANDLESCOPE(isolate); |
| 51 const GrowableObjectArray& message = GrowableObjectArray::Cast(msg); |
| 52 // Message is a list with three entries. |
| 53 ASSERT(message.Length() == 3); |
| 54 |
| 55 GrowableObjectArray& path = GrowableObjectArray::Handle(); |
| 56 GrowableObjectArray& option_keys = GrowableObjectArray::Handle(); |
| 57 GrowableObjectArray& option_values = GrowableObjectArray::Handle(); |
| 58 path ^= message.At(0); |
| 59 option_keys ^= message.At(1); |
| 60 option_values ^= message.At(2); |
| 61 |
| 62 ASSERT(!path.IsNull()); |
| 63 ASSERT(!option_keys.IsNull()); |
| 64 ASSERT(!option_values.IsNull()); |
| 65 // Path always has at least one entry in it. |
| 66 ASSERT(path.Length() > 0); |
| 67 // Same number of option keys as values. |
| 68 ASSERT(option_keys.Length() == option_values.Length()); |
| 69 |
| 70 String& pathSegment = String::Handle(); |
| 71 pathSegment ^= path.At(0); |
| 72 ASSERT(!pathSegment.IsNull()); |
| 73 |
| 74 ServiceMessageHandler handler = |
| 75 FindServiceMessageHandler(pathSegment.ToCString()); |
| 76 String& reply = String::Handle(); |
| 77 reply ^= handler(isolate); |
| 78 ASSERT(!reply.IsNull()); |
| 79 PostReply(reply, reply_port); |
| 80 } |
| 81 } |
| 82 |
| 83 |
| 84 static RawString* HandleName(Isolate* isolate) { |
| 30 TextBuffer buffer(256); | 85 TextBuffer buffer(256); |
| 31 buffer.Printf("{ \"id\": \"%s\" }", isolate->name()); | 86 JSONStream js(&buffer); |
| 87 js.OpenObject(); |
| 88 js.PrintProperty("type", "IsolateName"); |
| 89 js.PrintProperty("id", static_cast<intptr_t>(isolate->main_port())); |
| 90 js.PrintProperty("name", isolate->name()); |
| 91 js.CloseObject(); |
| 32 return String::New(buffer.buf()); | 92 return String::New(buffer.buf()); |
| 33 } | 93 } |
| 34 | 94 |
| 35 | 95 |
| 36 void Service::HandleServiceMessage(Isolate* isolate, Dart_Port reply_port, | 96 RawString* HandleStackTrace(Isolate* isolate) { |
| 37 const Instance& message) { | 97 TextBuffer buffer(256); |
| 38 ASSERT(isolate != NULL); | 98 JSONStream js(&buffer); |
| 39 ASSERT(reply_port != ILLEGAL_PORT); | 99 DebuggerStackTrace* stack = isolate->debugger()->StackTrace(); |
| 40 ASSERT(!message.IsNull()); | 100 js.OpenObject(); |
| 41 ASSERT(message.IsString()); | 101 js.PrintProperty("type", "StackTrace"); |
| 102 js.OpenArray("members"); |
| 103 intptr_t n_frames = stack->Length(); |
| 104 String& url = String::Handle(); |
| 105 String& function = String::Handle(); |
| 106 for (int i = 0; i < n_frames; i++) { |
| 107 ActivationFrame* frame = stack->ActivationFrameAt(i); |
| 108 url ^= frame->SourceUrl(); |
| 109 function ^= frame->function().UserVisibleName(); |
| 110 js.OpenObject(); |
| 111 js.PrintProperty("name", function.ToCString()); |
| 112 js.PrintProperty("url", url.ToCString()); |
| 113 js.PrintProperty("line", frame->LineNumber()); |
| 114 js.PrintProperty("function", frame->function()); |
| 115 js.PrintProperty("code", frame->code()); |
| 116 js.CloseObject(); |
| 117 } |
| 118 js.CloseArray(); |
| 119 js.CloseObject(); |
| 120 return String::New(buffer.buf()); |
| 121 } |
| 42 | 122 |
| 43 String& reply = String::Handle(); | |
| 44 | 123 |
| 45 // For now, assume service message is always an id check. | 124 RawString* HandleObjectHistogram(Isolate* isolate) { |
| 46 reply = HandleIdMessage(isolate, reply_port); | 125 TextBuffer buffer(256); |
| 126 JSONStream js(&buffer); |
| 127 ObjectHistogram* histogram = Isolate::Current()->object_histogram(); |
| 128 if (histogram == NULL) { |
| 129 js.OpenObject(); |
| 130 js.PrintProperty("type", "ObjectHistogram"); |
| 131 js.PrintProperty("error", "Run with --print_object_histogram"); |
| 132 js.CloseObject(); |
| 133 return String::New(buffer.buf()); |
| 134 } |
| 135 histogram->PrintToJSONStream(&js); |
| 136 return String::New(buffer.buf()); |
| 137 } |
| 47 | 138 |
| 48 ASSERT(!reply.IsNull()); | |
| 49 | 139 |
| 50 PostReply(reply, reply_port); | 140 static ServiceMessageHandlerEntry __message_handlers[] = { |
| 141 { "name", HandleName }, |
| 142 { "stacktrace", HandleStackTrace }, |
| 143 { "objecthistogram", HandleObjectHistogram}, |
| 144 }; |
| 145 |
| 146 |
| 147 static RawString* HandleFallthrough(Isolate* isolate) { |
| 148 TextBuffer buffer(256); |
| 149 JSONStream js(&buffer); |
| 150 js.OpenObject(); |
| 151 js.PrintProperty("type", "error"); |
| 152 js.PrintProperty("text", "request not supported."); |
| 153 js.CloseObject(); |
| 154 return String::New(buffer.buf()); |
| 155 } |
| 156 |
| 157 |
| 158 static ServiceMessageHandler FindServiceMessageHandler(const char* command) { |
| 159 intptr_t num_message_handlers = sizeof(__message_handlers) / |
| 160 sizeof(__message_handlers[0]); |
| 161 for (intptr_t i = 0; i < num_message_handlers; i++) { |
| 162 const ServiceMessageHandlerEntry& entry = __message_handlers[i]; |
| 163 if (!strcmp(command, entry.command)) { |
| 164 return entry.handler; |
| 165 } |
| 166 } |
| 167 return HandleFallthrough; |
| 51 } | 168 } |
| 52 | 169 |
| 53 } // namespace dart | 170 } // namespace dart |
| OLD | NEW |