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

Unified Diff: src/debug.cc

Issue 1210393002: Revert of Debugger: use list to find shared function info in a script. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: 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 fefccc893ffe03c145a933c982a3f3488fcf3d01..f814db84868032201feebecc059560e810a7bcd4 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -1984,125 +1984,126 @@
}
-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 (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;
- }
- }
-
- 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_;
-};
-
-
-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);
- 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);
- }
- // If not, compile to reveal inner functions, if possible.
- if (shared->allows_lazy_compilation_without_context()) {
- if (!CompileToRevealInnerFunctions(shared)) break;
- continue;
- }
-
- // 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;
- SharedFunctionInfo* shared = NULL;
- 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;
+ // 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 (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();
+ 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.
+
+ if (target.is_null()) return isolate_->factory()->undefined_value();
+
+ // There will be at least one break point when we are done.
+ has_break_points_ = true;
+
+ // 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();
+ }
+ } // 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);
+ }
+ }
+
+ return target;
}
« 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