Commit adae3f77 authored by vegorov@chromium.org's avatar vegorov@chromium.org

Allow redirecting disassembly and deoptimization traces into a file.

This is controlled by two flags:

--redirect_code_traces
--redirect_code_traces_to=<filename>

When redirection is enabled but --redirect_code_traces_to is not specified traces are written to a file code-<pid>-<isolate>.asm. This mangling scheme matches hydrogen.cfg and allows easy discovery of compilation artifacts in a multi-V8 environment (e.g. when compilation is traced from inside Chromium).

D8 defines --redirect_code_traces_to=code.asm similar to hydrogen.cfg redirection.

BUG=
R=danno@chromium.org

Review URL: https://codereview.chromium.org/43273004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17571 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d538ff90
......@@ -826,7 +826,7 @@ void RelocInfo::Print(Isolate* isolate, FILE* out) {
PrintF(out, " (%s) (%p)", Code::Kind2String(code->kind()),
target_address());
if (rmode_ == CODE_TARGET_WITH_ID) {
PrintF(" (id=%d)", static_cast<int>(data_));
PrintF(out, " (id=%d)", static_cast<int>(data_));
}
} else if (IsPosition(rmode_)) {
PrintF(out, " (%" V8_PTR_PREFIX "d)", data());
......
......@@ -1750,9 +1750,10 @@ void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
builtins_[i] = code;
#ifdef ENABLE_DISASSEMBLER
if (FLAG_print_builtin_code) {
PrintF("Builtin: %s\n", functions[i].s_name);
Code::cast(code)->Disassemble(functions[i].s_name);
PrintF("\n");
CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
PrintF(trace_scope.file(), "Builtin: %s\n", functions[i].s_name);
Code::cast(code)->Disassemble(functions[i].s_name, trace_scope.file());
PrintF(trace_scope.file(), "\n");
}
#endif
} else {
......
......@@ -160,8 +160,9 @@ Handle<Code> CodeStub::GetCode(Isolate* isolate) {
#ifdef ENABLE_DISASSEMBLER
if (FLAG_print_code_stubs) {
new_object->Disassemble(*GetName());
PrintF("\n");
CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
new_object->Disassemble(*GetName(), trace_scope.file());
PrintF(trace_scope.file(), "\n");
}
#endif
......
......@@ -136,10 +136,12 @@ void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
FunctionLiteral* function = info->function();
bool print_source = code->kind() == Code::OPTIMIZED_FUNCTION ||
code->kind() == Code::FUNCTION;
CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer());
if (print_source) {
Handle<Script> script = info->script();
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
PrintF("--- Raw source ---\n");
PrintF(tracing_scope.file(), "--- Raw source ---\n");
ConsStringIteratorOp op;
StringCharacterStream stream(String::cast(script->source()),
&op,
......@@ -149,31 +151,36 @@ void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
int source_len =
function->end_position() - function->start_position() + 1;
for (int i = 0; i < source_len; i++) {
if (stream.HasMore()) PrintF("%c", stream.GetNext());
if (stream.HasMore()) {
PrintF(tracing_scope.file(), "%c", stream.GetNext());
}
}
PrintF("\n\n");
PrintF(tracing_scope.file(), "\n\n");
}
}
if (info->IsOptimizing()) {
if (FLAG_print_unopt_code) {
PrintF("--- Unoptimized code ---\n");
PrintF(tracing_scope.file(), "--- Unoptimized code ---\n");
info->closure()->shared()->code()->Disassemble(
*function->debug_name()->ToCString());
*function->debug_name()->ToCString(), tracing_scope.file());
}
PrintF("--- Optimized code ---\n");
PrintF(tracing_scope.file(), "--- Optimized code ---\n");
} else {
PrintF("--- Code ---\n");
PrintF(tracing_scope.file(), "--- Code ---\n");
}
if (print_source) {
PrintF("source_position = %d\n", function->start_position());
PrintF(tracing_scope.file(),
"source_position = %d\n", function->start_position());
}
if (info->IsStub()) {
CodeStub::Major major_key = info->code_stub()->MajorKey();
code->Disassemble(CodeStub::MajorName(major_key, false));
code->Disassemble(CodeStub::MajorName(major_key, false),
tracing_scope.file());
} else {
code->Disassemble(*function->debug_name()->ToCString());
code->Disassemble(*function->debug_name()->ToCString(),
tracing_scope.file());
}
PrintF("--- End code ---\n");
PrintF(tracing_scope.file(), "--- End code ---\n");
}
#endif // ENABLE_DISASSEMBLER
}
......
......@@ -1585,6 +1585,7 @@ static void SetStandaloneFlagsViaCommandLine() {
char **fake_argv = new char*[2];
fake_argv[0] = NULL;
fake_argv[1] = strdup("--trace-hydrogen-file=hydrogen.cfg");
fake_argv[2] = strdup("--redirect-code-traces-to=code.asm");
v8::V8::SetFlagsFromCommandLine(&fake_argc, fake_argv, false);
free(fake_argv[1]);
delete[] fake_argv;
......@@ -1674,6 +1675,7 @@ int Shell::Main(int argc, char* argv[]) {
v8::V8::InitializeICU();
#ifndef V8_SHARED
i::FLAG_trace_hydrogen_file = "hydrogen.cfg";
i::FLAG_redirect_code_traces_to = "code.asm";
#else
SetStandaloneFlagsViaCommandLine();
#endif
......
This diff is collapsed.
......@@ -451,7 +451,7 @@ class Deoptimizer : public Malloced {
DisallowHeapAllocation* disallow_heap_allocation_;
#endif // DEBUG
bool trace_;
CodeTracer::Scope* trace_scope_;
static const int table_entry_size_;
......
......@@ -795,6 +795,12 @@ DEFINE_bool(log_timer_events, false,
DEFINE_implication(log_timer_events, log_internal_timer_events)
DEFINE_implication(log_internal_timer_events, prof)
DEFINE_bool(redirect_code_traces, false,
"output deopt information and disassembly into file "
"code-<pid>-<isolate id>.asm")
DEFINE_string(redirect_code_traces_to, NULL,
"output deopt information and disassembly into the given file")
//
// Disassembler only flags
//
......
......@@ -2465,6 +2465,12 @@ HTracer* Isolate::GetHTracer() {
}
CodeTracer* Isolate::GetCodeTracer() {
if (code_tracer() == NULL) set_code_tracer(new CodeTracer(id()));
return code_tracer();
}
Map* Isolate::get_initial_js_array_map(ElementsKind kind) {
Context* native_context = context()->native_context();
Object* maybe_map_array = native_context->js_array_maps();
......
......@@ -55,6 +55,7 @@ class Bootstrapper;
class CodeGenerator;
class CodeRange;
struct CodeStubInterfaceDescriptor;
class CodeTracer;
class CompilationCache;
class ContextSlotCache;
class ContextSwitcher;
......@@ -377,6 +378,7 @@ typedef List<HeapObject*, PreallocatedStorageAllocationPolicy> DebugObjectCache;
V(bool, observer_delivery_pending, false) \
V(HStatistics*, hstatistics, NULL) \
V(HTracer*, htracer, NULL) \
V(CodeTracer*, code_tracer, NULL) \
ISOLATE_DEBUGGER_INIT_LIST(V)
class Isolate {
......@@ -1126,6 +1128,7 @@ class Isolate {
HStatistics* GetHStatistics();
HTracer* GetHTracer();
CodeTracer* GetCodeTracer();
FunctionEntryHook function_entry_hook() { return function_entry_hook_; }
void set_function_entry_hook(FunctionEntryHook function_entry_hook) {
......@@ -1507,6 +1510,73 @@ inline void Context::mark_out_of_memory() {
native_context()->set_out_of_memory(GetIsolate()->heap()->true_value());
}
class CodeTracer V8_FINAL : public Malloced {
public:
explicit CodeTracer(int isolate_id)
: file_(NULL),
scope_depth_(0) {
if (!ShouldRedirect()) {
file_ = stdout;
return;
}
if (FLAG_redirect_code_traces_to == NULL) {
OS::SNPrintF(filename_,
"code-%d-%d.asm",
OS::GetCurrentProcessId(),
isolate_id);
} else {
OS::StrNCpy(filename_, FLAG_redirect_code_traces_to, filename_.length());
}
WriteChars(filename_.start(), "", 0, false);
}
class Scope {
public:
explicit Scope(CodeTracer* tracer) : tracer_(tracer) { tracer->OpenFile(); }
~Scope() { tracer_->CloseFile(); }
FILE* file() const { return tracer_->file(); }
private:
CodeTracer* tracer_;
};
void OpenFile() {
if (!ShouldRedirect()) {
return;
}
if (file_ == NULL) {
file_ = OS::FOpen(filename_.start(), "a");
}
scope_depth_++;
}
void CloseFile() {
if (!ShouldRedirect()) {
return;
}
if (--scope_depth_ == 0) {
fclose(file_);
file_ = NULL;
}
}
FILE* file() const { return file_; }
private:
static bool ShouldRedirect() {
return FLAG_redirect_code_traces;
}
EmbeddedVector<char, 128> filename_;
FILE* file_;
int scope_depth_;
};
} } // namespace v8::internal
......
......@@ -1150,7 +1150,9 @@ RegExpEngine::CompilationResult RegExpCompiler::Assemble(
work_list_ = NULL;
#ifdef DEBUG
if (FLAG_print_code) {
Handle<Code>::cast(code)->Disassemble(*pattern->ToCString());
CodeTracer::Scope trace_scope(heap->isolate()->GetCodeTracer());
Handle<Code>::cast(code)->Disassemble(*pattern->ToCString(),
trace_scope.file());
}
if (FLAG_trace_regexp_assembler) {
delete macro_assembler_;
......
......@@ -830,7 +830,7 @@ void JSTypedArray::JSTypedArrayPrint(FILE* out) {
byte_length()->ShortPrint(out);
PrintF(out, "\n - length = ");
length()->ShortPrint(out);
PrintF("\n");
PrintF(out, "\n");
PrintElements(out);
}
......@@ -844,7 +844,7 @@ void JSDataView::JSDataViewPrint(FILE* out) {
byte_offset()->ShortPrint(out);
PrintF(out, "\n - byte_length = ");
byte_length()->ShortPrint(out);
PrintF("\n");
PrintF(out, "\n");
}
......
......@@ -10831,7 +10831,7 @@ Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
}
void Code::PrintDeoptLocation(int bailout_id) {
void Code::PrintDeoptLocation(FILE* out, int bailout_id) {
const char* last_comment = NULL;
int mask = RelocInfo::ModeMask(RelocInfo::COMMENT)
| RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
......@@ -10845,7 +10845,7 @@ void Code::PrintDeoptLocation(int bailout_id) {
(bailout_id == Deoptimizer::GetDeoptimizationId(
GetIsolate(), info->target_address(), Deoptimizer::SOFT))) {
CHECK(RelocInfo::IsRuntimeEntry(info->rmode()));
PrintF(" %s\n", last_comment);
PrintF(out, " %s\n", last_comment);
return;
}
}
......@@ -11047,10 +11047,10 @@ void DeoptimizationOutputData::DeoptimizationOutputDataPrint(FILE* out) {
this->DeoptPoints());
if (this->DeoptPoints() == 0) return;
PrintF("%6s %8s %s\n", "ast id", "pc", "state");
PrintF(out, "%6s %8s %s\n", "ast id", "pc", "state");
for (int i = 0; i < this->DeoptPoints(); i++) {
int pc_and_state = this->PcAndState(i)->value();
PrintF("%6d %8d %s\n",
PrintF(out, "%6d %8d %s\n",
this->AstId(i).ToInt(),
FullCodeGenerator::PcField::decode(pc_and_state),
FullCodeGenerator::State2String(
......@@ -11161,7 +11161,7 @@ void Code::Disassemble(const char* name, FILE* out) {
DeoptimizationInputData::cast(this->deoptimization_data());
data->DeoptimizationInputDataPrint(out);
}
PrintF("\n");
PrintF(out, "\n");
if (is_crankshafted()) {
SafepointTable table(this);
......@@ -11169,7 +11169,7 @@ void Code::Disassemble(const char* name, FILE* out) {
for (unsigned i = 0; i < table.length(); i++) {
unsigned pc_offset = table.GetPcOffset(i);
PrintF(out, "%p %4d ", (instruction_start() + pc_offset), pc_offset);
table.PrintEntry(i);
table.PrintEntry(i, out);
PrintF(out, " (sp -> fp)");
SafepointEntry entry = table.GetEntry(i);
if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
......@@ -11210,7 +11210,7 @@ void Code::Disassemble(const char* name, FILE* out) {
#endif
}
PrintF("RelocInfo (size = %d)\n", relocation_size());
PrintF(out, "RelocInfo (size = %d)\n", relocation_size());
for (RelocIterator it(this); !it.done(); it.next()) {
it.rinfo()->Print(GetIsolate(), out);
}
......
......@@ -5376,7 +5376,7 @@ class Code: public HeapObject {
return GetCodeAgeStub(isolate, kNotExecutedCodeAge, NO_MARKING_PARITY);
}
void PrintDeoptLocation(int bailout_id);
void PrintDeoptLocation(FILE* out, int bailout_id);
bool CanDeoptAt(Address pc);
#ifdef VERIFY_HEAP
......
......@@ -83,7 +83,7 @@ SafepointEntry SafepointTable::FindEntry(Address pc) const {
}
void SafepointTable::PrintEntry(unsigned index) const {
void SafepointTable::PrintEntry(unsigned index, FILE* out) const {
disasm::NameConverter converter;
SafepointEntry entry = GetEntry(index);
uint8_t* bits = entry.bits();
......@@ -93,25 +93,25 @@ void SafepointTable::PrintEntry(unsigned index) const {
ASSERT(IsAligned(kNumSafepointRegisters, kBitsPerByte));
const int first = kNumSafepointRegisters >> kBitsPerByteLog2;
int last = entry_size_ - 1;
for (int i = first; i < last; i++) PrintBits(bits[i], kBitsPerByte);
for (int i = first; i < last; i++) PrintBits(out, bits[i], kBitsPerByte);
int last_bits = code_->stack_slots() - ((last - first) * kBitsPerByte);
PrintBits(bits[last], last_bits);
PrintBits(out, bits[last], last_bits);
// Print the registers (if any).
if (!entry.HasRegisters()) return;
for (int j = 0; j < kNumSafepointRegisters; j++) {
if (entry.HasRegisterAt(j)) {
PrintF(" | %s", converter.NameOfCPURegister(j));
PrintF(out, " | %s", converter.NameOfCPURegister(j));
}
}
}
}
void SafepointTable::PrintBits(uint8_t byte, int digits) {
void SafepointTable::PrintBits(FILE* out, uint8_t byte, int digits) {
ASSERT(digits >= 0 && digits <= kBitsPerByte);
for (int i = 0; i < digits; i++) {
PrintF("%c", ((byte & (1 << i)) == 0) ? '0' : '1');
PrintF(out, "%c", ((byte & (1 << i)) == 0) ? '0' : '1');
}
}
......
......@@ -126,7 +126,7 @@ class SafepointTable BASE_EMBEDDED {
// Returns the entry for the given pc.
SafepointEntry FindEntry(Address pc) const;
void PrintEntry(unsigned index) const;
void PrintEntry(unsigned index, FILE* out = stdout) const;
private:
static const uint8_t kNoRegisters = 0xFF;
......@@ -149,7 +149,7 @@ class SafepointTable BASE_EMBEDDED {
return GetPcOffsetLocation(index) + kPcSize;
}
static void PrintBits(uint8_t byte, int digits);
static void PrintBits(FILE* out, uint8_t byte, int digits);
DisallowHeapAllocation no_allocation_;
Code* code_;
......
......@@ -1096,7 +1096,10 @@ Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
masm_.GetCode(&desc);
Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject());
#ifdef ENABLE_DISASSEMBLER
if (FLAG_print_code_stubs) code->Disassemble(name);
if (FLAG_print_code_stubs) {
CodeTracer::Scope trace_scope(isolate()->GetCodeTracer());
code->Disassemble(name, trace_scope.file());
}
#endif
return code;
}
......
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