| Index: src/debug.cc
|
| diff --git a/src/debug.cc b/src/debug.cc
|
| index c105e44faa5b5cedaea4a8108ad024137f52729b..34ba3949e90acefd5651f772cbb3ce524d4a33ce 100644
|
| --- a/src/debug.cc
|
| +++ b/src/debug.cc
|
| @@ -1727,203 +1727,50 @@ void Debug::ClearStepNext() {
|
| }
|
|
|
|
|
| -// Helper function to compile full code for debugging. This code will
|
| -// have debug break slots and deoptimization
|
| -// information. Deoptimization information is required in case that an
|
| -// optimized version of this function is still activated on the
|
| -// stack. It will also make sure that the full code is compiled with
|
| -// the same flags as the previous version - that is flags which can
|
| -// change the code generated. The current method of mapping from
|
| -// already compiled full code without debug break slots to full code
|
| -// with debug break slots depends on the generated code is otherwise
|
| -// exactly the same.
|
| -static bool CompileFullCodeForDebugging(Handle<SharedFunctionInfo> shared,
|
| - Handle<Code> current_code) {
|
| - ASSERT(!current_code->has_debug_break_slots());
|
| -
|
| - CompilationInfo info(shared);
|
| - info.MarkCompilingForDebugging(current_code);
|
| - ASSERT(!info.shared_info()->is_compiled());
|
| - ASSERT(!info.isolate()->has_pending_exception());
|
| -
|
| - // Use compile lazy which will end up compiling the full code in the
|
| - // configuration configured above.
|
| - bool result = Compiler::CompileLazy(&info);
|
| - ASSERT(result != Isolate::Current()->has_pending_exception());
|
| - info.isolate()->clear_pending_exception();
|
| -#if DEBUG
|
| - if (result) {
|
| - Handle<Code> new_code(shared->code());
|
| - ASSERT(new_code->has_debug_break_slots());
|
| - ASSERT(current_code->is_compiled_optimizable() ==
|
| - new_code->is_compiled_optimizable());
|
| - ASSERT(current_code->instruction_size() <= new_code->instruction_size());
|
| - }
|
| -#endif
|
| - return result;
|
| -}
|
| -
|
| -
|
| void Debug::PrepareForBreakPoints() {
|
| // If preparing for the first break point make sure to deoptimize all
|
| // functions as debugging does not work with optimized code.
|
| if (!has_break_points_) {
|
| Deoptimizer::DeoptimizeAll();
|
|
|
| - Handle<Code> lazy_compile =
|
| - Handle<Code>(isolate_->builtins()->builtin(Builtins::kLazyCompile));
|
| -
|
| - // Keep the list of activated functions in a handlified list as it
|
| - // is used both in GC and non-GC code.
|
| - List<Handle<JSFunction> > active_functions(100);
|
| -
|
| - {
|
| - // We are going to iterate heap to find all functions without
|
| - // debug break slots.
|
| - isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask);
|
| -
|
| - // Ensure no GC in this scope as we are comparing raw pointer
|
| - // values and performing a heap iteration.
|
| - AssertNoAllocation no_allocation;
|
| -
|
| - // Find all non-optimized code functions with activation frames on
|
| - // the stack.
|
| - for (JavaScriptFrameIterator it(isolate_); !it.done(); it.Advance()) {
|
| - JavaScriptFrame* frame = it.frame();
|
| - if (frame->function()->IsJSFunction()) {
|
| - JSFunction* function = JSFunction::cast(frame->function());
|
| - if (function->code()->kind() == Code::FUNCTION &&
|
| - !function->code()->has_debug_break_slots())
|
| - active_functions.Add(Handle<JSFunction>(function));
|
| - }
|
| - }
|
| - // Sort the functions on the object pointer value to prepare for
|
| - // the binary search below.
|
| - active_functions.Sort(HandleObjectPointerCompare<JSFunction>);
|
| -
|
| - // Scan the heap for all non-optimized functions which has no
|
| - // debug break slots.
|
| - HeapIterator iterator;
|
| - HeapObject* obj = NULL;
|
| - while (((obj = iterator.next()) != NULL)) {
|
| - if (obj->IsJSFunction()) {
|
| - JSFunction* function = JSFunction::cast(obj);
|
| - if (function->shared()->allows_lazy_compilation() &&
|
| - function->shared()->script()->IsScript() &&
|
| - function->code()->kind() == Code::FUNCTION &&
|
| - !function->code()->has_debug_break_slots()) {
|
| - bool has_activation =
|
| - SortedListBSearch<Handle<JSFunction> >(
|
| - active_functions,
|
| - Handle<JSFunction>(function),
|
| - HandleObjectPointerCompare<JSFunction>) != -1;
|
| - if (!has_activation) {
|
| - function->set_code(*lazy_compile);
|
| - function->shared()->set_code(*lazy_compile);
|
| - }
|
| - }
|
| - }
|
| + // We are going to iterate heap to find all functions without
|
| + // debug break slots.
|
| + isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask);
|
| +
|
| + AssertNoAllocation no_allocation;
|
| + Builtins* builtins = isolate_->builtins();
|
| + Code* lazy_compile = builtins->builtin(Builtins::kLazyCompile);
|
| +
|
| + // Find all non-optimized code functions with activation frames on
|
| + // the stack.
|
| + List<JSFunction*> active_functions(100);
|
| + for (JavaScriptFrameIterator it(isolate_); !it.done(); it.Advance()) {
|
| + JavaScriptFrame* frame = it.frame();
|
| + if (frame->function()->IsJSFunction()) {
|
| + JSFunction* function = JSFunction::cast(frame->function());
|
| + if (function->code()->kind() == Code::FUNCTION)
|
| + active_functions.Add(function);
|
| }
|
| }
|
| -
|
| - // Now the non-GC scope is left, and the sorting of the functions
|
| - // in active_function is not ensured any more. The code below does
|
| - // not rely on it.
|
| -
|
| - // Now recompile all functions with activation frames and and
|
| - // patch the return address to run in the new compiled code.
|
| - for (int i = 0; i < active_functions.length(); i++) {
|
| - Handle<JSFunction> function = active_functions[i];
|
| - Handle<SharedFunctionInfo> shared(function->shared());
|
| - // If recompilation is not possible just skip it.
|
| - if (shared->is_toplevel() ||
|
| - !shared->allows_lazy_compilation() ||
|
| - shared->code()->kind() == Code::BUILTIN) {
|
| - continue;
|
| - }
|
| -
|
| - // Make sure that the shared full code is compiled with debug
|
| - // break slots.
|
| - Handle<Code> current_code(function->code());
|
| - if (shared->code()->has_debug_break_slots()) {
|
| - // if the code is already recompiled to have break slots skip
|
| - // recompilation.
|
| - ASSERT(!function->code()->has_debug_break_slots());
|
| - } else {
|
| - // Try to compile the full code with debug break slots. If it
|
| - // fails just keep the current code.
|
| - ASSERT(shared->code() == *current_code);
|
| - ZoneScope zone_scope(isolate_, DELETE_ON_EXIT);
|
| - shared->set_code(*lazy_compile);
|
| - bool prev_force_debugger_active =
|
| - isolate_->debugger()->force_debugger_active();
|
| - isolate_->debugger()->set_force_debugger_active(true);
|
| - CompileFullCodeForDebugging(shared, current_code);
|
| - isolate_->debugger()->set_force_debugger_active(
|
| - prev_force_debugger_active);
|
| - if (!shared->is_compiled()) {
|
| - shared->set_code(*current_code);
|
| - continue;
|
| - }
|
| - }
|
| - Handle<Code> new_code(shared->code());
|
| -
|
| - // Find the function and patch return address.
|
| - for (JavaScriptFrameIterator it(isolate_); !it.done(); it.Advance()) {
|
| - JavaScriptFrame* frame = it.frame();
|
| - // If the current frame is for this function in its
|
| - // non-optimized form rewrite the return address to continue
|
| - // in the newly compiled full code with debug break slots.
|
| - if (frame->function()->IsJSFunction() &&
|
| - frame->function() == *function &&
|
| - frame->LookupCode()->kind() == Code::FUNCTION) {
|
| - intptr_t delta = frame->pc() - current_code->instruction_start();
|
| - int debug_break_slot_count = 0;
|
| - int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT);
|
| - for (RelocIterator it(*new_code, mask); !it.done(); it.next()) {
|
| - // Check if the pc in the new code with debug break
|
| - // slots is before this slot.
|
| - RelocInfo* info = it.rinfo();
|
| - int debug_break_slot_bytes =
|
| - debug_break_slot_count * Assembler::kDebugBreakSlotLength;
|
| - intptr_t new_delta =
|
| - info->pc() -
|
| - new_code->instruction_start() -
|
| - debug_break_slot_bytes;
|
| - if (new_delta > delta) {
|
| - break;
|
| - }
|
| -
|
| - // Passed a debug break slot in the full code with debug
|
| - // break slots.
|
| - debug_break_slot_count++;
|
| + active_functions.Sort();
|
| +
|
| + // Scan the heap for all non-optimized functions which has no
|
| + // debug break slots.
|
| + HeapIterator iterator;
|
| + HeapObject* obj = NULL;
|
| + while (((obj = iterator.next()) != NULL)) {
|
| + if (obj->IsJSFunction()) {
|
| + JSFunction* function = JSFunction::cast(obj);
|
| + if (function->shared()->allows_lazy_compilation() &&
|
| + function->shared()->script()->IsScript() &&
|
| + function->code()->kind() == Code::FUNCTION &&
|
| + !function->code()->has_debug_break_slots()) {
|
| + bool has_activation =
|
| + SortedListBSearch<JSFunction*>(active_functions, function) != -1;
|
| + if (!has_activation) {
|
| + function->set_code(lazy_compile);
|
| + function->shared()->set_code(lazy_compile);
|
| }
|
| - int debug_break_slot_bytes =
|
| - debug_break_slot_count * Assembler::kDebugBreakSlotLength;
|
| - if (FLAG_trace_deopt) {
|
| - PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
|
| - "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
|
| - "for debugging, "
|
| - "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n",
|
| - reinterpret_cast<intptr_t>(
|
| - current_code->instruction_start()),
|
| - reinterpret_cast<intptr_t>(
|
| - current_code->instruction_start()) +
|
| - current_code->instruction_size(),
|
| - current_code->instruction_size(),
|
| - reinterpret_cast<intptr_t>(new_code->instruction_start()),
|
| - reinterpret_cast<intptr_t>(new_code->instruction_start()) +
|
| - new_code->instruction_size(),
|
| - new_code->instruction_size(),
|
| - reinterpret_cast<intptr_t>(frame->pc()),
|
| - reinterpret_cast<intptr_t>(new_code->instruction_start()) +
|
| - delta + debug_break_slot_bytes);
|
| - }
|
| -
|
| - // Patch the return address to return into the code with
|
| - // debug break slots.
|
| - frame->set_pc(
|
| - new_code->instruction_start() + delta + debug_break_slot_bytes);
|
| }
|
| }
|
| }
|
| @@ -2994,9 +2841,7 @@ void Debugger::EnqueueDebugCommand(v8::Debug::ClientData* client_data) {
|
| bool Debugger::IsDebuggerActive() {
|
| ScopedLock with(debugger_access_);
|
|
|
| - return message_handler_ != NULL ||
|
| - !event_listener_.is_null() ||
|
| - force_debugger_active_;
|
| + return message_handler_ != NULL || !event_listener_.is_null();
|
| }
|
|
|
|
|
|
|