Index: src/log.cc |
=================================================================== |
--- src/log.cc (revision 7267) |
+++ src/log.cc (working copy) |
@@ -64,12 +64,12 @@ |
void IncrementStateCounter(StateTag state) { |
- Counters::state_counters[state].Increment(); |
+ COUNTERS->state_counters(state)->Increment(); |
} |
void DecrementStateCounter(StateTag state) { |
- Counters::state_counters[state].Decrement(); |
+ COUNTERS->state_counters(state)->Decrement(); |
} |
}; |
@@ -82,7 +82,7 @@ |
// |
class Profiler: public Thread { |
public: |
- Profiler(); |
+ explicit Profiler(Isolate* isolate); |
void Engage(); |
void Disengage(); |
@@ -113,9 +113,9 @@ |
void Run(); |
// Pause and Resume TickSample data collection. |
- static bool paused() { return paused_; } |
- static void pause() { paused_ = true; } |
- static void resume() { paused_ = false; } |
+ bool paused() const { return paused_; } |
+ void pause() { paused_ = true; } |
+ void resume() { paused_ = false; } |
private: |
// Returns the next index in the cyclic buffer. |
@@ -137,23 +137,24 @@ |
bool running_; |
// Tells whether we are currently recording tick samples. |
- static bool paused_; |
+ bool paused_; |
}; |
-bool Profiler::paused_ = false; |
- |
// |
// StackTracer implementation |
// |
-void StackTracer::Trace(TickSample* sample) { |
+void StackTracer::Trace(Isolate* isolate, TickSample* sample) { |
+ ASSERT(isolate->IsInitialized()); |
+ |
sample->tos = NULL; |
sample->frames_count = 0; |
// Avoid collecting traces while doing GC. |
if (sample->state == GC) return; |
- const Address js_entry_sp = Top::js_entry_sp(Top::GetCurrentThread()); |
+ const Address js_entry_sp = |
+ Isolate::js_entry_sp(isolate->thread_local_top()); |
if (js_entry_sp == 0) { |
// Not executing JS now. |
return; |
@@ -164,7 +165,7 @@ |
sample->tos = Memory::Address_at(sample->sp); |
int i = 0; |
- const Address callback = Top::external_callback(); |
+ const Address callback = isolate->external_callback(); |
// Surprisingly, PC can point _exactly_ to callback start, with good |
// probability, and this will result in reporting fake nested |
// callback call. |
@@ -172,7 +173,8 @@ |
sample->stack[i++] = callback; |
} |
- SafeStackTraceFrameIterator it(sample->fp, sample->sp, |
+ SafeStackTraceFrameIterator it(isolate, |
+ sample->fp, sample->sp, |
sample->sp, js_entry_sp); |
while (!it.done() && i < TickSample::kMaxFramesCount) { |
sample->stack[i++] = it.frame()->pc(); |
@@ -188,8 +190,8 @@ |
// |
class Ticker: public Sampler { |
public: |
- explicit Ticker(int interval) : |
- Sampler(interval), |
+ explicit Ticker(Isolate* isolate, int interval): |
+ Sampler(isolate, interval), |
window_(NULL), |
profiler_(NULL) {} |
@@ -225,7 +227,7 @@ |
protected: |
virtual void DoSampleStack(TickSample* sample) { |
- StackTracer::Trace(sample); |
+ StackTracer::Trace(isolate(), sample); |
} |
private: |
@@ -241,12 +243,12 @@ |
for (int i = 0; i < kBufferSize; i++) { |
buffer_[i] = static_cast<byte>(OTHER); |
} |
- Logger::ticker_->SetWindow(this); |
+ LOGGER->ticker_->SetWindow(this); |
} |
SlidingStateWindow::~SlidingStateWindow() { |
- Logger::ticker_->ClearWindow(); |
+ LOGGER->ticker_->ClearWindow(); |
} |
@@ -266,14 +268,15 @@ |
// |
// Profiler implementation. |
// |
-Profiler::Profiler() |
- : Thread("v8:Profiler"), |
+Profiler::Profiler(Isolate* isolate) |
+ : Thread(isolate, "v8:Profiler"), |
head_(0), |
tail_(0), |
overflow_(false), |
buffer_semaphore_(OS::CreateSemaphore(0)), |
engaged_(false), |
- running_(false) { |
+ running_(false), |
+ paused_(false) { |
} |
@@ -292,9 +295,9 @@ |
Start(); |
// Register to get ticks. |
- Logger::ticker_->SetProfiler(this); |
+ LOGGER->ticker_->SetProfiler(this); |
- Logger::ProfilerBeginEvent(); |
+ LOGGER->ProfilerBeginEvent(); |
} |
@@ -302,7 +305,7 @@ |
if (!engaged_) return; |
// Stop receiving ticks. |
- Logger::ticker_->ClearProfiler(); |
+ LOGGER->ticker_->ClearProfiler(); |
// Terminate the worker thread by setting running_ to false, |
// inserting a fake element in the queue and then wait for |
@@ -314,15 +317,16 @@ |
Insert(&sample); |
Join(); |
- LOG(UncheckedStringEvent("profiler", "end")); |
+ LOG(ISOLATE, UncheckedStringEvent("profiler", "end")); |
} |
void Profiler::Run() { |
TickSample sample; |
bool overflow = Remove(&sample); |
+ i::Isolate* isolate = ISOLATE; |
while (running_) { |
- LOG(TickEvent(&sample, overflow)); |
+ LOG(isolate, TickEvent(&sample, overflow)); |
overflow = Remove(&sample); |
} |
} |
@@ -331,23 +335,38 @@ |
// |
// Logger class implementation. |
// |
-Ticker* Logger::ticker_ = NULL; |
-Profiler* Logger::profiler_ = NULL; |
-SlidingStateWindow* Logger::sliding_state_window_ = NULL; |
-int Logger::logging_nesting_ = 0; |
-int Logger::cpu_profiler_nesting_ = 0; |
-int Logger::heap_profiler_nesting_ = 0; |
+Logger::Logger() |
+ : ticker_(NULL), |
+ profiler_(NULL), |
+ sliding_state_window_(NULL), |
+ log_events_(NULL), |
+ logging_nesting_(0), |
+ cpu_profiler_nesting_(0), |
+ heap_profiler_nesting_(0), |
+ log_(new Log(this)), |
+ is_initialized_(false), |
+ last_address_(NULL), |
+ prev_sp_(NULL), |
+ prev_function_(NULL), |
+ prev_to_(NULL), |
+ prev_code_(NULL) { |
+} |
+ |
+Logger::~Logger() { |
+ delete log_; |
+} |
+ |
#define DECLARE_EVENT(ignore1, name) name, |
-const char* kLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = { |
+static const char* const kLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = { |
LOG_EVENTS_AND_TAGS_LIST(DECLARE_EVENT) |
}; |
#undef DECLARE_EVENT |
void Logger::ProfilerBeginEvent() { |
- if (!Log::IsEnabled()) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled()) return; |
+ LogMessageBuilder msg(this); |
msg.Append("profiler,\"begin\",%d\n", kSamplingIntervalMs); |
msg.WriteToLogFile(); |
} |
@@ -364,8 +383,8 @@ |
#ifdef ENABLE_LOGGING_AND_PROFILING |
void Logger::UncheckedStringEvent(const char* name, const char* value) { |
- if (!Log::IsEnabled()) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled()) return; |
+ LogMessageBuilder msg(this); |
msg.Append("%s,\"%s\"\n", name, value); |
msg.WriteToLogFile(); |
} |
@@ -388,8 +407,8 @@ |
#ifdef ENABLE_LOGGING_AND_PROFILING |
void Logger::UncheckedIntEvent(const char* name, int value) { |
- if (!Log::IsEnabled()) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled()) return; |
+ LogMessageBuilder msg(this); |
msg.Append("%s,%d\n", name, value); |
msg.WriteToLogFile(); |
} |
@@ -398,8 +417,8 @@ |
#ifdef ENABLE_LOGGING_AND_PROFILING |
void Logger::UncheckedIntPtrTEvent(const char* name, intptr_t value) { |
- if (!Log::IsEnabled()) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled()) return; |
+ LogMessageBuilder msg(this); |
msg.Append("%s,%" V8_PTR_PREFIX "d\n", name, value); |
msg.WriteToLogFile(); |
} |
@@ -408,8 +427,8 @@ |
void Logger::HandleEvent(const char* name, Object** location) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_handles) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_handles) return; |
+ LogMessageBuilder msg(this); |
msg.Append("%s,0x%" V8PRIxPTR "\n", name, location); |
msg.WriteToLogFile(); |
#endif |
@@ -421,8 +440,8 @@ |
// caller's responsibility to ensure that log is enabled and that |
// FLAG_log_api is true. |
void Logger::ApiEvent(const char* format, ...) { |
- ASSERT(Log::IsEnabled() && FLAG_log_api); |
- LogMessageBuilder msg; |
+ ASSERT(log_->IsEnabled() && FLAG_log_api); |
+ LogMessageBuilder msg(this); |
va_list ap; |
va_start(ap, format); |
msg.AppendVA(format, ap); |
@@ -434,7 +453,7 @@ |
void Logger::ApiNamedSecurityCheck(Object* key) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_api) return; |
+ if (!log_->IsEnabled() || !FLAG_log_api) return; |
if (key->IsString()) { |
SmartPointer<char> str = |
String::cast(key)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); |
@@ -452,8 +471,8 @@ |
uintptr_t start, |
uintptr_t end) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_prof) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_prof) return; |
+ LogMessageBuilder msg(this); |
msg.Append("shared-library,\"%s\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR "\n", |
library_path, |
start, |
@@ -467,8 +486,8 @@ |
uintptr_t start, |
uintptr_t end) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_prof) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_prof) return; |
+ LogMessageBuilder msg(this); |
msg.Append("shared-library,\"%ls\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR "\n", |
library_path, |
start, |
@@ -482,7 +501,7 @@ |
void Logger::LogRegExpSource(Handle<JSRegExp> regexp) { |
// Prints "/" + re.source + "/" + |
// (re.global?"g":"") + (re.ignorecase?"i":"") + (re.multiline?"m":"") |
- LogMessageBuilder msg; |
+ LogMessageBuilder msg(this); |
Handle<Object> source = GetProperty(regexp, "source"); |
if (!source->IsString()) { |
@@ -524,8 +543,8 @@ |
void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_regexp) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_regexp) return; |
+ LogMessageBuilder msg(this); |
msg.Append("regexp-compile,"); |
LogRegExpSource(regexp); |
msg.Append(in_cache ? ",hit\n" : ",miss\n"); |
@@ -536,9 +555,9 @@ |
void Logger::LogRuntime(Vector<const char> format, JSArray* args) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_runtime) return; |
+ if (!log_->IsEnabled() || !FLAG_log_runtime) return; |
HandleScope scope; |
- LogMessageBuilder msg; |
+ LogMessageBuilder msg(this); |
for (int i = 0; i < format.length(); i++) { |
char c = format[i]; |
if (c == '%' && i <= format.length() - 2) { |
@@ -582,7 +601,7 @@ |
void Logger::ApiIndexedSecurityCheck(uint32_t index) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_api) return; |
+ if (!log_->IsEnabled() || !FLAG_log_api) return; |
ApiEvent("api,check-security,%u\n", index); |
#endif |
} |
@@ -593,13 +612,13 @@ |
Object* name) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
ASSERT(name->IsString()); |
- if (!Log::IsEnabled() || !FLAG_log_api) return; |
+ if (!log_->IsEnabled() || !FLAG_log_api) return; |
String* class_name_obj = holder->class_name(); |
SmartPointer<char> class_name = |
class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); |
SmartPointer<char> property_name = |
String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); |
- Logger::ApiEvent("api,%s,\"%s\",\"%s\"\n", tag, *class_name, *property_name); |
+ LOGGER->ApiEvent("api,%s,\"%s\",\"%s\"\n", tag, *class_name, *property_name); |
#endif |
} |
@@ -607,37 +626,37 @@ |
JSObject* holder, |
uint32_t index) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_api) return; |
+ if (!log_->IsEnabled() || !FLAG_log_api) return; |
String* class_name_obj = holder->class_name(); |
SmartPointer<char> class_name = |
class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); |
- Logger::ApiEvent("api,%s,\"%s\",%u\n", tag, *class_name, index); |
+ LOGGER->ApiEvent("api,%s,\"%s\",%u\n", tag, *class_name, index); |
#endif |
} |
void Logger::ApiObjectAccess(const char* tag, JSObject* object) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_api) return; |
+ if (!log_->IsEnabled() || !FLAG_log_api) return; |
String* class_name_obj = object->class_name(); |
SmartPointer<char> class_name = |
class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); |
- Logger::ApiEvent("api,%s,\"%s\"\n", tag, *class_name); |
+ LOGGER->ApiEvent("api,%s,\"%s\"\n", tag, *class_name); |
#endif |
} |
void Logger::ApiEntryCall(const char* name) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_api) return; |
- Logger::ApiEvent("api,%s\n", name); |
+ if (!log_->IsEnabled() || !FLAG_log_api) return; |
+ LOGGER->ApiEvent("api,%s\n", name); |
#endif |
} |
void Logger::NewEvent(const char* name, void* object, size_t size) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log) return; |
+ LogMessageBuilder msg(this); |
msg.Append("new,%s,0x%" V8PRIxPTR ",%u\n", name, object, |
static_cast<unsigned int>(size)); |
msg.WriteToLogFile(); |
@@ -647,19 +666,28 @@ |
void Logger::DeleteEvent(const char* name, void* object) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log) return; |
+ LogMessageBuilder msg(this); |
msg.Append("delete,%s,0x%" V8PRIxPTR "\n", name, object); |
msg.WriteToLogFile(); |
#endif |
} |
+void Logger::NewEventStatic(const char* name, void* object, size_t size) { |
+ LOGGER->NewEvent(name, object, size); |
+} |
+ |
+ |
+void Logger::DeleteEventStatic(const char* name, void* object) { |
+ LOGGER->DeleteEvent(name, object); |
+} |
+ |
#ifdef ENABLE_LOGGING_AND_PROFILING |
void Logger::CallbackEventInternal(const char* prefix, const char* name, |
Address entry_point) { |
- if (!Log::IsEnabled() || !FLAG_log_code) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_code) return; |
+ LogMessageBuilder msg(this); |
msg.Append("%s,%s,", |
kLogEventsNames[CODE_CREATION_EVENT], |
kLogEventsNames[CALLBACK_TAG]); |
@@ -673,7 +701,7 @@ |
void Logger::CallbackEvent(String* name, Address entry_point) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_code) return; |
+ if (!log_->IsEnabled() || !FLAG_log_code) return; |
SmartPointer<char> str = |
name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); |
CallbackEventInternal("", *str, entry_point); |
@@ -683,7 +711,7 @@ |
void Logger::GetterCallbackEvent(String* name, Address entry_point) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_code) return; |
+ if (!log_->IsEnabled() || !FLAG_log_code) return; |
SmartPointer<char> str = |
name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); |
CallbackEventInternal("get ", *str, entry_point); |
@@ -693,7 +721,7 @@ |
void Logger::SetterCallbackEvent(String* name, Address entry_point) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_code) return; |
+ if (!log_->IsEnabled() || !FLAG_log_code) return; |
SmartPointer<char> str = |
name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); |
CallbackEventInternal("set ", *str, entry_point); |
@@ -705,8 +733,8 @@ |
Code* code, |
const char* comment) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_code) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_code) return; |
+ LogMessageBuilder msg(this); |
msg.Append("%s,%s,", |
kLogEventsNames[CODE_CREATION_EVENT], |
kLogEventsNames[tag]); |
@@ -758,9 +786,12 @@ |
SharedFunctionInfo* shared, |
String* name) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_code) return; |
- if (code == Builtins::builtin(Builtins::LazyCompile)) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_code) return; |
+ if (code == Isolate::Current()->builtins()->builtin( |
+ Builtins::LazyCompile)) |
+ return; |
+ |
+ LogMessageBuilder msg(this); |
SmartPointer<char> str = |
name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); |
msg.Append("%s,%s,", |
@@ -785,8 +816,8 @@ |
SharedFunctionInfo* shared, |
String* source, int line) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_code) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_code) return; |
+ LogMessageBuilder msg(this); |
SmartPointer<char> name = |
shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); |
SmartPointer<char> sourcestr = |
@@ -811,8 +842,8 @@ |
void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_code) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_code) return; |
+ LogMessageBuilder msg(this); |
msg.Append("%s,%s,", |
kLogEventsNames[CODE_CREATION_EVENT], |
kLogEventsNames[tag]); |
@@ -827,8 +858,8 @@ |
void Logger::CodeMovingGCEvent() { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_code || !FLAG_ll_prof) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_code || !FLAG_ll_prof) return; |
+ LogMessageBuilder msg(this); |
msg.Append("%s\n", kLogEventsNames[CODE_MOVING_GC]); |
msg.WriteToLogFile(); |
OS::SignalCodeMovingGC(); |
@@ -838,8 +869,8 @@ |
void Logger::RegExpCodeCreateEvent(Code* code, String* source) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_code) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_code) return; |
+ LogMessageBuilder msg(this); |
msg.Append("%s,%s,", |
kLogEventsNames[CODE_CREATION_EVENT], |
kLogEventsNames[REG_EXP_TAG]); |
@@ -870,8 +901,8 @@ |
void Logger::SnapshotPositionEvent(Address addr, int pos) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_snapshot_positions) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_snapshot_positions) return; |
+ LogMessageBuilder msg(this); |
msg.Append("%s,", kLogEventsNames[SNAPSHOT_POSITION_EVENT]); |
msg.AppendAddress(addr); |
msg.Append(",%d", pos); |
@@ -892,8 +923,8 @@ |
void Logger::MoveEventInternal(LogEventsAndTags event, |
Address from, |
Address to) { |
- if (!Log::IsEnabled() || !FLAG_log_code) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_code) return; |
+ LogMessageBuilder msg(this); |
msg.Append("%s,", kLogEventsNames[event]); |
msg.AppendAddress(from); |
msg.Append(','); |
@@ -906,8 +937,8 @@ |
#ifdef ENABLE_LOGGING_AND_PROFILING |
void Logger::DeleteEventInternal(LogEventsAndTags event, Address from) { |
- if (!Log::IsEnabled() || !FLAG_log_code) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_code) return; |
+ LogMessageBuilder msg(this); |
msg.Append("%s,", kLogEventsNames[event]); |
msg.AppendAddress(from); |
msg.Append('\n'); |
@@ -918,8 +949,8 @@ |
void Logger::ResourceEvent(const char* name, const char* tag) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log) return; |
+ LogMessageBuilder msg(this); |
msg.Append("%s,%s,", name, tag); |
uint32_t sec, usec; |
@@ -936,11 +967,11 @@ |
void Logger::SuspectReadEvent(String* name, Object* obj) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_suspect) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_suspect) return; |
+ LogMessageBuilder msg(this); |
String* class_name = obj->IsJSObject() |
? JSObject::cast(obj)->class_name() |
- : Heap::empty_string(); |
+ : HEAP->empty_string(); |
msg.Append("suspect-read,"); |
msg.Append(class_name); |
msg.Append(','); |
@@ -955,8 +986,8 @@ |
void Logger::HeapSampleBeginEvent(const char* space, const char* kind) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_gc) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_gc) return; |
+ LogMessageBuilder msg(this); |
// Using non-relative system time in order to be able to synchronize with |
// external memory profiling events (e.g. DOM memory size). |
msg.Append("heap-sample-begin,\"%s\",\"%s\",%.0f\n", |
@@ -969,8 +1000,8 @@ |
void Logger::HeapSampleStats(const char* space, const char* kind, |
intptr_t capacity, intptr_t used) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_gc) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_gc) return; |
+ LogMessageBuilder msg(this); |
msg.Append("heap-sample-stats,\"%s\",\"%s\"," |
"%" V8_PTR_PREFIX "d,%" V8_PTR_PREFIX "d\n", |
space, kind, capacity, used); |
@@ -981,8 +1012,8 @@ |
void Logger::HeapSampleEndEvent(const char* space, const char* kind) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_gc) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_gc) return; |
+ LogMessageBuilder msg(this); |
msg.Append("heap-sample-end,\"%s\",\"%s\"\n", space, kind); |
msg.WriteToLogFile(); |
#endif |
@@ -991,8 +1022,8 @@ |
void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_gc) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_gc) return; |
+ LogMessageBuilder msg(this); |
msg.Append("heap-sample-item,%s,%d,%d\n", type, number, bytes); |
msg.WriteToLogFile(); |
#endif |
@@ -1002,32 +1033,32 @@ |
void Logger::HeapSampleJSConstructorEvent(const char* constructor, |
int number, int bytes) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_gc) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_gc) return; |
+ LogMessageBuilder msg(this); |
msg.Append("heap-js-cons-item,%s,%d,%d\n", constructor, number, bytes); |
msg.WriteToLogFile(); |
#endif |
} |
+// Event starts with comma, so we don't have it in the format string. |
+static const char kEventText[] = "heap-js-ret-item,%s"; |
+// We take placeholder strings into account, but it's OK to be conservative. |
+static const int kEventTextLen = sizeof(kEventText)/sizeof(kEventText[0]); |
void Logger::HeapSampleJSRetainersEvent( |
const char* constructor, const char* event) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_gc) return; |
- // Event starts with comma, so we don't have it in the format string. |
- static const char* event_text = "heap-js-ret-item,%s"; |
- // We take placeholder strings into account, but it's OK to be conservative. |
- static const int event_text_len = StrLength(event_text); |
+ if (!log_->IsEnabled() || !FLAG_log_gc) return; |
const int cons_len = StrLength(constructor); |
const int event_len = StrLength(event); |
int pos = 0; |
// Retainer lists can be long. We may need to split them into multiple events. |
do { |
- LogMessageBuilder msg; |
- msg.Append(event_text, constructor); |
+ LogMessageBuilder msg(this); |
+ msg.Append(kEventText, constructor); |
int to_write = event_len - pos; |
- if (to_write > Log::kMessageBufferSize - (cons_len + event_text_len)) { |
- int cut_pos = pos + Log::kMessageBufferSize - (cons_len + event_text_len); |
+ if (to_write > Log::kMessageBufferSize - (cons_len + kEventTextLen)) { |
+ int cut_pos = pos + Log::kMessageBufferSize - (cons_len + kEventTextLen); |
ASSERT(cut_pos < event_len); |
while (cut_pos > pos && event[cut_pos] != ',') --cut_pos; |
if (event[cut_pos] != ',') { |
@@ -1053,8 +1084,8 @@ |
void Logger::HeapSampleJSProducerEvent(const char* constructor, |
Address* stack) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_gc) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log_gc) return; |
+ LogMessageBuilder msg(this); |
msg.Append("heap-js-prod-item,%s", constructor); |
while (*stack != NULL) { |
msg.Append(",0x%" V8PRIxPTR, *stack++); |
@@ -1067,8 +1098,8 @@ |
void Logger::DebugTag(const char* call_site_tag) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_log) return; |
+ LogMessageBuilder msg(this); |
msg.Append("debug-tag,%s\n", call_site_tag); |
msg.WriteToLogFile(); |
#endif |
@@ -1077,13 +1108,13 @@ |
void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log) return; |
+ if (!log_->IsEnabled() || !FLAG_log) return; |
StringBuilder s(parameter.length() + 1); |
for (int i = 0; i < parameter.length(); ++i) { |
s.AddCharacter(static_cast<char>(parameter[i])); |
} |
char* parameter_string = s.Finalize(); |
- LogMessageBuilder msg; |
+ LogMessageBuilder msg(this); |
msg.Append("debug-queue-event,%s,%15.3f,%s\n", |
event_type, |
OS::TimeCurrentMillis(), |
@@ -1096,8 +1127,8 @@ |
#ifdef ENABLE_LOGGING_AND_PROFILING |
void Logger::TickEvent(TickSample* sample, bool overflow) { |
- if (!Log::IsEnabled() || !FLAG_prof) return; |
- LogMessageBuilder msg; |
+ if (!log_->IsEnabled() || !FLAG_prof) return; |
+ LogMessageBuilder msg(this); |
msg.Append("%s,", kLogEventsNames[TICK_EVENT]); |
msg.AppendAddress(sample->pc); |
msg.Append(','); |
@@ -1130,7 +1161,7 @@ |
void Logger::PauseProfiler(int flags, int tag) { |
- if (!Log::IsEnabled()) return; |
+ if (!log_->IsEnabled()) return; |
if (profiler_ != NULL && (flags & PROFILER_MODULE_CPU)) { |
// It is OK to have negative nesting. |
if (--cpu_profiler_nesting_ == 0) { |
@@ -1141,7 +1172,7 @@ |
} |
FLAG_log_code = false; |
// Must be the same message as Log::kDynamicBufferSeal. |
- LOG(UncheckedStringEvent("profiler", "pause")); |
+ LOG(ISOLATE, UncheckedStringEvent("profiler", "pause")); |
} |
--logging_nesting_; |
} |
@@ -1160,7 +1191,7 @@ |
void Logger::ResumeProfiler(int flags, int tag) { |
- if (!Log::IsEnabled()) return; |
+ if (!log_->IsEnabled()) return; |
if (tag != 0) { |
UncheckedIntEvent("open-tag", tag); |
} |
@@ -1169,7 +1200,7 @@ |
++logging_nesting_; |
if (FLAG_prof_lazy) { |
profiler_->Engage(); |
- LOG(UncheckedStringEvent("profiler", "resume")); |
+ LOG(ISOLATE, UncheckedStringEvent("profiler", "resume")); |
FLAG_log_code = true; |
LogCompiledFunctions(); |
LogAccessorCallbacks(); |
@@ -1192,8 +1223,7 @@ |
// This function can be called when Log's mutex is acquired, |
// either from main or Profiler's thread. |
-void Logger::StopLoggingAndProfiling() { |
- Log::stop(); |
+void Logger::LogFailure() { |
PauseProfiler(PROFILER_MODULE_CPU, 0); |
} |
@@ -1204,7 +1234,7 @@ |
int Logger::GetLogLines(int from_pos, char* dest_buf, int max_size) { |
- return Log::GetLogLines(from_pos, dest_buf, max_size); |
+ return log_->GetLogLines(from_pos, dest_buf, max_size); |
} |
@@ -1326,14 +1356,14 @@ |
tag = Logger::KEYED_CALL_IC_TAG; |
break; |
} |
- PROFILE(CodeCreateEvent(tag, code_object, description)); |
+ PROFILE(ISOLATE, CodeCreateEvent(tag, code_object, description)); |
} |
} |
void Logger::LogCodeInfo() { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- if (!Log::IsEnabled() || !FLAG_log_code || !FLAG_ll_prof) return; |
+ if (!log_->IsEnabled() || !FLAG_log_code || !FLAG_ll_prof) return; |
#if V8_TARGET_ARCH_IA32 |
const char arch[] = "ia32"; |
#elif V8_TARGET_ARCH_X64 |
@@ -1343,7 +1373,7 @@ |
#else |
const char arch[] = "unknown"; |
#endif |
- LogMessageBuilder msg; |
+ LogMessageBuilder msg(this); |
msg.Append("code-info,%s,%d\n", arch, Code::kHeaderSize); |
msg.WriteToLogFile(); |
#endif // ENABLE_LOGGING_AND_PROFILING |
@@ -1351,10 +1381,10 @@ |
void Logger::LowLevelCodeCreateEvent(Code* code, LogMessageBuilder* msg) { |
- if (!FLAG_ll_prof || Log::output_code_handle_ == NULL) return; |
- int pos = static_cast<int>(ftell(Log::output_code_handle_)); |
+ if (!FLAG_ll_prof || log_->output_code_handle_ == NULL) return; |
+ int pos = static_cast<int>(ftell(log_->output_code_handle_)); |
size_t rv = fwrite(code->instruction_start(), 1, code->instruction_size(), |
- Log::output_code_handle_); |
+ log_->output_code_handle_); |
ASSERT(static_cast<size_t>(code->instruction_size()) == rv); |
USE(rv); |
msg->Append(",%d", pos); |
@@ -1380,7 +1410,9 @@ |
// During iteration, there can be heap allocation due to |
// GetScriptLineNumber call. |
for (int i = 0; i < compiled_funcs_count; ++i) { |
- if (*code_objects[i] == Builtins::builtin(Builtins::LazyCompile)) continue; |
+ if (*code_objects[i] == Isolate::Current()->builtins()->builtin( |
+ Builtins::LazyCompile)) |
+ continue; |
Handle<SharedFunctionInfo> shared = sfis[i]; |
Handle<String> func_name(shared->DebugName()); |
if (shared->script()->IsScript()) { |
@@ -1389,20 +1421,23 @@ |
Handle<String> script_name(String::cast(script->name())); |
int line_num = GetScriptLineNumber(script, shared->start_position()); |
if (line_num > 0) { |
- PROFILE(CodeCreateEvent( |
- Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script), |
- *code_objects[i], *shared, |
- *script_name, line_num + 1)); |
+ PROFILE(ISOLATE, |
+ CodeCreateEvent( |
+ Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script), |
+ *code_objects[i], *shared, |
+ *script_name, line_num + 1)); |
} else { |
// Can't distinguish eval and script here, so always use Script. |
- PROFILE(CodeCreateEvent( |
- Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), |
- *code_objects[i], *shared, *script_name)); |
+ PROFILE(ISOLATE, |
+ CodeCreateEvent( |
+ Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), |
+ *code_objects[i], *shared, *script_name)); |
} |
} else { |
- PROFILE(CodeCreateEvent( |
- Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script), |
- *code_objects[i], *shared, *func_name)); |
+ PROFILE(ISOLATE, |
+ CodeCreateEvent( |
+ Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script), |
+ *code_objects[i], *shared, *func_name)); |
} |
} else if (shared->IsApiFunction()) { |
// API function. |
@@ -1412,11 +1447,13 @@ |
CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data); |
Object* callback_obj = call_data->callback(); |
Address entry_point = v8::ToCData<Address>(callback_obj); |
- PROFILE(CallbackEvent(*func_name, entry_point)); |
+ PROFILE(ISOLATE, CallbackEvent(*func_name, entry_point)); |
} |
} else { |
- PROFILE(CodeCreateEvent( |
- Logger::LAZY_COMPILE_TAG, *code_objects[i], *shared, *func_name)); |
+ PROFILE(ISOLATE, |
+ CodeCreateEvent( |
+ Logger::LAZY_COMPILE_TAG, *code_objects[i], |
+ *shared, *func_name)); |
} |
} |
} |
@@ -1425,6 +1462,7 @@ |
void Logger::LogAccessorCallbacks() { |
AssertNoAllocation no_alloc; |
HeapIterator iterator; |
+ i::Isolate* isolate = ISOLATE; |
for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
if (!obj->IsAccessorInfo()) continue; |
AccessorInfo* ai = AccessorInfo::cast(obj); |
@@ -1432,11 +1470,11 @@ |
String* name = String::cast(ai->name()); |
Address getter_entry = v8::ToCData<Address>(ai->getter()); |
if (getter_entry != 0) { |
- PROFILE(GetterCallbackEvent(name, getter_entry)); |
+ PROFILE(isolate, GetterCallbackEvent(name, getter_entry)); |
} |
Address setter_entry = v8::ToCData<Address>(ai->setter()); |
if (setter_entry != 0) { |
- PROFILE(SetterCallbackEvent(name, setter_entry)); |
+ PROFILE(isolate, SetterCallbackEvent(name, setter_entry)); |
} |
} |
} |
@@ -1446,20 +1484,10 @@ |
bool Logger::Setup() { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- // --log-all enables all the log flags. |
- if (FLAG_log_all) { |
- FLAG_log_runtime = true; |
- FLAG_log_api = true; |
- FLAG_log_code = true; |
- FLAG_log_gc = true; |
- FLAG_log_suspect = true; |
- FLAG_log_handles = true; |
- FLAG_log_regexp = true; |
- } |
+ // Tests and EnsureInitialize() can call this twice in a row. It's harmless. |
+ if (is_initialized_) return true; |
+ is_initialized_ = true; |
- // --prof implies --log-code. |
- if (FLAG_prof) FLAG_log_code = true; |
- |
// --ll-prof implies --log-code and --log-snapshot-positions. |
if (FLAG_ll_prof) { |
FLAG_log_code = true; |
@@ -1472,73 +1500,30 @@ |
FLAG_prof_auto = false; |
} |
- bool start_logging = FLAG_log || FLAG_log_runtime || FLAG_log_api |
- || FLAG_log_code || FLAG_log_gc || FLAG_log_handles || FLAG_log_suspect |
- || FLAG_log_regexp || FLAG_log_state_changes; |
+ // TODO(isolates): this assert introduces cyclic dependency (logger |
+ // -> thread local top -> heap -> logger). |
+ // ASSERT(VMState::is_outermost_external()); |
- bool open_log_file = start_logging || FLAG_prof_lazy; |
+ log_->Initialize(); |
- // If we're logging anything, we need to open the log file. |
- if (open_log_file) { |
- if (strcmp(FLAG_logfile, "-") == 0) { |
- Log::OpenStdout(); |
- } else if (strcmp(FLAG_logfile, "*") == 0) { |
- Log::OpenMemoryBuffer(); |
- } else if (strchr(FLAG_logfile, '%') != NULL) { |
- // If there's a '%' in the log file name we have to expand |
- // placeholders. |
- HeapStringAllocator allocator; |
- StringStream stream(&allocator); |
- for (const char* p = FLAG_logfile; *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 '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); |
- } |
- } |
- SmartPointer<const char> expanded = stream.ToCString(); |
- Log::OpenFile(*expanded); |
- } else { |
- Log::OpenFile(FLAG_logfile); |
- } |
- } |
- |
if (FLAG_ll_prof) LogCodeInfo(); |
- ticker_ = new Ticker(kSamplingIntervalMs); |
+ ticker_ = new Ticker(Isolate::Current(), kSamplingIntervalMs); |
if (FLAG_sliding_state_window && sliding_state_window_ == NULL) { |
sliding_state_window_ = new SlidingStateWindow(); |
} |
+ bool start_logging = FLAG_log || FLAG_log_runtime || FLAG_log_api |
+ || FLAG_log_code || FLAG_log_gc || FLAG_log_handles || FLAG_log_suspect |
+ || FLAG_log_regexp || FLAG_log_state_changes; |
+ |
if (start_logging) { |
logging_nesting_ = 1; |
} |
if (FLAG_prof) { |
- profiler_ = new Profiler(); |
+ profiler_ = new Profiler(Isolate::Current()); |
if (!FLAG_prof_auto) { |
profiler_->pause(); |
} else { |
@@ -1549,7 +1534,6 @@ |
} |
} |
- LogMessageBuilder::set_write_failure_handler(StopLoggingAndProfiling); |
return true; |
#else |
@@ -1558,6 +1542,11 @@ |
} |
+Sampler* Logger::sampler() { |
+ return ticker_; |
+} |
+ |
+ |
void Logger::EnsureTickerStarted() { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
ASSERT(ticker_ != NULL); |
@@ -1575,7 +1564,8 @@ |
void Logger::TearDown() { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
- LogMessageBuilder::set_write_failure_handler(NULL); |
+ if (!is_initialized_) return; |
+ is_initialized_ = false; |
// Stop the profiler before closing the file. |
if (profiler_ != NULL) { |
@@ -1590,7 +1580,7 @@ |
delete ticker_; |
ticker_ = NULL; |
- Log::Close(); |
+ log_->Close(); |
#endif |
} |
@@ -1613,4 +1603,56 @@ |
#endif |
} |
+ |
+Mutex* SamplerRegistry::mutex_ = OS::CreateMutex(); |
+List<Sampler*>* SamplerRegistry::active_samplers_ = NULL; |
+ |
+ |
+bool SamplerRegistry::IterateActiveSamplers(VisitSampler func, void* param) { |
+ ScopedLock lock(mutex_); |
+ for (int i = 0; |
+ ActiveSamplersExist() && i < active_samplers_->length(); |
+ ++i) { |
+ func(active_samplers_->at(i), param); |
+ } |
+ return ActiveSamplersExist(); |
+} |
+ |
+ |
+static void ComputeCpuProfiling(Sampler* sampler, void* flag_ptr) { |
+ bool* flag = reinterpret_cast<bool*>(flag_ptr); |
+ *flag |= sampler->IsProfiling(); |
+} |
+ |
+ |
+SamplerRegistry::State SamplerRegistry::GetState() { |
+ bool flag = false; |
+ if (!IterateActiveSamplers(&ComputeCpuProfiling, &flag)) { |
+ return HAS_NO_SAMPLERS; |
+ } |
+ return flag ? HAS_CPU_PROFILING_SAMPLERS : HAS_SAMPLERS; |
+} |
+ |
+ |
+void SamplerRegistry::AddActiveSampler(Sampler* sampler) { |
+ ASSERT(sampler->IsActive()); |
+ ScopedLock lock(mutex_); |
+ if (active_samplers_ == NULL) { |
+ active_samplers_ = new List<Sampler*>; |
+ } else { |
+ ASSERT(!active_samplers_->Contains(sampler)); |
+ } |
+ active_samplers_->Add(sampler); |
+} |
+ |
+ |
+void SamplerRegistry::RemoveActiveSampler(Sampler* sampler) { |
+ ASSERT(sampler->IsActive()); |
+ ScopedLock lock(mutex_); |
+ ASSERT(active_samplers_ != NULL); |
+ bool removed = active_samplers_->RemoveElement(sampler); |
+ ASSERT(removed); |
+ USE(removed); |
+} |
+ |
} } // namespace v8::internal |