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 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 // Skip the dash. | 252 // Skip the dash. |
253 s++; | 253 s++; |
254 // Extract the PC. | 254 // Extract the PC. |
255 if (!GetUnsignedIntegerId(s, address, 16)) { | 255 if (!GetUnsignedIntegerId(s, address, 16)) { |
256 return false; | 256 return false; |
257 } | 257 } |
258 return true; | 258 return true; |
259 } | 259 } |
260 | 260 |
261 | 261 |
| 262 // Verifies that |s| begins with |prefix| and then calls |GetIntegerId| on |
| 263 // the remainder of |s|. |
| 264 static bool GetPrefixedIntegerId(const char* s, |
| 265 const char* prefix, |
| 266 intptr_t* service_id) { |
| 267 if (s == NULL) { |
| 268 return false; |
| 269 } |
| 270 ASSERT(prefix != NULL); |
| 271 const intptr_t kInputLen = strlen(s); |
| 272 const intptr_t kPrefixLen = strlen(prefix); |
| 273 ASSERT(kPrefixLen > 0); |
| 274 if (kInputLen <= kPrefixLen) { |
| 275 return false; |
| 276 } |
| 277 if (strncmp(s, prefix, kPrefixLen) != 0) { |
| 278 return false; |
| 279 } |
| 280 // Prefix satisfied. Move forward. |
| 281 s += kPrefixLen; |
| 282 // Attempt to read integer id. |
| 283 return GetIntegerId(s, service_id); |
| 284 } |
| 285 |
| 286 |
| 287 static bool IsValidClassId(Isolate* isolate, intptr_t cid) { |
| 288 ASSERT(isolate != NULL); |
| 289 ClassTable* class_table = isolate->class_table(); |
| 290 ASSERT(class_table != NULL); |
| 291 return class_table->IsValidIndex(cid) && class_table->HasValidClassAt(cid); |
| 292 } |
| 293 |
| 294 |
| 295 static RawClass* GetClassForId(Isolate* isolate, intptr_t cid) { |
| 296 ASSERT(isolate == Isolate::Current()); |
| 297 ASSERT(isolate != NULL); |
| 298 ClassTable* class_table = isolate->class_table(); |
| 299 ASSERT(class_table != NULL); |
| 300 return class_table->At(cid); |
| 301 } |
| 302 |
| 303 |
262 // TODO(johnmccutchan): Split into separate file and write unit tests. | 304 // TODO(johnmccutchan): Split into separate file and write unit tests. |
263 class MethodParameter { | 305 class MethodParameter { |
264 public: | 306 public: |
265 MethodParameter(const char* name, bool required) | 307 MethodParameter(const char* name, bool required) |
266 : name_(name), required_(required) { | 308 : name_(name), required_(required) { |
267 } | 309 } |
268 | 310 |
269 virtual ~MethodParameter() { } | 311 virtual ~MethodParameter() { } |
270 | 312 |
271 virtual bool Validate(const char* value) const { | 313 virtual bool Validate(const char* value) const { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 } | 377 } |
336 for (const char* cp = value; *cp != '\0'; cp++) { | 378 for (const char* cp = value; *cp != '\0'; cp++) { |
337 if (*cp < '0' || *cp > '9') { | 379 if (*cp < '0' || *cp > '9') { |
338 return false; | 380 return false; |
339 } | 381 } |
340 } | 382 } |
341 return true; | 383 return true; |
342 } | 384 } |
343 | 385 |
344 static intptr_t Parse(const char* value) { | 386 static intptr_t Parse(const char* value) { |
| 387 if (value == NULL) { |
| 388 return -1; |
| 389 } |
345 char* end_ptr = NULL; | 390 char* end_ptr = NULL; |
346 uintptr_t result = strtoul(value, &end_ptr, 10); | 391 uintptr_t result = strtoul(value, &end_ptr, 10); |
347 ASSERT(*end_ptr == '\0'); // Parsed full string | 392 ASSERT(*end_ptr == '\0'); // Parsed full string |
348 return result; | 393 return result; |
349 } | 394 } |
350 }; | 395 }; |
351 | 396 |
352 | 397 |
353 class IdParameter : public MethodParameter { | 398 class IdParameter : public MethodParameter { |
354 public: | 399 public: |
(...skipping 1874 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2229 }; | 2274 }; |
2230 | 2275 |
2231 | 2276 |
2232 static const MethodParameter* get_cpu_profile_params[] = { | 2277 static const MethodParameter* get_cpu_profile_params[] = { |
2233 ISOLATE_PARAMETER, | 2278 ISOLATE_PARAMETER, |
2234 new EnumParameter("tags", true, tags_enum_names), | 2279 new EnumParameter("tags", true, tags_enum_names), |
2235 NULL, | 2280 NULL, |
2236 }; | 2281 }; |
2237 | 2282 |
2238 | 2283 |
| 2284 // TODO(johnmccutchan): Rename this to GetCpuSamples. |
2239 static bool GetCpuProfile(Isolate* isolate, JSONStream* js) { | 2285 static bool GetCpuProfile(Isolate* isolate, JSONStream* js) { |
2240 Profile::TagOrder tag_order = | 2286 Profile::TagOrder tag_order = |
2241 EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values); | 2287 EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values); |
2242 ProfilerService::PrintJSON(js, tag_order); | 2288 ProfilerService::PrintJSON(js, tag_order); |
2243 return true; | 2289 return true; |
2244 } | 2290 } |
2245 | 2291 |
2246 | 2292 |
| 2293 static const MethodParameter* get_allocation_samples_params[] = { |
| 2294 ISOLATE_PARAMETER, |
| 2295 new EnumParameter("tags", true, tags_enum_names), |
| 2296 new IdParameter("classId", false), |
| 2297 NULL, |
| 2298 }; |
| 2299 |
| 2300 |
| 2301 static bool GetAllocationSamples(Isolate* isolate, JSONStream* js) { |
| 2302 Profile::TagOrder tag_order = |
| 2303 EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values); |
| 2304 const char* class_id = js->LookupParam("classId"); |
| 2305 intptr_t cid = -1; |
| 2306 GetPrefixedIntegerId(class_id, "classes/", &cid); |
| 2307 if (IsValidClassId(isolate, cid)) { |
| 2308 const Class& cls = Class::Handle(GetClassForId(isolate, cid)); |
| 2309 ProfilerService::PrintAllocationJSON(js, tag_order, cls); |
| 2310 } else { |
| 2311 PrintInvalidParamError(js, "classId"); |
| 2312 } |
| 2313 return true; |
| 2314 } |
| 2315 |
| 2316 |
2247 static const MethodParameter* clear_cpu_profile_params[] = { | 2317 static const MethodParameter* clear_cpu_profile_params[] = { |
2248 ISOLATE_PARAMETER, | 2318 ISOLATE_PARAMETER, |
2249 NULL, | 2319 NULL, |
2250 }; | 2320 }; |
2251 | 2321 |
2252 | 2322 |
2253 static bool ClearCpuProfile(Isolate* isolate, JSONStream* js) { | 2323 static bool ClearCpuProfile(Isolate* isolate, JSONStream* js) { |
2254 ProfilerService::ClearSamples(); | 2324 ProfilerService::ClearSamples(); |
2255 PrintSuccess(js); | 2325 PrintSuccess(js); |
2256 return true; | 2326 return true; |
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2744 isolate->set_debugger_name(js->LookupParam("name")); | 2814 isolate->set_debugger_name(js->LookupParam("name")); |
2745 if (Service::NeedsIsolateEvents()) { | 2815 if (Service::NeedsIsolateEvents()) { |
2746 ServiceEvent event(isolate, ServiceEvent::kIsolateUpdate); | 2816 ServiceEvent event(isolate, ServiceEvent::kIsolateUpdate); |
2747 Service::HandleEvent(&event); | 2817 Service::HandleEvent(&event); |
2748 } | 2818 } |
2749 PrintSuccess(js); | 2819 PrintSuccess(js); |
2750 return true; | 2820 return true; |
2751 } | 2821 } |
2752 | 2822 |
2753 | 2823 |
| 2824 static const MethodParameter* set_trace_class_allocation_params[] = { |
| 2825 ISOLATE_PARAMETER, |
| 2826 new IdParameter("classId", true), |
| 2827 new BoolParameter("enable", true), |
| 2828 NULL, |
| 2829 }; |
| 2830 |
| 2831 |
| 2832 static bool SetTraceClassAllocation(Isolate* isolate, JSONStream* js) { |
| 2833 const char* class_id = js->LookupParam("classId"); |
| 2834 const bool enable = BoolParameter::Parse(js->LookupParam("enable")); |
| 2835 intptr_t cid = -1; |
| 2836 GetPrefixedIntegerId(class_id, "classes/", &cid); |
| 2837 if (!IsValidClassId(isolate, cid)) { |
| 2838 PrintInvalidParamError(js, "classId"); |
| 2839 return true; |
| 2840 } |
| 2841 const Class& cls = Class::Handle(GetClassForId(isolate, cid)); |
| 2842 ASSERT(!cls.IsNull()); |
| 2843 cls.SetTraceAllocation(enable); |
| 2844 PrintSuccess(js); |
| 2845 return true; |
| 2846 } |
| 2847 |
| 2848 |
2754 static ServiceMethodDescriptor service_methods_[] = { | 2849 static ServiceMethodDescriptor service_methods_[] = { |
2755 { "_dumpIdZone", DumpIdZone, NULL }, | 2850 { "_dumpIdZone", DumpIdZone, NULL }, |
2756 { "_echo", Echo, | 2851 { "_echo", Echo, |
2757 NULL }, | 2852 NULL }, |
2758 { "_respondWithMalformedJson", RespondWithMalformedJson, | 2853 { "_respondWithMalformedJson", RespondWithMalformedJson, |
2759 NULL }, | 2854 NULL }, |
2760 { "_respondWithMalformedObject", RespondWithMalformedObject, | 2855 { "_respondWithMalformedObject", RespondWithMalformedObject, |
2761 NULL }, | 2856 NULL }, |
2762 { "_triggerEchoEvent", TriggerEchoEvent, | 2857 { "_triggerEchoEvent", TriggerEchoEvent, |
2763 NULL }, | 2858 NULL }, |
2764 { "addBreakpoint", AddBreakpoint, | 2859 { "addBreakpoint", AddBreakpoint, |
2765 add_breakpoint_params }, | 2860 add_breakpoint_params }, |
2766 { "addBreakpointAtEntry", AddBreakpointAtEntry, | 2861 { "addBreakpointAtEntry", AddBreakpointAtEntry, |
2767 add_breakpoint_at_entry_params }, | 2862 add_breakpoint_at_entry_params }, |
2768 { "_addBreakpointAtActivation", AddBreakpointAtActivation, | 2863 { "_addBreakpointAtActivation", AddBreakpointAtActivation, |
2769 add_breakpoint_at_activation_params }, | 2864 add_breakpoint_at_activation_params }, |
2770 { "_clearCpuProfile", ClearCpuProfile, | 2865 { "_clearCpuProfile", ClearCpuProfile, |
2771 clear_cpu_profile_params }, | 2866 clear_cpu_profile_params }, |
2772 { "evaluate", Evaluate, | 2867 { "evaluate", Evaluate, |
2773 evaluate_params }, | 2868 evaluate_params }, |
2774 { "evaluateInFrame", EvaluateInFrame, | 2869 { "evaluateInFrame", EvaluateInFrame, |
2775 evaluate_in_frame_params }, | 2870 evaluate_in_frame_params }, |
2776 { "_getAllocationProfile", GetAllocationProfile, | 2871 { "_getAllocationProfile", GetAllocationProfile, |
2777 get_allocation_profile_params }, | 2872 get_allocation_profile_params }, |
| 2873 { "_getAllocationSamples", GetAllocationSamples, |
| 2874 get_allocation_samples_params }, |
2778 { "_getCallSiteData", GetCallSiteData, | 2875 { "_getCallSiteData", GetCallSiteData, |
2779 get_call_site_data_params }, | 2876 get_call_site_data_params }, |
2780 { "getClassList", GetClassList, | 2877 { "getClassList", GetClassList, |
2781 get_class_list_params }, | 2878 get_class_list_params }, |
2782 { "_getCoverage", GetCoverage, | 2879 { "_getCoverage", GetCoverage, |
2783 get_coverage_params }, | 2880 get_coverage_params }, |
2784 { "_getCpuProfile", GetCpuProfile, | 2881 { "_getCpuProfile", GetCpuProfile, |
2785 get_cpu_profile_params }, | 2882 get_cpu_profile_params }, |
2786 { "getFlagList", GetFlagList, | 2883 { "getFlagList", GetFlagList, |
2787 get_flag_list_params }, | 2884 get_flag_list_params }, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2830 { "_requestHeapSnapshot", RequestHeapSnapshot, | 2927 { "_requestHeapSnapshot", RequestHeapSnapshot, |
2831 request_heap_snapshot_params }, | 2928 request_heap_snapshot_params }, |
2832 { "_setExceptionPauseInfo", SetExceptionPauseInfo, | 2929 { "_setExceptionPauseInfo", SetExceptionPauseInfo, |
2833 set_exception_pause_info_params }, | 2930 set_exception_pause_info_params }, |
2834 { "_setFlag", SetFlag, | 2931 { "_setFlag", SetFlag, |
2835 set_flags_params }, | 2932 set_flags_params }, |
2836 { "setLibraryDebuggable", SetLibraryDebuggable, | 2933 { "setLibraryDebuggable", SetLibraryDebuggable, |
2837 set_library_debuggable_params }, | 2934 set_library_debuggable_params }, |
2838 { "setName", SetName, | 2935 { "setName", SetName, |
2839 set_name_params }, | 2936 set_name_params }, |
| 2937 { "_setTraceClassAllocation", SetTraceClassAllocation, |
| 2938 set_trace_class_allocation_params }, |
2840 }; | 2939 }; |
2841 | 2940 |
2842 | 2941 |
2843 ServiceMethodDescriptor* FindMethod(const char* method_name) { | 2942 ServiceMethodDescriptor* FindMethod(const char* method_name) { |
2844 intptr_t num_methods = sizeof(service_methods_) / | 2943 intptr_t num_methods = sizeof(service_methods_) / |
2845 sizeof(service_methods_[0]); | 2944 sizeof(service_methods_[0]); |
2846 for (intptr_t i = 0; i < num_methods; i++) { | 2945 for (intptr_t i = 0; i < num_methods; i++) { |
2847 ServiceMethodDescriptor& method = service_methods_[i]; | 2946 ServiceMethodDescriptor& method = service_methods_[i]; |
2848 if (strcmp(method_name, method.name) == 0) { | 2947 if (strcmp(method_name, method.name) == 0) { |
2849 return &method; | 2948 return &method; |
2850 } | 2949 } |
2851 } | 2950 } |
2852 return NULL; | 2951 return NULL; |
2853 } | 2952 } |
2854 | 2953 |
2855 | 2954 |
2856 } // namespace dart | 2955 } // namespace dart |
OLD | NEW |