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/isolate.h" | 5 #include "vm/isolate.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
| 9 #include "platform/json.h" |
9 #include "lib/mirrors.h" | 10 #include "lib/mirrors.h" |
10 #include "vm/code_observers.h" | 11 #include "vm/code_observers.h" |
11 #include "vm/compiler_stats.h" | 12 #include "vm/compiler_stats.h" |
12 #include "vm/dart_api_state.h" | 13 #include "vm/dart_api_state.h" |
13 #include "vm/dart_entry.h" | 14 #include "vm/dart_entry.h" |
14 #include "vm/debugger.h" | 15 #include "vm/debugger.h" |
15 #include "vm/heap.h" | 16 #include "vm/heap.h" |
16 #include "vm/message_handler.h" | 17 #include "vm/message_handler.h" |
17 #include "vm/object_store.h" | 18 #include "vm/object_store.h" |
18 #include "vm/parser.h" | 19 #include "vm/parser.h" |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 stack_limit_(0), | 336 stack_limit_(0), |
336 saved_stack_limit_(0), | 337 saved_stack_limit_(0), |
337 message_handler_(NULL), | 338 message_handler_(NULL), |
338 spawn_data_(0), | 339 spawn_data_(0), |
339 gc_prologue_callbacks_(), | 340 gc_prologue_callbacks_(), |
340 gc_epilogue_callbacks_(), | 341 gc_epilogue_callbacks_(), |
341 deopt_cpu_registers_copy_(NULL), | 342 deopt_cpu_registers_copy_(NULL), |
342 deopt_fpu_registers_copy_(NULL), | 343 deopt_fpu_registers_copy_(NULL), |
343 deopt_frame_copy_(NULL), | 344 deopt_frame_copy_(NULL), |
344 deopt_frame_copy_size_(0), | 345 deopt_frame_copy_size_(0), |
345 deferred_objects_(NULL) { | 346 deferred_objects_(NULL), |
| 347 stacktrace_(NULL), |
| 348 stack_frame_index_(-1) { |
346 } | 349 } |
347 | 350 |
348 | 351 |
349 Isolate::~Isolate() { | 352 Isolate::~Isolate() { |
350 delete [] name_; | 353 delete [] name_; |
351 delete heap_; | 354 delete heap_; |
352 delete object_store_; | 355 delete object_store_; |
353 delete api_state_; | 356 delete api_state_; |
354 delete stub_code_; | 357 delete stub_code_; |
355 delete debugger_; | 358 delete debugger_; |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 | 631 |
629 | 632 |
630 Dart_IsolateCreateCallback Isolate::create_callback_ = NULL; | 633 Dart_IsolateCreateCallback Isolate::create_callback_ = NULL; |
631 Dart_IsolateInterruptCallback Isolate::interrupt_callback_ = NULL; | 634 Dart_IsolateInterruptCallback Isolate::interrupt_callback_ = NULL; |
632 Dart_IsolateUnhandledExceptionCallback | 635 Dart_IsolateUnhandledExceptionCallback |
633 Isolate::unhandled_exception_callback_ = NULL; | 636 Isolate::unhandled_exception_callback_ = NULL; |
634 Dart_IsolateShutdownCallback Isolate::shutdown_callback_ = NULL; | 637 Dart_IsolateShutdownCallback Isolate::shutdown_callback_ = NULL; |
635 Dart_FileOpenCallback Isolate::file_open_callback_ = NULL; | 638 Dart_FileOpenCallback Isolate::file_open_callback_ = NULL; |
636 Dart_FileWriteCallback Isolate::file_write_callback_ = NULL; | 639 Dart_FileWriteCallback Isolate::file_write_callback_ = NULL; |
637 Dart_FileCloseCallback Isolate::file_close_callback_ = NULL; | 640 Dart_FileCloseCallback Isolate::file_close_callback_ = NULL; |
| 641 Dart_IsolateInterruptCallback Isolate::vmstats_callback_ = NULL; |
638 | 642 |
639 | 643 |
640 void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor, | 644 void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor, |
641 bool visit_prologue_weak_handles, | 645 bool visit_prologue_weak_handles, |
642 bool validate_frames) { | 646 bool validate_frames) { |
643 ASSERT(visitor != NULL); | 647 ASSERT(visitor != NULL); |
644 | 648 |
645 // Visit objects in the object store. | 649 // Visit objects in the object store. |
646 object_store()->VisitObjectPointers(visitor); | 650 object_store()->VisitObjectPointers(visitor); |
647 | 651 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
682 | 686 |
683 | 687 |
684 void Isolate::VisitWeakPersistentHandles(HandleVisitor* visitor, | 688 void Isolate::VisitWeakPersistentHandles(HandleVisitor* visitor, |
685 bool visit_prologue_weak_handles) { | 689 bool visit_prologue_weak_handles) { |
686 if (api_state() != NULL) { | 690 if (api_state() != NULL) { |
687 api_state()->VisitWeakHandles(visitor, visit_prologue_weak_handles); | 691 api_state()->VisitWeakHandles(visitor, visit_prologue_weak_handles); |
688 } | 692 } |
689 } | 693 } |
690 | 694 |
691 | 695 |
| 696 static Monitor* status_sync = NULL; |
| 697 |
| 698 |
| 699 bool Isolate::FetchStacktrace() { |
| 700 Isolate* isolate = Isolate::Current(); |
| 701 MonitorLocker ml(status_sync); |
| 702 DebuggerStackTrace* stack = Debugger::CollectStackTrace(); |
| 703 TextBuffer buffer(256); |
| 704 buffer.Printf("{ \"handle\": \"0x%"Px64"\", \"stacktrace\": [ ", |
| 705 reinterpret_cast<int64_t>(isolate)); |
| 706 intptr_t n_frames = stack->Length(); |
| 707 String& url = String::Handle(); |
| 708 String& function = String::Handle(); |
| 709 for (int i = 0; i < n_frames; i++) { |
| 710 if (i > 0) { |
| 711 buffer.Printf(", "); |
| 712 } |
| 713 ActivationFrame* frame = stack->ActivationFrameAt(i); |
| 714 url ^= frame->SourceUrl(); |
| 715 function ^= frame->function().UserVisibleName(); |
| 716 buffer.Printf("{ \"url\": \"%s\", ", url.ToCString()); |
| 717 buffer.Printf("\"line\": %"Pd", ", frame->LineNumber()); |
| 718 buffer.Printf("\"function\": \"%s\", ", function.ToCString()); |
| 719 |
| 720 const Code& code = frame->code(); |
| 721 buffer.Printf("\"code\": { "); |
| 722 buffer.Printf("\"alive\": %s, ", code.is_alive() ? "false" : "true"); |
| 723 buffer.Printf("\"optimized\": %s }}", |
| 724 code.is_optimized() ? "false" : "true"); |
| 725 } |
| 726 buffer.Printf("]}"); |
| 727 isolate->stacktrace_ = strndup(buffer.buf(), buffer.length()); |
| 728 ml.Notify(); |
| 729 return true; |
| 730 } |
| 731 |
| 732 |
| 733 bool Isolate::FetchStackFrameDetails() { |
| 734 Isolate* isolate = Isolate::Current(); |
| 735 ASSERT(isolate->stack_frame_index_ >= 0); |
| 736 MonitorLocker ml(status_sync); |
| 737 DebuggerStackTrace* stack = Debugger::CollectStackTrace(); |
| 738 intptr_t frame_index = isolate->stack_frame_index_; |
| 739 if (frame_index >= stack->Length()) { |
| 740 // Frame no longer available. |
| 741 return NULL; |
| 742 } |
| 743 ActivationFrame* frame = stack->ActivationFrameAt(frame_index); |
| 744 TextBuffer buffer(256); |
| 745 buffer.Printf("{ \"handle\": \"0x%"Px64"\", \"frame_index\": %"Pd", ", |
| 746 reinterpret_cast<int64_t>(isolate), frame_index); |
| 747 |
| 748 const Code& code = frame->code(); |
| 749 buffer.Printf("\"code\": { \"size\": %"Pd", ", code.Size()); |
| 750 buffer.Printf("\"alive\": %s, ", code.is_alive() ? "false" : "true"); |
| 751 buffer.Printf("\"optimized\": %s }, ", |
| 752 code.is_optimized() ? "false" : "true"); |
| 753 // TODO(tball): add compilation stats (time, etc.), when available. |
| 754 |
| 755 buffer.Printf("\"local_vars\": [ "); |
| 756 intptr_t n_local_vars = frame->NumLocalVariables(); |
| 757 String& var_name = String::Handle(); |
| 758 Instance& value = Instance::Handle(); |
| 759 for (int i = 0; i < n_local_vars; i++) { |
| 760 if (i > 0) { |
| 761 buffer.Printf(", "); |
| 762 } |
| 763 intptr_t token_pos, end_pos; |
| 764 frame->VariableAt(i, &var_name, &token_pos, &end_pos, &value); |
| 765 buffer.Printf( |
| 766 "{ \"name\": \"%s\", \"pos\": %"Pd", \"end_pos\": %"Pd", " |
| 767 "\"value\": \"%s\" }", |
| 768 var_name.ToCString(), token_pos, end_pos, value.ToCString()); |
| 769 } |
| 770 buffer.Printf("]}"); |
| 771 isolate->stacktrace_ = strndup(buffer.buf(), buffer.length()); |
| 772 ml.Notify(); |
| 773 return true; |
| 774 } |
| 775 |
| 776 |
| 777 char* Isolate::DoStacktraceInterrupt(Dart_IsolateInterruptCallback cb) { |
| 778 ASSERT(stacktrace_ == NULL); |
| 779 SetVmStatsCallback(cb); |
| 780 if (status_sync == NULL) { |
| 781 status_sync = new Monitor(); |
| 782 } |
| 783 ScheduleInterrupts(Isolate::kVmStatusInterrupt); |
| 784 { |
| 785 MonitorLocker ml(status_sync); |
| 786 if (stacktrace_ == NULL) { // It may already be available. |
| 787 ml.Wait(); |
| 788 } |
| 789 } |
| 790 SetVmStatsCallback(NULL); |
| 791 ASSERT(stacktrace_ != NULL); |
| 792 // result is freed by VmStats::WebServer(). |
| 793 char* result = stacktrace_; |
| 794 stacktrace_ = NULL; |
| 795 return result; |
| 796 } |
| 797 |
| 798 |
| 799 char* Isolate::GetStatusStacktrace() { |
| 800 return DoStacktraceInterrupt(&FetchStacktrace); |
| 801 } |
| 802 |
| 803 char* Isolate::GetStatusStackFrame(intptr_t index) { |
| 804 ASSERT(index >= 0); |
| 805 stack_frame_index_ = index; |
| 806 char* result = DoStacktraceInterrupt(&FetchStackFrameDetails); |
| 807 stack_frame_index_ = -1; |
| 808 return result; |
| 809 } |
| 810 |
| 811 |
| 812 // Returns the isolate's general detail information. |
| 813 char* Isolate::GetStatusDetails() { |
| 814 const char* format = "{\n" |
| 815 " \"handle\": \"0x%"Px64"\",\n" |
| 816 " \"name\": \"%s\",\n" |
| 817 " \"port\": %"Pd",\n" |
| 818 " \"starttime\": %"Pd",\n" |
| 819 " \"stacklimit\": %"Pd",\n" |
| 820 " \"newspace\": {\n" |
| 821 " \"used\": %"Pd",\n" |
| 822 " \"capacity\": %"Pd"\n" |
| 823 " },\n" |
| 824 " \"oldspace\": {\n" |
| 825 " \"used\": %"Pd",\n" |
| 826 " \"capacity\": %"Pd"\n" |
| 827 " }\n" |
| 828 "}"; |
| 829 char buffer[300]; |
| 830 int64_t address = reinterpret_cast<int64_t>(this); |
| 831 int n = OS::SNPrint(buffer, 300, format, address, name(), main_port(), |
| 832 (start_time() / 1000L), saved_stack_limit(), |
| 833 heap()->Used(Heap::kNew) / KB, |
| 834 heap()->Capacity(Heap::kNew) / KB, |
| 835 heap()->Used(Heap::kOld) / KB, |
| 836 heap()->Capacity(Heap::kOld) / KB); |
| 837 ASSERT(n < 300); |
| 838 return strdup(buffer); |
| 839 } |
| 840 |
| 841 |
692 char* Isolate::GetStatus(const char* request) { | 842 char* Isolate::GetStatus(const char* request) { |
693 char* p = const_cast<char*>(request); | 843 char* p = const_cast<char*>(request); |
694 const char* service_type = "/isolate/"; | 844 const char* service_type = "/isolate/"; |
695 ASSERT(strncmp(p, service_type, strlen(service_type)) == 0); | 845 ASSERT(!strncmp(p, service_type, strlen(service_type))); |
696 p += strlen(service_type); | 846 p += strlen(service_type); |
697 | 847 |
698 // Extract isolate handle. | 848 // Extract isolate handle. |
699 int64_t addr; | 849 int64_t addr; |
700 OS::StringToInt64(p, &addr); | 850 OS::StringToInt64(p, &addr); |
| 851 // TODO(tball): add validity check when issue 9600 is fixed. |
701 Isolate* isolate = reinterpret_cast<Isolate*>(addr); | 852 Isolate* isolate = reinterpret_cast<Isolate*>(addr); |
702 Heap* heap = isolate->heap(); | 853 p += strcspn(p, "/"); |
703 | 854 |
704 char buffer[256]; | 855 // Query "/isolate/<handle>". |
705 int64_t port = isolate->main_port(); | 856 if (strlen(p) == 0) { |
706 int64_t start_time = (isolate->start_time() / 1000L); | 857 return isolate->GetStatusDetails(); |
707 #if defined(TARGET_ARCH_X64) | 858 } |
708 const char* format = "{\n" | 859 |
709 " \"name\": \"%s\",\n" | 860 // Query "/isolate/<handle>/stacktrace" |
710 " \"port\": %ld,\n" | 861 if (!strcmp(p, "/stacktrace")) { |
711 " \"starttime\": %ld,\n" | 862 return isolate->GetStatusStacktrace(); |
712 " \"stacklimit\": %ld,\n" | 863 } |
713 " \"newspace\": {\n" | 864 |
714 " \"used\": %ld,\n" | 865 // Query "/isolate/<handle>/stacktrace/<frame-index>" |
715 " \"capacity\": %ld\n" | 866 const char* stacktrace_query = "/stacktrace/"; |
716 " },\n" | 867 int64_t frame_index = -1; |
717 " \"oldspace\": {\n" | 868 if (!strncmp(p, stacktrace_query, strlen(stacktrace_query))) { |
718 " \"used\": %ld,\n" | 869 p += strlen(stacktrace_query); |
719 " \"capacity\": %ld\n" | 870 OS::StringToInt64(p, &frame_index); |
720 " }\n" | 871 if (frame_index >= 0) { |
721 "}"; | 872 return isolate->GetStatusStackFrame(frame_index); |
722 #else | 873 } |
723 const char* format = "{\n" | 874 } |
724 " \"name\": \"%s\",\n" | 875 |
725 " \"port\": %lld,\n" | 876 // TODO(tball): "/isolate/<handle>/stacktrace/<frame-index>"/disassemble" |
726 " \"starttime\": %lld,\n" | 877 |
727 " \"stacklimit\": %d,\n" | 878 return NULL; // Unimplemented query. |
728 " \"newspace\": {\n" | |
729 " \"used\": %d,\n" | |
730 " \"capacity\": %d\n" | |
731 " },\n" | |
732 " \"oldspace\": {\n" | |
733 " \"used\": %d,\n" | |
734 " \"capacity\": %d\n" | |
735 " }\n" | |
736 "}"; | |
737 #endif | |
738 int n = OS::SNPrint(buffer, 256, format, isolate->name(), port, start_time, | |
739 isolate->saved_stack_limit(), | |
740 heap->Used(Heap::kNew) / KB, | |
741 heap->Capacity(Heap::kNew) / KB, | |
742 heap->Used(Heap::kOld) / KB, | |
743 heap->Capacity(Heap::kOld) / KB); | |
744 ASSERT(n < 256); | |
745 return strdup(buffer); | |
746 } | 879 } |
747 | 880 |
748 } // namespace dart | 881 } // namespace dart |
OLD | NEW |