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/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; | |
|
siva
2013/04/01 22:07:55
= NULL;
Tom Ball
2013/04/02 16:49:16
Done.
| |
| 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\": %d, ", 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()); | |
|
siva
2013/04/01 22:07:55
I guess with a little tweak to the implementation
Tom Ball
2013/04/02 16:49:16
Agreed.
| |
| 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\": %d, \"end_pos\": %d, " | |
| 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 ml.Wait(); | |
|
siva
2013/04/01 22:07:55
I think you need to test a condition in a while lo
Tom Ball
2013/04/02 16:49:16
Added a test that stacktrace_ is still NULL before
| |
| 786 } | |
| 787 SetVmStatsCallback(NULL); | |
| 788 ASSERT(stacktrace_ != NULL); | |
| 789 // result is freed by VmStats::WebServer(). | |
| 790 char* result = stacktrace_; | |
| 791 stacktrace_ = NULL; | |
| 792 return result; | |
| 793 } | |
| 794 | |
| 795 | |
| 796 char* Isolate::GetStatusStacktrace() { | |
| 797 return DoStacktraceInterrupt(&FetchStacktrace); | |
| 798 } | |
| 799 | |
| 800 char* Isolate::GetStatusStackFrame(intptr_t index) { | |
| 801 ASSERT(index >= 0); | |
| 802 stack_frame_index_ = index; | |
| 803 char* result = DoStacktraceInterrupt(&FetchStackFrameDetails); | |
| 804 stack_frame_index_ = -1; | |
| 805 return result; | |
| 806 } | |
| 807 | |
| 808 | |
| 809 // Returns the isolate's general detail information. | |
| 810 char* Isolate::GetStatusDetails() { | |
| 811 const char* format = "{\n" | |
| 812 " \"handle\": \"0x%"Px64"\",\n" | |
| 813 " \"name\": \"%s\",\n" | |
| 814 " \"port\": %"Pd",\n" | |
| 815 " \"starttime\": %"Pd",\n" | |
| 816 " \"stacklimit\": %"Pd",\n" | |
| 817 " \"newspace\": {\n" | |
| 818 " \"used\": %"Pd",\n" | |
| 819 " \"capacity\": %"Pd"\n" | |
| 820 " },\n" | |
| 821 " \"oldspace\": {\n" | |
| 822 " \"used\": %"Pd",\n" | |
| 823 " \"capacity\": %"Pd"\n" | |
| 824 " }\n" | |
| 825 "}"; | |
| 826 char buffer[300]; | |
| 827 int64_t address = reinterpret_cast<int64_t>(this); | |
| 828 int n = OS::SNPrint(buffer, 300, format, address, name(), main_port(), | |
| 829 (start_time() / 1000L), saved_stack_limit(), | |
| 830 heap()->Used(Heap::kNew) / KB, | |
| 831 heap()->Capacity(Heap::kNew) / KB, | |
| 832 heap()->Used(Heap::kOld) / KB, | |
| 833 heap()->Capacity(Heap::kOld) / KB); | |
| 834 ASSERT(n < 300); | |
| 835 return strdup(buffer); | |
| 836 } | |
| 837 | |
| 838 | |
| 692 char* Isolate::GetStatus(const char* request) { | 839 char* Isolate::GetStatus(const char* request) { |
| 693 char* p = const_cast<char*>(request); | 840 char* p = const_cast<char*>(request); |
| 694 const char* service_type = "/isolate/"; | 841 const char* service_type = "/isolate/"; |
| 695 ASSERT(strncmp(p, service_type, strlen(service_type)) == 0); | 842 ASSERT(!strncmp(p, service_type, strlen(service_type))); |
| 696 p += strlen(service_type); | 843 p += strlen(service_type); |
| 697 | 844 |
| 698 // Extract isolate handle. | 845 // Extract isolate handle. |
| 699 int64_t addr; | 846 int64_t addr; |
| 700 OS::StringToInt64(p, &addr); | 847 OS::StringToInt64(p, &addr); |
| 701 Isolate* isolate = reinterpret_cast<Isolate*>(addr); | 848 Isolate* isolate = reinterpret_cast<Isolate*>(addr); |
|
siva
2013/04/01 22:07:55
Is there a way to assert that this addr is a valid
Tom Ball
2013/04/02 16:49:16
File issue 9600, and added TODO.
| |
| 702 Heap* heap = isolate->heap(); | 849 p += strcspn(p, "/"); |
| 703 | 850 |
| 704 char buffer[256]; | 851 // Query "/isolate/<handle>". |
| 705 int64_t port = isolate->main_port(); | 852 if (strlen(p) == 0) { |
| 706 int64_t start_time = (isolate->start_time() / 1000L); | 853 return isolate->GetStatusDetails(); |
| 707 #if defined(TARGET_ARCH_X64) | 854 } |
| 708 const char* format = "{\n" | 855 |
| 709 " \"name\": \"%s\",\n" | 856 // Query "/isolate/<handle>/stacktrace" |
| 710 " \"port\": %ld,\n" | 857 if (!strcmp(p, "/stacktrace")) { |
| 711 " \"starttime\": %ld,\n" | 858 return isolate->GetStatusStacktrace(); |
| 712 " \"stacklimit\": %ld,\n" | 859 } |
| 713 " \"newspace\": {\n" | 860 |
| 714 " \"used\": %ld,\n" | 861 // Query "/isolate/<handle>/stacktrace/<frame-index>" |
| 715 " \"capacity\": %ld\n" | 862 const char* stacktrace_query = "/stacktrace/"; |
| 716 " },\n" | 863 int64_t frame_index = -1; |
| 717 " \"oldspace\": {\n" | 864 if (!strncmp(p, stacktrace_query, strlen(stacktrace_query))) { |
| 718 " \"used\": %ld,\n" | 865 p += strlen(stacktrace_query); |
| 719 " \"capacity\": %ld\n" | 866 OS::StringToInt64(p, &frame_index); |
| 720 " }\n" | 867 if (frame_index >= 0) { |
| 721 "}"; | 868 return isolate->GetStatusStackFrame(frame_index); |
| 722 #else | 869 } |
| 723 const char* format = "{\n" | 870 } |
| 724 " \"name\": \"%s\",\n" | 871 |
| 725 " \"port\": %lld,\n" | 872 // TODO(tball): "/isolate/<handle>/stacktrace/<frame-index>"/disassemble" |
| 726 " \"starttime\": %lld,\n" | 873 |
| 727 " \"stacklimit\": %d,\n" | 874 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 } | 875 } |
| 747 | 876 |
| 748 } // namespace dart | 877 } // namespace dart |
| OLD | NEW |