| 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 "platform/globals.h" | 8 #include "platform/globals.h" |
| 9 | 9 |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 823 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 834 // posting the reply (this can be used for asynchronous delegation of | 834 // posting the reply (this can be used for asynchronous delegation of |
| 835 // the response handling). | 835 // the response handling). |
| 836 typedef bool (*RootMessageHandler)(JSONStream* stream); | 836 typedef bool (*RootMessageHandler)(JSONStream* stream); |
| 837 | 837 |
| 838 struct RootMessageHandlerEntry { | 838 struct RootMessageHandlerEntry { |
| 839 const char* command; | 839 const char* command; |
| 840 RootMessageHandler handler; | 840 RootMessageHandler handler; |
| 841 }; | 841 }; |
| 842 | 842 |
| 843 static RootMessageHandler FindRootMessageHandler(const char* command); | 843 static RootMessageHandler FindRootMessageHandler(const char* command); |
| 844 static RootMessageHandler FindRootMessageHandlerNew(const char* command); |
| 844 | 845 |
| 845 | 846 |
| 846 static void PrintArgumentsAndOptions(const JSONObject& obj, JSONStream* js) { | 847 static void PrintArgumentsAndOptions(const JSONObject& obj, JSONStream* js) { |
| 847 JSONObject jsobj(&obj, "request"); | 848 JSONObject jsobj(&obj, "request"); |
| 848 { | 849 { |
| 849 JSONArray jsarr(&jsobj, "arguments"); | 850 JSONArray jsarr(&jsobj, "arguments"); |
| 850 for (intptr_t i = 0; i < js->num_arguments(); i++) { | 851 for (intptr_t i = 0; i < js->num_arguments(); i++) { |
| 851 jsarr.AddValue(js->GetArgument(i)); | 852 jsarr.AddValue(js->GetArgument(i)); |
| 852 } | 853 } |
| 853 } | 854 } |
| (...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1449 return Object::sentinel().raw(); | 1450 return Object::sentinel().raw(); |
| 1450 } | 1451 } |
| 1451 return type.raw(); | 1452 return type.raw(); |
| 1452 } | 1453 } |
| 1453 | 1454 |
| 1454 // Not found. | 1455 // Not found. |
| 1455 return Object::sentinel().raw(); | 1456 return Object::sentinel().raw(); |
| 1456 } | 1457 } |
| 1457 | 1458 |
| 1458 | 1459 |
| 1460 static RawObject* LookupHeapObjectCode(Isolate* isolate, |
| 1461 char** parts, int num_parts) { |
| 1462 if (num_parts != 2) { |
| 1463 return Object::sentinel().raw(); |
| 1464 } |
| 1465 uword pc; |
| 1466 static const char* kCollectedPrefix = "collected-"; |
| 1467 static intptr_t kCollectedPrefixLen = strlen(kCollectedPrefix); |
| 1468 static const char* kNativePrefix = "native-"; |
| 1469 static intptr_t kNativePrefixLen = strlen(kNativePrefix); |
| 1470 static const char* kReusedPrefix = "reused-"; |
| 1471 static intptr_t kReusedPrefixLen = strlen(kReusedPrefix); |
| 1472 const char* id = parts[1]; |
| 1473 if (strncmp(kCollectedPrefix, id, kCollectedPrefixLen) == 0) { |
| 1474 if (!GetUnsignedIntegerId(&id[kCollectedPrefixLen], &pc, 16)) { |
| 1475 return Object::sentinel().raw(); |
| 1476 } |
| 1477 // TODO(turnidge): Return "collected" instead. |
| 1478 return Object::null(); |
| 1479 } |
| 1480 if (strncmp(kNativePrefix, id, kNativePrefixLen) == 0) { |
| 1481 if (!GetUnsignedIntegerId(&id[kNativePrefixLen], &pc, 16)) { |
| 1482 return Object::sentinel().raw(); |
| 1483 } |
| 1484 // TODO(johnmccutchan): Support native Code. |
| 1485 return Object::null(); |
| 1486 } |
| 1487 if (strncmp(kReusedPrefix, id, kReusedPrefixLen) == 0) { |
| 1488 if (!GetUnsignedIntegerId(&id[kReusedPrefixLen], &pc, 16)) { |
| 1489 return Object::sentinel().raw(); |
| 1490 } |
| 1491 // TODO(turnidge): Return "expired" instead. |
| 1492 return Object::null(); |
| 1493 } |
| 1494 int64_t timestamp = 0; |
| 1495 if (!GetCodeId(id, ×tamp, &pc) || (timestamp < 0)) { |
| 1496 return Object::sentinel().raw(); |
| 1497 } |
| 1498 Code& code = Code::Handle(Code::FindCode(pc, timestamp)); |
| 1499 if (!code.IsNull()) { |
| 1500 return code.raw(); |
| 1501 } |
| 1502 |
| 1503 // Not found. |
| 1504 return Object::sentinel().raw(); |
| 1505 } |
| 1506 |
| 1507 |
| 1459 static RawObject* LookupHeapObject(Isolate* isolate, | 1508 static RawObject* LookupHeapObject(Isolate* isolate, |
| 1460 const char* id_original, | 1509 const char* id_original, |
| 1461 ObjectIdRing::LookupResult* result) { | 1510 ObjectIdRing::LookupResult* result) { |
| 1462 char* id = isolate->current_zone()->MakeCopyOfString(id_original); | 1511 char* id = isolate->current_zone()->MakeCopyOfString(id_original); |
| 1463 | 1512 |
| 1464 // Parse the id by splitting at each '/'. | 1513 // Parse the id by splitting at each '/'. |
| 1465 const int MAX_PARTS = 8; | 1514 const int MAX_PARTS = 8; |
| 1466 char* parts[MAX_PARTS]; | 1515 char* parts[MAX_PARTS]; |
| 1467 int num_parts = 0; | 1516 int num_parts = 0; |
| 1468 int i = 0; | 1517 int i = 0; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1497 *result = lookup_result; | 1546 *result = lookup_result; |
| 1498 } | 1547 } |
| 1499 return Object::sentinel().raw(); | 1548 return Object::sentinel().raw(); |
| 1500 } | 1549 } |
| 1501 return obj.raw(); | 1550 return obj.raw(); |
| 1502 | 1551 |
| 1503 } else if (strcmp(parts[0], "libraries") == 0) { | 1552 } else if (strcmp(parts[0], "libraries") == 0) { |
| 1504 return LookupHeapObjectLibraries(isolate, parts, num_parts); | 1553 return LookupHeapObjectLibraries(isolate, parts, num_parts); |
| 1505 } else if (strcmp(parts[0], "classes") == 0) { | 1554 } else if (strcmp(parts[0], "classes") == 0) { |
| 1506 return LookupHeapObjectClasses(isolate, parts, num_parts); | 1555 return LookupHeapObjectClasses(isolate, parts, num_parts); |
| 1556 } else if (strcmp(parts[0], "code") == 0) { |
| 1557 return LookupHeapObjectCode(isolate, parts, num_parts); |
| 1507 } | 1558 } |
| 1508 | 1559 |
| 1509 // Not found. | 1560 // Not found. |
| 1510 return Object::sentinel().raw(); | 1561 return Object::sentinel().raw(); |
| 1511 } | 1562 } |
| 1512 | 1563 |
| 1513 | 1564 |
| 1514 static void PrintSentinel(JSONStream* js, | 1565 static void PrintSentinel(JSONStream* js, |
| 1515 const char* id, | 1566 const char* id, |
| 1516 const char* preview) { | 1567 const char* preview) { |
| (...skipping 1385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2902 } | 2953 } |
| 2903 } | 2954 } |
| 2904 if (FLAG_trace_service) { | 2955 if (FLAG_trace_service) { |
| 2905 OS::Print("vm-service: No isolate message handler for <%s>.\n", command); | 2956 OS::Print("vm-service: No isolate message handler for <%s>.\n", command); |
| 2906 } | 2957 } |
| 2907 return NULL; | 2958 return NULL; |
| 2908 } | 2959 } |
| 2909 | 2960 |
| 2910 | 2961 |
| 2911 static bool HandleIsolateGetObject(Isolate* isolate, JSONStream* js) { | 2962 static bool HandleIsolateGetObject(Isolate* isolate, JSONStream* js) { |
| 2912 const char* id = js->LookupOption("id"); | 2963 const char* id = js->LookupOption("objectId"); |
| 2913 if (id == NULL) { | 2964 if (id == NULL) { |
| 2914 // TODO(turnidge): Print the isolate here instead. | 2965 // TODO(turnidge): Print the isolate here instead. |
| 2915 PrintError(js, "GetObject expects an 'id' parameter\n", | 2966 PrintError(js, "GetObject expects an 'objectId' parameter\n", |
| 2916 js->num_arguments()); | 2967 js->num_arguments()); |
| 2917 return true; | 2968 return true; |
| 2918 } | 2969 } |
| 2919 | 2970 |
| 2920 // Handle heap objects. | 2971 // Handle heap objects. |
| 2921 ObjectIdRing::LookupResult lookup_result; | 2972 ObjectIdRing::LookupResult lookup_result; |
| 2922 const Object& obj = | 2973 const Object& obj = |
| 2923 Object::Handle(LookupHeapObject(isolate, id, &lookup_result)); | 2974 Object::Handle(LookupHeapObject(isolate, id, &lookup_result)); |
| 2924 if (obj.raw() != Object::sentinel().raw()) { | 2975 if (obj.raw() != Object::sentinel().raw()) { |
| 2925 // We found a heap object for this id. Return it. | 2976 // We found a heap object for this id. Return it. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2945 | 2996 |
| 2946 static bool HandleIsolateGetClassList(Isolate* isolate, JSONStream* js) { | 2997 static bool HandleIsolateGetClassList(Isolate* isolate, JSONStream* js) { |
| 2947 ClassTable* table = isolate->class_table(); | 2998 ClassTable* table = isolate->class_table(); |
| 2948 JSONObject jsobj(js); | 2999 JSONObject jsobj(js); |
| 2949 table->PrintToJSONObject(&jsobj); | 3000 table->PrintToJSONObject(&jsobj); |
| 2950 return true; | 3001 return true; |
| 2951 } | 3002 } |
| 2952 | 3003 |
| 2953 | 3004 |
| 2954 static IsolateMessageHandlerEntry isolate_handlers_new[] = { | 3005 static IsolateMessageHandlerEntry isolate_handlers_new[] = { |
| 3006 { "getIsolate", HandleIsolate }, |
| 2955 { "getObject", HandleIsolateGetObject }, | 3007 { "getObject", HandleIsolateGetObject }, |
| 2956 { "getBreakpoints", HandleIsolateGetBreakpoints }, | 3008 { "getBreakpoints", HandleIsolateGetBreakpoints }, |
| 2957 { "pause", HandleIsolatePause }, | 3009 { "pause", HandleIsolatePause }, |
| 2958 { "resume", HandleIsolateResume }, | 3010 { "resume", HandleIsolateResume }, |
| 2959 { "getStack", HandleIsolateGetStack }, | 3011 { "getStack", HandleIsolateGetStack }, |
| 2960 { "getCpuProfile", HandleIsolateGetCpuProfile }, | 3012 { "getCpuProfile", HandleIsolateGetCpuProfile }, |
| 2961 { "getTagProfile", HandleIsolateGetTagProfile }, | 3013 { "getTagProfile", HandleIsolateGetTagProfile }, |
| 2962 { "getAllocationProfile", HandleIsolateGetAllocationProfile }, | 3014 { "getAllocationProfile", HandleIsolateGetAllocationProfile }, |
| 2963 { "getHeapMap", HandleIsolateGetHeapMap }, | 3015 { "getHeapMap", HandleIsolateGetHeapMap }, |
| 2964 { "addBreakpoint", HandleIsolateAddBreakpoint }, | 3016 { "addBreakpoint", HandleIsolateAddBreakpoint }, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2983 return entry.handler; | 3035 return entry.handler; |
| 2984 } | 3036 } |
| 2985 } | 3037 } |
| 2986 if (FLAG_trace_service) { | 3038 if (FLAG_trace_service) { |
| 2987 OS::Print("Service has no isolate message handler for <%s>\n", command); | 3039 OS::Print("Service has no isolate message handler for <%s>\n", command); |
| 2988 } | 3040 } |
| 2989 return NULL; | 3041 return NULL; |
| 2990 } | 3042 } |
| 2991 | 3043 |
| 2992 | 3044 |
| 3045 void Service::HandleRootMessageNew(const Array& msg) { |
| 3046 Isolate* isolate = Isolate::Current(); |
| 3047 ASSERT(!msg.IsNull()); |
| 3048 |
| 3049 { |
| 3050 StackZone zone(isolate); |
| 3051 HANDLESCOPE(isolate); |
| 3052 |
| 3053 const Array& message = Array::Cast(msg); |
| 3054 // Message is a list with five entries. |
| 3055 ASSERT(message.Length() == 5); |
| 3056 |
| 3057 Instance& reply_port = Instance::Handle(isolate); |
| 3058 String& method = String::Handle(isolate); |
| 3059 Array& param_keys = Array::Handle(isolate); |
| 3060 Array& param_values = Array::Handle(isolate); |
| 3061 reply_port ^= msg.At(1); |
| 3062 method ^= msg.At(2); |
| 3063 param_keys ^= msg.At(3); |
| 3064 param_values ^= msg.At(4); |
| 3065 |
| 3066 ASSERT(!method.IsNull()); |
| 3067 ASSERT(!param_keys.IsNull()); |
| 3068 ASSERT(!param_values.IsNull()); |
| 3069 ASSERT(param_keys.Length() == param_values.Length()); |
| 3070 |
| 3071 if (!reply_port.IsSendPort()) { |
| 3072 FATAL("SendPort expected."); |
| 3073 } |
| 3074 |
| 3075 RootMessageHandler handler = |
| 3076 FindRootMessageHandlerNew(method.ToCString()); |
| 3077 { |
| 3078 JSONStream js; |
| 3079 js.SetupNew(zone.GetZone(), SendPort::Cast(reply_port).Id(), |
| 3080 method, param_keys, param_values); |
| 3081 if (handler == NULL) { |
| 3082 // Check for an embedder handler. |
| 3083 EmbedderServiceHandler* e_handler = |
| 3084 FindRootEmbedderHandler(method.ToCString()); |
| 3085 if (e_handler != NULL) { |
| 3086 EmbedderHandleMessage(e_handler, &js); |
| 3087 } else { |
| 3088 PrintError(&js, "Unrecognized path"); |
| 3089 } |
| 3090 js.PostReply(); |
| 3091 } else { |
| 3092 if (handler(&js)) { |
| 3093 // Handler returns true if the reply is ready to be posted. |
| 3094 // TODO(johnmccutchan): Support asynchronous replies. |
| 3095 js.PostReply(); |
| 3096 } |
| 3097 } |
| 3098 } |
| 3099 } |
| 3100 } |
| 3101 |
| 3102 |
| 2993 void Service::HandleRootMessage(const Instance& msg) { | 3103 void Service::HandleRootMessage(const Instance& msg) { |
| 2994 Isolate* isolate = Isolate::Current(); | 3104 Isolate* isolate = Isolate::Current(); |
| 2995 ASSERT(!msg.IsNull()); | 3105 ASSERT(!msg.IsNull()); |
| 2996 ASSERT(msg.IsArray()); | 3106 ASSERT(msg.IsArray()); |
| 2997 | 3107 |
| 2998 { | 3108 { |
| 2999 StackZone zone(isolate); | 3109 StackZone zone(isolate); |
| 3000 HANDLESCOPE(isolate); | 3110 HANDLESCOPE(isolate); |
| 3001 | 3111 |
| 3002 const Array& message = Array::Cast(msg); | 3112 const Array& message = Array::Cast(msg); |
| 3003 // Message is a list with five entries. | 3113 // Message is a list with five entries. |
| 3004 ASSERT(message.Length() == 5); | 3114 ASSERT(message.Length() == 5); |
| 3005 | 3115 |
| 3116 Object& tmp = Object::Handle(isolate); |
| 3117 tmp = message.At(2); |
| 3118 if (tmp.IsString()) { |
| 3119 return Service::HandleRootMessageNew(message); |
| 3120 } |
| 3121 |
| 3006 Instance& reply_port = Instance::Handle(isolate); | 3122 Instance& reply_port = Instance::Handle(isolate); |
| 3007 GrowableObjectArray& path = GrowableObjectArray::Handle(isolate); | 3123 GrowableObjectArray& path = GrowableObjectArray::Handle(isolate); |
| 3008 Array& option_keys = Array::Handle(isolate); | 3124 Array& option_keys = Array::Handle(isolate); |
| 3009 Array& option_values = Array::Handle(isolate); | 3125 Array& option_values = Array::Handle(isolate); |
| 3010 | 3126 |
| 3011 reply_port ^= message.At(1); | 3127 reply_port ^= message.At(1); |
| 3012 path ^= message.At(2); | 3128 path ^= message.At(2); |
| 3013 option_keys ^= message.At(3); | 3129 option_keys ^= message.At(3); |
| 3014 option_values ^= message.At(4); | 3130 option_values ^= message.At(4); |
| 3015 | 3131 |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3172 return entry.handler; | 3288 return entry.handler; |
| 3173 } | 3289 } |
| 3174 } | 3290 } |
| 3175 if (FLAG_trace_service) { | 3291 if (FLAG_trace_service) { |
| 3176 OS::Print("vm-service: No root message handler for <%s>.\n", command); | 3292 OS::Print("vm-service: No root message handler for <%s>.\n", command); |
| 3177 } | 3293 } |
| 3178 return NULL; | 3294 return NULL; |
| 3179 } | 3295 } |
| 3180 | 3296 |
| 3181 | 3297 |
| 3298 static RootMessageHandlerEntry root_handlers_new[] = { |
| 3299 { "getVM", HandleVM }, |
| 3300 }; |
| 3301 |
| 3302 |
| 3303 static RootMessageHandler FindRootMessageHandlerNew(const char* command) { |
| 3304 intptr_t num_message_handlers = sizeof(root_handlers_new) / |
| 3305 sizeof(root_handlers_new[0]); |
| 3306 for (intptr_t i = 0; i < num_message_handlers; i++) { |
| 3307 const RootMessageHandlerEntry& entry = root_handlers_new[i]; |
| 3308 if (strcmp(command, entry.command) == 0) { |
| 3309 return entry.handler; |
| 3310 } |
| 3311 } |
| 3312 if (FLAG_trace_service) { |
| 3313 OS::Print("vm-service: No root message handler for <%s>.\n", command); |
| 3314 } |
| 3315 return NULL; |
| 3316 } |
| 3317 |
| 3318 |
| 3182 void Service::SendEvent(intptr_t eventId, const Object& eventMessage) { | 3319 void Service::SendEvent(intptr_t eventId, const Object& eventMessage) { |
| 3183 if (!IsRunning()) { | 3320 if (!IsRunning()) { |
| 3184 return; | 3321 return; |
| 3185 } | 3322 } |
| 3186 Isolate* isolate = Isolate::Current(); | 3323 Isolate* isolate = Isolate::Current(); |
| 3187 ASSERT(isolate != NULL); | 3324 ASSERT(isolate != NULL); |
| 3188 HANDLESCOPE(isolate); | 3325 HANDLESCOPE(isolate); |
| 3189 | 3326 |
| 3190 // Construct a list of the form [eventId, eventMessage]. | 3327 // Construct a list of the form [eventId, eventMessage]. |
| 3191 const Array& list = Array::Handle(Array::New(2)); | 3328 const Array& list = Array::Handle(Array::New(2)); |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3343 while (current != NULL) { | 3480 while (current != NULL) { |
| 3344 if (strcmp(name, current->name()) == 0) { | 3481 if (strcmp(name, current->name()) == 0) { |
| 3345 return current; | 3482 return current; |
| 3346 } | 3483 } |
| 3347 current = current->next(); | 3484 current = current->next(); |
| 3348 } | 3485 } |
| 3349 return NULL; | 3486 return NULL; |
| 3350 } | 3487 } |
| 3351 | 3488 |
| 3352 } // namespace dart | 3489 } // namespace dart |
| OLD | NEW |