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