Logger: introduce abstract interface for CodeEvent listeners.
New abstract class CodeEventListener was created. CodeEventLogger which is the base class for Jit, LowLevel and CodeAddressMap loggers was inherited from CodeEventListener. CodeAddressMap class was moved to serializer.cc because serializer is the only user for it. Actually it collects code names and pushes them to the standard log as SnapshotCodeNameEvent. So I extracted this code into separate function CodeNameEvent. It happens that this method works only when Serializer serializes an object. So I added direct log call there. CodeEventLogger class declaration was moved to the header because CodeAddressMap needs it. The code for the nested class CodeEventLogger::NameBuffer was left in the cc file. CpuProfiler now is inherit CodeEventListener but not used the loggers infrastructure yet due to the complex initialization schema. I'd like to fix that in a separate cl. BUG=none TEST=current test set. R=yangguo@chromium.org, yurys@chromium.org Review URL: https://codereview.chromium.org/19724007 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15911 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
7471ae893e
commit
141ada02f2
@ -184,7 +184,7 @@ class ProfilerEventsProcessor : public Thread {
|
||||
} while (false)
|
||||
|
||||
|
||||
class CpuProfiler {
|
||||
class CpuProfiler : public CodeEventListener {
|
||||
public:
|
||||
explicit CpuProfiler(Isolate* isolate);
|
||||
|
||||
@ -193,7 +193,7 @@ class CpuProfiler {
|
||||
ProfileGenerator* test_generator,
|
||||
ProfilerEventsProcessor* test_processor);
|
||||
|
||||
~CpuProfiler();
|
||||
virtual ~CpuProfiler();
|
||||
|
||||
void StartProfiling(const char* title, bool record_samples = false);
|
||||
void StartProfiling(String* title, bool record_samples);
|
||||
@ -209,30 +209,30 @@ class CpuProfiler {
|
||||
|
||||
// Must be called via PROFILE macro, otherwise will crash when
|
||||
// profiling is not enabled.
|
||||
void CallbackEvent(Name* name, Address entry_point);
|
||||
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,
|
||||
SharedFunctionInfo* shared,
|
||||
CompilationInfo* info,
|
||||
Name* name);
|
||||
void CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
SharedFunctionInfo* shared,
|
||||
CompilationInfo* info,
|
||||
Name* source, int line);
|
||||
void CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code, int args_count);
|
||||
void CodeMovingGCEvent() {}
|
||||
void CodeMoveEvent(Address from, Address to);
|
||||
void CodeDeleteEvent(Address from);
|
||||
void GetterCallbackEvent(Name* name, Address entry_point);
|
||||
void RegExpCodeCreateEvent(Code* code, String* source);
|
||||
void SetterCallbackEvent(Name* name, Address entry_point);
|
||||
void SharedFunctionInfoMoveEvent(Address from, Address to);
|
||||
virtual void CallbackEvent(Name* name, Address entry_point);
|
||||
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code, const char* comment);
|
||||
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code, Name* name);
|
||||
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
SharedFunctionInfo* shared,
|
||||
CompilationInfo* info,
|
||||
Name* name);
|
||||
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
SharedFunctionInfo* shared,
|
||||
CompilationInfo* info,
|
||||
Name* source, int line);
|
||||
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code, int args_count);
|
||||
virtual void CodeMovingGCEvent() {}
|
||||
virtual void CodeMoveEvent(Address from, Address to);
|
||||
virtual void CodeDeleteEvent(Address from);
|
||||
virtual void GetterCallbackEvent(Name* name, Address entry_point);
|
||||
virtual void RegExpCodeCreateEvent(Code* code, String* source);
|
||||
virtual void SetterCallbackEvent(Name* name, Address entry_point);
|
||||
virtual void SharedFunctionInfoMoveEvent(Address from, Address to);
|
||||
|
||||
INLINE(bool is_profiling() const) { return is_profiling_; }
|
||||
bool* is_profiling_address() {
|
||||
|
503
src/log.cc
503
src/log.cc
@ -54,6 +54,11 @@ static const char* const kLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = {
|
||||
#undef DECLARE_EVENT
|
||||
|
||||
|
||||
#define CALL_LISTENERS(Call) \
|
||||
for (int i = 0; i < listeners_.length(); ++i) { \
|
||||
listeners_[i]->Call; \
|
||||
}
|
||||
|
||||
#define PROFILER_LOG(Call) \
|
||||
do { \
|
||||
CpuProfiler* cpu_profiler = isolate_->cpu_profiler(); \
|
||||
@ -72,220 +77,193 @@ static const char* ComputeMarker(Code* code) {
|
||||
}
|
||||
|
||||
|
||||
class CodeEventLogger {
|
||||
class CodeEventLogger::NameBuffer {
|
||||
public:
|
||||
virtual ~CodeEventLogger() { }
|
||||
NameBuffer() { Reset(); }
|
||||
|
||||
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);
|
||||
void Reset() {
|
||||
utf8_pos_ = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
class NameBuffer {
|
||||
public:
|
||||
NameBuffer() { Reset(); }
|
||||
void Init(Logger::LogEventsAndTags tag) {
|
||||
Reset();
|
||||
AppendBytes(kLogEventsNames[tag]);
|
||||
AppendByte(':');
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
utf8_pos_ = 0;
|
||||
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 Init(Logger::LogEventsAndTags tag) {
|
||||
Reset();
|
||||
AppendBytes(kLogEventsNames[tag]);
|
||||
AppendByte(':');
|
||||
}
|
||||
|
||||
void AppendName(Name* name) {
|
||||
if (name->IsString()) {
|
||||
AppendString(String::cast(name));
|
||||
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<char>(c);
|
||||
} 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(')');
|
||||
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 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<char>(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, int size) {
|
||||
size = Min(size, kUtf8BufferSize - utf8_pos_);
|
||||
OS::MemCopy(utf8_buffer_ + utf8_pos_, bytes, 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<char> 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 AppendBytes(const char* bytes) {
|
||||
AppendBytes(bytes, StrLength(bytes));
|
||||
void AppendHex(uint32_t n) {
|
||||
Vector<char> 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;
|
||||
}
|
||||
}
|
||||
|
||||
void AppendByte(char c) {
|
||||
if (utf8_pos_ >= kUtf8BufferSize) return;
|
||||
utf8_buffer_[utf8_pos_++] = c;
|
||||
}
|
||||
|
||||
void AppendInt(int n) {
|
||||
Vector<char> 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<char> 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];
|
||||
};
|
||||
const char* get() { return utf8_buffer_; }
|
||||
int size() const { return utf8_pos_; }
|
||||
|
||||
private:
|
||||
virtual void LogRecordedBuffer(Code* code,
|
||||
SharedFunctionInfo* shared,
|
||||
NameBuffer* name_buffer) = 0;
|
||||
static const int kUtf8BufferSize = 512;
|
||||
static const int kUtf16BufferSize = 128;
|
||||
|
||||
NameBuffer name_buffer_;
|
||||
int utf8_pos_;
|
||||
char utf8_buffer_[kUtf8BufferSize];
|
||||
uc16 utf16_buffer[kUtf16BufferSize];
|
||||
};
|
||||
|
||||
|
||||
CodeEventLogger::CodeEventLogger() : name_buffer_(new NameBuffer) { }
|
||||
|
||||
CodeEventLogger::~CodeEventLogger() { delete name_buffer_; }
|
||||
|
||||
|
||||
void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
const char* comment) {
|
||||
name_buffer_.Init(tag);
|
||||
name_buffer_.AppendBytes(comment);
|
||||
LogRecordedBuffer(code, NULL, &name_buffer_);
|
||||
name_buffer_->Init(tag);
|
||||
name_buffer_->AppendBytes(comment);
|
||||
LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
|
||||
}
|
||||
|
||||
|
||||
void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
Name* name) {
|
||||
name_buffer_.Init(tag);
|
||||
name_buffer_.AppendName(name);
|
||||
LogRecordedBuffer(code, NULL, &name_buffer_);
|
||||
name_buffer_->Init(tag);
|
||||
name_buffer_->AppendName(name);
|
||||
LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
|
||||
}
|
||||
|
||||
|
||||
void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
SharedFunctionInfo* shared,
|
||||
CompilationInfo* info,
|
||||
Name* name) {
|
||||
name_buffer_.Init(tag);
|
||||
name_buffer_.AppendBytes(ComputeMarker(code));
|
||||
name_buffer_.AppendName(name);
|
||||
LogRecordedBuffer(code, shared, &name_buffer_);
|
||||
Code* code,
|
||||
SharedFunctionInfo* shared,
|
||||
CompilationInfo* info,
|
||||
Name* name) {
|
||||
name_buffer_->Init(tag);
|
||||
name_buffer_->AppendBytes(ComputeMarker(code));
|
||||
name_buffer_->AppendName(name);
|
||||
LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
|
||||
}
|
||||
|
||||
|
||||
void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
SharedFunctionInfo* shared,
|
||||
CompilationInfo* info,
|
||||
Name* source, int line) {
|
||||
name_buffer_.Init(tag);
|
||||
name_buffer_.AppendBytes(ComputeMarker(code));
|
||||
name_buffer_.AppendString(shared->DebugName());
|
||||
name_buffer_.AppendByte(' ');
|
||||
Code* code,
|
||||
SharedFunctionInfo* shared,
|
||||
CompilationInfo* info,
|
||||
Name* source, int line) {
|
||||
name_buffer_->Init(tag);
|
||||
name_buffer_->AppendBytes(ComputeMarker(code));
|
||||
name_buffer_->AppendString(shared->DebugName());
|
||||
name_buffer_->AppendByte(' ');
|
||||
if (source->IsString()) {
|
||||
name_buffer_.AppendString(String::cast(source));
|
||||
name_buffer_->AppendString(String::cast(source));
|
||||
} else {
|
||||
name_buffer_.AppendBytes("symbol(hash ");
|
||||
name_buffer_.AppendHex(Name::cast(source)->Hash());
|
||||
name_buffer_.AppendByte(')');
|
||||
name_buffer_->AppendBytes("symbol(hash ");
|
||||
name_buffer_->AppendHex(Name::cast(source)->Hash());
|
||||
name_buffer_->AppendByte(')');
|
||||
}
|
||||
name_buffer_.AppendByte(':');
|
||||
name_buffer_.AppendInt(line);
|
||||
LogRecordedBuffer(code, shared, &name_buffer_);
|
||||
name_buffer_->AppendByte(':');
|
||||
name_buffer_->AppendInt(line);
|
||||
LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
|
||||
}
|
||||
|
||||
|
||||
void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
int args_count) {
|
||||
name_buffer_.Init(tag);
|
||||
name_buffer_.AppendInt(args_count);
|
||||
LogRecordedBuffer(code, NULL, &name_buffer_);
|
||||
name_buffer_->Init(tag);
|
||||
name_buffer_->AppendInt(args_count);
|
||||
LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
|
||||
}
|
||||
|
||||
|
||||
void CodeEventLogger::RegExpCodeCreateEvent(Code* code, String* source) {
|
||||
name_buffer_.Init(Logger::REG_EXP_TAG);
|
||||
name_buffer_.AppendString(source);
|
||||
LogRecordedBuffer(code, NULL, &name_buffer_);
|
||||
name_buffer_->Init(Logger::REG_EXP_TAG);
|
||||
name_buffer_->AppendString(source);
|
||||
LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
|
||||
}
|
||||
|
||||
|
||||
// Low-level logging support.
|
||||
#define LL_LOG(Call) if (ll_logger_) ll_logger_->Call;
|
||||
|
||||
class LowLevelLogger : public CodeEventLogger {
|
||||
public:
|
||||
explicit LowLevelLogger(const char* file_name);
|
||||
virtual ~LowLevelLogger();
|
||||
|
||||
void CodeMoveEvent(Address from, Address to);
|
||||
void CodeDeleteEvent(Address from);
|
||||
void SnapshotPositionEvent(Address addr, int pos);
|
||||
void CodeMovingGCEvent();
|
||||
virtual void CodeMoveEvent(Address from, Address to);
|
||||
virtual void CodeDeleteEvent(Address from);
|
||||
virtual void SnapshotPositionEvent(Address addr, int pos);
|
||||
virtual void CodeMovingGCEvent();
|
||||
|
||||
private:
|
||||
virtual void LogRecordedBuffer(Code* code,
|
||||
SharedFunctionInfo* shared,
|
||||
NameBuffer* name_buffer);
|
||||
const char* name,
|
||||
int length);
|
||||
|
||||
// Low-level profiling event structures.
|
||||
struct CodeCreateStruct {
|
||||
@ -383,14 +361,15 @@ void LowLevelLogger::LogCodeInfo() {
|
||||
|
||||
void LowLevelLogger::LogRecordedBuffer(Code* code,
|
||||
SharedFunctionInfo*,
|
||||
NameBuffer* name_buffer) {
|
||||
const char* name,
|
||||
int length) {
|
||||
CodeCreateStruct event;
|
||||
event.name_size = name_buffer->size();
|
||||
event.name_size = length;
|
||||
event.code_address = code->instruction_start();
|
||||
ASSERT(event.code_address == code->address() + Code::kHeaderSize);
|
||||
event.code_size = code->instruction_size();
|
||||
LogWriteStruct(event);
|
||||
LogWriteBytes(name_buffer->get(), name_buffer->size());
|
||||
LogWriteBytes(name, length);
|
||||
LogWriteBytes(
|
||||
reinterpret_cast<const char*>(code->instruction_start()),
|
||||
code->instruction_size());
|
||||
@ -434,143 +413,33 @@ void LowLevelLogger::CodeMovingGCEvent() {
|
||||
}
|
||||
|
||||
|
||||
#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<const char*>(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<const char*>(entry->value) : NULL;
|
||||
}
|
||||
|
||||
void Remove(Address code_address) {
|
||||
HashMap::Entry* entry = FindEntry(code_address);
|
||||
if (entry != NULL) {
|
||||
DeleteArray(static_cast<char*>(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<char>(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;
|
||||
#define JIT_LOG(Call) if (jit_logger_) jit_logger_->Call;
|
||||
|
||||
|
||||
class JitLogger : public CodeEventLogger {
|
||||
public:
|
||||
explicit JitLogger(JitCodeEventHandler code_event_handler);
|
||||
|
||||
void CodeMoveEvent(Address from, Address to);
|
||||
void CodeDeleteEvent(Address from);
|
||||
void AddCodeLinePosInfoEvent(
|
||||
virtual void CodeMoveEvent(Address from, Address to);
|
||||
virtual void CodeDeleteEvent(Address from);
|
||||
virtual void AddCodeLinePosInfoEvent(
|
||||
void* jit_handler_data,
|
||||
int pc_offset,
|
||||
int position,
|
||||
JitCodeEvent::PositionType position_type);
|
||||
|
||||
void* StartCodePosInfoEvent();
|
||||
void EndCodePosInfoEvent(Code* code, void* jit_handler_data);
|
||||
|
||||
private:
|
||||
virtual void LogRecordedBuffer(Code* code,
|
||||
SharedFunctionInfo* shared,
|
||||
CodeEventLogger::NameBuffer* name_buffer);
|
||||
const char* name,
|
||||
int length);
|
||||
|
||||
JitCodeEventHandler code_event_handler_;
|
||||
};
|
||||
|
||||
#define JIT_LOG(Call) if (jit_logger_) jit_logger_->Call;
|
||||
|
||||
|
||||
JitLogger::JitLogger(JitCodeEventHandler code_event_handler)
|
||||
: code_event_handler_(code_event_handler) {
|
||||
@ -579,7 +448,8 @@ JitLogger::JitLogger(JitCodeEventHandler code_event_handler)
|
||||
|
||||
void JitLogger::LogRecordedBuffer(Code* code,
|
||||
SharedFunctionInfo* shared,
|
||||
CodeEventLogger::NameBuffer* name_buffer) {
|
||||
const char* name,
|
||||
int length) {
|
||||
JitCodeEvent event;
|
||||
memset(&event, 0, sizeof(event));
|
||||
event.type = JitCodeEvent::CODE_ADDED;
|
||||
@ -590,8 +460,8 @@ void JitLogger::LogRecordedBuffer(Code* code,
|
||||
script_handle = Handle<Script>(Script::cast(shared->script()));
|
||||
}
|
||||
event.script = ToApiHandle<v8::Script>(script_handle);
|
||||
event.name.str = name_buffer->get();
|
||||
event.name.len = name_buffer->size();
|
||||
event.name.str = name;
|
||||
event.name.len = length;
|
||||
code_event_handler_(&event);
|
||||
}
|
||||
|
||||
@ -844,7 +714,7 @@ Logger::Logger(Isolate* isolate)
|
||||
log_(new Log(this)),
|
||||
ll_logger_(NULL),
|
||||
jit_logger_(NULL),
|
||||
code_address_map_(new CodeAddressMap),
|
||||
listeners_(5),
|
||||
is_initialized_(false),
|
||||
last_address_(NULL),
|
||||
prev_sp_(NULL),
|
||||
@ -856,11 +726,27 @@ Logger::Logger(Isolate* isolate)
|
||||
|
||||
|
||||
Logger::~Logger() {
|
||||
delete code_address_map_;
|
||||
delete log_;
|
||||
}
|
||||
|
||||
|
||||
void Logger::addCodeEventListener(CodeEventListener* listener) {
|
||||
ASSERT(!hasCodeEventListener(listener));
|
||||
listeners_.Add(listener);
|
||||
}
|
||||
|
||||
|
||||
void Logger::removeCodeEventListener(CodeEventListener* listener) {
|
||||
ASSERT(hasCodeEventListener(listener));
|
||||
listeners_.RemoveElement(listener);
|
||||
}
|
||||
|
||||
|
||||
bool Logger::hasCodeEventListener(CodeEventListener* listener) {
|
||||
return listeners_.Contains(listener);
|
||||
}
|
||||
|
||||
|
||||
void Logger::ProfilerBeginEvent() {
|
||||
if (!log_->IsEnabled()) return;
|
||||
Log::MessageBuilder msg(log_);
|
||||
@ -1279,9 +1165,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
|
||||
PROFILER_LOG(CodeCreateEvent(tag, code, comment));
|
||||
|
||||
if (!is_logging_code_events()) return;
|
||||
JIT_LOG(CodeCreateEvent(tag, code, comment));
|
||||
LL_LOG(CodeCreateEvent(tag, code, comment));
|
||||
CODE_ADDRESS_MAP_LOG(CodeCreateEvent(tag, code, comment));
|
||||
CALL_LISTENERS(CodeCreateEvent(tag, code, comment));
|
||||
|
||||
if (!FLAG_log_code || !log_->IsEnabled()) return;
|
||||
Log::MessageBuilder msg(log_);
|
||||
@ -1298,9 +1182,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
|
||||
PROFILER_LOG(CodeCreateEvent(tag, code, name));
|
||||
|
||||
if (!is_logging_code_events()) return;
|
||||
JIT_LOG(CodeCreateEvent(tag, code, name));
|
||||
LL_LOG(CodeCreateEvent(tag, code, name));
|
||||
CODE_ADDRESS_MAP_LOG(CodeCreateEvent(tag, code, name));
|
||||
CALL_LISTENERS(CodeCreateEvent(tag, code, name));
|
||||
|
||||
if (!FLAG_log_code || !log_->IsEnabled()) return;
|
||||
Log::MessageBuilder msg(log_);
|
||||
@ -1325,9 +1207,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
|
||||
PROFILER_LOG(CodeCreateEvent(tag, code, shared, info, name));
|
||||
|
||||
if (!is_logging_code_events()) return;
|
||||
JIT_LOG(CodeCreateEvent(tag, code, shared, info, name));
|
||||
LL_LOG(CodeCreateEvent(tag, code, shared, info, name));
|
||||
CODE_ADDRESS_MAP_LOG(CodeCreateEvent(tag, code, shared, info, name));
|
||||
CALL_LISTENERS(CodeCreateEvent(tag, code, shared, info, name));
|
||||
|
||||
if (!FLAG_log_code || !log_->IsEnabled()) return;
|
||||
if (code == isolate_->builtins()->builtin(
|
||||
@ -1362,9 +1242,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
|
||||
PROFILER_LOG(CodeCreateEvent(tag, code, shared, info, source, line));
|
||||
|
||||
if (!is_logging_code_events()) return;
|
||||
JIT_LOG(CodeCreateEvent(tag, code, shared, info, source, line));
|
||||
LL_LOG(CodeCreateEvent(tag, code, shared, info, source, line));
|
||||
CODE_ADDRESS_MAP_LOG(CodeCreateEvent(tag, code, shared, info, source, line));
|
||||
CALL_LISTENERS(CodeCreateEvent(tag, code, shared, info, source, line));
|
||||
|
||||
if (!FLAG_log_code || !log_->IsEnabled()) return;
|
||||
Log::MessageBuilder msg(log_);
|
||||
@ -1393,9 +1271,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
|
||||
PROFILER_LOG(CodeCreateEvent(tag, code, args_count));
|
||||
|
||||
if (!is_logging_code_events()) return;
|
||||
JIT_LOG(CodeCreateEvent(tag, code, args_count));
|
||||
LL_LOG(CodeCreateEvent(tag, code, args_count));
|
||||
CODE_ADDRESS_MAP_LOG(CodeCreateEvent(tag, code, args_count));
|
||||
CALL_LISTENERS(CodeCreateEvent(tag, code, args_count));
|
||||
|
||||
if (!FLAG_log_code || !log_->IsEnabled()) return;
|
||||
Log::MessageBuilder msg(log_);
|
||||
@ -1411,7 +1287,7 @@ void Logger::CodeMovingGCEvent() {
|
||||
|
||||
if (!is_logging_code_events()) return;
|
||||
if (!log_->IsEnabled() || !FLAG_ll_prof) return;
|
||||
LL_LOG(CodeMovingGCEvent());
|
||||
CALL_LISTENERS(CodeMovingGCEvent());
|
||||
OS::SignalCodeMovingGC();
|
||||
}
|
||||
|
||||
@ -1420,9 +1296,7 @@ void Logger::RegExpCodeCreateEvent(Code* code, String* source) {
|
||||
PROFILER_LOG(RegExpCodeCreateEvent(code, source));
|
||||
|
||||
if (!is_logging_code_events()) return;
|
||||
JIT_LOG(RegExpCodeCreateEvent(code, source));
|
||||
LL_LOG(RegExpCodeCreateEvent(code, source));
|
||||
CODE_ADDRESS_MAP_LOG(RegExpCodeCreateEvent(code, source));
|
||||
CALL_LISTENERS(RegExpCodeCreateEvent(code, source));
|
||||
|
||||
if (!FLAG_log_code || !log_->IsEnabled()) return;
|
||||
Log::MessageBuilder msg(log_);
|
||||
@ -1439,9 +1313,7 @@ void Logger::CodeMoveEvent(Address from, Address to) {
|
||||
PROFILER_LOG(CodeMoveEvent(from, to));
|
||||
|
||||
if (!is_logging_code_events()) return;
|
||||
JIT_LOG(CodeMoveEvent(from, to));
|
||||
LL_LOG(CodeMoveEvent(from, to));
|
||||
CODE_ADDRESS_MAP_LOG(CodeMoveEvent(from, to));
|
||||
CALL_LISTENERS(CodeMoveEvent(from, to));
|
||||
MoveEventInternal(CODE_MOVE_EVENT, from, to);
|
||||
}
|
||||
|
||||
@ -1450,9 +1322,7 @@ void Logger::CodeDeleteEvent(Address from) {
|
||||
PROFILER_LOG(CodeDeleteEvent(from));
|
||||
|
||||
if (!is_logging_code_events()) return;
|
||||
JIT_LOG(CodeDeleteEvent(from));
|
||||
LL_LOG(CodeDeleteEvent(from));
|
||||
CODE_ADDRESS_MAP_LOG(CodeDeleteEvent(from));
|
||||
CALL_LISTENERS(CodeDeleteEvent(from));
|
||||
|
||||
if (!FLAG_log_code || !log_->IsEnabled()) return;
|
||||
Log::MessageBuilder msg(log_);
|
||||
@ -1496,18 +1366,19 @@ void Logger::CodeEndLinePosInfoRecordEvent(Code* code,
|
||||
}
|
||||
|
||||
|
||||
void Logger::CodeNameEvent(Address addr, int pos, const char* code_name) {
|
||||
if (code_name == NULL) return; // Not a code object.
|
||||
Log::MessageBuilder msg(log_);
|
||||
msg.Append("%s,%d,", kLogEventsNames[SNAPSHOT_CODE_NAME_EVENT], pos);
|
||||
msg.AppendDoubleQuotedString(code_name);
|
||||
msg.Append("\n");
|
||||
msg.WriteToLogFile();
|
||||
}
|
||||
|
||||
|
||||
void Logger::SnapshotPositionEvent(Address addr, int pos) {
|
||||
if (!log_->IsEnabled()) return;
|
||||
LL_LOG(SnapshotPositionEvent(addr, pos));
|
||||
if (Serializer::enabled()) {
|
||||
const char* code_name = code_address_map_->Lookup(addr);
|
||||
if (code_name == NULL) return; // Not a code object.
|
||||
Log::MessageBuilder msg(log_);
|
||||
msg.Append("%s,%d,", kLogEventsNames[SNAPSHOT_CODE_NAME_EVENT], pos);
|
||||
msg.AppendDoubleQuotedString(code_name);
|
||||
msg.Append("\n");
|
||||
msg.WriteToLogFile();
|
||||
}
|
||||
if (!FLAG_log_snapshot_positions) return;
|
||||
Log::MessageBuilder msg(log_);
|
||||
msg.Append("%s,", kLogEventsNames[SNAPSHOT_POSITION_EVENT]);
|
||||
@ -2009,6 +1880,7 @@ bool Logger::SetUp(Isolate* isolate) {
|
||||
|
||||
if (FLAG_ll_prof) {
|
||||
ll_logger_ = new LowLevelLogger(*log_file_name);
|
||||
addCodeEventListener(ll_logger_);
|
||||
}
|
||||
|
||||
ticker_ = new Ticker(isolate, kSamplingIntervalMs);
|
||||
@ -2036,18 +1908,19 @@ bool Logger::SetUp(Isolate* isolate) {
|
||||
void Logger::SetCodeEventHandler(uint32_t options,
|
||||
JitCodeEventHandler event_handler) {
|
||||
if (jit_logger_) {
|
||||
removeCodeEventListener(jit_logger_);
|
||||
delete jit_logger_;
|
||||
jit_logger_ = NULL;
|
||||
}
|
||||
|
||||
if (event_handler) {
|
||||
jit_logger_ = new JitLogger(event_handler);
|
||||
}
|
||||
|
||||
if (jit_logger_ != NULL && (options & kJitCodeEventEnumExisting)) {
|
||||
HandleScope scope(isolate_);
|
||||
LogCodeObjects();
|
||||
LogCompiledFunctions();
|
||||
addCodeEventListener(jit_logger_);
|
||||
if (options & kJitCodeEventEnumExisting) {
|
||||
HandleScope scope(isolate_);
|
||||
LogCodeObjects();
|
||||
LogCompiledFunctions();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2072,11 +1945,13 @@ FILE* Logger::TearDown() {
|
||||
ticker_ = NULL;
|
||||
|
||||
if (ll_logger_) {
|
||||
removeCodeEventListener(ll_logger_);
|
||||
delete ll_logger_;
|
||||
ll_logger_ = NULL;
|
||||
}
|
||||
|
||||
if (jit_logger_) {
|
||||
removeCodeEventListener(jit_logger_);
|
||||
delete jit_logger_;
|
||||
jit_logger_ = NULL;
|
||||
}
|
||||
|
91
src/log.h
91
src/log.h
@ -70,7 +70,7 @@ namespace internal {
|
||||
// tick profiler requires code events, so --prof implies --log-code.
|
||||
|
||||
// Forward declarations.
|
||||
class CodeAddressMap;
|
||||
class CodeEventListener;
|
||||
class CompilationInfo;
|
||||
class CpuProfiler;
|
||||
class Isolate;
|
||||
@ -155,7 +155,6 @@ class JitLogger;
|
||||
class LowLevelLogger;
|
||||
class Sampler;
|
||||
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
#define DECLARE_ENUM(enum_item, ignore) enum_item,
|
||||
@ -226,6 +225,11 @@ class Logger {
|
||||
|
||||
|
||||
// ==== Events logged by --log-code. ====
|
||||
void addCodeEventListener(CodeEventListener* listener);
|
||||
void removeCodeEventListener(CodeEventListener* listener);
|
||||
bool hasCodeEventListener(CodeEventListener* listener);
|
||||
|
||||
|
||||
// Emits a code event for a callback function.
|
||||
void CallbackEvent(Name* name, Address entry_point);
|
||||
void GetterCallbackEvent(Name* name, Address entry_point);
|
||||
@ -269,6 +273,7 @@ class Logger {
|
||||
|
||||
void SharedFunctionInfoMoveEvent(Address from, Address to);
|
||||
|
||||
void CodeNameEvent(Address addr, int pos, const char* code_name);
|
||||
void SnapshotPositionEvent(Address addr, int pos);
|
||||
|
||||
// ==== Events logged by --log-gc. ====
|
||||
@ -439,7 +444,7 @@ class Logger {
|
||||
Log* log_;
|
||||
LowLevelLogger* ll_logger_;
|
||||
JitLogger* jit_logger_;
|
||||
CodeAddressMap* code_address_map_;
|
||||
List<CodeEventListener*> listeners_;
|
||||
|
||||
// Guards against multiple calls to TearDown() that can happen in some tests.
|
||||
// 'true' between SetUp() and TearDown().
|
||||
@ -462,6 +467,86 @@ class Logger {
|
||||
};
|
||||
|
||||
|
||||
class CodeEventListener {
|
||||
public:
|
||||
virtual ~CodeEventListener() {}
|
||||
|
||||
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
const char* comment) = 0;
|
||||
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
Name* name) = 0;
|
||||
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
SharedFunctionInfo* shared,
|
||||
CompilationInfo* info,
|
||||
Name* name) = 0;
|
||||
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
SharedFunctionInfo* shared,
|
||||
CompilationInfo* info,
|
||||
Name* source,
|
||||
int line) = 0;
|
||||
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
int args_count) = 0;
|
||||
virtual void CallbackEvent(Name* name, Address entry_point) = 0;
|
||||
virtual void GetterCallbackEvent(Name* name, Address entry_point) = 0;
|
||||
virtual void SetterCallbackEvent(Name* name, Address entry_point) = 0;
|
||||
virtual void RegExpCodeCreateEvent(Code* code, String* source) = 0;
|
||||
virtual void CodeMoveEvent(Address from, Address to) = 0;
|
||||
virtual void CodeDeleteEvent(Address from) = 0;
|
||||
virtual void SharedFunctionInfoMoveEvent(Address from, Address to) = 0;
|
||||
virtual void CodeMovingGCEvent() = 0;
|
||||
};
|
||||
|
||||
|
||||
class CodeEventLogger : public CodeEventListener {
|
||||
public:
|
||||
CodeEventLogger();
|
||||
virtual ~CodeEventLogger();
|
||||
|
||||
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
const char* comment);
|
||||
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
Name* name);
|
||||
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
int args_count);
|
||||
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
SharedFunctionInfo* shared,
|
||||
CompilationInfo* info,
|
||||
Name* name);
|
||||
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
|
||||
Code* code,
|
||||
SharedFunctionInfo* shared,
|
||||
CompilationInfo* info,
|
||||
Name* source,
|
||||
int line);
|
||||
virtual void RegExpCodeCreateEvent(Code* code, String* source);
|
||||
|
||||
virtual void CallbackEvent(Name* name, Address entry_point) { }
|
||||
virtual void GetterCallbackEvent(Name* name, Address entry_point) { }
|
||||
virtual void SetterCallbackEvent(Name* name, Address entry_point) { }
|
||||
virtual void SharedFunctionInfoMoveEvent(Address from, Address to) { }
|
||||
virtual void CodeMovingGCEvent() { }
|
||||
|
||||
private:
|
||||
class NameBuffer;
|
||||
|
||||
virtual void LogRecordedBuffer(Code* code,
|
||||
SharedFunctionInfo* shared,
|
||||
const char* name,
|
||||
int length) = 0;
|
||||
|
||||
NameBuffer* name_buffer_;
|
||||
};
|
||||
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
||||
|
||||
|
141
src/serialize.cc
141
src/serialize.cc
@ -665,6 +665,141 @@ bool Serializer::serialization_enabled_ = false;
|
||||
bool Serializer::too_late_to_enable_now_ = false;
|
||||
|
||||
|
||||
class CodeAddressMap: public CodeEventLogger {
|
||||
public:
|
||||
explicit CodeAddressMap(Isolate* isolate)
|
||||
: isolate_(isolate) {
|
||||
isolate->logger()->addCodeEventListener(this);
|
||||
}
|
||||
|
||||
virtual ~CodeAddressMap() {
|
||||
isolate_->logger()->removeCodeEventListener(this);
|
||||
}
|
||||
|
||||
virtual void CodeMoveEvent(Address from, Address to) {
|
||||
address_to_name_map_.Move(from, to);
|
||||
}
|
||||
|
||||
virtual 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<const char*>(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<const char*>(entry->value) : NULL;
|
||||
}
|
||||
|
||||
void Remove(Address code_address) {
|
||||
HashMap::Entry* entry = FindEntry(code_address);
|
||||
if (entry != NULL) {
|
||||
DeleteArray(static_cast<char*>(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<char>(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*,
|
||||
const char* name,
|
||||
int length) {
|
||||
address_to_name_map_.Insert(code->address(), name, length);
|
||||
}
|
||||
|
||||
NameMap address_to_name_map_;
|
||||
Isolate* isolate_;
|
||||
};
|
||||
|
||||
|
||||
CodeAddressMap* Serializer::code_address_map_ = NULL;
|
||||
|
||||
|
||||
void Serializer::Enable() {
|
||||
if (!serialization_enabled_) {
|
||||
ASSERT(!too_late_to_enable_now_);
|
||||
}
|
||||
if (serialization_enabled_) return;
|
||||
serialization_enabled_ = true;
|
||||
i::Isolate* isolate = Isolate::Current();
|
||||
isolate->InitializeLoggingAndCounters();
|
||||
code_address_map_ = new CodeAddressMap(isolate);
|
||||
}
|
||||
|
||||
|
||||
void Serializer::Disable() {
|
||||
if (!serialization_enabled_) return;
|
||||
serialization_enabled_ = false;
|
||||
delete code_address_map_;
|
||||
code_address_map_ = NULL;
|
||||
}
|
||||
|
||||
|
||||
Deserializer::Deserializer(SnapshotByteSource* source)
|
||||
: isolate_(NULL),
|
||||
source_(source),
|
||||
@ -1458,7 +1593,11 @@ void Serializer::ObjectSerializer::Serialize() {
|
||||
"ObjectSerialization");
|
||||
sink_->PutInt(size >> kObjectAlignmentBits, "Size in words");
|
||||
|
||||
LOG(i::Isolate::Current(),
|
||||
ASSERT(code_address_map_);
|
||||
const char* code_name = code_address_map_->Lookup(object_->address());
|
||||
LOG(serializer_->isolate_,
|
||||
CodeNameEvent(object_->address(), sink_->Position(), code_name));
|
||||
LOG(serializer_->isolate_,
|
||||
SnapshotPositionEvent(object_->address(), sink_->Position()));
|
||||
|
||||
// Mark this object as already serialized.
|
||||
|
@ -459,6 +459,8 @@ class SerializationAddressMapper {
|
||||
};
|
||||
|
||||
|
||||
class CodeAddressMap;
|
||||
|
||||
// There can be only one serializer per V8 process.
|
||||
class Serializer : public SerializerDeserializer {
|
||||
public:
|
||||
@ -472,14 +474,9 @@ class Serializer : public SerializerDeserializer {
|
||||
return fullness_[space];
|
||||
}
|
||||
|
||||
static void Enable() {
|
||||
if (!serialization_enabled_) {
|
||||
ASSERT(!too_late_to_enable_now_);
|
||||
}
|
||||
serialization_enabled_ = true;
|
||||
}
|
||||
static void Enable();
|
||||
static void Disable();
|
||||
|
||||
static void Disable() { serialization_enabled_ = false; }
|
||||
// Call this when you have made use of the fact that there is no serialization
|
||||
// going on.
|
||||
static void TooLateToEnableNow() { too_late_to_enable_now_ = true; }
|
||||
@ -589,6 +586,7 @@ class Serializer : public SerializerDeserializer {
|
||||
friend class Deserializer;
|
||||
|
||||
private:
|
||||
static CodeAddressMap* code_address_map_;
|
||||
DISALLOW_COPY_AND_ASSIGN(Serializer);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user