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 12 matching lines...) Expand all Loading... | |
23 #include "vm/object.h" | 23 #include "vm/object.h" |
24 #include "vm/object_graph.h" | 24 #include "vm/object_graph.h" |
25 #include "vm/object_id_ring.h" | 25 #include "vm/object_id_ring.h" |
26 #include "vm/object_store.h" | 26 #include "vm/object_store.h" |
27 #include "vm/parser.h" | 27 #include "vm/parser.h" |
28 #include "vm/port.h" | 28 #include "vm/port.h" |
29 #include "vm/profiler_service.h" | 29 #include "vm/profiler_service.h" |
30 #include "vm/reusable_handles.h" | 30 #include "vm/reusable_handles.h" |
31 #include "vm/service_event.h" | 31 #include "vm/service_event.h" |
32 #include "vm/service_isolate.h" | 32 #include "vm/service_isolate.h" |
33 #include "vm/source_report.h" | |
33 #include "vm/stack_frame.h" | 34 #include "vm/stack_frame.h" |
34 #include "vm/symbols.h" | 35 #include "vm/symbols.h" |
35 #include "vm/unicode.h" | 36 #include "vm/unicode.h" |
36 #include "vm/version.h" | 37 #include "vm/version.h" |
37 | 38 |
38 namespace dart { | 39 namespace dart { |
39 | 40 |
40 #define Z (T->zone()) | 41 #define Z (T->zone()) |
41 | 42 |
42 | 43 |
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
554 for (i = 0; enums[i] != NULL; i++) { | 555 for (i = 0; enums[i] != NULL; i++) { |
555 if (strcmp(value, enums[i]) == 0) { | 556 if (strcmp(value, enums[i]) == 0) { |
556 return values[i]; | 557 return values[i]; |
557 } | 558 } |
558 } | 559 } |
559 // Default value. | 560 // Default value. |
560 return values[i]; | 561 return values[i]; |
561 } | 562 } |
562 | 563 |
563 | 564 |
565 class EnumListParameter : public MethodParameter { | |
566 public: | |
567 EnumListParameter(const char* name, bool required, const char* const* enums) | |
568 : MethodParameter(name, required), | |
569 enums_(enums) { | |
570 } | |
571 | |
572 virtual bool Validate(const char* value) const { | |
573 return ElementCount(value, enums_) >= 0; | |
574 } | |
575 | |
576 static const char** Parse(Zone* zone, | |
577 const char* value_in, | |
578 const char* const* enums) { | |
Cutch
2016/01/06 19:18:26
Why pass in enums again? You store it in the const
turnidge
2016/01/06 20:58:13
The rest of our Parse methods are static and I was
| |
579 const char* kJsonChars = " \t\r\n[,]"; | |
580 | |
581 // Make a writeable copy of the value. | |
582 char* value = zone->MakeCopyOfString(value_in); | |
583 intptr_t element_count = ElementCount(value, enums); | |
584 intptr_t element_pos = 0; | |
585 | |
586 // Allocate our element array. +1 for NULL terminator. | |
587 char** elements = zone->Alloc<char*>(element_count + 1); | |
588 elements[element_count] = NULL; | |
589 | |
590 // Parse the string destructively. Build the list of elements. | |
Cutch
2016/01/06 19:18:26
Zone allocation is cheap, consider doing this with
turnidge
2016/01/06 20:58:12
This already is a copy of the string, check out th
| |
591 while (element_pos < element_count) { | |
592 // Skip to the next element. | |
593 value += strspn(value, kJsonChars); | |
594 | |
595 intptr_t len = strcspn(value, kJsonChars); | |
596 ASSERT(len > 0); // We rely on the parameter being validated already. | |
597 value[len] = '\0'; | |
598 elements[element_pos++] = value; | |
599 | |
600 // Advance. +1 for null terminator. | |
601 value += (len + 1); | |
602 } | |
603 return const_cast<const char**>(elements); | |
604 } | |
605 | |
606 private: | |
607 // Returns number of elements in the list. -1 on parse error. | |
608 static intptr_t ElementCount(const char* value, const char* const* enums) { | |
609 if (value == NULL) { | |
610 return -1; | |
611 } | |
612 const char* cp = value; | |
Cutch
2016/01/06 19:18:26
Skip whitespace before checking for '['
turnidge
2016/01/06 20:58:12
The whitespace will be trimmed already by the time
| |
613 if (*cp++ != '[') { | |
614 // Missing initial [. | |
615 return -1; | |
616 } | |
617 bool closed = false; | |
618 bool element_allowed = true; | |
619 intptr_t element_count = 0; | |
620 while (true) { | |
621 // Skip json whitespace. | |
622 cp += strspn(cp, " \t\r\n"); | |
Cutch
2016/01/06 19:18:25
Pull this constant string out to a kWhitespaceChar
turnidge
2016/01/06 20:58:12
Done.
| |
623 switch (*cp) { | |
624 case '\0': | |
625 return closed ? element_count : -1; | |
626 case ']': | |
627 closed = true; | |
628 cp++; | |
629 break; | |
630 case ',': | |
631 if (element_allowed) { | |
632 return -1; | |
633 } | |
634 element_allowed = true; | |
635 cp++; | |
636 break; | |
637 default: | |
638 if (!element_allowed) { | |
639 return -1; | |
640 } | |
641 bool valid_enum = false; | |
642 for (intptr_t i = 0; enums[i] != NULL; i++) { | |
Cutch
2016/01/06 19:18:26
Maybe allow for enums to be NULL so that an arbitr
turnidge
2016/01/06 20:58:12
Done.
| |
643 intptr_t len = strlen(enums[i]); | |
644 if (strncmp(cp, enums[i], len) == 0) { | |
645 element_count++; | |
646 valid_enum = true; | |
647 cp += len; | |
648 element_allowed = false; // we need a comma first. | |
649 break; | |
650 } | |
651 } | |
652 if (!valid_enum) { | |
653 return -1; | |
654 } | |
655 break; | |
656 } | |
657 } | |
658 } | |
659 | |
660 const char* const* enums_; | |
661 }; | |
662 | |
663 | |
564 typedef bool (*ServiceMethodEntry)(Thread* thread, JSONStream* js); | 664 typedef bool (*ServiceMethodEntry)(Thread* thread, JSONStream* js); |
565 | 665 |
566 | 666 |
567 struct ServiceMethodDescriptor { | 667 struct ServiceMethodDescriptor { |
568 const char* name; | 668 const char* name; |
569 const ServiceMethodEntry entry; | 669 const ServiceMethodEntry entry; |
570 const MethodParameter* const * parameters; | 670 const MethodParameter* const * parameters; |
571 }; | 671 }; |
572 | 672 |
573 | 673 |
(...skipping 1610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2184 NULL, | 2284 NULL, |
2185 }; | 2285 }; |
2186 | 2286 |
2187 | 2287 |
2188 static bool GetCoverage(Thread* thread, JSONStream* js) { | 2288 static bool GetCoverage(Thread* thread, JSONStream* js) { |
2189 // TODO(rmacnak): Remove this response; it is subsumed by GetCallSiteData. | 2289 // TODO(rmacnak): Remove this response; it is subsumed by GetCallSiteData. |
2190 return GetHitsOrSites(thread, js, false); | 2290 return GetHitsOrSites(thread, js, false); |
2191 } | 2291 } |
2192 | 2292 |
2193 | 2293 |
2294 static const char* kCallSitesStr = "CallSites"; | |
2295 static const char* kCoverageStr = "Coverage"; | |
2296 | |
2297 | |
2298 static const char* const report_enum_names[] = { | |
2299 kCallSitesStr, | |
2300 kCoverageStr, | |
2301 NULL, | |
2302 }; | |
2303 | |
2304 | |
2305 static const MethodParameter* get_source_report_params[] = { | |
2306 ISOLATE_PARAMETER, | |
2307 new EnumListParameter("reports", true, report_enum_names), | |
2308 new IdParameter("scriptId", false), | |
2309 new UIntParameter("tokenPos", false), | |
2310 new UIntParameter("endTokenPos", false), | |
2311 NULL, | |
2312 }; | |
2313 | |
2314 | |
2315 static bool GetSourceReport(Thread* thread, JSONStream* js) { | |
2316 const char* reports_str = js->LookupParam("reports"); | |
2317 const char** reports = | |
2318 EnumListParameter::Parse(thread->zone(), reports_str, report_enum_names); | |
2319 intptr_t report_set = 0; | |
2320 while (*reports != NULL) { | |
2321 if (strcmp(*reports, kCallSitesStr) == 0) { | |
2322 report_set |= SourceReport::kCallSites; | |
2323 } else if (strcmp(*reports, kCoverageStr) == 0) { | |
2324 report_set |= SourceReport::kCoverage; | |
2325 } | |
2326 reports++; | |
2327 } | |
2328 | |
2329 Script& script = Script::Handle(); | |
2330 intptr_t start_pos = UIntParameter::Parse(js->LookupParam("tokenPos")); | |
2331 intptr_t end_pos = UIntParameter::Parse(js->LookupParam("endTokenPos")); | |
2332 | |
2333 if (js->HasParam("scriptId")) { | |
2334 // Get the target script. | |
2335 const char* script_id_param = js->LookupParam("scriptId"); | |
2336 const Object& obj = | |
2337 Object::Handle(LookupHeapObject(thread, script_id_param, NULL)); | |
2338 if (obj.raw() == Object::sentinel().raw() || !obj.IsScript()) { | |
2339 PrintInvalidParamError(js, "scriptId"); | |
2340 return true; | |
2341 } | |
2342 script ^= obj.raw(); | |
2343 } else { | |
2344 if (js->HasParam("tokenPos")) { | |
2345 js->PrintError( | |
2346 kInvalidParams, | |
2347 "%s: the 'tokenPos' parameter requires the 'scriptId' parameter", | |
2348 js->method()); | |
2349 return false; | |
Cutch
2016/01/06 19:18:25
These should return true or else we will hit the U
turnidge
2016/01/06 20:58:13
Thanks. Done.
| |
2350 } | |
2351 if (js->HasParam("endTokenPos")) { | |
2352 js->PrintError( | |
2353 kInvalidParams, | |
2354 "%s: the 'endTokenPos' parameter requires the 'scriptId' parameter", | |
2355 js->method()); | |
2356 return false; | |
2357 } | |
2358 } | |
2359 SourceReport report(report_set); | |
2360 report.PrintJSON(js, script, start_pos, end_pos); | |
2361 return true; | |
2362 } | |
2363 | |
2364 | |
2194 static const MethodParameter* get_call_site_data_params[] = { | 2365 static const MethodParameter* get_call_site_data_params[] = { |
2195 ISOLATE_PARAMETER, | 2366 ISOLATE_PARAMETER, |
2196 new IdParameter("targetId", false), | 2367 new IdParameter("targetId", false), |
2197 NULL, | 2368 NULL, |
2198 }; | 2369 }; |
2199 | 2370 |
2200 | 2371 |
2201 static bool GetCallSiteData(Thread* thread, JSONStream* js) { | 2372 static bool GetCallSiteData(Thread* thread, JSONStream* js) { |
2202 return GetHitsOrSites(thread, js, true); | 2373 return GetHitsOrSites(thread, js, true); |
2203 } | 2374 } |
(...skipping 1397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3601 { "_getObjectByAddress", GetObjectByAddress, | 3772 { "_getObjectByAddress", GetObjectByAddress, |
3602 get_object_by_address_params }, | 3773 get_object_by_address_params }, |
3603 { "_getPorts", GetPorts, | 3774 { "_getPorts", GetPorts, |
3604 get_ports_params }, | 3775 get_ports_params }, |
3605 { "_getReachableSize", GetReachableSize, | 3776 { "_getReachableSize", GetReachableSize, |
3606 get_reachable_size_params }, | 3777 get_reachable_size_params }, |
3607 { "_getRetainedSize", GetRetainedSize, | 3778 { "_getRetainedSize", GetRetainedSize, |
3608 get_retained_size_params }, | 3779 get_retained_size_params }, |
3609 { "_getRetainingPath", GetRetainingPath, | 3780 { "_getRetainingPath", GetRetainingPath, |
3610 get_retaining_path_params }, | 3781 get_retaining_path_params }, |
3782 { "_getSourceReport", GetSourceReport, | |
3783 get_source_report_params }, | |
3611 { "getStack", GetStack, | 3784 { "getStack", GetStack, |
3612 get_stack_params }, | 3785 get_stack_params }, |
3613 { "_getTagProfile", GetTagProfile, | 3786 { "_getTagProfile", GetTagProfile, |
3614 get_tag_profile_params }, | 3787 get_tag_profile_params }, |
3615 { "_getTypeArgumentsList", GetTypeArgumentsList, | 3788 { "_getTypeArgumentsList", GetTypeArgumentsList, |
3616 get_type_arguments_list_params }, | 3789 get_type_arguments_list_params }, |
3617 { "getVersion", GetVersion, | 3790 { "getVersion", GetVersion, |
3618 get_version_params }, | 3791 get_version_params }, |
3619 { "getVM", GetVM, | 3792 { "getVM", GetVM, |
3620 get_vm_params }, | 3793 get_vm_params }, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3660 const ServiceMethodDescriptor& method = service_methods_[i]; | 3833 const ServiceMethodDescriptor& method = service_methods_[i]; |
3661 if (strcmp(method_name, method.name) == 0) { | 3834 if (strcmp(method_name, method.name) == 0) { |
3662 return &method; | 3835 return &method; |
3663 } | 3836 } |
3664 } | 3837 } |
3665 return NULL; | 3838 return NULL; |
3666 } | 3839 } |
3667 | 3840 |
3668 | 3841 |
3669 } // namespace dart | 3842 } // namespace dart |
OLD | NEW |