JSC_enableProfiler=true should also cause JSGlobalData to save the profiler output somewhere
https://bugs.webkit.org/show_bug.cgi?id=113144
Source/JavaScriptCore:
Reviewed by Geoffrey Garen.
Added the ability to save profiler output with JSC_enableProfiler=true. It will save it
to the current directory, or JSC_PROFILER_PATH if the latter was specified.
This works by saving the Profiler::Database either when it is destroyed or atexit(),
whichever happens first.
This allows use of the profiler from any WebKit client.
* jsc.cpp:
(jscmain):
* profiler/ProfilerDatabase.cpp:
(Profiler):
(JSC::Profiler::Database::Database):
(JSC::Profiler::Database::~Database):
(JSC::Profiler::Database::registerToSaveAtExit):
(JSC::Profiler::Database::addDatabaseToAtExit):
(JSC::Profiler::Database::removeDatabaseFromAtExit):
(JSC::Profiler::Database::performAtExitSave):
(JSC::Profiler::Database::removeFirstAtExitDatabase):
(JSC::Profiler::Database::atExitCallback):
* profiler/ProfilerDatabase.h:
(JSC::Profiler::Database::databaseID):
(Database):
* runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::JSGlobalData):
Source/WTF:
Reviewed by Geoffrey Garen.
I got tired of the fact that getpid(2) is not a syscall on Windows (unless you do
_getpid() I believe), so I wrote a header that abstracts it. I also changed existing
code that uses getpid() to use WTF::getCurrentProcessID().
* GNUmakefile.list.am:
* WTF.gypi:
* WTF.pro:
* WTF.vcproj/WTF.vcproj:
* WTF.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/MetaAllocator.cpp:
(WTF::MetaAllocator::dumpProfile):
* wtf/ProcessID.h: Added.
(WTF):
(WTF::getCurrentProcessID):
* wtf/text/StringImpl.cpp:
(WTF::StringStats::printStats):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@146932 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp b/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp
index 3a0a752..acc9531 100644
--- a/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,13 +33,25 @@
namespace JSC { namespace Profiler {
+static volatile int databaseCounter;
+static SpinLock registrationLock;
+static int didRegisterAtExit;
+static Database* firstDatabase;
+
Database::Database(JSGlobalData& globalData)
- : m_globalData(globalData)
+ : m_databaseID(atomicIncrement(&databaseCounter))
+ , m_globalData(globalData)
+ , m_shouldSaveAtExit(false)
+ , m_nextRegisteredDatabase(0)
{
}
Database::~Database()
{
+ if (m_shouldSaveAtExit) {
+ removeDatabaseFromAtExit();
+ performAtExitSave();
+ }
}
Bytecodes* Database::ensureBytecodesFor(CodeBlock* codeBlock)
@@ -110,5 +122,62 @@
return true;
}
+void Database::registerToSaveAtExit(const char* filename)
+{
+ m_atExitSaveFilename = filename;
+
+ if (m_shouldSaveAtExit)
+ return;
+
+ addDatabaseToAtExit();
+ m_shouldSaveAtExit = true;
+}
+
+void Database::addDatabaseToAtExit()
+{
+ if (atomicIncrement(&didRegisterAtExit) == 1)
+ atexit(atExitCallback);
+
+ TCMalloc_SpinLockHolder holder(®istrationLock);
+ m_nextRegisteredDatabase = firstDatabase;
+ firstDatabase = this;
+}
+
+void Database::removeDatabaseFromAtExit()
+{
+ TCMalloc_SpinLockHolder holder(®istrationLock);
+ for (Database** current = &firstDatabase; *current; current = &(*current)->m_nextRegisteredDatabase) {
+ if (*current != this)
+ continue;
+ *current = m_nextRegisteredDatabase;
+ m_nextRegisteredDatabase = 0;
+ m_shouldSaveAtExit = false;
+ break;
+ }
+}
+
+void Database::performAtExitSave() const
+{
+ save(m_atExitSaveFilename.data());
+}
+
+Database* Database::removeFirstAtExitDatabase()
+{
+ TCMalloc_SpinLockHolder holder(®istrationLock);
+ Database* result = firstDatabase;
+ if (result) {
+ firstDatabase = result->m_nextRegisteredDatabase;
+ result->m_nextRegisteredDatabase = 0;
+ result->m_shouldSaveAtExit = false;
+ }
+ return result;
+}
+
+void Database::atExitCallback()
+{
+ while (Database* database = removeFirstAtExitDatabase())
+ database->performAtExitSave();
+}
+
} } // namespace JSC::Profiler