summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/profiler
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2015-05-20 09:56:07 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2015-05-20 09:56:07 +0000
commit41386e9cb918eed93b3f13648cbef387e371e451 (patch)
treea97f9d7bd1d9d091833286085f72da9d83fd0606 /Source/JavaScriptCore/profiler
parente15dd966d523731101f70ccf768bba12435a0208 (diff)
downloadWebKitGtk-tarball-41386e9cb918eed93b3f13648cbef387e371e451.tar.gz
webkitgtk-2.4.9webkitgtk-2.4.9
Diffstat (limited to 'Source/JavaScriptCore/profiler')
-rw-r--r--Source/JavaScriptCore/profiler/CallIdentifier.h43
-rw-r--r--Source/JavaScriptCore/profiler/LegacyProfiler.cpp94
-rw-r--r--Source/JavaScriptCore/profiler/LegacyProfiler.h22
-rw-r--r--Source/JavaScriptCore/profiler/Profile.cpp43
-rw-r--r--Source/JavaScriptCore/profiler/Profile.h44
-rw-r--r--Source/JavaScriptCore/profiler/ProfileGenerator.cpp161
-rw-r--r--Source/JavaScriptCore/profiler/ProfileGenerator.h29
-rw-r--r--Source/JavaScriptCore/profiler/ProfileNode.cpp160
-rw-r--r--Source/JavaScriptCore/profiler/ProfileNode.h170
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerBytecode.cpp2
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp11
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerBytecodes.cpp2
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerCompilation.cpp26
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerCompilation.h14
-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.cpp14
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerDatabase.h16
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerJettisonReason.cpp73
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerJettisonReason.h54
-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.cpp2
-rw-r--r--Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.cpp2
26 files changed, 386 insertions, 618 deletions
diff --git a/Source/JavaScriptCore/profiler/CallIdentifier.h b/Source/JavaScriptCore/profiler/CallIdentifier.h
index 691fc6250..bf9f904b0 100644
--- a/Source/JavaScriptCore/profiler/CallIdentifier.h
+++ b/Source/JavaScriptCore/profiler/CallIdentifier.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2014 Apple Inc. All Rights Reserved.
+ * 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
@@ -36,37 +36,32 @@ 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& functionName, const String& url, unsigned lineNumber, unsigned columnNumber)
- : m_functionName(functionName)
+ CallIdentifier(const String& name, const String& url, int lineNumber)
+ : m_name(name)
, 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); }
+ 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); }
struct Hash {
static unsigned hash(const CallIdentifier& key)
{
- unsigned hashCodes[4] = {
- key.m_functionName.impl()->hash(),
+ unsigned hashCodes[3] = {
+ key.m_name.impl()->hash(),
key.m_url.impl()->hash(),
- key.m_lineNumber,
- key.m_columnNumber
+ key.m_lineNumber
};
return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
}
@@ -79,14 +74,8 @@ namespace JSC {
#ifndef NDEBUG
operator const char*() const { return c_str(); }
- const char* c_str() const { return m_functionName.utf8().data(); }
+ const char* c_str() const { return m_name.utf8().data(); }
#endif
-
- private:
- String m_functionName;
- String m_url;
- unsigned m_lineNumber;
- unsigned m_columnNumber;
};
} // namespace JSC
@@ -98,15 +87,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(), std::numeric_limits<unsigned>::max());
+ new (NotNull, &slot) JSC::CallIdentifier(String(), String(), 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();
+ return value.m_name.isNull() && value.m_url.isNull() && value.m_lineNumber == 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 787d362dc..dd2acd9f0 100644
--- a/Source/JavaScriptCore/profiler/LegacyProfiler.cpp
+++ b/Source/JavaScriptCore/profiler/LegacyProfiler.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2012, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 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
@@ -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 Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Computer, 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,7 +36,7 @@
#include "JSFunction.h"
#include "JSGlobalObject.h"
#include "Nodes.h"
-#include "JSCInlines.h"
+#include "Operations.h"
#include "Profile.h"
#include "ProfileGenerator.h"
#include "ProfileNode.h"
@@ -47,19 +47,21 @@ 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);
+static CallIdentifier createCallIdentifierFromFunctionImp(ExecState*, JSObject*, const String& defaultSourceURL, int defaultLineNumber);
-LegacyProfiler* LegacyProfiler::s_sharedLegacyProfiler = nullptr;
+LegacyProfiler* LegacyProfiler::s_sharedLegacyProfiler = 0;
LegacyProfiler* LegacyProfiler::profiler()
{
if (!s_sharedLegacyProfiler)
s_sharedLegacyProfiler = new LegacyProfiler();
return s_sharedLegacyProfiler;
-}
+}
-void LegacyProfiler::startProfiling(ExecState* exec, const String& title, PassRefPtr<Stopwatch> stopwatch)
+void LegacyProfiler::startProfiling(ExecState* exec, const String& title)
{
+ ASSERT_ARG(title, !title.isNull());
+
if (!exec)
return;
@@ -74,14 +76,14 @@ void LegacyProfiler::startProfiling(ExecState* exec, const String& title, PassRe
}
exec->vm().setEnabledProfiler(this);
- RefPtr<ProfileGenerator> profileGenerator = ProfileGenerator::create(exec, title, ++ProfilesUID, stopwatch);
+ RefPtr<ProfileGenerator> profileGenerator = ProfileGenerator::create(exec, title, ++ProfilesUID);
m_currentProfiles.append(profileGenerator);
}
-RefPtr<Profile> LegacyProfiler::stopProfiling(ExecState* exec, const String& title)
+PassRefPtr<Profile> LegacyProfiler::stopProfiling(ExecState* exec, const String& title)
{
if (!exec)
- return nullptr;
+ return 0;
JSGlobalObject* origin = exec->lexicalGlobalObject();
for (ptrdiff_t i = m_currentProfiles.size() - 1; i >= 0; --i) {
@@ -93,12 +95,12 @@ RefPtr<Profile> LegacyProfiler::stopProfiling(ExecState* exec, const String& tit
m_currentProfiles.remove(i);
if (!m_currentProfiles.size())
exec->vm().setEnabledProfiler(nullptr);
-
+
return returnProfile;
}
}
- return nullptr;
+ return 0;
}
void LegacyProfiler::stopProfiling(JSGlobalObject* origin)
@@ -114,95 +116,69 @@ void LegacyProfiler::stopProfiling(JSGlobalObject* origin)
}
}
-static inline void callFunctionForProfilesWithGroup(std::function<void(ProfileGenerator*)> callback, const Vector<RefPtr<ProfileGenerator>>& profiles, unsigned targetProfileGroup)
+static inline void dispatchFunctionToProfiles(ExecState* callerOrHandlerCallFrame, const Vector<RefPtr<ProfileGenerator>>& profiles, ProfileGenerator::ProfileFunction function, const CallIdentifier& callIdentifier, unsigned currentProfileTargetGroup)
{
- for (const RefPtr<ProfileGenerator>& profile : profiles) {
- if (profile->profileGroup() == targetProfileGroup || !profile->origin())
- callback(profile.get());
+ for (size_t i = 0; i < profiles.size(); ++i) {
+ if (profiles[i]->profileGroup() == currentProfileTargetGroup || !profiles[i]->origin())
+ (profiles[i].get()->*function)(callerOrHandlerCallFrame, callIdentifier);
}
}
-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());
+ dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::willExecute, createCallIdentifier(callerCallFrame, function, "", 0), callerCallFrame->lexicalGlobalObject()->profileGroup());
}
-void LegacyProfiler::willExecute(ExecState* callerCallFrame, const String& sourceURL, unsigned startingLineNumber, unsigned startingColumnNumber)
+void LegacyProfiler::willExecute(ExecState* callerCallFrame, const String& sourceURL, int startingLineNumber)
{
ASSERT(!m_currentProfiles.isEmpty());
- CallIdentifier callIdentifier = createCallIdentifier(callerCallFrame, JSValue(), sourceURL, startingLineNumber, startingColumnNumber);
+ CallIdentifier callIdentifier = createCallIdentifier(callerCallFrame, JSValue(), sourceURL, startingLineNumber);
- callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::willExecute, std::placeholders::_1, callerCallFrame, callIdentifier), m_currentProfiles, callerCallFrame->lexicalGlobalObject()->profileGroup());
+ dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::willExecute, callIdentifier, 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());
+ dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(callerCallFrame, function, "", 0), callerCallFrame->lexicalGlobalObject()->profileGroup());
}
-void LegacyProfiler::didExecute(ExecState* callerCallFrame, const String& sourceURL, unsigned startingLineNumber, unsigned startingColumnNumber)
+void LegacyProfiler::didExecute(ExecState* callerCallFrame, const String& sourceURL, int startingLineNumber)
{
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());
+ dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(callerCallFrame, JSValue(), sourceURL, startingLineNumber), 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());
+ dispatchFunctionToProfiles(handlerCallFrame, m_currentProfiles, &ProfileGenerator::exceptionUnwind, createCallIdentifier(handlerCallFrame, JSValue(), "", 0), handlerCallFrame->lexicalGlobalObject()->profileGroup());
}
-CallIdentifier LegacyProfiler::createCallIdentifier(ExecState* exec, JSValue functionValue, const String& defaultSourceURL, unsigned defaultLineNumber, unsigned defaultColumnNumber)
+CallIdentifier LegacyProfiler::createCallIdentifier(ExecState* exec, JSValue functionValue, const String& defaultSourceURL, int defaultLineNumber)
{
if (!functionValue)
- return CallIdentifier(ASCIILiteral(GlobalCodeExecution), defaultSourceURL, defaultLineNumber, defaultColumnNumber);
+ return CallIdentifier(GlobalCodeExecution, defaultSourceURL, defaultLineNumber);
if (!functionValue.isObject())
- return CallIdentifier(ASCIILiteral("(unknown)"), defaultSourceURL, defaultLineNumber, defaultColumnNumber);
+ return CallIdentifier("(unknown)", defaultSourceURL, defaultLineNumber);
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);
+ return createCallIdentifierFromFunctionImp(exec, asObject(functionValue), defaultSourceURL, defaultLineNumber);
+ return CallIdentifier(makeString("(", asObject(functionValue)->methodTable()->className(asObject(functionValue)), " object)"), defaultSourceURL, defaultLineNumber);
}
-CallIdentifier createCallIdentifierFromFunctionImp(ExecState* exec, JSObject* function, const String& defaultSourceURL, unsigned defaultLineNumber, unsigned defaultColumnNumber)
+CallIdentifier createCallIdentifierFromFunctionImp(ExecState* exec, JSObject* function, const String& defaultSourceURL, int defaultLineNumber)
{
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);
+ if (jsFunction && !jsFunction->isHostFunction())
+ return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, jsFunction->jsExecutable()->sourceURL(), jsFunction->jsExecutable()->lineNo());
+ return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, defaultSourceURL, defaultLineNumber);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/profiler/LegacyProfiler.h b/Source/JavaScriptCore/profiler/LegacyProfiler.h
index af0ab41e2..607ddec9d 100644
--- a/Source/JavaScriptCore/profiler/LegacyProfiler.h
+++ b/Source/JavaScriptCore/profiler/LegacyProfiler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2012, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 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
@@ -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 Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Computer, 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,21 +47,17 @@ 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 static LegacyProfiler* profiler();
+ static CallIdentifier createCallIdentifier(ExecState*, JSValue, const WTF::String& sourceURL, int lineNumber);
- JS_EXPORT_PRIVATE void startProfiling(ExecState*, const WTF::String& title, PassRefPtr<Stopwatch>);
- JS_EXPORT_PRIVATE RefPtr<Profile> stopProfiling(ExecState*, const WTF::String& title);
+ JS_EXPORT_PRIVATE void startProfiling(ExecState*, const WTF::String& title);
+ JS_EXPORT_PRIVATE PassRefPtr<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 willExecute(ExecState* callerCallFrame, const WTF::String& sourceURL, int startingLineNumber);
void didExecute(ExecState* callerCallFrame, JSValue function);
- void didExecute(ExecState* callerCallFrame, const WTF::String& sourceURL, unsigned startingLineNumber, unsigned startingColumnNumber);
+ void didExecute(ExecState* callerCallFrame, const WTF::String& sourceURL, int startingLineNumber);
void exceptionUnwind(ExecState* handlerCallFrame);
diff --git a/Source/JavaScriptCore/profiler/Profile.cpp b/Source/JavaScriptCore/profiler/Profile.cpp
index f3d450ab2..ed21e7879 100644
--- a/Source/JavaScriptCore/profiler/Profile.cpp
+++ b/Source/JavaScriptCore/profiler/Profile.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2014 Apple Inc. All Rights Reserved.
+ * 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
@@ -31,34 +31,45 @@
namespace JSC {
-Ref<Profile> Profile::create(const String& title, unsigned uid, double startTime)
+PassRefPtr<Profile> Profile::create(const String& title, unsigned uid)
{
- return adoptRef(*new Profile(title, uid, startTime));
+ return adoptRef(new Profile(title, uid));
}
-Profile::Profile(const String& title, unsigned uid, double startTime)
+Profile::Profile(const String& title, unsigned uid)
: 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));
+ m_head = ProfileNode::create(0, CallIdentifier("Thread_1", String(), 0), 0, 0);
}
Profile::~Profile()
{
}
-#ifndef NDEBUG
-void Profile::debugPrint()
+void Profile::forEach(void (ProfileNode::*function)())
{
- CalculateProfileSubtreeDataFunctor functor;
- m_rootNode->forEachNodePostorder(functor);
- ProfileNode::ProfileSubtreeData data = functor.returnValue();
+ 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();
+ }
+}
+#ifndef NDEBUG
+void Profile::debugPrintData() const
+{
dataLogF("Call graph:\n");
- m_rootNode->debugPrintRecursively(0, data);
+ m_head->debugPrintData(0);
}
typedef WTF::KeyValuePair<FunctionCallHashCount::ValueType, unsigned> NameCountPair;
@@ -68,17 +79,13 @@ static inline bool functionNameCountPairComparator(const NameCountPair& a, const
return a.value > b.value;
}
-void Profile::debugPrintSampleStyle()
+void Profile::debugPrintDataSampleStyle() const
{
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);
+ m_head->debugPrintDataSampleStyle(0, countedFunctions);
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 41cb670ca..b1f093d69 100644
--- a/Source/JavaScriptCore/profiler/Profile.h
+++ b/Source/JavaScriptCore/profiler/Profile.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2014 Apple Inc. All Rights Reserved.
+ * 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
@@ -33,33 +33,35 @@
namespace JSC {
-class JS_EXPORT_PRIVATE Profile : public RefCounted<Profile> {
-public:
- static Ref<Profile> create(const String& title, unsigned uid, double);
- virtual ~Profile();
+ class Profile : public RefCounted<Profile> {
+ public:
+ static PassRefPtr<Profile> create(const String& title, unsigned uid);
+ virtual ~Profile();
- const String& title() const { return m_title; }
- unsigned uid() const { return m_uid; }
+ 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; }
- ProfileNode* rootNode() const { return m_rootNode.get(); }
- void setRootNode(PassRefPtr<ProfileNode> rootNode) { m_rootNode = rootNode; }
+ void forEach(void (ProfileNode::*)());
#ifndef NDEBUG
- void debugPrint();
- void debugPrintSampleStyle();
+ void debugPrintData() const;
+ void debugPrintDataSampleStyle() const;
#endif
-protected:
- Profile(const String& title, unsigned uid, double startTime);
+ protected:
+ Profile(const String& title, unsigned uid);
-private:
- void removeProfileStart();
- void removeProfileEnd();
-
- String m_title;
- RefPtr<ProfileNode> m_rootNode;
- unsigned m_uid;
-};
+ private:
+ void removeProfileStart();
+ void removeProfileEnd();
+
+ String m_title;
+ RefPtr<ProfileNode> m_head;
+ unsigned int m_uid;
+ };
} // namespace JSC
diff --git a/Source/JavaScriptCore/profiler/ProfileGenerator.cpp b/Source/JavaScriptCore/profiler/ProfileGenerator.cpp
index f70e4a3f6..9361caf70 100644
--- a/Source/JavaScriptCore/profiler/ProfileGenerator.cpp
+++ b/Source/JavaScriptCore/profiler/ProfileGenerator.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2014 Apple Inc. All Rights Reserved.
+ * 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
@@ -27,46 +27,44 @@
#include "ProfileGenerator.h"
#include "CallFrame.h"
+#include "CallFrameInlines.h"
#include "CodeBlock.h"
#include "JSGlobalObject.h"
#include "JSStringRef.h"
#include "JSFunction.h"
#include "LegacyProfiler.h"
-#include "JSCInlines.h"
+#include "Operations.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)
+static const char* NonJSExecution = "(idle)";
+
+PassRefPtr<ProfileGenerator> ProfileGenerator::create(ExecState* exec, const String& title, unsigned uid)
{
- return adoptRef(*new ProfileGenerator(exec, title, uid, stopwatch));
+ return adoptRef(new ProfileGenerator(exec, title, uid));
}
-ProfileGenerator::ProfileGenerator(ExecState* exec, const String& title, unsigned uid, PassRefPtr<Stopwatch> stopwatch)
- : m_origin(exec ? exec->lexicalGlobalObject() : nullptr)
+ProfileGenerator::ProfileGenerator(ExecState* exec, const String& title, unsigned uid)
+ : m_origin(exec ? exec->lexicalGlobalObject() : 0)
, 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();
+ m_profile = Profile::create(title, uid);
+ m_currentNode = m_head = m_profile->head();
if (exec)
- addParentForConsoleStart(exec, startTime);
+ addParentForConsoleStart(exec);
}
class AddParentForConsoleStartFunctor {
public:
- AddParentForConsoleStartFunctor(ExecState* exec, RefPtr<ProfileNode>& rootNode, RefPtr<ProfileNode>& currentNode, double startTime)
+ AddParentForConsoleStartFunctor(ExecState* exec, RefPtr<ProfileNode>& head, RefPtr<ProfileNode>& currentNode)
: m_exec(exec)
, m_hasSkippedFirstFrame(false)
, m_foundParent(false)
- , m_rootNode(rootNode)
+ , m_head(head)
, m_currentNode(currentNode)
- , m_startTime(startTime)
{
}
@@ -80,11 +78,10 @@ public:
}
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());
+ unsigned unusedColumn = 0;
+ visitor->computeLineAndColumn(line, unusedColumn);
+ m_currentNode = ProfileNode::create(m_exec, LegacyProfiler::createCallIdentifier(m_exec, visitor->callee(), visitor->sourceURL(), line), m_head.get(), m_head.get());
+ m_head->insertNode(m_currentNode.get());
m_foundParent = true;
return StackVisitor::Done;
@@ -93,18 +90,20 @@ public:
private:
ExecState* m_exec;
bool m_hasSkippedFirstFrame;
- bool m_foundParent;
- RefPtr<ProfileNode>& m_rootNode;
+ bool m_foundParent;
+ RefPtr<ProfileNode>& m_head;
RefPtr<ProfileNode>& m_currentNode;
- double m_startTime;
};
-void ProfileGenerator::addParentForConsoleStart(ExecState* exec, double startTime)
+void ProfileGenerator::addParentForConsoleStart(ExecState* exec)
{
- AddParentForConsoleStartFunctor functor(exec, m_rootNode, m_currentNode, startTime);
+ AddParentForConsoleStartFunctor functor(exec, m_head, m_currentNode);
exec->iterate(functor);
- m_foundConsoleStartParent = functor.foundParent();
+ if (!functor.foundParent()) {
+ m_currentNode = ProfileNode::create(exec, LegacyProfiler::createCallIdentifier(exec, JSValue(), String(), 0), m_head.get(), m_head.get());
+ m_head->insertNode(m_currentNode.get());
+ }
}
const String& ProfileGenerator::title() const
@@ -112,92 +111,46 @@ 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());
+ 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);
}
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());
+ ASSERT(m_currentNode);
+ m_currentNode = m_currentNode->willExecute(callerCallFrame, callIdentifier);
}
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());
+ 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);
}
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());
+ 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());
return;
}
- endCallEntry(m_currentNode.get());
- m_currentNode = m_currentNode->parent();
+ m_currentNode = m_currentNode->didExecute();
}
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);
@@ -209,44 +162,56 @@ void ProfileGenerator::exceptionUnwind(ExecState* handlerCallFrame, const CallId
void ProfileGenerator::stopProfiling()
{
- for (ProfileNode* node = m_currentNode.get(); node != m_profile->rootNode(); node = node->parent())
- endCallEntry(node);
+ m_profile->forEach(&ProfileNode::stopProfiling);
- if (m_foundConsoleStartParent) {
- removeProfileStart();
- removeProfileEnd();
- }
+ 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);
+
+ m_head->setSelfTime(0.0);
+ m_head->addChild(idleNode.release());
+ }
}
// 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())
+ ProfileNode* currentNode = 0;
+ for (ProfileNode* next = m_head.get(); next; next = next->firstChild())
currentNode = next;
- if (currentNode->callIdentifier().functionName() != "profile")
+ if (currentNode->callIdentifier().m_name != "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.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())
+ ProfileNode* currentNode = 0;
+ for (ProfileNode* next = m_head.get(); next; next = next->lastChild())
currentNode = next;
- if (currentNode->callIdentifier().functionName() != "profileEnd")
+ if (currentNode->callIdentifier().m_name != "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 387ed5f4a..40cc8de01 100644
--- a/Source/JavaScriptCore/profiler/ProfileGenerator.h
+++ b/Source/JavaScriptCore/profiler/ProfileGenerator.h
@@ -22,28 +22,26 @@
* (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 Ref<ProfileGenerator> create(ExecState*, const WTF::String& title, unsigned uid, PassRefPtr<Stopwatch>);
+ static PassRefPtr<ProfileGenerator> create(ExecState*, const WTF::String& title, unsigned uid);
// Members
const WTF::String& title() const;
@@ -51,32 +49,29 @@ 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&);
- void setIsSuspended(bool suspended) { ASSERT(m_suspended != suspended); m_suspended = suspended; }
+ void exceptionUnwind(ExecState* handlerCallFrame, const CallIdentifier&);
+ // Stopping Profiling
void stopProfiling();
+ typedef void (ProfileGenerator::*ProfileFunction)(ExecState* callerOrHandlerCallFrame, const CallIdentifier& callIdentifier);
+
private:
- ProfileGenerator(ExecState*, const WTF::String& title, unsigned uid, PassRefPtr<Stopwatch>);
- void addParentForConsoleStart(ExecState*, double);
+ ProfileGenerator(ExecState*, const WTF::String& title, unsigned uid);
+ void addParentForConsoleStart(ExecState*);
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_head;
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 9bcf37586..fe2342ea4 100644
--- a/Source/JavaScriptCore/profiler/ProfileNode.cpp
+++ b/Source/JavaScriptCore/profiler/ProfileNode.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2014 Apple Inc. All rights reserved.
+ * 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
@@ -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 Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Computer, 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.
*
@@ -34,39 +34,83 @@
#include <wtf/DataLog.h>
#include <wtf/text/StringHash.h>
+#if OS(WINDOWS)
+#include <windows.h>
+#endif
+
using namespace WTF;
namespace JSC {
-ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* parentNode)
+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)
: m_callerCallFrame(callerCallFrame)
, m_callIdentifier(callIdentifier)
+ , m_head(headNode)
, m_parent(parentNode)
-#ifndef NDEBUG
- , m_nextSibling(nullptr)
-#endif
+ , m_nextSibling(0)
+ , m_startTime(0.0)
+ , m_totalTime(0.0)
+ , m_selfTime(0.0)
+ , m_numberOfCalls(0)
{
+ startTimer();
}
-ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* nodeToCopy)
+ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* nodeToCopy)
: m_callerCallFrame(callerCallFrame)
, m_callIdentifier(nodeToCopy->callIdentifier())
+ , m_head(headNode)
, m_parent(nodeToCopy->parent())
- , m_calls(nodeToCopy->calls())
-#ifndef NDEBUG
- , m_nextSibling(nullptr)
-#endif
+ , m_nextSibling(0)
+ , m_startTime(0.0)
+ , m_totalTime(nodeToCopy->totalTime())
+ , m_selfTime(nodeToCopy->selfTime())
+ , m_numberOfCalls(nodeToCopy->numberOfCalls())
{
}
+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()
+{
+ 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());
}
@@ -75,18 +119,17 @@ 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
+ for (size_t i = 0; i < m_children.size(); ++i) {
+ if (*node == m_children[i].get()) {
+ m_children.remove(i);
+ break;
+ }
+ }
+
+ resetChildrensSiblings();
}
-void ProfileNode::spliceNode(PassRefPtr<ProfileNode> prpNode)
+void ProfileNode::insertNode(PassRefPtr<ProfileNode> prpNode)
{
RefPtr<ProfileNode> node = prpNode;
@@ -97,7 +140,21 @@ void ProfileNode::spliceNode(PassRefPtr<ProfileNode> prpNode)
m_children.append(node.release());
}
-#ifndef NDEBUG
+void ProfileNode::stopProfiling()
+{
+ if (m_startTime)
+ endAndRecordCall();
+
+ ASSERT(m_selfTime == 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_selfTime += m_children[i]->totalTime();
+
+ ASSERT(m_selfTime <= m_totalTime);
+ m_selfTime = m_totalTime - m_selfTime;
+}
+
ProfileNode* ProfileNode::traverseNextNodePostOrder() const
{
ProfileNode* next = m_nextSibling;
@@ -108,63 +165,54 @@ ProfileNode* ProfileNode::traverseNextNodePostOrder() const
return next;
}
-void ProfileNode::debugPrint()
+void ProfileNode::endAndRecordCall()
{
- CalculateProfileSubtreeDataFunctor functor;
- forEachNodePostorder(functor);
- ProfileNode::ProfileSubtreeData data = functor.returnValue();
+ m_totalTime += m_startTime ? getCount() - m_startTime : 0.0;
+ m_startTime = 0.0;
- debugPrintRecursively(0, data);
+ ++m_numberOfCalls;
}
-void ProfileNode::debugPrintSampleStyle()
+void ProfileNode::startTimer()
{
- FunctionCallHashCount countedFunctions;
-
- CalculateProfileSubtreeDataFunctor functor;
- forEachNodePostorder(functor);
- ProfileNode::ProfileSubtreeData data = functor.returnValue();
+ if (!m_startTime)
+ m_startTime = getCount();
+}
- debugPrintSampleStyleRecursively(0, countedFunctions, data);
+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());
}
-void ProfileNode::debugPrintRecursively(int indentLevel, const ProfileSubtreeData& data)
+#ifndef NDEBUG
+void ProfileNode::debugPrintData(int indentLevel) const
{
// 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,
+ dataLogF("Function Name %s %d SelfTime %.3fms/%.3f%% TotalTime %.3fms/%.3f%% Next Sibling %s\n",
+ functionName().utf8().data(),
+ m_numberOfCalls, m_selfTime, selfPercent(), m_totalTime, totalPercent(),
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);
+ (*currentChild)->debugPrintData(indentLevel);
}
// print the profiled data in a format that matches the tool sample's output.
-double ProfileNode::debugPrintSampleStyleRecursively(int indentLevel, FunctionCallHashCount& countedFunctions, const ProfileSubtreeData& data)
+double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount& countedFunctions) const
{
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;
+ double sampleCount = m_totalTime * 1000;
if (indentLevel) {
for (int i = 0; i < indentLevel; ++i)
dataLogF(" ");
@@ -180,7 +228,7 @@ double ProfileNode::debugPrintSampleStyleRecursively(int indentLevel, FunctionCa
// 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 += (*currentChild)->debugPrintDataSampleStyle(indentLevel, countedFunctions);
sumOfChildrensCount *= 1000; //
// Print remainder of samples to match sample's output
@@ -192,7 +240,7 @@ double ProfileNode::debugPrintSampleStyleRecursively(int indentLevel, FunctionCa
dataLogF("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data());
}
- return nodeTotalTime;
+ return m_totalTime;
}
#endif
diff --git a/Source/JavaScriptCore/profiler/ProfileNode.h b/Source/JavaScriptCore/profiler/ProfileNode.h
index fcaee0e24..e21b42282 100644
--- a/Source/JavaScriptCore/profiler/ProfileNode.h
+++ b/Source/JavaScriptCore/profiler/ProfileNode.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2014 Apple Inc. All rights reserved.
+ * 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
@@ -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 Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Computer, 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.
*
@@ -44,150 +44,96 @@ namespace JSC {
class ProfileNode : public RefCounted<ProfileNode> {
public:
- static Ref<ProfileNode> create(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* parentNode)
+ static PassRefPtr<ProfileNode> create(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
{
- return adoptRef(*new ProfileNode(callerCallFrame, callIdentifier, parentNode));
+ return adoptRef(new ProfileNode(callerCallFrame, callIdentifier, headNode, parentNode));
}
- static Ref<ProfileNode> create(ExecState* callerCallFrame, ProfileNode* node)
+ static PassRefPtr<ProfileNode> create(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* node)
{
- return adoptRef(*new ProfileNode(callerCallFrame, node));
+ return adoptRef(new ProfileNode(callerCallFrame, headNode, 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(); }
+ ProfileNode* willExecute(ExecState* callerCallFrame, const CallIdentifier&);
+ ProfileNode* didExecute();
+
+ void stopProfiling();
+
+ // CallIdentifier members
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(); }
+ 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; }
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); }
+ ProfileNode* nextSibling() const { return m_nextSibling; }
+ void setNextSibling(ProfileNode* nextSibling) { m_nextSibling = nextSibling; }
- 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; }
+ // Time members
+ double startTime() const { return m_startTime; }
+ void setStartTime(double startTime) { m_startTime = startTime; }
- 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>);
+ double totalTime() const { return m_totalTime; }
+ void setTotalTime(double time) { m_totalTime = time; }
-#ifndef NDEBUG
- struct ProfileSubtreeData {
- HashMap<ProfileNode*, std::pair<double, double>> selfAndTotalTimes;
- double rootTotalTime;
- };
+ double selfTime() const { return m_selfTime; }
+ void setSelfTime(double time) { m_selfTime = time; }
- // Use these functions to dump the subtree rooted at this node.
- void debugPrint();
- void debugPrintSampleStyle();
+ double totalPercent() const { return (m_totalTime / (m_head ? m_head->totalTime() : totalTime())) * 100.0; }
+ double selfPercent() const { return (m_selfTime / (m_head ? m_head->totalTime() : totalTime())) * 100.0; }
- // These are used to recursively print entire subtrees using precomputed self and total times.
- template <typename Functor> void forEachNodePostorder(Functor&);
+ unsigned numberOfCalls() const { return m_numberOfCalls; }
- void debugPrintRecursively(int indentLevel, const ProfileSubtreeData&);
- double debugPrintSampleStyleRecursively(int indentLevel, FunctionCallHashCount&, const ProfileSubtreeData&);
+ // 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; }
+ void removeChild(ProfileNode*);
+ void addChild(PassRefPtr<ProfileNode> prpChild);
+ void insertNode(PassRefPtr<ProfileNode> prpNode);
+
+ ProfileNode* traverseNextNodePostOrder() const;
+
+ void endAndRecordCall();
+
+#ifndef NDEBUG
+ const char* c_str() const { return m_callIdentifier; }
+ void debugPrintData(int indentLevel) const;
+ double debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount&) const;
#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(ExecState* callerCallFrame, const CallIdentifier&, ProfileNode* headNode, ProfileNode* parentNode);
+ ProfileNode(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* nodeToCopy);
- ProfileNode* traverseNextNodePostOrder() const;
-#endif
+ void startTimer();
+ void resetChildrensSiblings();
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
- };
-#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);
- }
+ double m_startTime;
+ double m_totalTime;
+ double m_selfTime;
+ unsigned m_numberOfCalls;
- 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;
+ Vector<RefPtr<ProfileNode>> m_children;
};
-#endif
} // namespace JSC
diff --git a/Source/JavaScriptCore/profiler/ProfilerBytecode.cpp b/Source/JavaScriptCore/profiler/ProfilerBytecode.cpp
index 6eeeb27b9..ca602e42f 100644
--- a/Source/JavaScriptCore/profiler/ProfilerBytecode.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerBytecode.cpp
@@ -28,7 +28,7 @@
#include "JSGlobalObject.h"
#include "ObjectConstructor.h"
-#include "JSCInlines.h"
+#include "Operations.h"
namespace JSC { namespace Profiler {
diff --git a/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp b/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp
index 145ee44d1..838153bea 100644
--- a/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012, 2013, 2014 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
@@ -29,7 +29,7 @@
#include "CodeBlock.h"
#include "JSGlobalObject.h"
#include "Operands.h"
-#include "JSCInlines.h"
+#include "Operations.h"
#include <wtf/StringPrintStream.h>
namespace JSC { namespace Profiler {
@@ -44,16 +44,13 @@ BytecodeSequence::BytecodeSequence(CodeBlock* codeBlock)
if (!description.length())
continue;
out.reset();
- out.print("arg", i, ": ", description);
+ out.print("arg", i, " (r", virtualRegisterForArgument(i).offset(), "): ", 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);
+ codeBlock->dumpBytecode(out, bytecodeIndex);
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 74c55abcf..aa5a6d9c9 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 "JSCInlines.h"
+#include "Operations.h"
#include <wtf/StringPrintStream.h>
namespace JSC { namespace Profiler {
diff --git a/Source/JavaScriptCore/profiler/ProfilerCompilation.cpp b/Source/JavaScriptCore/profiler/ProfilerCompilation.cpp
index 488f563de..55766ce5c 100644
--- a/Source/JavaScriptCore/profiler/ProfilerCompilation.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerCompilation.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012, 2013, 2014 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
@@ -28,9 +28,8 @@
#include "JSGlobalObject.h"
#include "ObjectConstructor.h"
-#include "JSCInlines.h"
+#include "Operations.h"
#include "ProfilerDatabase.h"
-#include "Watchpoint.h"
#include <wtf/StringPrintStream.h>
namespace JSC { namespace Profiler {
@@ -38,7 +37,6 @@ 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)
@@ -69,11 +67,6 @@ 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;
@@ -94,18 +87,6 @@ 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);
@@ -145,9 +126,6 @@ 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 b358b659c..dc2810525 100644
--- a/Source/JavaScriptCore/profiler/ProfilerCompilation.h
+++ b/Source/JavaScriptCore/profiler/ProfilerCompilation.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012, 2013, 2014 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
@@ -31,7 +31,6 @@
#include "ProfilerCompilationKind.h"
#include "ProfilerCompiledBytecode.h"
#include "ProfilerExecutionCounter.h"
-#include "ProfilerJettisonReason.h"
#include "ProfilerOSRExit.h"
#include "ProfilerOSRExitSite.h"
#include "ProfilerOriginStack.h"
@@ -39,11 +38,7 @@
#include <wtf/RefCounted.h>
#include <wtf/SegmentedVector.h>
-namespace JSC {
-
-class FireDetail;
-
-namespace Profiler {
+namespace JSC { namespace Profiler {
class Bytecodes;
class Database;
@@ -68,20 +63,15 @@ 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, std::unique_ptr<ExecutionCounter>> m_counters;
diff --git a/Source/JavaScriptCore/profiler/ProfilerCompilationKind.cpp b/Source/JavaScriptCore/profiler/ProfilerCompilationKind.cpp
index 3fbe25192..78ce70586 100644
--- a/Source/JavaScriptCore/profiler/ProfilerCompilationKind.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerCompilationKind.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012, 2014 Apple Inc. All rights reserved.
+ * 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
@@ -42,12 +42,6 @@ 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 575ec2947..4806d39b9 100644
--- a/Source/JavaScriptCore/profiler/ProfilerCompilationKind.h
+++ b/Source/JavaScriptCore/profiler/ProfilerCompilationKind.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012, 2014 Apple Inc. All rights reserved.
+ * 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
@@ -31,9 +31,7 @@ namespace JSC { namespace Profiler {
enum CompilationKind {
LLInt,
Baseline,
- DFG,
- FTL,
- FTLForOSREntry
+ DFG
};
} } // namespace JSC::Profiler
diff --git a/Source/JavaScriptCore/profiler/ProfilerCompiledBytecode.cpp b/Source/JavaScriptCore/profiler/ProfilerCompiledBytecode.cpp
index 4891c315c..455a48ed9 100644
--- a/Source/JavaScriptCore/profiler/ProfilerCompiledBytecode.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerCompiledBytecode.cpp
@@ -28,7 +28,7 @@
#include "JSGlobalObject.h"
#include "ObjectConstructor.h"
-#include "JSCInlines.h"
+#include "Operations.h"
namespace JSC { namespace Profiler {
diff --git a/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp b/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp
index fc952c0c2..f83652dda 100644
--- a/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp
@@ -29,13 +29,13 @@
#include "CodeBlock.h"
#include "JSONObject.h"
#include "ObjectConstructor.h"
-#include "JSCInlines.h"
+#include "Operations.h"
namespace JSC { namespace Profiler {
static std::atomic<int> databaseCounter;
-static StaticLock registrationLock;
+static SpinLock registrationLock = SPINLOCK_INITIALIZER;
static std::atomic<int> didRegisterAtExit;
static Database* firstDatabase;
@@ -57,7 +57,7 @@ Database::~Database()
Bytecodes* Database::ensureBytecodesFor(CodeBlock* codeBlock)
{
- LockHolder locker(m_lock);
+ Locker locker(m_lock);
codeBlock = codeBlock->baselineVersion();
@@ -75,7 +75,7 @@ Bytecodes* Database::ensureBytecodesFor(CodeBlock* codeBlock)
void Database::notifyDestruction(CodeBlock* codeBlock)
{
- LockHolder locker(m_lock);
+ Locker locker(m_lock);
m_bytecodesMap.remove(codeBlock);
}
@@ -138,14 +138,14 @@ void Database::addDatabaseToAtExit()
if (++didRegisterAtExit == 1)
atexit(atExitCallback);
- LockHolder holder(registrationLock);
+ TCMalloc_SpinLockHolder holder(&registrationLock);
m_nextRegisteredDatabase = firstDatabase;
firstDatabase = this;
}
void Database::removeDatabaseFromAtExit()
{
- LockHolder holder(registrationLock);
+ TCMalloc_SpinLockHolder holder(&registrationLock);
for (Database** current = &firstDatabase; *current; current = &(*current)->m_nextRegisteredDatabase) {
if (*current != this)
continue;
@@ -163,7 +163,7 @@ void Database::performAtExitSave() const
Database* Database::removeFirstAtExitDatabase()
{
- LockHolder holder(registrationLock);
+ TCMalloc_SpinLockHolder 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 9bb64cf49..7d4f3cf2c 100644
--- a/Source/JavaScriptCore/profiler/ProfilerDatabase.h
+++ b/Source/JavaScriptCore/profiler/ProfilerDatabase.h
@@ -32,7 +32,6 @@
#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>
@@ -71,6 +70,21 @@ public:
void registerToSaveAtExit(const char* filename);
private:
+ // Use a full-blown adaptive mutex because:
+ // - There is only one ProfilerDatabase per VM. The size overhead of the system's
+ // mutex is negligible if you only have one of them.
+ // - It's locked infrequently - once per bytecode generation, compilation, and
+ // code block collection - so the fact that the fast path still requires a
+ // function call is neglible.
+ // - It tends to be held for a while. Currently, we hold it while generating
+ // Profiler::Bytecodes for a CodeBlock. That's uncommon and shouldn't affect
+ // performance, but if we did have contention, we would want a sensible,
+ // power-aware backoff. An adaptive mutex will do this as a matter of course,
+ // but a spinlock won't.
+ typedef Mutex Lock;
+ typedef MutexLocker Locker;
+
+
void addDatabaseToAtExit();
void removeDatabaseFromAtExit();
void performAtExitSave() const;
diff --git a/Source/JavaScriptCore/profiler/ProfilerJettisonReason.cpp b/Source/JavaScriptCore/profiler/ProfilerJettisonReason.cpp
deleted file mode 100644
index 5fad7297f..000000000
--- a/Source/JavaScriptCore/profiler/ProfilerJettisonReason.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 0a15ba30e..000000000
--- a/Source/JavaScriptCore/profiler/ProfilerJettisonReason.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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
index 2a5d5be40..0024791b4 100644
--- a/Source/JavaScriptCore/profiler/ProfilerOSRExit.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerOSRExit.cpp
@@ -28,7 +28,7 @@
#include "JSGlobalObject.h"
#include "ObjectConstructor.h"
-#include "JSCInlines.h"
+#include "Operations.h"
namespace JSC { namespace Profiler {
diff --git a/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.cpp b/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.cpp
index b17d57e52..d54f7a275 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 "JSCInlines.h"
+#include "Operations.h"
#include <wtf/StringPrintStream.h>
namespace JSC { namespace Profiler {
diff --git a/Source/JavaScriptCore/profiler/ProfilerOrigin.cpp b/Source/JavaScriptCore/profiler/ProfilerOrigin.cpp
index 7c28f7ba3..1ac29d1cc 100644
--- a/Source/JavaScriptCore/profiler/ProfilerOrigin.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerOrigin.cpp
@@ -28,7 +28,7 @@
#include "JSGlobalObject.h"
#include "ObjectConstructor.h"
-#include "JSCInlines.h"
+#include "Operations.h"
#include "ProfilerBytecodes.h"
#include "ProfilerDatabase.h"
diff --git a/Source/JavaScriptCore/profiler/ProfilerOriginStack.cpp b/Source/JavaScriptCore/profiler/ProfilerOriginStack.cpp
index 9b61daec1..018ceeb8c 100644
--- a/Source/JavaScriptCore/profiler/ProfilerOriginStack.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerOriginStack.cpp
@@ -28,7 +28,7 @@
#include "CodeOrigin.h"
#include "JSGlobalObject.h"
-#include "JSCInlines.h"
+#include "Operations.h"
#include "ProfilerDatabase.h"
namespace JSC { namespace Profiler {
diff --git a/Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.cpp b/Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.cpp
index fe590ff78..6ca6c9f15 100644
--- a/Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerProfiledBytecodes.cpp
@@ -28,7 +28,7 @@
#include "JSGlobalObject.h"
#include "ObjectConstructor.h"
-#include "JSCInlines.h"
+#include "Operations.h"
namespace JSC { namespace Profiler {