Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(364)

Unified Diff: src/log.cc

Issue 18259024: Logger: extract low level logging code into a separate class. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: comments addressed Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/log.h ('k') | src/log-utils.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/log.cc
diff --git a/src/log.cc b/src/log.cc
index a44add6cb928f8fe59fc6d8ffff6d595318a6055..843d128679649c920112bd702defd15276ed92db 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -45,6 +45,82 @@
namespace v8 {
namespace internal {
+
+// Low-level logging support.
+class LowLevelLogger {
+ public:
+ explicit LowLevelLogger(const char* file_name);
+ ~LowLevelLogger();
+
+ void CodeCreateEvent(Code* code, const char* name, int name_size);
+ void CodeMoveEvent(Address from, Address to);
+ void CodeDeleteEvent(Address from);
+ void SnapshotPositionEvent(Address addr, int pos);
+ void CodeMovingGCEvent();
+
+ private:
+ // Low-level profiling event structures.
+
+ struct CodeCreateStruct {
+ static const char kTag = 'C';
+
+ int32_t name_size;
+ Address code_address;
+ int32_t code_size;
+ };
+
+
+ struct CodeMoveStruct {
+ static const char kTag = 'M';
+
+ Address from_address;
+ Address to_address;
+ };
+
+
+ struct CodeDeleteStruct {
+ static const char kTag = 'D';
+
+ Address address;
+ };
+
+
+ struct SnapshotPositionStruct {
+ static const char kTag = 'P';
+
+ Address address;
+ int32_t position;
+ };
+
+
+ static const char kCodeMovingGCTag = 'G';
+
+
+ // Extension added to V8 log file name to get the low-level log name.
+ static const char kLogExt[];
+
+ // File buffer size of the low-level log. We don't use the default to
+ // minimize the associated overhead.
+ static const int kLogBufferSize = 2 * MB;
+
+ void LogCodeInfo();
+ void LogWriteBytes(const char* bytes, int size);
+
+ template <typename T>
+ void LogWriteStruct(const T& s) {
+ char tag = T::kTag;
+ LogWriteBytes(reinterpret_cast<const char*>(&tag), sizeof(tag));
+ LogWriteBytes(reinterpret_cast<const char*>(&s), sizeof(s));
+ }
+
+ FILE* ll_output_handle_;
+};
+
+const char LowLevelLogger::kLogExt[] = ".ll";
+
+#define LL_LOG(Call) if (ll_logger_) ll_logger_->Call;
+
+
// 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.
@@ -210,43 +286,6 @@ void Profiler::Run() {
}
-// Low-level profiling event structures.
-
-struct LowLevelCodeCreateStruct {
- static const char kTag = 'C';
-
- int32_t name_size;
- Address code_address;
- int32_t code_size;
-};
-
-
-struct LowLevelCodeMoveStruct {
- static const char kTag = 'M';
-
- Address from_address;
- Address to_address;
-};
-
-
-struct LowLevelCodeDeleteStruct {
- static const char kTag = 'D';
-
- Address address;
-};
-
-
-struct LowLevelSnapshotPositionStruct {
- static const char kTag = 'P';
-
- Address address;
- int32_t position;
-};
-
-
-static const char kCodeMovingGCTag = 'G';
-
-
//
// Logger class implementation.
//
@@ -405,6 +444,7 @@ Logger::Logger(Isolate* isolate)
logging_nesting_(0),
cpu_profiler_nesting_(0),
log_(new Log(this)),
+ ll_logger_(NULL),
name_buffer_(new NameBuffer),
address_to_name_map_(NULL),
is_initialized_(false),
@@ -952,9 +992,7 @@ void Logger::LogRecordedBuffer(Code* code, SharedFunctionInfo* shared) {
name_buffer_->size());
}
if (!log_->IsEnabled()) return;
- if (FLAG_ll_prof) {
- LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
- }
+ LL_LOG(CodeCreateEvent(code, name_buffer_->get(), name_buffer_->size()));
if (Serializer::enabled()) {
RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
}
@@ -1142,7 +1180,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count) {
void Logger::CodeMovingGCEvent() {
if (!log_->IsEnabled() || !FLAG_ll_prof) return;
- LowLevelLogWriteBytes(&kCodeMovingGCTag, sizeof(kCodeMovingGCTag));
+ LL_LOG(CodeMovingGCEvent());
OS::SignalCodeMovingGC();
}
@@ -1169,7 +1207,7 @@ void Logger::RegExpCodeCreateEvent(Code* code, String* source) {
void Logger::CodeMoveEvent(Address from, Address to) {
if (code_event_handler_ != NULL) IssueCodeMovedEvent(from, to);
if (!log_->IsEnabled()) return;
- if (FLAG_ll_prof) LowLevelCodeMoveEvent(from, to);
+ LL_LOG(CodeMoveEvent(from, to));
if (Serializer::enabled() && address_to_name_map_ != NULL) {
address_to_name_map_->Move(from, to);
}
@@ -1180,7 +1218,7 @@ void Logger::CodeMoveEvent(Address from, Address to) {
void Logger::CodeDeleteEvent(Address from) {
if (code_event_handler_ != NULL) IssueCodeRemovedEvent(from);
if (!log_->IsEnabled()) return;
- if (FLAG_ll_prof) LowLevelCodeDeleteEvent(from);
+ LL_LOG(CodeDeleteEvent(from));
if (Serializer::enabled() && address_to_name_map_ != NULL) {
address_to_name_map_->Remove(from);
}
@@ -1226,7 +1264,7 @@ void Logger::CodeEndLinePosInfoRecordEvent(Code* code,
void Logger::SnapshotPositionEvent(Address addr, int pos) {
if (!log_->IsEnabled()) return;
- if (FLAG_ll_prof) LowLevelSnapshotPositionEvent(addr, pos);
+ LL_LOG(SnapshotPositionEvent(addr, pos));
if (Serializer::enabled() && address_to_name_map_ != NULL) {
const char* code_name = address_to_name_map_->Lookup(addr);
if (code_name == NULL) return; // Not a code object.
@@ -1564,8 +1602,38 @@ void Logger::LogCodeObject(Object* object) {
}
-void Logger::LogCodeInfo() {
- if (!log_->IsEnabled() || !FLAG_ll_prof) return;
+void Logger::RegisterSnapshotCodeName(Code* code,
+ const char* name,
+ int name_size) {
+ ASSERT(Serializer::enabled());
+ if (address_to_name_map_ == NULL) {
+ address_to_name_map_ = new NameMap;
+ }
+ address_to_name_map_->Insert(code->address(), name, name_size);
+}
+
+
+LowLevelLogger::LowLevelLogger(const char* name)
+ : ll_output_handle_(NULL) {
+ // Open the low-level log file.
+ size_t len = strlen(name);
+ ScopedVector<char> ll_name(static_cast<int>(len + sizeof(kLogExt)));
+ OS::MemCopy(ll_name.start(), name, len);
+ OS::MemCopy(ll_name.start() + len, kLogExt, sizeof(kLogExt));
+ ll_output_handle_ = OS::FOpen(ll_name.start(), OS::LogFileOpenMode);
+ setvbuf(ll_output_handle_, NULL, _IOFBF, kLogBufferSize);
+
+ LogCodeInfo();
+}
+
+
+LowLevelLogger::~LowLevelLogger() {
+ fclose(ll_output_handle_);
+ ll_output_handle_ = NULL;
+}
+
+
+void LowLevelLogger::LogCodeInfo() {
#if V8_TARGET_ARCH_IA32
const char arch[] = "ia32";
#elif V8_TARGET_ARCH_X64
@@ -1577,71 +1645,62 @@ void Logger::LogCodeInfo() {
#else
const char arch[] = "unknown";
#endif
- LowLevelLogWriteBytes(arch, sizeof(arch));
-}
-
-
-void Logger::RegisterSnapshotCodeName(Code* code,
- const char* name,
- int name_size) {
- ASSERT(Serializer::enabled());
- if (address_to_name_map_ == NULL) {
- address_to_name_map_ = new NameMap;
- }
- address_to_name_map_->Insert(code->address(), name, name_size);
+ LogWriteBytes(arch, sizeof(arch));
}
-
-void Logger::LowLevelCodeCreateEvent(Code* code,
+void LowLevelLogger::CodeCreateEvent(Code* code,
const char* name,
int name_size) {
- if (log_->ll_output_handle_ == NULL) return;
- LowLevelCodeCreateStruct event;
+ CodeCreateStruct event;
event.name_size = name_size;
event.code_address = code->instruction_start();
ASSERT(event.code_address == code->address() + Code::kHeaderSize);
event.code_size = code->instruction_size();
- LowLevelLogWriteStruct(event);
- LowLevelLogWriteBytes(name, name_size);
- LowLevelLogWriteBytes(
+ LogWriteStruct(event);
+ LogWriteBytes(name, name_size);
+ LogWriteBytes(
reinterpret_cast<const char*>(code->instruction_start()),
code->instruction_size());
}
-void Logger::LowLevelCodeMoveEvent(Address from, Address to) {
- if (log_->ll_output_handle_ == NULL) return;
- LowLevelCodeMoveStruct event;
+void LowLevelLogger::CodeMoveEvent(Address from, Address to) {
+ CodeMoveStruct event;
event.from_address = from + Code::kHeaderSize;
event.to_address = to + Code::kHeaderSize;
- LowLevelLogWriteStruct(event);
+ LogWriteStruct(event);
}
-void Logger::LowLevelCodeDeleteEvent(Address from) {
- if (log_->ll_output_handle_ == NULL) return;
- LowLevelCodeDeleteStruct event;
+void LowLevelLogger::CodeDeleteEvent(Address from) {
+ CodeDeleteStruct event;
event.address = from + Code::kHeaderSize;
- LowLevelLogWriteStruct(event);
+ LogWriteStruct(event);
}
-void Logger::LowLevelSnapshotPositionEvent(Address addr, int pos) {
- if (log_->ll_output_handle_ == NULL) return;
- LowLevelSnapshotPositionStruct event;
+void LowLevelLogger::SnapshotPositionEvent(Address addr, int pos) {
+ SnapshotPositionStruct event;
event.address = addr + Code::kHeaderSize;
event.position = pos;
- LowLevelLogWriteStruct(event);
+ LogWriteStruct(event);
}
-void Logger::LowLevelLogWriteBytes(const char* bytes, int size) {
- size_t rv = fwrite(bytes, 1, size, log_->ll_output_handle_);
+void LowLevelLogger::LogWriteBytes(const char* bytes, int size) {
+ size_t rv = fwrite(bytes, 1, size, ll_output_handle_);
ASSERT(static_cast<size_t>(size) == rv);
USE(rv);
}
+void LowLevelLogger::CodeMovingGCEvent() {
+ const char tag = kCodeMovingGCTag;
+
+ LogWriteBytes(&tag, sizeof(tag));
+}
+
+
void Logger::LogCodeObjects() {
Heap* heap = isolate_->heap();
heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
@@ -1744,6 +1803,63 @@ void Logger::LogAccessorCallbacks() {
}
+static void AddIsolateIdIfNeeded(StringStream* stream) {
+ Isolate* isolate = Isolate::Current();
+ if (isolate->IsDefaultIsolate()) return;
+ stream->Add("isolate-%p-", isolate);
+}
+
+
+static SmartArrayPointer<const char> PrepareLogFileName(const char* file_name) {
+ if (strchr(file_name, '%') != NULL ||
+ !Isolate::Current()->IsDefaultIsolate()) {
+ // If there's a '%' in the log file name we have to expand
+ // placeholders.
+ HeapStringAllocator allocator;
+ StringStream stream(&allocator);
+ AddIsolateIdIfNeeded(&stream);
+ for (const char* p = file_name; *p; p++) {
+ if (*p == '%') {
+ p++;
+ switch (*p) {
+ case '\0':
+ // If there's a % at the end of the string we back up
+ // one character so we can escape the loop properly.
+ p--;
+ break;
+ case 'p':
+ stream.Add("%d", OS::GetCurrentProcessId());
+ break;
+ case 't': {
+ // %t expands to the current time in milliseconds.
+ double time = OS::TimeCurrentMillis();
+ stream.Add("%.0f", FmtElm(time));
+ break;
+ }
+ case '%':
+ // %% expands (contracts really) to %.
+ stream.Put('%');
+ break;
+ default:
+ // All other %'s expand to themselves.
+ stream.Put('%');
+ stream.Put(*p);
+ break;
+ }
+ } else {
+ stream.Put(*p);
+ }
+ }
+ return SmartArrayPointer<const char>(stream.ToCString());
+ }
+ int length = StrLength(file_name);
+ char* str = NewArray<char>(length + 1);
+ OS::MemCopy(str, file_name, length);
+ str[length] = '\0';
+ return SmartArrayPointer<const char>(str);
+}
+
+
bool Logger::SetUp(Isolate* isolate) {
// Tests and EnsureInitialize() can call this twice in a row. It's harmless.
if (is_initialized_) return true;
@@ -1760,9 +1876,13 @@ bool Logger::SetUp(Isolate* isolate) {
FLAG_prof_auto = false;
}
- log_->Initialize();
+ SmartArrayPointer<const char> log_file_name =
+ PrepareLogFileName(FLAG_logfile);
+ log_->Initialize(*log_file_name);
- if (FLAG_ll_prof) LogCodeInfo();
+ if (FLAG_ll_prof) {
+ ll_logger_ = new LowLevelLogger(*log_file_name);
+ }
ticker_ = new Ticker(isolate, kSamplingIntervalMs);
@@ -1819,6 +1939,11 @@ FILE* Logger::TearDown() {
delete ticker_;
ticker_ = NULL;
+ if (ll_logger_) {
+ delete ll_logger_;
+ ll_logger_ = NULL;
+ }
+
return log_->Close();
}
« no previous file with comments | « src/log.h ('k') | src/log-utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698