00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <stdarg.h>
00029
00030 #include "v8.h"
00031
00032 #include "log.h"
00033 #include "platform.h"
00034 #include "string-stream.h"
00035
00036 namespace v8 { namespace internal {
00037
00038 #ifdef ENABLE_LOGGING_AND_PROFILING
00039
00040
00041
00042
00043
00044
00045 class SlidingStateWindow {
00046 public:
00047 SlidingStateWindow();
00048 ~SlidingStateWindow();
00049 void AddState(StateTag state);
00050
00051 private:
00052 static const int kBufferSize = 256;
00053 int current_index_;
00054 bool is_full_;
00055 byte buffer_[kBufferSize];
00056
00057
00058 void IncrementStateCounter(StateTag state) {
00059 Counters::state_counters[state].Increment();
00060 }
00061
00062
00063 void DecrementStateCounter(StateTag state) {
00064 Counters::state_counters[state].Decrement();
00065 }
00066 };
00067
00068
00069
00070
00071
00072
00073
00074
00075 class Profiler: public Thread {
00076 public:
00077 Profiler();
00078 void Engage();
00079 void Disengage();
00080
00081
00082 void Insert(TickSample* sample) {
00083 if (Succ(head_) == tail_) {
00084 overflow_ = true;
00085 } else {
00086 buffer_[head_] = *sample;
00087 head_ = Succ(head_);
00088 buffer_semaphore_->Signal();
00089 }
00090 }
00091
00092
00093 bool Remove(TickSample* sample) {
00094 buffer_semaphore_->Wait();
00095 *sample = buffer_[tail_];
00096 bool result = overflow_;
00097 tail_ = Succ(tail_);
00098 overflow_ = false;
00099 return result;
00100 }
00101
00102 void Run();
00103
00104 private:
00105
00106 int Succ(int index) { return (index + 1) % kBufferSize; }
00107
00108
00109
00110 static const int kBufferSize = 128;
00111 TickSample buffer_[kBufferSize];
00112 int head_;
00113 int tail_;
00114 bool overflow_;
00115 Semaphore* buffer_semaphore_;
00116
00117
00118 bool running_;
00119 };
00120
00121
00122
00123
00124
00125
00126 class Ticker: public Sampler {
00127 public:
00128 explicit Ticker(int interval):
00129 Sampler(interval, FLAG_prof), window_(NULL), profiler_(NULL) {}
00130
00131 ~Ticker() { if (IsActive()) Stop(); }
00132
00133 void Tick(TickSample* sample) {
00134 if (profiler_) profiler_->Insert(sample);
00135 if (window_) window_->AddState(sample->state);
00136 }
00137
00138 void SetWindow(SlidingStateWindow* window) {
00139 window_ = window;
00140 if (!IsActive()) Start();
00141 }
00142
00143 void ClearWindow() {
00144 window_ = NULL;
00145 if (!profiler_ && IsActive()) Stop();
00146 }
00147
00148 void SetProfiler(Profiler* profiler) {
00149 profiler_ = profiler;
00150 if (!IsActive()) Start();
00151 }
00152
00153 void ClearProfiler() {
00154 profiler_ = NULL;
00155 if (!window_ && IsActive()) Stop();
00156 }
00157
00158 private:
00159 SlidingStateWindow* window_;
00160 Profiler* profiler_;
00161 };
00162
00163
00164
00165
00166
00167 SlidingStateWindow::SlidingStateWindow(): current_index_(0), is_full_(false) {
00168 for (int i = 0; i < kBufferSize; i++) {
00169 buffer_[i] = static_cast<byte>(OTHER);
00170 }
00171 Logger::ticker_->SetWindow(this);
00172 }
00173
00174
00175 SlidingStateWindow::~SlidingStateWindow() {
00176 Logger::ticker_->ClearWindow();
00177 }
00178
00179
00180 void SlidingStateWindow::AddState(StateTag state) {
00181 if (is_full_) {
00182 DecrementStateCounter(static_cast<StateTag>(buffer_[current_index_]));
00183 } else if (current_index_ == kBufferSize - 1) {
00184 is_full_ = true;
00185 }
00186 buffer_[current_index_] = static_cast<byte>(state);
00187 IncrementStateCounter(state);
00188 ASSERT(IsPowerOf2(kBufferSize));
00189 current_index_ = (current_index_ + 1) & (kBufferSize - 1);
00190 }
00191
00192
00193
00194
00195
00196 Profiler::Profiler() {
00197 buffer_semaphore_ = OS::CreateSemaphore(0);
00198 head_ = 0;
00199 tail_ = 0;
00200 overflow_ = false;
00201 running_ = false;
00202 }
00203
00204
00205 void Profiler::Engage() {
00206 OS::LogSharedLibraryAddresses();
00207
00208
00209 running_ = true;
00210 Start();
00211
00212
00213 Logger::ticker_->SetProfiler(this);
00214
00215 LOG(StringEvent("profiler", "begin"));
00216 }
00217
00218
00219 void Profiler::Disengage() {
00220
00221 Logger::ticker_->ClearProfiler();
00222
00223
00224
00225
00226 running_ = false;
00227 TickSample sample;
00228 sample.pc = 0;
00229 sample.sp = 0;
00230 sample.state = OTHER;
00231 Insert(&sample);
00232 Join();
00233
00234 LOG(StringEvent("profiler", "end"));
00235 }
00236
00237
00238 void Profiler::Run() {
00239 TickSample sample;
00240 bool overflow = Logger::profiler_->Remove(&sample);
00241 while (running_) {
00242 LOG(TickEvent(&sample, overflow));
00243 overflow = Logger::profiler_->Remove(&sample);
00244 }
00245 }
00246
00247
00248
00249
00250
00251 Ticker* Logger::ticker_ = NULL;
00252 FILE* Logger::logfile_ = NULL;
00253 Profiler* Logger::profiler_ = NULL;
00254 Mutex* Logger::mutex_ = NULL;
00255 VMState* Logger::current_state_ = NULL;
00256 SlidingStateWindow* Logger::sliding_state_window_ = NULL;
00257
00258 #endif // ENABLE_LOGGING_AND_PROFILING
00259
00260 void Logger::Preamble(const char* content) {
00261 #ifdef ENABLE_LOGGING_AND_PROFILING
00262 if (logfile_ == NULL || !FLAG_log_code) return;
00263 ScopedLock sl(mutex_);
00264 fprintf(logfile_, "%s", content);
00265 #endif
00266 }
00267
00268
00269 void Logger::StringEvent(const char* name, const char* value) {
00270 #ifdef ENABLE_LOGGING_AND_PROFILING
00271 if (logfile_ == NULL || !FLAG_log) return;
00272 ScopedLock sl(mutex_);
00273 fprintf(logfile_, "%s,\"%s\"\n", name, value);
00274 #endif
00275 }
00276
00277
00278 void Logger::IntEvent(const char* name, int value) {
00279 #ifdef ENABLE_LOGGING_AND_PROFILING
00280 if (logfile_ == NULL || !FLAG_log) return;
00281 ScopedLock sl(mutex_);
00282 fprintf(logfile_, "%s,%d\n", name, value);
00283 #endif
00284 }
00285
00286
00287 void Logger::HandleEvent(const char* name, Object** location) {
00288 #ifdef ENABLE_LOGGING_AND_PROFILING
00289 if (logfile_ == NULL || !FLAG_log_handles) return;
00290 ScopedLock sl(mutex_);
00291 fprintf(logfile_, "%s,0x%x\n", name,
00292 reinterpret_cast<unsigned int>(location));
00293 #endif
00294 }
00295
00296
00297 #ifdef ENABLE_LOGGING_AND_PROFILING
00298
00299
00300
00301 void Logger::ApiEvent(const char* format, ...) {
00302 ASSERT(logfile_ != NULL && FLAG_log_api);
00303 ScopedLock sl(mutex_);
00304 va_list ap;
00305 va_start(ap, format);
00306 vfprintf(logfile_, format, ap);
00307 }
00308 #endif
00309
00310
00311 void Logger::ApiNamedSecurityCheck(Object* key) {
00312 #ifdef ENABLE_LOGGING_AND_PROFILING
00313 if (logfile_ == NULL || !FLAG_log_api) return;
00314 if (key->IsString()) {
00315 SmartPointer<char> str =
00316 String::cast(key)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
00317 ApiEvent("api,check-security,\"%s\"\n", *str);
00318 } else if (key->IsUndefined()) {
00319 ApiEvent("api,check-security,undefined\n");
00320 } else {
00321 ApiEvent("api,check-security,['no-name']\n");
00322 }
00323 #endif
00324 }
00325
00326
00327 void Logger::SharedLibraryEvent(const char* library_path,
00328 unsigned start,
00329 unsigned end) {
00330 #ifdef ENABLE_LOGGING_AND_PROFILING
00331 if (logfile_ == NULL || !FLAG_prof) return;
00332 ScopedLock sl(mutex_);
00333 fprintf(logfile_, "shared-library,\"%s\",0x%08x,0x%08x\n", library_path,
00334 start, end);
00335 #endif
00336 }
00337
00338
00339 void Logger::SharedLibraryEvent(const wchar_t* library_path,
00340 unsigned start,
00341 unsigned end) {
00342 #ifdef ENABLE_LOGGING_AND_PROFILING
00343 if (logfile_ == NULL || !FLAG_prof) return;
00344 ScopedLock sl(mutex_);
00345 fprintf(logfile_, "shared-library,\"%ls\",0x%08x,0x%08x\n", library_path,
00346 start, end);
00347 #endif
00348 }
00349
00350
00351 #ifdef ENABLE_LOGGING_AND_PROFILING
00352 void Logger::LogString(Handle<String> str) {
00353 int len = str->length();
00354 if (len > 256)
00355 len = 256;
00356 for (int i = 0; i < len; i++) {
00357 uc32 c = str->Get(i);
00358 if (c < 32 || (c > 126 && c <= 255)) {
00359 fprintf(logfile_, "\\x%02x", c);
00360 } else if (c > 255) {
00361 fprintf(logfile_, "\\u%04x", c);
00362 } else if (c == ',') {
00363 fprintf(logfile_, "\\,");
00364 } else {
00365 fprintf(logfile_, "%lc", c);
00366 }
00367 }
00368 }
00369
00370 void Logger::LogRegExpSource(Handle<JSRegExp> regexp) {
00371
00372
00373
00374 Handle<Object> source = GetProperty(regexp, "source");
00375 if (!source->IsString()) {
00376 fprintf(logfile_, "no source");
00377 return;
00378 }
00379
00380 switch (regexp->TypeTag()) {
00381 case JSRegExp::ATOM:
00382 fprintf(logfile_, "a");
00383 break;
00384 default:
00385 break;
00386 }
00387 fprintf(logfile_, "/");
00388 LogString(Handle<String>::cast(source));
00389 fprintf(logfile_, "/");
00390
00391
00392 Handle<Object> global = GetProperty(regexp, "global");
00393 if (global->IsTrue()) {
00394 fprintf(logfile_, "g");
00395 }
00396
00397 Handle<Object> ignorecase = GetProperty(regexp, "ignoreCase");
00398 if (ignorecase->IsTrue()) {
00399 fprintf(logfile_, "i");
00400 }
00401
00402 Handle<Object> multiline = GetProperty(regexp, "multiline");
00403 if (multiline->IsTrue()) {
00404 fprintf(logfile_, "m");
00405 }
00406 }
00407 #endif // ENABLE_LOGGING_AND_PROFILING
00408
00409
00410 void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
00411 #ifdef ENABLE_LOGGING_AND_PROFILING
00412 if (logfile_ == NULL || !FLAG_log_regexp) return;
00413 ScopedLock sl(mutex_);
00414
00415 fprintf(logfile_, "regexp-compile,");
00416 LogRegExpSource(regexp);
00417 fprintf(logfile_, in_cache ? ",hit\n" : ",miss\n");
00418 #endif
00419 }
00420
00421
00422 void Logger::RegExpExecEvent(Handle<JSRegExp> regexp,
00423 int start_index,
00424 Handle<String> input_string) {
00425 #ifdef ENABLE_LOGGING_AND_PROFILING
00426 if (logfile_ == NULL || !FLAG_log_regexp) return;
00427 ScopedLock sl(mutex_);
00428
00429 fprintf(logfile_, "regexp-run,");
00430 LogRegExpSource(regexp);
00431 fprintf(logfile_, ",");
00432 LogString(input_string);
00433 fprintf(logfile_, ",%d..%d\n", start_index, input_string->length());
00434 #endif
00435 }
00436
00437
00438 void Logger::ApiIndexedSecurityCheck(uint32_t index) {
00439 #ifdef ENABLE_LOGGING_AND_PROFILING
00440 if (logfile_ == NULL || !FLAG_log_api) return;
00441 ApiEvent("api,check-security,%u\n", index);
00442 #endif
00443 }
00444
00445
00446 void Logger::ApiNamedPropertyAccess(const char* tag,
00447 JSObject* holder,
00448 Object* name) {
00449 #ifdef ENABLE_LOGGING_AND_PROFILING
00450 ASSERT(name->IsString());
00451 if (logfile_ == NULL || !FLAG_log_api) return;
00452 String* class_name_obj = holder->class_name();
00453 SmartPointer<char> class_name =
00454 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
00455 SmartPointer<char> property_name =
00456 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
00457 Logger::ApiEvent("api,%s,\"%s\",\"%s\"\n", tag, *class_name, *property_name);
00458 #endif
00459 }
00460
00461 void Logger::ApiIndexedPropertyAccess(const char* tag,
00462 JSObject* holder,
00463 uint32_t index) {
00464 #ifdef ENABLE_LOGGING_AND_PROFILING
00465 if (logfile_ == NULL || !FLAG_log_api) return;
00466 String* class_name_obj = holder->class_name();
00467 SmartPointer<char> class_name =
00468 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
00469 Logger::ApiEvent("api,%s,\"%s\",%u\n", tag, *class_name, index);
00470 #endif
00471 }
00472
00473 void Logger::ApiObjectAccess(const char* tag, JSObject* object) {
00474 #ifdef ENABLE_LOGGING_AND_PROFILING
00475 if (logfile_ == NULL || !FLAG_log_api) return;
00476 String* class_name_obj = object->class_name();
00477 SmartPointer<char> class_name =
00478 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
00479 Logger::ApiEvent("api,%s,\"%s\"\n", tag, *class_name);
00480 #endif
00481 }
00482
00483
00484 void Logger::ApiEntryCall(const char* name) {
00485 #ifdef ENABLE_LOGGING_AND_PROFILING
00486 if (logfile_ == NULL || !FLAG_log_api) return;
00487 Logger::ApiEvent("api,%s\n", name);
00488 #endif
00489 }
00490
00491
00492 void Logger::NewEvent(const char* name, void* object, size_t size) {
00493 #ifdef ENABLE_LOGGING_AND_PROFILING
00494 if (logfile_ == NULL || !FLAG_log) return;
00495 ScopedLock sl(mutex_);
00496 fprintf(logfile_, "new,%s,0x%x,%u\n", name,
00497 reinterpret_cast<unsigned int>(object),
00498 static_cast<unsigned int>(size));
00499 #endif
00500 }
00501
00502
00503 void Logger::DeleteEvent(const char* name, void* object) {
00504 #ifdef ENABLE_LOGGING_AND_PROFILING
00505 if (logfile_ == NULL || !FLAG_log) return;
00506 ScopedLock sl(mutex_);
00507 fprintf(logfile_, "delete,%s,0x%x\n", name,
00508 reinterpret_cast<unsigned int>(object));
00509 #endif
00510 }
00511
00512
00513 void Logger::CodeCreateEvent(const char* tag, Code* code, const char* comment) {
00514 #ifdef ENABLE_LOGGING_AND_PROFILING
00515 if (logfile_ == NULL || !FLAG_log_code) return;
00516 ScopedLock sl(mutex_);
00517
00518 fprintf(logfile_, "code-creation,%s,0x%x,%d,\"", tag,
00519 reinterpret_cast<unsigned int>(code->address()),
00520 code->instruction_size());
00521 for (const char* p = comment; *p != '\0'; p++) {
00522 if (*p == '\"') fprintf(logfile_, "\\");
00523 fprintf(logfile_, "%c", *p);
00524 }
00525 fprintf(logfile_, "\"\n");
00526 #endif
00527 }
00528
00529
00530 void Logger::CodeCreateEvent(const char* tag, Code* code, String* name) {
00531 #ifdef ENABLE_LOGGING_AND_PROFILING
00532 if (logfile_ == NULL || !FLAG_log_code) return;
00533 ScopedLock sl(mutex_);
00534 SmartPointer<char> str =
00535 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
00536 fprintf(logfile_, "code-creation,%s,0x%x,%d,\"%s\"\n", tag,
00537 reinterpret_cast<unsigned int>(code->address()),
00538 code->instruction_size(), *str);
00539 #endif
00540 }
00541
00542
00543 void Logger::CodeCreateEvent(const char* tag, Code* code, int args_count) {
00544 #ifdef ENABLE_LOGGING_AND_PROFILING
00545 if (logfile_ == NULL || !FLAG_log_code) return;
00546 ScopedLock sl(mutex_);
00547
00548 fprintf(logfile_, "code-creation,%s,0x%x,%d,\"args_count: %d\"\n", tag,
00549 reinterpret_cast<unsigned int>(code->address()),
00550 code->instruction_size(),
00551 args_count);
00552 #endif
00553 }
00554
00555
00556 void Logger::CodeMoveEvent(Address from, Address to) {
00557 #ifdef ENABLE_LOGGING_AND_PROFILING
00558 if (logfile_ == NULL || !FLAG_log_code) return;
00559 ScopedLock sl(mutex_);
00560 fprintf(logfile_, "code-move,0x%x,0x%x\n",
00561 reinterpret_cast<unsigned int>(from),
00562 reinterpret_cast<unsigned int>(to));
00563 #endif
00564 }
00565
00566
00567 void Logger::CodeDeleteEvent(Address from) {
00568 #ifdef ENABLE_LOGGING_AND_PROFILING
00569 if (logfile_ == NULL || !FLAG_log_code) return;
00570 ScopedLock sl(mutex_);
00571 fprintf(logfile_, "code-delete,0x%x\n", reinterpret_cast<unsigned int>(from));
00572 #endif
00573 }
00574
00575
00576 void Logger::ResourceEvent(const char* name, const char* tag) {
00577 #ifdef ENABLE_LOGGING_AND_PROFILING
00578 if (logfile_ == NULL || !FLAG_log) return;
00579 ScopedLock sl(mutex_);
00580 fprintf(logfile_, "%s,%s,", name, tag);
00581
00582 uint32_t sec, usec;
00583 if (OS::GetUserTime(&sec, &usec) != -1) {
00584 fprintf(logfile_, "%d,%d,", sec, usec);
00585 }
00586 fprintf(logfile_, "%.0f", OS::TimeCurrentMillis());
00587
00588 fprintf(logfile_, "\n");
00589 #endif
00590 }
00591
00592
00593 void Logger::SuspectReadEvent(String* name, String* obj) {
00594 #ifdef ENABLE_LOGGING_AND_PROFILING
00595 if (logfile_ == NULL || !FLAG_log_suspect) return;
00596 ScopedLock sl(mutex_);
00597 fprintf(logfile_, "suspect-read,");
00598 obj->PrintOn(logfile_);
00599 fprintf(logfile_, ",\"");
00600 name->PrintOn(logfile_);
00601 fprintf(logfile_, "\"\n");
00602 #endif
00603 }
00604
00605
00606 void Logger::HeapSampleBeginEvent(const char* space, const char* kind) {
00607 #ifdef ENABLE_LOGGING_AND_PROFILING
00608 if (logfile_ == NULL || !FLAG_log_gc) return;
00609 ScopedLock sl(mutex_);
00610 fprintf(logfile_, "heap-sample-begin,\"%s\",\"%s\"\n", space, kind);
00611 #endif
00612 }
00613
00614
00615 void Logger::HeapSampleEndEvent(const char* space, const char* kind) {
00616 #ifdef ENABLE_LOGGING_AND_PROFILING
00617 if (logfile_ == NULL || !FLAG_log_gc) return;
00618 ScopedLock sl(mutex_);
00619 fprintf(logfile_, "heap-sample-end,\"%s\",\"%s\"\n", space, kind);
00620 #endif
00621 }
00622
00623
00624 void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) {
00625 #ifdef ENABLE_LOGGING_AND_PROFILING
00626 if (logfile_ == NULL || !FLAG_log_gc) return;
00627 ScopedLock sl(mutex_);
00628 fprintf(logfile_, "heap-sample-item,%s,%d,%d\n", type, number, bytes);
00629 #endif
00630 }
00631
00632
00633 void Logger::DebugTag(const char* call_site_tag) {
00634 #ifdef ENABLE_LOGGING_AND_PROFILING
00635 if (logfile_ == NULL || !FLAG_log) return;
00636 ScopedLock sl(mutex_);
00637 fprintf(logfile_, "debug-tag,%s\n", call_site_tag);
00638 #endif
00639 }
00640
00641
00642 void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) {
00643 #ifdef ENABLE_LOGGING_AND_PROFILING
00644 if (logfile_ == NULL || !FLAG_log) return;
00645 StringBuilder s(parameter.length() + 1);
00646 for (int i = 0; i < parameter.length(); ++i) {
00647 s.AddCharacter(static_cast<char>(parameter[i]));
00648 }
00649 char* parameter_string = s.Finalize();
00650 ScopedLock sl(mutex_);
00651 fprintf(logfile_,
00652 "debug-queue-event,%s,%15.3f,%s\n",
00653 event_type,
00654 OS::TimeCurrentMillis(),
00655 parameter_string);
00656 DeleteArray(parameter_string);
00657 #endif
00658 }
00659
00660
00661 #ifdef ENABLE_LOGGING_AND_PROFILING
00662 void Logger::TickEvent(TickSample* sample, bool overflow) {
00663 if (logfile_ == NULL || !FLAG_prof) return;
00664 ScopedLock sl(mutex_);
00665 fprintf(logfile_, "tick,0x%x,0x%x,%d", sample->pc, sample->sp,
00666 static_cast<int>(sample->state));
00667 if (overflow) fprintf(logfile_, ",overflow");
00668 fprintf(logfile_, "\n");
00669 }
00670 #endif
00671
00672
00673 bool Logger::Setup() {
00674 #ifdef ENABLE_LOGGING_AND_PROFILING
00675
00676 if (FLAG_log_all) {
00677 FLAG_log_api = true;
00678 FLAG_log_code = true;
00679 FLAG_log_gc = true;
00680 FLAG_log_suspect = true;
00681 FLAG_log_handles = true;
00682 FLAG_log_regexp = true;
00683 }
00684
00685
00686 if (FLAG_prof) FLAG_log_code = true;
00687
00688 bool open_log_file = FLAG_log || FLAG_log_api || FLAG_log_code
00689 || FLAG_log_gc || FLAG_log_handles || FLAG_log_suspect
00690 || FLAG_log_regexp;
00691
00692
00693 if (open_log_file) {
00694 if (strcmp(FLAG_logfile, "-") == 0) {
00695 logfile_ = stdout;
00696 } else if (strchr(FLAG_logfile, '%') != NULL) {
00697
00698
00699 HeapStringAllocator allocator;
00700 StringStream stream(&allocator);
00701 for (const char* p = FLAG_logfile; *p; p++) {
00702 if (*p == '%') {
00703 p++;
00704 switch (*p) {
00705 case '\0':
00706
00707
00708 p--;
00709 break;
00710 case 't': {
00711
00712 uint32_t time = static_cast<uint32_t>(OS::TimeCurrentMillis());
00713 stream.Add("%u", time);
00714 break;
00715 }
00716 case '%':
00717
00718 stream.Put('%');
00719 break;
00720 default:
00721
00722 stream.Put('%');
00723 stream.Put(*p);
00724 break;
00725 }
00726 } else {
00727 stream.Put(*p);
00728 }
00729 }
00730 SmartPointer<char> expanded = stream.ToCString();
00731 logfile_ = OS::FOpen(*expanded, "w");
00732 } else {
00733 logfile_ = OS::FOpen(FLAG_logfile, "w");
00734 }
00735 mutex_ = OS::CreateMutex();
00736 }
00737
00738 current_state_ = new VMState(OTHER);
00739
00740 ticker_ = new Ticker(10);
00741
00742 if (FLAG_sliding_state_window && sliding_state_window_ == NULL) {
00743 sliding_state_window_ = new SlidingStateWindow();
00744 }
00745
00746 if (FLAG_prof) {
00747 profiler_ = new Profiler();
00748 profiler_->Engage();
00749 }
00750
00751 return true;
00752
00753 #else
00754 return false;
00755 #endif
00756 }
00757
00758
00759 void Logger::TearDown() {
00760 #ifdef ENABLE_LOGGING_AND_PROFILING
00761
00762 if (profiler_ != NULL) {
00763 profiler_->Disengage();
00764 delete profiler_;
00765 profiler_ = NULL;
00766 }
00767
00768
00769 while (current_state_) delete current_state_;
00770 delete sliding_state_window_;
00771
00772 delete ticker_;
00773
00774 if (logfile_ != NULL) {
00775 fclose(logfile_);
00776 logfile_ = NULL;
00777 delete mutex_;
00778 mutex_ = NULL;
00779 }
00780 #endif
00781 }
00782
00783
00784 void Logger::EnableSlidingStateWindow() {
00785 #ifdef ENABLE_LOGGING_AND_PROFILING
00786
00787
00788
00789
00790 if (ticker_ == NULL) {
00791 FLAG_sliding_state_window = true;
00792 return;
00793 }
00794
00795
00796 if (sliding_state_window_ == NULL) {
00797 sliding_state_window_ = new SlidingStateWindow();
00798 }
00799 #endif
00800 }
00801
00802
00803
00804
00805
00806
00807
00808 #ifdef ENABLE_LOGGING_AND_PROFILING
00809 static const char* StateToString(StateTag state) {
00810 switch (state) {
00811 case GC:
00812 return "GC";
00813 case COMPILER:
00814 return "COMPILER";
00815 case OTHER:
00816 return "OTHER";
00817 default:
00818 UNREACHABLE();
00819 return NULL;
00820 }
00821 }
00822
00823 VMState::VMState(StateTag state) {
00824 state_ = state;
00825 previous_ = Logger::current_state_;
00826 Logger::current_state_ = this;
00827
00828 if (FLAG_log_state_changes) {
00829 LOG(StringEvent("Entering", StateToString(state_)));
00830 if (previous_) {
00831 LOG(StringEvent("From", StateToString(previous_->state_)));
00832 }
00833 }
00834 }
00835
00836
00837 VMState::~VMState() {
00838 Logger::current_state_ = previous_;
00839
00840 if (FLAG_log_state_changes) {
00841 LOG(StringEvent("Leaving", StateToString(state_)));
00842 if (previous_) {
00843 LOG(StringEvent("To", StateToString(previous_->state_)));
00844 }
00845 }
00846 }
00847 #endif
00848
00849 } }