Index: src/debug/liveedit.cc |
diff --git a/src/debug/liveedit.cc b/src/debug/liveedit.cc |
index ec85689a710aab697a343c33a89d8510e1350d32..50d60a1d9bbeec81590e5b29d8a91fdb097a5a8b 100644 |
--- a/src/debug/liveedit.cc |
+++ b/src/debug/liveedit.cc |
@@ -691,105 +691,6 @@ Handle<SharedFunctionInfo> SharedInfoWrapper::GetInfo() { |
} |
-class FunctionInfoListener { |
- public: |
- explicit FunctionInfoListener(Isolate* isolate) { |
- current_parent_index_ = -1; |
- len_ = 0; |
- result_ = isolate->factory()->NewJSArray(10); |
- } |
- |
- void FunctionStarted(FunctionLiteral* fun) { |
- HandleScope scope(isolate()); |
- FunctionInfoWrapper info = FunctionInfoWrapper::Create(isolate()); |
- info.SetInitialProperties(fun->name(), fun->start_position(), |
- fun->end_position(), fun->parameter_count(), |
- fun->materialized_literal_count(), |
- current_parent_index_); |
- current_parent_index_ = len_; |
- SetElementSloppy(result_, len_, info.GetJSArray()); |
- len_++; |
- } |
- |
- void FunctionDone() { |
- HandleScope scope(isolate()); |
- FunctionInfoWrapper info = FunctionInfoWrapper::cast( |
- *JSReceiver::GetElement(isolate(), result_, current_parent_index_) |
- .ToHandleChecked()); |
- current_parent_index_ = info.GetParentIndex(); |
- } |
- |
- // Saves full information about a function: its code, its scope info |
- // and a SharedFunctionInfo object. |
- void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope, |
- Zone* zone) { |
- if (!shared->IsSharedFunctionInfo()) { |
- return; |
- } |
- FunctionInfoWrapper info = FunctionInfoWrapper::cast( |
- *JSReceiver::GetElement(isolate(), result_, current_parent_index_) |
- .ToHandleChecked()); |
- info.SetFunctionCode(Handle<Code>(shared->code()), |
- Handle<HeapObject>(shared->scope_info())); |
- info.SetSharedFunctionInfo(shared); |
- |
- Handle<Object> scope_info_list = SerializeFunctionScope(scope, zone); |
- info.SetFunctionScopeInfo(scope_info_list); |
- } |
- |
- Handle<JSArray> GetResult() { return result_; } |
- |
- private: |
- Isolate* isolate() const { return result_->GetIsolate(); } |
- |
- Handle<Object> SerializeFunctionScope(Scope* scope, Zone* zone) { |
- Handle<JSArray> scope_info_list = isolate()->factory()->NewJSArray(10); |
- int scope_info_length = 0; |
- |
- // Saves some description of scope. It stores name and indexes of |
- // variables in the whole scope chain. Null-named slots delimit |
- // scopes of this chain. |
- Scope* current_scope = scope; |
- while (current_scope != NULL) { |
- HandleScope handle_scope(isolate()); |
- ZoneList<Variable*> stack_list(current_scope->StackLocalCount(), zone); |
- ZoneList<Variable*> context_list( |
- current_scope->ContextLocalCount(), zone); |
- ZoneList<Variable*> globals_list(current_scope->ContextGlobalCount(), |
- zone); |
- current_scope->CollectStackAndContextLocals(&stack_list, &context_list, |
- &globals_list); |
- context_list.Sort(&Variable::CompareIndex); |
- |
- for (int i = 0; i < context_list.length(); i++) { |
- SetElementSloppy(scope_info_list, |
- scope_info_length, |
- context_list[i]->name()); |
- scope_info_length++; |
- SetElementSloppy( |
- scope_info_list, |
- scope_info_length, |
- Handle<Smi>(Smi::FromInt(context_list[i]->index()), isolate())); |
- scope_info_length++; |
- } |
- SetElementSloppy(scope_info_list, |
- scope_info_length, |
- Handle<Object>(isolate()->heap()->null_value(), |
- isolate())); |
- scope_info_length++; |
- |
- current_scope = current_scope->outer_scope(); |
- } |
- |
- return scope_info_list; |
- } |
- |
- Handle<JSArray> result_; |
- int len_; |
- int current_parent_index_; |
-}; |
- |
- |
void LiveEdit::InitializeThreadLocal(Debug* debug) { |
debug->thread_local_.frame_drop_mode_ = LiveEdit::FRAMES_UNTOUCHED; |
} |
@@ -825,11 +726,10 @@ MaybeHandle<JSArray> LiveEdit::GatherCompileInfo(Handle<Script> script, |
Handle<String> source) { |
Isolate* isolate = script->GetIsolate(); |
- FunctionInfoListener listener(isolate); |
+ MaybeHandle<JSArray> infos; |
Handle<Object> original_source = |
Handle<Object>(script->source(), isolate); |
script->set_source(*source); |
- isolate->set_active_function_info_listener(&listener); |
{ |
// Creating verbose TryCatch from public API is currently the only way to |
@@ -838,7 +738,7 @@ MaybeHandle<JSArray> LiveEdit::GatherCompileInfo(Handle<Script> script, |
try_catch.SetVerbose(true); |
// A logical 'try' section. |
- Compiler::CompileForLiveEdit(script); |
+ infos = Compiler::CompileForLiveEdit(script); |
} |
// A logical 'catch' section. |
@@ -876,11 +776,10 @@ MaybeHandle<JSArray> LiveEdit::GatherCompileInfo(Handle<Script> script, |
} |
// A logical 'finally' section. |
- isolate->set_active_function_info_listener(NULL); |
script->set_source(*original_source); |
if (rethrow_exception.is_null()) { |
- return listener.GetResult(); |
+ return infos.ToHandleChecked(); |
} else { |
return isolate->Throw<JSArray>(rethrow_exception); |
} |
@@ -2038,35 +1937,107 @@ const char* LiveEdit::RestartFrame(JavaScriptFrame* frame) { |
return NULL; |
} |
+Handle<JSArray> LiveEditFunctionTracker::Collect(FunctionLiteral* node, |
+ Handle<Script> script, |
+ Zone* zone, Isolate* isolate) { |
+ LiveEditFunctionTracker visitor(script, zone, isolate); |
+ visitor.VisitFunctionLiteral(node); |
+ return visitor.result_; |
+} |
-LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate, |
- FunctionLiteral* fun) |
- : isolate_(isolate) { |
- if (isolate_->active_function_info_listener() != NULL) { |
- isolate_->active_function_info_listener()->FunctionStarted(fun); |
- } |
+LiveEditFunctionTracker::LiveEditFunctionTracker(Handle<Script> script, |
+ Zone* zone, Isolate* isolate) |
+ : AstTraversalVisitor(isolate) { |
+ current_parent_index_ = -1; |
+ isolate_ = isolate; |
+ len_ = 0; |
+ result_ = isolate->factory()->NewJSArray(10); |
+ script_ = script; |
+ zone_ = zone; |
} |
+void LiveEditFunctionTracker::VisitFunctionLiteral(FunctionLiteral* node) { |
+ Scope* scope = node->scope(); |
-LiveEditFunctionTracker::~LiveEditFunctionTracker() { |
- if (isolate_->active_function_info_listener() != NULL) { |
- isolate_->active_function_info_listener()->FunctionDone(); |
- } |
+ // FunctionStarted is called in pre-order. |
+ FunctionStarted(node); |
+ |
+ VisitDeclarations(scope->declarations()); |
+ VisitStatements(node->body()); |
+ |
+ // FunctionDone are called in post-order. |
+ // TODO(jgruber): If required, replace the (linear cost) |
+ // FindSharedFunctionInfo call with a more efficient implementation. |
+ Handle<SharedFunctionInfo> info = |
+ script_->FindSharedFunctionInfo(node).ToHandleChecked(); |
+ FunctionDone(info, scope); |
} |
+void LiveEditFunctionTracker::FunctionStarted(FunctionLiteral* fun) { |
+ HandleScope handle_scope(isolate_); |
+ FunctionInfoWrapper info = FunctionInfoWrapper::Create(isolate_); |
+ info.SetInitialProperties(fun->name(), fun->start_position(), |
+ fun->end_position(), fun->parameter_count(), |
+ fun->materialized_literal_count(), |
+ current_parent_index_); |
+ current_parent_index_ = len_; |
+ SetElementSloppy(result_, len_, info.GetJSArray()); |
+ len_++; |
+} |
-void LiveEditFunctionTracker::RecordFunctionInfo( |
- Handle<SharedFunctionInfo> info, FunctionLiteral* lit, |
- Zone* zone) { |
- if (isolate_->active_function_info_listener() != NULL) { |
- isolate_->active_function_info_listener()->FunctionInfo(info, lit->scope(), |
- zone); |
- } |
+// Saves full information about a function: its code, its scope info |
+// and a SharedFunctionInfo object. |
+void LiveEditFunctionTracker::FunctionDone(Handle<SharedFunctionInfo> shared, |
+ Scope* scope) { |
+ HandleScope handle_scope(isolate_); |
+ FunctionInfoWrapper info = FunctionInfoWrapper::cast( |
+ *JSReceiver::GetElement(isolate_, result_, current_parent_index_) |
+ .ToHandleChecked()); |
+ info.SetFunctionCode(Handle<Code>(shared->code()), |
+ Handle<HeapObject>(shared->scope_info())); |
+ info.SetSharedFunctionInfo(shared); |
+ |
+ Handle<Object> scope_info_list = SerializeFunctionScope(scope); |
+ info.SetFunctionScopeInfo(scope_info_list); |
+ |
+ current_parent_index_ = info.GetParentIndex(); |
} |
+Handle<Object> LiveEditFunctionTracker::SerializeFunctionScope(Scope* scope) { |
+ Handle<JSArray> scope_info_list = isolate_->factory()->NewJSArray(10); |
+ int scope_info_length = 0; |
+ |
+ // Saves some description of scope. It stores name and indexes of |
+ // variables in the whole scope chain. Null-named slots delimit |
+ // scopes of this chain. |
+ Scope* current_scope = scope; |
+ while (current_scope != NULL) { |
+ HandleScope handle_scope(isolate_); |
+ ZoneList<Variable*> stack_list(current_scope->StackLocalCount(), zone_); |
+ ZoneList<Variable*> context_list(current_scope->ContextLocalCount(), zone_); |
+ ZoneList<Variable*> globals_list(current_scope->ContextGlobalCount(), |
+ zone_); |
+ current_scope->CollectStackAndContextLocals(&stack_list, &context_list, |
+ &globals_list); |
+ context_list.Sort(&Variable::CompareIndex); |
+ |
+ for (int i = 0; i < context_list.length(); i++) { |
+ SetElementSloppy(scope_info_list, scope_info_length, |
+ context_list[i]->name()); |
+ scope_info_length++; |
+ SetElementSloppy( |
+ scope_info_list, scope_info_length, |
+ Handle<Smi>(Smi::FromInt(context_list[i]->index()), isolate_)); |
+ scope_info_length++; |
+ } |
+ SetElementSloppy(scope_info_list, scope_info_length, |
+ Handle<Object>(isolate_->heap()->null_value(), isolate_)); |
+ scope_info_length++; |
+ |
+ current_scope = current_scope->outer_scope(); |
+ } |
-bool LiveEditFunctionTracker::IsActive(Isolate* isolate) { |
- return isolate->active_function_info_listener() != NULL; |
+ return scope_info_list; |
} |
} // namespace internal |