Commit 3003b215 authored by vegorov@chromium.org's avatar vegorov@chromium.org

Basic GDB JIT Interface integration.

It has certain overheads even when gdb is not attached so it is guarded by ENABLE_GDBJIT_INTERFACE define and --gdbjit flag.

Review URL: http://codereview.chromium.org/5965011

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6367 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 9cee2813
...@@ -229,6 +229,9 @@ LIBRARY_FLAGS = { ...@@ -229,6 +229,9 @@ LIBRARY_FLAGS = {
}, },
'prof:oprofile': { 'prof:oprofile': {
'CPPDEFINES': ['ENABLE_OPROFILE_AGENT'] 'CPPDEFINES': ['ENABLE_OPROFILE_AGENT']
},
'gdbjit:on': {
'CPPDEFINES': ['ENABLE_GDB_JIT_INTERFACE']
} }
}, },
'msvc': { 'msvc': {
...@@ -706,6 +709,11 @@ SIMPLE_OPTIONS = { ...@@ -706,6 +709,11 @@ SIMPLE_OPTIONS = {
'default': 'off', 'default': 'off',
'help': 'enable profiling of build target' 'help': 'enable profiling of build target'
}, },
'gdbjit': {
'values': ['on', 'off'],
'default': 'off',
'help': 'enable GDB JIT interface'
},
'library': { 'library': {
'values': ['static', 'shared'], 'values': ['static', 'shared'],
'default': 'static', 'default': 'static',
...@@ -872,6 +880,8 @@ def VerifyOptions(env): ...@@ -872,6 +880,8 @@ def VerifyOptions(env):
return False return False
if env['os'] == 'win32' and env['library'] == 'shared' and env['prof'] == 'on': if env['os'] == 'win32' and env['library'] == 'shared' and env['prof'] == 'on':
Abort("Profiling on windows only supported for static library.") Abort("Profiling on windows only supported for static library.")
if env['gdbjit'] == 'on' and (env['os'] != 'linux' or (env['arch'] != 'ia32' and env['arch'] != 'x64')):
Abort("GDBJIT interface is supported only for Intel-compatible (ia32 or x64) Linux target.")
if env['prof'] == 'oprofile' and env['os'] != 'linux': if env['prof'] == 'oprofile' and env['os'] != 'linux':
Abort("OProfile is only supported on Linux.") Abort("OProfile is only supported on Linux.")
if env['os'] == 'win32' and env['soname'] == 'on': if env['os'] == 'win32' and env['soname'] == 'on':
......
...@@ -71,6 +71,7 @@ SOURCES = { ...@@ -71,6 +71,7 @@ SOURCES = {
frames.cc frames.cc
full-codegen.cc full-codegen.cc
func-name-inferrer.cc func-name-inferrer.cc
gdb-jit.cc
global-handles.cc global-handles.cc
fast-dtoa.cc fast-dtoa.cc
fixed-dtoa.cc fixed-dtoa.cc
......
...@@ -917,6 +917,11 @@ void PositionsRecorder::RecordPosition(int pos) { ...@@ -917,6 +917,11 @@ void PositionsRecorder::RecordPosition(int pos) {
ASSERT(pos != RelocInfo::kNoPosition); ASSERT(pos != RelocInfo::kNoPosition);
ASSERT(pos >= 0); ASSERT(pos >= 0);
state_.current_position = pos; state_.current_position = pos;
#ifdef ENABLE_GDB_JIT_INTERFACE
if (gdbjit_lineinfo_ != NULL) {
gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, false);
}
#endif
} }
...@@ -924,6 +929,11 @@ void PositionsRecorder::RecordStatementPosition(int pos) { ...@@ -924,6 +929,11 @@ void PositionsRecorder::RecordStatementPosition(int pos) {
ASSERT(pos != RelocInfo::kNoPosition); ASSERT(pos != RelocInfo::kNoPosition);
ASSERT(pos >= 0); ASSERT(pos >= 0);
state_.current_statement_position = pos; state_.current_statement_position = pos;
#ifdef ENABLE_GDB_JIT_INTERFACE
if (gdbjit_lineinfo_ != NULL) {
gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, true);
}
#endif
} }
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#ifndef V8_ASSEMBLER_H_ #ifndef V8_ASSEMBLER_H_
#define V8_ASSEMBLER_H_ #define V8_ASSEMBLER_H_
#include "gdb-jit.h"
#include "runtime.h" #include "runtime.h"
#include "top.h" #include "top.h"
#include "token.h" #include "token.h"
...@@ -637,7 +638,29 @@ struct PositionState { ...@@ -637,7 +638,29 @@ struct PositionState {
class PositionsRecorder BASE_EMBEDDED { class PositionsRecorder BASE_EMBEDDED {
public: public:
explicit PositionsRecorder(Assembler* assembler) explicit PositionsRecorder(Assembler* assembler)
: assembler_(assembler) {} : assembler_(assembler) {
#ifdef ENABLE_GDB_JIT_INTERFACE
gdbjit_lineinfo_ = NULL;
#endif
}
#ifdef ENABLE_GDB_JIT_INTERFACE
~PositionsRecorder() {
delete gdbjit_lineinfo_;
}
void StartGDBJITLineInfoRecording() {
if (FLAG_gdbjit) {
gdbjit_lineinfo_ = new GDBJITLineInfo();
}
}
GDBJITLineInfo* DetachGDBJITLineInfo() {
GDBJITLineInfo* lineinfo = gdbjit_lineinfo_;
gdbjit_lineinfo_ = NULL; // To prevent deallocation in destructor.
return lineinfo;
}
#endif
// Set current position to pos. // Set current position to pos.
void RecordPosition(int pos); void RecordPosition(int pos);
...@@ -657,6 +680,9 @@ class PositionsRecorder BASE_EMBEDDED { ...@@ -657,6 +680,9 @@ class PositionsRecorder BASE_EMBEDDED {
private: private:
Assembler* assembler_; Assembler* assembler_;
PositionState state_; PositionState state_;
#ifdef ENABLE_GDB_JIT_INTERFACE
GDBJITLineInfo* gdbjit_lineinfo_;
#endif
friend class PreservePositionScope; friend class PreservePositionScope;
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "arguments.h" #include "arguments.h"
#include "bootstrapper.h" #include "bootstrapper.h"
#include "builtins.h" #include "builtins.h"
#include "gdb-jit.h"
#include "ic-inl.h" #include "ic-inl.h"
#include "vm-state-inl.h" #include "vm-state-inl.h"
...@@ -1550,7 +1551,7 @@ void Builtins::Setup(bool create_heap_objects) { ...@@ -1550,7 +1551,7 @@ void Builtins::Setup(bool create_heap_objects) {
CodeDesc desc; CodeDesc desc;
masm.GetCode(&desc); masm.GetCode(&desc);
Code::Flags flags = functions[i].flags; Code::Flags flags = functions[i].flags;
Object* code = 0; Object* code = NULL;
{ {
// During startup it's OK to always allocate and defer GC to later. // During startup it's OK to always allocate and defer GC to later.
// This simplifies things because we don't need to retry. // This simplifies things because we don't need to retry.
...@@ -1564,7 +1565,11 @@ void Builtins::Setup(bool create_heap_objects) { ...@@ -1564,7 +1565,11 @@ void Builtins::Setup(bool create_heap_objects) {
} }
// Log the event and add the code to the builtins array. // Log the event and add the code to the builtins array.
PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG, PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG,
Code::cast(code), functions[i].s_name)); Code::cast(code),
functions[i].s_name));
GDBJIT(AddCode(GDBJITInterface::BUILTIN,
functions[i].s_name,
Code::cast(code)));
builtins_[i] = code; builtins_[i] = code;
#ifdef ENABLE_DISASSEMBLER #ifdef ENABLE_DISASSEMBLER
if (FLAG_print_builtin_code) { if (FLAG_print_builtin_code) {
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "bootstrapper.h" #include "bootstrapper.h"
#include "code-stubs.h" #include "code-stubs.h"
#include "factory.h" #include "factory.h"
#include "gdb-jit.h"
#include "macro-assembler.h" #include "macro-assembler.h"
#include "oprofile-agent.h" #include "oprofile-agent.h"
...@@ -66,6 +67,7 @@ void CodeStub::RecordCodeGeneration(Code* code, MacroAssembler* masm) { ...@@ -66,6 +67,7 @@ void CodeStub::RecordCodeGeneration(Code* code, MacroAssembler* masm) {
code->instruction_start(), code->instruction_start(),
code->instruction_size())); code->instruction_size()));
PROFILE(CodeCreateEvent(Logger::STUB_TAG, code, GetName())); PROFILE(CodeCreateEvent(Logger::STUB_TAG, code, GetName()));
GDBJIT(AddCode(GDBJITInterface::STUB, GetName(), code));
Counters::total_stubs_code_size.Increment(code->instruction_size()); Counters::total_stubs_code_size.Increment(code->instruction_size());
#ifdef ENABLE_DISASSEMBLER #ifdef ENABLE_DISASSEMBLER
......
...@@ -248,6 +248,9 @@ bool CodeGenerator::MakeCode(CompilationInfo* info) { ...@@ -248,6 +248,9 @@ bool CodeGenerator::MakeCode(CompilationInfo* info) {
// Generate code. // Generate code.
const int kInitialBufferSize = 4 * KB; const int kInitialBufferSize = 4 * KB;
MacroAssembler masm(NULL, kInitialBufferSize); MacroAssembler masm(NULL, kInitialBufferSize);
#ifdef ENABLE_GDB_JIT_INTERFACE
masm.positions_recorder()->StartGDBJITLineInfoRecording();
#endif
CodeGenerator cgen(&masm); CodeGenerator cgen(&masm);
CodeGeneratorScope scope(&cgen); CodeGeneratorScope scope(&cgen);
cgen.Generate(info); cgen.Generate(info);
...@@ -263,6 +266,14 @@ bool CodeGenerator::MakeCode(CompilationInfo* info) { ...@@ -263,6 +266,14 @@ bool CodeGenerator::MakeCode(CompilationInfo* info) {
code->SetNoStackCheckTable(); code->SetNoStackCheckTable();
CodeGenerator::PrintCode(code, info); CodeGenerator::PrintCode(code, info);
info->SetCode(code); // May be an empty handle. info->SetCode(code); // May be an empty handle.
#ifdef ENABLE_GDB_JIT_INTERFACE
if (!code.is_null()) {
GDBJITLineInfo* lineinfo =
masm.positions_recorder()->DetachGDBJITLineInfo();
GDBJIT(RegisterDetailedLineInfo(*code, lineinfo));
}
#endif
return !code.is_null(); return !code.is_null();
} }
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "data-flow.h" #include "data-flow.h"
#include "debug.h" #include "debug.h"
#include "full-codegen.h" #include "full-codegen.h"
#include "gdb-jit.h"
#include "hydrogen.h" #include "hydrogen.h"
#include "lithium-allocator.h" #include "lithium-allocator.h"
#include "liveedit.h" #include "liveedit.h"
...@@ -421,6 +422,9 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) { ...@@ -421,6 +422,9 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
OPROFILE(CreateNativeCodeRegion(String::cast(script->name()), OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
info->code()->instruction_start(), info->code()->instruction_start(),
info->code()->instruction_size())); info->code()->instruction_size()));
GDBJIT(AddCode(Handle<String>(String::cast(script->name())),
script,
info->code()));
} else { } else {
PROFILE(CodeCreateEvent( PROFILE(CodeCreateEvent(
info->is_eval() info->is_eval()
...@@ -431,6 +435,7 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) { ...@@ -431,6 +435,7 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
OPROFILE(CreateNativeCodeRegion(info->is_eval() ? "Eval" : "Script", OPROFILE(CreateNativeCodeRegion(info->is_eval() ? "Eval" : "Script",
info->code()->instruction_start(), info->code()->instruction_start(),
info->code()->instruction_size())); info->code()->instruction_size()));
GDBJIT(AddCode(Handle<String>(), script, info->code()));
} }
// Allocate function. // Allocate function.
...@@ -794,6 +799,10 @@ void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag, ...@@ -794,6 +799,10 @@ void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
code->instruction_size())); code->instruction_size()));
} }
} }
GDBJIT(AddCode(name,
Handle<Script>(info->script()),
Handle<Code>(info->code())));
} }
} } // namespace v8::internal } } // namespace v8::internal
...@@ -366,6 +366,14 @@ DEFINE_bool(debug_script_collected_events, true, ...@@ -366,6 +366,14 @@ DEFINE_bool(debug_script_collected_events, true,
"Enable debugger script collected events") "Enable debugger script collected events")
#endif #endif
//
// GDB JIT integration flags.
//
DEFINE_bool(gdbjit, false, "enable GDBJIT interface (disables compacting GC)")
DEFINE_bool(gdbjit_full, false, "enable GDBJIT interface for all code objects")
// //
// Debug only flags // Debug only flags
// //
......
...@@ -286,6 +286,9 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) { ...@@ -286,6 +286,9 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
CodeGenerator::MakeCodePrologue(info); CodeGenerator::MakeCodePrologue(info);
const int kInitialBufferSize = 4 * KB; const int kInitialBufferSize = 4 * KB;
MacroAssembler masm(NULL, kInitialBufferSize); MacroAssembler masm(NULL, kInitialBufferSize);
#ifdef ENABLE_GDB_JIT_INTERFACE
masm.positions_recorder()->StartGDBJITLineInfoRecording();
#endif
FullCodeGenerator cgen(&masm); FullCodeGenerator cgen(&masm);
cgen.Generate(info); cgen.Generate(info);
...@@ -304,6 +307,14 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) { ...@@ -304,6 +307,14 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
code->set_stack_check_table_start(table_offset); code->set_stack_check_table_start(table_offset);
CodeGenerator::PrintCode(code, info); CodeGenerator::PrintCode(code, info);
info->SetCode(code); // may be an empty handle. info->SetCode(code); // may be an empty handle.
#ifdef ENABLE_GDB_JIT_INTERFACE
if (!code.is_null()) {
GDBJITLineInfo* lineinfo =
masm.positions_recorder()->DetachGDBJITLineInfo();
GDBJIT(RegisterDetailedLineInfo(*code, lineinfo));
}
#endif
return !code.is_null(); return !code.is_null();
} }
......
This diff is collapsed.
// Copyright 2010 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.
#ifndef V8_GDB_JIT_H_
#define V8_GDB_JIT_H_
//
// Basic implementation of GDB JIT Interface client.
// GBD JIT Interface is supported in GDB 7.0 and above.
// Currently on x64 and ia32 architectures and Linux OS are supported.
//
#ifdef ENABLE_GDB_JIT_INTERFACE
#include "v8.h"
#include "factory.h"
namespace v8 {
namespace internal {
#define CODE_TAGS_LIST(V) \
V(LOAD_IC) \
V(KEYED_LOAD_IC) \
V(STORE_IC) \
V(KEYED_STORE_IC) \
V(CALL_IC) \
V(CALL_INITIALIZE) \
V(CALL_PRE_MONOMORPHIC) \
V(CALL_NORMAL) \
V(CALL_MEGAMORPHIC) \
V(CALL_MISS) \
V(STUB) \
V(BUILTIN) \
V(SCRIPT) \
V(EVAL)
class GDBJITLineInfo : public Malloced {
public:
GDBJITLineInfo()
: pc_info_(10) { }
void SetPosition(intptr_t pc, int pos, bool is_statement) {
AddPCInfo(PCInfo(pc, pos, is_statement));
}
struct PCInfo {
PCInfo(intptr_t pc, int pos, bool is_statement)
: pc_(pc), pos_(pos), is_statement_(is_statement) { }
intptr_t pc_;
int pos_;
bool is_statement_;
};
List<PCInfo>* pc_info() {
return &pc_info_;
}
private:
void AddPCInfo(const PCInfo& pc_info) {
pc_info_.Add(pc_info);
}
List<PCInfo> pc_info_;
};
class GDBJITInterface: public AllStatic {
public:
enum CodeTag {
#define V(x) x,
CODE_TAGS_LIST(V)
#undef V
TAG_COUNT
};
static const char* Tag2String(CodeTag tag) {
switch (tag) {
#define V(x) case x: return #x;
CODE_TAGS_LIST(V)
#undef V
default:
return NULL;
}
}
static void AddCode(const char* name,
Code* code,
Script* script = NULL);
static void AddCode(Handle<String> name,
Handle<Script> script,
Handle<Code> code);
static void AddCode(CodeTag tag, String* name, Code* code);
static void AddCode(CodeTag tag, const char* name, Code* code);
static void AddCode(CodeTag tag, Code* code);
static void RemoveCode(Code* code);
static void RegisterDetailedLineInfo(Code* code, GDBJITLineInfo* line_info);
};
#define GDBJIT(action) GDBJITInterface::action
} } // namespace v8::internal
#else
#define GDBJIT(action) ((void) 0)
#endif
#endif
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "compilation-cache.h" #include "compilation-cache.h"
#include "execution.h" #include "execution.h"
#include "heap-profiler.h" #include "heap-profiler.h"
#include "gdb-jit.h"
#include "global-handles.h" #include "global-handles.h"
#include "ic-inl.h" #include "ic-inl.h"
#include "mark-compact.h" #include "mark-compact.h"
...@@ -125,6 +126,12 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) { ...@@ -125,6 +126,12 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) {
if (!Heap::map_space()->MapPointersEncodable()) if (!Heap::map_space()->MapPointersEncodable())
compacting_collection_ = false; compacting_collection_ = false;
if (FLAG_collect_maps) CreateBackPointers(); if (FLAG_collect_maps) CreateBackPointers();
#ifdef ENABLE_GDB_JIT_INTERFACE
if (FLAG_gdbjit) {
// If GDBJIT interface is active disable compaction.
compacting_collection_ = false;
}
#endif
PagedSpaces spaces; PagedSpaces spaces;
for (PagedSpace* space = spaces.next(); for (PagedSpace* space = spaces.next();
...@@ -2906,6 +2913,11 @@ int MarkCompactCollector::RelocateNewObject(HeapObject* obj) { ...@@ -2906,6 +2913,11 @@ int MarkCompactCollector::RelocateNewObject(HeapObject* obj) {
void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj) { void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj) {
#ifdef ENABLE_GDB_JIT_INTERFACE
if (obj->IsCode()) {
GDBJITInterface::RemoveCode(reinterpret_cast<Code*>(obj));
}
#endif
#ifdef ENABLE_LOGGING_AND_PROFILING #ifdef ENABLE_LOGGING_AND_PROFILING
if (obj->IsCode()) { if (obj->IsCode()) {
PROFILE(CodeDeleteEvent(obj->address())); PROFILE(CodeDeleteEvent(obj->address()));
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment