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

Commit

Permalink
Merge pull request #7 from dp7/master
Browse files Browse the repository at this point in the history
V8 profiling patch re-based on Chromium v34
  • Loading branch information
darktears committed Mar 19, 2014
2 parents 2b716f2 + 0483117 commit edd9fe8
Show file tree
Hide file tree
Showing 12 changed files with 1,308 additions and 7 deletions.
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

0 comments on commit edd9fe8

Please sign in to comment.