Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(327)

Side by Side Diff: runtime/vm/service.cc

Issue 1566793002: Expose the new _getSourceReport api in the service protocol. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: code rev Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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) >= 0;
574 }
575
576 const char** Parse(Zone* zone, const char* value_in) const {
577 const char* kJsonChars = " \t\r\n[,]";
578
579 // Make a writeable copy of the value.
580 char* value = zone->MakeCopyOfString(value_in);
581 intptr_t element_count = ElementCount(value);
582 intptr_t element_pos = 0;
583
584 // Allocate our element array. +1 for NULL terminator.
585 char** elements = zone->Alloc<char*>(element_count + 1);
586 elements[element_count] = NULL;
587
588 // Parse the string destructively. Build the list of elements.
589 while (element_pos < element_count) {
590 // Skip to the next element.
591 value += strspn(value, kJsonChars);
592
593 intptr_t len = strcspn(value, kJsonChars);
594 ASSERT(len > 0); // We rely on the parameter being validated already.
595 value[len] = '\0';
596 elements[element_pos++] = value;
597
598 // Advance. +1 for null terminator.
599 value += (len + 1);
600 }
601 return const_cast<const char**>(elements);
602 }
603
604 private:
605 // For now observatory enums are ascii letters plus underscore.
606 static bool IsEnumChar(char c) {
607 return (((c >= 'a') && (c <= 'z')) ||
608 ((c >= 'A') && (c <= 'Z')) ||
609 (c == '_'));
610 }
611
612 // Returns number of elements in the list. -1 on parse error.
613 intptr_t ElementCount(const char* value) const {
614 const char* kJsonWhitespaceChars = " \t\r\n";
615
616 if (value == NULL) {
617 return -1;
618 }
619 const char* cp = value;
620 cp += strspn(cp, kJsonWhitespaceChars);
621 if (*cp++ != '[') {
622 // Missing initial [.
623 return -1;
624 }
625 bool closed = false;
626 bool element_allowed = true;
627 intptr_t element_count = 0;
628 while (true) {
629 // Skip json whitespace.
630 cp += strspn(cp, kJsonWhitespaceChars);
631 switch (*cp) {
632 case '\0':
633 return closed ? element_count : -1;
634 case ']':
635 closed = true;
636 cp++;
637 break;
638 case ',':
639 if (element_allowed) {
640 return -1;
641 }
642 element_allowed = true;
643 cp++;
644 break;
645 default:
646 if (!element_allowed) {
647 return -1;
648 }
649 bool valid_enum = false;
650 if (enums_ != NULL) {
651 for (intptr_t i = 0; enums_[i] != NULL; i++) {
652 intptr_t len = strlen(enums_[i]);
653 if (strncmp(cp, enums_[i], len) == 0) {
654 element_count++;
655 valid_enum = true;
656 cp += len;
657 element_allowed = false; // we need a comma first.
658 break;
659 }
660 }
661 } else {
662 // Allow any identifiers
663 const char* id_start = cp;
664 while (IsEnumChar(*cp)) {
665 cp++;
666 }
667 if (cp == id_start) {
668 // Empty identifier, something like this [,].
669 return -1;
670 }
671 }
672 if (!valid_enum) {
673 return -1;
674 }
675 break;
676 }
677 }
678 }
679
680 const char* const* enums_;
681 };
682
683
564 typedef bool (*ServiceMethodEntry)(Thread* thread, JSONStream* js); 684 typedef bool (*ServiceMethodEntry)(Thread* thread, JSONStream* js);
565 685
566 686
567 struct ServiceMethodDescriptor { 687 struct ServiceMethodDescriptor {
568 const char* name; 688 const char* name;
569 const ServiceMethodEntry entry; 689 const ServiceMethodEntry entry;
570 const MethodParameter* const * parameters; 690 const MethodParameter* const * parameters;
571 }; 691 };
572 692
573 693
(...skipping 1610 matching lines...) Expand 10 before | Expand all | Expand 10 after
2184 NULL, 2304 NULL,
2185 }; 2305 };
2186 2306
2187 2307
2188 static bool GetCoverage(Thread* thread, JSONStream* js) { 2308 static bool GetCoverage(Thread* thread, JSONStream* js) {
2189 // TODO(rmacnak): Remove this response; it is subsumed by GetCallSiteData. 2309 // TODO(rmacnak): Remove this response; it is subsumed by GetCallSiteData.
2190 return GetHitsOrSites(thread, js, false); 2310 return GetHitsOrSites(thread, js, false);
2191 } 2311 }
2192 2312
2193 2313
2314 static const char* kCallSitesStr = "CallSites";
2315 static const char* kCoverageStr = "Coverage";
2316
2317
2318 static const char* const report_enum_names[] = {
2319 kCallSitesStr,
2320 kCoverageStr,
2321 NULL,
2322 };
2323
2324
2325 static const EnumListParameter* reports_parameter =
2326 new EnumListParameter("reports", true, report_enum_names);
2327
2328
2329 static const MethodParameter* get_source_report_params[] = {
2330 ISOLATE_PARAMETER,
2331 reports_parameter,
2332 new IdParameter("scriptId", false),
2333 new UIntParameter("tokenPos", false),
2334 new UIntParameter("endTokenPos", false),
2335 NULL,
2336 };
2337
2338
2339 static bool GetSourceReport(Thread* thread, JSONStream* js) {
2340 const char* reports_str = js->LookupParam("reports");
2341 const char** reports = reports_parameter->Parse(thread->zone(), reports_str);
2342 intptr_t report_set = 0;
2343 while (*reports != NULL) {
2344 if (strcmp(*reports, kCallSitesStr) == 0) {
2345 report_set |= SourceReport::kCallSites;
2346 } else if (strcmp(*reports, kCoverageStr) == 0) {
2347 report_set |= SourceReport::kCoverage;
2348 }
2349 reports++;
2350 }
2351
2352 Script& script = Script::Handle();
2353 intptr_t start_pos = UIntParameter::Parse(js->LookupParam("tokenPos"));
2354 intptr_t end_pos = UIntParameter::Parse(js->LookupParam("endTokenPos"));
2355
2356 if (js->HasParam("scriptId")) {
2357 // Get the target script.
2358 const char* script_id_param = js->LookupParam("scriptId");
2359 const Object& obj =
2360 Object::Handle(LookupHeapObject(thread, script_id_param, NULL));
2361 if (obj.raw() == Object::sentinel().raw() || !obj.IsScript()) {
2362 PrintInvalidParamError(js, "scriptId");
2363 return true;
2364 }
2365 script ^= obj.raw();
2366 } else {
2367 if (js->HasParam("tokenPos")) {
2368 js->PrintError(
2369 kInvalidParams,
2370 "%s: the 'tokenPos' parameter requires the 'scriptId' parameter",
2371 js->method());
2372 return true;
2373 }
2374 if (js->HasParam("endTokenPos")) {
2375 js->PrintError(
2376 kInvalidParams,
2377 "%s: the 'endTokenPos' parameter requires the 'scriptId' parameter",
2378 js->method());
2379 return true;
2380 }
2381 }
2382 SourceReport report(report_set);
2383 report.PrintJSON(js, script, start_pos, end_pos);
2384 return true;
2385 }
2386
2387
2194 static const MethodParameter* get_call_site_data_params[] = { 2388 static const MethodParameter* get_call_site_data_params[] = {
2195 ISOLATE_PARAMETER, 2389 ISOLATE_PARAMETER,
2196 new IdParameter("targetId", false), 2390 new IdParameter("targetId", false),
2197 NULL, 2391 NULL,
2198 }; 2392 };
2199 2393
2200 2394
2201 static bool GetCallSiteData(Thread* thread, JSONStream* js) { 2395 static bool GetCallSiteData(Thread* thread, JSONStream* js) {
2202 return GetHitsOrSites(thread, js, true); 2396 return GetHitsOrSites(thread, js, true);
2203 } 2397 }
(...skipping 1397 matching lines...) Expand 10 before | Expand all | Expand 10 after
3601 { "_getObjectByAddress", GetObjectByAddress, 3795 { "_getObjectByAddress", GetObjectByAddress,
3602 get_object_by_address_params }, 3796 get_object_by_address_params },
3603 { "_getPorts", GetPorts, 3797 { "_getPorts", GetPorts,
3604 get_ports_params }, 3798 get_ports_params },
3605 { "_getReachableSize", GetReachableSize, 3799 { "_getReachableSize", GetReachableSize,
3606 get_reachable_size_params }, 3800 get_reachable_size_params },
3607 { "_getRetainedSize", GetRetainedSize, 3801 { "_getRetainedSize", GetRetainedSize,
3608 get_retained_size_params }, 3802 get_retained_size_params },
3609 { "_getRetainingPath", GetRetainingPath, 3803 { "_getRetainingPath", GetRetainingPath,
3610 get_retaining_path_params }, 3804 get_retaining_path_params },
3805 { "_getSourceReport", GetSourceReport,
3806 get_source_report_params },
3611 { "getStack", GetStack, 3807 { "getStack", GetStack,
3612 get_stack_params }, 3808 get_stack_params },
3613 { "_getTagProfile", GetTagProfile, 3809 { "_getTagProfile", GetTagProfile,
3614 get_tag_profile_params }, 3810 get_tag_profile_params },
3615 { "_getTypeArgumentsList", GetTypeArgumentsList, 3811 { "_getTypeArgumentsList", GetTypeArgumentsList,
3616 get_type_arguments_list_params }, 3812 get_type_arguments_list_params },
3617 { "getVersion", GetVersion, 3813 { "getVersion", GetVersion,
3618 get_version_params }, 3814 get_version_params },
3619 { "getVM", GetVM, 3815 { "getVM", GetVM,
3620 get_vm_params }, 3816 get_vm_params },
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
3660 const ServiceMethodDescriptor& method = service_methods_[i]; 3856 const ServiceMethodDescriptor& method = service_methods_[i];
3661 if (strcmp(method_name, method.name) == 0) { 3857 if (strcmp(method_name, method.name) == 0) {
3662 return &method; 3858 return &method;
3663 } 3859 }
3664 } 3860 }
3665 return NULL; 3861 return NULL;
3666 } 3862 }
3667 3863
3668 3864
3669 } // namespace dart 3865 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/observatory/tests/service/get_source_report_test.dart ('k') | runtime/vm/source_report.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698