Skip to content
This repository has been archived by the owner on Apr 3, 2020. It is now read-only.

V8 profiling patch re-based on Chromium v34 #7

Merged
merged 1 commit into from
Mar 19, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions build/features.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@

'v8_use_snapshot%': 'true',

# Enable XDK profiling support by default.
'v8_enable_xdkprof': 1,

# With post mortem support enabled, metadata is embedded into libv8 that
# describes various parameters of the VM for use by debuggers. See
# tools/gen-postmortem-metadata.py for details.
Expand Down
276 changes: 272 additions & 4 deletions src/log.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
#include "string-stream.h"
#include "vm-state-inl.h"

// XDK support
#include "third_party/xdk/xdk-v8.h"

namespace v8 {
namespace internal {

Expand Down Expand Up @@ -160,6 +163,15 @@ class CodeEventLogger::NameBuffer {
}
}

// XDK needs this function temporarily. It will be removed later.
void AppendAddress(Address address) {
Vector<char> buffer(utf8_buffer_ + utf8_pos_, kUtf8BufferSize - utf8_pos_);
int size = OS::SNPrintF(buffer, "0x%x", address);
if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
utf8_pos_ += size;
}
}

const char* get() { return utf8_buffer_; }
int size() const { return utf8_pos_; }

Expand Down Expand Up @@ -656,6 +668,226 @@ class JitLogger : public CodeEventLogger {
void* StartCodePosInfoEvent();
void EndCodePosInfoEvent(Code* code, void* jit_handler_data);

// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// XDK needs all this stuff below to generate the strings like
// "code-creation:..." in the same format as Logger generates.
// This string is sent to XDK by code_event_handler and then used for
// postprocessing. All these CodeCreateEvent(...) functions and helpers
// will be removed before commit.
void AppendCodeCreateHeader(NameBuffer* msg,
Logger::LogEventsAndTags tag,
Code* code) {
CHECK(msg);
msg->AppendBytes(kLogEventsNames[Logger::CODE_CREATION_EVENT]);
msg->AppendByte(',');
msg->AppendBytes(kLogEventsNames[tag]);
msg->AppendByte(',');
msg->AppendInt(code->kind());
msg->AppendByte(',');
msg->AppendAddress(code->instruction_start());
msg->AppendByte(',');
msg->AppendInt(code->instruction_size());
msg->AppendByte(',');
}


void AppendDetailed(NameBuffer* msg, String* str, bool show_impl_info) {
CHECK(msg);
if (str == NULL) return;
DisallowHeapAllocation no_gc; // Ensure string stay valid.
int len = str->length();
if (len > 0x1000)
len = 0x1000;
if (show_impl_info) {
msg->AppendByte(str->IsOneByteRepresentation() ? 'a' : '2');
if (StringShape(str).IsExternal())
msg->AppendByte('e');
if (StringShape(str).IsInternalized())
msg->AppendByte('#');
msg->AppendByte(':');
msg->AppendInt(str->length());
msg->AppendByte(':');
}
for (int i = 0; i < len; i++) {
uc32 c = str->Get(i);
if (c > 0xff) {
msg->AppendBytes("\\u");
msg->AppendHex(c);
} else if (c < 32 || c > 126) {
msg->AppendBytes("\\x");
msg->AppendHex(c);
} else if (c == ',') {
msg->AppendBytes("\\,");
} else if (c == '\\') {
msg->AppendBytes("\\\\");
} else if (c == '\"') {
msg->AppendBytes("\"\"");
} else {
msg->AppendByte(c);
}
}
}


void AppendDoubleQuotedString(NameBuffer* msg, const char* string) {
CHECK(msg);
msg->AppendByte('"');
for (const char* p = string; *p != '\0'; p++) {
if (*p == '"') {
msg->AppendByte('\\');
}
msg->AppendByte(*p);
}
msg->AppendByte('"');
}

void AppendSymbolName(NameBuffer* msg, Symbol* symbol) {
CHECK(msg);
ASSERT(symbol);
msg->AppendBytes("symbol(");
if (!symbol->name()->IsUndefined()) {
msg->AppendByte('"');
AppendDetailed(msg, String::cast(symbol->name()), false);
msg->AppendBytes("\" ");
}
msg->AppendBytes("hash ");
msg->AppendHex(symbol->Hash());
msg->AppendByte(')');
}


virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code, const char* comment) {
name_buffer_->Reset();
AppendCodeCreateHeader(name_buffer_, tag, code);
AppendDoubleQuotedString(name_buffer_, comment);
LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
}


virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code, Name* name) {
name_buffer_->Reset();
AppendCodeCreateHeader(name_buffer_, tag, code);
if (name->IsString()) {
name_buffer_->AppendByte('"');
AppendDetailed(name_buffer_, String::cast(name), false);
name_buffer_->AppendByte('"');
} else {
AppendSymbolName(name_buffer_, Symbol::cast(name));
}
LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
}


virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
CompilationInfo* info,
Name* name) {
name_buffer_->Reset();
AppendCodeCreateHeader(name_buffer_, tag, code);
if (name->IsString()) {
SmartArrayPointer<char> str =
String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
name_buffer_->AppendByte('"');
name_buffer_->AppendBytes(str.get());
name_buffer_->AppendByte('"');
} else {
AppendSymbolName(name_buffer_, Symbol::cast(name));
}
name_buffer_->AppendByte(',');
name_buffer_->AppendAddress(shared->address());
name_buffer_->AppendByte(',');
name_buffer_->AppendBytes(ComputeMarker(code));
LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
}


virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
CompilationInfo* info,
Name* source,
int line, int column) {
name_buffer_->Reset();
AppendCodeCreateHeader(name_buffer_, tag, code);
SmartArrayPointer<char> name =
shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
name_buffer_->AppendByte('"');
name_buffer_->AppendBytes(name.get());
name_buffer_->AppendByte(' ');
if (source->IsString()) {
SmartArrayPointer<char> sourcestr =
String::cast(source)->ToCString(DISALLOW_NULLS,
ROBUST_STRING_TRAVERSAL);
name_buffer_->AppendBytes(sourcestr.get());
} else {
AppendSymbolName(name_buffer_, Symbol::cast(source));
}
name_buffer_->AppendByte(':');
name_buffer_->AppendInt(line);
name_buffer_->AppendByte(':');
name_buffer_->AppendInt(column);
name_buffer_->AppendBytes("\",");
name_buffer_->AppendAddress(shared->address());
name_buffer_->AppendByte(',');
name_buffer_->AppendBytes(ComputeMarker(code));
LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
}


virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
CompilationInfo* info,
Name* source,
int line) {
name_buffer_->Reset();
AppendCodeCreateHeader(name_buffer_, tag, code);
SmartArrayPointer<char> name =
shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
name_buffer_->AppendByte('"');
name_buffer_->AppendBytes(name.get());
name_buffer_->AppendByte(' ');
if (source->IsString()) {
SmartArrayPointer<char> sourcestr =
String::cast(source)->ToCString(DISALLOW_NULLS,
ROBUST_STRING_TRAVERSAL);
name_buffer_->AppendBytes(sourcestr.get());
} else {
AppendSymbolName(name_buffer_, Symbol::cast(source));
}
name_buffer_->AppendByte(':');
name_buffer_->AppendInt(line);
name_buffer_->AppendBytes("\",");
name_buffer_->AppendAddress(shared->address());
name_buffer_->AppendByte(',');
name_buffer_->AppendBytes(ComputeMarker(code));
LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
}


virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code,
int args_count) {
name_buffer_->Reset();
AppendCodeCreateHeader(name_buffer_, tag, code);
name_buffer_->AppendBytes("\"args_count: ");
name_buffer_->AppendInt(args_count);
name_buffer_->AppendByte('"');
}


virtual void RegExpCodeCreateEvent(Code* code, String* source) {
name_buffer_->Reset();
AppendCodeCreateHeader(name_buffer_, Logger::REG_EXP_TAG, code);
name_buffer_->AppendByte('"');
AppendDetailed(name_buffer_, source, false);
name_buffer_->AppendByte('"');
}
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

private:
virtual void LogRecordedBuffer(Code* code,
SharedFunctionInfo* shared,
Expand Down Expand Up @@ -760,6 +992,7 @@ void JitLogger::EndCodePosInfoEvent(Code* code, void* jit_handler_data) {
}



// The Profiler samples pc and sp values for the main thread.
// Each sample is appended to a circular buffer.
// An independent thread removes data and writes it to the log.
Expand Down Expand Up @@ -1376,8 +1609,8 @@ static void AppendCodeCreateHeader(Log::MessageBuilder* msg,
kLogEventsNames[Logger::CODE_CREATION_EVENT],
kLogEventsNames[tag],
code->kind());
msg->AppendAddress(code->address());
msg->Append(",%d,", code->ExecutableSize());
msg->AppendAddress(code->instruction_start());
msg->Append(",%d,", code->instruction_size());
}


