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

Unified Diff: src/debug.cc

Issue 1206573004: Debugger: use list to find shared function info in a script. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix liveedit Created 5 years, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/debug.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/debug.cc
diff --git a/src/debug.cc b/src/debug.cc
index f814db84868032201feebecc059560e810a7bcd4..fefccc893ffe03c145a933c982a3f3488fcf3d01 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -1984,126 +1984,125 @@ void Debug::PrepareForBreakPoints() {
}
-Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
- int position) {
- // Iterate the heap looking for SharedFunctionInfo generated from the
- // script. The inner most SharedFunctionInfo containing the source position
- // for the requested break point is found.
- // NOTE: This might require several heap iterations. If the SharedFunctionInfo
- // which is found is not compiled it is compiled and the heap is iterated
- // again as the compilation might create inner functions from the newly
- // compiled function and the actual requested break point might be in one of
- // these functions.
- // NOTE: The below fix-point iteration depends on all functions that cannot be
- // compiled lazily without a context to not be compiled at all. Compilation
- // will be triggered at points where we do not need a context.
- bool done = false;
- // The current candidate for the source position:
- int target_start_position = RelocInfo::kNoPosition;
- Handle<JSFunction> target_function;
- Handle<SharedFunctionInfo> target;
- Heap* heap = isolate_->heap();
- while (!done) {
- { // Extra scope for iterator.
- // If lazy compilation is off, we won't have duplicate shared function
- // infos that need to be filtered.
- HeapIterator iterator(heap, FLAG_lazy ? HeapIterator::kNoFiltering
- : HeapIterator::kFilterUnreachable);
- for (HeapObject* obj = iterator.next();
- obj != NULL; obj = iterator.next()) {
- bool found_next_candidate = false;
- Handle<JSFunction> function;
- Handle<SharedFunctionInfo> shared;
- if (obj->IsJSFunction()) {
- function = Handle<JSFunction>(JSFunction::cast(obj));
- shared = Handle<SharedFunctionInfo>(function->shared());
- DCHECK(shared->allows_lazy_compilation() || shared->is_compiled());
- found_next_candidate = true;
- } else if (obj->IsSharedFunctionInfo()) {
- shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj));
- // Skip functions that we cannot compile lazily without a context,
- // which is not available here, because there is no closure.
- found_next_candidate = shared->is_compiled() ||
- shared->allows_lazy_compilation_without_context();
- }
- if (!found_next_candidate) continue;
- if (shared->script() == *script) {
- // If the SharedFunctionInfo found has the requested script data and
- // contains the source position it is a candidate.
- int start_position = shared->function_token_position();
- if (start_position == RelocInfo::kNoPosition) {
- start_position = shared->start_position();
- }
- if (start_position <= position &&
- position <= shared->end_position()) {
- // If there is no candidate or this function is within the current
- // candidate this is the new candidate.
- if (target.is_null()) {
- target_start_position = start_position;
- target_function = function;
- target = shared;
- } else {
- if (target_start_position == start_position &&
- shared->end_position() == target->end_position()) {
- // If a top-level function contains only one function
- // declaration the source for the top-level and the function
- // is the same. In that case prefer the non top-level function.
- if (!shared->is_toplevel()) {
- target_start_position = start_position;
- target_function = function;
- target = shared;
- }
- } else if (target_start_position <= start_position &&
- shared->end_position() <= target->end_position()) {
- // This containment check includes equality as a function
- // inside a top-level function can share either start or end
- // position with the top-level function.
- target_start_position = start_position;
- target_function = function;
- target = shared;
- }
- }
- }
- }
- } // End for loop.
- } // End no-allocation scope.
+class SharedFunctionInfoFinder {
+ public:
+ explicit SharedFunctionInfoFinder(int target_position)
+ : current_candidate_(NULL),
+ current_candidate_closure_(NULL),
+ current_start_position_(RelocInfo::kNoPosition),
+ target_position_(target_position) {}
+
+ void NewCandidate(SharedFunctionInfo* shared, JSFunction* closure = NULL) {
+ int start_position = shared->function_token_position();
+ if (start_position == RelocInfo::kNoPosition) {
+ start_position = shared->start_position();
+ }
- if (target.is_null()) return isolate_->factory()->undefined_value();
+ if (start_position > target_position_) return;
+ if (target_position_ > shared->end_position()) return;
+
+ if (current_candidate_ != NULL) {
+ if (current_start_position_ == start_position &&
+ shared->end_position() == current_candidate_->end_position()) {
+ // If a top-level function contains only one function
+ // declaration the source for the top-level and the function
+ // is the same. In that case prefer the non top-level function.
+ if (shared->is_toplevel()) return;
+ } else if (start_position < current_start_position_ ||
+ current_candidate_->end_position() < shared->end_position()) {
+ return;
+ }
+ }
- // There will be at least one break point when we are done.
- has_break_points_ = true;
+ current_start_position_ = start_position;
+ current_candidate_ = shared;
+ current_candidate_closure_ = closure;
+ }
+
+ SharedFunctionInfo* Result() { return current_candidate_; }
+
+ JSFunction* ResultClosure() { return current_candidate_closure_; }
+
+ private:
+ SharedFunctionInfo* current_candidate_;
+ JSFunction* current_candidate_closure_;
+ int current_start_position_;
+ int target_position_;
+ DisallowHeapAllocation no_gc_;
+};
- // If the candidate found is compiled we are done.
- done = target->is_compiled();
- if (!done) {
- // If the candidate is not compiled, compile it to reveal any inner
- // functions which might contain the requested source position. This
- // will compile all inner functions that cannot be compiled without a
- // context, because Compiler::GetSharedFunctionInfo checks whether the
- // debugger is active.
- MaybeHandle<Code> maybe_result = target_function.is_null()
- ? Compiler::GetUnoptimizedCode(target)
- : Compiler::GetUnoptimizedCode(target_function);
- if (maybe_result.is_null()) return isolate_->factory()->undefined_value();
+
+template <typename C>
+bool Debug::CompileToRevealInnerFunctions(C* compilable) {
+ HandleScope scope(isolate_);
+ // Force compiling inner functions that require context.
+ // TODO(yangguo): remove this hack.
+ bool has_break_points = has_break_points_;
+ has_break_points_ = true;
+ Handle<C> compilable_handle(compilable);
+ bool result = !Compiler::GetUnoptimizedCode(compilable_handle).is_null();
+ has_break_points_ = has_break_points;
+ return result;
+}
+
+
+Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
+ int position) {
+ while (true) {
+ // Go through all shared function infos associated with this script to
+ // find the inner most function containing this position.
+ if (!script->shared_function_infos()->IsWeakFixedArray()) break;
+ WeakFixedArray* array =
+ WeakFixedArray::cast(script->shared_function_infos());
+
+ SharedFunctionInfo* shared;
+ {
+ SharedFunctionInfoFinder finder(position);
+ for (int i = 0; i < array->Length(); i++) {
+ Object* item = array->Get(i);
+ if (!item->IsSharedFunctionInfo()) continue;
+ SharedFunctionInfo* shared = SharedFunctionInfo::cast(item);
brucedawson 2015/06/29 17:08:53 Is it intentional that this shadows the outer-scop
+ finder.NewCandidate(shared);
+ }
+ shared = finder.Result();
+ if (shared == NULL) break;
+ // We found it if it's already compiled.
+ if (shared->is_compiled()) return handle(shared);
}
- } // End while loop.
-
- // JSFunctions from the same literal may not have the same shared function
- // info. Find those JSFunctions and deduplicate the shared function info.
- HeapIterator iterator(heap, FLAG_lazy ? HeapIterator::kNoFiltering
- : HeapIterator::kFilterUnreachable);
- for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
- if (!obj->IsJSFunction()) continue;
- JSFunction* function = JSFunction::cast(obj);
- SharedFunctionInfo* shared = function->shared();
- if (shared != *target && shared->script() == target->script() &&
- shared->start_position_and_type() ==
- target->start_position_and_type()) {
- function->set_shared(*target);
+ // If not, compile to reveal inner functions, if possible.
+ if (shared->allows_lazy_compilation_without_context()) {
+ if (!CompileToRevealInnerFunctions(shared)) break;
+ continue;
}
- }
- return target;
+ // If not possible, comb the heap for the best suitable compile target.
+ JSFunction* closure;
+ {
+ HeapIterator it(isolate_->heap(), HeapIterator::kNoFiltering);
+ SharedFunctionInfoFinder finder(position);
+ while (HeapObject* object = it.next()) {
+ JSFunction* closure = NULL;
brucedawson 2015/06/29 17:08:53 Is it intentional that this shadows the outer-scop
+ SharedFunctionInfo* shared = NULL;
brucedawson 2015/06/29 17:08:53 Is it intentional that this shadows the outer-scop
+ if (object->IsJSFunction()) {
+ closure = JSFunction::cast(object);
+ shared = closure->shared();
+ } else if (object->IsSharedFunctionInfo()) {
+ shared = SharedFunctionInfo::cast(object);
+ if (!shared->allows_lazy_compilation_without_context()) continue;
+ } else {
+ continue;
+ }
+ if (shared->script() == *script) finder.NewCandidate(shared, closure);
+ }
+ closure = finder.ResultClosure();
+ shared = finder.Result();
+ }
+ if (closure == NULL ? !CompileToRevealInnerFunctions(shared)
+ : !CompileToRevealInnerFunctions(closure)) {
+ break;
+ }
+ }
+ return isolate_->factory()->undefined_value();
}
« no previous file with comments | « src/debug.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698