Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(533)

Side by Side Diff: src/debug/liveedit.cc

Issue 1971683002: [debugger] Refactor LiveEdit function info collection (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Keep infos as MaybeHandle Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/debug/liveedit.h ('k') | src/isolate.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/debug/liveedit.h" 5 #include "src/debug/liveedit.h"
6 6
7 #include "src/ast/scopeinfo.h" 7 #include "src/ast/scopeinfo.h"
8 #include "src/ast/scopes.h" 8 #include "src/ast/scopes.h"
9 #include "src/code-stubs.h" 9 #include "src/code-stubs.h"
10 #include "src/compilation-cache.h" 10 #include "src/compilation-cache.h"
(...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 } 684 }
685 685
686 686
687 Handle<SharedFunctionInfo> SharedInfoWrapper::GetInfo() { 687 Handle<SharedFunctionInfo> SharedInfoWrapper::GetInfo() {
688 Handle<Object> element = this->GetField(kSharedInfoOffset_); 688 Handle<Object> element = this->GetField(kSharedInfoOffset_);
689 Handle<JSValue> value_wrapper = Handle<JSValue>::cast(element); 689 Handle<JSValue> value_wrapper = Handle<JSValue>::cast(element);
690 return UnwrapSharedFunctionInfoFromJSValue(value_wrapper); 690 return UnwrapSharedFunctionInfoFromJSValue(value_wrapper);
691 } 691 }
692 692
693 693
694 class FunctionInfoListener {
695 public:
696 explicit FunctionInfoListener(Isolate* isolate) {
697 current_parent_index_ = -1;
698 len_ = 0;
699 result_ = isolate->factory()->NewJSArray(10);
700 }
701
702 void FunctionStarted(FunctionLiteral* fun) {
703 HandleScope scope(isolate());
704 FunctionInfoWrapper info = FunctionInfoWrapper::Create(isolate());
705 info.SetInitialProperties(fun->name(), fun->start_position(),
706 fun->end_position(), fun->parameter_count(),
707 fun->materialized_literal_count(),
708 current_parent_index_);
709 current_parent_index_ = len_;
710 SetElementSloppy(result_, len_, info.GetJSArray());
711 len_++;
712 }
713
714 void FunctionDone() {
715 HandleScope scope(isolate());
716 FunctionInfoWrapper info = FunctionInfoWrapper::cast(
717 *JSReceiver::GetElement(isolate(), result_, current_parent_index_)
718 .ToHandleChecked());
719 current_parent_index_ = info.GetParentIndex();
720 }
721
722 // Saves full information about a function: its code, its scope info
723 // and a SharedFunctionInfo object.
724 void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope,
725 Zone* zone) {
726 if (!shared->IsSharedFunctionInfo()) {
727 return;
728 }
729 FunctionInfoWrapper info = FunctionInfoWrapper::cast(
730 *JSReceiver::GetElement(isolate(), result_, current_parent_index_)
731 .ToHandleChecked());
732 info.SetFunctionCode(Handle<Code>(shared->code()),
733 Handle<HeapObject>(shared->scope_info()));
734 info.SetSharedFunctionInfo(shared);
735
736 Handle<Object> scope_info_list = SerializeFunctionScope(scope, zone);
737 info.SetFunctionScopeInfo(scope_info_list);
738 }
739
740 Handle<JSArray> GetResult() { return result_; }
741
742 private:
743 Isolate* isolate() const { return result_->GetIsolate(); }
744
745 Handle<Object> SerializeFunctionScope(Scope* scope, Zone* zone) {
746 Handle<JSArray> scope_info_list = isolate()->factory()->NewJSArray(10);
747 int scope_info_length = 0;
748
749 // Saves some description of scope. It stores name and indexes of
750 // variables in the whole scope chain. Null-named slots delimit
751 // scopes of this chain.
752 Scope* current_scope = scope;
753 while (current_scope != NULL) {
754 HandleScope handle_scope(isolate());
755 ZoneList<Variable*> stack_list(current_scope->StackLocalCount(), zone);
756 ZoneList<Variable*> context_list(
757 current_scope->ContextLocalCount(), zone);
758 ZoneList<Variable*> globals_list(current_scope->ContextGlobalCount(),
759 zone);
760 current_scope->CollectStackAndContextLocals(&stack_list, &context_list,
761 &globals_list);
762 context_list.Sort(&Variable::CompareIndex);
763
764 for (int i = 0; i < context_list.length(); i++) {
765 SetElementSloppy(scope_info_list,
766 scope_info_length,
767 context_list[i]->name());
768 scope_info_length++;
769 SetElementSloppy(
770 scope_info_list,
771 scope_info_length,
772 Handle<Smi>(Smi::FromInt(context_list[i]->index()), isolate()));
773 scope_info_length++;
774 }
775 SetElementSloppy(scope_info_list,
776 scope_info_length,
777 Handle<Object>(isolate()->heap()->null_value(),
778 isolate()));
779 scope_info_length++;
780
781 current_scope = current_scope->outer_scope();
782 }
783
784 return scope_info_list;
785 }
786
787 Handle<JSArray> result_;
788 int len_;
789 int current_parent_index_;
790 };
791
792
793 void LiveEdit::InitializeThreadLocal(Debug* debug) { 694 void LiveEdit::InitializeThreadLocal(Debug* debug) {
794 debug->thread_local_.frame_drop_mode_ = LiveEdit::FRAMES_UNTOUCHED; 695 debug->thread_local_.frame_drop_mode_ = LiveEdit::FRAMES_UNTOUCHED;
795 } 696 }
796 697
797 698
798 bool LiveEdit::SetAfterBreakTarget(Debug* debug) { 699 bool LiveEdit::SetAfterBreakTarget(Debug* debug) {
799 Code* code = NULL; 700 Code* code = NULL;
800 Isolate* isolate = debug->isolate_; 701 Isolate* isolate = debug->isolate_;
801 switch (debug->thread_local_.frame_drop_mode_) { 702 switch (debug->thread_local_.frame_drop_mode_) {
802 case FRAMES_UNTOUCHED: 703 case FRAMES_UNTOUCHED:
(...skipping 15 matching lines...) Expand all
818 } 719 }
819 debug->after_break_target_ = code->entry(); 720 debug->after_break_target_ = code->entry();
820 return true; 721 return true;
821 } 722 }
822 723
823 724
824 MaybeHandle<JSArray> LiveEdit::GatherCompileInfo(Handle<Script> script, 725 MaybeHandle<JSArray> LiveEdit::GatherCompileInfo(Handle<Script> script,
825 Handle<String> source) { 726 Handle<String> source) {
826 Isolate* isolate = script->GetIsolate(); 727 Isolate* isolate = script->GetIsolate();
827 728
828 FunctionInfoListener listener(isolate); 729 MaybeHandle<JSArray> infos;
829 Handle<Object> original_source = 730 Handle<Object> original_source =
830 Handle<Object>(script->source(), isolate); 731 Handle<Object>(script->source(), isolate);
831 script->set_source(*source); 732 script->set_source(*source);
832 isolate->set_active_function_info_listener(&listener);
833 733
834 { 734 {
835 // Creating verbose TryCatch from public API is currently the only way to 735 // Creating verbose TryCatch from public API is currently the only way to
836 // force code save location. We do not use this the object directly. 736 // force code save location. We do not use this the object directly.
837 v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate)); 737 v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
838 try_catch.SetVerbose(true); 738 try_catch.SetVerbose(true);
839 739
840 // A logical 'try' section. 740 // A logical 'try' section.
841 Compiler::CompileForLiveEdit(script); 741 infos = Compiler::CompileForLiveEdit(script);
842 } 742 }
843 743
844 // A logical 'catch' section. 744 // A logical 'catch' section.
845 Handle<JSObject> rethrow_exception; 745 Handle<JSObject> rethrow_exception;
846 if (isolate->has_pending_exception()) { 746 if (isolate->has_pending_exception()) {
847 Handle<Object> exception(isolate->pending_exception(), isolate); 747 Handle<Object> exception(isolate->pending_exception(), isolate);
848 MessageLocation message_location = isolate->GetMessageLocation(); 748 MessageLocation message_location = isolate->GetMessageLocation();
849 749
850 isolate->clear_pending_message(); 750 isolate->clear_pending_message();
851 isolate->clear_pending_exception(); 751 isolate->clear_pending_exception();
(...skipping 17 matching lines...) Expand all
869 Object::SetProperty(rethrow_exception, start_pos_key, start_pos, SLOPPY) 769 Object::SetProperty(rethrow_exception, start_pos_key, start_pos, SLOPPY)
870 .Assert(); 770 .Assert();
871 Object::SetProperty(rethrow_exception, end_pos_key, end_pos, SLOPPY) 771 Object::SetProperty(rethrow_exception, end_pos_key, end_pos, SLOPPY)
872 .Assert(); 772 .Assert();
873 Object::SetProperty(rethrow_exception, script_obj_key, script_obj, SLOPPY) 773 Object::SetProperty(rethrow_exception, script_obj_key, script_obj, SLOPPY)
874 .Assert(); 774 .Assert();
875 } 775 }
876 } 776 }
877 777
878 // A logical 'finally' section. 778 // A logical 'finally' section.
879 isolate->set_active_function_info_listener(NULL);
880 script->set_source(*original_source); 779 script->set_source(*original_source);
881 780
882 if (rethrow_exception.is_null()) { 781 if (rethrow_exception.is_null()) {
883 return listener.GetResult(); 782 return infos.ToHandleChecked();
884 } else { 783 } else {
885 return isolate->Throw<JSArray>(rethrow_exception); 784 return isolate->Throw<JSArray>(rethrow_exception);
886 } 785 }
887 } 786 }
888 787
889 788
890 // Visitor that finds all references to a particular code object, 789 // Visitor that finds all references to a particular code object,
891 // including "CODE_TARGET" references in other code objects and replaces 790 // including "CODE_TARGET" references in other code objects and replaces
892 // them on the fly. 791 // them on the fly.
893 class ReplacingVisitor : public ObjectVisitor { 792 class ReplacingVisitor : public ObjectVisitor {
(...skipping 1137 matching lines...) Expand 10 before | Expand all | Expand 10 after
2031 } 1930 }
2032 if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE) { 1931 if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE) {
2033 return "Function is blocked under native code"; 1932 return "Function is blocked under native code";
2034 } 1933 }
2035 if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR) { 1934 if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR) {
2036 return "Function is blocked under a generator activation"; 1935 return "Function is blocked under a generator activation";
2037 } 1936 }
2038 return NULL; 1937 return NULL;
2039 } 1938 }
2040 1939
2041 1940 Handle<JSArray> LiveEditFunctionTracker::Collect(FunctionLiteral* node,
2042 LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate, 1941 Handle<Script> script,
2043 FunctionLiteral* fun) 1942 Zone* zone, Isolate* isolate) {
2044 : isolate_(isolate) { 1943 LiveEditFunctionTracker visitor(script, zone, isolate);
2045 if (isolate_->active_function_info_listener() != NULL) { 1944 visitor.VisitFunctionLiteral(node);
2046 isolate_->active_function_info_listener()->FunctionStarted(fun); 1945 return visitor.result_;
2047 }
2048 } 1946 }
2049 1947
2050 1948 LiveEditFunctionTracker::LiveEditFunctionTracker(Handle<Script> script,
2051 LiveEditFunctionTracker::~LiveEditFunctionTracker() { 1949 Zone* zone, Isolate* isolate)
2052 if (isolate_->active_function_info_listener() != NULL) { 1950 : AstTraversalVisitor(isolate) {
2053 isolate_->active_function_info_listener()->FunctionDone(); 1951 current_parent_index_ = -1;
2054 } 1952 isolate_ = isolate;
1953 len_ = 0;
1954 result_ = isolate->factory()->NewJSArray(10);
1955 script_ = script;
1956 zone_ = zone;
2055 } 1957 }
2056 1958
1959 void LiveEditFunctionTracker::VisitFunctionLiteral(FunctionLiteral* node) {
1960 Scope* scope = node->scope();
2057 1961
2058 void LiveEditFunctionTracker::RecordFunctionInfo( 1962 // FunctionStarted is called in pre-order.
2059 Handle<SharedFunctionInfo> info, FunctionLiteral* lit, 1963 FunctionStarted(node);
2060 Zone* zone) { 1964
2061 if (isolate_->active_function_info_listener() != NULL) { 1965 VisitDeclarations(scope->declarations());
2062 isolate_->active_function_info_listener()->FunctionInfo(info, lit->scope(), 1966 VisitStatements(node->body());
2063 zone); 1967
2064 } 1968 // FunctionDone are called in post-order.
1969 // TODO(jgruber): If required, replace the (linear cost)
1970 // FindSharedFunctionInfo call with a more efficient implementation.
1971 Handle<SharedFunctionInfo> info =
1972 script_->FindSharedFunctionInfo(node).ToHandleChecked();
1973 FunctionDone(info, scope);
2065 } 1974 }
2066 1975
1976 void LiveEditFunctionTracker::FunctionStarted(FunctionLiteral* fun) {
1977 HandleScope handle_scope(isolate_);
1978 FunctionInfoWrapper info = FunctionInfoWrapper::Create(isolate_);
1979 info.SetInitialProperties(fun->name(), fun->start_position(),
1980 fun->end_position(), fun->parameter_count(),
1981 fun->materialized_literal_count(),
1982 current_parent_index_);
1983 current_parent_index_ = len_;
1984 SetElementSloppy(result_, len_, info.GetJSArray());
1985 len_++;
1986 }
2067 1987
2068 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) { 1988 // Saves full information about a function: its code, its scope info
2069 return isolate->active_function_info_listener() != NULL; 1989 // and a SharedFunctionInfo object.
1990 void LiveEditFunctionTracker::FunctionDone(Handle<SharedFunctionInfo> shared,
1991 Scope* scope) {
1992 HandleScope handle_scope(isolate_);
1993 FunctionInfoWrapper info = FunctionInfoWrapper::cast(
1994 *JSReceiver::GetElement(isolate_, result_, current_parent_index_)
1995 .ToHandleChecked());
1996 info.SetFunctionCode(Handle<Code>(shared->code()),
1997 Handle<HeapObject>(shared->scope_info()));
1998 info.SetSharedFunctionInfo(shared);
1999
2000 Handle<Object> scope_info_list = SerializeFunctionScope(scope);
2001 info.SetFunctionScopeInfo(scope_info_list);
2002
2003 current_parent_index_ = info.GetParentIndex();
2004 }
2005
2006 Handle<Object> LiveEditFunctionTracker::SerializeFunctionScope(Scope* scope) {
2007 Handle<JSArray> scope_info_list = isolate_->factory()->NewJSArray(10);
2008 int scope_info_length = 0;
2009
2010 // Saves some description of scope. It stores name and indexes of
2011 // variables in the whole scope chain. Null-named slots delimit
2012 // scopes of this chain.
2013 Scope* current_scope = scope;
2014 while (current_scope != NULL) {
2015 HandleScope handle_scope(isolate_);
2016 ZoneList<Variable*> stack_list(current_scope->StackLocalCount(), zone_);
2017 ZoneList<Variable*> context_list(current_scope->ContextLocalCount(), zone_);
2018 ZoneList<Variable*> globals_list(current_scope->ContextGlobalCount(),
2019 zone_);
2020 current_scope->CollectStackAndContextLocals(&stack_list, &context_list,
2021 &globals_list);
2022 context_list.Sort(&Variable::CompareIndex);
2023
2024 for (int i = 0; i < context_list.length(); i++) {
2025 SetElementSloppy(scope_info_list, scope_info_length,
2026 context_list[i]->name());
2027 scope_info_length++;
2028 SetElementSloppy(
2029 scope_info_list, scope_info_length,
2030 Handle<Smi>(Smi::FromInt(context_list[i]->index()), isolate_));
2031 scope_info_length++;
2032 }
2033 SetElementSloppy(scope_info_list, scope_info_length,
2034 Handle<Object>(isolate_->heap()->null_value(), isolate_));
2035 scope_info_length++;
2036
2037 current_scope = current_scope->outer_scope();
2038 }
2039
2040 return scope_info_list;
2070 } 2041 }
2071 2042
2072 } // namespace internal 2043 } // namespace internal
2073 } // namespace v8 2044 } // namespace v8
OLDNEW
« no previous file with comments | « src/debug/liveedit.h ('k') | src/isolate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698