typedef void (*MessageCallback)(Handle<Message> message, Handle<Value> error);
+// --- Tracing ---
+
+typedef void (*LogEventCallback)(const char* name, int event);
/**
* Create new error objects by calling the corresponding error object
*/
void RequestGarbageCollectionForTesting(GarbageCollectionType type);
+ /**
+ * Set the callback to invoke for logging event.
+ */
+ void SetEventLogger(LogEventCallback that);
+
private:
Isolate();
Isolate(const Isolate&);
}
+void Isolate::SetEventLogger(LogEventCallback that) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+ isolate->set_event_logger(that);
+}
+
String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj)
: str_(NULL), length_(0) {
i::Isolate* isolate = i::Isolate::Current();
if (Enabled()) {
timer_.Start();
}
- if (FLAG_log_internal_timer_events) {
- LOG(isolate(), TimerEvent(Logger::START, name()));
- }
+ isolate()->event_logger()(name(), Logger::START);
}
AddSample(static_cast<int>(timer_.Elapsed().InMilliseconds()));
timer_.Stop();
}
- if (FLAG_log_internal_timer_events) {
- LOG(isolate(), TimerEvent(Logger::END, name()));
- }
+ isolate()->event_logger()(name(), Logger::END);
}
} } // namespace v8::internal
bootstrapper_->Initialize(create_heap_objects);
builtins_.SetUp(this, create_heap_objects);
+ if (FLAG_log_internal_timer_events) {
+ set_event_logger(Logger::LogInternalEvents);
+ } else {
+ set_event_logger(Logger::EmptyLogInternalEvents);
+ }
+
// Set default value if not yet set.
// TODO(yangguo): move this to ResourceConstraints::ConfigureDefaults
// once ResourceConstraints becomes an argument to the Isolate constructor.
/* A previously allocated buffer of kMinimalBufferSize bytes, or NULL. */ \
V(byte*, assembler_spare_buffer, NULL) \
V(FatalErrorCallback, exception_behavior, NULL) \
+ V(LogEventCallback, event_logger, NULL) \
V(AllowCodeGenerationFromStringsCallback, allow_code_gen_callback, NULL) \
/* To distinguish the function templates, so that we can find them in the */ \
/* function cache of the native context. */ \
}
+void Logger::LogInternalEvents(const char* name, int se) {
+ Isolate* isolate = Isolate::Current();
+ LOG(isolate, TimerEvent(static_cast<StartEnd>(se), name));
+}
+
+
void Logger::TimerEventScope::LogTimerEvent(StartEnd se) {
- LOG(isolate_, TimerEvent(se, name_));
+ isolate_->event_logger()(name_, se);
}
static void EnterExternal(Isolate* isolate);
static void LeaveExternal(Isolate* isolate);
+ static void EmptyLogInternalEvents(const char* name, int se) { }
+ static void LogInternalEvents(const char* name, int se);
+
class TimerEventScope {
public:
TimerEventScope(Isolate* isolate, const char* name)
: isolate_(isolate), name_(name) {
- if (FLAG_log_internal_timer_events) LogTimerEvent(START);
+ LogTimerEvent(START);
}
~TimerEventScope() {
- if (FLAG_log_internal_timer_events) LogTimerEvent(END);
+ LogTimerEvent(END);
}
void LogTimerEvent(StartEnd se);
ApiCallOptimizationChecker checker;
checker.RunAll();
}
+
+
+static const char* last_event_message;
+static int last_event_status;
+void StoringEventLoggerCallback(const char* message, int status) {
+ last_event_message = message;
+ last_event_status = status;
+}
+
+
+TEST(EventLogging) {
+ v8::Isolate* isolate = CcTest::isolate();
+ isolate->SetEventLogger(StoringEventLoggerCallback);
+ v8::internal::HistogramTimer* histogramTimer =
+ new v8::internal::HistogramTimer(
+ "V8.Test", 0, 10000, 50,
+ reinterpret_cast<v8::internal::Isolate*>(isolate));
+ histogramTimer->Start();
+ CHECK_EQ("V8.Test", last_event_message);
+ CHECK_EQ(0, last_event_status);
+ histogramTimer->Stop();
+ CHECK_EQ("V8.Test", last_event_message);
+ CHECK_EQ(1, last_event_status);
+}