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

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: 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, 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
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
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
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
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