Index: src/log.cc |
diff --git a/src/log.cc b/src/log.cc |
index d93a9d82b117022e629f9f84530578e15efed611..1214907708e36e127800ff1f7e8fd614c0dbdb34 100644 |
--- a/src/log.cc |
+++ b/src/log.cc |
@@ -530,7 +530,8 @@ Logger::Logger() |
prev_sp_(NULL), |
prev_function_(NULL), |
prev_to_(NULL), |
- prev_code_(NULL) { |
+ prev_code_(NULL), |
+ notified_reset_(0) { |
} |
@@ -940,7 +941,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, |
Code* code, |
SharedFunctionInfo* shared, |
String* name) { |
- if (!log_->IsEnabled()) return; |
+ if (!log_->IsEnabled() && !CodeAddressNotification::IsEnabled()) return; |
if (FLAG_ll_prof || Serializer::enabled()) { |
name_buffer_->Reset(); |
name_buffer_->AppendBytes(kLogEventsNames[tag]); |
@@ -954,6 +955,19 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, |
if (Serializer::enabled()) { |
RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size()); |
} |
+ if (CodeAddressNotification::IsEnabled()) { |
+ name_buffer_->Reset(); |
+ name_buffer_->AppendString(name); |
+ name_buffer_->AppendByte('\0'); |
+ CodeAddressNotification::WriteSymbolMap(this, |
+ Add, |
+ code->instruction_start(), |
+ code->instruction_size(), |
+ name_buffer_->get(), |
+ tag, |
+ shared->script(), |
+ 0); |
+ } |
if (!FLAG_log_code) return; |
if (code == Isolate::Current()->builtins()->builtin( |
Builtins::kLazyCompile)) |
@@ -981,7 +995,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, |
Code* code, |
SharedFunctionInfo* shared, |
String* source, int line) { |
- if (!log_->IsEnabled()) return; |
+ if (!log_->IsEnabled() && !CodeAddressNotification::IsEnabled()) return; |
if (FLAG_ll_prof || Serializer::enabled()) { |
name_buffer_->Reset(); |
name_buffer_->AppendBytes(kLogEventsNames[tag]); |
@@ -999,6 +1013,19 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, |
if (Serializer::enabled()) { |
RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size()); |
} |
+ if (CodeAddressNotification::IsEnabled()) { |
+ name_buffer_->Reset(); |
+ name_buffer_->AppendString(shared->DebugName()); |
+ name_buffer_->AppendByte('\0'); |
+ CodeAddressNotification::WriteSymbolMap(this, |
+ Add, |
+ code->instruction_start(), |
+ code->instruction_size(), |
+ name_buffer_->get(), |
+ tag, |
+ shared->script(), |
+ line); |
+ } |
if (!FLAG_log_code) return; |
LogMessageBuilder msg(this); |
SmartArrayPointer<char> name = |
@@ -1055,7 +1082,7 @@ void Logger::CodeMovingGCEvent() { |
void Logger::RegExpCodeCreateEvent(Code* code, String* source) { |
- if (!log_->IsEnabled()) return; |
+ if (!log_->IsEnabled() && !CodeAddressNotification::IsEnabled()) return; |
if (FLAG_ll_prof || Serializer::enabled()) { |
name_buffer_->Reset(); |
name_buffer_->AppendBytes(kLogEventsNames[REG_EXP_TAG]); |
@@ -1068,6 +1095,21 @@ void Logger::RegExpCodeCreateEvent(Code* code, String* source) { |
if (Serializer::enabled()) { |
RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size()); |
} |
+ if (CodeAddressNotification::IsEnabled()) { |
+ name_buffer_->Reset(); |
+ name_buffer_->AppendBytes(kLogEventsNames[REG_EXP_TAG]); |
+ name_buffer_->AppendByte(':'); |
+ name_buffer_->AppendString(source); |
+ name_buffer_->AppendByte('\0'); |
+ CodeAddressNotification::WriteSymbolMap(this, |
+ Add, |
+ code->instruction_start(), |
+ code->instruction_size(), |
+ name_buffer_->get(), |
+ REG_EXP_TAG, |
+ NULL, |
+ 0); |
+ } |
if (!FLAG_log_code) return; |
LogMessageBuilder msg(this); |
msg.Append("%s,%s,", |
@@ -1083,21 +1125,41 @@ void Logger::RegExpCodeCreateEvent(Code* code, String* source) { |
void Logger::CodeMoveEvent(Address from, Address to) { |
- if (!log_->IsEnabled()) return; |
+ if (!log_->IsEnabled() && !CodeAddressNotification::IsEnabled()) return; |
if (FLAG_ll_prof) LowLevelCodeMoveEvent(from, to); |
if (Serializer::enabled() && address_to_name_map_ != NULL) { |
address_to_name_map_->Move(from, to); |
} |
+ if (CodeAddressNotification::IsEnabled()) { |
+ CodeAddressNotification::WriteSymbolMap(this, |
+ Move, |
+ from, |
+ 0, |
+ NULL, |
+ CODE_MOVE_EVENT, |
+ to, |
+ 0); |
+ } |
MoveEventInternal(CODE_MOVE_EVENT, from, to); |
} |
void Logger::CodeDeleteEvent(Address from) { |
- if (!log_->IsEnabled()) return; |
+ if (!log_->IsEnabled() && !CodeAddressNotification::IsEnabled()) return; |
if (FLAG_ll_prof) LowLevelCodeDeleteEvent(from); |
if (Serializer::enabled() && address_to_name_map_ != NULL) { |
address_to_name_map_->Remove(from); |
} |
+ if (CodeAddressNotification::IsEnabled()) { |
+ CodeAddressNotification::WriteSymbolMap(this, |
+ Remove, |
+ from, |
+ 0, |
+ NULL, |
+ CODE_DELETE_EVENT, |
+ NULL, |
+ 0); |
+ } |
DeleteEventInternal(CODE_DELETE_EVENT, from); |
} |
@@ -1325,6 +1387,12 @@ bool Logger::IsProfilerSamplerActive() { |
} |
+// This returns true if API callback for symbol address is enabled. |
+bool Logger::CodeAddressCallbackEnabled() { |
+ return CodeAddressNotification::IsEnabled(); |
+} |
+ |
+ |
class EnumerateOptimizedFunctionsVisitor: public OptimizedFunctionVisitor { |
public: |
EnumerateOptimizedFunctionsVisitor(Handle<SharedFunctionInfo>* sfis, |
@@ -1789,4 +1857,79 @@ void SamplerRegistry::RemoveActiveSampler(Sampler* sampler) { |
USE(removed); |
} |
+ |
+// External code address mapping notifications. |
+ |
+// Counter to indicate that enumeration of compiled functions is required. |
+// Incremented each time notification enabled and enumeration requested. |
+// Callback setting is not isolated. Set global and check from each logger. |
+volatile Atomic32 NeedReset = 0; |
+Atomic32 EnumIncr = 1; |
+// The current callback (only one) |
+volatile AtomicWord ExtCallback = NULL; |
+ |
+// Called by host to set callbacks - null turns off callbacks. |
+// Callback may still be called after it is turned off. The caller must |
+// close the isolate before unloading the callback code. |
+void CodeAddressNotification::SetCodeAddressEventCallback(CodeAddressEvent cb, |
+ bool enumExisting) { |
+ AtomicWord newcb = (AtomicWord)cb; |
+ AtomicWord old = NoBarrier_AtomicExchange(&ExtCallback, newcb); |
+ |
+ if (cb != NULL && enumExisting) { |
+ NoBarrier_AtomicIncrement(&NeedReset, EnumIncr); |
+ } |
+} |
+ |
+ |
+// Called by v8 when a symbol map is created or changed. |
+void CodeAddressNotification::WriteSymbolMap(Logger* logger, |
+ CodeAddressOperation op, |
+ const void* addr1, |
+ int len, |
+ const char* symbol, |
+ Logger::LogEventsAndTags tag, |
+ const void* addr2, |
+ int line) { |
+ CodeAddressEvent cb = (CodeAddressEvent)ExtCallback; |
+ if (cb != NULL) { |
+ if (logger->notified_reset_ < NeedReset) { |
+ // Enumeration needed. Log a reset, then log existing functions. |
+ logger->notified_reset_ = NeedReset; |
+ cb(CodeAddressOperation::Reset, |
+ NULL, |
+ 0, |
+ "", |
+ Logger::CODE_CREATION_EVENT, |
+ NULL, |
+ 0); |
+ logger->LogCompiledFunctions(); |
+ } |
+ |
+ if (op == Add) { |
+ switch (tag) { |
+ case Logger::SCRIPT_TAG: |
+ case Logger::NATIVE_SCRIPT_TAG: |
+ op = Source; |
+ break; |
+ case Logger::FUNCTION_TAG: |
+ case Logger::LAZY_COMPILE_TAG: |
+ case Logger::NATIVE_FUNCTION_TAG: |
+ case Logger::NATIVE_LAZY_COMPILE_TAG: |
+ case Logger::REG_EXP_TAG: |
+ break; |
+ default: |
+ return; |
+ } |
+ } |
+ cb(op, addr1, len, symbol, static_cast<int>(tag), addr2, line); |
+ } |
+} |
+ |
+ |
+// Called by v8 to determine if callbacks are enabled. |
+bool CodeAddressNotification::IsEnabled() { |
+ return ExtCallback != NULL; |
+} |
+ |
} } // namespace v8::internal |