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

Unified Diff: src/debug.cc

Issue 1100183002: debug: cache SharedFunctionInfo for multi-bp set Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 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') | src/debug-debugger.js » ('j') | 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 7b64f2f198a6a29bbacc66546dc636ca55ffbefb..d39007a079228322b69dd2b148158a7524cbfe20 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -749,6 +749,7 @@ bool Debug::Load() {
void Debug::Unload() {
ClearAllBreakPoints();
ClearStepping();
+ ClearSharedFunctionInfoInScript();
// Return debugger is not loaded.
if (!is_loaded()) return;
@@ -2000,6 +2001,44 @@ void Debug::PrepareForBreakPoints() {
}
+static int MatchSharedFunctionInfo(Handle<SharedFunctionInfo> shared,
+ int position,
+ Handle<SharedFunctionInfo> target,
+ int target_start_position) {
+ // 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()) {
+ return start_position;
+ } 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()) {
+ return start_position;
+ }
+ } 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.
+ return start_position;
+ }
+ }
+ }
+ return RelocInfo::kNoPosition;
+}
+
+
Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
int position) {
// Iterate the heap looking for SharedFunctionInfo generated from the
@@ -2019,12 +2058,35 @@ Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
Handle<JSFunction> target_function;
Handle<SharedFunctionInfo> target;
Heap* heap = isolate_->heap();
+
+ if (!shared_info_list_.is_empty()) {
+ for (Handle<SharedFunctionInfo>* it = shared_info_list_.begin();
+ it != shared_info_list_.end();
+ it++) {
+ Handle<SharedFunctionInfo> shared = *it;
+ DCHECK(shared->script() == *script);
+
+ int start_position = MatchSharedFunctionInfo(shared,
+ position,
+ target,
+ target_start_position);
+ if (start_position == RelocInfo::kNoPosition) continue;
+
+ target_start_position = start_position;
+ target = shared;
+ }
+
+ if (target.is_null()) return isolate_->factory()->undefined_value();
+ return target;
+ }
+
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;
@@ -2043,44 +2105,17 @@ Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
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;
- }
- }
- }
- }
+ if (shared->script() != *script) continue;
+
+ int start_position = MatchSharedFunctionInfo(shared,
+ position,
+ target,
+ target_start_position);
+ if (start_position == RelocInfo::kNoPosition) continue;
+
+ target_start_position = start_position;
+ target_function = function;
+ target = shared;
} // End for loop.
} // End no-allocation scope.
@@ -2123,6 +2158,82 @@ Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
}
+bool Debug::CollectSharedFunctionInfoInScript(Handle<Script> script) {
+ bool done = false;
+ // The current candidate for the source position:
+ Handle<JSFunction> target_function;
+ Handle<SharedFunctionInfo> target;
+ Heap* heap = isolate_->heap();
+ GlobalHandles* global_handles = isolate_->global_handles();
+ while (!done) {
+ DCHECK(shared_info_list_.is_empty());
+ done = true;
+
+ { // 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) continue;
+
+ if (!shared->is_compiled()) {
+ target = shared;
+ target_function = function;
+ done = false;
+ break;
+ }
+
+ shared_info_list_.Add(global_handles->Create(*shared));
+ } // End for loop.
+ } // End no-allocation scope.
+
+ if (done) continue;
+
+ // Cleanup the list, next iteration will re-add all shared infos
+ ClearSharedFunctionInfoInScript();
+
+ // 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::BuildFunctionInfo 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 false;
+ } // End while loop.
+
+ return true;
+}
+
+
+void Debug::ClearSharedFunctionInfoInScript() {
+ while (!shared_info_list_.is_empty()) {
+ Handle<SharedFunctionInfo> shared = shared_info_list_.RemoveLast();
+ Object** location = reinterpret_cast<Object**>(shared.location());
+ GlobalHandles::Destroy(location);
+ }
+}
+
+
// Ensures the debug information is present for shared.
bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
Handle<JSFunction> function) {
@@ -2667,10 +2778,12 @@ void Debug::OnAfterCompile(Handle<Script> script) {
// Call UpdateScriptBreakPoints expect no exceptions.
Handle<Object> argv[] = { wrapper };
+ ClearSharedFunctionInfoInScript();
if (Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points),
isolate_->js_builtins_object(),
arraysize(argv),
argv).is_null()) {
+ ClearSharedFunctionInfoInScript();
return;
}
« no previous file with comments | « src/debug.h ('k') | src/debug-debugger.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698