Profiler should say things about OSR exits
https://bugs.webkit.org/show_bug.cgi?id=104497
Reviewed by Oliver Hunt.
Source/JavaScriptCore:
This adds support for profiling OSR exits. For each exit that is taken, the profiler
records the machine code address that the exit occurred on, the exit kind, the origin
stack, and the number of times that it happened.
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* assembler/AbstractMacroAssembler.h:
(Jump):
(JSC::AbstractMacroAssembler::Jump::label):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::saveCompilation):
(CodeBlock):
(JSC::CodeBlock::compilation):
(DFGData):
* bytecode/DFGExitProfile.h:
(DFG):
* bytecode/ExitKind.cpp: Added.
(JSC):
(JSC::exitKindToString):
(JSC::exitKindIsCountable):
(WTF):
(WTF::printInternal):
* bytecode/ExitKind.h: Added.
(JSC):
(WTF):
* dfg/DFGGraph.h:
(Graph):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::linkOSRExits):
(JSC::DFG::JITCompiler::link):
(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::compileFunction):
* dfg/DFGJITCompiler.h:
(JITCompiler):
* dfg/DFGOSRExitCompiler.cpp:
* jit/JIT.cpp:
(JSC::JIT::JIT):
(JSC::JIT::privateCompile):
* jit/JIT.h:
(JIT):
* jit/JumpReplacementWatchpoint.h:
(JSC::JumpReplacementWatchpoint::sourceLabel):
(JumpReplacementWatchpoint):
* profiler/ProfilerCompilation.cpp:
(JSC::Profiler::Compilation::addOSRExitSite):
(Profiler):
(JSC::Profiler::Compilation::addOSRExit):
(JSC::Profiler::Compilation::toJS):
* profiler/ProfilerCompilation.h:
(Compilation):
* profiler/ProfilerDatabase.cpp:
(JSC::Profiler::Database::newCompilation):
* profiler/ProfilerDatabase.h:
(Database):
* profiler/ProfilerOSRExit.cpp: Added.
(Profiler):
(JSC::Profiler::OSRExit::OSRExit):
(JSC::Profiler::OSRExit::~OSRExit):
(JSC::Profiler::OSRExit::toJS):
* profiler/ProfilerOSRExit.h: Added.
(Profiler):
(OSRExit):
(JSC::Profiler::OSRExit::id):
(JSC::Profiler::OSRExit::origin):
(JSC::Profiler::OSRExit::exitKind):
(JSC::Profiler::OSRExit::isWatchpoint):
(JSC::Profiler::OSRExit::counterAddress):
(JSC::Profiler::OSRExit::count):
* profiler/ProfilerOSRExitSite.cpp: Added.
(Profiler):
(JSC::Profiler::OSRExitSite::toJS):
* profiler/ProfilerOSRExitSite.h: Added.
(Profiler):
(OSRExitSite):
(JSC::Profiler::OSRExitSite::OSRExitSite):
(JSC::Profiler::OSRExitSite::codeAddress):
* runtime/CommonIdentifiers.h:
Tools:
Adds support for displaying OSR exit information for full summary (just displays the
counts and the number of recompilations), bytecode display (says which bytecodes
exited), and DFG display (annotates disassembly with taken OSR exits and their
counts).
* Scripts/display-profiler-output:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@137175 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/profiler/ProfilerCompilation.cpp b/Source/JavaScriptCore/profiler/ProfilerCompilation.cpp
index a4dcba0..fc1901f 100644
--- a/Source/JavaScriptCore/profiler/ProfilerCompilation.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerCompilation.cpp
@@ -56,6 +56,17 @@
return result;
}
+void Compilation::addOSRExitSite(const void* codeAddress)
+{
+ m_osrExitSites.append(OSRExitSite(codeAddress));
+}
+
+OSRExit* Compilation::addOSRExit(unsigned id, const OriginStack& originStack, ExitKind exitKind, bool isWatchpoint)
+{
+ m_osrExits.append(OSRExit(id, originStack, exitKind, isWatchpoint));
+ return &m_osrExits.last();
+}
+
JSValue Compilation::toJS(ExecState* exec) const
{
JSObject* result = constructEmptyObject(exec);
@@ -78,6 +89,16 @@
}
result->putDirect(exec->globalData(), exec->propertyNames().counters, counters);
+ JSArray* exitSites = constructEmptyArray(exec, 0);
+ for (unsigned i = 0; i < m_osrExitSites.size(); ++i)
+ exitSites->putDirectIndex(exec, i, m_osrExitSites[i].toJS(exec));
+ result->putDirect(exec->globalData(), exec->propertyNames().osrExitSites, exitSites);
+
+ JSArray* exits = constructEmptyArray(exec, 0);
+ for (unsigned i = 0; i < m_osrExits.size(); ++i)
+ exits->putDirectIndex(exec, i, m_osrExits[i].toJS(exec));
+ result->putDirect(exec->globalData(), exec->propertyNames().osrExits, exits);
+
return result;
}
diff --git a/Source/JavaScriptCore/profiler/ProfilerCompilation.h b/Source/JavaScriptCore/profiler/ProfilerCompilation.h
index d14c05c..697b8cf 100644
--- a/Source/JavaScriptCore/profiler/ProfilerCompilation.h
+++ b/Source/JavaScriptCore/profiler/ProfilerCompilation.h
@@ -26,13 +26,16 @@
#ifndef ProfilerCompilation_h
#define ProfilerCompilation_h
+#include "ExitKind.h"
#include "JSValue.h"
#include "ProfilerCompilationKind.h"
#include "ProfilerCompiledBytecode.h"
#include "ProfilerExecutionCounter.h"
+#include "ProfilerOSRExit.h"
+#include "ProfilerOSRExitSite.h"
#include "ProfilerOriginStack.h"
-#include <wtf/FastAllocBase.h>
-#include <wtf/Noncopyable.h>
+#include <wtf/RefCounted.h>
+#include <wtf/SegmentedVector.h>
namespace JSC { namespace Profiler {
@@ -41,8 +44,7 @@
// Represents the act of executing some bytecodes in some engine, and does
// all of the counting for those executions.
-class Compilation {
- WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_NONCOPYABLE(Compilation);
+class Compilation : public RefCounted<Compilation> {
public:
Compilation(Bytecodes*, CompilationKind);
~Compilation();
@@ -52,6 +54,8 @@
void addDescription(const CompiledBytecode&);
ExecutionCounter* executionCounterFor(const OriginStack&);
+ void addOSRExitSite(const void* codeAddress);
+ OSRExit* addOSRExit(unsigned id, const OriginStack&, ExitKind, bool isWatchpoint);
JSValue toJS(ExecState*) const;
@@ -60,6 +64,8 @@
CompilationKind m_kind;
Vector<CompiledBytecode> m_descriptions;
HashMap<OriginStack, OwnPtr<ExecutionCounter> > m_counters;
+ Vector<OSRExitSite> m_osrExitSites;
+ SegmentedVector<OSRExit> m_osrExits;
};
} } // namespace JSC::Profiler
diff --git a/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp b/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp
index 72e083a..fce17e9 100644
--- a/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp
+++ b/Source/JavaScriptCore/profiler/ProfilerDatabase.cpp
@@ -79,15 +79,14 @@
m_bytecodesMap.remove(codeBlock);
}
-Compilation* Database::newCompilation(Bytecodes* bytecodes, CompilationKind kind)
+PassRefPtr<Compilation> Database::newCompilation(Bytecodes* bytecodes, CompilationKind kind)
{
- OwnPtr<Compilation> compilation = adoptPtr(new Compilation(bytecodes, kind));
- Compilation* result = compilation.get();
- m_compilations.append(compilation.release());
- return result;
+ RefPtr<Compilation> compilation = adoptRef(new Compilation(bytecodes, kind));
+ m_compilations.append(compilation);
+ return compilation.release();
}
-Compilation* Database::newCompilation(CodeBlock* codeBlock, CompilationKind kind)
+PassRefPtr<Compilation> Database::newCompilation(CodeBlock* codeBlock, CompilationKind kind)
{
return newCompilation(ensureBytecodesFor(codeBlock), kind);
}
diff --git a/Source/JavaScriptCore/profiler/ProfilerDatabase.h b/Source/JavaScriptCore/profiler/ProfilerDatabase.h
index d45d654..5f1270d 100644
--- a/Source/JavaScriptCore/profiler/ProfilerDatabase.h
+++ b/Source/JavaScriptCore/profiler/ProfilerDatabase.h
@@ -33,6 +33,7 @@
#include <wtf/FastAllocBase.h>
#include <wtf/HashMap.h>
#include <wtf/Noncopyable.h>
+#include <wtf/PassRefPtr.h>
#include <wtf/SegmentedVector.h>
#include <wtf/text/WTFString.h>
@@ -47,8 +48,8 @@
Bytecodes* ensureBytecodesFor(CodeBlock*);
void notifyDestruction(CodeBlock*);
- Compilation* newCompilation(CodeBlock*, CompilationKind);
- Compilation* newCompilation(Bytecodes*, CompilationKind);
+ PassRefPtr<Compilation> newCompilation(CodeBlock*, CompilationKind);
+ PassRefPtr<Compilation> newCompilation(Bytecodes*, CompilationKind);
// 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,7 @@
JSGlobalData& m_globalData;
SegmentedVector<Bytecodes> m_bytecodes;
HashMap<CodeBlock*, Bytecodes*> m_bytecodesMap;
- Vector<OwnPtr<Compilation> > m_compilations;
+ Vector<RefPtr<Compilation> > m_compilations;
};
} } // namespace JSC::Profiler
diff --git a/Source/JavaScriptCore/profiler/ProfilerOSRExit.cpp b/Source/JavaScriptCore/profiler/ProfilerOSRExit.cpp
new file mode 100644
index 0000000..da0398d
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerOSRExit.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfilerOSRExit.h"
+
+#include "JSGlobalObject.h"
+
+namespace JSC { namespace Profiler {
+
+OSRExit::OSRExit(unsigned id, const OriginStack& origin, ExitKind kind, bool isWatchpoint)
+ : m_id(id)
+ , m_origin(origin)
+ , m_exitKind(kind)
+ , m_isWatchpoint(isWatchpoint)
+ , m_counter(0)
+{
+}
+
+OSRExit::~OSRExit()
+{
+}
+
+JSValue OSRExit::toJS(ExecState* exec) const
+{
+ JSObject* result = constructEmptyObject(exec);
+ result->putDirect(exec->globalData(), exec->propertyNames().id, jsNumber(m_id));
+ result->putDirect(exec->globalData(), exec->propertyNames().origin, m_origin.toJS(exec));
+ result->putDirect(exec->globalData(), exec->propertyNames().exitKind, jsString(exec, exitKindToString(m_exitKind)));
+ result->putDirect(exec->globalData(), exec->propertyNames().isWatchpoint, jsBoolean(m_isWatchpoint));
+ result->putDirect(exec->globalData(), exec->propertyNames().count, jsNumber(m_counter));
+ return result;
+}
+
+} } // namespace JSC::Profiler
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerOSRExit.h b/Source/JavaScriptCore/profiler/ProfilerOSRExit.h
new file mode 100644
index 0000000..b96d1d6
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerOSRExit.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfilerOSRExit_h
+#define ProfilerOSRExit_h
+
+#include "ExitKind.h"
+#include "JSValue.h"
+#include "ProfilerOriginStack.h"
+
+namespace JSC { namespace Profiler {
+
+class OSRExit {
+public:
+ OSRExit(unsigned id, const OriginStack&, ExitKind, bool isWatchpoint);
+ ~OSRExit();
+
+ unsigned id() const { return m_id; }
+ const OriginStack& origin() const { return m_origin; }
+ ExitKind exitKind() const { return m_exitKind; }
+ bool isWatchpoint() const { return m_isWatchpoint; }
+
+ uint64_t* counterAddress() { return &m_counter; }
+ uint64_t count() const { return m_counter; }
+
+ JSValue toJS(ExecState*) const;
+
+private:
+ unsigned m_id;
+ OriginStack m_origin;
+ ExitKind m_exitKind;
+ bool m_isWatchpoint;
+ uint64_t m_counter;
+};
+
+} } // namespace JSC::Profiler
+
+#endif // ProfilerOSRExit_h
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.cpp b/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.cpp
new file mode 100644
index 0000000..908236f
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfilerOSRExitSite.h"
+
+#include "JSScope.h"
+#include "JSString.h"
+#include <wtf/StringPrintStream.h>
+
+namespace JSC { namespace Profiler {
+
+JSValue OSRExitSite::toJS(ExecState* exec) const
+{
+ return jsString(exec, toString(RawPointer(m_codeAddress)));
+}
+
+} } // namespace JSC::Profiler
+
diff --git a/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.h b/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.h
new file mode 100644
index 0000000..9339ac1
--- /dev/null
+++ b/Source/JavaScriptCore/profiler/ProfilerOSRExitSite.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfilerOSRExitSite_h
+#define ProfilerOSRExitSite_h
+
+#include "JSValue.h"
+
+namespace JSC { namespace Profiler {
+
+class OSRExitSite {
+public:
+ explicit OSRExitSite(const void* codeAddress)
+ : m_codeAddress(codeAddress)
+ {
+ }
+
+ const void* codeAddress() const { return m_codeAddress; }
+
+ JSValue toJS(ExecState*) const;
+
+private:
+ const void* m_codeAddress;
+};
+
+} } // namespace JSC::Profiler
+
+#endif // ProfilerOSRExitSite_h
+