| Index: runtime/bin/vmstats_impl.cc
|
| ===================================================================
|
| --- runtime/bin/vmstats_impl.cc (revision 21583)
|
| +++ runtime/bin/vmstats_impl.cc (working copy)
|
| @@ -27,13 +27,25 @@
|
| dart::Mutex* VmStatusService::mutex_;
|
|
|
|
|
| -void VmStats::Start(int port, const char* root_dir) {
|
| +void VmStats::Start(int port, const char* root_dir, bool verbose) {
|
| if (instance_ != NULL) {
|
| FATAL("VmStats already started.");
|
| }
|
| - instance_ = new VmStats();
|
| + instance_ = new VmStats(verbose);
|
| instance_monitor_ = new dart::Monitor();
|
| + Initialize();
|
| VmStatusService::InitOnce();
|
| +
|
| + if (port >= 0) {
|
| + StartServer(port, root_dir);
|
| + }
|
| +}
|
| +
|
| +
|
| +void VmStats::StartServer(int port, const char* root_dir) {
|
| + ASSERT(port >= 0);
|
| + ASSERT(instance_ != NULL);
|
| + ASSERT(instance_monitor_ != NULL);
|
| Socket::Initialize();
|
|
|
| if (root_dir != NULL) {
|
| @@ -68,7 +80,6 @@
|
| }
|
| }
|
|
|
| -
|
| void VmStats::Stop() {
|
| ASSERT(instance_ != NULL);
|
| MonitorLocker ml(instance_monitor_);
|
| @@ -87,18 +98,14 @@
|
|
|
| void VmStats::AddIsolate(IsolateData* isolate_data,
|
| Dart_Isolate isolate) {
|
| - if (instance_ != NULL) {
|
| - MonitorLocker ml(instance_monitor_);
|
| - instance_->isolate_table_[isolate_data] = isolate;
|
| - }
|
| + MonitorLocker ml(instance_monitor_);
|
| + instance_->isolate_table_[isolate_data] = isolate;
|
| }
|
|
|
|
|
| void VmStats::RemoveIsolate(IsolateData* isolate_data) {
|
| - if (instance_ != NULL) {
|
| - MonitorLocker ml(instance_monitor_);
|
| - instance_->isolate_table_.erase(isolate_data);
|
| - }
|
| + MonitorLocker ml(instance_monitor_);
|
| + instance_->isolate_table_.erase(isolate_data);
|
| }
|
|
|
|
|
| @@ -234,7 +241,9 @@
|
| }
|
| char* url = strdup(&buffer[4]);
|
|
|
| - Log::Print("vmstats: %s requested\n", url);
|
| + if (instance_->verbose_) {
|
| + Log::Print("vmstats: %s requested\n", url);
|
| + }
|
| char* content = NULL;
|
|
|
| // Check for VmStats-specific URLs.
|
| @@ -314,10 +323,10 @@
|
| reinterpret_cast<intptr_t>(isolate));
|
| char* status = VmStatusService::GetVmStatus(request);
|
| if (status != NULL) {
|
| - text.AddString(status);
|
| if (!first) {
|
| text.AddString(",\n");
|
| }
|
| + text.AddString(status);
|
| first = false;
|
| free(status);
|
| }
|
| @@ -327,6 +336,94 @@
|
| }
|
|
|
|
|
| +// Advance the scanner to the value token of a specified name-value pair.
|
| +void SeekNamedValue(const char* name, dart::JSONScanner* scanner) {
|
| + while (!scanner->EOM()) {
|
| + scanner->Scan();
|
| + if (scanner->IsStringLiteral(name)) {
|
| + scanner->Scan();
|
| + ASSERT(scanner->CurrentToken() == dart::JSONScanner::TokenColon);
|
| + scanner->Scan();
|
| + return;
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +// Windows doesn't have strndup(), so this is a simple, private version.
|
| +static char* StrNDup(const char* s, uword len) {
|
| + if (strlen(s) < len) {
|
| + len = strlen(s);
|
| + }
|
| + char* result = reinterpret_cast<char*>(malloc(len + 1));
|
| + memmove(result, s, len);
|
| + result[len + 1] = '\0';
|
| + return result;
|
| +}
|
| +
|
| +
|
| +void VmStats::DumpStackThread(uword unused) {
|
| + Log::Print("Isolate dump:\n");
|
| + IsolateTable::iterator itr;
|
| + MonitorLocker ml(instance_monitor_);
|
| + for (itr = instance_->isolate_table_.begin();
|
| + itr != instance_->isolate_table_.end(); ++itr) {
|
| + Dart_Isolate isolate = itr->second;
|
| +
|
| + // Print isolate name and details.
|
| + static char buffer[512];
|
| + snprintf(buffer, sizeof(buffer),
|
| + "/isolate/0x%"Px, reinterpret_cast<intptr_t>(isolate));
|
| + char* isolate_details = VmStatusService::GetVmStatus(buffer);
|
| + if (isolate_details != NULL) {
|
| + dart::JSONScanner scanner(isolate_details);
|
| + SeekNamedValue("name", &scanner);
|
| + char* name = StrNDup(scanner.TokenChars(), scanner.TokenLen());
|
| + SeekNamedValue("port", &scanner);
|
| + char* port = StrNDup(scanner.TokenChars(), scanner.TokenLen());
|
| + Log::Print("\"%s\" port=%s\n", name, port);
|
| + free(isolate_details);
|
| + free(port);
|
| + free(name);
|
| + }
|
| +
|
| + // Print stack trace.
|
| + snprintf(buffer, sizeof(buffer),
|
| + "/isolate/0x%"Px"/stacktrace",
|
| + reinterpret_cast<intptr_t>(isolate));
|
| + char* trace = VmStatusService::GetVmStatus(buffer);
|
| + if (trace != NULL) {
|
| + dart::JSONScanner scanner(trace);
|
| + while (true) {
|
| + SeekNamedValue("url", &scanner);
|
| + if (scanner.CurrentToken() == dart::JSONScanner::TokenEOM) {
|
| + break;
|
| + }
|
| + char* url = StrNDup(scanner.TokenChars(), scanner.TokenLen());
|
| + SeekNamedValue("line", &scanner);
|
| + char* line = StrNDup(scanner.TokenChars(), scanner.TokenLen());
|
| + SeekNamedValue("function", &scanner);
|
| + char* function = StrNDup(scanner.TokenChars(), scanner.TokenLen());
|
| + Log::Print(" at %s(%s:%s)\n", function, url, line);
|
| + free(url);
|
| + free(line);
|
| + free(function);
|
| + }
|
| + free(trace);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +void VmStats::DumpStack() {
|
| + int err = dart::Thread::Start(DumpStackThread, 0);
|
| + if (err != 0) {
|
| + Log::PrintErr("Failed starting VmStats stackdump thread: %d\n", err);
|
| + Shutdown();
|
| + }
|
| +}
|
| +
|
| +
|
| // Global static pointer used to ensure a single instance of the class.
|
| VmStatusService* VmStatusService::instance_ = NULL;
|
|
|
| @@ -346,6 +443,8 @@
|
|
|
|
|
| int VmStatusService::RegisterPlugin(Dart_VmStatusCallback callback) {
|
| + ASSERT(VmStatusService::instance_ != NULL);
|
| + ASSERT(VmStatusService::mutex_ != NULL);
|
| MutexLocker ml(mutex_);
|
| if (callback == NULL) {
|
| return -1;
|
| @@ -362,6 +461,7 @@
|
|
|
|
|
| char* VmStatusService::GetVmStatus(const char* request) {
|
| + ASSERT(VmStatusService::instance_ != NULL);
|
| VmStatusPlugin* plugin = instance_->registered_plugin_list_;
|
| while (plugin != NULL) {
|
| char* result = (plugin->callback())(request);
|
|
|