Expand Down Expand Up @@ -1623,11 +1856,18 @@ void Logger::MoveEventInternal(LogEventsAndTags event,
Address from,
Address to) {
if (!FLAG_log_code || !log_->IsEnabled()) return;

Code* from_code = Code::cast(HeapObject::FromAddress(from));
const size_t header_size =
from_code->instruction_start() - reinterpret_cast<byte*>(from_code);
Address to_code =
reinterpret_cast<byte*>(HeapObject::FromAddress(to)) + header_size;

Log::MessageBuilder msg(log_);
msg.Append("%s,", kLogEventsNames[event]);
msg.AppendAddress(from);
msg.AppendAddress(from_code->instruction_start());
msg.Append(',');
msg.AppendAddress(to);
msg.AppendAddress(to_code);
msg.Append('\n');
msg.WriteToLogFile();
}
Expand Down Expand Up @@ -1748,6 +1988,15 @@ void Logger::TickEvent(TickSample* sample, bool overflow) {
}


void Logger::XDKResumeProfiler() {
if (!log_->IsEnabled()) return;
if (profiler_ != NULL) {
profiler_->resume();
is_logging_ = true;
}
}


void Logger::StopProfiler() {
if (!log_->IsEnabled()) return;
if (profiler_ != NULL) {
Expand Down Expand Up @@ -1886,6 +2135,12 @@ void Logger::LogCodeObject(Object* object) {


void Logger::LogCodeObjects() {
// Starting from Chromium v34 this function is also called from
// V8::Initialize. This causes reading the heap to collect already
// compiled methods. For XDK that must be done because XDK profiler
// consumes CODE_ADDED events and mantains a map of compiled methods.
return;

Heap* heap = isolate_->heap();
heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
"Logger::LogCodeObjects");
Expand Down Expand Up @@ -1946,6 +2201,12 @@ void Logger::LogExistingFunction(Handle<SharedFunctionInfo> shared,


void Logger::LogCompiledFunctions() {
// Starting from Chromium v34 this function is also called from
// V8::Initialize. This causes reading the heap to collect already
// compiled methods. For XDK that must be done because XDK profiler
// consumes CODE_ADDED events and mantains a map of compiled methods.
return;

Heap* heap = isolate_->heap();
heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
"Logger::LogCompiledFunctions");
Expand Down Expand Up @@ -2081,10 +2342,17 @@ bool Logger::SetUp(Isolate* isolate) {
is_logging_ = true;
}

xdk::XDKInitializeForV8(isolate);

if (FLAG_prof) {
profiler_ = new Profiler(isolate);
is_logging_ = true;
profiler_->Engage();

// A way to to start profiler in pause mode was removed.
// To pause collection of the CPU ticks we need to emulate pause.
// This will be removed later once XDK agent will have own sampler.
profiler_->pause();
}

if (FLAG_log_internal_timer_events || FLAG_prof) timer_.Start();
Expand Down
13 changes: 10 additions & 3 deletions src/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,13 @@ class Logger {
// When data collection is paused, CPU Tick events are discarded.
void StopProfiler();

// Resumes collection of CPU Tick events.
void XDKResumeProfiler();

// XDK agent uses it log code map (list of CodeAdded event
// before resume CPU Tick events.
Log* XDKGetLog() { return log_; }

void LogExistingFunction(Handle<SharedFunctionInfo> shared,
Handle<Code> code);
// Logs all compiled functions found in the heap.
Expand Down Expand Up @@ -528,15 +535,15 @@ class CodeEventLogger : public CodeEventListener {
virtual void SharedFunctionInfoMoveEvent(Address from, Address to) { }
virtual void CodeMovingGCEvent() { }

private:
protected:
class NameBuffer;
NameBuffer* name_buffer_;

private:
virtual void LogRecordedBuffer(Code* code,
SharedFunctionInfo* shared,
const char* name,
int length) = 0;

NameBuffer* name_buffer_;
};


Expand Down
Loading