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