ComputeCallDebugBreak(int argc, Code::Kind kind) { Isolate* isolate = Isolate::Current(); CALL_HEAP_FUNCTION( isolate, isolate->stub_cache()->ComputeCallDebugBreak(argc, kind), Code); } static Handle ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind) { Isolate* isolate = Isolate::Current(); CALL_HEAP_FUNCTION( isolate, isolate->stub_cache()->ComputeCallDebugPrepareStepIn(argc, kind), Code); } static v8::Handle GetDebugEventContext(Isolate* isolate) { Handle context = isolate->debug()->debugger_entry()->GetContext(); // Isolate::context() may have been NULL when "script collected" event // occured. if (context.is_null()) return v8::Local(); Handle global_context(context->global_context()); return v8::Utils::ToLocal(global_context); } BreakLocationIterator::BreakLocationIterator(Handle debug_info, BreakLocatorType type) { debug_info_ = debug_info; type_ = type; reloc_iterator_ = NULL; reloc_iterator_original_ = NULL; Reset(); // Initialize the rest of the member variables. } BreakLocationIterator::~BreakLocationIterator() { ASSERT(reloc_iterator_ != NULL); ASSERT(reloc_iterator_original_ != NULL); delete reloc_iterator_; delete reloc_iterator_original_; } void BreakLocationIterator::Next() { AssertNoAllocation nogc; ASSERT(!RinfoDone()); // Iterate through reloc info for code and original code stopping at each // breakable code target. bool first = break_point_ == -1; while (!RinfoDone()) { if (!first) RinfoNext(); first = false; if (RinfoDone()) return; // Whenever a statement position or (plain) position is passed update the // current value of these. if (RelocInfo::IsPosition(rmode())) { if (RelocInfo::IsStatementPosition(rmode())) { statement_position_ = static_cast( rinfo()->data() - debug_info_->shared()->start_position()); } // Always update the position as we don't want that to be before the // statement position. position_ = static_cast( rinfo()->data() - debug_info_->shared()->start_position()); ASSERT(position_ >= 0); ASSERT(statement_position_ >= 0); } if (IsDebugBreakSlot()) { // There is always a possible break point at a debug break slot. break_point_++; return; } else if (RelocInfo::IsCodeTarget(rmode())) { // Check for breakable code target. Look in the original code as setting // break points can cause the code targets in the running (debugged) code // to be of a different kind than in the original code. Address target = original_rinfo()->target_address(); Code* code = Code::GetCodeFromTargetAddress(target); if ((code->is_inline_cache_stub() && !code->is_type_recording_binary_op_stub() && !code->is_compare_ic_stub()) || RelocInfo::IsConstructCall(rmode())) { break_point_++; return; } if (code->kind() == Code::STUB) { if (IsDebuggerStatement()) { break_point_++; return; } if (type_ == ALL_BREAK_LOCATIONS) { if (Debug::IsBreakStub(code)) { break_point_++; return; } } else { ASSERT(type_ == SOURCE_BREAK_LOCATIONS); if (Debug::IsSourceBreakStub(code)) { break_point_++; return; } } } } // Check for break at return. if (RelocInfo::IsJSReturn(rmode())) { // Set the positions to the end of the function. if (debug_info_->shared()->HasSourceCode()) { position_ = debug_info_->shared()->end_position() - debug_info_->shared()->start_position() - 1; } else { position_ = 0; } statement_position_ = position_; break_point_++; return; } } } void BreakLocationIterator::Next(int count) { while (count > 0) { Next(); count--; } } // Find the break point closest to the supplied address. void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) { // Run through all break points to locate the one closest to the address. int closest_break_point = 0; int distance = kMaxInt; while (!Done()) { // Check if this break point is closer that what was previously found. if (this->pc() < pc && pc - this->pc() < distance) { closest_break_point = break_point(); distance = static_cast(pc - this->pc()); // Check whether we can't get any closer. if (distance == 0) break; } Next(); } // Move to the break point found. Reset(); Next(closest_break_point); } // Find the break point closest to the supplied source position. void BreakLocationIterator::FindBreakLocationFromPosition(int position) { // Run through all break points to locate the one closest to the source // position. int closest_break_point = 0; int distance = kMaxInt; while (!Done()) { // Check if this break point is closer that what was previously found. if (position <= statement_position() && statement_position() - position < distance) { closest_break_point = break_point(); distance = statement_position() - position; // Check whether we can't get any closer. if (distance == 0) break; } Next(); } // Move to the break point found. Reset(); Next(closest_break_point); } void BreakLocationIterator::Reset() { // Create relocation iterators for the two code objects. if (reloc_iterator_ != NULL) delete reloc_iterator_; if (reloc_iterator_original_ != NULL) delete reloc_iterator_original_; reloc_iterator_ = new RelocIterator(debug_info_->code()); reloc_iterator_original_ = new RelocIterator(debug_info_->original_code()); // Position at the first break point. break_point_ = -1; position_ = 1; statement_position_ = 1; Next(); } bool BreakLocationIterator::Done() const { return RinfoDone(); } void BreakLocationIterator::SetBreakPoint(Handle break_point_object) { // If there is not already a real break point here patch code with debug // break. if (!HasBreakPoint()) { SetDebugBreak(); } ASSERT(IsDebugBreak() || IsDebuggerStatement()); // Set the break point information. DebugInfo::SetBreakPoint(debug_info_, code_position(), position(), statement_position(), break_point_object); } void BreakLocationIterator::ClearBreakPoint(Handle break_point_object) { // Clear the break point information. DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object); // If there are no more break points here remove the debug break. if (!HasBreakPoint()) { ClearDebugBreak(); ASSERT(!IsDebugBreak()); } } void BreakLocationIterator::SetOneShot() { // Debugger statement always calls debugger. No need to modify it. if (IsDebuggerStatement()) { return; } // If there is a real break point here no more to do. if (HasBreakPoint()) { ASSERT(IsDebugBreak()); return; } // Patch code with debug break. SetDebugBreak(); } void BreakLocationIterator::ClearOneShot() { // Debugger statement always calls debugger. No need to modify it. if (IsDebuggerStatement()) { return; } // If there is a real break point here no more to do. if (HasBreakPoint()) { ASSERT(IsDebugBreak()); return; } // Patch code removing debug break. ClearDebugBreak(); ASSERT(!IsDebugBreak()); } void BreakLocationIterator::SetDebugBreak() { // Debugger statement always calls debugger. No need to modify it. if (IsDebuggerStatement()) { return; } // If there is already a break point here just return. This might happen if // the same code is flooded with break points twice. Flooding the same // function twice might happen when stepping in a function with an exception // handler as the handler and the function is the same. if (IsDebugBreak()) { return; } if (RelocInfo::IsJSReturn(rmode())) { // Patch the frame exit code with a break point. SetDebugBreakAtReturn(); } else if (IsDebugBreakSlot()) { // Patch the code in the break slot. SetDebugBreakAtSlot(); } else { // Patch the IC call. SetDebugBreakAtIC(); } ASSERT(IsDebugBreak()); } void BreakLocationIterator::ClearDebugBreak() { // Debugger statement always calls debugger. No need to modify it. if (IsDebuggerStatement()) { return; } if (RelocInfo::IsJSReturn(rmode())) { // Restore the frame exit code. ClearDebugBreakAtReturn(); } else if (IsDebugBreakSlot()) { // Restore the code in the break slot. ClearDebugBreakAtSlot(); } else { // Patch the IC call. ClearDebugBreakAtIC(); } ASSERT(!IsDebugBreak()); } void BreakLocationIterator::PrepareStepIn() { HandleScope scope; // Step in can only be prepared if currently positioned on an IC call, // construct call or CallFunction stub call. Address target = rinfo()->target_address(); Handle code(Code::GetCodeFromTargetAddress(target)); if (code->is_call_stub() || code->is_keyed_call_stub()) { // Step in through IC call is handled by the runtime system. Therefore make // sure that the any current IC is cleared and the runtime system is // called. If the executing code has a debug break at the location change // the call in the original code as it is the code there that will be // executed in place of the debug break call. Handle stub = ComputeCallDebugPrepareStepIn(code->arguments_count(), code->kind()); if (IsDebugBreak()) { original_rinfo()->set_target_address(stub->entry()); } else { rinfo()->set_target_address(stub->entry()); } } else { #ifdef DEBUG // All the following stuff is needed only for assertion checks so the code // is wrapped in ifdef. Handle maybe_call_function_stub = code; if (IsDebugBreak()) { Address original_target = original_rinfo()->target_address(); maybe_call_function_stub = Handle(Code::GetCodeFromTargetAddress(original_target)); } bool is_call_function_stub = (maybe_call_function_stub->kind() == Code::STUB && maybe_call_function_stub->major_key() == CodeStub::CallFunction); // Step in through construct call requires no changes to the running code. // Step in through getters/setters should already be prepared as well // because caller of this function (Debug::PrepareStep) is expected to // flood the top frame's function with one shot breakpoints. // Step in through CallFunction stub should also be prepared by caller of // this function (Debug::PrepareStep) which should flood target function // with breakpoints. ASSERT(RelocInfo::IsConstructCall(rmode()) || code->is_inline_cache_stub() || is_call_function_stub); #endif } } // Check whether the break point is at a position which will exit the function. bool BreakLocationIterator::IsExit() const { return (RelocInfo::IsJSReturn(rmode())); } bool BreakLocationIterator::HasBreakPoint() { return debug_info_->HasBreakPoint(code_position()); } // Check whether there is a debug break at the current position. bool BreakLocationIterator::IsDebugBreak() { if (RelocInfo::IsJSReturn(rmode())) { return IsDebugBreakAtReturn(); } else if (IsDebugBreakSlot()) { return IsDebugBreakAtSlot(); } else { return Debug::IsDebugBreak(rinfo()->target_address()); } } void BreakLocationIterator::SetDebugBreakAtIC() { // Patch the original code with the current address as the current address // might have changed by the inline caching since the code was copied. original_rinfo()->set_target_address(rinfo()->target_address()); RelocInfo::Mode mode = rmode(); if (RelocInfo::IsCodeTarget(mode)) { Address target = rinfo()->target_address(); Handle code(Code::GetCodeFromTargetAddress(target)); // Patch the code to invoke the builtin debug break function matching the // calling convention used by the call site. Handle dbgbrk_code(Debug::FindDebugBreak(code, mode)); rinfo()->set_target_address(dbgbrk_code->entry()); // For stubs that refer back to an inlined version clear the cached map for // the inlined case to always go through the IC. As long as the break point // is set the patching performed by the runtime system will take place in // the code copy and will therefore have no effect on the running code // keeping it from using the inlined code. if (code->is_keyed_load_stub()) { KeyedLoadIC::ClearInlinedVersion(pc()); } else if (code->is_keyed_store_stub()) { KeyedStoreIC::ClearInlinedVersion(pc()); } else if (code->is_load_stub()) { LoadIC::ClearInlinedVersion(pc()); } else if (code->is_store_stub()) { StoreIC::ClearInlinedVersion(pc()); } } } void BreakLocationIterator::ClearDebugBreakAtIC() { // Patch the code to the original invoke. rinfo()->set_target_address(original_rinfo()->target_address()); RelocInfo::Mode mode = rmode(); if (RelocInfo::IsCodeTarget(mode)) { AssertNoAllocation nogc; Address target = original_rinfo()->target_address(); Code* code = Code::GetCodeFromTargetAddress(target); // Restore the inlined version of keyed stores to get back to the // fast case. We need to patch back the keyed store because no // patching happens when running normally. For keyed loads, the // map check will get patched back when running normally after ICs // have been cleared at GC. if (code->is_keyed_store_stub()) KeyedStoreIC::RestoreInlinedVersion(pc()); } } bool BreakLocationIterator::IsDebuggerStatement() { return RelocInfo::DEBUG_BREAK == rmode(); } bool BreakLocationIterator::IsDebugBreakSlot() { return RelocInfo::DEBUG_BREAK_SLOT == rmode(); } Object* BreakLocationIterator::BreakPointObjects() { return debug_info_->GetBreakPointObjects(code_position()); } // Clear out all the debug break code. This is ONLY supposed to be used when // shutting down the debugger as it will leave the break point information in // DebugInfo even though the code is patched back to the non break point state. void BreakLocationIterator::ClearAllDebugBreak() { while (!Done()) { ClearDebugBreak(); Next(); } } bool BreakLocationIterator::RinfoDone() const { ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); return reloc_iterator_->done(); } void BreakLocationIterator::RinfoNext() { reloc_iterator_->next(); reloc_iterator_original_->next(); #ifdef DEBUG ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); if (!reloc_iterator_->done()) { ASSERT(rmode() == original_rmode()); } #endif } // Threading support. void Debug::ThreadInit() { thread_local_.break_count_ = 0; thread_local_.break_id_ = 0; thread_local_.break_frame_id_ = StackFrame::NO_ID; 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_.step_out_fp_ = 0; thread_local_.after_break_target_ = 0; // TODO(isolates): frames_are_dropped_? thread_local_.debugger_entry_ = NULL; thread_local_.pending_interrupts_ = 0; thread_local_.restarter_frame_function_pointer_ = NULL; } char* Debug::ArchiveDebug(char* storage) { char* to = storage; memcpy(to, reinterpret_cast(&thread_local_), sizeof(ThreadLocal)); to += sizeof(ThreadLocal); memcpy(to, reinterpret_cast(®isters_), sizeof(registers_)); ThreadInit(); ASSERT(to <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread(); } char* Debug::RestoreDebug(char* storage) { char* from = storage; memcpy(reinterpret_cast(&thread_local_), from, sizeof(ThreadLocal)); from += sizeof(ThreadLocal); memcpy(reinterpret_cast(®isters_), from, sizeof(registers_)); ASSERT(from <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread(); } int Debug::ArchiveSpacePerThread() { return sizeof(ThreadLocal) + sizeof(JSCallerSavedBuffer); } // Frame structure (conforms InternalFrame structure): // -- code // -- SMI maker // -- function (slot is called "context") // -- frame base Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame, Handle code) { ASSERT(bottom_js_frame->is_java_script()); Address fp = bottom_js_frame->fp(); // Move function pointer into "context" slot. Memory::Object_at(fp + StandardFrameConstants::kContextOffset) = Memory::Object_at(fp + JavaScriptFrameConstants::kFunctionOffset); Memory::Object_at(fp + InternalFrameConstants::kCodeOffset) = *code; Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset) = Smi::FromInt(StackFrame::INTERNAL); return reinterpret_cast(&Memory::Object_at( fp + StandardFrameConstants::kContextOffset)); } const int Debug::kFrameDropperFrameSize = 4; void ScriptCache::Add(Handle 登录后可以享受更多权益 您还没有登录,登录后您可以: 收藏Android系统代码 收藏喜欢的文章 多个平台共享账号 去登录 首次使用?从这里 注册
ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind) { Isolate* isolate = Isolate::Current(); CALL_HEAP_FUNCTION( isolate, isolate->stub_cache()->ComputeCallDebugPrepareStepIn(argc, kind), Code); } static v8::Handle GetDebugEventContext(Isolate* isolate) { Handle context = isolate->debug()->debugger_entry()->GetContext(); // Isolate::context() may have been NULL when "script collected" event // occured. if (context.is_null()) return v8::Local(); Handle global_context(context->global_context()); return v8::Utils::ToLocal(global_context); } BreakLocationIterator::BreakLocationIterator(Handle debug_info, BreakLocatorType type) { debug_info_ = debug_info; type_ = type; reloc_iterator_ = NULL; reloc_iterator_original_ = NULL; Reset(); // Initialize the rest of the member variables. } BreakLocationIterator::~BreakLocationIterator() { ASSERT(reloc_iterator_ != NULL); ASSERT(reloc_iterator_original_ != NULL); delete reloc_iterator_; delete reloc_iterator_original_; } void BreakLocationIterator::Next() { AssertNoAllocation nogc; ASSERT(!RinfoDone()); // Iterate through reloc info for code and original code stopping at each // breakable code target. bool first = break_point_ == -1; while (!RinfoDone()) { if (!first) RinfoNext(); first = false; if (RinfoDone()) return; // Whenever a statement position or (plain) position is passed update the // current value of these. if (RelocInfo::IsPosition(rmode())) { if (RelocInfo::IsStatementPosition(rmode())) { statement_position_ = static_cast( rinfo()->data() - debug_info_->shared()->start_position()); } // Always update the position as we don't want that to be before the // statement position. position_ = static_cast( rinfo()->data() - debug_info_->shared()->start_position()); ASSERT(position_ >= 0); ASSERT(statement_position_ >= 0); } if (IsDebugBreakSlot()) { // There is always a possible break point at a debug break slot. break_point_++; return; } else if (RelocInfo::IsCodeTarget(rmode())) { // Check for breakable code target. Look in the original code as setting // break points can cause the code targets in the running (debugged) code // to be of a different kind than in the original code. Address target = original_rinfo()->target_address(); Code* code = Code::GetCodeFromTargetAddress(target); if ((code->is_inline_cache_stub() && !code->is_type_recording_binary_op_stub() && !code->is_compare_ic_stub()) || RelocInfo::IsConstructCall(rmode())) { break_point_++; return; } if (code->kind() == Code::STUB) { if (IsDebuggerStatement()) { break_point_++; return; } if (type_ == ALL_BREAK_LOCATIONS) { if (Debug::IsBreakStub(code)) { break_point_++; return; } } else { ASSERT(type_ == SOURCE_BREAK_LOCATIONS); if (Debug::IsSourceBreakStub(code)) { break_point_++; return; } } } } // Check for break at return. if (RelocInfo::IsJSReturn(rmode())) { // Set the positions to the end of the function. if (debug_info_->shared()->HasSourceCode()) { position_ = debug_info_->shared()->end_position() - debug_info_->shared()->start_position() - 1; } else { position_ = 0; } statement_position_ = position_; break_point_++; return; } } } void BreakLocationIterator::Next(int count) { while (count > 0) { Next(); count--; } } // Find the break point closest to the supplied address. void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) { // Run through all break points to locate the one closest to the address. int closest_break_point = 0; int distance = kMaxInt; while (!Done()) { // Check if this break point is closer that what was previously found. if (this->pc() < pc && pc - this->pc() < distance) { closest_break_point = break_point(); distance = static_cast(pc - this->pc()); // Check whether we can't get any closer. if (distance == 0) break; } Next(); } // Move to the break point found. Reset(); Next(closest_break_point); } // Find the break point closest to the supplied source position. void BreakLocationIterator::FindBreakLocationFromPosition(int position) { // Run through all break points to locate the one closest to the source // position. int closest_break_point = 0; int distance = kMaxInt; while (!Done()) { // Check if this break point is closer that what was previously found. if (position <= statement_position() && statement_position() - position < distance) { closest_break_point = break_point(); distance = statement_position() - position; // Check whether we can't get any closer. if (distance == 0) break; } Next(); } // Move to the break point found. Reset(); Next(closest_break_point); } void BreakLocationIterator::Reset() { // Create relocation iterators for the two code objects. if (reloc_iterator_ != NULL) delete reloc_iterator_; if (reloc_iterator_original_ != NULL) delete reloc_iterator_original_; reloc_iterator_ = new RelocIterator(debug_info_->code()); reloc_iterator_original_ = new RelocIterator(debug_info_->original_code()); // Position at the first break point. break_point_ = -1; position_ = 1; statement_position_ = 1; Next(); } bool BreakLocationIterator::Done() const { return RinfoDone(); } void BreakLocationIterator::SetBreakPoint(Handle break_point_object) { // If there is not already a real break point here patch code with debug // break. if (!HasBreakPoint()) { SetDebugBreak(); } ASSERT(IsDebugBreak() || IsDebuggerStatement()); // Set the break point information. DebugInfo::SetBreakPoint(debug_info_, code_position(), position(), statement_position(), break_point_object); } void BreakLocationIterator::ClearBreakPoint(Handle break_point_object) { // Clear the break point information. DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object); // If there are no more break points here remove the debug break. if (!HasBreakPoint()) { ClearDebugBreak(); ASSERT(!IsDebugBreak()); } } void BreakLocationIterator::SetOneShot() { // Debugger statement always calls debugger. No need to modify it. if (IsDebuggerStatement()) { return; } // If there is a real break point here no more to do. if (HasBreakPoint()) { ASSERT(IsDebugBreak()); return; } // Patch code with debug break. SetDebugBreak(); } void BreakLocationIterator::ClearOneShot() { // Debugger statement always calls debugger. No need to modify it. if (IsDebuggerStatement()) { return; } // If there is a real break point here no more to do. if (HasBreakPoint()) { ASSERT(IsDebugBreak()); return; } // Patch code removing debug break. ClearDebugBreak(); ASSERT(!IsDebugBreak()); } void BreakLocationIterator::SetDebugBreak() { // Debugger statement always calls debugger. No need to modify it. if (IsDebuggerStatement()) { return; } // If there is already a break point here just return. This might happen if // the same code is flooded with break points twice. Flooding the same // function twice might happen when stepping in a function with an exception // handler as the handler and the function is the same. if (IsDebugBreak()) { return; } if (RelocInfo::IsJSReturn(rmode())) { // Patch the frame exit code with a break point. SetDebugBreakAtReturn(); } else if (IsDebugBreakSlot()) { // Patch the code in the break slot. SetDebugBreakAtSlot(); } else { // Patch the IC call. SetDebugBreakAtIC(); } ASSERT(IsDebugBreak()); } void BreakLocationIterator::ClearDebugBreak() { // Debugger statement always calls debugger. No need to modify it. if (IsDebuggerStatement()) { return; } if (RelocInfo::IsJSReturn(rmode())) { // Restore the frame exit code. ClearDebugBreakAtReturn(); } else if (IsDebugBreakSlot()) { // Restore the code in the break slot. ClearDebugBreakAtSlot(); } else { // Patch the IC call. ClearDebugBreakAtIC(); } ASSERT(!IsDebugBreak()); } void BreakLocationIterator::PrepareStepIn() { HandleScope scope; // Step in can only be prepared if currently positioned on an IC call, // construct call or CallFunction stub call. Address target = rinfo()->target_address(); Handle code(Code::GetCodeFromTargetAddress(target)); if (code->is_call_stub() || code->is_keyed_call_stub()) { // Step in through IC call is handled by the runtime system. Therefore make // sure that the any current IC is cleared and the runtime system is // called. If the executing code has a debug break at the location change // the call in the original code as it is the code there that will be // executed in place of the debug break call. Handle stub = ComputeCallDebugPrepareStepIn(code->arguments_count(), code->kind()); if (IsDebugBreak()) { original_rinfo()->set_target_address(stub->entry()); } else { rinfo()->set_target_address(stub->entry()); } } else { #ifdef DEBUG // All the following stuff is needed only for assertion checks so the code // is wrapped in ifdef. Handle maybe_call_function_stub = code; if (IsDebugBreak()) { Address original_target = original_rinfo()->target_address(); maybe_call_function_stub = Handle(Code::GetCodeFromTargetAddress(original_target)); } bool is_call_function_stub = (maybe_call_function_stub->kind() == Code::STUB && maybe_call_function_stub->major_key() == CodeStub::CallFunction); // Step in through construct call requires no changes to the running code. // Step in through getters/setters should already be prepared as well // because caller of this function (Debug::PrepareStep) is expected to // flood the top frame's function with one shot breakpoints. // Step in through CallFunction stub should also be prepared by caller of // this function (Debug::PrepareStep) which should flood target function // with breakpoints. ASSERT(RelocInfo::IsConstructCall(rmode()) || code->is_inline_cache_stub() || is_call_function_stub); #endif } } // Check whether the break point is at a position which will exit the function. bool BreakLocationIterator::IsExit() const { return (RelocInfo::IsJSReturn(rmode())); } bool BreakLocationIterator::HasBreakPoint() { return debug_info_->HasBreakPoint(code_position()); } // Check whether there is a debug break at the current position. bool BreakLocationIterator::IsDebugBreak() { if (RelocInfo::IsJSReturn(rmode())) { return IsDebugBreakAtReturn(); } else if (IsDebugBreakSlot()) { return IsDebugBreakAtSlot(); } else { return Debug::IsDebugBreak(rinfo()->target_address()); } } void BreakLocationIterator::SetDebugBreakAtIC() { // Patch the original code with the current address as the current address // might have changed by the inline caching since the code was copied. original_rinfo()->set_target_address(rinfo()->target_address()); RelocInfo::Mode mode = rmode(); if (RelocInfo::IsCodeTarget(mode)) { Address target = rinfo()->target_address(); Handle code(Code::GetCodeFromTargetAddress(target)); // Patch the code to invoke the builtin debug break function matching the // calling convention used by the call site. Handle dbgbrk_code(Debug::FindDebugBreak(code, mode)); rinfo()->set_target_address(dbgbrk_code->entry()); // For stubs that refer back to an inlined version clear the cached map for // the inlined case to always go through the IC. As long as the break point // is set the patching performed by the runtime system will take place in // the code copy and will therefore have no effect on the running code // keeping it from using the inlined code. if (code->is_keyed_load_stub()) { KeyedLoadIC::ClearInlinedVersion(pc()); } else if (code->is_keyed_store_stub()) { KeyedStoreIC::ClearInlinedVersion(pc()); } else if (code->is_load_stub()) { LoadIC::ClearInlinedVersion(pc()); } else if (code->is_store_stub()) { StoreIC::ClearInlinedVersion(pc()); } } } void BreakLocationIterator::ClearDebugBreakAtIC() { // Patch the code to the original invoke. rinfo()->set_target_address(original_rinfo()->target_address()); RelocInfo::Mode mode = rmode(); if (RelocInfo::IsCodeTarget(mode)) { AssertNoAllocation nogc; Address target = original_rinfo()->target_address(); Code* code = Code::GetCodeFromTargetAddress(target); // Restore the inlined version of keyed stores to get back to the // fast case. We need to patch back the keyed store because no // patching happens when running normally. For keyed loads, the // map check will get patched back when running normally after ICs // have been cleared at GC. if (code->is_keyed_store_stub()) KeyedStoreIC::RestoreInlinedVersion(pc()); } } bool BreakLocationIterator::IsDebuggerStatement() { return RelocInfo::DEBUG_BREAK == rmode(); } bool BreakLocationIterator::IsDebugBreakSlot() { return RelocInfo::DEBUG_BREAK_SLOT == rmode(); } Object* BreakLocationIterator::BreakPointObjects() { return debug_info_->GetBreakPointObjects(code_position()); } // Clear out all the debug break code. This is ONLY supposed to be used when // shutting down the debugger as it will leave the break point information in // DebugInfo even though the code is patched back to the non break point state. void BreakLocationIterator::ClearAllDebugBreak() { while (!Done()) { ClearDebugBreak(); Next(); } } bool BreakLocationIterator::RinfoDone() const { ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); return reloc_iterator_->done(); } void BreakLocationIterator::RinfoNext() { reloc_iterator_->next(); reloc_iterator_original_->next(); #ifdef DEBUG ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); if (!reloc_iterator_->done()) { ASSERT(rmode() == original_rmode()); } #endif } // Threading support. void Debug::ThreadInit() { thread_local_.break_count_ = 0; thread_local_.break_id_ = 0; thread_local_.break_frame_id_ = StackFrame::NO_ID; 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_.step_out_fp_ = 0; thread_local_.after_break_target_ = 0; // TODO(isolates): frames_are_dropped_? thread_local_.debugger_entry_ = NULL; thread_local_.pending_interrupts_ = 0; thread_local_.restarter_frame_function_pointer_ = NULL; } char* Debug::ArchiveDebug(char* storage) { char* to = storage; memcpy(to, reinterpret_cast(&thread_local_), sizeof(ThreadLocal)); to += sizeof(ThreadLocal); memcpy(to, reinterpret_cast(®isters_), sizeof(registers_)); ThreadInit(); ASSERT(to <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread(); } char* Debug::RestoreDebug(char* storage) { char* from = storage; memcpy(reinterpret_cast(&thread_local_), from, sizeof(ThreadLocal)); from += sizeof(ThreadLocal); memcpy(reinterpret_cast(®isters_), from, sizeof(registers_)); ASSERT(from <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread(); } int Debug::ArchiveSpacePerThread() { return sizeof(ThreadLocal) + sizeof(JSCallerSavedBuffer); } // Frame structure (conforms InternalFrame structure): // -- code // -- SMI maker // -- function (slot is called "context") // -- frame base Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame, Handle code) { ASSERT(bottom_js_frame->is_java_script()); Address fp = bottom_js_frame->fp(); // Move function pointer into "context" slot. Memory::Object_at(fp + StandardFrameConstants::kContextOffset) = Memory::Object_at(fp + JavaScriptFrameConstants::kFunctionOffset); Memory::Object_at(fp + InternalFrameConstants::kCodeOffset) = *code; Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset) = Smi::FromInt(StackFrame::INTERNAL); return reinterpret_cast(&Memory::Object_at( fp + StandardFrameConstants::kContextOffset)); } const int Debug::kFrameDropperFrameSize = 4; void ScriptCache::Add(Handle 登录后可以享受更多权益 您还没有登录,登录后您可以: 收藏Android系统代码 收藏喜欢的文章 多个平台共享账号 去登录 首次使用?从这里 注册
code(Code::GetCodeFromTargetAddress(target)); if (code->is_call_stub() || code->is_keyed_call_stub()) { // Step in through IC call is handled by the runtime system. Therefore make // sure that the any current IC is cleared and the runtime system is // called. If the executing code has a debug break at the location change // the call in the original code as it is the code there that will be // executed in place of the debug break call. Handle stub = ComputeCallDebugPrepareStepIn(code->arguments_count(), code->kind()); if (IsDebugBreak()) { original_rinfo()->set_target_address(stub->entry()); } else { rinfo()->set_target_address(stub->entry()); } } else { #ifdef DEBUG // All the following stuff is needed only for assertion checks so the code // is wrapped in ifdef. Handle maybe_call_function_stub = code; if (IsDebugBreak()) { Address original_target = original_rinfo()->target_address(); maybe_call_function_stub = Handle(Code::GetCodeFromTargetAddress(original_target)); } bool is_call_function_stub = (maybe_call_function_stub->kind() == Code::STUB && maybe_call_function_stub->major_key() == CodeStub::CallFunction); // Step in through construct call requires no changes to the running code. // Step in through getters/setters should already be prepared as well // because caller of this function (Debug::PrepareStep) is expected to // flood the top frame's function with one shot breakpoints. // Step in through CallFunction stub should also be prepared by caller of // this function (Debug::PrepareStep) which should flood target function // with breakpoints. ASSERT(RelocInfo::IsConstructCall(rmode()) || code->is_inline_cache_stub() || is_call_function_stub); #endif } } // Check whether the break point is at a position which will exit the function. bool BreakLocationIterator::IsExit() const { return (RelocInfo::IsJSReturn(rmode())); } bool BreakLocationIterator::HasBreakPoint() { return debug_info_->HasBreakPoint(code_position()); } // Check whether there is a debug break at the current position. bool BreakLocationIterator::IsDebugBreak() { if (RelocInfo::IsJSReturn(rmode())) { return IsDebugBreakAtReturn(); } else if (IsDebugBreakSlot()) { return IsDebugBreakAtSlot(); } else { return Debug::IsDebugBreak(rinfo()->target_address()); } } void BreakLocationIterator::SetDebugBreakAtIC() { // Patch the original code with the current address as the current address // might have changed by the inline caching since the code was copied. original_rinfo()->set_target_address(rinfo()->target_address()); RelocInfo::Mode mode = rmode(); if (RelocInfo::IsCodeTarget(mode)) { Address target = rinfo()->target_address(); Handle code(Code::GetCodeFromTargetAddress(target)); // Patch the code to invoke the builtin debug break function matching the // calling convention used by the call site. Handle dbgbrk_code(Debug::FindDebugBreak(code, mode)); rinfo()->set_target_address(dbgbrk_code->entry()); // For stubs that refer back to an inlined version clear the cached map for // the inlined case to always go through the IC. As long as the break point // is set the patching performed by the runtime system will take place in // the code copy and will therefore have no effect on the running code // keeping it from using the inlined code. if (code->is_keyed_load_stub()) { KeyedLoadIC::ClearInlinedVersion(pc()); } else if (code->is_keyed_store_stub()) { KeyedStoreIC::ClearInlinedVersion(pc()); } else if (code->is_load_stub()) { LoadIC::ClearInlinedVersion(pc()); } else if (code->is_store_stub()) { StoreIC::ClearInlinedVersion(pc()); } } } void BreakLocationIterator::ClearDebugBreakAtIC() { // Patch the code to the original invoke. rinfo()->set_target_address(original_rinfo()->target_address()); RelocInfo::Mode mode = rmode(); if (RelocInfo::IsCodeTarget(mode)) { AssertNoAllocation nogc; Address target = original_rinfo()->target_address(); Code* code = Code::GetCodeFromTargetAddress(target); // Restore the inlined version of keyed stores to get back to the // fast case. We need to patch back the keyed store because no // patching happens when running normally. For keyed loads, the // map check will get patched back when running normally after ICs // have been cleared at GC. if (code->is_keyed_store_stub()) KeyedStoreIC::RestoreInlinedVersion(pc()); } } bool BreakLocationIterator::IsDebuggerStatement() { return RelocInfo::DEBUG_BREAK == rmode(); } bool BreakLocationIterator::IsDebugBreakSlot() { return RelocInfo::DEBUG_BREAK_SLOT == rmode(); } Object* BreakLocationIterator::BreakPointObjects() { return debug_info_->GetBreakPointObjects(code_position()); } // Clear out all the debug break code. This is ONLY supposed to be used when // shutting down the debugger as it will leave the break point information in // DebugInfo even though the code is patched back to the non break point state. void BreakLocationIterator::ClearAllDebugBreak() { while (!Done()) { ClearDebugBreak(); Next(); } } bool BreakLocationIterator::RinfoDone() const { ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); return reloc_iterator_->done(); } void BreakLocationIterator::RinfoNext() { reloc_iterator_->next(); reloc_iterator_original_->next(); #ifdef DEBUG ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); if (!reloc_iterator_->done()) { ASSERT(rmode() == original_rmode()); } #endif } // Threading support. void Debug::ThreadInit() { thread_local_.break_count_ = 0; thread_local_.break_id_ = 0; thread_local_.break_frame_id_ = StackFrame::NO_ID; 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_.step_out_fp_ = 0; thread_local_.after_break_target_ = 0; // TODO(isolates): frames_are_dropped_? thread_local_.debugger_entry_ = NULL; thread_local_.pending_interrupts_ = 0; thread_local_.restarter_frame_function_pointer_ = NULL; } char* Debug::ArchiveDebug(char* storage) { char* to = storage; memcpy(to, reinterpret_cast(&thread_local_), sizeof(ThreadLocal)); to += sizeof(ThreadLocal); memcpy(to, reinterpret_cast(®isters_), sizeof(registers_)); ThreadInit(); ASSERT(to <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread(); } char* Debug::RestoreDebug(char* storage) { char* from = storage; memcpy(reinterpret_cast(&thread_local_), from, sizeof(ThreadLocal)); from += sizeof(ThreadLocal); memcpy(reinterpret_cast(®isters_), from, sizeof(registers_)); ASSERT(from <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread(); } int Debug::ArchiveSpacePerThread() { return sizeof(ThreadLocal) + sizeof(JSCallerSavedBuffer); } // Frame structure (conforms InternalFrame structure): // -- code // -- SMI maker // -- function (slot is called "context") // -- frame base Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame, Handle code) { ASSERT(bottom_js_frame->is_java_script()); Address fp = bottom_js_frame->fp(); // Move function pointer into "context" slot. Memory::Object_at(fp + StandardFrameConstants::kContextOffset) = Memory::Object_at(fp + JavaScriptFrameConstants::kFunctionOffset); Memory::Object_at(fp + InternalFrameConstants::kCodeOffset) = *code; Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset) = Smi::FromInt(StackFrame::INTERNAL); return reinterpret_cast(&Memory::Object_at( fp + StandardFrameConstants::kContextOffset)); } const int Debug::kFrameDropperFrameSize = 4; void ScriptCache::Add(Handle 登录后可以享受更多权益 您还没有登录,登录后您可以: 收藏Android系统代码 收藏喜欢的文章 多个平台共享账号 去登录 首次使用?从这里 注册
stub = ComputeCallDebugPrepareStepIn(code->arguments_count(), code->kind()); if (IsDebugBreak()) { original_rinfo()->set_target_address(stub->entry()); } else { rinfo()->set_target_address(stub->entry()); } } else { #ifdef DEBUG // All the following stuff is needed only for assertion checks so the code // is wrapped in ifdef. Handle maybe_call_function_stub = code; if (IsDebugBreak()) { Address original_target = original_rinfo()->target_address(); maybe_call_function_stub = Handle(Code::GetCodeFromTargetAddress(original_target)); } bool is_call_function_stub = (maybe_call_function_stub->kind() == Code::STUB && maybe_call_function_stub->major_key() == CodeStub::CallFunction); // Step in through construct call requires no changes to the running code. // Step in through getters/setters should already be prepared as well // because caller of this function (Debug::PrepareStep) is expected to // flood the top frame's function with one shot breakpoints. // Step in through CallFunction stub should also be prepared by caller of // this function (Debug::PrepareStep) which should flood target function // with breakpoints. ASSERT(RelocInfo::IsConstructCall(rmode()) || code->is_inline_cache_stub() || is_call_function_stub); #endif } } // Check whether the break point is at a position which will exit the function. bool BreakLocationIterator::IsExit() const { return (RelocInfo::IsJSReturn(rmode())); } bool BreakLocationIterator::HasBreakPoint() { return debug_info_->HasBreakPoint(code_position()); } // Check whether there is a debug break at the current position. bool BreakLocationIterator::IsDebugBreak() { if (RelocInfo::IsJSReturn(rmode())) { return IsDebugBreakAtReturn(); } else if (IsDebugBreakSlot()) { return IsDebugBreakAtSlot(); } else { return Debug::IsDebugBreak(rinfo()->target_address()); } } void BreakLocationIterator::SetDebugBreakAtIC() { // Patch the original code with the current address as the current address // might have changed by the inline caching since the code was copied. original_rinfo()->set_target_address(rinfo()->target_address()); RelocInfo::Mode mode = rmode(); if (RelocInfo::IsCodeTarget(mode)) { Address target = rinfo()->target_address(); Handle code(Code::GetCodeFromTargetAddress(target)); // Patch the code to invoke the builtin debug break function matching the // calling convention used by the call site. Handle dbgbrk_code(Debug::FindDebugBreak(code, mode)); rinfo()->set_target_address(dbgbrk_code->entry()); // For stubs that refer back to an inlined version clear the cached map for // the inlined case to always go through the IC. As long as the break point // is set the patching performed by the runtime system will take place in // the code copy and will therefore have no effect on the running code // keeping it from using the inlined code. if (code->is_keyed_load_stub()) { KeyedLoadIC::ClearInlinedVersion(pc()); } else if (code->is_keyed_store_stub()) { KeyedStoreIC::ClearInlinedVersion(pc()); } else if (code->is_load_stub()) { LoadIC::ClearInlinedVersion(pc()); } else if (code->is_store_stub()) { StoreIC::ClearInlinedVersion(pc()); } } } void BreakLocationIterator::ClearDebugBreakAtIC() { // Patch the code to the original invoke. rinfo()->set_target_address(original_rinfo()->target_address()); RelocInfo::Mode mode = rmode(); if (RelocInfo::IsCodeTarget(mode)) { AssertNoAllocation nogc; Address target = original_rinfo()->target_address(); Code* code = Code::GetCodeFromTargetAddress(target); // Restore the inlined version of keyed stores to get back to the // fast case. We need to patch back the keyed store because no // patching happens when running normally. For keyed loads, the // map check will get patched back when running normally after ICs // have been cleared at GC. if (code->is_keyed_store_stub()) KeyedStoreIC::RestoreInlinedVersion(pc()); } } bool BreakLocationIterator::IsDebuggerStatement() { return RelocInfo::DEBUG_BREAK == rmode(); } bool BreakLocationIterator::IsDebugBreakSlot() { return RelocInfo::DEBUG_BREAK_SLOT == rmode(); } Object* BreakLocationIterator::BreakPointObjects() { return debug_info_->GetBreakPointObjects(code_position()); } // Clear out all the debug break code. This is ONLY supposed to be used when // shutting down the debugger as it will leave the break point information in // DebugInfo even though the code is patched back to the non break point state. void BreakLocationIterator::ClearAllDebugBreak() { while (!Done()) { ClearDebugBreak(); Next(); } } bool BreakLocationIterator::RinfoDone() const { ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); return reloc_iterator_->done(); } void BreakLocationIterator::RinfoNext() { reloc_iterator_->next(); reloc_iterator_original_->next(); #ifdef DEBUG ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); if (!reloc_iterator_->done()) { ASSERT(rmode() == original_rmode()); } #endif } // Threading support. void Debug::ThreadInit() { thread_local_.break_count_ = 0; thread_local_.break_id_ = 0; thread_local_.break_frame_id_ = StackFrame::NO_ID; 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_.step_out_fp_ = 0; thread_local_.after_break_target_ = 0; // TODO(isolates): frames_are_dropped_? thread_local_.debugger_entry_ = NULL; thread_local_.pending_interrupts_ = 0; thread_local_.restarter_frame_function_pointer_ = NULL; } char* Debug::ArchiveDebug(char* storage) { char* to = storage; memcpy(to, reinterpret_cast(&thread_local_), sizeof(ThreadLocal)); to += sizeof(ThreadLocal); memcpy(to, reinterpret_cast(®isters_), sizeof(registers_)); ThreadInit(); ASSERT(to <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread(); } char* Debug::RestoreDebug(char* storage) { char* from = storage; memcpy(reinterpret_cast(&thread_local_), from, sizeof(ThreadLocal)); from += sizeof(ThreadLocal); memcpy(reinterpret_cast(®isters_), from, sizeof(registers_)); ASSERT(from <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread(); } int Debug::ArchiveSpacePerThread() { return sizeof(ThreadLocal) + sizeof(JSCallerSavedBuffer); } // Frame structure (conforms InternalFrame structure): // -- code // -- SMI maker // -- function (slot is called "context") // -- frame base Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame, Handle code) { ASSERT(bottom_js_frame->is_java_script()); Address fp = bottom_js_frame->fp(); // Move function pointer into "context" slot. Memory::Object_at(fp + StandardFrameConstants::kContextOffset) = Memory::Object_at(fp + JavaScriptFrameConstants::kFunctionOffset); Memory::Object_at(fp + InternalFrameConstants::kCodeOffset) = *code; Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset) = Smi::FromInt(StackFrame::INTERNAL); return reinterpret_cast(&Memory::Object_at( fp + StandardFrameConstants::kContextOffset)); } const int Debug::kFrameDropperFrameSize = 4; void ScriptCache::Add(Handle 登录后可以享受更多权益 您还没有登录,登录后您可以: 收藏Android系统代码 收藏喜欢的文章 多个平台共享账号 去登录 首次使用?从这里 注册
maybe_call_function_stub = code; if (IsDebugBreak()) { Address original_target = original_rinfo()->target_address(); maybe_call_function_stub = Handle(Code::GetCodeFromTargetAddress(original_target)); } bool is_call_function_stub = (maybe_call_function_stub->kind() == Code::STUB && maybe_call_function_stub->major_key() == CodeStub::CallFunction); // Step in through construct call requires no changes to the running code. // Step in through getters/setters should already be prepared as well // because caller of this function (Debug::PrepareStep) is expected to // flood the top frame's function with one shot breakpoints. // Step in through CallFunction stub should also be prepared by caller of // this function (Debug::PrepareStep) which should flood target function // with breakpoints. ASSERT(RelocInfo::IsConstructCall(rmode()) || code->is_inline_cache_stub() || is_call_function_stub); #endif } } // Check whether the break point is at a position which will exit the function. bool BreakLocationIterator::IsExit() const { return (RelocInfo::IsJSReturn(rmode())); } bool BreakLocationIterator::HasBreakPoint() { return debug_info_->HasBreakPoint(code_position()); } // Check whether there is a debug break at the current position. bool BreakLocationIterator::IsDebugBreak() { if (RelocInfo::IsJSReturn(rmode())) { return IsDebugBreakAtReturn(); } else if (IsDebugBreakSlot()) { return IsDebugBreakAtSlot(); } else { return Debug::IsDebugBreak(rinfo()->target_address()); } } void BreakLocationIterator::SetDebugBreakAtIC() { // Patch the original code with the current address as the current address // might have changed by the inline caching since the code was copied. original_rinfo()->set_target_address(rinfo()->target_address()); RelocInfo::Mode mode = rmode(); if (RelocInfo::IsCodeTarget(mode)) { Address target = rinfo()->target_address(); Handle code(Code::GetCodeFromTargetAddress(target)); // Patch the code to invoke the builtin debug break function matching the // calling convention used by the call site. Handle dbgbrk_code(Debug::FindDebugBreak(code, mode)); rinfo()->set_target_address(dbgbrk_code->entry()); // For stubs that refer back to an inlined version clear the cached map for // the inlined case to always go through the IC. As long as the break point // is set the patching performed by the runtime system will take place in // the code copy and will therefore have no effect on the running code // keeping it from using the inlined code. if (code->is_keyed_load_stub()) { KeyedLoadIC::ClearInlinedVersion(pc()); } else if (code->is_keyed_store_stub()) { KeyedStoreIC::ClearInlinedVersion(pc()); } else if (code->is_load_stub()) { LoadIC::ClearInlinedVersion(pc()); } else if (code->is_store_stub()) { StoreIC::ClearInlinedVersion(pc()); } } } void BreakLocationIterator::ClearDebugBreakAtIC() { // Patch the code to the original invoke. rinfo()->set_target_address(original_rinfo()->target_address()); RelocInfo::Mode mode = rmode(); if (RelocInfo::IsCodeTarget(mode)) { AssertNoAllocation nogc; Address target = original_rinfo()->target_address(); Code* code = Code::GetCodeFromTargetAddress(target); // Restore the inlined version of keyed stores to get back to the // fast case. We need to patch back the keyed store because no // patching happens when running normally. For keyed loads, the // map check will get patched back when running normally after ICs // have been cleared at GC. if (code->is_keyed_store_stub()) KeyedStoreIC::RestoreInlinedVersion(pc()); } } bool BreakLocationIterator::IsDebuggerStatement() { return RelocInfo::DEBUG_BREAK == rmode(); } bool BreakLocationIterator::IsDebugBreakSlot() { return RelocInfo::DEBUG_BREAK_SLOT == rmode(); } Object* BreakLocationIterator::BreakPointObjects() { return debug_info_->GetBreakPointObjects(code_position()); } // Clear out all the debug break code. This is ONLY supposed to be used when // shutting down the debugger as it will leave the break point information in // DebugInfo even though the code is patched back to the non break point state. void BreakLocationIterator::ClearAllDebugBreak() { while (!Done()) { ClearDebugBreak(); Next(); } } bool BreakLocationIterator::RinfoDone() const { ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); return reloc_iterator_->done(); } void BreakLocationIterator::RinfoNext() { reloc_iterator_->next(); reloc_iterator_original_->next(); #ifdef DEBUG ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); if (!reloc_iterator_->done()) { ASSERT(rmode() == original_rmode()); } #endif } // Threading support. void Debug::ThreadInit() { thread_local_.break_count_ = 0; thread_local_.break_id_ = 0; thread_local_.break_frame_id_ = StackFrame::NO_ID; 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_.step_out_fp_ = 0; thread_local_.after_break_target_ = 0; // TODO(isolates): frames_are_dropped_? thread_local_.debugger_entry_ = NULL; thread_local_.pending_interrupts_ = 0; thread_local_.restarter_frame_function_pointer_ = NULL; } char* Debug::ArchiveDebug(char* storage) { char* to = storage; memcpy(to, reinterpret_cast(&thread_local_), sizeof(ThreadLocal)); to += sizeof(ThreadLocal); memcpy(to, reinterpret_cast(®isters_), sizeof(registers_)); ThreadInit(); ASSERT(to <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread(); } char* Debug::RestoreDebug(char* storage) { char* from = storage; memcpy(reinterpret_cast(&thread_local_), from, sizeof(ThreadLocal)); from += sizeof(ThreadLocal); memcpy(reinterpret_cast(®isters_), from, sizeof(registers_)); ASSERT(from <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread(); } int Debug::ArchiveSpacePerThread() { return sizeof(ThreadLocal) + sizeof(JSCallerSavedBuffer); } // Frame structure (conforms InternalFrame structure): // -- code // -- SMI maker // -- function (slot is called "context") // -- frame base Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame, Handle code) { ASSERT(bottom_js_frame->is_java_script()); Address fp = bottom_js_frame->fp(); // Move function pointer into "context" slot. Memory::Object_at(fp + StandardFrameConstants::kContextOffset) = Memory::Object_at(fp + JavaScriptFrameConstants::kFunctionOffset); Memory::Object_at(fp + InternalFrameConstants::kCodeOffset) = *code; Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset) = Smi::FromInt(StackFrame::INTERNAL); return reinterpret_cast(&Memory::Object_at( fp + StandardFrameConstants::kContextOffset)); } const int Debug::kFrameDropperFrameSize = 4; void ScriptCache::Add(Handle 登录后可以享受更多权益 您还没有登录,登录后您可以: 收藏Android系统代码 收藏喜欢的文章 多个平台共享账号 去登录 首次使用?从这里 注册
(Code::GetCodeFromTargetAddress(original_target)); } bool is_call_function_stub = (maybe_call_function_stub->kind() == Code::STUB && maybe_call_function_stub->major_key() == CodeStub::CallFunction); // Step in through construct call requires no changes to the running code. // Step in through getters/setters should already be prepared as well // because caller of this function (Debug::PrepareStep) is expected to // flood the top frame's function with one shot breakpoints. // Step in through CallFunction stub should also be prepared by caller of // this function (Debug::PrepareStep) which should flood target function // with breakpoints. ASSERT(RelocInfo::IsConstructCall(rmode()) || code->is_inline_cache_stub() || is_call_function_stub); #endif } } // Check whether the break point is at a position which will exit the function. bool BreakLocationIterator::IsExit() const { return (RelocInfo::IsJSReturn(rmode())); } bool BreakLocationIterator::HasBreakPoint() { return debug_info_->HasBreakPoint(code_position()); } // Check whether there is a debug break at the current position. bool BreakLocationIterator::IsDebugBreak() { if (RelocInfo::IsJSReturn(rmode())) { return IsDebugBreakAtReturn(); } else if (IsDebugBreakSlot()) { return IsDebugBreakAtSlot(); } else { return Debug::IsDebugBreak(rinfo()->target_address()); } } void BreakLocationIterator::SetDebugBreakAtIC() { // Patch the original code with the current address as the current address // might have changed by the inline caching since the code was copied. original_rinfo()->set_target_address(rinfo()->target_address()); RelocInfo::Mode mode = rmode(); if (RelocInfo::IsCodeTarget(mode)) { Address target = rinfo()->target_address(); Handle code(Code::GetCodeFromTargetAddress(target)); // Patch the code to invoke the builtin debug break function matching the // calling convention used by the call site. Handle dbgbrk_code(Debug::FindDebugBreak(code, mode)); rinfo()->set_target_address(dbgbrk_code->entry()); // For stubs that refer back to an inlined version clear the cached map for // the inlined case to always go through the IC. As long as the break point // is set the patching performed by the runtime system will take place in // the code copy and will therefore have no effect on the running code // keeping it from using the inlined code. if (code->is_keyed_load_stub()) { KeyedLoadIC::ClearInlinedVersion(pc()); } else if (code->is_keyed_store_stub()) { KeyedStoreIC::ClearInlinedVersion(pc()); } else if (code->is_load_stub()) { LoadIC::ClearInlinedVersion(pc()); } else if (code->is_store_stub()) { StoreIC::ClearInlinedVersion(pc()); } } } void BreakLocationIterator::ClearDebugBreakAtIC() { // Patch the code to the original invoke. rinfo()->set_target_address(original_rinfo()->target_address()); RelocInfo::Mode mode = rmode(); if (RelocInfo::IsCodeTarget(mode)) { AssertNoAllocation nogc; Address target = original_rinfo()->target_address(); Code* code = Code::GetCodeFromTargetAddress(target); // Restore the inlined version of keyed stores to get back to the // fast case. We need to patch back the keyed store because no // patching happens when running normally. For keyed loads, the // map check will get patched back when running normally after ICs // have been cleared at GC. if (code->is_keyed_store_stub()) KeyedStoreIC::RestoreInlinedVersion(pc()); } } bool BreakLocationIterator::IsDebuggerStatement() { return RelocInfo::DEBUG_BREAK == rmode(); } bool BreakLocationIterator::IsDebugBreakSlot() { return RelocInfo::DEBUG_BREAK_SLOT == rmode(); } Object* BreakLocationIterator::BreakPointObjects() { return debug_info_->GetBreakPointObjects(code_position()); } // Clear out all the debug break code. This is ONLY supposed to be used when // shutting down the debugger as it will leave the break point information in // DebugInfo even though the code is patched back to the non break point state. void BreakLocationIterator::ClearAllDebugBreak() { while (!Done()) { ClearDebugBreak(); Next(); } } bool BreakLocationIterator::RinfoDone() const { ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); return reloc_iterator_->done(); } void BreakLocationIterator::RinfoNext() { reloc_iterator_->next(); reloc_iterator_original_->next(); #ifdef DEBUG ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); if (!reloc_iterator_->done()) { ASSERT(rmode() == original_rmode()); } #endif } // Threading support. void Debug::ThreadInit() { thread_local_.break_count_ = 0; thread_local_.break_id_ = 0; thread_local_.break_frame_id_ = StackFrame::NO_ID; 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_.step_out_fp_ = 0; thread_local_.after_break_target_ = 0; // TODO(isolates): frames_are_dropped_? thread_local_.debugger_entry_ = NULL; thread_local_.pending_interrupts_ = 0; thread_local_.restarter_frame_function_pointer_ = NULL; } char* Debug::ArchiveDebug(char* storage) { char* to = storage; memcpy(to, reinterpret_cast(&thread_local_), sizeof(ThreadLocal)); to += sizeof(ThreadLocal); memcpy(to, reinterpret_cast(®isters_), sizeof(registers_)); ThreadInit(); ASSERT(to <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread(); } char* Debug::RestoreDebug(char* storage) { char* from = storage; memcpy(reinterpret_cast(&thread_local_), from, sizeof(ThreadLocal)); from += sizeof(ThreadLocal); memcpy(reinterpret_cast(®isters_), from, sizeof(registers_)); ASSERT(from <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread(); } int Debug::ArchiveSpacePerThread() { return sizeof(ThreadLocal) + sizeof(JSCallerSavedBuffer); } // Frame structure (conforms InternalFrame structure): // -- code // -- SMI maker // -- function (slot is called "context") // -- frame base Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame, Handle code) { ASSERT(bottom_js_frame->is_java_script()); Address fp = bottom_js_frame->fp(); // Move function pointer into "context" slot. Memory::Object_at(fp + StandardFrameConstants::kContextOffset) = Memory::Object_at(fp + JavaScriptFrameConstants::kFunctionOffset); Memory::Object_at(fp + InternalFrameConstants::kCodeOffset) = *code; Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset) = Smi::FromInt(StackFrame::INTERNAL); return reinterpret_cast(&Memory::Object_at( fp + StandardFrameConstants::kContextOffset)); } const int Debug::kFrameDropperFrameSize = 4; void ScriptCache::Add(Handle 登录后可以享受更多权益 您还没有登录,登录后您可以: 收藏Android系统代码 收藏喜欢的文章 多个平台共享账号 去登录 首次使用?从这里 注册
code(Code::GetCodeFromTargetAddress(target)); // Patch the code to invoke the builtin debug break function matching the // calling convention used by the call site. Handle dbgbrk_code(Debug::FindDebugBreak(code, mode)); rinfo()->set_target_address(dbgbrk_code->entry()); // For stubs that refer back to an inlined version clear the cached map for // the inlined case to always go through the IC. As long as the break point // is set the patching performed by the runtime system will take place in // the code copy and will therefore have no effect on the running code // keeping it from using the inlined code. if (code->is_keyed_load_stub()) { KeyedLoadIC::ClearInlinedVersion(pc()); } else if (code->is_keyed_store_stub()) { KeyedStoreIC::ClearInlinedVersion(pc()); } else if (code->is_load_stub()) { LoadIC::ClearInlinedVersion(pc()); } else if (code->is_store_stub()) { StoreIC::ClearInlinedVersion(pc()); } } } void BreakLocationIterator::ClearDebugBreakAtIC() { // Patch the code to the original invoke. rinfo()->set_target_address(original_rinfo()->target_address()); RelocInfo::Mode mode = rmode(); if (RelocInfo::IsCodeTarget(mode)) { AssertNoAllocation nogc; Address target = original_rinfo()->target_address(); Code* code = Code::GetCodeFromTargetAddress(target); // Restore the inlined version of keyed stores to get back to the // fast case. We need to patch back the keyed store because no // patching happens when running normally. For keyed loads, the // map check will get patched back when running normally after ICs // have been cleared at GC. if (code->is_keyed_store_stub()) KeyedStoreIC::RestoreInlinedVersion(pc()); } } bool BreakLocationIterator::IsDebuggerStatement() { return RelocInfo::DEBUG_BREAK == rmode(); } bool BreakLocationIterator::IsDebugBreakSlot() { return RelocInfo::DEBUG_BREAK_SLOT == rmode(); } Object* BreakLocationIterator::BreakPointObjects() { return debug_info_->GetBreakPointObjects(code_position()); } // Clear out all the debug break code. This is ONLY supposed to be used when // shutting down the debugger as it will leave the break point information in // DebugInfo even though the code is patched back to the non break point state. void BreakLocationIterator::ClearAllDebugBreak() { while (!Done()) { ClearDebugBreak(); Next(); } } bool BreakLocationIterator::RinfoDone() const { ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); return reloc_iterator_->done(); } void BreakLocationIterator::RinfoNext() { reloc_iterator_->next(); reloc_iterator_original_->next(); #ifdef DEBUG ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); if (!reloc_iterator_->done()) { ASSERT(rmode() == original_rmode()); } #endif } // Threading support. void Debug::ThreadInit() { thread_local_.break_count_ = 0; thread_local_.break_id_ = 0; thread_local_.break_frame_id_ = StackFrame::NO_ID; 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_.step_out_fp_ = 0; thread_local_.after_break_target_ = 0; // TODO(isolates): frames_are_dropped_? thread_local_.debugger_entry_ = NULL; thread_local_.pending_interrupts_ = 0; thread_local_.restarter_frame_function_pointer_ = NULL; } char* Debug::ArchiveDebug(char* storage) { char* to = storage; memcpy(to, reinterpret_cast(&thread_local_), sizeof(ThreadLocal)); to += sizeof(ThreadLocal); memcpy(to, reinterpret_cast(®isters_), sizeof(registers_)); ThreadInit(); ASSERT(to <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread(); } char* Debug::RestoreDebug(char* storage) { char* from = storage; memcpy(reinterpret_cast(&thread_local_), from, sizeof(ThreadLocal)); from += sizeof(ThreadLocal); memcpy(reinterpret_cast(®isters_), from, sizeof(registers_)); ASSERT(from <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread(); } int Debug::ArchiveSpacePerThread() { return sizeof(ThreadLocal) + sizeof(JSCallerSavedBuffer); } // Frame structure (conforms InternalFrame structure): // -- code // -- SMI maker // -- function (slot is called "context") // -- frame base Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame, Handle code) { ASSERT(bottom_js_frame->is_java_script()); Address fp = bottom_js_frame->fp(); // Move function pointer into "context" slot. Memory::Object_at(fp + StandardFrameConstants::kContextOffset) = Memory::Object_at(fp + JavaScriptFrameConstants::kFunctionOffset); Memory::Object_at(fp + InternalFrameConstants::kCodeOffset) = *code; Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset) = Smi::FromInt(StackFrame::INTERNAL); return reinterpret_cast(&Memory::Object_at( fp + StandardFrameConstants::kContextOffset)); } const int Debug::kFrameDropperFrameSize = 4; void ScriptCache::Add(Handle 登录后可以享受更多权益 您还没有登录,登录后您可以: 收藏Android系统代码 收藏喜欢的文章 多个平台共享账号 去登录 首次使用?从这里 注册
dbgbrk_code(Debug::FindDebugBreak(code, mode)); rinfo()->set_target_address(dbgbrk_code->entry()); // For stubs that refer back to an inlined version clear the cached map for // the inlined case to always go through the IC. As long as the break point // is set the patching performed by the runtime system will take place in // the code copy and will therefore have no effect on the running code // keeping it from using the inlined code. if (code->is_keyed_load_stub()) { KeyedLoadIC::ClearInlinedVersion(pc()); } else if (code->is_keyed_store_stub()) { KeyedStoreIC::ClearInlinedVersion(pc()); } else if (code->is_load_stub()) { LoadIC::ClearInlinedVersion(pc()); } else if (code->is_store_stub()) { StoreIC::ClearInlinedVersion(pc()); } } } void BreakLocationIterator::ClearDebugBreakAtIC() { // Patch the code to the original invoke. rinfo()->set_target_address(original_rinfo()->target_address()); RelocInfo::Mode mode = rmode(); if (RelocInfo::IsCodeTarget(mode)) { AssertNoAllocation nogc; Address target = original_rinfo()->target_address(); Code* code = Code::GetCodeFromTargetAddress(target); // Restore the inlined version of keyed stores to get back to the // fast case. We need to patch back the keyed store because no // patching happens when running normally. For keyed loads, the // map check will get patched back when running normally after ICs // have been cleared at GC. if (code->is_keyed_store_stub()) KeyedStoreIC::RestoreInlinedVersion(pc()); } } bool BreakLocationIterator::IsDebuggerStatement() { return RelocInfo::DEBUG_BREAK == rmode(); } bool BreakLocationIterator::IsDebugBreakSlot() { return RelocInfo::DEBUG_BREAK_SLOT == rmode(); } Object* BreakLocationIterator::BreakPointObjects() { return debug_info_->GetBreakPointObjects(code_position()); } // Clear out all the debug break code. This is ONLY supposed to be used when // shutting down the debugger as it will leave the break point information in // DebugInfo even though the code is patched back to the non break point state. void BreakLocationIterator::ClearAllDebugBreak() { while (!Done()) { ClearDebugBreak(); Next(); } } bool BreakLocationIterator::RinfoDone() const { ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); return reloc_iterator_->done(); } void BreakLocationIterator::RinfoNext() { reloc_iterator_->next(); reloc_iterator_original_->next(); #ifdef DEBUG ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); if (!reloc_iterator_->done()) { ASSERT(rmode() == original_rmode()); } #endif } // Threading support. void Debug::ThreadInit() { thread_local_.break_count_ = 0; thread_local_.break_id_ = 0; thread_local_.break_frame_id_ = StackFrame::NO_ID; 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_.step_out_fp_ = 0; thread_local_.after_break_target_ = 0; // TODO(isolates): frames_are_dropped_? thread_local_.debugger_entry_ = NULL; thread_local_.pending_interrupts_ = 0; thread_local_.restarter_frame_function_pointer_ = NULL; } char* Debug::ArchiveDebug(char* storage) { char* to = storage; memcpy(to, reinterpret_cast(&thread_local_), sizeof(ThreadLocal)); to += sizeof(ThreadLocal); memcpy(to, reinterpret_cast(®isters_), sizeof(registers_)); ThreadInit(); ASSERT(to <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread(); } char* Debug::RestoreDebug(char* storage) { char* from = storage; memcpy(reinterpret_cast(&thread_local_), from, sizeof(ThreadLocal)); from += sizeof(ThreadLocal); memcpy(reinterpret_cast(®isters_), from, sizeof(registers_)); ASSERT(from <= storage + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread(); } int Debug::ArchiveSpacePerThread() { return sizeof(ThreadLocal) + sizeof(JSCallerSavedBuffer); } // Frame structure (conforms InternalFrame structure): // -- code // -- SMI maker // -- function (slot is called "context") // -- frame base Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame, Handle code) { ASSERT(bottom_js_frame->is_java_script()); Address fp = bottom_js_frame->fp(); // Move function pointer into "context" slot. Memory::Object_at(fp + StandardFrameConstants::kContextOffset) = Memory::Object_at(fp + JavaScriptFrameConstants::kFunctionOffset); Memory::Object_at(fp + InternalFrameConstants::kCodeOffset) = *code; Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset) = Smi::FromInt(StackFrame::INTERNAL); return reinterpret_cast(&Memory::Object_at( fp + StandardFrameConstants::kContextOffset)); } const int Debug::kFrameDropperFrameSize = 4; void ScriptCache::Add(Handle 登录后可以享受更多权益 您还没有登录,登录后您可以: 收藏Android系统代码 收藏喜欢的文章 多个平台共享账号 去登录 首次使用?从这里 注册
code) { ASSERT(bottom_js_frame->is_java_script()); Address fp = bottom_js_frame->fp(); // Move function pointer into "context" slot. Memory::Object_at(fp + StandardFrameConstants::kContextOffset) = Memory::Object_at(fp + JavaScriptFrameConstants::kFunctionOffset); Memory::Object_at(fp + InternalFrameConstants::kCodeOffset) = *code; Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset) = Smi::FromInt(StackFrame::INTERNAL); return reinterpret_cast(&Memory::Object_at( fp + StandardFrameConstants::kContextOffset)); } const int Debug::kFrameDropperFrameSize = 4; void ScriptCache::Add(Handle 登录后可以享受更多权益 您还没有登录,登录后您可以: 收藏Android系统代码 收藏喜欢的文章 多个平台共享账号 去登录 首次使用?从这里 注册
您还没有登录,登录后您可以:
首次使用?从这里 注册