📄 debug.cc.svn-base
字号:
}#endif}bool Debug::has_break_points_ = false;DebugInfoListNode* Debug::debug_info_list_ = NULL;// Threading support.void Debug::ThreadInit() { thread_local_.last_step_action_ = StepNone; thread_local_.last_statement_position_ = RelocInfo::kNoPosition; thread_local_.step_count_ = 0; thread_local_.last_fp_ = 0; thread_local_.step_into_fp_ = 0; thread_local_.after_break_target_ = 0;}JSCallerSavedBuffer Debug::registers_;Debug::ThreadLocal Debug::thread_local_;char* Debug::ArchiveDebug(char* storage) { char* to = storage; memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); to += sizeof(ThreadLocal); memcpy(to, reinterpret_cast<char*>(®isters_), sizeof(registers_)); ThreadInit(); ASSERT(to <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread();}char* Debug::RestoreDebug(char* storage) { char* from = storage; memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); from += sizeof(ThreadLocal); memcpy(reinterpret_cast<char*>(®isters_), from, sizeof(registers_)); ASSERT(from <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread();}int Debug::ArchiveSpacePerThread() { return sizeof(ThreadLocal) + sizeof(registers_);}// Default break enabled.bool Debug::disable_break_ = false;// Default call debugger on uncaught exception.bool Debug::break_on_exception_ = false;bool Debug::break_on_uncaught_exception_ = true;Handle<Context> Debug::debug_context_ = Handle<Context>();Code* Debug::debug_break_return_entry_ = NULL;Code* Debug::debug_break_return_ = NULL;void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Object> obj, void* data) { DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data); RemoveDebugInfo(node->debug_info());#ifdef DEBUG node = Debug::debug_info_list_; while (node != NULL) { ASSERT(node != reinterpret_cast<DebugInfoListNode*>(data)); node = node->next(); }#endif}DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { // Globalize the request debug info object and make it weak. debug_info_ = Handle<DebugInfo>::cast((GlobalHandles::Create(debug_info))); GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()), this, Debug::HandleWeakDebugInfo);}DebugInfoListNode::~DebugInfoListNode() { GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location()));}void Debug::Setup(bool create_heap_objects) { ThreadInit(); if (create_heap_objects) { // Get code to handle entry to debug break on return. debug_break_return_entry_ = Builtins::builtin(Builtins::Return_DebugBreakEntry); ASSERT(debug_break_return_entry_->IsCode()); // Get code to handle debug break on return. debug_break_return_ = Builtins::builtin(Builtins::Return_DebugBreak); ASSERT(debug_break_return_->IsCode()); }}bool Debug::CompileDebuggerScript(int index) { HandleScope scope; // Bail out if the index is invalid. if (index == -1) { return false; } // Find source and name for the requested script. Handle<String> source_code = Bootstrapper::NativesSourceLookup(index); Vector<const char> name = Natives::GetScriptName(index); Handle<String> script_name = Factory::NewStringFromAscii(name); // Compile the script. bool allow_natives_syntax = FLAG_allow_natives_syntax; FLAG_allow_natives_syntax = true; Handle<JSFunction> boilerplate; boilerplate = Compiler::Compile(source_code, script_name, 0, 0, NULL, NULL); FLAG_allow_natives_syntax = allow_natives_syntax; // Silently ignore stack overflows during compilation. if (boilerplate.is_null()) { ASSERT(Top::has_pending_exception()); Top::clear_pending_exception(); return false; } // Execute the boilerplate function in the debugger context. Handle<Context> context = Top::global_context(); bool caught_exception = false; Handle<JSFunction> function = Factory::NewFunctionFromBoilerplate(boilerplate, context); Handle<Object> result = Execution::TryCall(function, Handle<Object>(context->global()), 0, NULL, &caught_exception); // Check for caught exceptions. if (caught_exception) { Handle<Object> message = MessageHandler::MakeMessageObject( "error_loading_debugger", NULL, HandleVector<Object>(&result, 1), Handle<String>()); MessageHandler::ReportMessage(NULL, message); return false; } // Mark this script as native and return successfully. Handle<Script> script(Script::cast(function->shared()->script())); script->set_type(Smi::FromInt(SCRIPT_TYPE_NATIVE)); return true;}bool Debug::Load() { // Return if debugger is already loaded. if (IsLoaded()) return true; // Bail out if we're already in the process of compiling the native // JavaScript source code for the debugger. if (Debugger::compiling_natives() || Debugger::is_loading_debugger()) return false; Debugger::set_loading_debugger(true); // Disable breakpoints and interrupts while compiling and running the // debugger scripts including the context creation code. DisableBreak disable(true); PostponeInterruptsScope postpone; // Create the debugger context. HandleScope scope; Handle<Context> context = Bootstrapper::CreateEnvironment(Handle<Object>::null(), v8::Handle<ObjectTemplate>(), NULL); // Use the debugger context. SaveContext save; Top::set_context(*context); Top::set_security_context(*context); // Expose the builtins object in the debugger context. Handle<String> key = Factory::LookupAsciiSymbol("builtins"); Handle<GlobalObject> global = Handle<GlobalObject>(context->global()); SetProperty(global, key, Handle<Object>(global->builtins()), NONE); // Compile the JavaScript for the debugger in the debugger context. Debugger::set_compiling_natives(true); bool caught_exception = !CompileDebuggerScript(Natives::GetIndex("mirror")) || !CompileDebuggerScript(Natives::GetIndex("debug")); Debugger::set_compiling_natives(false); // Make sure we mark the debugger as not loading before we might // return. Debugger::set_loading_debugger(false); // Check for caught exceptions. if (caught_exception) return false; // Debugger loaded. debug_context_ = Handle<Context>::cast(GlobalHandles::Create(*context)); return true;}void Debug::Unload() { // Return debugger is not loaded. if (!IsLoaded()) { return; } // Clear debugger context global handle. GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location())); debug_context_ = Handle<Context>();}void Debug::Iterate(ObjectVisitor* v) {#define VISIT(field) v->VisitPointer(reinterpret_cast<Object**>(&(field))); VISIT(debug_break_return_entry_); VISIT(debug_break_return_);#undef VISIT}Object* Debug::Break(Arguments args) { HandleScope scope; ASSERT(args.length() == 0); // Get the top-most JavaScript frame. JavaScriptFrameIterator it; JavaScriptFrame* frame = it.frame(); // Just continue if breaks are disabled or debugger cannot be loaded. if (disable_break() || !Load()) { SetAfterBreakTarget(frame); return Heap::undefined_value(); } SaveBreakFrame save; EnterDebuggerContext enter; // Postpone interrupt during breakpoint processing. PostponeInterruptsScope postpone; // Get the debug info (create it if it does not exist). Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared()); Handle<DebugInfo> debug_info = GetDebugInfo(shared); // Find the break point where execution has stopped. BreakLocationIterator break_location_iterator(debug_info, ALL_BREAK_LOCATIONS); break_location_iterator.FindBreakLocationFromAddress(frame->pc()); // Check whether step next reached a new statement. if (!StepNextContinue(&break_location_iterator, frame)) { // Decrease steps left if performing multiple steps. if (thread_local_.step_count_ > 0) { thread_local_.step_count_--; } } // If there is one or more real break points check whether any of these are // triggered. Handle<Object> break_points_hit(Heap::undefined_value()); if (break_location_iterator.HasBreakPoint()) { Handle<Object> break_point_objects = Handle<Object>(break_location_iterator.BreakPointObjects()); break_points_hit = CheckBreakPoints(break_point_objects); } // Notify debugger if a real break point is triggered or if performing single // stepping with no more steps to perform. Otherwise do another step. if (!break_points_hit->IsUndefined() || (thread_local_.last_step_action_ != StepNone && thread_local_.step_count_ == 0)) { // Clear all current stepping setup. ClearStepping(); // Notify the debug event listeners. Debugger::OnDebugBreak(break_points_hit); } else if (thread_local_.last_step_action_ != StepNone) { // Hold on to last step action as it is cleared by the call to // ClearStepping. StepAction step_action = thread_local_.last_step_action_; int step_count = thread_local_.step_count_; // Clear all current stepping setup. ClearStepping(); // Set up for the remaining steps. PrepareStep(step_action, step_count); } // Install jump to the call address which was overwritten. SetAfterBreakTarget(frame); return Heap::undefined_value();}// Check the break point objects for whether one or more are actually// triggered. This function returns a JSArray with the break point objects// which is triggered.Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) { int break_points_hit_count = 0; Handle<JSArray> break_points_hit = Factory::NewJSArray(1); // If there are multiple break points they are in a FixedArray. ASSERT(!break_point_objects->IsUndefined()); if (break_point_objects->IsFixedArray()) { Handle<FixedArray> array(FixedArray::cast(*break_point_objects)); for (int i = 0; i < array->length(); i++) { Handle<Object> o(array->get(i)); if (CheckBreakPoint(o)) { break_points_hit->SetElement(break_points_hit_count++, *o); } } } else { if (CheckBreakPoint(break_point_objects)) { break_points_hit->SetElement(break_points_hit_count++, *break_point_objects); } } // Return undefined if no break points where triggered. if (break_points_hit_count == 0) { return Factory::undefined_value(); } return break_points_hit;}// Check whether a single break point object is triggered.bool Debug::CheckBreakPoint(Handle<Object> break_point_object) { // Ignore check if break point object is not a JSObject. if (!break_point_object->IsJSObject()) return true; // Get the function CheckBreakPoint (defined in debug.js). Handle<JSFunction> check_break_point = Handle<JSFunction>(JSFunction::cast( debug_context()->global()->GetProperty( *Factory::LookupAsciiSymbol("IsBreakPointTriggered")))); // Get the break id as an object. Handle<Object> break_id = Factory::NewNumberFromInt(Top::break_id()); // Call HandleBreakPointx. bool caught_exception = false; const int argc = 2; Object** argv[argc] = { break_id.location(), reinterpret_cast<Object**>(break_point_object.location()) }; Handle<Object> result = Execution::TryCall(check_break_point, Top::builtins(), argc, argv, &caught_exception); // If exception or non boolean result handle as not triggered if (caught_exception || !result->IsBoolean()) { return false; } // Return whether the break point is triggered. return *result == Heap::true_value();}// Check whether the function has debug information.bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) { return !shared->debug_info()->IsUndefined();}// Return the debug info for this function. EnsureDebugInfo must be called// prior to ensure the debug info has been generated for shared.Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) { ASSERT(HasDebugInfo(shared)); return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));}void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared, int source_position, Handle<Object> break_point_object) { if (!EnsureDebugInfo(shared)) { // Return if retrieving debug info failed.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -