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 |directory| and then calls |GetIntegerId| on | |
263 // the remainder of |s|. | |
264 // NOTE: Callers are required to include a trailing / in |directory|. | |
265 static bool GetIntegerIdFromDirectory(const char* s, | |
266 const char* directory, | |
267 intptr_t* service_id) { | |
turnidge
2015/07/13 23:37:49
The word Directory here bothers me some.
How abou
Cutch
2015/07/14 15:53:47
Done.
| |
268 ASSERT(s != NULL); | |
269 ASSERT(directory != NULL); | |
270 const intptr_t kInputLen = strlen(s); | |
271 const intptr_t kDirectoryLen = strlen(directory); | |
272 ASSERT(kDirectoryLen > 0); | |
273 ASSERT(directory[kDirectoryLen - 1] == '/'); | |
274 if (kInputLen <= kDirectoryLen) { | |
275 return false; | |
276 } | |
277 if (strncmp(s, directory, kDirectoryLen) != 0) { | |
278 return false; | |
279 } | |
280 // Directory prefix satisfied. Move forward. | |
281 s += kDirectoryLen; | |
282 // Attempt to read integer id. | |
283 return GetIntegerId(s, service_id); | |
284 } | |
285 | |
286 | |
287 static bool ValidateClassId(Isolate* isolate, intptr_t cid) { | |
turnidge
2015/07/13 23:37:49
Change name to IsValidClassId?
Cutch
2015/07/14 15:53:47
Done.
| |
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 bool ValidateClassId(Isolate* isolate, const char* class_id) { | |
296 intptr_t cid; | |
297 if (!GetIntegerIdFromDirectory(class_id, "classes/", &cid)) { | |
298 return false; | |
299 } | |
300 return ValidateClassId(isolate, cid); | |
301 } | |
turnidge
2015/07/13 23:37:49
I would like you to get rid of the overloaded vers
Cutch
2015/07/14 15:53:47
Done.
| |
302 | |
303 | |
304 static RawClass* GetClassForId(Isolate* isolate, intptr_t cid) { | |
305 ASSERT(isolate == Isolate::Current()); | |
306 ASSERT(isolate != NULL); | |
307 ClassTable* class_table = isolate->class_table(); | |
308 ASSERT(class_table != NULL); | |
309 return class_table->At(cid); | |
310 } | |
311 | |
312 | |
313 static RawClass* GetClassForId(Isolate* isolate, const char* class_id) { | |
314 intptr_t cid; | |
315 ASSERT(GetIntegerIdFromDirectory(class_id, "classes/", &cid)); | |
turnidge
2015/07/13 23:37:49
Do ASSERTs get removed in release builds? I don't
Cutch
2015/07/14 15:53:47
Good catch.
| |
316 return GetClassForId(isolate, cid); | |
317 } | |
318 | |
319 | |
262 // TODO(johnmccutchan): Split into separate file and write unit tests. | 320 // TODO(johnmccutchan): Split into separate file and write unit tests. |
263 class MethodParameter { | 321 class MethodParameter { |
264 public: | 322 public: |
265 MethodParameter(const char* name, bool required) | 323 MethodParameter(const char* name, bool required) |
266 : name_(name), required_(required) { | 324 : name_(name), required_(required) { |
267 } | 325 } |
268 | 326 |
269 virtual ~MethodParameter() { } | 327 virtual ~MethodParameter() { } |
270 | 328 |
271 virtual bool Validate(const char* value) const { | 329 virtual bool Validate(const char* value) const { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
335 } | 393 } |
336 for (const char* cp = value; *cp != '\0'; cp++) { | 394 for (const char* cp = value; *cp != '\0'; cp++) { |
337 if (*cp < '0' || *cp > '9') { | 395 if (*cp < '0' || *cp > '9') { |
338 return false; | 396 return false; |
339 } | 397 } |
340 } | 398 } |
341 return true; | 399 return true; |
342 } | 400 } |
343 | 401 |
344 static intptr_t Parse(const char* value) { | 402 static intptr_t Parse(const char* value) { |
403 if (value == NULL) { | |
404 return -1; | |
405 } | |
345 char* end_ptr = NULL; | 406 char* end_ptr = NULL; |
346 uintptr_t result = strtoul(value, &end_ptr, 10); | 407 uintptr_t result = strtoul(value, &end_ptr, 10); |
347 ASSERT(*end_ptr == '\0'); // Parsed full string | 408 ASSERT(*end_ptr == '\0'); // Parsed full string |
348 return result; | 409 return result; |
349 } | 410 } |
350 }; | 411 }; |
351 | 412 |
352 | 413 |
353 class IdParameter : public MethodParameter { | 414 class IdParameter : public MethodParameter { |
354 public: | 415 public: |
(...skipping 1870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2225 Profile::kUser, | 2286 Profile::kUser, |
2226 Profile::kVMUser, | 2287 Profile::kVMUser, |
2227 Profile::kVM, | 2288 Profile::kVM, |
2228 Profile::kNoTags, // Default value. | 2289 Profile::kNoTags, // Default value. |
2229 }; | 2290 }; |
2230 | 2291 |
2231 | 2292 |
2232 static const MethodParameter* get_cpu_profile_params[] = { | 2293 static const MethodParameter* get_cpu_profile_params[] = { |
2233 ISOLATE_PARAMETER, | 2294 ISOLATE_PARAMETER, |
2234 new EnumParameter("tags", true, tags_enum_names), | 2295 new EnumParameter("tags", true, tags_enum_names), |
2296 new IdParameter("classId", false), | |
2235 NULL, | 2297 NULL, |
2236 }; | 2298 }; |
2237 | 2299 |
2238 | 2300 |
2239 static bool GetCpuProfile(Isolate* isolate, JSONStream* js) { | 2301 static bool GetCpuProfile(Isolate* isolate, JSONStream* js) { |
turnidge
2015/07/13 23:37:49
As mentioned elsewhere, consider separating cpu an
Cutch
2015/07/14 15:53:47
Done.
| |
2240 Profile::TagOrder tag_order = | 2302 Profile::TagOrder tag_order = |
2241 EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values); | 2303 EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values); |
2242 ProfilerService::PrintJSON(js, tag_order); | 2304 const char* class_id = js->LookupParam("classId"); |
2305 if (ValidateClassId(isolate, class_id)) { | |
2306 const Class& cls = Class::Handle(GetClassForId(isolate, class_id)); | |
turnidge
2015/07/13 23:37:49
You are double-parsing the class id, once in Valid
Cutch
2015/07/14 15:53:47
Done.
| |
2307 ProfilerService::PrintAllocationJSON(js, tag_order, cls); | |
2308 } else { | |
2309 ProfilerService::PrintJSON(js, tag_order); | |
2310 } | |
2243 return true; | 2311 return true; |
2244 } | 2312 } |
2245 | 2313 |
2246 | 2314 |
2247 static const MethodParameter* clear_cpu_profile_params[] = { | 2315 static const MethodParameter* clear_cpu_profile_params[] = { |
2248 ISOLATE_PARAMETER, | 2316 ISOLATE_PARAMETER, |
2249 NULL, | 2317 NULL, |
2250 }; | 2318 }; |
2251 | 2319 |
2252 | 2320 |
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2744 isolate->set_debugger_name(js->LookupParam("name")); | 2812 isolate->set_debugger_name(js->LookupParam("name")); |
2745 if (Service::NeedsIsolateEvents()) { | 2813 if (Service::NeedsIsolateEvents()) { |
2746 ServiceEvent event(isolate, ServiceEvent::kIsolateUpdate); | 2814 ServiceEvent event(isolate, ServiceEvent::kIsolateUpdate); |
2747 Service::HandleEvent(&event); | 2815 Service::HandleEvent(&event); |
2748 } | 2816 } |
2749 PrintSuccess(js); | 2817 PrintSuccess(js); |
2750 return true; | 2818 return true; |
2751 } | 2819 } |
2752 | 2820 |
2753 | 2821 |
2822 static const MethodParameter* trace_class_allocation_params[] = { | |
2823 ISOLATE_PARAMETER, | |
2824 new IdParameter("classId", true), | |
2825 new BoolParameter("enable", true), | |
2826 NULL, | |
2827 }; | |
2828 | |
2829 | |
2830 static bool TraceClassAllocation(Isolate* isolate, JSONStream* js) { | |
2831 const char* class_id = js->LookupParam("classId"); | |
2832 const bool enable = BoolParameter::Parse(js->LookupParam("enable")); | |
2833 | |
2834 if (!ValidateClassId(isolate, class_id)) { | |
2835 PrintInvalidParamError(js, "cid"); | |
2836 return true; | |
2837 } | |
2838 | |
2839 const Class& cls = Class::Handle(GetClassForId(isolate, class_id)); | |
2840 ASSERT(!cls.IsNull()); | |
2841 | |
2842 cls.SetTraceAllocation(enable); | |
2843 PrintSuccess(js); | |
2844 return true; | |
2845 } | |
2846 | |
2847 | |
2754 static ServiceMethodDescriptor service_methods_[] = { | 2848 static ServiceMethodDescriptor service_methods_[] = { |
2755 { "_dumpIdZone", DumpIdZone, NULL }, | 2849 { "_dumpIdZone", DumpIdZone, NULL }, |
2756 { "_echo", Echo, | 2850 { "_echo", Echo, |
2757 NULL }, | 2851 NULL }, |
2758 { "_respondWithMalformedJson", RespondWithMalformedJson, | 2852 { "_respondWithMalformedJson", RespondWithMalformedJson, |
2759 NULL }, | 2853 NULL }, |
2760 { "_respondWithMalformedObject", RespondWithMalformedObject, | 2854 { "_respondWithMalformedObject", RespondWithMalformedObject, |
2761 NULL }, | 2855 NULL }, |
2762 { "_triggerEchoEvent", TriggerEchoEvent, | 2856 { "_triggerEchoEvent", TriggerEchoEvent, |
2763 NULL }, | 2857 NULL }, |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2830 { "_requestHeapSnapshot", RequestHeapSnapshot, | 2924 { "_requestHeapSnapshot", RequestHeapSnapshot, |
2831 request_heap_snapshot_params }, | 2925 request_heap_snapshot_params }, |
2832 { "_setExceptionPauseInfo", SetExceptionPauseInfo, | 2926 { "_setExceptionPauseInfo", SetExceptionPauseInfo, |
2833 set_exception_pause_info_params }, | 2927 set_exception_pause_info_params }, |
2834 { "_setFlag", SetFlag, | 2928 { "_setFlag", SetFlag, |
2835 set_flags_params }, | 2929 set_flags_params }, |
2836 { "setLibraryDebuggable", SetLibraryDebuggable, | 2930 { "setLibraryDebuggable", SetLibraryDebuggable, |
2837 set_library_debuggable_params }, | 2931 set_library_debuggable_params }, |
2838 { "setName", SetName, | 2932 { "setName", SetName, |
2839 set_name_params }, | 2933 set_name_params }, |
2934 { "_traceClassAllocation", TraceClassAllocation, | |
turnidge
2015/07/13 23:37:49
Consider changing rpc name for consistency with se
Cutch
2015/07/14 15:53:48
Done.
| |
2935 trace_class_allocation_params }, | |
2840 }; | 2936 }; |
2841 | 2937 |
2842 | 2938 |
2843 ServiceMethodDescriptor* FindMethod(const char* method_name) { | 2939 ServiceMethodDescriptor* FindMethod(const char* method_name) { |
2844 intptr_t num_methods = sizeof(service_methods_) / | 2940 intptr_t num_methods = sizeof(service_methods_) / |
2845 sizeof(service_methods_[0]); | 2941 sizeof(service_methods_[0]); |
2846 for (intptr_t i = 0; i < num_methods; i++) { | 2942 for (intptr_t i = 0; i < num_methods; i++) { |
2847 ServiceMethodDescriptor& method = service_methods_[i]; | 2943 ServiceMethodDescriptor& method = service_methods_[i]; |
2848 if (strcmp(method_name, method.name) == 0) { | 2944 if (strcmp(method_name, method.name) == 0) { |
2849 return &method; | 2945 return &method; |
2850 } | 2946 } |
2851 } | 2947 } |
2852 return NULL; | 2948 return NULL; |
2853 } | 2949 } |
2854 | 2950 |
2855 | 2951 |
2856 } // namespace dart | 2952 } // namespace dart |
OLD | NEW |