summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/profiler
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2015-10-15 09:45:50 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2015-10-15 09:45:50 +0000
commite15dd966d523731101f70ccf768bba12435a0208 (patch)
treeae9cb828a24ded2585a41af3f21411523b47897d /Source/JavaScriptCore/profiler
downloadWebKitGtk-tarball-e15dd966d523731101f70ccf768bba12435a0208.tar.gz
webkitgtk-2.10.2webkitgtk-2.10.2
Diffstat (limited to 'Source/JavaScriptCore/profiler')
-rw-r--r--Source/JavaScriptCore/profiler/CallIdentifier.h112
-rw-r--r--Source/JavaScriptCore/profiler/LegacyProfiler.cpp208
-rw-r--r--Source/JavaScriptCore/profiler/LegacyProfiler.h77
-rw-r--r--Source/JavaScriptCore/profiler/Profile.cpp95
-rw-r--r--Source/JavaScriptCore/profiler/Profile.h66
-rw-r--r--Source/JavaScriptCore/profiler/ProfileGenerator.cpp254
-rw-r--r--Source/JavaScriptCore/profiler/ProfileGenerator.h84
-rw-r--r--Source/JavaScriptCore/profiler/ProfileNode.cpp199
-rw-r--r--Source/JavaScriptCore/profiler/ProfileNode.h194
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerBytecode.cpp45
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerBytecode.h65
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp92
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.h65
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerBytecodes.cpp69
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerBytecodes.h63
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerCompilation.cpp156
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerCompilation.h98
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerCompilationKind.cpp58
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerCompilationKind.h49
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerCompiledBytecode.cpp56
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerCompiledBytecode.h55
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerDatabase.cpp183
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerDatabase.h94
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerExecutionCounter.h50
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerJettisonReason.cpp73
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerJettisonReason.h54
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerOSRExit.cpp60
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerOSRExit.h61
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerOSRExitSite.cpp46
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerOSRExitSite.h52
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerOrigin.cpp57
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerOrigin.h120
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerOriginStack.cpp111
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerOriginStack.h102
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.cpp56
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.h51
36 files changed, 3330 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/profiler/CallIdentifier.h b/Source/JavaScriptCore/profiler/CallIdentifier.h
new file mode 100644
index 000000000..691fc6250
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/CallIdentifier.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2008, 2014 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef CallIdentifier_h
+#define CallIdentifier_h
+
+#include <wtf/text/CString.h>
+#include <wtf/text/StringHash.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+
+ struct CallIdentifier {
+ WTF_MAKE_FAST_ALLOCATED;
+ public:
+ CallIdentifier()
+ : m_lineNumber(0)
+ , m_columnNumber(0)
+ {
+ }
+
+ CallIdentifier(const String& functionName, const String& url, unsigned lineNumber, unsigned columnNumber)
+ : m_functionName(functionName)
+ , m_url(!url.isNull() ? url : "")
+ , m_lineNumber(lineNumber)
+ , m_columnNumber(columnNumber)
+ {
+ }
+
+ const String& functionName() const { return m_functionName; }
+
+ const String& url() const { return m_url; }
+ unsigned lineNumber() const { return m_lineNumber; }
+ unsigned columnNumber() const { return m_columnNumber; }
+
+ inline bool operator==(const CallIdentifier& other) const { return other.m_lineNumber == m_lineNumber && other.m_columnNumber == m_columnNumber && other.m_functionName == m_functionName && other.m_url == m_url; }
+ inline bool operator!=(const CallIdentifier& other) const { return !(*this == other); }
+
+ struct Hash {
+ static unsigned hash(const CallIdentifier& key)
+ {
+ unsigned hashCodes[4] = {
+ key.m_functionName.impl()->hash(),
+ key.m_url.impl()->hash(),
+ key.m_lineNumber,
+ key.m_columnNumber
+ };
+ return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
+ }
+
+ static bool equal(const CallIdentifier& a, const CallIdentifier& b) { return a == b; }
+ static const bool safeToCompareToEmptyOrDeleted = true;
+ };
+
+ unsigned hash() const { return Hash::hash(*this); }
+
+#ifndef NDEBUG
+ operator const char*() const { return c_str(); }
+ const char* c_str() const { return m_functionName.utf8().data(); }
+#endif
+
+ private:
+ String m_functionName;
+ String m_url;
+ unsigned m_lineNumber;
+ unsigned m_columnNumber;
+ };
+
+} // namespace JSC
+
+namespace WTF {
+
+ template<> struct DefaultHash<JSC::CallIdentifier> { typedef JSC::CallIdentifier::Hash Hash; };
+
+ template<> struct HashTraits<JSC::CallIdentifier> : GenericHashTraits<JSC::CallIdentifier> {
+ static void constructDeletedValue(JSC::CallIdentifier& slot)
+ {
+ new (NotNull, &slot) JSC::CallIdentifier(String(), String(), std::numeric_limits<unsigned>::max(), std::numeric_limits<unsigned>::max());
+ }
+
+ static bool isDeletedValue(const JSC::CallIdentifier& value)
+ {
+ return value.functionName().isNull() && value.url().isNull() && value.lineNumber() == std::numeric_limits<unsigned>::max() && value.columnNumber() == std::numeric_limits<unsigned>::max();
+ }
+ };
+
+} // namespace WTF
+
+#endif // CallIdentifier_h
diff --git a/Source/JavaScriptCore/profiler/LegacyProfiler.cpp b/Source/JavaScriptCore/profiler/LegacyProfiler.cpp
new file mode 100644
index 000000000..787d362dc
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/LegacyProfiler.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2008, 2012, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LegacyProfiler.h"
+
+#include "CallFrame.h"
+#include "CodeBlock.h"
+#include "CommonIdentifiers.h"
+#include "InternalFunction.h"
+#include "JSFunction.h"
+#include "JSGlobalObject.h"
+#include "Nodes.h"
+#include "JSCInlines.h"
+#include "Profile.h"
+#include "ProfileGenerator.h"
+#include "ProfileNode.h"
+
+namespace JSC {
+
+static const char* GlobalCodeExecution = "(program)";
+static const char* AnonymousFunction = "(anonymous function)";
+static unsigned ProfilesUID = 0;
+
+static CallIdentifier createCallIdentifierFromFunctionImp(ExecState*, JSObject*, const String& defaultSourceURL, unsigned defaultLineNumber, unsigned defaultColumnNumber);
+
+LegacyProfiler* LegacyProfiler::s_sharedLegacyProfiler = nullptr;
+
+LegacyProfiler* LegacyProfiler::profiler()
+{
+ if (!s_sharedLegacyProfiler)
+ s_sharedLegacyProfiler = new LegacyProfiler();
+ return s_sharedLegacyProfiler;
+}
+
+void LegacyProfiler::startProfiling(ExecState* exec, const String& title, PassRefPtr<Stopwatch> stopwatch)
+{
+ if (!exec)
+ return;
+
+ // Check if we currently have a Profile for this global ExecState and title.
+ // If so return early and don't create a new Profile.
+ JSGlobalObject* origin = exec->lexicalGlobalObject();
+
+ for (size_t i = 0; i < m_currentProfiles.size(); ++i) {
+ ProfileGenerator* profileGenerator = m_currentProfiles[i].get();
+ if (profileGenerator->origin() == origin && profileGenerator->title() == title)
+ return;
+ }
+
+ exec->vm().setEnabledProfiler(this);
+ RefPtr<ProfileGenerator> profileGenerator = ProfileGenerator::create(exec, title, ++ProfilesUID, stopwatch);
+ m_currentProfiles.append(profileGenerator);
+}
+
+RefPtr<Profile> LegacyProfiler::stopProfiling(ExecState* exec, const String& title)
+{
+ if (!exec)
+ return nullptr;
+
+ JSGlobalObject* origin = exec->lexicalGlobalObject();
+ for (ptrdiff_t i = m_currentProfiles.size() - 1; i >= 0; --i) {
+ ProfileGenerator* profileGenerator = m_currentProfiles[i].get();
+ if (profileGenerator->origin() == origin && (title.isNull() || profileGenerator->title() == title)) {
+ profileGenerator->stopProfiling();
+ RefPtr<Profile> returnProfile = profileGenerator->profile();
+
+ m_currentProfiles.remove(i);
+ if (!m_currentProfiles.size())
+ exec->vm().setEnabledProfiler(nullptr);
+
+ return returnProfile;
+ }
+ }
+
+ return nullptr;
+}
+
+void LegacyProfiler::stopProfiling(JSGlobalObject* origin)
+{
+ for (ptrdiff_t i = m_currentProfiles.size() - 1; i >= 0; --i) {
+ ProfileGenerator* profileGenerator = m_currentProfiles[i].get();
+ if (profileGenerator->origin() == origin) {
+ profileGenerator->stopProfiling();
+ m_currentProfiles.remove(i);
+ if (!m_currentProfiles.size())
+ origin->vm().setEnabledProfiler(nullptr);
+ }
+ }
+}
+
+static inline void callFunctionForProfilesWithGroup(std::function<void(ProfileGenerator*)> callback, const Vector<RefPtr<ProfileGenerator>>& profiles, unsigned targetProfileGroup)
+{
+ for (const RefPtr<ProfileGenerator>& profile : profiles) {
+ if (profile->profileGroup() == targetProfileGroup || !profile->origin())
+ callback(profile.get());
+ }
+}
+
+void LegacyProfiler::suspendProfiling(JSC::ExecState* exec)
+{
+ if (!exec)
+ return;
+
+ callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::setIsSuspended, std::placeholders::_1, true), m_currentProfiles, exec->lexicalGlobalObject()->profileGroup());
+}
+
+void LegacyProfiler::unsuspendProfiling(JSC::ExecState* exec)
+{
+ if (!exec)
+ return;
+
+ callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::setIsSuspended, std::placeholders::_1, false), m_currentProfiles, exec->lexicalGlobalObject()->profileGroup());
+}
+
+void LegacyProfiler::willExecute(ExecState* callerCallFrame, JSValue function)
+{
+ ASSERT(!m_currentProfiles.isEmpty());
+
+ CallIdentifier callIdentifier = createCallIdentifier(callerCallFrame, function, StringImpl::empty(), 0, 0);
+
+ callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::willExecute, std::placeholders::_1, callerCallFrame, callIdentifier), m_currentProfiles, callerCallFrame->lexicalGlobalObject()->profileGroup());
+}
+
+void LegacyProfiler::willExecute(ExecState* callerCallFrame, const String& sourceURL, unsigned startingLineNumber, unsigned startingColumnNumber)
+{
+ ASSERT(!m_currentProfiles.isEmpty());
+
+ CallIdentifier callIdentifier = createCallIdentifier(callerCallFrame, JSValue(), sourceURL, startingLineNumber, startingColumnNumber);
+
+ callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::willExecute, std::placeholders::_1, callerCallFrame, callIdentifier), m_currentProfiles, callerCallFrame->lexicalGlobalObject()->profileGroup());
+}
+
+void LegacyProfiler::didExecute(ExecState* callerCallFrame, JSValue function)
+{
+ ASSERT(!m_currentProfiles.isEmpty());
+
+ CallIdentifier callIdentifier = createCallIdentifier(callerCallFrame, function, StringImpl::empty(), 0, 0);
+
+ callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::didExecute, std::placeholders::_1, callerCallFrame, callIdentifier), m_currentProfiles, callerCallFrame->lexicalGlobalObject()->profileGroup());
+}
+
+void LegacyProfiler::didExecute(ExecState* callerCallFrame, const String& sourceURL, unsigned startingLineNumber, unsigned startingColumnNumber)
+{
+ ASSERT(!m_currentProfiles.isEmpty());
+
+ CallIdentifier callIdentifier = createCallIdentifier(callerCallFrame, JSValue(), sourceURL, startingLineNumber, startingColumnNumber);
+
+ callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::didExecute, std::placeholders::_1, callerCallFrame, callIdentifier), m_currentProfiles, callerCallFrame->lexicalGlobalObject()->profileGroup());
+}
+
+void LegacyProfiler::exceptionUnwind(ExecState* handlerCallFrame)
+{
+ ASSERT(!m_currentProfiles.isEmpty());
+
+ CallIdentifier callIdentifier = createCallIdentifier(handlerCallFrame, JSValue(), StringImpl::empty(), 0, 0);
+
+ callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::exceptionUnwind, std::placeholders::_1, handlerCallFrame, callIdentifier), m_currentProfiles, handlerCallFrame->lexicalGlobalObject()->profileGroup());
+}
+
+CallIdentifier LegacyProfiler::createCallIdentifier(ExecState* exec, JSValue functionValue, const String& defaultSourceURL, unsigned defaultLineNumber, unsigned defaultColumnNumber)
+{
+ if (!functionValue)
+ return CallIdentifier(ASCIILiteral(GlobalCodeExecution), defaultSourceURL, defaultLineNumber, defaultColumnNumber);
+ if (!functionValue.isObject())
+ return CallIdentifier(ASCIILiteral("(unknown)"), defaultSourceURL, defaultLineNumber, defaultColumnNumber);
+ if (asObject(functionValue)->inherits(JSFunction::info()) || asObject(functionValue)->inherits(InternalFunction::info()))
+ return createCallIdentifierFromFunctionImp(exec, asObject(functionValue), defaultSourceURL, defaultLineNumber, defaultColumnNumber);
+ if (asObject(functionValue)->inherits(JSCallee::info()))
+ return CallIdentifier(ASCIILiteral(GlobalCodeExecution), defaultSourceURL, defaultLineNumber, defaultColumnNumber);
+ return CallIdentifier(asObject(functionValue)->methodTable()->className(asObject(functionValue)), defaultSourceURL, defaultLineNumber, defaultColumnNumber);
+}
+
+CallIdentifier createCallIdentifierFromFunctionImp(ExecState* exec, JSObject* function, const String& defaultSourceURL, unsigned defaultLineNumber, unsigned defaultColumnNumber)
+{
+ const String& name = getCalculatedDisplayName(exec, function);
+ JSFunction* jsFunction = jsDynamicCast<JSFunction*>(function);
+ if (jsFunction && !jsFunction->isHostOrBuiltinFunction())
+ return CallIdentifier(name.isEmpty() ? ASCIILiteral(AnonymousFunction) : name, jsFunction->jsExecutable()->sourceURL(), jsFunction->jsExecutable()->firstLine(), jsFunction->jsExecutable()->startColumn());
+ return CallIdentifier(name.isEmpty() ? ASCIILiteral(AnonymousFunction) : name, defaultSourceURL, defaultLineNumber, defaultColumnNumber);
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/profiler/LegacyProfiler.h b/Source/JavaScriptCore/profiler/LegacyProfiler.h
new file mode 100644
index 000000000..af0ab41e2
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/LegacyProfiler.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2008, 2012, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LegacyProfiler_h
+#define LegacyProfiler_h
+
+#include "Profile.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Stopwatch.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class ExecState;
+class JSGlobalObject;
+class JSObject;
+class JSValue;
+class ProfileGenerator;
+struct CallIdentifier;
+
+class LegacyProfiler {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ JS_EXPORT_PRIVATE static LegacyProfiler* profiler();
+ static CallIdentifier createCallIdentifier(ExecState*, JSValue, const WTF::String& sourceURL, unsigned defaultLineNumber, unsigned defaultColumnNumber);
+
+ JS_EXPORT_PRIVATE void startProfiling(ExecState*, const WTF::String& title, PassRefPtr<Stopwatch>);
+ JS_EXPORT_PRIVATE RefPtr<Profile> stopProfiling(ExecState*, const WTF::String& title);
+ void stopProfiling(JSGlobalObject*);
+
+ // Used to ignore profile node subtrees rooted at InjectedScript calls.
+ JS_EXPORT_PRIVATE void suspendProfiling(ExecState*);
+ JS_EXPORT_PRIVATE void unsuspendProfiling(ExecState*);
+
+ void willExecute(ExecState* callerCallFrame, JSValue function);
+ void willExecute(ExecState* callerCallFrame, const WTF::String& sourceURL, unsigned startingLineNumber, unsigned startingColumnNumber);
+ void didExecute(ExecState* callerCallFrame, JSValue function);
+ void didExecute(ExecState* callerCallFrame, const WTF::String& sourceURL, unsigned startingLineNumber, unsigned startingColumnNumber);
+
+ void exceptionUnwind(ExecState* handlerCallFrame);
+
+ const Vector<RefPtr<ProfileGenerator>>& currentProfiles() { return m_currentProfiles; };
+
+private:
+ Vector<RefPtr<ProfileGenerator>> m_currentProfiles;
+ static LegacyProfiler* s_sharedLegacyProfiler;
+};
+
+} // namespace JSC
+
+#endif // LegacyProfiler_h
diff --git a/Source/JavaScriptCore/profiler/Profile.cpp b/Source/JavaScriptCore/profiler/Profile.cpp
new file mode 100644
index 000000000..f3d450ab2
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/Profile.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2008, 2014 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Profile.h"
+
+#include "ProfileNode.h"
+#include <wtf/DataLog.h>
+
+namespace JSC {
+
+Ref<Profile> Profile::create(const String& title, unsigned uid, double startTime)
+{
+ return adoptRef(*new Profile(title, uid, startTime));
+}
+
+Profile::Profile(const String& title, unsigned uid, double startTime)
+ : m_title(title)
+ , m_uid(uid)
+{
+ // FIXME: When multi-threading is supported this will be a vector and calls
+ // into the profiler will need to know which thread it is executing on.
+ m_rootNode = ProfileNode::create(nullptr, CallIdentifier(ASCIILiteral("Thread_1"), String(), 0, 0), nullptr);
+ m_rootNode->appendCall(ProfileNode::Call(startTime));
+}
+
+Profile::~Profile()
+{
+}
+
+#ifndef NDEBUG
+void Profile::debugPrint()
+{
+ CalculateProfileSubtreeDataFunctor functor;
+ m_rootNode->forEachNodePostorder(functor);
+ ProfileNode::ProfileSubtreeData data = functor.returnValue();
+
+ dataLogF("Call graph:\n");
+ m_rootNode->debugPrintRecursively(0, data);
+}
+
+typedef WTF::KeyValuePair<FunctionCallHashCount::ValueType, unsigned> NameCountPair;
+
+static inline bool functionNameCountPairComparator(const NameCountPair& a, const NameCountPair& b)
+{
+ return a.value > b.value;
+}
+
+void Profile::debugPrintSampleStyle()
+{
+ typedef Vector<NameCountPair> NameCountPairVector;
+
+ CalculateProfileSubtreeDataFunctor functor;
+ m_rootNode->forEachNodePostorder(functor);
+ ProfileNode::ProfileSubtreeData data = functor.returnValue();
+
+ FunctionCallHashCount countedFunctions;
+ dataLogF("Call graph:\n");
+ m_rootNode->debugPrintSampleStyleRecursively(0, countedFunctions, data);
+
+ dataLogF("\nTotal number in stack:\n");
+ NameCountPairVector sortedFunctions(countedFunctions.size());
+ copyToVector(countedFunctions, sortedFunctions);
+
+ std::sort(sortedFunctions.begin(), sortedFunctions.end(), functionNameCountPairComparator);
+ for (NameCountPairVector::iterator it = sortedFunctions.begin(); it != sortedFunctions.end(); ++it)
+ dataLogF(" %-12d%s\n", (*it).value, String((*it).key).utf8().data());
+
+ dataLogF("\nSort by top of stack, same collapsed (when >= 5):\n");
+}
+#endif
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/profiler/Profile.h b/Source/JavaScriptCore/profiler/Profile.h
new file mode 100644
index 000000000..41cb670ca
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/Profile.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2008, 2014 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Profile_h
+#define Profile_h
+
+#include "ProfileNode.h"
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+
+class JS_EXPORT_PRIVATE Profile : public RefCounted<Profile> {
+public:
+ static Ref<Profile> create(const String& title, unsigned uid, double);
+ virtual ~Profile();
+
+ const String& title() const { return m_title; }
+ unsigned uid() const { return m_uid; }
+
+ ProfileNode* rootNode() const { return m_rootNode.get(); }
+ void setRootNode(PassRefPtr<ProfileNode> rootNode) { m_rootNode = rootNode; }
+
+#ifndef NDEBUG
+ void debugPrint();
+ void debugPrintSampleStyle();
+#endif
+
+protected:
+ Profile(const String& title, unsigned uid, double startTime);
+
+private:
+ void removeProfileStart();
+ void removeProfileEnd();
+
+ String m_title;
+ RefPtr<ProfileNode> m_rootNode;
+ unsigned m_uid;
+};
+
+} // namespace JSC
+
+#endif // Profile_h
diff --git a/Source/JavaScriptCore/profiler/ProfileGenerator.cpp b/Source/JavaScriptCore/profiler/ProfileGenerator.cpp
new file mode 100644
index 000000000..f70e4a3f6
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfileGenerator.cpp
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2008, 2014 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfileGenerator.h"
+
+#include "CallFrame.h"
+#include "CodeBlock.h"
+#include "JSGlobalObject.h"
+#include "JSStringRef.h"
+#include "JSFunction.h"
+#include "LegacyProfiler.h"
+#include "JSCInlines.h"
+#include "Profile.h"
+#include "StackVisitor.h"
+#include "Tracing.h"
+
+namespace JSC {
+
+Ref<ProfileGenerator> ProfileGenerator::create(ExecState* exec, const String& title, unsigned uid, PassRefPtr<Stopwatch> stopwatch)
+{
+ return adoptRef(*new ProfileGenerator(exec, title, uid, stopwatch));
+}
+
+ProfileGenerator::ProfileGenerator(ExecState* exec, const String& title, unsigned uid, PassRefPtr<Stopwatch> stopwatch)
+ : m_origin(exec ? exec->lexicalGlobalObject() : nullptr)
+ , m_profileGroup(exec ? exec->lexicalGlobalObject()->profileGroup() : 0)
+ , m_stopwatch(stopwatch)
+ , m_foundConsoleStartParent(false)
+ , m_suspended(false)
+{
+ double startTime = m_stopwatch->elapsedTime();
+ m_profile = Profile::create(title, uid, startTime);
+ m_currentNode = m_rootNode = m_profile->rootNode();
+ if (exec)
+ addParentForConsoleStart(exec, startTime);
+}
+
+class AddParentForConsoleStartFunctor {
+public:
+ AddParentForConsoleStartFunctor(ExecState* exec, RefPtr<ProfileNode>& rootNode, RefPtr<ProfileNode>& currentNode, double startTime)
+ : m_exec(exec)
+ , m_hasSkippedFirstFrame(false)
+ , m_foundParent(false)
+ , m_rootNode(rootNode)
+ , m_currentNode(currentNode)
+ , m_startTime(startTime)
+ {
+ }
+
+ bool foundParent() const { return m_foundParent; }
+
+ StackVisitor::Status operator()(StackVisitor& visitor)
+ {
+ if (!m_hasSkippedFirstFrame) {
+ m_hasSkippedFirstFrame = true;
+ return StackVisitor::Continue;
+ }
+
+ unsigned line = 0;
+ unsigned column = 0;
+ visitor->computeLineAndColumn(line, column);
+ m_currentNode = ProfileNode::create(m_exec, LegacyProfiler::createCallIdentifier(m_exec, visitor->callee(), visitor->sourceURL(), line, column), m_rootNode.get());
+ m_currentNode->appendCall(ProfileNode::Call(m_startTime));
+ m_rootNode->spliceNode(m_currentNode.get());
+
+ m_foundParent = true;
+ return StackVisitor::Done;
+ }
+
+private:
+ ExecState* m_exec;
+ bool m_hasSkippedFirstFrame;
+ bool m_foundParent;
+ RefPtr<ProfileNode>& m_rootNode;
+ RefPtr<ProfileNode>& m_currentNode;
+ double m_startTime;
+};
+
+void ProfileGenerator::addParentForConsoleStart(ExecState* exec, double startTime)
+{
+ AddParentForConsoleStartFunctor functor(exec, m_rootNode, m_currentNode, startTime);
+ exec->iterate(functor);
+
+ m_foundConsoleStartParent = functor.foundParent();
+}
+
+const String& ProfileGenerator::title() const
+{
+ return m_profile->title();
+}
+
+void ProfileGenerator::beginCallEntry(ProfileNode* node, double startTime)
+{
+ ASSERT_ARG(node, node);
+
+ if (std::isnan(startTime))
+ startTime = m_stopwatch->elapsedTime();
+
+ node->appendCall(ProfileNode::Call(startTime));
+}
+
+void ProfileGenerator::endCallEntry(ProfileNode* node)
+{
+ ASSERT_ARG(node, node);
+
+ ProfileNode::Call& last = node->lastCall();
+
+ double previousElapsedTime = std::isnan(last.elapsedTime()) ? 0.0 : last.elapsedTime();
+ double newlyElapsedTime = m_stopwatch->elapsedTime() - last.startTime();
+ last.setElapsedTime(previousElapsedTime + newlyElapsedTime);
+}
+
+void ProfileGenerator::willExecute(ExecState* callerCallFrame, const CallIdentifier& callIdentifier)
+{
+ if (JAVASCRIPTCORE_PROFILE_WILL_EXECUTE_ENABLED()) {
+ CString name = callIdentifier.functionName().utf8();
+ CString url = callIdentifier.url().utf8();
+ JAVASCRIPTCORE_PROFILE_WILL_EXECUTE(m_profileGroup, const_cast<char*>(name.data()), const_cast<char*>(url.data()), callIdentifier.lineNumber(), callIdentifier.columnNumber());
+ }
+
+ if (!m_origin)
+ return;
+
+ if (m_suspended)
+ return;
+
+ RefPtr<ProfileNode> calleeNode = nullptr;
+
+ // Find or create a node for the callee call frame.
+ for (const RefPtr<ProfileNode>& child : m_currentNode->children()) {
+ if (child->callIdentifier() == callIdentifier)
+ calleeNode = child;
+ }
+
+ if (!calleeNode) {
+ calleeNode = ProfileNode::create(callerCallFrame, callIdentifier, m_currentNode.get());
+ m_currentNode->addChild(calleeNode);
+ }
+
+ m_currentNode = calleeNode;
+ beginCallEntry(calleeNode.get(), m_stopwatch->elapsedTime());
+}
+
+void ProfileGenerator::didExecute(ExecState* callerCallFrame, const CallIdentifier& callIdentifier)
+{
+ if (JAVASCRIPTCORE_PROFILE_DID_EXECUTE_ENABLED()) {
+ CString name = callIdentifier.functionName().utf8();
+ CString url = callIdentifier.url().utf8();
+ JAVASCRIPTCORE_PROFILE_DID_EXECUTE(m_profileGroup, const_cast<char*>(name.data()), const_cast<char*>(url.data()), callIdentifier.lineNumber(), callIdentifier.columnNumber());
+ }
+
+ if (!m_origin)
+ return;
+
+ if (m_suspended)
+ return;
+
+ // Make a new node if the caller node has never seen this callee call frame before.
+ // This can happen if |console.profile()| is called several frames deep in the call stack.
+ ASSERT(m_currentNode);
+ if (m_currentNode->callIdentifier() != callIdentifier) {
+ RefPtr<ProfileNode> calleeNode = ProfileNode::create(callerCallFrame, callIdentifier, m_currentNode.get());
+ beginCallEntry(calleeNode.get(), m_currentNode->lastCall().startTime());
+ endCallEntry(calleeNode.get());
+ m_currentNode->spliceNode(calleeNode.release());
+ return;
+ }
+
+ endCallEntry(m_currentNode.get());
+ m_currentNode = m_currentNode->parent();
+}
+
+void ProfileGenerator::exceptionUnwind(ExecState* handlerCallFrame, const CallIdentifier&)
+{
+ if (m_suspended)
+ return;
+
+ // If the current node was called by the handler (==) or any
+ // more nested function (>) the we have exited early from it.
+ ASSERT(m_currentNode);
+ while (m_currentNode->callerCallFrame() >= handlerCallFrame) {
+ didExecute(m_currentNode->callerCallFrame(), m_currentNode->callIdentifier());
+ ASSERT(m_currentNode);
+ }
+}
+
+void ProfileGenerator::stopProfiling()
+{
+ for (ProfileNode* node = m_currentNode.get(); node != m_profile->rootNode(); node = node->parent())
+ endCallEntry(node);
+
+ if (m_foundConsoleStartParent) {
+ removeProfileStart();
+ removeProfileEnd();
+ }
+
+ ASSERT(m_currentNode);
+
+ // Set the current node to the parent, because we are in a call that
+ // will not get didExecute call.
+ m_currentNode = m_currentNode->parent();
+}
+
+// The console.profile that started this ProfileGenerator will be the first child.
+void ProfileGenerator::removeProfileStart()
+{
+ ProfileNode* currentNode = nullptr;
+ for (ProfileNode* next = m_rootNode.get(); next; next = next->firstChild())
+ currentNode = next;
+
+ if (currentNode->callIdentifier().functionName() != "profile")
+ return;
+
+ currentNode->parent()->removeChild(currentNode);
+}
+
+// The console.profileEnd that stopped this ProfileGenerator will be the last child.
+void ProfileGenerator::removeProfileEnd()
+{
+ ProfileNode* currentNode = nullptr;
+ for (ProfileNode* next = m_rootNode.get(); next; next = next->lastChild())
+ currentNode = next;
+
+ if (currentNode->callIdentifier().functionName() != "profileEnd")
+ return;
+
+ ASSERT(currentNode->callIdentifier() == (currentNode->parent()->children()[currentNode->parent()->children().size() - 1])->callIdentifier());
+ currentNode->parent()->removeChild(currentNode);
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/profiler/ProfileGenerator.h b/Source/JavaScriptCore/profiler/ProfileGenerator.h
new file mode 100644
index 000000000..387ed5f4a
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfileGenerator.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfileGenerator_h
+#define ProfileGenerator_h
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Stopwatch.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+
+ class DebuggerCallFrame;
+ class ExecState;
+ class JSGlobalObject;
+ class Profile;
+ class ProfileNode;
+ struct CallIdentifier;
+
+ class ProfileGenerator : public RefCounted<ProfileGenerator> {
+ public:
+ static Ref<ProfileGenerator> create(ExecState*, const WTF::String& title, unsigned uid, PassRefPtr<Stopwatch>);
+
+ // Members
+ const WTF::String& title() const;
+ PassRefPtr<Profile> profile() const { return m_profile; }
+ JSGlobalObject* origin() const { return m_origin; }
+ unsigned profileGroup() const { return m_profileGroup; }
+
+ void willExecute(ExecState* callerCallFrame, const CallIdentifier&);
+ void didExecute(ExecState* callerCallFrame, const CallIdentifier&);
+ void exceptionUnwind(ExecState* handlerCallFrame, const CallIdentifier&);
+
+ void setIsSuspended(bool suspended) { ASSERT(m_suspended != suspended); m_suspended = suspended; }
+
+ void stopProfiling();
+
+ private:
+ ProfileGenerator(ExecState*, const WTF::String& title, unsigned uid, PassRefPtr<Stopwatch>);
+ void addParentForConsoleStart(ExecState*, double);
+
+ void removeProfileStart();
+ void removeProfileEnd();
+
+ void beginCallEntry(ProfileNode*, double startTime);
+ void endCallEntry(ProfileNode*);
+
+ RefPtr<Profile> m_profile;
+ JSGlobalObject* m_origin;
+ unsigned m_profileGroup;
+ RefPtr<Stopwatch> m_stopwatch;
+ RefPtr<ProfileNode> m_rootNode;
+ RefPtr<ProfileNode> m_currentNode;
+ bool m_foundConsoleStartParent;
+ bool m_suspended;
+ };
+
+} // namespace JSC
+
+#endif // ProfileGenerator_h
diff --git a/Source/JavaScriptCore/profiler/ProfileNode.cpp b/Source/JavaScriptCore/profiler/ProfileNode.cpp
new file mode 100644
index 000000000..9bcf37586
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfileNode.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2008, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfileNode.h"
+
+#include "LegacyProfiler.h"
+#include <wtf/DateMath.h>
+#include <wtf/DataLog.h>
+#include <wtf/text/StringHash.h>
+
+using namespace WTF;
+
+namespace JSC {
+
+ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* parentNode)
+ : m_callerCallFrame(callerCallFrame)
+ , m_callIdentifier(callIdentifier)
+ , m_parent(parentNode)
+#ifndef NDEBUG
+ , m_nextSibling(nullptr)
+#endif
+{
+}
+
+ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* nodeToCopy)
+ : m_callerCallFrame(callerCallFrame)
+ , m_callIdentifier(nodeToCopy->callIdentifier())
+ , m_parent(nodeToCopy->parent())
+ , m_calls(nodeToCopy->calls())
+#ifndef NDEBUG
+ , m_nextSibling(nullptr)
+#endif
+{
+}
+
+void ProfileNode::addChild(PassRefPtr<ProfileNode> prpChild)
+{
+ RefPtr<ProfileNode> child = prpChild;
+ child->setParent(this);
+#ifndef NDEBUG
+ if (m_children.size())
+ m_children.last()->setNextSibling(child.get());
+#endif
+ m_children.append(child.release());
+}
+
+void ProfileNode::removeChild(ProfileNode* node)
+{
+ if (!node)
+ return;
+
+ m_children.removeFirstMatching([node] (const RefPtr<ProfileNode>& current) {
+ return *node == current.get();
+ });
+
+#ifndef NDEBUG
+ size_t size = m_children.size();
+ for (size_t i = 0; i < size; ++i)
+ m_children[i]->setNextSibling(i + 1 == size ? nullptr : m_children[i + 1].get());
+#endif
+}
+
+void ProfileNode::spliceNode(PassRefPtr<ProfileNode> prpNode)
+{
+ RefPtr<ProfileNode> node = prpNode;
+
+ for (unsigned i = 0; i < m_children.size(); ++i)
+ node->addChild(m_children[i].release());
+
+ m_children.clear();
+ m_children.append(node.release());
+}
+
+#ifndef NDEBUG
+ProfileNode* ProfileNode::traverseNextNodePostOrder() const
+{
+ ProfileNode* next = m_nextSibling;
+ if (!next)
+ return m_parent;
+ while (ProfileNode* firstChild = next->firstChild())
+ next = firstChild;
+ return next;
+}
+
+void ProfileNode::debugPrint()
+{
+ CalculateProfileSubtreeDataFunctor functor;
+ forEachNodePostorder(functor);
+ ProfileNode::ProfileSubtreeData data = functor.returnValue();
+
+ debugPrintRecursively(0, data);
+}
+
+void ProfileNode::debugPrintSampleStyle()
+{
+ FunctionCallHashCount countedFunctions;
+
+ CalculateProfileSubtreeDataFunctor functor;
+ forEachNodePostorder(functor);
+ ProfileNode::ProfileSubtreeData data = functor.returnValue();
+
+ debugPrintSampleStyleRecursively(0, countedFunctions, data);
+}
+
+void ProfileNode::debugPrintRecursively(int indentLevel, const ProfileSubtreeData& data)
+{
+ // Print function names
+ for (int i = 0; i < indentLevel; ++i)
+ dataLogF(" ");
+
+ auto it = data.selfAndTotalTimes.find(this);
+ ASSERT(it != data.selfAndTotalTimes.end());
+
+ double nodeSelfTime = it->value.first;
+ double nodeTotalTime = it->value.second;
+ double rootTotalTime = data.rootTotalTime;
+
+ dataLogF("Function Name %s %zu SelfTime %.3fms/%.3f%% TotalTime %.3fms/%.3f%% Next Sibling %s\n",
+ functionName().utf8().data(),
+ m_calls.size(), nodeSelfTime, nodeSelfTime / rootTotalTime * 100.0, nodeTotalTime, nodeTotalTime / rootTotalTime * 100.0,
+ m_nextSibling ? m_nextSibling->functionName().utf8().data() : "");
+
+ ++indentLevel;
+
+ // Print children's names and information
+ for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild)
+ (*currentChild)->debugPrintRecursively(indentLevel, data);
+}
+
+// print the profiled data in a format that matches the tool sample's output.
+double ProfileNode::debugPrintSampleStyleRecursively(int indentLevel, FunctionCallHashCount& countedFunctions, const ProfileSubtreeData& data)
+{
+ dataLogF(" ");
+
+ auto it = data.selfAndTotalTimes.find(this);
+ ASSERT(it != data.selfAndTotalTimes.end());
+ double nodeTotalTime = it->value.second;
+
+ // Print function names
+ const char* name = functionName().utf8().data();
+ double sampleCount = nodeTotalTime * 1000;
+ if (indentLevel) {
+ for (int i = 0; i < indentLevel; ++i)
+ dataLogF(" ");
+
+ countedFunctions.add(functionName().impl());
+
+ dataLogF("%.0f %s\n", sampleCount ? sampleCount : 1, name);
+ } else
+ dataLogF("%s\n", name);
+
+ ++indentLevel;
+
+ // Print children's names and information
+ double sumOfChildrensCount = 0.0;
+ for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild)
+ sumOfChildrensCount += (*currentChild)->debugPrintSampleStyleRecursively(indentLevel, countedFunctions, data);
+
+ sumOfChildrensCount *= 1000; //
+ // Print remainder of samples to match sample's output
+ if (sumOfChildrensCount < sampleCount) {
+ dataLogF(" ");
+ while (indentLevel--)
+ dataLogF(" ");
+
+ dataLogF("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data());
+ }
+
+ return nodeTotalTime;
+}
+#endif
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/profiler/ProfileNode.h b/Source/JavaScriptCore/profiler/ProfileNode.h
new file mode 100644
index 000000000..fcaee0e24
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfileNode.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2008, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfileNode_h
+#define ProfileNode_h
+
+#include "CallIdentifier.h"
+#include <wtf/HashCountedSet.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+ class ExecState;
+ class ProfileNode;
+
+ typedef HashCountedSet<StringImpl*> FunctionCallHashCount;
+
+ class ProfileNode : public RefCounted<ProfileNode> {
+ public:
+ static Ref<ProfileNode> create(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* parentNode)
+ {
+ return adoptRef(*new ProfileNode(callerCallFrame, callIdentifier, parentNode));
+ }
+
+ static Ref<ProfileNode> create(ExecState* callerCallFrame, ProfileNode* node)
+ {
+ return adoptRef(*new ProfileNode(callerCallFrame, node));
+ }
+
+ struct Call {
+ public:
+ Call(double startTime, double elapsedTime = NAN)
+ : m_startTime(startTime)
+ , m_elapsedTime(elapsedTime)
+ {
+ }
+
+ double startTime() const { return m_startTime; }
+ void setStartTime(double time)
+ {
+ ASSERT_ARG(time, time >= 0.0 || std::isnan(time));
+ m_startTime = time;
+ }
+
+ double elapsedTime() const { return m_elapsedTime; }
+ void setElapsedTime(double time)
+ {
+ ASSERT_ARG(time, time >= 0.0 || std::isnan(time));
+ m_elapsedTime = time;
+ }
+
+ private:
+ double m_startTime;
+ double m_elapsedTime;
+ };
+
+ bool operator==(ProfileNode* node) { return m_callIdentifier == node->callIdentifier(); }
+
+ ExecState* callerCallFrame() const { return m_callerCallFrame; }
+ const CallIdentifier& callIdentifier() const { return m_callIdentifier; }
+ unsigned id() const { return m_callIdentifier.hash(); }
+ const String& functionName() const { return m_callIdentifier.functionName(); }
+ const String& url() const { return m_callIdentifier.url(); }
+ unsigned lineNumber() const { return m_callIdentifier.lineNumber(); }
+ unsigned columnNumber() const { return m_callIdentifier.columnNumber(); }
+
+ ProfileNode* parent() const { return m_parent; }
+ void setParent(ProfileNode* parent) { m_parent = parent; }
+
+ const Vector<Call>& calls() const { return m_calls; }
+ Call& lastCall() { ASSERT(!m_calls.isEmpty()); return m_calls.last(); }
+ void appendCall(Call call) { m_calls.append(call); }
+
+ const Vector<RefPtr<ProfileNode>>& children() const { return m_children; }
+ ProfileNode* firstChild() const { return m_children.size() ? m_children.first().get() : nullptr; }
+ ProfileNode* lastChild() const { return m_children.size() ? m_children.last().get() : nullptr; }
+
+ void removeChild(ProfileNode*);
+ void addChild(PassRefPtr<ProfileNode>);
+ // Reparent our child nodes to the passed node, and make it a child node of |this|.
+ void spliceNode(PassRefPtr<ProfileNode>);
+
+#ifndef NDEBUG
+ struct ProfileSubtreeData {
+ HashMap<ProfileNode*, std::pair<double, double>> selfAndTotalTimes;
+ double rootTotalTime;
+ };
+
+ // Use these functions to dump the subtree rooted at this node.
+ void debugPrint();
+ void debugPrintSampleStyle();
+
+ // These are used to recursively print entire subtrees using precomputed self and total times.
+ template <typename Functor> void forEachNodePostorder(Functor&);
+
+ void debugPrintRecursively(int indentLevel, const ProfileSubtreeData&);
+ double debugPrintSampleStyleRecursively(int indentLevel, FunctionCallHashCount&, const ProfileSubtreeData&);
+#endif
+
+ private:
+ typedef Vector<RefPtr<ProfileNode>>::const_iterator StackIterator;
+
+ ProfileNode(ExecState* callerCallFrame, const CallIdentifier&, ProfileNode* parentNode);
+ ProfileNode(ExecState* callerCallFrame, ProfileNode* nodeToCopy);
+
+#ifndef NDEBUG
+ ProfileNode* nextSibling() const { return m_nextSibling; }
+ void setNextSibling(ProfileNode* nextSibling) { m_nextSibling = nextSibling; }
+
+ ProfileNode* traverseNextNodePostOrder() const;
+#endif
+
+ ExecState* m_callerCallFrame;
+ CallIdentifier m_callIdentifier;
+ ProfileNode* m_parent;
+ Vector<Call> m_calls;
+ Vector<RefPtr<ProfileNode>> m_children;
+
+#ifndef NDEBUG
+ ProfileNode* m_nextSibling;
+#endif
+ };
+
+#ifndef NDEBUG
+ template <typename Functor> inline void ProfileNode::forEachNodePostorder(Functor& functor)
+ {
+ ProfileNode* currentNode = this;
+ // Go down to the first node of the traversal, and slowly walk back up.
+ for (ProfileNode* nextNode = currentNode; nextNode; nextNode = nextNode->firstChild())
+ currentNode = nextNode;
+
+ ProfileNode* endNode = this;
+ while (currentNode && currentNode != endNode) {
+ functor(currentNode);
+ currentNode = currentNode->traverseNextNodePostOrder();
+ }
+
+ functor(endNode);
+ }
+
+ struct CalculateProfileSubtreeDataFunctor {
+ void operator()(ProfileNode* node)
+ {
+ double selfTime = 0.0;
+ for (const ProfileNode::Call& call : node->calls())
+ selfTime += call.elapsedTime();
+
+ double totalTime = selfTime;
+ for (RefPtr<ProfileNode> child : node->children()) {
+ auto it = m_data.selfAndTotalTimes.find(child.get());
+ if (it != m_data.selfAndTotalTimes.end())
+ totalTime += it->value.second;
+ }
+
+ ASSERT(node);
+ m_data.selfAndTotalTimes.set(node, std::make_pair(selfTime, totalTime));
+ }
+
+ ProfileNode::ProfileSubtreeData returnValue() { return WTF::move(m_data); }
+
+ ProfileNode::ProfileSubtreeData m_data;
+ };
+#endif
+
+} // namespace JSC
+
+#endif // ProfileNode_h
diff --git a/Source/JavaScriptCore/profiler/ProfilerBytecode.cpp b/Source/JavaScriptCore/profiler/ProfilerBytecode.cpp
new file mode 100644
index 000000000..6eeeb27b9
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerBytecode.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfilerBytecode.h"
+
+#include "JSGlobalObject.h"
+#include "ObjectConstructor.h"
+#include "JSCInlines.h"
+
+namespace JSC { namespace Profiler {
+
+JSValue Bytecode::toJS(ExecState* exec) const
+{
+ JSObject* result = constructEmptyObject(exec);
+ result->putDirect(exec->vm(), exec->propertyNames().bytecodeIndex, jsNumber(m_bytecodeIndex));
+ result->putDirect(exec->vm(), exec->propertyNames().opcode, jsString(exec, String::fromUTF8(opcodeNames[m_opcodeID])));
+ result->putDirect(exec->vm(), exec->propertyNames().description, jsString(exec, String::fromUTF8(m_description)));
+ return result;
+}
+
+} } // namespace JSC::Profiler
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerBytecode.h b/Source/JavaScriptCore/profiler/ProfilerBytecode.h
new file mode 100644
index 000000000..8e99c9a09
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerBytecode.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfilerBytecode_h
+#define ProfilerBytecode_h
+
+#include "JSCJSValue.h"
+#include "Opcode.h"
+#include <wtf/text/CString.h>
+
+namespace JSC { namespace Profiler {
+
+class Bytecode {
+public:
+ Bytecode()
+ : m_bytecodeIndex(std::numeric_limits<unsigned>::max())
+ {
+ }
+
+ Bytecode(unsigned bytecodeIndex, OpcodeID opcodeID, const CString& description)
+ : m_bytecodeIndex(bytecodeIndex)
+ , m_opcodeID(opcodeID)
+ , m_description(description)
+ {
+ }
+
+ unsigned bytecodeIndex() const { return m_bytecodeIndex; }
+ OpcodeID opcodeID() const { return m_opcodeID; }
+ const CString& description() const { return m_description; }
+
+ JSValue toJS(ExecState*) const;
+private:
+ unsigned m_bytecodeIndex;
+ OpcodeID m_opcodeID;
+ CString m_description;
+};
+
+inline unsigned getBytecodeIndexForBytecode(Bytecode* bytecode) { return bytecode->bytecodeIndex(); }
+
+} } // namespace JSC::Profiler
+
+#endif // ProfilerBytecode_h
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp b/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp
new file mode 100644
index 000000000..145ee44d1
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfilerBytecodeSequence.h"
+
+#include "CodeBlock.h"
+#include "JSGlobalObject.h"
+#include "Operands.h"
+#include "JSCInlines.h"
+#include <wtf/StringPrintStream.h>
+
+namespace JSC { namespace Profiler {
+
+BytecodeSequence::BytecodeSequence(CodeBlock* codeBlock)
+{
+ StringPrintStream out;
+
+ for (unsigned i = 0; i < codeBlock->numberOfArgumentValueProfiles(); ++i) {
+ ConcurrentJITLocker locker(codeBlock->m_lock);
+ CString description = codeBlock->valueProfileForArgument(i)->briefDescription(locker);
+ if (!description.length())
+ continue;
+ out.reset();
+ out.print("arg", i, ": ", description);
+ m_header.append(out.toCString());
+ }
+
+ StubInfoMap stubInfos;
+ codeBlock->getStubInfoMap(stubInfos);
+
+ for (unsigned bytecodeIndex = 0; bytecodeIndex < codeBlock->instructions().size();) {
+ out.reset();
+ codeBlock->dumpBytecode(out, bytecodeIndex, stubInfos);
+ m_sequence.append(Bytecode(bytecodeIndex, codeBlock->vm()->interpreter->getOpcodeID(codeBlock->instructions()[bytecodeIndex].u.opcode), out.toCString()));
+ bytecodeIndex += opcodeLength(
+ codeBlock->vm()->interpreter->getOpcodeID(
+ codeBlock->instructions()[bytecodeIndex].u.opcode));
+ }
+}
+
+BytecodeSequence::~BytecodeSequence()
+{
+}
+
+unsigned BytecodeSequence::indexForBytecodeIndex(unsigned bytecodeIndex) const
+{
+ return binarySearch<Bytecode, unsigned>(m_sequence, m_sequence.size(), bytecodeIndex, getBytecodeIndexForBytecode) - m_sequence.begin();
+}
+
+const Bytecode& BytecodeSequence::forBytecodeIndex(unsigned bytecodeIndex) const
+{
+ return at(indexForBytecodeIndex(bytecodeIndex));
+}
+
+void BytecodeSequence::addSequenceProperties(ExecState* exec, JSObject* result) const
+{
+ JSArray* header = constructEmptyArray(exec, 0);
+ for (unsigned i = 0; i < m_header.size(); ++i)
+ header->putDirectIndex(exec, i, jsString(exec, String::fromUTF8(m_header[i])));
+ result->putDirect(exec->vm(), exec->propertyNames().header, header);
+
+ JSArray* sequence = constructEmptyArray(exec, 0);
+ for (unsigned i = 0; i < m_sequence.size(); ++i)
+ sequence->putDirectIndex(exec, i, m_sequence[i].toJS(exec));
+ result->putDirect(exec->vm(), exec->propertyNames().bytecode, sequence);
+}
+
+} } // namespace JSC::Profiler
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.h b/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.h
new file mode 100644
index 000000000..1d5c82a18
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfilerBytecodeSequence_h
+#define ProfilerBytecodeSequence_h
+
+#include "JSCJSValue.h"
+#include "ProfilerBytecode.h"
+#include <wtf/PrintStream.h>
+#include <wtf/Vector.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+
+class CodeBlock;
+
+namespace Profiler {
+
+class BytecodeSequence {
+public:
+ BytecodeSequence(CodeBlock*);
+ ~BytecodeSequence();
+
+ // Note that this data structure is not indexed by bytecode index.
+ unsigned size() const { return m_sequence.size(); }
+ const Bytecode& at(unsigned i) const { return m_sequence[i]; }
+
+ unsigned indexForBytecodeIndex(unsigned bytecodeIndex) const;
+ const Bytecode& forBytecodeIndex(unsigned bytecodeIndex) const;
+
+protected:
+ void addSequenceProperties(ExecState*, JSObject*) const;
+
+private:
+ Vector<CString> m_header;
+ Vector<Bytecode> m_sequence;
+};
+
+} } // namespace JSC::Profiler
+
+#endif // ProfilerBytecodeSequence_h
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerBytecodes.cpp b/Source/JavaScriptCore/profiler/ProfilerBytecodes.cpp
new file mode 100644
index 000000000..74c55abcf
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerBytecodes.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfilerBytecodes.h"
+
+#include "CodeBlock.h"
+#include "JSGlobalObject.h"
+#include "ObjectConstructor.h"
+#include "JSCInlines.h"
+#include <wtf/StringPrintStream.h>
+
+namespace JSC { namespace Profiler {
+
+Bytecodes::Bytecodes(size_t id, CodeBlock* codeBlock)
+ : BytecodeSequence(codeBlock)
+ , m_id(id)
+ , m_inferredName(codeBlock->inferredName())
+ , m_sourceCode(codeBlock->sourceCodeForTools())
+ , m_hash(codeBlock->hash())
+ , m_instructionCount(codeBlock->instructionCount())
+{
+}
+
+Bytecodes::~Bytecodes() { }
+
+void Bytecodes::dump(PrintStream& out) const
+{
+ out.print("#", m_hash, "(", m_id, ")");
+}
+
+JSValue Bytecodes::toJS(ExecState* exec) const
+{
+ JSObject* result = constructEmptyObject(exec);
+
+ result->putDirect(exec->vm(), exec->propertyNames().bytecodesID, jsNumber(m_id));
+ result->putDirect(exec->vm(), exec->propertyNames().inferredName, jsString(exec, String::fromUTF8(m_inferredName)));
+ result->putDirect(exec->vm(), exec->propertyNames().sourceCode, jsString(exec, String::fromUTF8(m_sourceCode)));
+ result->putDirect(exec->vm(), exec->propertyNames().hash, jsString(exec, String::fromUTF8(toCString(m_hash))));
+ result->putDirect(exec->vm(), exec->propertyNames().instructionCount, jsNumber(m_instructionCount));
+ addSequenceProperties(exec, result);
+
+ return result;
+}
+
+} } // namespace JSC::Profiler
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerBytecodes.h b/Source/JavaScriptCore/profiler/ProfilerBytecodes.h
new file mode 100644
index 000000000..e44598019
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerBytecodes.h
@@ -0,0 +1,63 @@
+/*
+ * 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfilerBytecodes_h
+#define ProfilerBytecodes_h
+
+#include "CodeBlockHash.h"
+#include "JSCJSValue.h"
+#include "ProfilerBytecodeSequence.h"
+#include <wtf/PrintStream.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC { namespace Profiler {
+
+class Bytecodes : public BytecodeSequence {
+public:
+ Bytecodes(size_t id, CodeBlock*);
+ ~Bytecodes();
+
+ size_t id() const { return m_id; }
+ const CString& inferredName() const { return m_inferredName; }
+ const CString& sourceCode() const { return m_sourceCode; }
+ unsigned instructionCount() const { return m_instructionCount; }
+ CodeBlockHash hash() const { return m_hash; }
+
+ void dump(PrintStream&) const;
+
+ JSValue toJS(ExecState*) const;
+
+private:
+ size_t m_id;
+ CString m_inferredName;
+ CString m_sourceCode;
+ CodeBlockHash m_hash;
+ unsigned m_instructionCount;
+};
+
+} } // namespace JSC::Profiler
+
+#endif // ProfilerBytecodes_h
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerCompilation.cpp b/Source/JavaScriptCore/profiler/ProfilerCompilation.cpp
new file mode 100644
index 000000000..488f563de
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerCompilation.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfilerCompilation.h"
+
+#include "JSGlobalObject.h"
+#include "ObjectConstructor.h"
+#include "JSCInlines.h"
+#include "ProfilerDatabase.h"
+#include "Watchpoint.h"
+#include <wtf/StringPrintStream.h>
+
+namespace JSC { namespace Profiler {
+
+Compilation::Compilation(Bytecodes* bytecodes, CompilationKind kind)
+ : m_bytecodes(bytecodes)
+ , m_kind(kind)
+ , m_jettisonReason(NotJettisoned)
+ , m_numInlinedGetByIds(0)
+ , m_numInlinedPutByIds(0)
+ , m_numInlinedCalls(0)
+{
+}
+
+Compilation::~Compilation() { }
+
+void Compilation::addProfiledBytecodes(Database& database, CodeBlock* profiledBlock)
+{
+ Bytecodes* bytecodes = database.ensureBytecodesFor(profiledBlock);
+
+ // First make sure that we haven't already added profiled bytecodes for this code
+ // block. We do this using an O(N) search because I suspect that this list will
+ // tend to be fairly small, and the additional space costs of having a HashMap/Set
+ // would be greater than the time cost of occasionally doing this search.
+
+ for (unsigned i = m_profiledBytecodes.size(); i--;) {
+ if (m_profiledBytecodes[i].bytecodes() == bytecodes)
+ return;
+ }
+
+ m_profiledBytecodes.append(ProfiledBytecodes(bytecodes, profiledBlock));
+}
+
+void Compilation::addDescription(const CompiledBytecode& compiledBytecode)
+{
+ m_descriptions.append(compiledBytecode);
+}
+
+void Compilation::addDescription(const OriginStack& stack, const CString& description)
+{
+ addDescription(CompiledBytecode(stack, description));
+}
+
+ExecutionCounter* Compilation::executionCounterFor(const OriginStack& origin)
+{
+ std::unique_ptr<ExecutionCounter>& counter = m_counters.add(origin, nullptr).iterator->value;
+ if (!counter)
+ counter = std::make_unique<ExecutionCounter>();
+
+ return counter.get();
+}
+
+void Compilation::addOSRExitSite(const Vector<const void*>& codeAddresses)
+{
+ m_osrExitSites.append(OSRExitSite(codeAddresses));
+}
+
+OSRExit* Compilation::addOSRExit(unsigned id, const OriginStack& originStack, ExitKind exitKind, bool isWatchpoint)
+{
+ m_osrExits.append(OSRExit(id, originStack, exitKind, isWatchpoint));
+ return &m_osrExits.last();
+}
+
+void Compilation::setJettisonReason(JettisonReason jettisonReason, const FireDetail* detail)
+{
+ if (m_jettisonReason != NotJettisoned)
+ return; // We only care about the original jettison reason.
+
+ m_jettisonReason = jettisonReason;
+ if (detail)
+ m_additionalJettisonReason = toCString(*detail);
+ else
+ m_additionalJettisonReason = CString();
+}
+
+JSValue Compilation::toJS(ExecState* exec) const
+{
+ JSObject* result = constructEmptyObject(exec);
+
+ result->putDirect(exec->vm(), exec->propertyNames().bytecodesID, jsNumber(m_bytecodes->id()));
+ result->putDirect(exec->vm(), exec->propertyNames().compilationKind, jsString(exec, String::fromUTF8(toCString(m_kind))));
+
+ JSArray* profiledBytecodes = constructEmptyArray(exec, 0);
+ for (unsigned i = 0; i < m_profiledBytecodes.size(); ++i)
+ profiledBytecodes->putDirectIndex(exec, i, m_profiledBytecodes[i].toJS(exec));
+ result->putDirect(exec->vm(), exec->propertyNames().profiledBytecodes, profiledBytecodes);
+
+ JSArray* descriptions = constructEmptyArray(exec, 0);
+ for (unsigned i = 0; i < m_descriptions.size(); ++i)
+ descriptions->putDirectIndex(exec, i, m_descriptions[i].toJS(exec));
+ result->putDirect(exec->vm(), exec->propertyNames().descriptions, descriptions);
+
+ JSArray* counters = constructEmptyArray(exec, 0);
+ for (auto it = m_counters.begin(), end = m_counters.end(); it != end; ++it) {
+ JSObject* counterEntry = constructEmptyObject(exec);
+ counterEntry->putDirect(exec->vm(), exec->propertyNames().origin, it->key.toJS(exec));
+ counterEntry->putDirect(exec->vm(), exec->propertyNames().executionCount, jsNumber(it->value->count()));
+ counters->push(exec, counterEntry);
+ }
+ result->putDirect(exec->vm(), exec->propertyNames().counters, counters);
+
+ JSArray* exitSites = constructEmptyArray(exec, 0);
+ for (unsigned i = 0; i < m_osrExitSites.size(); ++i)
+ exitSites->putDirectIndex(exec, i, m_osrExitSites[i].toJS(exec));
+ result->putDirect(exec->vm(), exec->propertyNames().osrExitSites, exitSites);
+
+ JSArray* exits = constructEmptyArray(exec, 0);
+ for (unsigned i = 0; i < m_osrExits.size(); ++i)
+ exits->putDirectIndex(exec, i, m_osrExits[i].toJS(exec));
+ result->putDirect(exec->vm(), exec->propertyNames().osrExits, exits);
+
+ result->putDirect(exec->vm(), exec->propertyNames().numInlinedGetByIds, jsNumber(m_numInlinedGetByIds));
+ result->putDirect(exec->vm(), exec->propertyNames().numInlinedPutByIds, jsNumber(m_numInlinedPutByIds));
+ result->putDirect(exec->vm(), exec->propertyNames().numInlinedCalls, jsNumber(m_numInlinedCalls));
+ result->putDirect(exec->vm(), exec->propertyNames().jettisonReason, jsString(exec, String::fromUTF8(toCString(m_jettisonReason))));
+ if (!m_additionalJettisonReason.isNull())
+ result->putDirect(exec->vm(), exec->propertyNames().additionalJettisonReason, jsString(exec, String::fromUTF8(m_additionalJettisonReason)));
+
+ return result;
+}
+
+} } // namespace JSC::Profiler
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerCompilation.h b/Source/JavaScriptCore/profiler/ProfilerCompilation.h
new file mode 100644
index 000000000..b358b659c
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerCompilation.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfilerCompilation_h
+#define ProfilerCompilation_h
+
+#include "ExitKind.h"
+#include "JSCJSValue.h"
+#include "ProfilerCompilationKind.h"
+#include "ProfilerCompiledBytecode.h"
+#include "ProfilerExecutionCounter.h"
+#include "ProfilerJettisonReason.h"
+#include "ProfilerOSRExit.h"
+#include "ProfilerOSRExitSite.h"
+#include "ProfilerOriginStack.h"
+#include "ProfilerProfiledBytecodes.h"
+#include <wtf/RefCounted.h>
+#include <wtf/SegmentedVector.h>
+
+namespace JSC {
+
+class FireDetail;
+
+namespace Profiler {
+
+class Bytecodes;
+class Database;
+
+// Represents the act of executing some bytecodes in some engine, and does
+// all of the counting for those executions.
+
+class Compilation : public RefCounted<Compilation> {
+public:
+ Compilation(Bytecodes*, CompilationKind);
+ ~Compilation();
+
+ void addProfiledBytecodes(Database&, CodeBlock*);
+ unsigned profiledBytecodesSize() const { return m_profiledBytecodes.size(); }
+ const ProfiledBytecodes& profiledBytecodesAt(unsigned i) const { return m_profiledBytecodes[i]; }
+
+ void noticeInlinedGetById() { m_numInlinedGetByIds++; }
+ void noticeInlinedPutById() { m_numInlinedPutByIds++; }
+ void noticeInlinedCall() { m_numInlinedCalls++; }
+
+ Bytecodes* bytecodes() const { return m_bytecodes; }
+ CompilationKind kind() const { return m_kind; }
+
+ void addDescription(const CompiledBytecode&);
+ void addDescription(const OriginStack&, const CString& description);
+ ExecutionCounter* executionCounterFor(const OriginStack&);
+ void addOSRExitSite(const Vector<const void*>& codeAddresses);
+ OSRExit* addOSRExit(unsigned id, const OriginStack&, ExitKind, bool isWatchpoint);
+
+ void setJettisonReason(JettisonReason, const FireDetail*);
+
+ JSValue toJS(ExecState*) const;
+
+private:
+ Bytecodes* m_bytecodes;
+ CompilationKind m_kind;
+ JettisonReason m_jettisonReason;
+ CString m_additionalJettisonReason;
+ Vector<ProfiledBytecodes> m_profiledBytecodes;
+ Vector<CompiledBytecode> m_descriptions;
+ HashMap<OriginStack, std::unique_ptr<ExecutionCounter>> m_counters;
+ Vector<OSRExitSite> m_osrExitSites;
+ SegmentedVector<OSRExit> m_osrExits;
+ unsigned m_numInlinedGetByIds;
+ unsigned m_numInlinedPutByIds;
+ unsigned m_numInlinedCalls;
+};
+
+} } // namespace JSC::Profiler
+
+#endif // ProfilerCompilation_h
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerCompilationKind.cpp b/Source/JavaScriptCore/profiler/ProfilerCompilationKind.cpp
new file mode 100644
index 000000000..3fbe25192
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerCompilationKind.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfilerCompilationKind.h"
+
+#include <wtf/PrintStream.h>
+
+namespace WTF {
+
+void printInternal(PrintStream& out, JSC::Profiler::CompilationKind kind)
+{
+ switch (kind) {
+ case JSC::Profiler::LLInt:
+ out.print("LLInt");
+ return;
+ case JSC::Profiler::Baseline:
+ out.print("Baseline");
+ return;
+ case JSC::Profiler::DFG:
+ out.print("DFG");
+ return;
+ case JSC::Profiler::FTL:
+ out.print("FTL");
+ return;
+ case JSC::Profiler::FTLForOSREntry:
+ out.print("FTLForOSREntry");
+ return;
+ default:
+ CRASH();
+ return;
+ }
+}
+
+} // namespace WTF
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerCompilationKind.h b/Source/JavaScriptCore/profiler/ProfilerCompilationKind.h
new file mode 100644
index 000000000..575ec2947
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerCompilationKind.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfilerCompilationKind_h
+#define ProfilerCompilationKind_h
+
+namespace JSC { namespace Profiler {
+
+enum CompilationKind {
+ LLInt,
+ Baseline,
+ DFG,
+ FTL,
+ FTLForOSREntry
+};
+
+} } // namespace JSC::Profiler
+
+namespace WTF {
+
+class PrintStream;
+void printInternal(PrintStream&, JSC::Profiler::CompilationKind);
+
+} // namespace WTF
+
+#endif // ProfilerCompilationKind_h
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerCompiledBytecode.cpp b/Source/JavaScriptCore/profiler/ProfilerCompiledBytecode.cpp
new file mode 100644
index 000000000..4891c315c
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerCompiledBytecode.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfilerCompiledBytecode.h"
+
+#include "JSGlobalObject.h"
+#include "ObjectConstructor.h"
+#include "JSCInlines.h"
+
+namespace JSC { namespace Profiler {
+
+CompiledBytecode::CompiledBytecode(const OriginStack& origin, const CString& description)
+ : m_origin(origin)
+ , m_description(description)
+{
+}
+
+CompiledBytecode::~CompiledBytecode()
+{
+}
+
+JSValue CompiledBytecode::toJS(ExecState* exec) const
+{
+ JSObject* result = constructEmptyObject(exec);
+
+ result->putDirect(exec->vm(), exec->propertyNames().origin, m_origin.toJS(exec));
+ result->putDirect(exec->vm(), exec->propertyNames().description, jsString(exec, String::fromUTF8(m_description)));
+
+ return result;
+}
+
+} } // namespace JSC::Profiler
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerCompiledBytecode.h b/Source/JavaScriptCore/profiler/ProfilerCompiledBytecode.h
new file mode 100644
index 000000000..84044445a
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerCompiledBytecode.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfilerCompiledBytecode_h
+#define ProfilerCompiledBytecode_h
+
+#include "JSCJSValue.h"
+#include "ProfilerOriginStack.h"
+#include <wtf/text/CString.h>
+
+namespace JSC { namespace Profiler {
+
+class CompiledBytecode {
+public:
+ // It's valid to have an empty OriginStack, which indicates that this is some
+ // sort of non-bytecode-related machine code.
+ CompiledBytecode(const OriginStack&, const CString& description);
+ ~CompiledBytecode();
+
+ const OriginStack& originStack() const { return m_origin; }
+ const CString& description() const { return m_description; }
+
+ JSValue toJS(ExecState*) const;
+
+private:
+ OriginStack m_origin;
+ CString m_description;
+};
+
+} } // namespace JSC::Profiler
+
+#endif // ProfilerCompiledBytecode_h
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp b/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp
new file mode 100644
index 000000000..fc952c0c2
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp
@@ -0,0 +1,183 @@
+/*
+ * 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfilerDatabase.h"
+
+#include "CodeBlock.h"
+#include "JSONObject.h"
+#include "ObjectConstructor.h"
+#include "JSCInlines.h"
+
+namespace JSC { namespace Profiler {
+
+static std::atomic<int> databaseCounter;
+
+static StaticLock registrationLock;
+static std::atomic<int> didRegisterAtExit;
+static Database* firstDatabase;
+
+Database::Database(VM& vm)
+ : m_databaseID(++databaseCounter)
+ , m_vm(vm)
+ , m_shouldSaveAtExit(false)
+ , m_nextRegisteredDatabase(0)
+{
+}
+
+Database::~Database()
+{
+ if (m_shouldSaveAtExit) {
+ removeDatabaseFromAtExit();
+ performAtExitSave();
+ }
+}
+
+Bytecodes* Database::ensureBytecodesFor(CodeBlock* codeBlock)
+{
+ LockHolder locker(m_lock);
+
+ codeBlock = codeBlock->baselineVersion();
+
+ HashMap<CodeBlock*, Bytecodes*>::iterator iter = m_bytecodesMap.find(codeBlock);
+ if (iter != m_bytecodesMap.end())
+ return iter->value;
+
+ m_bytecodes.append(Bytecodes(m_bytecodes.size(), codeBlock));
+ Bytecodes* result = &m_bytecodes.last();
+
+ m_bytecodesMap.add(codeBlock, result);
+
+ return result;
+}
+
+void Database::notifyDestruction(CodeBlock* codeBlock)
+{
+ LockHolder locker(m_lock);
+
+ m_bytecodesMap.remove(codeBlock);
+}
+
+void Database::addCompilation(PassRefPtr<Compilation> compilation)
+{
+ ASSERT(!isCompilationThread());
+
+ m_compilations.append(compilation);
+}
+
+JSValue Database::toJS(ExecState* exec) const
+{
+ JSObject* result = constructEmptyObject(exec);
+
+ JSArray* bytecodes = constructEmptyArray(exec, 0);
+ for (unsigned i = 0; i < m_bytecodes.size(); ++i)
+ bytecodes->putDirectIndex(exec, i, m_bytecodes[i].toJS(exec));
+ result->putDirect(exec->vm(), exec->propertyNames().bytecodes, bytecodes);
+
+ JSArray* compilations = constructEmptyArray(exec, 0);
+ for (unsigned i = 0; i < m_compilations.size(); ++i)
+ compilations->putDirectIndex(exec, i, m_compilations[i]->toJS(exec));
+ result->putDirect(exec->vm(), exec->propertyNames().compilations, compilations);
+
+ return result;
+}
+
+String Database::toJSON() const
+{
+ JSGlobalObject* globalObject = JSGlobalObject::create(
+ m_vm, JSGlobalObject::createStructure(m_vm, jsNull()));
+
+ return JSONStringify(globalObject->globalExec(), toJS(globalObject->globalExec()), 0);
+}
+
+bool Database::save(const char* filename) const
+{
+ auto out = FilePrintStream::open(filename, "w");
+ if (!out)
+ return false;
+
+ out->print(toJSON());
+ return true;
+}
+
+void Database::registerToSaveAtExit(const char* filename)
+{
+ m_atExitSaveFilename = filename;
+
+ if (m_shouldSaveAtExit)
+ return;
+
+ addDatabaseToAtExit();
+ m_shouldSaveAtExit = true;
+}
+
+void Database::addDatabaseToAtExit()
+{
+ if (++didRegisterAtExit == 1)
+ atexit(atExitCallback);
+
+ LockHolder holder(registrationLock);
+ m_nextRegisteredDatabase = firstDatabase;
+ firstDatabase = this;
+}
+
+void Database::removeDatabaseFromAtExit()
+{
+ LockHolder holder(registrationLock);
+ 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()
+{
+ LockHolder holder(registrationLock);
+ 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
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerDatabase.h b/Source/JavaScriptCore/profiler/ProfilerDatabase.h
new file mode 100644
index 000000000..9bb64cf49
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerDatabase.h
@@ -0,0 +1,94 @@
+/*
+ * 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfilerDatabase_h
+#define ProfilerDatabase_h
+
+#include "JSCJSValue.h"
+#include "ProfilerBytecodes.h"
+#include "ProfilerCompilation.h"
+#include "ProfilerCompilationKind.h"
+#include <wtf/FastMalloc.h>
+#include <wtf/HashMap.h>
+#include <wtf/Lock.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/SegmentedVector.h>
+#include <wtf/ThreadingPrimitives.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC { namespace Profiler {
+
+class Database {
+ WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_NONCOPYABLE(Database);
+public:
+ JS_EXPORT_PRIVATE Database(VM&);
+ JS_EXPORT_PRIVATE ~Database();
+
+ int databaseID() const { return m_databaseID; }
+
+ Bytecodes* ensureBytecodesFor(CodeBlock*);
+ void notifyDestruction(CodeBlock*);
+
+ void addCompilation(PassRefPtr<Compilation>);
+
+ // Converts the database to a JavaScript object that is suitable for JSON stringification.
+ // Note that it's probably a good idea to use an ExecState* associated with a global
+ // object that is "clean" - i.e. array and object prototypes haven't had strange things
+ // done to them. And yes, it should be appropriate to just use a globalExec here.
+ JS_EXPORT_PRIVATE JSValue toJS(ExecState*) const;
+
+ // Converts the database to a JavaScript object using a private temporary global object,
+ // and then returns the JSON representation of that object.
+ JS_EXPORT_PRIVATE String toJSON() const;
+
+ // Saves the JSON representation (from toJSON()) to the given file. Returns false if the
+ // save failed.
+ JS_EXPORT_PRIVATE bool save(const char* filename) const;
+
+ void registerToSaveAtExit(const char* filename);
+
+private:
+ void addDatabaseToAtExit();
+ void removeDatabaseFromAtExit();
+ void performAtExitSave() const;
+ static Database* removeFirstAtExitDatabase();
+ static void atExitCallback();
+
+ int m_databaseID;
+ VM& m_vm;
+ SegmentedVector<Bytecodes> m_bytecodes;
+ HashMap<CodeBlock*, Bytecodes*> m_bytecodesMap;
+ Vector<RefPtr<Compilation>> m_compilations;
+ bool m_shouldSaveAtExit;
+ CString m_atExitSaveFilename;
+ Database* m_nextRegisteredDatabase;
+ Lock m_lock;
+};
+
+} } // namespace JSC::Profiler
+
+#endif // ProfilerDatabase_h
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerExecutionCounter.h b/Source/JavaScriptCore/profiler/ProfilerExecutionCounter.h
new file mode 100644
index 000000000..8989e38b5
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerExecutionCounter.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfilerExecutionCounter_h
+#define ProfilerExecutionCounter_h
+
+#include <wtf/FastMalloc.h>
+#include <wtf/Noncopyable.h>
+
+namespace JSC { namespace Profiler {
+
+class ExecutionCounter {
+ WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_NONCOPYABLE(ExecutionCounter);
+public:
+ ExecutionCounter() : m_counter(0) { }
+
+ uint64_t* address() { return &m_counter; }
+
+ uint64_t count() const { return m_counter; }
+
+private:
+ uint64_t m_counter;
+};
+
+} } // namespace JSC::Profiler
+
+#endif // ProfilerExecutionCounter_h
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerJettisonReason.cpp b/Source/JavaScriptCore/profiler/ProfilerJettisonReason.cpp
new file mode 100644
index 000000000..5fad7297f
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerJettisonReason.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfilerJettisonReason.h"
+
+#include <wtf/PrintStream.h>
+
+namespace WTF {
+
+using namespace JSC::Profiler;
+
+void printInternal(PrintStream& out, JettisonReason reason)
+{
+ switch (reason) {
+ case NotJettisoned:
+ out.print("NotJettisoned");
+ return;
+ case JettisonDueToWeakReference:
+ out.print("WeakReference");
+ return;
+ case JettisonDueToDebuggerBreakpoint:
+ out.print("DebuggerBreakpoint");
+ return;
+ case JettisonDueToDebuggerStepping:
+ out.print("DebuggerStepping");
+ return;
+ case JettisonDueToLegacyProfiler:
+ out.print("LegacyProfiler");
+ return;
+ case JettisonDueToBaselineLoopReoptimizationTrigger:
+ out.print("BaselineLoopReoptimizationTrigger");
+ return;
+ case JettisonDueToBaselineLoopReoptimizationTriggerOnOSREntryFail:
+ out.print("BaselineLoopReoptimizationTriggerOnOSREntryFail");
+ return;
+ case JettisonDueToOSRExit:
+ out.print("OSRExit");
+ return;
+ case JettisonDueToProfiledWatchpoint:
+ out.print("ProfiledWatchpoint");
+ return;
+ case JettisonDueToUnprofiledWatchpoint:
+ out.print("UnprofiledWatchpoint");
+ return;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+}
+
+} // namespace WTF
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerJettisonReason.h b/Source/JavaScriptCore/profiler/ProfilerJettisonReason.h
new file mode 100644
index 000000000..0a15ba30e
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerJettisonReason.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfilerJettisonReason_h
+#define ProfilerJettisonReason_h
+
+namespace JSC { namespace Profiler {
+
+enum JettisonReason {
+ NotJettisoned,
+ JettisonDueToWeakReference,
+ JettisonDueToDebuggerBreakpoint,
+ JettisonDueToDebuggerStepping,
+ JettisonDueToLegacyProfiler,
+ JettisonDueToBaselineLoopReoptimizationTrigger,
+ JettisonDueToBaselineLoopReoptimizationTriggerOnOSREntryFail,
+ JettisonDueToOSRExit,
+ JettisonDueToProfiledWatchpoint,
+ JettisonDueToUnprofiledWatchpoint
+};
+
+} } // namespace JSC::Profiler
+
+namespace WTF {
+
+class PrintStream;
+void printInternal(PrintStream&, JSC::Profiler::JettisonReason);
+
+} // namespace WTF
+
+#endif // ProfilerJettisonReason_h
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerOSRExit.cpp b/Source/JavaScriptCore/profiler/ProfilerOSRExit.cpp
new file mode 100644
index 000000000..2a5d5be40
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerOSRExit.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfilerOSRExit.h"
+
+#include "JSGlobalObject.h"
+#include "ObjectConstructor.h"
+#include "JSCInlines.h"
+
+namespace JSC { namespace Profiler {
+
+OSRExit::OSRExit(unsigned id, const OriginStack& origin, ExitKind kind, bool isWatchpoint)
+ : m_id(id)
+ , m_origin(origin)
+ , m_exitKind(kind)
+ , m_isWatchpoint(isWatchpoint)
+ , m_counter(0)
+{
+}
+
+OSRExit::~OSRExit()
+{
+}
+
+JSValue OSRExit::toJS(ExecState* exec) const
+{
+ JSObject* result = constructEmptyObject(exec);
+ result->putDirect(exec->vm(), exec->propertyNames().id, jsNumber(m_id));
+ result->putDirect(exec->vm(), exec->propertyNames().origin, m_origin.toJS(exec));
+ result->putDirect(exec->vm(), exec->propertyNames().exitKind, jsString(exec, exitKindToString(m_exitKind)));
+ result->putDirect(exec->vm(), exec->propertyNames().isWatchpoint, jsBoolean(m_isWatchpoint));
+ result->putDirect(exec->vm(), exec->propertyNames().count, jsNumber(m_counter));
+ return result;
+}
+
+} } // namespace JSC::Profiler
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerOSRExit.h b/Source/JavaScriptCore/profiler/ProfilerOSRExit.h
new file mode 100644
index 000000000..2a23d0b2c
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerOSRExit.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfilerOSRExit_h
+#define ProfilerOSRExit_h
+
+#include "ExitKind.h"
+#include "JSCJSValue.h"
+#include "ProfilerOriginStack.h"
+
+namespace JSC { namespace Profiler {
+
+class OSRExit {
+public:
+ OSRExit(unsigned id, const OriginStack&, ExitKind, bool isWatchpoint);
+ ~OSRExit();
+
+ unsigned id() const { return m_id; }
+ const OriginStack& origin() const { return m_origin; }
+ ExitKind exitKind() const { return m_exitKind; }
+ bool isWatchpoint() const { return m_isWatchpoint; }
+
+ uint64_t* counterAddress() { return &m_counter; }
+ uint64_t count() const { return m_counter; }
+
+ JSValue toJS(ExecState*) const;
+
+private:
+ unsigned m_id;
+ OriginStack m_origin;
+ ExitKind m_exitKind;
+ bool m_isWatchpoint;
+ uint64_t m_counter;
+};
+
+} } // namespace JSC::Profiler
+
+#endif // ProfilerOSRExit_h
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.cpp b/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.cpp
new file mode 100644
index 000000000..b17d57e52
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfilerOSRExitSite.h"
+
+#include "JSGlobalObject.h"
+#include "JSScope.h"
+#include "JSString.h"
+#include "JSCInlines.h"
+#include <wtf/StringPrintStream.h>
+
+namespace JSC { namespace Profiler {
+
+JSValue OSRExitSite::toJS(ExecState* exec) const
+{
+ JSArray* result = constructEmptyArray(exec, 0);
+ for (unsigned i = 0; i < m_codeAddresses.size(); ++i)
+ result->putDirectIndex(exec, i, jsString(exec, toString(RawPointer(m_codeAddresses[i]))));
+ return result;
+}
+
+} } // namespace JSC::Profiler
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.h b/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.h
new file mode 100644
index 000000000..fa418e9b8
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfilerOSRExitSite_h
+#define ProfilerOSRExitSite_h
+
+#include "JSCJSValue.h"
+#include <wtf/Vector.h>
+
+namespace JSC { namespace Profiler {
+
+class OSRExitSite {
+public:
+ explicit OSRExitSite(const Vector<const void*>& codeAddresses)
+ : m_codeAddresses(codeAddresses)
+ {
+ }
+
+ const Vector<const void*>& codeAddress() const { return m_codeAddresses; }
+
+ JSValue toJS(ExecState*) const;
+
+private:
+ Vector<const void*> m_codeAddresses;
+};
+
+} } // namespace JSC::Profiler
+
+#endif // ProfilerOSRExitSite_h
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerOrigin.cpp b/Source/JavaScriptCore/profiler/ProfilerOrigin.cpp
new file mode 100644
index 000000000..7c28f7ba3
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerOrigin.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfilerOrigin.h"
+
+#include "JSGlobalObject.h"
+#include "ObjectConstructor.h"
+#include "JSCInlines.h"
+#include "ProfilerBytecodes.h"
+#include "ProfilerDatabase.h"
+
+namespace JSC { namespace Profiler {
+
+Origin::Origin(Database& database, CodeBlock* codeBlock, unsigned bytecodeIndex)
+ : m_bytecodes(database.ensureBytecodesFor(codeBlock))
+ , m_bytecodeIndex(bytecodeIndex)
+{
+}
+
+void Origin::dump(PrintStream& out) const
+{
+ out.print(*m_bytecodes, ":bc#", m_bytecodeIndex);
+}
+
+JSValue Origin::toJS(ExecState* exec) const
+{
+ JSObject* result = constructEmptyObject(exec);
+ result->putDirect(exec->vm(), exec->propertyNames().bytecodesID, jsNumber(m_bytecodes->id()));
+ result->putDirect(exec->vm(), exec->propertyNames().bytecodeIndex, jsNumber(m_bytecodeIndex));
+ return result;
+}
+
+} } // namespace JSC::Profiler
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerOrigin.h b/Source/JavaScriptCore/profiler/ProfilerOrigin.h
new file mode 100644
index 000000000..09b388451
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerOrigin.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfilerOrigin_h
+#define ProfilerOrigin_h
+
+#include "CodeBlockHash.h"
+#include "JSCJSValue.h"
+#include <wtf/HashMap.h>
+#include <wtf/PrintStream.h>
+
+namespace JSC {
+
+class CodeBlock;
+
+namespace Profiler {
+
+class Bytecodes;
+class Database;
+
+class Origin {
+public:
+ Origin()
+ : m_bytecodeIndex(std::numeric_limits<unsigned>::max())
+ {
+ }
+
+ Origin(WTF::HashTableDeletedValueType)
+ : m_bytecodeIndex(std::numeric_limits<unsigned>::max() - 1)
+ {
+ }
+
+ Origin(Bytecodes* bytecodes, unsigned bytecodeIndex)
+ : m_bytecodes(bytecodes)
+ , m_bytecodeIndex(bytecodeIndex)
+ {
+ ASSERT(m_bytecodeIndex < std::numeric_limits<unsigned>::max() - 1);
+ }
+
+ Origin(Database&, CodeBlock*, unsigned bytecodeIndex);
+
+ bool operator!() const { return m_bytecodeIndex == std::numeric_limits<unsigned>::max(); }
+
+ Bytecodes* bytecodes() const { return m_bytecodes; }
+ unsigned bytecodeIndex() const { return m_bytecodeIndex; }
+
+ bool operator==(const Origin&) const;
+ bool operator!=(const Origin& other) const { return !(*this == other); }
+ unsigned hash() const;
+
+ bool isHashTableDeletedValue() const;
+
+ void dump(PrintStream&) const;
+ JSValue toJS(ExecState*) const;
+
+private:
+ Bytecodes* m_bytecodes;
+ unsigned m_bytecodeIndex;
+};
+
+inline bool Origin::operator==(const Origin& other) const
+{
+ return m_bytecodes == other.m_bytecodes
+ && m_bytecodeIndex == other.m_bytecodeIndex;
+}
+
+inline unsigned Origin::hash() const
+{
+ return WTF::PtrHash<Bytecodes*>::hash(m_bytecodes) + m_bytecodeIndex;
+}
+
+inline bool Origin::isHashTableDeletedValue() const
+{
+ return m_bytecodeIndex == std::numeric_limits<unsigned>::max();
+}
+
+struct OriginHash {
+ static unsigned hash(const Origin& key) { return key.hash(); }
+ static bool equal(const Origin& a, const Origin& b) { return a == b; }
+ static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+} } // namespace JSC::Profiler
+
+namespace WTF {
+
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<JSC::Profiler::Origin> {
+ typedef JSC::Profiler::OriginHash Hash;
+};
+
+template<typename T> struct HashTraits;
+template<> struct HashTraits<JSC::Profiler::Origin> : SimpleClassHashTraits<JSC::Profiler::Origin> { };
+
+} // namespace WTF
+
+#endif // ProfilerOrigin_h
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerOriginStack.cpp b/Source/JavaScriptCore/profiler/ProfilerOriginStack.cpp
new file mode 100644
index 000000000..9b61daec1
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerOriginStack.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfilerOriginStack.h"
+
+#include "CodeOrigin.h"
+#include "JSGlobalObject.h"
+#include "JSCInlines.h"
+#include "ProfilerDatabase.h"
+
+namespace JSC { namespace Profiler {
+
+OriginStack::OriginStack(WTF::HashTableDeletedValueType)
+{
+ m_stack.append(Origin(WTF::HashTableDeletedValue));
+}
+
+OriginStack::OriginStack(const Origin& origin)
+{
+ m_stack.append(origin);
+}
+
+OriginStack::OriginStack(Database& database, CodeBlock* codeBlock, const CodeOrigin& codeOrigin)
+{
+ Vector<CodeOrigin> stack = codeOrigin.inlineStack();
+
+ append(Origin(database, codeBlock, stack[0].bytecodeIndex));
+
+ for (unsigned i = 1; i < stack.size(); ++i) {
+ append(Origin(
+ database.ensureBytecodesFor(stack[i].inlineCallFrame->baselineCodeBlock()),
+ stack[i].bytecodeIndex));
+ }
+}
+
+OriginStack::~OriginStack() { }
+
+void OriginStack::append(const Origin& origin)
+{
+ m_stack.append(origin);
+}
+
+bool OriginStack::operator==(const OriginStack& other) const
+{
+ if (m_stack.size() != other.m_stack.size())
+ return false;
+
+ for (unsigned i = m_stack.size(); i--;) {
+ if (m_stack[i] != other.m_stack[i])
+ return false;
+ }
+
+ return true;
+}
+
+unsigned OriginStack::hash() const
+{
+ unsigned result = m_stack.size();
+
+ for (unsigned i = m_stack.size(); i--;) {
+ result *= 3;
+ result += m_stack[i].hash();
+ }
+
+ return result;
+}
+
+void OriginStack::dump(PrintStream& out) const
+{
+ for (unsigned i = 0; i < m_stack.size(); ++i) {
+ if (i)
+ out.print(" --> ");
+ out.print(m_stack[i]);
+ }
+}
+
+JSValue OriginStack::toJS(ExecState* exec) const
+{
+ JSArray* result = constructEmptyArray(exec, 0);
+
+ for (unsigned i = 0; i < m_stack.size(); ++i)
+ result->putDirectIndex(exec, i, m_stack[i].toJS(exec));
+
+ return result;
+}
+
+} } // namespace JSC::Profiler
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerOriginStack.h b/Source/JavaScriptCore/profiler/ProfilerOriginStack.h
new file mode 100644
index 000000000..415e8d9b0
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerOriginStack.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfilerOriginStack_h
+#define ProfilerOriginStack_h
+
+#include "JSCJSValue.h"
+#include "ProfilerOrigin.h"
+#include <wtf/HashMap.h>
+#include <wtf/PrintStream.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class CodeBlock;
+struct CodeOrigin;
+
+namespace Profiler {
+
+class Database;
+
+class OriginStack {
+public:
+ OriginStack() { }
+
+ OriginStack(WTF::HashTableDeletedValueType);
+
+ explicit OriginStack(const Origin&);
+
+ explicit OriginStack(Database&, CodeBlock*, const CodeOrigin&);
+
+ ~OriginStack();
+
+ void append(const Origin&);
+
+ bool operator!() const { return m_stack.isEmpty(); }
+
+ unsigned size() const { return m_stack.size(); }
+ const Origin& fromBottom(unsigned i) const { return m_stack[i]; }
+ const Origin& fromTop(unsigned i) const { return m_stack[m_stack.size() - i - 1]; }
+
+ bool operator==(const OriginStack&) const;
+ unsigned hash() const;
+
+ bool isHashTableDeletedValue() const;
+
+ void dump(PrintStream&) const;
+ JSValue toJS(ExecState*) const;
+
+private:
+ Vector<Origin, 1> m_stack;
+};
+
+inline bool OriginStack::isHashTableDeletedValue() const
+{
+ return m_stack.size() == 1 && m_stack[0].isHashTableDeletedValue();
+}
+
+struct OriginStackHash {
+ static unsigned hash(const OriginStack& key) { return key.hash(); }
+ static bool equal(const OriginStack& a, const OriginStack& b) { return a == b; }
+ static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+} } // namespace JSC::Profiler
+
+namespace WTF {
+
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<JSC::Profiler::OriginStack> {
+ typedef JSC::Profiler::OriginStackHash Hash;
+};
+
+template<typename T> struct HashTraits;
+template<> struct HashTraits<JSC::Profiler::OriginStack> : SimpleClassHashTraits<JSC::Profiler::OriginStack> { };
+
+} // namespace WTF
+
+#endif // ProfilerOriginStack_h
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.cpp b/Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.cpp
new file mode 100644
index 000000000..fe590ff78
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfilerProfiledBytecodes.h"
+
+#include "JSGlobalObject.h"
+#include "ObjectConstructor.h"
+#include "JSCInlines.h"
+
+namespace JSC { namespace Profiler {
+
+ProfiledBytecodes::ProfiledBytecodes(Bytecodes* bytecodes, CodeBlock* profiledBlock)
+ : BytecodeSequence(profiledBlock)
+ , m_bytecodes(bytecodes)
+{
+}
+
+ProfiledBytecodes::~ProfiledBytecodes()
+{
+}
+
+JSValue ProfiledBytecodes::toJS(ExecState* exec) const
+{
+ JSObject* result = constructEmptyObject(exec);
+
+ result->putDirect(exec->vm(), exec->propertyNames().bytecodesID, jsNumber(m_bytecodes->id()));
+ addSequenceProperties(exec, result);
+
+ return result;
+}
+
+} } // namespace JSC::Profiler
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.h b/Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.h
new file mode 100644
index 000000000..d7cb6ffa8
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfilerProfiledBytecodes_h
+#define ProfilerProfiledBytecodes_h
+
+#include "ProfilerBytecodeSequence.h"
+#include "ProfilerBytecodes.h"
+#include "ProfilerOriginStack.h"
+
+namespace JSC { namespace Profiler {
+
+class ProfiledBytecodes : public BytecodeSequence {
+public:
+ ProfiledBytecodes(Bytecodes*, CodeBlock*);
+ ~ProfiledBytecodes();
+
+ const Bytecodes* bytecodes() const { return m_bytecodes; }
+
+ JSValue toJS(ExecState*) const;
+
+private:
+ Bytecodes* m_bytecodes;
+};
+
+} } // namespace JSC::Profiler
+
+#endif // ProfilerProfiledBytecodes_h
+