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

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: Return MaybeHandle from CompileForLiveEdit 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 670 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 } 681 }
682 682
683 683
684 Handle<SharedFunctionInfo> SharedInfoWrapper::GetInfo() { 684 Handle<SharedFunctionInfo> SharedInfoWrapper::GetInfo() {
685 Handle<Object> element = this->GetField(kSharedInfoOffset_); 685 Handle<Object> element = this->GetField(kSharedInfoOffset_);
686 Handle<JSValue> value_wrapper = Handle<JSValue>::cast(element); 686 Handle<JSValue> value_wrapper = Handle<JSValue>::cast(element);
687 return UnwrapSharedFunctionInfoFromJSValue(value_wrapper); 687 return UnwrapSharedFunctionInfoFromJSValue(value_wrapper);
688 } 688 }
689 689
690 690
691 class FunctionInfoListener {
692 public:
693 explicit FunctionInfoListener(Isolate* isolate) {
694 current_parent_index_ = -1;
695 len_ = 0;
696 result_ = isolate->factory()->NewJSArray(10);
697 }
698
699 void FunctionStarted(FunctionLiteral* fun) {
700 HandleScope scope(isolate());
701 FunctionInfoWrapper info = FunctionInfoWrapper::Create(isolate());
702 info.SetInitialProperties(fun->name(), fun->start_position(),
703 fun->end_position(), fun->parameter_count(),
704 fun->materialized_literal_count(),
705 current_parent_index_);
706 current_parent_index_ = len_;
707 SetElementSloppy(result_, len_, info.GetJSArray());
708 len_++;
709 }
710
711 void FunctionDone() {
712 HandleScope scope(isolate());
713 FunctionInfoWrapper info = FunctionInfoWrapper::cast(
714 *JSReceiver::GetElement(isolate(), result_, current_parent_index_)
715 .ToHandleChecked());
716 current_parent_index_ = info.GetParentIndex();
717 }
718
719 // Saves full information about a function: its code, its scope info
720 // and a SharedFunctionInfo object.
721 void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope,
722 Zone* zone) {
723 if (!shared->IsSharedFunctionInfo()) {
724 return;
725 }
726 FunctionInfoWrapper info = FunctionInfoWrapper::cast(
727 *JSReceiver::GetElement(isolate(), result_, current_parent_index_)
728 .ToHandleChecked());
729 info.SetFunctionCode(Handle<Code>(shared->code()),
730 Handle<HeapObject>(shared->scope_info()));
731 info.SetSharedFunctionInfo(shared);
732
733 Handle<Object> scope_info_list = SerializeFunctionScope(scope, zone);
734 info.SetFunctionScopeInfo(scope_info_list);
735 }
736
737 Handle<JSArray> GetResult() { return result_; }
738
739 private:
740 Isolate* isolate() const { return result_->GetIsolate(); }
741
742 Handle<Object> SerializeFunctionScope(Scope* scope, Zone* zone) {
743 Handle<JSArray> scope_info_list = isolate()->factory()->NewJSArray(10);
744 int scope_info_length = 0;
745
746 // Saves some description of scope. It stores name and indexes of
747 // variables in the whole scope chain. Null-named slots delimit
748 // scopes of this chain.
749 Scope* current_scope = scope;
750 while (current_scope != NULL) {
751 HandleScope handle_scope(isolate());
752 ZoneList<Variable*> stack_list(current_scope->StackLocalCount(), zone);
753 ZoneList<Variable*> context_list(
754 current_scope->ContextLocalCount(), zone);
755 ZoneList<Variable*> globals_list(current_scope->ContextGlobalCount(),
756 zone);
757 current_scope->CollectStackAndContextLocals(&stack_list, &context_list,
758 &globals_list);
759 context_list.Sort(&Variable::CompareIndex);
760
761 for (int i = 0; i < context_list.length(); i++) {
762 SetElementSloppy(scope_info_list,
763 scope_info_length,
764 context_list[i]->name());
765 scope_info_length++;
766 SetElementSloppy(
767 scope_info_list,
768 scope_info_length,
769 Handle<Smi>(Smi::FromInt(context_list[i]->index()), isolate()));
770 scope_info_length++;
771 }
772 SetElementSloppy(scope_info_list,
773 scope_info_length,
774 Handle<Object>(isolate()->heap()->null_value(),
775 isolate()));
776 scope_info_length++;
777
778 current_scope = current_scope->outer_scope();
779 }
780
781 return scope_info_list;
782 }
783
784 Handle<JSArray> result_;
785 int len_;
786 int current_parent_index_;
787 };
788
789
790 void LiveEdit::InitializeThreadLocal(Debug* debug) { 691 void LiveEdit::InitializeThreadLocal(Debug* debug) {
791 debug->thread_local_.frame_drop_mode_ = LiveEdit::FRAMES_UNTOUCHED; 692 debug->thread_local_.frame_drop_mode_ = LiveEdit::FRAMES_UNTOUCHED;
792 } 693 }
793 694
794 695
795 bool LiveEdit::SetAfterBreakTarget(Debug* debug) { 696 bool LiveEdit::SetAfterBreakTarget(Debug* debug) {
796 Code* code = NULL; 697 Code* code = NULL;
797 Isolate* isolate = debug->isolate_; 698 Isolate* isolate = debug->isolate_;
798 switch (debug->thread_local_.frame_drop_mode_) { 699 switch (debug->thread_local_.frame_drop_mode_) {
799 case FRAMES_UNTOUCHED: 700 case FRAMES_UNTOUCHED:
(...skipping 15 matching lines...) Expand all
815 } 716 }
816 debug->after_break_target_ = code->entry(); 717 debug->after_break_target_ = code->entry();
817 return true; 718 return true;
818 } 719 }
819 720
820 721
821 MaybeHandle<JSArray> LiveEdit::GatherCompileInfo(Handle<Script> script, 722 MaybeHandle<JSArray> LiveEdit::GatherCompileInfo(Handle<Script> script,
822 Handle<String> source) { 723 Handle<String> source) {
823 Isolate* isolate = script->GetIsolate(); 724 Isolate* isolate = script->GetIsolate();
824 725
825 FunctionInfoListener listener(isolate); 726 Handle<JSArray> infos;
826 Handle<Object> original_source = 727 Handle<Object> original_source =
827 Handle<Object>(script->source(), isolate); 728 Handle<Object>(script->source(), isolate);
828 script->set_source(*source); 729 script->set_source(*source);
829 isolate->set_active_function_info_listener(&listener);
830 730
831 { 731 {
832 // Creating verbose TryCatch from public API is currently the only way to 732 // Creating verbose TryCatch from public API is currently the only way to
833 // force code save location. We do not use this the object directly. 733 // force code save location. We do not use this the object directly.
834 v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate)); 734 v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
835 try_catch.SetVerbose(true); 735 try_catch.SetVerbose(true);
836 736
837 // A logical 'try' section. 737 // A logical 'try' section.
838 Compiler::CompileForLiveEdit(script); 738 Compiler::CompileForLiveEdit(script).ToHandle(&infos);
Yang 2016/05/13 08:50:26 Or we could just keep infos as a MaybeHandle.
839 } 739 }
840 740
841 // A logical 'catch' section. 741 // A logical 'catch' section.
842 Handle<JSObject> rethrow_exception; 742 Handle<JSObject> rethrow_exception;
843 if (isolate->has_pending_exception()) { 743 if (isolate->has_pending_exception()) {
844 Handle<Object> exception(isolate->pending_exception(), isolate); 744 Handle<Object> exception(isolate->pending_exception(), isolate);
845 MessageLocation message_location = isolate->GetMessageLocation(); 745 MessageLocation message_location = isolate->GetMessageLocation();
846 746
847 isolate->clear_pending_message(); 747 isolate->clear_pending_message();
848 isolate->clear_pending_exception(); 748 isolate->clear_pending_exception();
(...skipping 17 matching lines...) Expand all
866 Object::SetProperty(rethrow_exception, start_pos_key, start_pos, SLOPPY) 766 Object::SetProperty(rethrow_exception, start_pos_key, start_pos, SLOPPY)
867 .Assert(); 767 .Assert();
868 Object::SetProperty(rethrow_exception, end_pos_key, end_pos, SLOPPY) 768 Object::SetProperty(rethrow_exception, end_pos_key, end_pos, SLOPPY)
869 .Assert(); 769 .Assert();
870 Object::SetProperty(rethrow_exception, script_obj_key, script_obj, SLOPPY) 770 Object::SetProperty(rethrow_exception, script_obj_key, script_obj, SLOPPY)
871 .Assert(); 771 .Assert();
872 } 772 }
873 } 773 }
874 774
875 // A logical 'finally' section. 775 // A logical 'finally' section.
876 isolate->set_active_function_info_listener(NULL);
877 script->set_source(*original_source); 776 script->set_source(*original_source);
878 777
879 if (rethrow_exception.is_null()) { 778 if (rethrow_exception.is_null()) {
880 return listener.GetResult(); 779 return infos;
881 } else { 780 } else {
882 return isolate->Throw<JSArray>(rethrow_exception); 781 return isolate->Throw<JSArray>(rethrow_exception);
883 } 782 }
884 } 783 }
885 784
886 785
887 // Visitor that finds all references to a particular code object, 786 // Visitor that finds all references to a particular code object,
888 // including "CODE_TARGET" references in other code objects and replaces 787 // including "CODE_TARGET" references in other code objects and replaces
889 // them on the fly. 788 // them on the fly.
890 class ReplacingVisitor : public ObjectVisitor { 789 class ReplacingVisitor : public ObjectVisitor {
(...skipping 1095 matching lines...) Expand 10 before | Expand all | Expand 10 after
1986 } 1885 }
1987 if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE) { 1886 if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE) {
1988 return "Function is blocked under native code"; 1887 return "Function is blocked under native code";
1989 } 1888 }
1990 if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR) { 1889 if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR) {
1991 return "Function is blocked under a generator activation"; 1890 return "Function is blocked under a generator activation";
1992 } 1891 }
1993 return NULL; 1892 return NULL;
1994 } 1893 }
1995 1894
1996 1895 Handle<JSArray> LiveEditFunctionTracker::Collect(FunctionLiteral* node,
1997 LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate, 1896 Handle<Script> script,
1998 FunctionLiteral* fun) 1897 Zone* zone, Isolate* isolate) {
1999 : isolate_(isolate) { 1898 LiveEditFunctionTracker visitor(script, zone, isolate);
2000 if (isolate_->active_function_info_listener() != NULL) { 1899 visitor.VisitFunctionLiteral(node);
2001 isolate_->active_function_info_listener()->FunctionStarted(fun); 1900 return visitor.result_;
2002 }
2003 } 1901 }
2004 1902
2005 1903 LiveEditFunctionTracker::LiveEditFunctionTracker(Handle<Script> script,
2006 LiveEditFunctionTracker::~LiveEditFunctionTracker() { 1904 Zone* zone, Isolate* isolate)
2007 if (isolate_->active_function_info_listener() != NULL) { 1905 : AstTraversalVisitor(isolate) {
2008 isolate_->active_function_info_listener()->FunctionDone(); 1906 current_parent_index_ = -1;
2009 } 1907 isolate_ = isolate;
1908 len_ = 0;
1909 result_ = isolate->factory()->NewJSArray(10);
1910 script_ = script;
1911 zone_ = zone;
2010 } 1912 }
2011 1913
1914 void LiveEditFunctionTracker::VisitFunctionLiteral(FunctionLiteral* node) {
1915 Scope* scope = node->scope();
2012 1916
2013 void LiveEditFunctionTracker::RecordFunctionInfo( 1917 // FunctionStarted is called in pre-order.
2014 Handle<SharedFunctionInfo> info, FunctionLiteral* lit, 1918 FunctionStarted(node);
2015 Zone* zone) { 1919
2016 if (isolate_->active_function_info_listener() != NULL) { 1920 VisitDeclarations(scope->declarations());
2017 isolate_->active_function_info_listener()->FunctionInfo(info, lit->scope(), 1921 VisitStatements(node->body());
2018 zone); 1922
2019 } 1923 // FunctionDone are called in post-order.
1924 // TODO(jgruber): If required, replace the (linear cost)
1925 // FindSharedFunctionInfo call with a more efficient implementation.
1926 Handle<SharedFunctionInfo> info =
1927 script_->FindSharedFunctionInfo(node).ToHandleChecked();
1928 FunctionDone(info, scope);
2020 } 1929 }
2021 1930
1931 void LiveEditFunctionTracker::FunctionStarted(FunctionLiteral* fun) {
1932 HandleScope handle_scope(isolate_);
1933 FunctionInfoWrapper info = FunctionInfoWrapper::Create(isolate_);
1934 info.SetInitialProperties(fun->name(), fun->start_position(),
1935 fun->end_position(), fun->parameter_count(),
1936 fun->materialized_literal_count(),
1937 current_parent_index_);
1938 current_parent_index_ = len_;
1939 SetElementSloppy(result_, len_, info.GetJSArray());
1940 len_++;
1941 }
2022 1942
2023 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) { 1943 // Saves full information about a function: its code, its scope info
2024 return isolate->active_function_info_listener() != NULL; 1944 // and a SharedFunctionInfo object.
1945 void LiveEditFunctionTracker::FunctionDone(Handle<SharedFunctionInfo> shared,
1946 Scope* scope) {
1947 HandleScope handle_scope(isolate_);
1948 FunctionInfoWrapper info = FunctionInfoWrapper::cast(
1949 *JSReceiver::GetElement(isolate_, result_, current_parent_index_)
1950 .ToHandleChecked());
1951 info.SetFunctionCode(Handle<Code>(shared->code()),
1952 Handle<HeapObject>(shared->scope_info()));
1953 info.SetSharedFunctionInfo(shared);
1954
1955 Handle<Object> scope_info_list = SerializeFunctionScope(scope);
1956 info.SetFunctionScopeInfo(scope_info_list);
1957
1958 current_parent_index_ = info.GetParentIndex();
1959 }
1960
1961 Handle<Object> LiveEditFunctionTracker::SerializeFunctionScope(Scope* scope) {
1962 Handle<JSArray> scope_info_list = isolate_->factory()->NewJSArray(10);
1963 int scope_info_length = 0;
1964
1965 // Saves some description of scope. It stores name and indexes of
1966 // variables in the whole scope chain. Null-named slots delimit
1967 // scopes of this chain.
1968 Scope* current_scope = scope;
1969 while (current_scope != NULL) {
1970 HandleScope handle_scope(isolate_);
1971 ZoneList<Variable*> stack_list(current_scope->StackLocalCount(), zone_);
1972 ZoneList<Variable*> context_list(current_scope->ContextLocalCount(), zone_);
1973 ZoneList<Variable*> globals_list(current_scope->ContextGlobalCount(),
1974 zone_);
1975 current_scope->CollectStackAndContextLocals(&stack_list, &context_list,
1976 &globals_list);
1977 context_list.Sort(&Variable::CompareIndex);
1978
1979 for (int i = 0; i < context_list.length(); i++) {
1980 SetElementSloppy(scope_info_list, scope_info_length,
1981 context_list[i]->name());
1982 scope_info_length++;
1983 SetElementSloppy(
1984 scope_info_list, scope_info_length,
1985 Handle<Smi>(Smi::FromInt(context_list[i]->index()), isolate_));
1986 scope_info_length++;
1987 }
1988 SetElementSloppy(scope_info_list, scope_info_length,
1989 Handle<Object>(isolate_->heap()->null_value(), isolate_));
1990 scope_info_length++;
1991
1992 current_scope = current_scope->outer_scope();
1993 }
1994
1995 return scope_info_list;
2025 } 1996 }
2026 1997
2027 } // namespace internal 1998 } // namespace internal
2028 } // namespace v8 1999 } // 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