| 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
|
|
|