Chromium Code Reviews| Index: src/debug.cc |
| diff --git a/src/debug.cc b/src/debug.cc |
| index c70b834f7abdebb75f34a8fcd695607732f89e51..b1f09dff94b39cf658f6e03e8b3b20b6e6522fd1 100644 |
| --- a/src/debug.cc |
| +++ b/src/debug.cc |
| @@ -698,7 +698,7 @@ void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data) { |
| // We need to clear all breakpoints associated with the function to restore |
| // original code and avoid patching the code twice later because |
| // the function will live in the heap until next gc, and can be found by |
| - // Runtime::FindSharedFunctionInfoInScript. |
| + // Debug::FindSharedFunctionInfoInScript. |
| BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); |
| it.ClearAllDebugBreak(); |
| debug->RemoveDebugInfo(node->debug_info()); |
| @@ -1173,10 +1173,8 @@ bool Debug::SetBreakPointForScript(Handle<Script> script, |
| HandleScope scope(isolate_); |
| // No need to call PrepareForBreakPoints because it will be called |
| - // implicitly by Runtime::FindSharedFunctionInfoInScript. |
| - Object* result = Runtime::FindSharedFunctionInfoInScript(isolate_, |
| - script, |
| - *source_position); |
| + // implicitly by Debug::FindSharedFunctionInfoInScript. |
|
Toon Verwaest
2012/09/03 13:44:22
Just move PrepareForBreakPoints() here from FindSh
Michael Starzinger
2012/09/03 14:08:49
Done.
|
| + Object* result = FindSharedFunctionInfoInScript(script, *source_position); |
| if (result->IsUndefined()) return false; |
| // Make sure the function has set up the debug info. |
| @@ -2092,6 +2090,117 @@ void Debug::PrepareForBreakPoints() { |
| } |
| +Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script, |
| + int position) { |
| + // 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. |
| + PrepareForBreakPoints(); |
| + |
| + // 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. |
| + bool done = false; |
| + // The current candidate for the source position: |
| + int target_start_position = RelocInfo::kNoPosition; |
| + Handle<JSFunction> target_function; |
| + Handle<SharedFunctionInfo> target; |
| + while (!done) { |
| + { // Extra scope for iterator and no-allocation. |
| + isolate_->heap()->EnsureHeapIsIterable(); |
| + AssertNoAllocation no_alloc_during_heap_iteration; |
| + HeapIterator iterator; |
| + 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()); |
| + ASSERT(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. |
| + |
| + if (target.is_null()) { |
| + return isolate_->heap()->undefined_value(); |
| + } |
| + |
| + // There will be at least one break point when we are done. |
| + has_break_points_ = true; |
|
Michael Starzinger
2012/09/03 13:36:53
These are the only two lines I changed in this fun
|
| + |
| + // 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::BuildFunctionInfo checks whether the |
| + // debugger is active. |
| + if (target_function.is_null()) { |
| + SharedFunctionInfo::CompileLazy(target, KEEP_EXCEPTION); |
| + } else { |
| + JSFunction::CompileLazy(target_function, KEEP_EXCEPTION); |
| + } |
| + } |
| + } // End while loop. |
| + |
| + return *target; |
| +} |
| + |
| + |
| // Ensures the debug information is present for shared. |
| bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, |
| Handle<JSFunction> function) { |