| Index: src/debug.cc
|
| diff --git a/src/debug.cc b/src/debug.cc
|
| index c70b834f7abdebb75f34a8fcd695607732f89e51..4ebdd88730d77f914cfbd2e3f313cc079d19db7b 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());
|
| @@ -1172,11 +1172,10 @@ bool Debug::SetBreakPointForScript(Handle<Script> script,
|
| int* source_position) {
|
| 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);
|
| + PrepareForBreakPoints();
|
| +
|
| + // Obtain shared function info for the function.
|
| + Object* result = FindSharedFunctionInfoInScript(script, *source_position);
|
| if (result->IsUndefined()) return false;
|
|
|
| // Make sure the function has set up the debug info.
|
| @@ -2092,6 +2091,115 @@ void Debug::PrepareForBreakPoints() {
|
| }
|
|
|
|
|
| +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;
|
| + 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;
|
| +
|
| + // 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) {
|
|
|