<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[201990] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/201990">201990</a></dd>
<dt>Author</dt> <dd>mark.lam@apple.com</dd>
<dt>Date</dt> <dd>2016-06-13 08:53:42 -0700 (Mon, 13 Jun 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>Add a mechanism for collecting LLINT stats.
https://bugs.webkit.org/show_bug.cgi?id=158668
Reviewed by Filip Pizlo.
Source/JavaScriptCore:
This patch will add a mechanism for collecting the stats on LLINT opcode
execution counts. The changes made to enable this are:
1. Refactored how Options availability work so that we can add a new category:
Configurable (in addition to the pre-existing Normal and Restricted
availability).
Normal options - always available.
Restricted options - only available on debug builds.
Configurable options - depends on #define flag options.
This change is necessary so that:
a. we won't have to rebuild the world when we want to enable that #define flag
to make that Configurable option available.
b. when the #define flag is disabled, the option will be invisible to the user.
With this, we add our first configurable option, JSC_reportLLIntStats, which
is dependent on the ENABLE_LLINT_STATS flag. See next.
2. Added the ENABLE_LLINT_STATS flag in LLIntCommon.h. To enable LLINT stats
collection, we'll need to set this flag to a non-zero value, and rebuilding
the project. By design, this will only require a minimal set of files to
be rebuilt.
ENABLE_LLINT_STATS is 0 (i.e. disabled) by default.
3. Added a slow path callback to the LLINT's traceExecution() macro, to call
_llint_count_opcode(), which in turns counts the opcode. This callback will
only be built into the LLINT if ENABLE_LLINT_STATS is non-zero.
4. Added s_opcodeStatsArray to LLInt::Data. This is where the stats are
recorded and stored.
5. Added calls to LLInt::Data::dumpStats() in jsc.cpp and DumpRenderTree.mm
to dump the LLINT stats if enabled. If enabled, the LLINT stats will be
sorted and dumped (via dataLog) before the programs terminate.
* interpreter/Interpreter.h:
* jsc.cpp:
(main):
* llint/LLIntCommon.h:
* llint/LLIntData.cpp:
(JSC::LLInt::initialize):
(JSC::LLInt::Data::dumpStats):
* llint/LLIntData.h:
(JSC::LLInt::Data::opcodeStats):
* llint/LLIntOfflineAsmConfig.h:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::llint_crash):
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* llint/LLIntSlowPaths.h:
* llint/LowLevelInterpreter.asm:
* runtime/Options.cpp:
(JSC::parse):
(JSC::Options::isAvailable):
(JSC::overrideOptionWithHeuristic):
(JSC::scaleJITPolicy):
(JSC::Options::initialize):
(JSC::Options::setOptionWithoutAlias):
(JSC::Options::dumpAllOptions):
(JSC::Options::dumpOption):
* runtime/Options.h:
(JSC::Option::Option):
(JSC::Option::operator!=):
(JSC::Option::id):
Tools:
* DumpRenderTree/mac/DumpRenderTree.mm:
(DumpRenderTreeMain):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpreterh">trunk/Source/JavaScriptCore/interpreter/Interpreter.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntCommonh">trunk/Source/JavaScriptCore/llint/LLIntCommon.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntDatacpp">trunk/Source/JavaScriptCore/llint/LLIntData.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntDatah">trunk/Source/JavaScriptCore/llint/LLIntData.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntOfflineAsmConfigh">trunk/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathsh">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreterasm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionscpp">trunk/Source/JavaScriptCore/runtime/Options.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsDumpRenderTreemacDumpRenderTreemm">trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (201989 => 201990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-06-13 15:53:42 UTC (rev 201990)
</span><span class="lines">@@ -1,3 +1,75 @@
</span><ins>+2016-06-13 Mark Lam <mark.lam@apple.com>
+
+ Add a mechanism for collecting LLINT stats.
+ https://bugs.webkit.org/show_bug.cgi?id=158668
+
+ Reviewed by Filip Pizlo.
+
+ This patch will add a mechanism for collecting the stats on LLINT opcode
+ execution counts. The changes made to enable this are:
+
+ 1. Refactored how Options availability work so that we can add a new category:
+ Configurable (in addition to the pre-existing Normal and Restricted
+ availability).
+ Normal options - always available.
+ Restricted options - only available on debug builds.
+ Configurable options - depends on #define flag options.
+
+ This change is necessary so that:
+ a. we won't have to rebuild the world when we want to enable that #define flag
+ to make that Configurable option available.
+ b. when the #define flag is disabled, the option will be invisible to the user.
+
+ With this, we add our first configurable option, JSC_reportLLIntStats, which
+ is dependent on the ENABLE_LLINT_STATS flag. See next.
+
+ 2. Added the ENABLE_LLINT_STATS flag in LLIntCommon.h. To enable LLINT stats
+ collection, we'll need to set this flag to a non-zero value, and rebuilding
+ the project. By design, this will only require a minimal set of files to
+ be rebuilt.
+
+ ENABLE_LLINT_STATS is 0 (i.e. disabled) by default.
+
+ 3. Added a slow path callback to the LLINT's traceExecution() macro, to call
+ _llint_count_opcode(), which in turns counts the opcode. This callback will
+ only be built into the LLINT if ENABLE_LLINT_STATS is non-zero.
+
+ 4. Added s_opcodeStatsArray to LLInt::Data. This is where the stats are
+ recorded and stored.
+
+ 5. Added calls to LLInt::Data::dumpStats() in jsc.cpp and DumpRenderTree.mm
+ to dump the LLINT stats if enabled. If enabled, the LLINT stats will be
+ sorted and dumped (via dataLog) before the programs terminate.
+
+ * interpreter/Interpreter.h:
+ * jsc.cpp:
+ (main):
+ * llint/LLIntCommon.h:
+ * llint/LLIntData.cpp:
+ (JSC::LLInt::initialize):
+ (JSC::LLInt::Data::dumpStats):
+ * llint/LLIntData.h:
+ (JSC::LLInt::Data::opcodeStats):
+ * llint/LLIntOfflineAsmConfig.h:
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::llint_crash):
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ * llint/LLIntSlowPaths.h:
+ * llint/LowLevelInterpreter.asm:
+ * runtime/Options.cpp:
+ (JSC::parse):
+ (JSC::Options::isAvailable):
+ (JSC::overrideOptionWithHeuristic):
+ (JSC::scaleJITPolicy):
+ (JSC::Options::initialize):
+ (JSC::Options::setOptionWithoutAlias):
+ (JSC::Options::dumpAllOptions):
+ (JSC::Options::dumpOption):
+ * runtime/Options.h:
+ (JSC::Option::Option):
+ (JSC::Option::operator!=):
+ (JSC::Option::id):
+
</ins><span class="cx"> 2016-06-11 Mark Lam <mark.lam@apple.com>
</span><span class="cx">
</span><span class="cx"> Minimize the amount of memcpy done for allocating Error stacks.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpreterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.h (201989 => 201990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.h        2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.h        2016-06-13 15:53:42 UTC (rev 201990)
</span><span class="lines">@@ -35,7 +35,6 @@
</span><span class="cx"> #include "JSCell.h"
</span><span class="cx"> #include "JSObject.h"
</span><span class="cx"> #include "JSStack.h"
</span><del>-#include "LLIntData.h"
</del><span class="cx"> #include "Opcode.h"
</span><span class="cx"> #include "SourceProvider.h"
</span><span class="cx"> #include "StackAlignment.h"
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (201989 => 201990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2016-06-13 15:53:42 UTC (rev 201990)
</span><span class="lines">@@ -51,6 +51,7 @@
</span><span class="cx"> #include "JSProxy.h"
</span><span class="cx"> #include "JSString.h"
</span><span class="cx"> #include "JSWASMModule.h"
</span><ins>+#include "LLIntData.h"
</ins><span class="cx"> #include "ProfilerDatabase.h"
</span><span class="cx"> #include "SamplingProfiler.h"
</span><span class="cx"> #include "ShadowChicken.h"
</span><span class="lines">@@ -1983,6 +1984,8 @@
</span><span class="cx"> EXCEPT(res = 3)
</span><span class="cx"> if (Options::logHeapStatisticsAtExit())
</span><span class="cx"> HeapStatistics::reportSuccess();
</span><ins>+ if (Options::reportLLIntStats())
+ LLInt::Data::dumpStats();
</ins><span class="cx">
</span><span class="cx"> #if PLATFORM(EFL)
</span><span class="cx"> ecore_shutdown();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntCommonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntCommon.h (201989 => 201990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntCommon.h        2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/JavaScriptCore/llint/LLIntCommon.h        2016-06-13 15:53:42 UTC (rev 201990)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012-2013, 2016 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -26,6 +26,9 @@
</span><span class="cx"> #ifndef LLIntCommon_h
</span><span class="cx"> #define LLIntCommon_h
</span><span class="cx">
</span><ins>+// Enables LLINT stats collection.
+#define ENABLE_LLINT_STATS 0
+
</ins><span class="cx"> // Print every instruction executed.
</span><span class="cx"> #define LLINT_EXECUTION_TRACING 0
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntData.cpp (201989 => 201990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntData.cpp        2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/JavaScriptCore/llint/LLIntData.cpp        2016-06-13 15:53:42 UTC (rev 201990)
</span><span class="lines">@@ -25,12 +25,14 @@
</span><span class="cx">
</span><span class="cx"> #include "config.h"
</span><span class="cx"> #include "LLIntData.h"
</span><ins>+
</ins><span class="cx"> #include "BytecodeConventions.h"
</span><span class="cx"> #include "CodeBlock.h"
</span><span class="cx"> #include "CodeType.h"
</span><span class="cx"> #include "Instruction.h"
</span><span class="cx"> #include "JSScope.h"
</span><span class="cx"> #include "LLIntCLoop.h"
</span><ins>+#include "LLIntCommon.h"
</ins><span class="cx"> #include "MaxFrameExtentForSlowPathCall.h"
</span><span class="cx"> #include "Opcode.h"
</span><span class="cx"> #include "PropertyOffset.h"
</span><span class="lines">@@ -43,6 +45,7 @@
</span><span class="cx">
</span><span class="cx"> Instruction* Data::s_exceptionInstructions = 0;
</span><span class="cx"> Opcode Data::s_opcodeMap[numOpcodeIDs] = { };
</span><ins>+OpcodeStatsArray* Data::s_opcodeStatsArray = nullptr;
</ins><span class="cx">
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> extern "C" void llint_entry(void*);
</span><span class="lines">@@ -62,6 +65,13 @@
</span><span class="cx"> Data::s_exceptionInstructions[i].u.pointer =
</span><span class="cx"> LLInt::getCodePtr(llint_throw_from_slow_path_trampoline);
</span><span class="cx"> #endif // ENABLE(JIT)
</span><ins>+
+#if ENABLE(LLINT_STATS)
+ Data::s_opcodeStatsArray = new OpcodeStatsArray();
+ unsigned i = 0;
+ for (auto& stats : *Data::s_opcodeStatsArray)
+ stats.id = static_cast<OpcodeID>(i++);
+#endif
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> #if COMPILER(CLANG)
</span><span class="lines">@@ -217,4 +227,25 @@
</span><span class="cx"> #pragma clang diagnostic pop
</span><span class="cx"> #endif
</span><span class="cx">
</span><ins>+void Data::dumpStats()
+{
+#if ENABLE(LLINT_STATS)
+ if (!Options::reportLLIntStats())
+ return;
+
+ auto statsCopy = *s_opcodeStatsArray;
+ std::sort(statsCopy.begin(), statsCopy.end(), [] (OpcodeStats& a, OpcodeStats& b) -> bool {
+ return a.count > b.count;
+ });
+
+ dataLog("Opcode stats:\n");
+ unsigned i = 0;
+ for (auto& stats : statsCopy) {
+ if (stats.count)
+ dataLog(" [", i++, "]: fast:", stats.count, " ", opcodeNames[stats.id], "\n");
+ }
+#endif
+}
+
+
</ins><span class="cx"> } } // namespace JSC::LLInt
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntData.h (201989 => 201990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntData.h        2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/JavaScriptCore/llint/LLIntData.h        2016-06-13 15:53:42 UTC (rev 201990)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx">
</span><span class="cx"> #include "JSCJSValue.h"
</span><span class="cx"> #include "Opcode.h"
</span><ins>+#include <array>
</ins><span class="cx">
</span><span class="cx"> namespace JSC {
</span><span class="cx">
</span><span class="lines">@@ -42,13 +43,24 @@
</span><span class="cx">
</span><span class="cx"> namespace LLInt {
</span><span class="cx">
</span><ins>+struct OpcodeStats {
+ OpcodeID id;
+ size_t count { 0 };
+};
+typedef std::array<OpcodeStats, numOpcodeIDs> OpcodeStatsArray;
+
</ins><span class="cx"> class Data {
</span><span class="cx"> public:
</span><ins>+
</ins><span class="cx"> static void performAssertions(VM&);
</span><ins>+ static OpcodeStats& opcodeStats(OpcodeID id) { return (*s_opcodeStatsArray)[id]; }
</ins><span class="cx">
</span><ins>+ JS_EXPORT_PRIVATE static void dumpStats();
+
</ins><span class="cx"> private:
</span><span class="cx"> static Instruction* s_exceptionInstructions;
</span><span class="cx"> static Opcode s_opcodeMap[numOpcodeIDs];
</span><ins>+ static OpcodeStatsArray* s_opcodeStatsArray;
</ins><span class="cx">
</span><span class="cx"> friend void initialize();
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntOfflineAsmConfigh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h (201989 => 201990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h        2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h        2016-06-13 15:53:42 UTC (rev 201990)
</span><span class="lines">@@ -155,6 +155,12 @@
</span><span class="cx"> #define OFFLINE_ASM_BIG_ENDIAN 0
</span><span class="cx"> #endif
</span><span class="cx">
</span><ins>+#if ENABLE(LLINT_STATS)
+#define OFFLINE_ASM_COLLECT_STATS 1
+#else
+#define OFFLINE_ASM_COLLECT_STATS 0
+#endif
+
</ins><span class="cx"> #if LLINT_EXECUTION_TRACING
</span><span class="cx"> #define OFFLINE_ASM_EXECUTION_TRACING 1
</span><span class="cx"> #else
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (201989 => 201990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2016-06-13 15:53:42 UTC (rev 201990)
</span><span class="lines">@@ -49,6 +49,7 @@
</span><span class="cx"> #include "JSString.h"
</span><span class="cx"> #include "JSWithScope.h"
</span><span class="cx"> #include "LLIntCommon.h"
</span><ins>+#include "LLIntData.h"
</ins><span class="cx"> #include "LLIntExceptions.h"
</span><span class="cx"> #include "LowLevelInterpreter.h"
</span><span class="cx"> #include "ObjectConstructor.h"
</span><span class="lines">@@ -1623,4 +1624,15 @@
</span><span class="cx"> CRASH();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+#if ENABLE(LLINT_STATS)
+
+LLINT_SLOW_PATH_DECL(count_opcode)
+{
+ OpcodeID opcodeID = exec->vm().interpreter->getOpcodeID(pc[0].u.opcode);
+ Data::opcodeStats(opcodeID).count++;
+ LLINT_END_IMPL();
+}
+
+#endif // ENABLE(LLINT_STATS)
+
</ins><span class="cx"> } } // namespace JSC::LLInt
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h (201989 => 201990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h        2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h        2016-06-13 15:53:42 UTC (rev 201990)
</span><span class="lines">@@ -54,6 +54,7 @@
</span><span class="cx"> LLINT_SLOW_PATH_HIDDEN_DECL(trace_arityCheck_for_construct);
</span><span class="cx"> LLINT_SLOW_PATH_HIDDEN_DECL(trace);
</span><span class="cx"> LLINT_SLOW_PATH_HIDDEN_DECL(special_trace);
</span><ins>+LLINT_SLOW_PATH_HIDDEN_DECL(count_opcode);
</ins><span class="cx"> LLINT_SLOW_PATH_HIDDEN_DECL(entry_osr);
</span><span class="cx"> LLINT_SLOW_PATH_HIDDEN_DECL(entry_osr_function_for_call);
</span><span class="cx"> LLINT_SLOW_PATH_HIDDEN_DECL(entry_osr_function_for_construct);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (201989 => 201990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2016-06-13 15:53:42 UTC (rev 201990)
</span><span class="lines">@@ -726,6 +726,9 @@
</span><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> macro traceExecution()
</span><ins>+ if COLLECT_STATS
+ callSlowPath(_llint_count_opcode)
+ end
</ins><span class="cx"> if EXECUTION_TRACING
</span><span class="cx"> callSlowPath(_llint_trace)
</span><span class="cx"> end
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.cpp (201989 => 201990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.cpp        2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/JavaScriptCore/runtime/Options.cpp        2016-06-13 15:53:42 UTC (rev 201990)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #include "config.h"
</span><span class="cx"> #include "Options.h"
</span><span class="cx">
</span><ins>+#include "LLIntCommon.h"
</ins><span class="cx"> #include <algorithm>
</span><span class="cx"> #include <limits>
</span><span class="cx"> #include <math.h>
</span><span class="lines">@@ -123,16 +124,31 @@
</span><span class="cx"> return false;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+bool Options::isAvailable(Options::ID id, Options::Availability availability)
+{
+ if (availability == Availability::Restricted)
+ return allowRestrictedOptions();
+ ASSERT(availability == Availability::Configurable);
+
+ UNUSED_PARAM(id);
+#if ENABLE(LLINT_STATS)
+ if (id == reportLLIntStatsID)
+ return true;
+#endif
+ return false;
+}
+
</ins><span class="cx"> template<typename T>
</span><del>-bool overrideOptionWithHeuristic(T& variable, const char* name, Options::Availability availability)
</del><ins>+bool overrideOptionWithHeuristic(T& variable, Options::ID id, const char* name, Options::Availability availability)
</ins><span class="cx"> {
</span><del>- bool isAvailable = (availability != Options::Availability::Restricted) || allowRestrictedOptions();
</del><ins>+ bool available = (availability == Options::Availability::Normal)
+ || Options::isAvailable(id, availability);
</ins><span class="cx">
</span><span class="cx"> const char* stringValue = getenv(name);
</span><span class="cx"> if (!stringValue)
</span><span class="cx"> return false;
</span><span class="cx">
</span><del>- if (isAvailable && parse(stringValue, variable))
</del><ins>+ if (available && parse(stringValue, variable))
</ins><span class="cx"> return true;
</span><span class="cx">
</span><span class="cx"> fprintf(stderr, "WARNING: failed to parse %s=%s\n", name, stringValue);
</span><span class="lines">@@ -258,7 +274,7 @@
</span><span class="cx"> scaleFactor = 0.0;
</span><span class="cx">
</span><span class="cx"> struct OptionToScale {
</span><del>- Options::OptionID id;
</del><ins>+ Options::ID id;
</ins><span class="cx"> int32_t minVal;
</span><span class="cx"> };
</span><span class="cx">
</span><span class="lines">@@ -406,7 +422,7 @@
</span><span class="cx"> CRASH();
</span><span class="cx"> #else // PLATFORM(COCOA)
</span><span class="cx"> #define FOR_EACH_OPTION(type_, name_, defaultValue_, availability_, description_) \
</span><del>- overrideOptionWithHeuristic(name_(), "JSC_" #name_, Availability::availability_);
</del><ins>+ overrideOptionWithHeuristic(name_(), name_##ID, "JSC_" #name_, Availability::availability_);
</ins><span class="cx"> JSC_OPTIONS(FOR_EACH_OPTION)
</span><span class="cx"> #undef FOR_EACH_OPTION
</span><span class="cx"> #endif // PLATFORM(COCOA)
</span><span class="lines">@@ -573,7 +589,8 @@
</span><span class="cx"> #define FOR_EACH_OPTION(type_, name_, defaultValue_, availability_, description_) \
</span><span class="cx"> if (strlen(#name_) == static_cast<size_t>(equalStr - arg) \
</span><span class="cx"> && !strncmp(arg, #name_, equalStr - arg)) { \
</span><del>- if (Availability::availability_ == Availability::Restricted && !allowRestrictedOptions()) \
</del><ins>+ if (Availability::availability_ != Availability::Normal \
+ && !isAvailable(name_##ID, Availability::availability_)) \
</ins><span class="cx"> return false; \
</span><span class="cx"> type_ value; \
</span><span class="cx"> value = (defaultValue_); \
</span><span class="lines">@@ -667,7 +684,7 @@
</span><span class="cx"> for (int id = 0; id < numberOfOptions; id++) {
</span><span class="cx"> if (separator && id)
</span><span class="cx"> builder.append(separator);
</span><del>- dumpOption(builder, level, static_cast<OptionID>(id), optionHeader, optionFooter, dumpDefaultsOption);
</del><ins>+ dumpOption(builder, level, static_cast<ID>(id), optionHeader, optionFooter, dumpDefaultsOption);
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -683,14 +700,15 @@
</span><span class="cx"> fprintf(stream, "%s", builder.toString().utf8().data());
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void Options::dumpOption(StringBuilder& builder, DumpLevel level, OptionID id,
</del><ins>+void Options::dumpOption(StringBuilder& builder, DumpLevel level, Options::ID id,
</ins><span class="cx"> const char* header, const char* footer, DumpDefaultsOption dumpDefaultsOption)
</span><span class="cx"> {
</span><span class="cx"> if (id >= numberOfOptions)
</span><span class="cx"> return; // Illegal option.
</span><span class="cx">
</span><span class="cx"> Option option(id);
</span><del>- if (option.availability() == Availability::Restricted && !allowRestrictedOptions())
</del><ins>+ Availability availability = option.availability();
+ if (availability != Availability::Normal && !isAvailable(id, availability))
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> bool wasOverridden = option.isOverridden();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (201989 => 201990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2016-06-13 15:53:42 UTC (rev 201990)
</span><span class="lines">@@ -371,7 +371,9 @@
</span><span class="cx"> v(bool, dumpAirAsJSBeforeAllocateStack, false, Normal, nullptr) \
</span><span class="cx"> v(bool, dumpAirAfterAllocateStack, false, Normal, nullptr) \
</span><span class="cx"> \
</span><del>- v(bool, useSuperSampler, false, Normal, nullptr)
</del><ins>+ v(bool, useSuperSampler, false, Normal, nullptr) \
+ \
+ v(bool, reportLLIntStats, false, Configurable, "Reports LLInt statistics")
</ins><span class="cx">
</span><span class="cx"> enum OptionEquivalence {
</span><span class="cx"> SameOption,
</span><span class="lines">@@ -421,7 +423,8 @@
</span><span class="cx">
</span><span class="cx"> enum class Availability {
</span><span class="cx"> Normal = 0,
</span><del>- Restricted
</del><ins>+ Restricted,
+ Configurable
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> // This typedef is to allow us to eliminate the '_' in the field name in
</span><span class="lines">@@ -429,7 +432,7 @@
</span><span class="cx"> typedef int32_t int32;
</span><span class="cx">
</span><span class="cx"> // Declare the option IDs:
</span><del>- enum OptionID {
</del><ins>+ enum ID {
</ins><span class="cx"> #define FOR_EACH_OPTION(type_, name_, defaultValue_, availability_, description_) \
</span><span class="cx"> name_##ID,
</span><span class="cx"> JSC_OPTIONS(FOR_EACH_OPTION)
</span><span class="lines">@@ -470,6 +473,8 @@
</span><span class="cx"> JSC_OPTIONS(FOR_EACH_OPTION)
</span><span class="cx"> #undef FOR_EACH_OPTION
</span><span class="cx">
</span><ins>+ static bool isAvailable(ID, Availability);
+
</ins><span class="cx"> private:
</span><span class="cx"> // For storing for an option value:
</span><span class="cx"> union Entry {
</span><span class="lines">@@ -499,7 +504,7 @@
</span><span class="cx"> static void dumpOptionsIfNeeded();
</span><span class="cx"> static void dumpAllOptions(StringBuilder&, DumpLevel, const char* title,
</span><span class="cx"> const char* separator, const char* optionHeader, const char* optionFooter, DumpDefaultsOption);
</span><del>- static void dumpOption(StringBuilder&, DumpLevel, OptionID,
</del><ins>+ static void dumpOption(StringBuilder&, DumpLevel, ID,
</ins><span class="cx"> const char* optionHeader, const char* optionFooter, DumpDefaultsOption);
</span><span class="cx">
</span><span class="cx"> static bool setOptionWithoutAlias(const char* arg);
</span><span class="lines">@@ -516,7 +521,7 @@
</span><span class="cx">
</span><span class="cx"> class Option {
</span><span class="cx"> public:
</span><del>- Option(Options::OptionID id)
</del><ins>+ Option(Options::ID id)
</ins><span class="cx"> : m_id(id)
</span><span class="cx"> , m_entry(Options::s_options[m_id])
</span><span class="cx"> {
</span><span class="lines">@@ -527,6 +532,7 @@
</span><span class="cx"> bool operator==(const Option& other) const;
</span><span class="cx"> bool operator!=(const Option& other) const { return !(*this == other); }
</span><span class="cx">
</span><ins>+ Options::ID id() const { return m_id; }
</ins><span class="cx"> const char* name() const;
</span><span class="cx"> const char* description() const;
</span><span class="cx"> Options::Type type() const;
</span><span class="lines">@@ -544,13 +550,13 @@
</span><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> // Only used for constructing default Options.
</span><del>- Option(Options::OptionID id, Options::Entry& entry)
</del><ins>+ Option(Options::ID id, Options::Entry& entry)
</ins><span class="cx"> : m_id(id)
</span><span class="cx"> , m_entry(entry)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><del>- Options::OptionID m_id;
</del><ins>+ Options::ID m_id;
</ins><span class="cx"> Options::Entry& m_entry;
</span><span class="cx"> };
</span><span class="cx">
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (201989 => 201990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Tools/ChangeLog        2016-06-13 15:53:42 UTC (rev 201990)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2016-06-13 Mark Lam <mark.lam@apple.com>
+
+ Add a mechanism for collecting LLINT stats.
+ https://bugs.webkit.org/show_bug.cgi?id=158668
+
+ Reviewed by Filip Pizlo.
+
+ * DumpRenderTree/mac/DumpRenderTree.mm:
+ (DumpRenderTreeMain):
+
</ins><span class="cx"> 2016-06-13 Romain Bellessort <romain.bellessort@crf.canon.fr>
</span><span class="cx">
</span><span class="cx"> [GTK] Enabling Shadow DOM by default
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreemacDumpRenderTreemm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm (201989 => 201990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm        2016-06-13 14:10:18 UTC (rev 201989)
+++ trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm        2016-06-13 15:53:42 UTC (rev 201990)
</span><span class="lines">@@ -57,6 +57,7 @@
</span><span class="cx"> #import "WorkQueueItem.h"
</span><span class="cx"> #import <CoreFoundation/CoreFoundation.h>
</span><span class="cx"> #import <JavaScriptCore/HeapStatistics.h>
</span><ins>+#import <JavaScriptCore/LLIntData.h>
</ins><span class="cx"> #import <JavaScriptCore/Options.h>
</span><span class="cx"> #import <WebCore/Logging.h>
</span><span class="cx"> #import <WebKit/DOMElement.h>
</span><span class="lines">@@ -1442,6 +1443,8 @@
</span><span class="cx"> [WebCoreStatistics emptyCache]; // Otherwise SVGImages trigger false positives for Frame/Node counts
</span><span class="cx"> if (JSC::Options::logHeapStatisticsAtExit())
</span><span class="cx"> JSC::HeapStatistics::reportSuccess();
</span><ins>+ if (JSC::Options::reportLLIntStats())
+ JSC::LLInt::Data::dumpStats();
</ins><span class="cx"> [pool release];
</span><span class="cx"> returningFromMain = true;
</span><span class="cx"> return 0;
</span></span></pre>
</div>
</div>
</body>
</html>