diff --git a/src/log.cc b/src/log.cc index afd8f7de77..1a9dd297a9 100644 --- a/src/log.cc +++ b/src/log.cc @@ -47,21 +47,161 @@ namespace v8 { namespace internal { +#define DECLARE_EVENT(ignore1, name) name, +static const char* const kLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = { + LOG_EVENTS_AND_TAGS_LIST(DECLARE_EVENT) +}; +#undef DECLARE_EVENT + + +class CodeEventLogger { + public: + virtual ~CodeEventLogger() { } + + void CodeCreateEvent(Logger::LogEventsAndTags tag, + Code* code, + const char* comment); + void CodeCreateEvent(Logger::LogEventsAndTags tag, + Code* code, + Name* name); + void CodeCreateEvent(Logger::LogEventsAndTags tag, + Code* code, + int args_count); + void CodeCreateEvent(Logger::LogEventsAndTags tag, + Code* code, + SharedFunctionInfo* shared, + CompilationInfo* info, + Name* name); + void CodeCreateEvent(Logger::LogEventsAndTags tag, + Code* code, + SharedFunctionInfo* shared, + CompilationInfo* info, + Name* source, + int line); + void RegExpCodeCreateEvent(Code* code, String* source); + + protected: + class NameBuffer { + public: + NameBuffer() { Reset(); } + + void Reset() { + utf8_pos_ = 0; + } + + void Init(Logger::LogEventsAndTags tag) { + Reset(); + AppendBytes(kLogEventsNames[tag]); + AppendByte(':'); + } + + void AppendName(Name* name) { + if (name->IsString()) { + AppendString(String::cast(name)); + } else { + Symbol* symbol = Symbol::cast(name); + AppendBytes("symbol("); + if (!symbol->name()->IsUndefined()) { + AppendBytes("\""); + AppendString(String::cast(symbol->name())); + AppendBytes("\" "); + } + AppendBytes("hash "); + AppendHex(symbol->Hash()); + AppendByte(')'); + } + } + + void AppendString(String* str) { + if (str == NULL) return; + int uc16_length = Min(str->length(), kUtf16BufferSize); + String::WriteToFlat(str, utf16_buffer, 0, uc16_length); + int previous = unibrow::Utf16::kNoPreviousCharacter; + for (int i = 0; i < uc16_length && utf8_pos_ < kUtf8BufferSize; ++i) { + uc16 c = utf16_buffer[i]; + if (c <= unibrow::Utf8::kMaxOneByteChar) { + utf8_buffer_[utf8_pos_++] = static_cast(c); + } else { + int char_length = unibrow::Utf8::Length(c, previous); + if (utf8_pos_ + char_length > kUtf8BufferSize) break; + unibrow::Utf8::Encode(utf8_buffer_ + utf8_pos_, c, previous); + utf8_pos_ += char_length; + } + previous = c; + } + } + + void AppendBytes(const char* bytes, int size) { + size = Min(size, kUtf8BufferSize - utf8_pos_); + OS::MemCopy(utf8_buffer_ + utf8_pos_, bytes, size); + utf8_pos_ += size; + } + + void AppendBytes(const char* bytes) { + AppendBytes(bytes, StrLength(bytes)); + } + + void AppendByte(char c) { + if (utf8_pos_ >= kUtf8BufferSize) return; + utf8_buffer_[utf8_pos_++] = c; + } + + void AppendInt(int n) { + Vector buffer(utf8_buffer_ + utf8_pos_, + kUtf8BufferSize - utf8_pos_); + int size = OS::SNPrintF(buffer, "%d", n); + if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) { + utf8_pos_ += size; + } + } + + void AppendHex(uint32_t n) { + Vector buffer(utf8_buffer_ + utf8_pos_, + kUtf8BufferSize - utf8_pos_); + int size = OS::SNPrintF(buffer, "%x", n); + if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) { + utf8_pos_ += size; + } + } + + const char* get() { return utf8_buffer_; } + int size() const { return utf8_pos_; } + + private: + static const int kUtf8BufferSize = 512; + static const int kUtf16BufferSize = 128; + + int utf8_pos_; + char utf8_buffer_[kUtf8BufferSize]; + uc16 utf16_buffer[kUtf16BufferSize]; + }; + + private: + virtual void LogRecordedBuffer(Code* code, + SharedFunctionInfo* shared, + NameBuffer* name_buffer) = 0; + + NameBuffer name_buffer_; +}; + + // Low-level logging support. -class LowLevelLogger { +class LowLevelLogger : public CodeEventLogger { public: explicit LowLevelLogger(const char* file_name); - ~LowLevelLogger(); + virtual ~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. + virtual void LogRecordedBuffer(Code* code, + SharedFunctionInfo* shared, + NameBuffer* name_buffer); + // Low-level profiling event structures. struct CodeCreateStruct { static const char kTag = 'C'; @@ -122,6 +262,116 @@ const char LowLevelLogger::kLogExt[] = ".ll"; #define LL_LOG(Call) if (ll_logger_) ll_logger_->Call; +class CodeAddressMap: public CodeEventLogger { + public: + CodeAddressMap() { } + virtual ~CodeAddressMap() { } + + void CodeMoveEvent(Address from, Address to) { + address_to_name_map_.Move(from, to); + } + + void CodeDeleteEvent(Address from) { + address_to_name_map_.Remove(from); + } + + const char* Lookup(Address address) { + return address_to_name_map_.Lookup(address); + } + + private: + class NameMap { + public: + NameMap() : impl_(&PointerEquals) {} + + ~NameMap() { + for (HashMap::Entry* p = impl_.Start(); p != NULL; p = impl_.Next(p)) { + DeleteArray(static_cast(p->value)); + } + } + + void Insert(Address code_address, const char* name, int name_size) { + HashMap::Entry* entry = FindOrCreateEntry(code_address); + if (entry->value == NULL) { + entry->value = CopyName(name, name_size); + } + } + + const char* Lookup(Address code_address) { + HashMap::Entry* entry = FindEntry(code_address); + return (entry != NULL) ? static_cast(entry->value) : NULL; + } + + void Remove(Address code_address) { + HashMap::Entry* entry = FindEntry(code_address); + if (entry != NULL) { + DeleteArray(static_cast(entry->value)); + RemoveEntry(entry); + } + } + + void Move(Address from, Address to) { + if (from == to) return; + HashMap::Entry* from_entry = FindEntry(from); + ASSERT(from_entry != NULL); + void* value = from_entry->value; + RemoveEntry(from_entry); + HashMap::Entry* to_entry = FindOrCreateEntry(to); + ASSERT(to_entry->value == NULL); + to_entry->value = value; + } + + private: + static bool PointerEquals(void* lhs, void* rhs) { + return lhs == rhs; + } + + static char* CopyName(const char* name, int name_size) { + char* result = NewArray(name_size + 1); + for (int i = 0; i < name_size; ++i) { + char c = name[i]; + if (c == '\0') c = ' '; + result[i] = c; + } + result[name_size] = '\0'; + return result; + } + + HashMap::Entry* FindOrCreateEntry(Address code_address) { + return impl_.Lookup(code_address, ComputePointerHash(code_address), true); + } + + HashMap::Entry* FindEntry(Address code_address) { + return impl_.Lookup(code_address, + ComputePointerHash(code_address), + false); + } + + void RemoveEntry(HashMap::Entry* entry) { + impl_.Remove(entry->key, entry->hash); + } + + HashMap impl_; + + DISALLOW_COPY_AND_ASSIGN(NameMap); + }; + + virtual void LogRecordedBuffer(Code* code, + SharedFunctionInfo*, + NameBuffer* name_buffer) { + address_to_name_map_.Insert(code->address(), + name_buffer->get(), + name_buffer->size()); + } + + NameMap address_to_name_map_; +}; + + +#define CODE_ADDRESS_MAP_LOG(Call)\ + if (Serializer::enabled()) code_address_map_->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. @@ -291,152 +541,6 @@ void Profiler::Run() { // Logger class implementation. // -class Logger::NameMap { - public: - NameMap() : impl_(&PointerEquals) {} - - ~NameMap() { - for (HashMap::Entry* p = impl_.Start(); p != NULL; p = impl_.Next(p)) { - DeleteArray(static_cast(p->value)); - } - } - - void Insert(Address code_address, const char* name, int name_size) { - HashMap::Entry* entry = FindOrCreateEntry(code_address); - if (entry->value == NULL) { - entry->value = CopyName(name, name_size); - } - } - - const char* Lookup(Address code_address) { - HashMap::Entry* entry = FindEntry(code_address); - return (entry != NULL) ? static_cast(entry->value) : NULL; - } - - void Remove(Address code_address) { - HashMap::Entry* entry = FindEntry(code_address); - if (entry != NULL) { - DeleteArray(static_cast(entry->value)); - RemoveEntry(entry); - } - } - - void Move(Address from, Address to) { - if (from == to) return; - HashMap::Entry* from_entry = FindEntry(from); - ASSERT(from_entry != NULL); - void* value = from_entry->value; - RemoveEntry(from_entry); - HashMap::Entry* to_entry = FindOrCreateEntry(to); - ASSERT(to_entry->value == NULL); - to_entry->value = value; - } - - private: - static bool PointerEquals(void* lhs, void* rhs) { - return lhs == rhs; - } - - static char* CopyName(const char* name, int name_size) { - char* result = NewArray(name_size + 1); - for (int i = 0; i < name_size; ++i) { - char c = name[i]; - if (c == '\0') c = ' '; - result[i] = c; - } - result[name_size] = '\0'; - return result; - } - - HashMap::Entry* FindOrCreateEntry(Address code_address) { - return impl_.Lookup(code_address, ComputePointerHash(code_address), true); - } - - HashMap::Entry* FindEntry(Address code_address) { - return impl_.Lookup(code_address, ComputePointerHash(code_address), false); - } - - void RemoveEntry(HashMap::Entry* entry) { - impl_.Remove(entry->key, entry->hash); - } - - HashMap impl_; - - DISALLOW_COPY_AND_ASSIGN(NameMap); -}; - - -class Logger::NameBuffer { - public: - NameBuffer() { Reset(); } - - void Reset() { - utf8_pos_ = 0; - } - - void AppendString(String* str) { - if (str == NULL) return; - int uc16_length = Min(str->length(), kUtf16BufferSize); - String::WriteToFlat(str, utf16_buffer, 0, uc16_length); - int previous = unibrow::Utf16::kNoPreviousCharacter; - for (int i = 0; i < uc16_length && utf8_pos_ < kUtf8BufferSize; ++i) { - uc16 c = utf16_buffer[i]; - if (c <= unibrow::Utf8::kMaxOneByteChar) { - utf8_buffer_[utf8_pos_++] = static_cast(c); - } else { - int char_length = unibrow::Utf8::Length(c, previous); - if (utf8_pos_ + char_length > kUtf8BufferSize) break; - unibrow::Utf8::Encode(utf8_buffer_ + utf8_pos_, c, previous); - utf8_pos_ += char_length; - } - previous = c; - } - } - - void AppendBytes(const char* bytes, int size) { - size = Min(size, kUtf8BufferSize - utf8_pos_); - OS::MemCopy(utf8_buffer_ + utf8_pos_, bytes, size); - utf8_pos_ += size; - } - - void AppendBytes(const char* bytes) { - AppendBytes(bytes, StrLength(bytes)); - } - - void AppendByte(char c) { - if (utf8_pos_ >= kUtf8BufferSize) return; - utf8_buffer_[utf8_pos_++] = c; - } - - void AppendInt(int n) { - Vector buffer(utf8_buffer_ + utf8_pos_, kUtf8BufferSize - utf8_pos_); - int size = OS::SNPrintF(buffer, "%d", n); - if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) { - utf8_pos_ += size; - } - } - - void AppendHex(uint32_t n) { - Vector buffer(utf8_buffer_ + utf8_pos_, kUtf8BufferSize - utf8_pos_); - int size = OS::SNPrintF(buffer, "%x", n); - if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) { - utf8_pos_ += size; - } - } - - const char* get() { return utf8_buffer_; } - int size() const { return utf8_pos_; } - - private: - static const int kUtf8BufferSize = 512; - static const int kUtf16BufferSize = 128; - - int utf8_pos_; - char utf8_buffer_[kUtf8BufferSize]; - uc16 utf16_buffer[kUtf16BufferSize]; -}; - - Logger::Logger(Isolate* isolate) : isolate_(isolate), ticker_(NULL), @@ -447,8 +551,7 @@ Logger::Logger(Isolate* isolate) log_(new Log(this)), ll_logger_(NULL), jit_logger_(NULL), - name_buffer_(new NameBuffer), - address_to_name_map_(NULL), + code_address_map_(new CodeAddressMap), is_initialized_(false), last_address_(NULL), prev_sp_(NULL), @@ -460,21 +563,18 @@ Logger::Logger(Isolate* isolate) Logger::~Logger() { - delete address_to_name_map_; - delete name_buffer_; + delete code_address_map_; delete log_; } -class JitLogger { +class JitLogger : public CodeEventLogger { public: explicit JitLogger(JitCodeEventHandler code_event_handler); - void CodeCreateEvent(Code* code, Script* script, - const char* name, size_t name_len); void CodeMovedEvent(Address from, Address to); - void CodeRemovedEvent(Address from); - void AddCodeLinePosInfoEvent( + void CodeDeleteEvent(Address from); + void AddCodeLinePosInfoEvent( void* jit_handler_data, int pc_offset, int position, @@ -483,6 +583,10 @@ class JitLogger { void EndCodePosInfoEvent(Code* code, void* jit_handler_data); private: + virtual void LogRecordedBuffer(Code* code, + SharedFunctionInfo* shared, + CodeEventLogger::NameBuffer* name_buffer); + JitCodeEventHandler code_event_handler_; }; @@ -494,21 +598,21 @@ JitLogger::JitLogger(JitCodeEventHandler code_event_handler) } -void JitLogger::CodeCreateEvent(Code* code, - Script* script, - const char* name, - size_t name_len) { +void JitLogger::LogRecordedBuffer(Code* code, + SharedFunctionInfo* shared, + CodeEventLogger::NameBuffer* name_buffer) { JitCodeEvent event; memset(&event, 0, sizeof(event)); event.type = JitCodeEvent::CODE_ADDED; event.code_start = code->instruction_start(); event.code_len = code->instruction_size(); - Handle