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 | 8 |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/coverage.h" | 10 #include "vm/coverage.h" |
11 #include "vm/cpu.h" | 11 #include "vm/cpu.h" |
12 #include "vm/dart_api_impl.h" | 12 #include "vm/dart_api_impl.h" |
13 #include "vm/dart_entry.h" | 13 #include "vm/dart_entry.h" |
14 #include "vm/debugger.h" | 14 #include "vm/debugger.h" |
15 #include "vm/heap_histogram.h" | 15 #include "vm/heap_histogram.h" |
16 #include "vm/isolate.h" | 16 #include "vm/isolate.h" |
17 #include "vm/message.h" | 17 #include "vm/message.h" |
18 #include "vm/native_entry.h" | 18 #include "vm/native_entry.h" |
19 #include "vm/native_arguments.h" | 19 #include "vm/native_arguments.h" |
20 #include "vm/object.h" | 20 #include "vm/object.h" |
21 #include "vm/object_id_ring.h" | 21 #include "vm/object_id_ring.h" |
22 #include "vm/object_store.h" | 22 #include "vm/object_store.h" |
23 #include "vm/port.h" | 23 #include "vm/port.h" |
24 #include "vm/profiler.h" | 24 #include "vm/profiler.h" |
25 #include "vm/stack_frame.h" | |
25 #include "vm/symbols.h" | 26 #include "vm/symbols.h" |
26 | 27 |
27 | 28 |
28 namespace dart { | 29 namespace dart { |
29 | 30 |
30 struct ResourcesEntry { | 31 struct ResourcesEntry { |
31 const char* path_; | 32 const char* path_; |
32 const char* resource_; | 33 const char* resource_; |
33 int length_; | 34 int length_; |
34 }; | 35 }; |
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
562 GrowableObjectArray& option_keys = GrowableObjectArray::Handle(isolate); | 563 GrowableObjectArray& option_keys = GrowableObjectArray::Handle(isolate); |
563 GrowableObjectArray& option_values = GrowableObjectArray::Handle(isolate); | 564 GrowableObjectArray& option_values = GrowableObjectArray::Handle(isolate); |
564 reply_port ^= message.At(0); | 565 reply_port ^= message.At(0); |
565 path ^= message.At(1); | 566 path ^= message.At(1); |
566 option_keys ^= message.At(2); | 567 option_keys ^= message.At(2); |
567 option_values ^= message.At(3); | 568 option_values ^= message.At(3); |
568 | 569 |
569 ASSERT(!path.IsNull()); | 570 ASSERT(!path.IsNull()); |
570 ASSERT(!option_keys.IsNull()); | 571 ASSERT(!option_keys.IsNull()); |
571 ASSERT(!option_values.IsNull()); | 572 ASSERT(!option_values.IsNull()); |
572 // Path always has at least one entry in it. | |
573 ASSERT(path.Length() > 0); | |
574 // Same number of option keys as values. | 573 // Same number of option keys as values. |
575 ASSERT(option_keys.Length() == option_values.Length()); | 574 ASSERT(option_keys.Length() == option_values.Length()); |
576 | 575 |
577 String& pathSegment = String::Handle(); | 576 String& pathSegment = String::Handle(); |
578 pathSegment ^= path.At(0); | 577 if (path.Length() > 0) { |
578 pathSegment ^= path.At(0); | |
579 } else { | |
580 pathSegment ^= Symbols::Empty().raw(); | |
581 } | |
579 ASSERT(!pathSegment.IsNull()); | 582 ASSERT(!pathSegment.IsNull()); |
580 | 583 |
581 IsolateMessageHandler handler = | 584 IsolateMessageHandler handler = |
582 FindIsolateMessageHandler(pathSegment.ToCString()); | 585 FindIsolateMessageHandler(pathSegment.ToCString()); |
583 { | 586 { |
584 JSONStream js; | 587 JSONStream js; |
585 SetupJSONStream(&js, zone.GetZone(), | 588 SetupJSONStream(&js, zone.GetZone(), |
586 reply_port, path, option_keys, option_values); | 589 reply_port, path, option_keys, option_values); |
587 if (handler == NULL) { | 590 if (handler == NULL) { |
588 PrintError(&js, "Unrecognized path"); | 591 PrintError(&js, "Unrecognized path"); |
589 PostReply(&js); | 592 PostReply(&js); |
590 } else { | 593 } else { |
591 if (handler(isolate, &js)) { | 594 if (handler(isolate, &js)) { |
592 // Handler returns true if the reply is ready to be posted. | 595 // Handler returns true if the reply is ready to be posted. |
593 PostReply(&js); | 596 PostReply(&js); |
594 } | 597 } |
595 } | 598 } |
596 } | 599 } |
597 } | 600 } |
598 } | 601 } |
599 | 602 |
600 | 603 |
601 static bool HandleName(Isolate* isolate, JSONStream* js) { | 604 static bool HandleIsolate(Isolate* isolate, JSONStream* js) { |
602 JSONObject jsobj(js); | 605 JSONObject jsobj(js); |
603 jsobj.AddProperty("type", "IsolateName"); | 606 jsobj.AddProperty("type", "Isolate"); |
604 jsobj.AddProperty("id", static_cast<intptr_t>(isolate->main_port())); | 607 jsobj.AddPropertyF("id", "isolates/%" Pd "", |
605 jsobj.AddProperty("name", isolate->name()); | 608 static_cast<intptr_t>(isolate->main_port())); |
609 jsobj.AddPropertyF("name", "%" Pd "", | |
610 static_cast<intptr_t>(isolate->main_port())); | |
Cutch
2014/01/28 19:32:51
Does it make sense to move most of this into Isola
turnidge
2014/01/28 23:18:55
Yes, done.
| |
611 IsolateSpawnState* state = isolate->spawn_state(); | |
612 if (state != NULL) { | |
613 const Object& entry = Object::Handle(isolate, state->ResolveFunction()); | |
614 if (!entry.IsNull() && entry.IsFunction()) { | |
615 Function& func = Function::Handle(isolate); | |
616 func ^= entry.raw(); | |
617 jsobj.AddProperty("entry", func); | |
618 } | |
619 } | |
620 { | |
621 Heap* heap = isolate->heap(); | |
622 JSONObject jsheap(&jsobj, "heap"); | |
623 jsheap.AddProperty("usedNew", heap->UsedInWords(Heap::kNew)); | |
624 jsheap.AddProperty("capacityNew", heap->CapacityInWords(Heap::kNew)); | |
625 jsheap.AddProperty("usedOld", heap->UsedInWords(Heap::kOld)); | |
626 jsheap.AddProperty("capacityOld", heap->CapacityInWords(Heap::kOld)); | |
627 } | |
628 | |
629 DartFrameIterator iterator; | |
630 StackFrame* top_frame = iterator.NextFrame(); | |
Cutch
2014/01/28 19:32:51
Similiarly StackFrame::PrintToJSONStream?
turnidge
2014/01/28 23:18:55
I've updated all of the stack display code to use
| |
631 if (top_frame) { | |
632 JSONObject jsframe(&jsobj, "topFrame"); | |
633 const Code& code = Code::Handle(top_frame->LookupDartCode()); | |
634 const Function& top_function = Function::Handle(code.function()); | |
635 const Script& script = Script::Handle(top_function.script()); | |
636 const intptr_t token_pos = code.GetTokenIndexOfPC(top_frame->pc()); | |
637 intptr_t line, column; | |
638 script.GetTokenLocation(token_pos, &line, &column); | |
639 String& line_string = String::Handle(script.GetLine(line)); | |
640 | |
641 jsobj.AddProperty("script", script); | |
642 jsobj.AddProperty("line", line); | |
643 jsobj.AddProperty("lineString", line_string.ToCString()); | |
644 jsobj.AddProperty("function", top_function); | |
645 jsobj.AddProperty("code", code); | |
646 } | |
647 | |
648 const Library& lib = | |
649 Library::Handle(isolate->object_store()->root_library()); | |
650 jsobj.AddProperty("rootLib", lib); | |
651 | |
652 isolate->timer_list().PrintTimersToJSONProperty(&jsobj); | |
606 return true; | 653 return true; |
607 } | 654 } |
608 | 655 |
609 | 656 |
610 static bool HandleStackTrace(Isolate* isolate, JSONStream* js) { | 657 static bool HandleStackTrace(Isolate* isolate, JSONStream* js) { |
658 if (js->num_arguments() > 1) { | |
659 PrintError(js, "Command too long"); | |
660 return true; | |
661 } | |
611 DebuggerStackTrace* stack = isolate->debugger()->StackTrace(); | 662 DebuggerStackTrace* stack = isolate->debugger()->StackTrace(); |
612 JSONObject jsobj(js); | 663 JSONObject jsobj(js); |
613 jsobj.AddProperty("type", "StackTrace"); | 664 jsobj.AddProperty("type", "StackTrace"); |
614 JSONArray jsarr(&jsobj, "members"); | 665 JSONArray jsarr(&jsobj, "members"); |
615 intptr_t n_frames = stack->Length(); | 666 intptr_t num_frames = stack->Length(); |
616 String& function = String::Handle(); | |
617 Script& script = Script::Handle(); | 667 Script& script = Script::Handle(); |
618 for (int i = 0; i < n_frames; i++) { | 668 for (intptr_t i = 0; i < num_frames; i++) { |
619 ActivationFrame* frame = stack->FrameAt(i); | 669 ActivationFrame* frame = stack->FrameAt(i); |
620 script ^= frame->SourceScript(); | 670 script ^= frame->SourceScript(); |
621 function ^= frame->function().UserVisibleName(); | |
622 JSONObject jsobj(&jsarr); | 671 JSONObject jsobj(&jsarr); |
623 jsobj.AddProperty("name", function.ToCString()); | |
624 jsobj.AddProperty("script", script); | 672 jsobj.AddProperty("script", script); |
625 jsobj.AddProperty("line", frame->LineNumber()); | 673 jsobj.AddProperty("line", frame->LineNumber()); |
626 jsobj.AddProperty("function", frame->function()); | 674 jsobj.AddProperty("function", frame->function()); |
627 jsobj.AddProperty("code", frame->code()); | 675 jsobj.AddProperty("code", frame->code()); |
676 jsobj.AddProperty("depth", i); | |
677 { | |
678 JSONArray jsvars(&jsobj, "vars"); | |
679 const int num_vars = frame->NumLocalVariables(); | |
680 for (intptr_t v = 0; v < num_vars; v++) { | |
681 JSONObject jsvar(&jsvars); | |
682 String& var_name = String::Handle(); | |
683 Instance& var_value = Instance::Handle(); | |
684 intptr_t unused; | |
685 frame->VariableAt(v, &var_name, &unused, &unused, &var_value); | |
686 jsvar.AddProperty("name", var_name.ToCString()); | |
687 jsvar.AddProperty("value", var_value); | |
688 } | |
689 } | |
628 } | 690 } |
629 return true; | 691 return true; |
630 } | 692 } |
631 | 693 |
632 | 694 |
633 static bool HandleObjectHistogram(Isolate* isolate, JSONStream* js) { | 695 static bool HandleObjectHistogram(Isolate* isolate, JSONStream* js) { |
634 ObjectHistogram* histogram = Isolate::Current()->object_histogram(); | 696 ObjectHistogram* histogram = Isolate::Current()->object_histogram(); |
635 if (histogram == NULL) { | 697 if (histogram == NULL) { |
636 JSONObject jsobj(js); | 698 JSONObject jsobj(js); |
637 jsobj.AddProperty("type", "Error"); | 699 jsobj.AddProperty("type", "Error"); |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
858 } else { | 920 } else { |
859 PrintError(js, "Invalid sub collection %s", second); | 921 PrintError(js, "Invalid sub collection %s", second); |
860 return true; | 922 return true; |
861 } | 923 } |
862 } | 924 } |
863 UNREACHABLE(); | 925 UNREACHABLE(); |
864 return true; | 926 return true; |
865 } | 927 } |
866 | 928 |
867 | 929 |
868 static bool HandleLibrary(Isolate* isolate, JSONStream* js) { | |
869 if (js->num_arguments() == 1) { | |
870 const Library& lib = | |
871 Library::Handle(isolate->object_store()->root_library()); | |
872 lib.PrintToJSONStream(js, false); | |
873 return true; | |
874 } | |
875 PrintError(js, "Command too long"); | |
876 return true; | |
877 } | |
878 | |
879 | |
880 static bool HandleLibraries(Isolate* isolate, JSONStream* js) { | 930 static bool HandleLibraries(Isolate* isolate, JSONStream* js) { |
881 // TODO(johnmccutchan): Support fields and functions on libraries. | 931 // TODO(johnmccutchan): Support fields and functions on libraries. |
882 REQUIRE_COLLECTION_ID("libraries"); | 932 REQUIRE_COLLECTION_ID("libraries"); |
883 const GrowableObjectArray& libs = | 933 const GrowableObjectArray& libs = |
884 GrowableObjectArray::Handle(isolate->object_store()->libraries()); | 934 GrowableObjectArray::Handle(isolate->object_store()->libraries()); |
885 ASSERT(!libs.IsNull()); | 935 ASSERT(!libs.IsNull()); |
886 intptr_t id = 0; | 936 intptr_t id = 0; |
887 CHECK_COLLECTION_ID_BOUNDS("libraries", libs.Length(), js->GetArgument(1), | 937 CHECK_COLLECTION_ID_BOUNDS("libraries", libs.Length(), js->GetArgument(1), |
888 id, js); | 938 id, js); |
889 Library& lib = Library::Handle(); | 939 Library& lib = Library::Handle(); |
890 lib ^= libs.At(id); | 940 lib ^= libs.At(id); |
891 ASSERT(!lib.IsNull()); | 941 ASSERT(!lib.IsNull()); |
892 lib.PrintToJSONStream(js, false); | 942 lib.PrintToJSONStream(js, false); |
893 return true; | 943 return true; |
894 } | 944 } |
895 | 945 |
896 | 946 |
897 static bool HandleObjects(Isolate* isolate, JSONStream* js) { | 947 static bool HandleObjects(Isolate* isolate, JSONStream* js) { |
898 REQUIRE_COLLECTION_ID("objects"); | 948 REQUIRE_COLLECTION_ID("objects"); |
899 ASSERT(js->num_arguments() >= 2); | 949 ASSERT(js->num_arguments() >= 2); |
950 const char* arg = js->GetArgument(1); | |
951 | |
952 // TODO(turnidge): Handle <optimized out> the same way as other | |
953 // special nulls. | |
954 if (strcmp(arg, "null") == 0 || | |
955 strcmp(arg, "not-initialized") == 0 || | |
956 strcmp(arg, "being-initialized") == 0) { | |
957 Object::null_object().PrintToJSONStream(js, false); | |
958 return true; | |
959 | |
Cutch
2014/01/28 19:32:51
Remove extra blank line.
| |
960 } else if (strcmp(arg, "int") == 0) { | |
961 if (js->num_arguments() < 3) { | |
962 PrintError(js, "expected 3 arguments but found %" Pd "\n", | |
963 js->num_arguments()); | |
964 return true; | |
965 } | |
966 int64_t value = 0; | |
967 if (!OS::StringToInt64(js->GetArgument(2), &value) || | |
968 !Smi::IsValid64(value)) { | |
969 PrintError(js, "integer value too large\n", | |
970 js->num_arguments()); | |
971 return true; | |
972 } | |
973 const Integer& obj = | |
974 Integer::Handle(isolate, Smi::New(static_cast<intptr_t>(value))); | |
975 obj.PrintToJSONStream(js, false); | |
976 return true; | |
977 | |
Cutch
2014/01/28 19:32:51
Remove extra blank line.
| |
978 } else if (strcmp(arg, "bool") == 0) { | |
979 if (js->num_arguments() < 3) { | |
980 PrintError(js, "expected 3 arguments but found %" Pd "\n", | |
981 js->num_arguments()); | |
982 return true; | |
983 } | |
984 const char* value_str = js->GetArgument(2); | |
985 bool value = false; | |
986 if (strcmp(value_str, "false") == 0) { | |
987 value = false; | |
988 } else if (strcmp(value_str, "true") == 0) { | |
989 value = true; | |
990 } else { | |
991 PrintError(js, "expected 'true' or 'false' but found %s\n", value_str); | |
992 return true; | |
993 } | |
994 Bool::Get(value).PrintToJSONStream(js, false); | |
995 return true; | |
996 } | |
997 | |
900 ObjectIdRing* ring = isolate->object_id_ring(); | 998 ObjectIdRing* ring = isolate->object_id_ring(); |
901 ASSERT(ring != NULL); | 999 ASSERT(ring != NULL); |
902 intptr_t id = -1; | 1000 intptr_t id = -1; |
903 if (!GetIntegerId(js->GetArgument(1), &id)) { | 1001 if (!GetIntegerId(arg, &id)) { |
904 Object::null_object().PrintToJSONStream(js, false); | 1002 Object::null_object().PrintToJSONStream(js, false); |
905 return true; | 1003 return true; |
906 } | 1004 } |
907 Object& obj = Object::Handle(ring->GetObjectForId(id)); | 1005 Object& obj = Object::Handle(ring->GetObjectForId(id)); |
908 obj.PrintToJSONStream(js, false); | 1006 obj.PrintToJSONStream(js, false); |
909 return true; | 1007 return true; |
910 } | 1008 } |
911 | 1009 |
912 | 1010 |
913 | 1011 |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1051 | 1149 |
1052 | 1150 |
1053 static bool HandleAllocationProfile(Isolate* isolate, JSONStream* js) { | 1151 static bool HandleAllocationProfile(Isolate* isolate, JSONStream* js) { |
1054 isolate->class_table()->AllocationProfilePrintToJSONStream(js); | 1152 isolate->class_table()->AllocationProfilePrintToJSONStream(js); |
1055 return true; | 1153 return true; |
1056 } | 1154 } |
1057 | 1155 |
1058 | 1156 |
1059 static IsolateMessageHandlerEntry isolate_handlers[] = { | 1157 static IsolateMessageHandlerEntry isolate_handlers[] = { |
1060 { "_echo", HandleIsolateEcho }, | 1158 { "_echo", HandleIsolateEcho }, |
1159 { "", HandleIsolate }, | |
1061 { "allocationprofile", HandleAllocationProfile }, | 1160 { "allocationprofile", HandleAllocationProfile }, |
1062 { "classes", HandleClasses }, | 1161 { "classes", HandleClasses }, |
1063 { "code", HandleCode }, | 1162 { "code", HandleCode }, |
1064 { "coverage", HandleCoverage }, | 1163 { "coverage", HandleCoverage }, |
1065 { "debug", HandleDebug }, | 1164 { "debug", HandleDebug }, |
1066 { "libraries", HandleLibraries }, | 1165 { "libraries", HandleLibraries }, |
1067 { "library", HandleLibrary }, | |
1068 { "name", HandleName }, | |
1069 { "objecthistogram", HandleObjectHistogram}, | 1166 { "objecthistogram", HandleObjectHistogram}, |
1070 { "objects", HandleObjects }, | 1167 { "objects", HandleObjects }, |
1071 { "profile", HandleProfile }, | 1168 { "profile", HandleProfile }, |
1072 { "scripts", HandleScripts }, | 1169 { "scripts", HandleScripts }, |
1073 { "stacktrace", HandleStackTrace }, | 1170 { "stacktrace", HandleStackTrace }, |
1074 }; | 1171 }; |
1075 | 1172 |
1076 | 1173 |
1077 static IsolateMessageHandler FindIsolateMessageHandler(const char* command) { | 1174 static IsolateMessageHandler FindIsolateMessageHandler(const char* command) { |
1078 intptr_t num_message_handlers = sizeof(isolate_handlers) / | 1175 intptr_t num_message_handlers = sizeof(isolate_handlers) / |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1169 for (intptr_t i = 0; i < num_message_handlers; i++) { | 1266 for (intptr_t i = 0; i < num_message_handlers; i++) { |
1170 const RootMessageHandlerEntry& entry = root_handlers[i]; | 1267 const RootMessageHandlerEntry& entry = root_handlers[i]; |
1171 if (!strcmp(command, entry.command)) { | 1268 if (!strcmp(command, entry.command)) { |
1172 return entry.handler; | 1269 return entry.handler; |
1173 } | 1270 } |
1174 } | 1271 } |
1175 return NULL; | 1272 return NULL; |
1176 } | 1273 } |
1177 | 1274 |
1178 } // namespace dart | 1275 } // namespace dart |
OLD | NEW |