⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 debug.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
// Copyright 2006-2008 the V8 project authors. All rights reserved.// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met:////     * Redistributions of source code must retain the above copyright//       notice, this list of conditions and the following disclaimer.//     * Redistributions in binary form must reproduce the above//       copyright notice, this list of conditions and the following//       disclaimer in the documentation and/or other materials provided//       with the distribution.//     * Neither the name of Google Inc. nor the names of its//       contributors may be used to endorse or promote products derived//       from this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#include "v8.h"#include "api.h"#include "arguments.h"#include "bootstrapper.h"#include "code-stubs.h"#include "compiler.h"#include "debug.h"#include "execution.h"#include "global-handles.h"#include "natives.h"#include "stub-cache.h"#include "log.h"namespace v8 { namespace internal {static void PrintLn(v8::Local<v8::Value> value) {  v8::Local<v8::String> s = value->ToString();  char* data = NewArray<char>(s->Length() + 1);  if (data == NULL) {    V8::FatalProcessOutOfMemory("PrintLn");    return;  }  s->WriteAscii(data);  PrintF("%s\n", data);  DeleteArray(data);}static Handle<Code> ComputeCallDebugBreak(int argc) {  CALL_HEAP_FUNCTION(StubCache::ComputeCallDebugBreak(argc), Code);}static Handle<Code> ComputeCallDebugPrepareStepIn(int argc) {  CALL_HEAP_FUNCTION(StubCache::ComputeCallDebugPrepareStepIn(argc), Code);}BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> 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_ =            rinfo()->data() - debug_info_->shared()->start_position();      }      // Always update the position as we don't want that to be before the      // statement position.      position_ = rinfo()->data() - debug_info_->shared()->start_position();      ASSERT(position_ >= 0);      ASSERT(statement_position_ >= 0);    }    // 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.    if (RelocInfo::IsCodeTarget(rmode())) {      Address target = original_rinfo()->target_address();      Code* code = Debug::GetCodeTarget(target);      if (code->is_inline_cache_stub() || RelocInfo::IsConstructCall(rmode())) {        break_point_++;        return;      }      if (code->kind() == Code::STUB) {        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();      } 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 = 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<Object> break_point_object) {  // If there is not already a real break point here patch code with debug  // break.  if (!HasBreakPoint()) {    SetDebugBreak();  }  ASSERT(IsDebugBreak());  // Set the break point information.  DebugInfo::SetBreakPoint(debug_info_, code_position(),                           position(), statement_position(),                           break_point_object);}void BreakLocationIterator::ClearBreakPoint(Handle<Object> 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() {  // 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() {  // 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() {  // 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())) {    // This path is currently only used on IA32 as JSExitFrame on ARM uses a    // stub.    // Patch the JS frame exit code with a debug break call. See    // VisitReturnStatement and ExitJSFrame in codegen-ia32.cc for the    // precise return instructions sequence.    ASSERT(Debug::kIa32JSReturnSequenceLength >=           Debug::kIa32CallInstructionLength);    rinfo()->patch_code_with_call(Debug::debug_break_return_entry()->entry(),        Debug::kIa32JSReturnSequenceLength - Debug::kIa32CallInstructionLength);  } else {    // 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());    // Patch the code to invoke the builtin debug break function matching the    // calling convention used by the call site.    Handle<Code> dbgbrk_code(Debug::FindDebugBreak(rinfo()));    rinfo()->set_target_address(dbgbrk_code->entry());  }  ASSERT(IsDebugBreak());}void BreakLocationIterator::ClearDebugBreak() {  if (RelocInfo::IsJSReturn(rmode())) {    // Restore the JS frame exit code.    rinfo()->patch_code(original_rinfo()->pc(),                        Debug::kIa32JSReturnSequenceLength);  } else {    // Patch the code to the original invoke.    rinfo()->set_target_address(original_rinfo()->target_address());  }  ASSERT(!IsDebugBreak());}void BreakLocationIterator::PrepareStepIn() {  // Step in can only be prepared if currently positioned on an IC call or  // construct call.  Address target = rinfo()->target_address();  Code* code = Debug::GetCodeTarget(target);  if (code->is_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<Code> stub = ComputeCallDebugPrepareStepIn(code->arguments_count());    if (IsDebugBreak()) {      original_rinfo()->set_target_address(stub->entry());    } else {      rinfo()->set_target_address(stub->entry());    }  } else {    // Step in through constructs call requires no changes to the running code.    ASSERT(RelocInfo::IsConstructCall(rmode()));  }}// 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())) {    // This is IA32 specific but works as long as the ARM version    // still uses a stub for JSExitFrame.    //    // TODO(1240753): Make the test architecture independent or split    // parts of the debugger into architecture dependent files.    return (*(rinfo()->pc()) == 0xE8);  } else {    return Debug::IsDebugBreak(rinfo()->target_address());  }}Object* BreakLocationIterator::BreakPointObjects() {  return debug_info_->GetBreakPointObjects(code_position());}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());

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -