Chromium Code Reviews| 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 |