summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/profiler
diff options
context:
space:
mode:
authorKonstantin Tokarev <annulen@yandex.ru>2016-08-25 19:20:41 +0300
committerKonstantin Tokarev <annulen@yandex.ru>2017-02-02 12:30:55 +0000
commit6882a04fb36642862b11efe514251d32070c3d65 (patch)
treeb7959826000b061fd5ccc7512035c7478742f7b0 /Source/JavaScriptCore/profiler
parentab6df191029eeeb0b0f16f127d553265659f739e (diff)
downloadqtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/JavaScriptCore/profiler')
-rw-r--r--Source/JavaScriptCore/profiler/CallIdentifier.h43
-rw-r--r--Source/JavaScriptCore/profiler/LegacyProfiler.cpp103
-rw-r--r--Source/JavaScriptCore/profiler/LegacyProfiler.h26
-rw-r--r--Source/JavaScriptCore/profiler/Profile.cpp78
-rw-r--r--Source/JavaScriptCore/profiler/Profile.h48
-rw-r--r--Source/JavaScriptCore/profiler/ProfileGenerator.cpp194
-rw-r--r--Source/JavaScriptCore/profiler/ProfileGenerator.h29
-rw-r--r--Source/JavaScriptCore/profiler/ProfileNode.cpp263
-rw-r--r--Source/JavaScriptCore/profiler/ProfileNode.h205
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerBytecode.cpp2
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp16
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerBytecodes.cpp6
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerBytecodes.h10
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerCompilation.cpp46
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerCompilation.h16
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerCompilationKind.cpp8
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerCompilationKind.h6
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerCompiledBytecode.cpp2
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerDatabase.cpp40
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerDatabase.h11
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerExecutionCounter.h2
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerJettisonReason.cpp76
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerJettisonReason.h55
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerOSRExit.cpp2
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerOSRExitSite.cpp2
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerOrigin.cpp2
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerOriginStack.cpp5
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.cpp2
28 files changed, 700 insertions, 598 deletions
diff --git a/Source/JavaScriptCore/profiler/CallIdentifier.h b/Source/JavaScriptCore/profiler/CallIdentifier.h
index bf9f904b0..691fc6250 100644
--- a/Source/JavaScriptCore/profiler/CallIdentifier.h
+++ b/Source/JavaScriptCore/profiler/CallIdentifier.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * 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
@@ -36,32 +36,37 @@ namespace JSC {
struct CallIdentifier {
WTF_MAKE_FAST_ALLOCATED;
public:
- String m_name;
- String m_url;
- unsigned m_lineNumber;
-
CallIdentifier()
: m_lineNumber(0)
+ , m_columnNumber(0)
{
}
- CallIdentifier(const String& name, const String& url, int lineNumber)
- : m_name(name)
+ 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)
{
}
- inline bool operator==(const CallIdentifier& ci) const { return ci.m_lineNumber == m_lineNumber && ci.m_name == m_name && ci.m_url == m_url; }
- inline bool operator!=(const CallIdentifier& ci) const { return !(*this == ci); }
+ 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[3] = {
- key.m_name.impl()->hash(),
+ unsigned hashCodes[4] = {
+ key.m_functionName.impl()->hash(),
key.m_url.impl()->hash(),
- key.m_lineNumber
+ key.m_lineNumber,
+ key.m_columnNumber
};
return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
}
@@ -74,8 +79,14 @@ namespace JSC {
#ifndef NDEBUG
operator const char*() const { return c_str(); }
- const char* c_str() const { return m_name.utf8().data(); }
+ 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
@@ -87,15 +98,15 @@ namespace WTF {
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());
+ 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.m_name.isNull() && value.m_url.isNull() && value.m_lineNumber == std::numeric_limits<unsigned>::max();
+ 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
index 1db2e625e..787d362dc 100644
--- a/Source/JavaScriptCore/profiler/LegacyProfiler.cpp
+++ b/Source/JavaScriptCore/profiler/LegacyProfiler.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2012 Apple Inc. All rights reserved.
+ * 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
@@ -10,7 +10,7 @@
* 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 Computer, Inc. ("Apple") nor the names of
+ * 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.
*
@@ -36,11 +36,10 @@
#include "JSFunction.h"
#include "JSGlobalObject.h"
#include "Nodes.h"
-#include "Operations.h"
+#include "JSCInlines.h"
#include "Profile.h"
#include "ProfileGenerator.h"
#include "ProfileNode.h"
-#include <stdio.h>
namespace JSC {
@@ -48,21 +47,19 @@ static const char* GlobalCodeExecution = "(program)";
static const char* AnonymousFunction = "(anonymous function)";
static unsigned ProfilesUID = 0;
-static CallIdentifier createCallIdentifierFromFunctionImp(ExecState*, JSObject*, const String& defaultSourceURL, int defaultLineNumber);
+static CallIdentifier createCallIdentifierFromFunctionImp(ExecState*, JSObject*, const String& defaultSourceURL, unsigned defaultLineNumber, unsigned defaultColumnNumber);
-LegacyProfiler* LegacyProfiler::s_sharedLegacyProfiler = 0;
+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)
+void LegacyProfiler::startProfiling(ExecState* exec, const String& title, PassRefPtr<Stopwatch> stopwatch)
{
- ASSERT_ARG(title, !title.isNull());
-
if (!exec)
return;
@@ -76,15 +73,15 @@ void LegacyProfiler::startProfiling(ExecState* exec, const String& title)
return;
}
- exec->vm().m_enabledProfiler = this;
- RefPtr<ProfileGenerator> profileGenerator = ProfileGenerator::create(exec, title, ++ProfilesUID);
+ exec->vm().setEnabledProfiler(this);
+ RefPtr<ProfileGenerator> profileGenerator = ProfileGenerator::create(exec, title, ++ProfilesUID, stopwatch);
m_currentProfiles.append(profileGenerator);
}
-PassRefPtr<Profile> LegacyProfiler::stopProfiling(ExecState* exec, const String& title)
+RefPtr<Profile> LegacyProfiler::stopProfiling(ExecState* exec, const String& title)
{
if (!exec)
- return 0;
+ return nullptr;
JSGlobalObject* origin = exec->lexicalGlobalObject();
for (ptrdiff_t i = m_currentProfiles.size() - 1; i >= 0; --i) {
@@ -95,13 +92,13 @@ PassRefPtr<Profile> LegacyProfiler::stopProfiling(ExecState* exec, const String&
m_currentProfiles.remove(i);
if (!m_currentProfiles.size())
- exec->vm().m_enabledProfiler = 0;
-
+ exec->vm().setEnabledProfiler(nullptr);
+
return returnProfile;
}
}
- return 0;
+ return nullptr;
}
void LegacyProfiler::stopProfiling(JSGlobalObject* origin)
@@ -112,74 +109,100 @@ void LegacyProfiler::stopProfiling(JSGlobalObject* origin)
profileGenerator->stopProfiling();
m_currentProfiles.remove(i);
if (!m_currentProfiles.size())
- origin->vm().m_enabledProfiler = 0;
+ origin->vm().setEnabledProfiler(nullptr);
}
}
}
-static inline void dispatchFunctionToProfiles(ExecState* callerOrHandlerCallFrame, const Vector<RefPtr<ProfileGenerator> >& profiles, ProfileGenerator::ProfileFunction function, const CallIdentifier& callIdentifier, unsigned currentProfileTargetGroup)
+static inline void callFunctionForProfilesWithGroup(std::function<void(ProfileGenerator*)> callback, const Vector<RefPtr<ProfileGenerator>>& profiles, unsigned targetProfileGroup)
{
- for (size_t i = 0; i < profiles.size(); ++i) {
- if (profiles[i]->profileGroup() == currentProfileTargetGroup || !profiles[i]->origin())
- (profiles[i].get()->*function)(callerOrHandlerCallFrame, callIdentifier);
+ 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());
- dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::willExecute, createCallIdentifier(callerCallFrame, function, "", 0), callerCallFrame->lexicalGlobalObject()->profileGroup());
+ 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, int startingLineNumber)
+void LegacyProfiler::willExecute(ExecState* callerCallFrame, const String& sourceURL, unsigned startingLineNumber, unsigned startingColumnNumber)
{
ASSERT(!m_currentProfiles.isEmpty());
- CallIdentifier callIdentifier = createCallIdentifier(callerCallFrame, JSValue(), sourceURL, startingLineNumber);
+ CallIdentifier callIdentifier = createCallIdentifier(callerCallFrame, JSValue(), sourceURL, startingLineNumber, startingColumnNumber);
- dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::willExecute, callIdentifier, callerCallFrame->lexicalGlobalObject()->profileGroup());
+ 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());
- dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(callerCallFrame, function, "", 0), callerCallFrame->lexicalGlobalObject()->profileGroup());
+ 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, int startingLineNumber)
+void LegacyProfiler::didExecute(ExecState* callerCallFrame, const String& sourceURL, unsigned startingLineNumber, unsigned startingColumnNumber)
{
ASSERT(!m_currentProfiles.isEmpty());
- dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(callerCallFrame, JSValue(), sourceURL, startingLineNumber), callerCallFrame->lexicalGlobalObject()->profileGroup());
+ 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());
- dispatchFunctionToProfiles(handlerCallFrame, m_currentProfiles, &ProfileGenerator::exceptionUnwind, createCallIdentifier(handlerCallFrame, JSValue(), "", 0), handlerCallFrame->lexicalGlobalObject()->profileGroup());
+ 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, int defaultLineNumber)
+CallIdentifier LegacyProfiler::createCallIdentifier(ExecState* exec, JSValue functionValue, const String& defaultSourceURL, unsigned defaultLineNumber, unsigned defaultColumnNumber)
{
if (!functionValue)
- return CallIdentifier(GlobalCodeExecution, defaultSourceURL, defaultLineNumber);
+ return CallIdentifier(ASCIILiteral(GlobalCodeExecution), defaultSourceURL, defaultLineNumber, defaultColumnNumber);
if (!functionValue.isObject())
- return CallIdentifier("(unknown)", defaultSourceURL, defaultLineNumber);
- if (asObject(functionValue)->inherits(&JSFunction::s_info) || asObject(functionValue)->inherits(&InternalFunction::s_info))
- return createCallIdentifierFromFunctionImp(exec, asObject(functionValue), defaultSourceURL, defaultLineNumber);
- return CallIdentifier(makeString("(", asObject(functionValue)->methodTable()->className(asObject(functionValue)), " object)"), defaultSourceURL, defaultLineNumber);
+ 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, int defaultLineNumber)
+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->isHostFunction())
- return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, jsFunction->jsExecutable()->sourceURL(), jsFunction->jsExecutable()->lineNo());
- return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, defaultSourceURL, defaultLineNumber);
+ 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
index 6db57cbf2..af0ab41e2 100644
--- a/Source/JavaScriptCore/profiler/LegacyProfiler.h
+++ b/Source/JavaScriptCore/profiler/LegacyProfiler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2012 Apple Inc. All rights reserved.
+ * 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
@@ -10,7 +10,7 @@
* 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 Computer, Inc. ("Apple") nor the names of
+ * 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.
*
@@ -32,12 +32,12 @@
#include "Profile.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefPtr.h>
+#include <wtf/Stopwatch.h>
#include <wtf/Vector.h>
namespace JSC {
class ExecState;
-class VM;
class JSGlobalObject;
class JSObject;
class JSValue;
@@ -47,24 +47,28 @@ struct CallIdentifier;
class LegacyProfiler {
WTF_MAKE_FAST_ALLOCATED;
public:
- JS_EXPORT_PRIVATE static LegacyProfiler* profiler();
- static CallIdentifier createCallIdentifier(ExecState*, JSValue, const WTF::String& sourceURL, int lineNumber);
+ 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);
- JS_EXPORT_PRIVATE PassRefPtr<Profile> stopProfiling(ExecState*, const WTF::String& title);
+ 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, int startingLineNumber);
+ 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, int startingLineNumber);
+ void didExecute(ExecState* callerCallFrame, const WTF::String& sourceURL, unsigned startingLineNumber, unsigned startingColumnNumber);
void exceptionUnwind(ExecState* handlerCallFrame);
- const Vector<RefPtr<ProfileGenerator> >& currentProfiles() { return m_currentProfiles; };
+ const Vector<RefPtr<ProfileGenerator>>& currentProfiles() { return m_currentProfiles; };
private:
- Vector<RefPtr<ProfileGenerator> > m_currentProfiles;
+ Vector<RefPtr<ProfileGenerator>> m_currentProfiles;
static LegacyProfiler* s_sharedLegacyProfiler;
};
diff --git a/Source/JavaScriptCore/profiler/Profile.cpp b/Source/JavaScriptCore/profiler/Profile.cpp
index 2274889a1..f3d450ab2 100644
--- a/Source/JavaScriptCore/profiler/Profile.cpp
+++ b/Source/JavaScriptCore/profiler/Profile.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * 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
@@ -27,84 +27,38 @@
#include "Profile.h"
#include "ProfileNode.h"
-#include <stdio.h>
#include <wtf/DataLog.h>
namespace JSC {
-PassRefPtr<Profile> Profile::create(const String& title, unsigned uid)
+Ref<Profile> Profile::create(const String& title, unsigned uid, double startTime)
{
- return adoptRef(new Profile(title, uid));
+ return adoptRef(*new Profile(title, uid, startTime));
}
-Profile::Profile(const String& title, unsigned uid)
+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_head = ProfileNode::create(0, CallIdentifier("Thread_1", String(), 0), 0, 0);
+ m_rootNode = ProfileNode::create(nullptr, CallIdentifier(ASCIILiteral("Thread_1"), String(), 0, 0), nullptr);
+ m_rootNode->appendCall(ProfileNode::Call(startTime));
}
Profile::~Profile()
{
}
-void Profile::forEach(void (ProfileNode::*function)())
-{
- ProfileNode* currentNode = m_head->firstChild();
- for (ProfileNode* nextNode = currentNode; nextNode; nextNode = nextNode->firstChild())
- currentNode = nextNode;
-
- if (!currentNode)
- currentNode = m_head.get();
-
- ProfileNode* endNode = m_head->traverseNextNodePostOrder();
- while (currentNode && currentNode != endNode) {
- (currentNode->*function)();
- currentNode = currentNode->traverseNextNodePostOrder();
- }
-}
-
-void Profile::focus(const ProfileNode* profileNode)
-{
- if (!profileNode || !m_head)
- return;
-
- bool processChildren;
- const CallIdentifier& callIdentifier = profileNode->callIdentifier();
- for (ProfileNode* currentNode = m_head.get(); currentNode; currentNode = currentNode->traverseNextNodePreOrder(processChildren))
- processChildren = currentNode->focus(callIdentifier);
-
- // Set the visible time of all nodes so that the %s display correctly.
- forEach(&ProfileNode::calculateVisibleTotalTime);
-}
-
-void Profile::exclude(const ProfileNode* profileNode)
-{
- if (!profileNode || !m_head)
- return;
-
- const CallIdentifier& callIdentifier = profileNode->callIdentifier();
-
- for (ProfileNode* currentNode = m_head.get(); currentNode; currentNode = currentNode->traverseNextNodePreOrder())
- currentNode->exclude(callIdentifier);
-
- // Set the visible time of the head so the %s display correctly.
- m_head->setVisibleTotalTime(m_head->totalTime() - m_head->selfTime());
- m_head->setVisibleSelfTime(0.0);
-}
-
-void Profile::restoreAll()
-{
- forEach(&ProfileNode::restore);
-}
-
#ifndef NDEBUG
-void Profile::debugPrintData() const
+void Profile::debugPrint()
{
+ CalculateProfileSubtreeDataFunctor functor;
+ m_rootNode->forEachNodePostorder(functor);
+ ProfileNode::ProfileSubtreeData data = functor.returnValue();
+
dataLogF("Call graph:\n");
- m_head->debugPrintData(0);
+ m_rootNode->debugPrintRecursively(0, data);
}
typedef WTF::KeyValuePair<FunctionCallHashCount::ValueType, unsigned> NameCountPair;
@@ -114,13 +68,17 @@ static inline bool functionNameCountPairComparator(const NameCountPair& a, const
return a.value > b.value;
}
-void Profile::debugPrintDataSampleStyle() const
+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_head->debugPrintDataSampleStyle(0, countedFunctions);
+ m_rootNode->debugPrintSampleStyleRecursively(0, countedFunctions, data);
dataLogF("\nTotal number in stack:\n");
NameCountPairVector sortedFunctions(countedFunctions.size());
diff --git a/Source/JavaScriptCore/profiler/Profile.h b/Source/JavaScriptCore/profiler/Profile.h
index c1c69193c..41cb670ca 100644
--- a/Source/JavaScriptCore/profiler/Profile.h
+++ b/Source/JavaScriptCore/profiler/Profile.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * 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
@@ -33,39 +33,33 @@
namespace JSC {
- class Profile : public RefCounted<Profile> {
- public:
- static PassRefPtr<Profile> create(const String& title, unsigned uid);
- virtual ~Profile();
+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; }
- ProfileNode* head() const { return m_head.get(); }
- void setHead(PassRefPtr<ProfileNode> head) { m_head = head; }
- double totalTime() const { return m_head->totalTime(); }
- unsigned int uid() const { return m_uid; }
+ const String& title() const { return m_title; }
+ unsigned uid() const { return m_uid; }
- JS_EXPORT_PRIVATE void forEach(void (ProfileNode::*)());
-
- JS_EXPORT_PRIVATE void focus(const ProfileNode*);
- JS_EXPORT_PRIVATE void exclude(const ProfileNode*);
- JS_EXPORT_PRIVATE void restoreAll();
+ ProfileNode* rootNode() const { return m_rootNode.get(); }
+ void setRootNode(PassRefPtr<ProfileNode> rootNode) { m_rootNode = rootNode; }
#ifndef NDEBUG
- void debugPrintData() const;
- void debugPrintDataSampleStyle() const;
+ void debugPrint();
+ void debugPrintSampleStyle();
#endif
- protected:
- Profile(const String& title, unsigned uid);
+protected:
+ Profile(const String& title, unsigned uid, double startTime);
- private:
- void removeProfileStart();
- void removeProfileEnd();
-
- String m_title;
- RefPtr<ProfileNode> m_head;
- unsigned int m_uid;
- };
+private:
+ void removeProfileStart();
+ void removeProfileEnd();
+
+ String m_title;
+ RefPtr<ProfileNode> m_rootNode;
+ unsigned m_uid;
+};
} // namespace JSC
diff --git a/Source/JavaScriptCore/profiler/ProfileGenerator.cpp b/Source/JavaScriptCore/profiler/ProfileGenerator.cpp
index d240aff34..f70e4a3f6 100644
--- a/Source/JavaScriptCore/profiler/ProfileGenerator.cpp
+++ b/Source/JavaScriptCore/profiler/ProfileGenerator.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * 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
@@ -31,41 +31,80 @@
#include "JSGlobalObject.h"
#include "JSStringRef.h"
#include "JSFunction.h"
-#include "Interpreter.h"
#include "LegacyProfiler.h"
-#include "Operations.h"
+#include "JSCInlines.h"
#include "Profile.h"
+#include "StackVisitor.h"
#include "Tracing.h"
namespace JSC {
-static const char* NonJSExecution = "(idle)";
-
-PassRefPtr<ProfileGenerator> ProfileGenerator::create(ExecState* exec, const String& title, unsigned uid)
+Ref<ProfileGenerator> ProfileGenerator::create(ExecState* exec, const String& title, unsigned uid, PassRefPtr<Stopwatch> stopwatch)
{
- return adoptRef(new ProfileGenerator(exec, title, uid));
+ return adoptRef(*new ProfileGenerator(exec, title, uid, stopwatch));
}
-ProfileGenerator::ProfileGenerator(ExecState* exec, const String& title, unsigned uid)
- : m_origin(exec ? exec->lexicalGlobalObject() : 0)
+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)
{
- m_profile = Profile::create(title, uid);
- m_currentNode = m_head = m_profile->head();
+ double startTime = m_stopwatch->elapsedTime();
+ m_profile = Profile::create(title, uid, startTime);
+ m_currentNode = m_rootNode = m_profile->rootNode();
if (exec)
- addParentForConsoleStart(exec);
+ addParentForConsoleStart(exec, startTime);
}
-void ProfileGenerator::addParentForConsoleStart(ExecState* exec)
+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)
{
- int lineNumber;
- intptr_t sourceID;
- String sourceURL;
- JSValue function;
-
- exec->interpreter()->retrieveLastCaller(exec, lineNumber, sourceID, sourceURL, function);
- m_currentNode = ProfileNode::create(exec, LegacyProfiler::createCallIdentifier(exec, function ? function.toThisObject(exec) : 0, sourceURL, lineNumber), m_head.get(), m_head.get());
- m_head->insertNode(m_currentNode.get());
+ AddParentForConsoleStartFunctor functor(exec, m_rootNode, m_currentNode, startTime);
+ exec->iterate(functor);
+
+ m_foundConsoleStartParent = functor.foundParent();
}
const String& ProfileGenerator::title() const
@@ -73,46 +112,92 @@ 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.m_name.utf8();
- CString url = callIdentifier.m_url.utf8();
- JAVASCRIPTCORE_PROFILE_WILL_EXECUTE(m_profileGroup, const_cast<char*>(name.data()), const_cast<char*>(url.data()), callIdentifier.m_lineNumber);
+ 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;
- ASSERT(m_currentNode);
- m_currentNode = m_currentNode->willExecute(callerCallFrame, callIdentifier);
+ 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.m_name.utf8();
- CString url = callIdentifier.m_url.utf8();
- JAVASCRIPTCORE_PROFILE_DID_EXECUTE(m_profileGroup, const_cast<char*>(name.data()), const_cast<char*>(url.data()), callIdentifier.m_lineNumber);
+ 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> returningNode = ProfileNode::create(callerCallFrame, callIdentifier, m_head.get(), m_currentNode.get());
- returningNode->setStartTime(m_currentNode->startTime());
- returningNode->didExecute();
- m_currentNode->insertNode(returningNode.release());
+ 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;
}
- m_currentNode = m_currentNode->didExecute();
+ 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);
@@ -124,57 +209,44 @@ void ProfileGenerator::exceptionUnwind(ExecState* handlerCallFrame, const CallId
void ProfileGenerator::stopProfiling()
{
- m_profile->forEach(&ProfileNode::stopProfiling);
+ for (ProfileNode* node = m_currentNode.get(); node != m_profile->rootNode(); node = node->parent())
+ endCallEntry(node);
- removeProfileStart();
- removeProfileEnd();
+ 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();
-
- if (double headSelfTime = m_head->selfTime()) {
- RefPtr<ProfileNode> idleNode = ProfileNode::create(0, CallIdentifier(NonJSExecution, String(), 0), m_head.get(), m_head.get());
-
- idleNode->setTotalTime(headSelfTime);
- idleNode->setSelfTime(headSelfTime);
- idleNode->setVisible(true);
-
- m_head->setSelfTime(0.0);
- m_head->addChild(idleNode.release());
- }
}
-// The console.ProfileGenerator that started this ProfileGenerator will be the first child.
+// The console.profile that started this ProfileGenerator will be the first child.
void ProfileGenerator::removeProfileStart()
{
- ProfileNode* currentNode = 0;
- for (ProfileNode* next = m_head.get(); next; next = next->firstChild())
+ ProfileNode* currentNode = nullptr;
+ for (ProfileNode* next = m_rootNode.get(); next; next = next->firstChild())
currentNode = next;
- if (currentNode->callIdentifier().m_name != "profile")
+ if (currentNode->callIdentifier().functionName() != "profile")
return;
- // Attribute the time of the node aobut to be removed to the self time of its parent
- currentNode->parent()->setSelfTime(currentNode->parent()->selfTime() + currentNode->totalTime());
currentNode->parent()->removeChild(currentNode);
}
-// The console.ProfileGeneratorEnd that stopped this ProfileGenerator will be the last child.
+// The console.profileEnd that stopped this ProfileGenerator will be the last child.
void ProfileGenerator::removeProfileEnd()
{
- ProfileNode* currentNode = 0;
- for (ProfileNode* next = m_head.get(); next; next = next->lastChild())
+ ProfileNode* currentNode = nullptr;
+ for (ProfileNode* next = m_rootNode.get(); next; next = next->lastChild())
currentNode = next;
- if (currentNode->callIdentifier().m_name != "profileEnd")
+ if (currentNode->callIdentifier().functionName() != "profileEnd")
return;
- // Attribute the time of the node aobut to be removed to the self time of its parent
- currentNode->parent()->setSelfTime(currentNode->parent()->selfTime() + currentNode->totalTime());
-
ASSERT(currentNode->callIdentifier() == (currentNode->parent()->children()[currentNode->parent()->children().size() - 1])->callIdentifier());
currentNode->parent()->removeChild(currentNode);
}
diff --git a/Source/JavaScriptCore/profiler/ProfileGenerator.h b/Source/JavaScriptCore/profiler/ProfileGenerator.h
index 40cc8de01..387ed5f4a 100644
--- a/Source/JavaScriptCore/profiler/ProfileGenerator.h
+++ b/Source/JavaScriptCore/profiler/ProfileGenerator.h
@@ -22,26 +22,28 @@
* (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 "Profile.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;
+ struct CallIdentifier;
class ProfileGenerator : public RefCounted<ProfileGenerator> {
public:
- static PassRefPtr<ProfileGenerator> create(ExecState*, const WTF::String& title, unsigned uid);
+ static Ref<ProfileGenerator> create(ExecState*, const WTF::String& title, unsigned uid, PassRefPtr<Stopwatch>);
// Members
const WTF::String& title() const;
@@ -49,29 +51,32 @@ namespace JSC {
JSGlobalObject* origin() const { return m_origin; }
unsigned profileGroup() const { return m_profileGroup; }
- // Collecting
void willExecute(ExecState* callerCallFrame, const CallIdentifier&);
void didExecute(ExecState* callerCallFrame, const CallIdentifier&);
-
void exceptionUnwind(ExecState* handlerCallFrame, const CallIdentifier&);
- // Stopping Profiling
- void stopProfiling();
+ void setIsSuspended(bool suspended) { ASSERT(m_suspended != suspended); m_suspended = suspended; }
- typedef void (ProfileGenerator::*ProfileFunction)(ExecState* callerOrHandlerCallFrame, const CallIdentifier& callIdentifier);
+ void stopProfiling();
private:
- ProfileGenerator(ExecState*, const WTF::String& title, unsigned uid);
- void addParentForConsoleStart(ExecState*);
+ 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<ProfileNode> m_head;
+ RefPtr<Stopwatch> m_stopwatch;
+ RefPtr<ProfileNode> m_rootNode;
RefPtr<ProfileNode> m_currentNode;
+ bool m_foundConsoleStartParent;
+ bool m_suspended;
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/profiler/ProfileNode.cpp b/Source/JavaScriptCore/profiler/ProfileNode.cpp
index 5b6a25411..9bcf37586 100644
--- a/Source/JavaScriptCore/profiler/ProfileNode.cpp
+++ b/Source/JavaScriptCore/profiler/ProfileNode.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * 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
@@ -10,7 +10,7 @@
* 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 Computer, Inc. ("Apple") nor the names of
+ * 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.
*
@@ -30,126 +30,63 @@
#include "ProfileNode.h"
#include "LegacyProfiler.h"
-#include <stdio.h>
#include <wtf/DateMath.h>
#include <wtf/DataLog.h>
#include <wtf/text/StringHash.h>
-#if OS(WINDOWS)
-#include <windows.h>
-#endif
-
using namespace WTF;
namespace JSC {
-static double getCount()
-{
-#if OS(WINDOWS)
- static LARGE_INTEGER frequency;
- if (!frequency.QuadPart)
- QueryPerformanceFrequency(&frequency);
- LARGE_INTEGER counter;
- QueryPerformanceCounter(&counter);
- return static_cast<double>(counter.QuadPart) / frequency.QuadPart;
-#else
- return currentTimeMS();
-#endif
-}
-
-ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
+ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* parentNode)
: m_callerCallFrame(callerCallFrame)
, m_callIdentifier(callIdentifier)
- , m_head(headNode)
, m_parent(parentNode)
- , m_nextSibling(0)
- , m_startTime(0.0)
- , m_actualTotalTime(0.0)
- , m_visibleTotalTime(0.0)
- , m_actualSelfTime(0.0)
- , m_visibleSelfTime(0.0)
- , m_numberOfCalls(0)
- , m_visible(true)
+#ifndef NDEBUG
+ , m_nextSibling(nullptr)
+#endif
{
- startTimer();
}
-ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* nodeToCopy)
+ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* nodeToCopy)
: m_callerCallFrame(callerCallFrame)
, m_callIdentifier(nodeToCopy->callIdentifier())
- , m_head(headNode)
, m_parent(nodeToCopy->parent())
- , m_nextSibling(0)
- , m_startTime(0.0)
- , m_actualTotalTime(nodeToCopy->actualTotalTime())
- , m_visibleTotalTime(nodeToCopy->totalTime())
- , m_actualSelfTime(nodeToCopy->actualSelfTime())
- , m_visibleSelfTime(nodeToCopy->selfTime())
- , m_numberOfCalls(nodeToCopy->numberOfCalls())
- , m_visible(nodeToCopy->visible())
-{
-}
-
-ProfileNode* ProfileNode::willExecute(ExecState* callerCallFrame, const CallIdentifier& callIdentifier)
-{
- for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild) {
- if ((*currentChild)->callIdentifier() == callIdentifier) {
- (*currentChild)->startTimer();
- return (*currentChild).get();
- }
- }
-
- RefPtr<ProfileNode> newChild = ProfileNode::create(callerCallFrame, callIdentifier, m_head ? m_head : this, this); // If this ProfileNode has no head it is the head.
- if (m_children.size())
- m_children.last()->setNextSibling(newChild.get());
- m_children.append(newChild.release());
- return m_children.last().get();
-}
-
-ProfileNode* ProfileNode::didExecute()
+ , m_calls(nodeToCopy->calls())
+#ifndef NDEBUG
+ , m_nextSibling(nullptr)
+#endif
{
- endAndRecordCall();
- return m_parent;
}
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());
}
-ProfileNode* ProfileNode::findChild(ProfileNode* node) const
-{
- if (!node)
- return 0;
-
- for (size_t i = 0; i < m_children.size(); ++i) {
- if (*node == m_children[i].get())
- return m_children[i].get();
- }
-
- return 0;
-}
-
void ProfileNode::removeChild(ProfileNode* node)
{
if (!node)
return;
- for (size_t i = 0; i < m_children.size(); ++i) {
- if (*node == m_children[i].get()) {
- m_children.remove(i);
- break;
- }
- }
-
- resetChildrensSiblings();
+ 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::insertNode(PassRefPtr<ProfileNode> prpNode)
+void ProfileNode::spliceNode(PassRefPtr<ProfileNode> prpNode)
{
RefPtr<ProfileNode> node = prpNode;
@@ -160,24 +97,7 @@ void ProfileNode::insertNode(PassRefPtr<ProfileNode> prpNode)
m_children.append(node.release());
}
-void ProfileNode::stopProfiling()
-{
- if (m_startTime)
- endAndRecordCall();
-
- m_visibleTotalTime = m_actualTotalTime;
-
- ASSERT(m_actualSelfTime == 0.0 && m_startTime == 0.0);
-
- // Because we iterate in post order all of our children have been stopped before us.
- for (unsigned i = 0; i < m_children.size(); ++i)
- m_actualSelfTime += m_children[i]->totalTime();
-
- ASSERT(m_actualSelfTime <= m_actualTotalTime);
- m_actualSelfTime = m_actualTotalTime - m_actualSelfTime;
- m_visibleSelfTime = m_actualSelfTime;
-}
-
+#ifndef NDEBUG
ProfileNode* ProfileNode::traverseNextNodePostOrder() const
{
ProfileNode* next = m_nextSibling;
@@ -188,136 +108,63 @@ ProfileNode* ProfileNode::traverseNextNodePostOrder() const
return next;
}
-ProfileNode* ProfileNode::traverseNextNodePreOrder(bool processChildren) const
+void ProfileNode::debugPrint()
{
- if (processChildren && m_children.size())
- return m_children[0].get();
+ CalculateProfileSubtreeDataFunctor functor;
+ forEachNodePostorder(functor);
+ ProfileNode::ProfileSubtreeData data = functor.returnValue();
- if (m_nextSibling)
- return m_nextSibling;
-
- ProfileNode* nextParent = m_parent;
- if (!nextParent)
- return 0;
-
- ProfileNode* next;
- for (next = m_parent->nextSibling(); !next; next = nextParent->nextSibling()) {
- nextParent = nextParent->parent();
- if (!nextParent)
- return 0;
- }
-
- return next;
-}
-
-void ProfileNode::setTreeVisible(ProfileNode* node, bool visible)
-{
- ProfileNode* nodeParent = node->parent();
- ProfileNode* nodeSibling = node->nextSibling();
- node->setParent(0);
- node->setNextSibling(0);
-
- for (ProfileNode* currentNode = node; currentNode; currentNode = currentNode->traverseNextNodePreOrder())
- currentNode->setVisible(visible);
-
- node->setParent(nodeParent);
- node->setNextSibling(nodeSibling);
-}
-
-void ProfileNode::calculateVisibleTotalTime()
-{
- double sumOfVisibleChildrensTime = 0.0;
-
- for (unsigned i = 0; i < m_children.size(); ++i) {
- if (m_children[i]->visible())
- sumOfVisibleChildrensTime += m_children[i]->totalTime();
- }
-
- m_visibleTotalTime = m_visibleSelfTime + sumOfVisibleChildrensTime;
-}
-
-bool ProfileNode::focus(const CallIdentifier& callIdentifier)
-{
- if (!m_visible)
- return false;
-
- if (m_callIdentifier != callIdentifier) {
- m_visible = false;
- return true;
- }
-
- for (ProfileNode* currentParent = m_parent; currentParent; currentParent = currentParent->parent())
- currentParent->setVisible(true);
-
- return false;
-}
-
-void ProfileNode::exclude(const CallIdentifier& callIdentifier)
-{
- if (m_visible && m_callIdentifier == callIdentifier) {
- setTreeVisible(this, false);
-
- m_parent->setVisibleSelfTime(m_parent->selfTime() + m_visibleTotalTime);
- }
-}
-
-void ProfileNode::restore()
-{
- m_visibleTotalTime = m_actualTotalTime;
- m_visibleSelfTime = m_actualSelfTime;
- m_visible = true;
+ debugPrintRecursively(0, data);
}
-void ProfileNode::endAndRecordCall()
+void ProfileNode::debugPrintSampleStyle()
{
- m_actualTotalTime += m_startTime ? getCount() - m_startTime : 0.0;
- m_startTime = 0.0;
-
- ++m_numberOfCalls;
-}
+ FunctionCallHashCount countedFunctions;
-void ProfileNode::startTimer()
-{
- if (!m_startTime)
- m_startTime = getCount();
-}
+ CalculateProfileSubtreeDataFunctor functor;
+ forEachNodePostorder(functor);
+ ProfileNode::ProfileSubtreeData data = functor.returnValue();
-void ProfileNode::resetChildrensSiblings()
-{
- unsigned size = m_children.size();
- for (unsigned i = 0; i < size; ++i)
- m_children[i]->setNextSibling(i + 1 == size ? 0 : m_children[i + 1].get());
+ debugPrintSampleStyleRecursively(0, countedFunctions, data);
}
-#ifndef NDEBUG
-void ProfileNode::debugPrintData(int indentLevel) const
+void ProfileNode::debugPrintRecursively(int indentLevel, const ProfileSubtreeData& data)
{
// Print function names
for (int i = 0; i < indentLevel; ++i)
dataLogF(" ");
- dataLogF("Function Name %s %d SelfTime %.3fms/%.3f%% TotalTime %.3fms/%.3f%% VSelf %.3fms VTotal %.3fms Visible %s Next Sibling %s\n",
- functionName().utf8().data(),
- m_numberOfCalls, m_actualSelfTime, selfPercent(), m_actualTotalTime, totalPercent(),
- m_visibleSelfTime, m_visibleTotalTime,
- (m_visible ? "True" : "False"),
+ 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)->debugPrintData(indentLevel);
+ (*currentChild)->debugPrintRecursively(indentLevel, data);
}
// print the profiled data in a format that matches the tool sample's output.
-double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount& countedFunctions) const
+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 = m_actualTotalTime * 1000;
+ double sampleCount = nodeTotalTime * 1000;
if (indentLevel) {
for (int i = 0; i < indentLevel; ++i)
dataLogF(" ");
@@ -333,7 +180,7 @@ double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashC
// Print children's names and information
double sumOfChildrensCount = 0.0;
for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild)
- sumOfChildrensCount += (*currentChild)->debugPrintDataSampleStyle(indentLevel, countedFunctions);
+ sumOfChildrensCount += (*currentChild)->debugPrintSampleStyleRecursively(indentLevel, countedFunctions, data);
sumOfChildrensCount *= 1000; //
// Print remainder of samples to match sample's output
@@ -345,7 +192,7 @@ double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashC
dataLogF("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data());
}
- return m_actualTotalTime;
+ return nodeTotalTime;
}
#endif
diff --git a/Source/JavaScriptCore/profiler/ProfileNode.h b/Source/JavaScriptCore/profiler/ProfileNode.h
index f5fef86f8..7ad149e17 100644
--- a/Source/JavaScriptCore/profiler/ProfileNode.h
+++ b/Source/JavaScriptCore/profiler/ProfileNode.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * 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
@@ -10,7 +10,7 @@
* 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 Computer, Inc. ("Apple") nor the names of
+ * 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.
*
@@ -40,133 +40,154 @@ namespace JSC {
class ExecState;
class ProfileNode;
- typedef Vector<RefPtr<ProfileNode> >::const_iterator StackIterator;
typedef HashCountedSet<StringImpl*> FunctionCallHashCount;
class ProfileNode : public RefCounted<ProfileNode> {
public:
- static PassRefPtr<ProfileNode> create(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
+ static Ref<ProfileNode> create(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* parentNode)
{
- return adoptRef(new ProfileNode(callerCallFrame, callIdentifier, headNode, parentNode));
+ return adoptRef(*new ProfileNode(callerCallFrame, callIdentifier, parentNode));
}
- static PassRefPtr<ProfileNode> create(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* node)
+
+ static Ref<ProfileNode> create(ExecState* callerCallFrame, ProfileNode* node)
{
- return adoptRef(new ProfileNode(callerCallFrame, headNode, node));
+ return adoptRef(*new ProfileNode(callerCallFrame, node));
}
- bool operator==(ProfileNode* node) { return m_callIdentifier == node->callIdentifier(); }
-
- ProfileNode* willExecute(ExecState* callerCallFrame, const CallIdentifier&);
- ProfileNode* didExecute();
+ 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;
+ };
- void stopProfiling();
+ bool operator==(ProfileNode* node) { return m_callIdentifier == node->callIdentifier(); }
- // CallIdentifier members
ExecState* callerCallFrame() const { return m_callerCallFrame; }
const CallIdentifier& callIdentifier() const { return m_callIdentifier; }
- unsigned long callUID() const { return m_callIdentifier.hash(); };
- const String& functionName() const { return m_callIdentifier.m_name; }
- const String& url() const { return m_callIdentifier.m_url; }
- unsigned lineNumber() const { return m_callIdentifier.m_lineNumber; }
-
- // Relationships
- ProfileNode* head() const { return m_head; }
- void setHead(ProfileNode* head) { m_head = head; }
+ 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; }
- ProfileNode* nextSibling() const { return m_nextSibling; }
- void setNextSibling(ProfileNode* nextSibling) { m_nextSibling = nextSibling; }
- // Time members
- double startTime() const { return m_startTime; }
- void setStartTime(double startTime) { m_startTime = startTime; }
- double totalTime() const { return m_visibleTotalTime; }
- double actualTotalTime() const { return m_actualTotalTime; }
- void setTotalTime(double time) { m_actualTotalTime = time; m_visibleTotalTime = time; }
- void setActualTotalTime(double time) { m_actualTotalTime = time; }
- void setVisibleTotalTime(double time) { m_visibleTotalTime = time; }
- double selfTime() const { return m_visibleSelfTime; }
- double actualSelfTime() const { return m_actualSelfTime; }
- void setSelfTime(double time) {m_actualSelfTime = time; m_visibleSelfTime = time; }
- void setActualSelfTime(double time) { m_actualSelfTime = time; }
- void setVisibleSelfTime(double time) { m_visibleSelfTime = time; }
-
- double totalPercent() const { return (m_visibleTotalTime / (m_head ? m_head->totalTime() : totalTime())) * 100.0; }
- double selfPercent() const { return (m_visibleSelfTime / (m_head ? m_head->totalTime() : totalTime())) * 100.0; }
-
- unsigned numberOfCalls() const { return m_numberOfCalls; }
- void setNumberOfCalls(unsigned number) { m_numberOfCalls = number; }
-
- // Children members
- const Vector<RefPtr<ProfileNode> >& children() const { return m_children; }
- ProfileNode* firstChild() const { return m_children.size() ? m_children.first().get() : 0; }
- ProfileNode* lastChild() const { return m_children.size() ? m_children.last().get() : 0; }
- ProfileNode* findChild(ProfileNode*) const;
- void removeChild(ProfileNode*);
- void addChild(PassRefPtr<ProfileNode> prpChild);
- void insertNode(PassRefPtr<ProfileNode> prpNode);
+ 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); }
- // Visiblity
- bool visible() const { return m_visible; }
- void setVisible(bool visible) { m_visible = visible; }
+ 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; }
- static void setTreeVisible(ProfileNode*, bool visible);
+ 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>);
- // Sorting
- ProfileNode* traverseNextNodePostOrder() const;
- ProfileNode* traverseNextNodePreOrder(bool processChildren = true) const;
+#ifndef NDEBUG
+ struct ProfileSubtreeData {
+ HashMap<ProfileNode*, std::pair<double, double>> selfAndTotalTimes;
+ double rootTotalTime;
+ };
- // Views
- void calculateVisibleTotalTime();
- bool focus(const CallIdentifier&);
- void exclude(const CallIdentifier&);
- void restore();
+ // Use these functions to dump the subtree rooted at this node.
+ void debugPrint();
+ void debugPrintSampleStyle();
- void endAndRecordCall();
+ // These are used to recursively print entire subtrees using precomputed self and total times.
+ template <typename Functor> void forEachNodePostorder(Functor&);
-#ifndef NDEBUG
- const char* c_str() const { return m_callIdentifier; }
- void debugPrintData(int indentLevel) const;
- double debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount&) const;
+ void debugPrintRecursively(int indentLevel, const ProfileSubtreeData&);
+ double debugPrintSampleStyleRecursively(int indentLevel, FunctionCallHashCount&, const ProfileSubtreeData&);
#endif
private:
- ProfileNode(ExecState* callerCallFrame, const CallIdentifier&, ProfileNode* headNode, ProfileNode* parentNode);
- ProfileNode(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* nodeToCopy);
+ typedef Vector<RefPtr<ProfileNode>>::const_iterator StackIterator;
- void startTimer();
- void resetChildrensSiblings();
+ ProfileNode(ExecState* callerCallFrame, const CallIdentifier&, ProfileNode* parentNode);
+ ProfileNode(ExecState* callerCallFrame, ProfileNode* nodeToCopy);
- RefPtr<ProfileNode>* childrenBegin() { return m_children.begin(); }
- RefPtr<ProfileNode>* childrenEnd() { return m_children.end(); }
+#ifndef NDEBUG
+ ProfileNode* nextSibling() const { return m_nextSibling; }
+ void setNextSibling(ProfileNode* nextSibling) { m_nextSibling = nextSibling; }
- // Sorting comparators
- static inline bool totalTimeDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->totalTime() > b->totalTime(); }
- static inline bool totalTimeAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->totalTime() < b->totalTime(); }
- static inline bool selfTimeDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->selfTime() > b->selfTime(); }
- static inline bool selfTimeAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->selfTime() < b->selfTime(); }
- static inline bool callsDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->numberOfCalls() > b->numberOfCalls(); }
- static inline bool callsAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->numberOfCalls() < b->numberOfCalls(); }
- static inline bool functionNameDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return codePointCompareLessThan(b->functionName(), a->functionName()); }
- static inline bool functionNameAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return codePointCompareLessThan(a->functionName(), b->functionName()); }
+ ProfileNode* traverseNextNodePostOrder() const;
+#endif
ExecState* m_callerCallFrame;
CallIdentifier m_callIdentifier;
- ProfileNode* m_head;
ProfileNode* m_parent;
+ Vector<Call> m_calls;
+ Vector<RefPtr<ProfileNode>> m_children;
+
+#ifndef NDEBUG
ProfileNode* m_nextSibling;
+#endif
+ };
- double m_startTime;
- double m_actualTotalTime;
- double m_visibleTotalTime;
- double m_actualSelfTime;
- double m_visibleSelfTime;
- unsigned m_numberOfCalls;
+#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();
+ }
- bool m_visible;
+ functor(endNode);
+ }
- Vector<RefPtr<ProfileNode> > m_children;
+ 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 WTFMove(m_data); }
+
+ ProfileNode::ProfileSubtreeData m_data;
};
+#endif
} // namespace JSC
diff --git a/Source/JavaScriptCore/profiler/ProfilerBytecode.cpp b/Source/JavaScriptCore/profiler/ProfilerBytecode.cpp
index ca602e42f..6eeeb27b9 100644
--- a/Source/JavaScriptCore/profiler/ProfilerBytecode.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerBytecode.cpp
@@ -28,7 +28,7 @@
#include "JSGlobalObject.h"
#include "ObjectConstructor.h"
-#include "Operations.h"
+#include "JSCInlines.h"
namespace JSC { namespace Profiler {
diff --git a/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp b/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp
index a98b8bace..145ee44d1 100644
--- a/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * 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
@@ -29,7 +29,7 @@
#include "CodeBlock.h"
#include "JSGlobalObject.h"
#include "Operands.h"
-#include "Operations.h"
+#include "JSCInlines.h"
#include <wtf/StringPrintStream.h>
namespace JSC { namespace Profiler {
@@ -38,20 +38,22 @@ BytecodeSequence::BytecodeSequence(CodeBlock* codeBlock)
{
StringPrintStream out;
-#if ENABLE(VALUE_PROFILER)
for (unsigned i = 0; i < codeBlock->numberOfArgumentValueProfiles(); ++i) {
- CString description = codeBlock->valueProfileForArgument(i)->briefDescription();
+ ConcurrentJITLocker locker(codeBlock->m_lock);
+ CString description = codeBlock->valueProfileForArgument(i)->briefDescription(locker);
if (!description.length())
continue;
out.reset();
- out.print("arg", i, " (r", argumentToOperand(i), "): ", description);
+ out.print("arg", i, ": ", description);
m_header.append(out.toCString());
}
-#endif // ENABLE(VALUE_PROFILER)
+
+ StubInfoMap stubInfos;
+ codeBlock->getStubInfoMap(stubInfos);
for (unsigned bytecodeIndex = 0; bytecodeIndex < codeBlock->instructions().size();) {
out.reset();
- codeBlock->dumpBytecode(out, bytecodeIndex);
+ 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(
diff --git a/Source/JavaScriptCore/profiler/ProfilerBytecodes.cpp b/Source/JavaScriptCore/profiler/ProfilerBytecodes.cpp
index 3ae35dcc0..74c55abcf 100644
--- a/Source/JavaScriptCore/profiler/ProfilerBytecodes.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerBytecodes.cpp
@@ -29,7 +29,7 @@
#include "CodeBlock.h"
#include "JSGlobalObject.h"
#include "ObjectConstructor.h"
-#include "Operations.h"
+#include "JSCInlines.h"
#include <wtf/StringPrintStream.h>
namespace JSC { namespace Profiler {
@@ -56,8 +56,8 @@ 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, m_inferredName));
- result->putDirect(exec->vm(), exec->propertyNames().sourceCode, jsString(exec, m_sourceCode));
+ 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);
diff --git a/Source/JavaScriptCore/profiler/ProfilerBytecodes.h b/Source/JavaScriptCore/profiler/ProfilerBytecodes.h
index 47d856cb4..e44598019 100644
--- a/Source/JavaScriptCore/profiler/ProfilerBytecodes.h
+++ b/Source/JavaScriptCore/profiler/ProfilerBytecodes.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -40,8 +40,8 @@ public:
~Bytecodes();
size_t id() const { return m_id; }
- const String& inferredName() const { return m_inferredName; }
- const String& sourceCode() const { return m_sourceCode; }
+ 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; }
@@ -51,8 +51,8 @@ public:
private:
size_t m_id;
- String m_inferredName;
- String m_sourceCode;
+ CString m_inferredName;
+ CString m_sourceCode;
CodeBlockHash m_hash;
unsigned m_instructionCount;
};
diff --git a/Source/JavaScriptCore/profiler/ProfilerCompilation.cpp b/Source/JavaScriptCore/profiler/ProfilerCompilation.cpp
index f82414ffa..488f563de 100644
--- a/Source/JavaScriptCore/profiler/ProfilerCompilation.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerCompilation.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * 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
@@ -28,8 +28,9 @@
#include "JSGlobalObject.h"
#include "ObjectConstructor.h"
-#include "Operations.h"
+#include "JSCInlines.h"
#include "ProfilerDatabase.h"
+#include "Watchpoint.h"
#include <wtf/StringPrintStream.h>
namespace JSC { namespace Profiler {
@@ -37,6 +38,7 @@ 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)
@@ -67,16 +69,18 @@ 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)
{
- HashMap<OriginStack, OwnPtr<ExecutionCounter> >::iterator iter = m_counters.find(origin);
- if (iter != m_counters.end())
- return iter->value.get();
-
- OwnPtr<ExecutionCounter> counter = adoptPtr(new ExecutionCounter());
- ExecutionCounter* result = counter.get();
- m_counters.add(origin, counter.release());
- return result;
+ 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)
@@ -90,6 +94,18 @@ OSRExit* Compilation::addOSRExit(unsigned id, const OriginStack& originStack, Ex
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);
@@ -108,11 +124,10 @@ JSValue Compilation::toJS(ExecState* exec) const
result->putDirect(exec->vm(), exec->propertyNames().descriptions, descriptions);
JSArray* counters = constructEmptyArray(exec, 0);
- HashMap<OriginStack, OwnPtr<ExecutionCounter> >::const_iterator end = m_counters.end();
- for (HashMap<OriginStack, OwnPtr<ExecutionCounter> >::const_iterator iter = m_counters.begin(); iter != end; ++iter) {
+ for (auto it = m_counters.begin(), end = m_counters.end(); it != end; ++it) {
JSObject* counterEntry = constructEmptyObject(exec);
- counterEntry->putDirect(exec->vm(), exec->propertyNames().origin, iter->key.toJS(exec));
- counterEntry->putDirect(exec->vm(), exec->propertyNames().executionCount, jsNumber(iter->value->count()));
+ 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);
@@ -130,6 +145,9 @@ JSValue Compilation::toJS(ExecState* exec) const
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;
}
diff --git a/Source/JavaScriptCore/profiler/ProfilerCompilation.h b/Source/JavaScriptCore/profiler/ProfilerCompilation.h
index b3183fa02..b358b659c 100644
--- a/Source/JavaScriptCore/profiler/ProfilerCompilation.h
+++ b/Source/JavaScriptCore/profiler/ProfilerCompilation.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * 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
@@ -31,6 +31,7 @@
#include "ProfilerCompilationKind.h"
#include "ProfilerCompiledBytecode.h"
#include "ProfilerExecutionCounter.h"
+#include "ProfilerJettisonReason.h"
#include "ProfilerOSRExit.h"
#include "ProfilerOSRExitSite.h"
#include "ProfilerOriginStack.h"
@@ -38,7 +39,11 @@
#include <wtf/RefCounted.h>
#include <wtf/SegmentedVector.h>
-namespace JSC { namespace Profiler {
+namespace JSC {
+
+class FireDetail;
+
+namespace Profiler {
class Bytecodes;
class Database;
@@ -63,18 +68,23 @@ public:
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, OwnPtr<ExecutionCounter> > m_counters;
+ HashMap<OriginStack, std::unique_ptr<ExecutionCounter>> m_counters;
Vector<OSRExitSite> m_osrExitSites;
SegmentedVector<OSRExit> m_osrExits;
unsigned m_numInlinedGetByIds;
diff --git a/Source/JavaScriptCore/profiler/ProfilerCompilationKind.cpp b/Source/JavaScriptCore/profiler/ProfilerCompilationKind.cpp
index 78ce70586..3fbe25192 100644
--- a/Source/JavaScriptCore/profiler/ProfilerCompilationKind.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerCompilationKind.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * 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
@@ -42,6 +42,12 @@ void printInternal(PrintStream& out, JSC::Profiler::CompilationKind kind)
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;
diff --git a/Source/JavaScriptCore/profiler/ProfilerCompilationKind.h b/Source/JavaScriptCore/profiler/ProfilerCompilationKind.h
index 4806d39b9..575ec2947 100644
--- a/Source/JavaScriptCore/profiler/ProfilerCompilationKind.h
+++ b/Source/JavaScriptCore/profiler/ProfilerCompilationKind.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * 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
@@ -31,7 +31,9 @@ namespace JSC { namespace Profiler {
enum CompilationKind {
LLInt,
Baseline,
- DFG
+ DFG,
+ FTL,
+ FTLForOSREntry
};
} } // namespace JSC::Profiler
diff --git a/Source/JavaScriptCore/profiler/ProfilerCompiledBytecode.cpp b/Source/JavaScriptCore/profiler/ProfilerCompiledBytecode.cpp
index 455a48ed9..4891c315c 100644
--- a/Source/JavaScriptCore/profiler/ProfilerCompiledBytecode.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerCompiledBytecode.cpp
@@ -28,7 +28,7 @@
#include "JSGlobalObject.h"
#include "ObjectConstructor.h"
-#include "Operations.h"
+#include "JSCInlines.h"
namespace JSC { namespace Profiler {
diff --git a/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp b/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp
index a2fffd955..fc952c0c2 100644
--- a/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp
@@ -29,21 +29,18 @@
#include "CodeBlock.h"
#include "JSONObject.h"
#include "ObjectConstructor.h"
-#include "Operations.h"
+#include "JSCInlines.h"
namespace JSC { namespace Profiler {
-#if COMPILER(MINGW) || COMPILER(MSVC7_OR_LOWER) || OS(WINCE)
-static int databaseCounter;
-#else
-static volatile int databaseCounter;
-#endif
-static SpinLock registrationLock = SPINLOCK_INITIALIZER;
-static int didRegisterAtExit;
+static std::atomic<int> databaseCounter;
+
+static StaticLock registrationLock;
+static std::atomic<int> didRegisterAtExit;
static Database* firstDatabase;
Database::Database(VM& vm)
- : m_databaseID(atomicIncrement(&databaseCounter))
+ : m_databaseID(++databaseCounter)
, m_vm(vm)
, m_shouldSaveAtExit(false)
, m_nextRegisteredDatabase(0)
@@ -60,6 +57,8 @@ Database::~Database()
Bytecodes* Database::ensureBytecodesFor(CodeBlock* codeBlock)
{
+ LockHolder locker(m_lock);
+
codeBlock = codeBlock->baselineVersion();
HashMap<CodeBlock*, Bytecodes*>::iterator iter = m_bytecodesMap.find(codeBlock);
@@ -76,19 +75,16 @@ Bytecodes* Database::ensureBytecodesFor(CodeBlock* codeBlock)
void Database::notifyDestruction(CodeBlock* codeBlock)
{
+ LockHolder locker(m_lock);
+
m_bytecodesMap.remove(codeBlock);
}
-PassRefPtr<Compilation> Database::newCompilation(Bytecodes* bytecodes, CompilationKind kind)
+void Database::addCompilation(PassRefPtr<Compilation> compilation)
{
- RefPtr<Compilation> compilation = adoptRef(new Compilation(bytecodes, kind));
+ ASSERT(!isCompilationThread());
+
m_compilations.append(compilation);
- return compilation.release();
-}
-
-PassRefPtr<Compilation> Database::newCompilation(CodeBlock* codeBlock, CompilationKind kind)
-{
- return newCompilation(ensureBytecodesFor(codeBlock), kind);
}
JSValue Database::toJS(ExecState* exec) const
@@ -118,7 +114,7 @@ String Database::toJSON() const
bool Database::save(const char* filename) const
{
- OwnPtr<FilePrintStream> out = FilePrintStream::open(filename, "w");
+ auto out = FilePrintStream::open(filename, "w");
if (!out)
return false;
@@ -139,17 +135,17 @@ void Database::registerToSaveAtExit(const char* filename)
void Database::addDatabaseToAtExit()
{
- if (atomicIncrement(&didRegisterAtExit) == 1)
+ if (++didRegisterAtExit == 1)
atexit(atExitCallback);
- TCMalloc_SpinLockHolder holder(&registrationLock);
+ LockHolder holder(registrationLock);
m_nextRegisteredDatabase = firstDatabase;
firstDatabase = this;
}
void Database::removeDatabaseFromAtExit()
{
- TCMalloc_SpinLockHolder holder(&registrationLock);
+ LockHolder holder(registrationLock);
for (Database** current = &firstDatabase; *current; current = &(*current)->m_nextRegisteredDatabase) {
if (*current != this)
continue;
@@ -167,7 +163,7 @@ void Database::performAtExitSave() const
Database* Database::removeFirstAtExitDatabase()
{
- TCMalloc_SpinLockHolder holder(&registrationLock);
+ LockHolder holder(registrationLock);
Database* result = firstDatabase;
if (result) {
firstDatabase = result->m_nextRegisteredDatabase;
diff --git a/Source/JavaScriptCore/profiler/ProfilerDatabase.h b/Source/JavaScriptCore/profiler/ProfilerDatabase.h
index 172c8eeac..9bb64cf49 100644
--- a/Source/JavaScriptCore/profiler/ProfilerDatabase.h
+++ b/Source/JavaScriptCore/profiler/ProfilerDatabase.h
@@ -30,11 +30,13 @@
#include "ProfilerBytecodes.h"
#include "ProfilerCompilation.h"
#include "ProfilerCompilationKind.h"
-#include <wtf/FastAllocBase.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 {
@@ -50,8 +52,7 @@ public:
Bytecodes* ensureBytecodesFor(CodeBlock*);
void notifyDestruction(CodeBlock*);
- PassRefPtr<Compilation> newCompilation(CodeBlock*, CompilationKind);
- PassRefPtr<Compilation> newCompilation(Bytecodes*, CompilationKind);
+ 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
@@ -70,7 +71,6 @@ public:
void registerToSaveAtExit(const char* filename);
private:
-
void addDatabaseToAtExit();
void removeDatabaseFromAtExit();
void performAtExitSave() const;
@@ -81,10 +81,11 @@ private:
VM& m_vm;
SegmentedVector<Bytecodes> m_bytecodes;
HashMap<CodeBlock*, Bytecodes*> m_bytecodesMap;
- Vector<RefPtr<Compilation> > m_compilations;
+ Vector<RefPtr<Compilation>> m_compilations;
bool m_shouldSaveAtExit;
CString m_atExitSaveFilename;
Database* m_nextRegisteredDatabase;
+ Lock m_lock;
};
} } // namespace JSC::Profiler
diff --git a/Source/JavaScriptCore/profiler/ProfilerExecutionCounter.h b/Source/JavaScriptCore/profiler/ProfilerExecutionCounter.h
index 2884bc5dc..8989e38b5 100644
--- a/Source/JavaScriptCore/profiler/ProfilerExecutionCounter.h
+++ b/Source/JavaScriptCore/profiler/ProfilerExecutionCounter.h
@@ -26,7 +26,7 @@
#ifndef ProfilerExecutionCounter_h
#define ProfilerExecutionCounter_h
-#include <wtf/FastAllocBase.h>
+#include <wtf/FastMalloc.h>
#include <wtf/Noncopyable.h>
namespace JSC { namespace Profiler {
diff --git a/Source/JavaScriptCore/profiler/ProfilerJettisonReason.cpp b/Source/JavaScriptCore/profiler/ProfilerJettisonReason.cpp
new file mode 100644
index 000000000..3068ff34c
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerJettisonReason.cpp
@@ -0,0 +1,76 @@
+/*
+ * 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;
+ case JettisonDueToOldAge:
+ out.print("JettisonDueToOldAge");
+ 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..6a7932604
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerJettisonReason.h
@@ -0,0 +1,55 @@
+/*
+ * 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,
+ JettisonDueToOldAge
+};
+
+} } // 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
index 0024791b4..2a5d5be40 100644
--- a/Source/JavaScriptCore/profiler/ProfilerOSRExit.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerOSRExit.cpp
@@ -28,7 +28,7 @@
#include "JSGlobalObject.h"
#include "ObjectConstructor.h"
-#include "Operations.h"
+#include "JSCInlines.h"
namespace JSC { namespace Profiler {
diff --git a/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.cpp b/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.cpp
index d54f7a275..b17d57e52 100644
--- a/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.cpp
@@ -29,7 +29,7 @@
#include "JSGlobalObject.h"
#include "JSScope.h"
#include "JSString.h"
-#include "Operations.h"
+#include "JSCInlines.h"
#include <wtf/StringPrintStream.h>
namespace JSC { namespace Profiler {
diff --git a/Source/JavaScriptCore/profiler/ProfilerOrigin.cpp b/Source/JavaScriptCore/profiler/ProfilerOrigin.cpp
index 1ac29d1cc..7c28f7ba3 100644
--- a/Source/JavaScriptCore/profiler/ProfilerOrigin.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerOrigin.cpp
@@ -28,7 +28,7 @@
#include "JSGlobalObject.h"
#include "ObjectConstructor.h"
-#include "Operations.h"
+#include "JSCInlines.h"
#include "ProfilerBytecodes.h"
#include "ProfilerDatabase.h"
diff --git a/Source/JavaScriptCore/profiler/ProfilerOriginStack.cpp b/Source/JavaScriptCore/profiler/ProfilerOriginStack.cpp
index 018ceeb8c..b8eecdd60 100644
--- a/Source/JavaScriptCore/profiler/ProfilerOriginStack.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerOriginStack.cpp
@@ -27,8 +27,9 @@
#include "ProfilerOriginStack.h"
#include "CodeOrigin.h"
+#include "InlineCallFrame.h"
#include "JSGlobalObject.h"
-#include "Operations.h"
+#include "JSCInlines.h"
#include "ProfilerDatabase.h"
namespace JSC { namespace Profiler {
@@ -51,7 +52,7 @@ OriginStack::OriginStack(Database& database, CodeBlock* codeBlock, const CodeOri
for (unsigned i = 1; i < stack.size(); ++i) {
append(Origin(
- database.ensureBytecodesFor(stack[i].inlineCallFrame->baselineCodeBlock()),
+ database.ensureBytecodesFor(stack[i].inlineCallFrame->baselineCodeBlock.get()),
stack[i].bytecodeIndex));
}
}
diff --git a/Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.cpp b/Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.cpp
index 6ca6c9f15..fe590ff78 100644
--- a/Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.cpp
@@ -28,7 +28,7 @@
#include "JSGlobalObject.h"
#include "ObjectConstructor.h"
-#include "Operations.h"
+#include "JSCInlines.h"
namespace JSC { namespace Profiler {