<!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  &lt;mark.lam@apple.com&gt;
+
+        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  &lt;mark.lam@apple.com&gt;
</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 &quot;JSCell.h&quot;
</span><span class="cx"> #include &quot;JSObject.h&quot;
</span><span class="cx"> #include &quot;JSStack.h&quot;
</span><del>-#include &quot;LLIntData.h&quot;
</del><span class="cx"> #include &quot;Opcode.h&quot;
</span><span class="cx"> #include &quot;SourceProvider.h&quot;
</span><span class="cx"> #include &quot;StackAlignment.h&quot;
</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 &quot;JSProxy.h&quot;
</span><span class="cx"> #include &quot;JSString.h&quot;
</span><span class="cx"> #include &quot;JSWASMModule.h&quot;
</span><ins>+#include &quot;LLIntData.h&quot;
</ins><span class="cx"> #include &quot;ProfilerDatabase.h&quot;
</span><span class="cx"> #include &quot;SamplingProfiler.h&quot;
</span><span class="cx"> #include &quot;ShadowChicken.h&quot;
</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 &quot;config.h&quot;
</span><span class="cx"> #include &quot;LLIntData.h&quot;
</span><ins>+
</ins><span class="cx"> #include &quot;BytecodeConventions.h&quot;
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><span class="cx"> #include &quot;CodeType.h&quot;
</span><span class="cx"> #include &quot;Instruction.h&quot;
</span><span class="cx"> #include &quot;JSScope.h&quot;
</span><span class="cx"> #include &quot;LLIntCLoop.h&quot;
</span><ins>+#include &quot;LLIntCommon.h&quot;
</ins><span class="cx"> #include &quot;MaxFrameExtentForSlowPathCall.h&quot;
</span><span class="cx"> #include &quot;Opcode.h&quot;
</span><span class="cx"> #include &quot;PropertyOffset.h&quot;
</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 &quot;C&quot; 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&amp; stats : *Data::s_opcodeStatsArray)
+        stats.id = static_cast&lt;OpcodeID&gt;(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&amp; a, OpcodeStats&amp; b) -&gt; bool {
+        return a.count &gt; b.count;
+    });
+    
+    dataLog(&quot;Opcode stats:\n&quot;);
+    unsigned i = 0;
+    for (auto&amp; stats : statsCopy) {
+        if (stats.count)
+            dataLog(&quot;   [&quot;, i++, &quot;]: fast:&quot;, stats.count, &quot; &quot;, opcodeNames[stats.id], &quot;\n&quot;);
+    }
+#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 &quot;JSCJSValue.h&quot;
</span><span class="cx"> #include &quot;Opcode.h&quot;
</span><ins>+#include &lt;array&gt;
</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&lt;OpcodeStats, numOpcodeIDs&gt; OpcodeStatsArray;
+
</ins><span class="cx"> class Data {
</span><span class="cx"> public:
</span><ins>+
</ins><span class="cx">     static void performAssertions(VM&amp;);
</span><ins>+    static OpcodeStats&amp; 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 &quot;JSString.h&quot;
</span><span class="cx"> #include &quot;JSWithScope.h&quot;
</span><span class="cx"> #include &quot;LLIntCommon.h&quot;
</span><ins>+#include &quot;LLIntData.h&quot;
</ins><span class="cx"> #include &quot;LLIntExceptions.h&quot;
</span><span class="cx"> #include &quot;LowLevelInterpreter.h&quot;
</span><span class="cx"> #include &quot;ObjectConstructor.h&quot;
</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-&gt;vm().interpreter-&gt;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 &quot;config.h&quot;
</span><span class="cx"> #include &quot;Options.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;LLIntCommon.h&quot;
</ins><span class="cx"> #include &lt;algorithm&gt;
</span><span class="cx"> #include &lt;limits&gt;
</span><span class="cx"> #include &lt;math.h&gt;
</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&lt;typename T&gt;
</span><del>-bool overrideOptionWithHeuristic(T&amp; variable, const char* name, Options::Availability availability)
</del><ins>+bool overrideOptionWithHeuristic(T&amp; 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 &amp;&amp; parse(stringValue, variable))
</del><ins>+    if (available &amp;&amp; parse(stringValue, variable))
</ins><span class="cx">         return true;
</span><span class="cx">     
</span><span class="cx">     fprintf(stderr, &quot;WARNING: failed to parse %s=%s\n&quot;, 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_(), &quot;JSC_&quot; #name_, Availability::availability_);
</del><ins>+            overrideOptionWithHeuristic(name_(), name_##ID, &quot;JSC_&quot; #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&lt;size_t&gt;(equalStr - arg)      \
</span><span class="cx">         &amp;&amp; !strncmp(arg, #name_, equalStr - arg)) {                \
</span><del>-        if (Availability::availability_ == Availability::Restricted &amp;&amp; !allowRestrictedOptions()) \
</del><ins>+        if (Availability::availability_ != Availability::Normal     \
+            &amp;&amp; !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 &lt; numberOfOptions; id++) {
</span><span class="cx">         if (separator &amp;&amp; id)
</span><span class="cx">             builder.append(separator);
</span><del>-        dumpOption(builder, level, static_cast&lt;OptionID&gt;(id), optionHeader, optionFooter, dumpDefaultsOption);
</del><ins>+        dumpOption(builder, level, static_cast&lt;ID&gt;(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, &quot;%s&quot;, builder.toString().utf8().data());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Options::dumpOption(StringBuilder&amp; builder, DumpLevel level, OptionID id,
</del><ins>+void Options::dumpOption(StringBuilder&amp; 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 &gt;= 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 &amp;&amp; !allowRestrictedOptions())
</del><ins>+    Availability availability = option.availability();
+    if (availability != Availability::Normal &amp;&amp; !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, &quot;Reports LLInt statistics&quot;)
</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&amp;, DumpLevel, const char* title,
</span><span class="cx">         const char* separator, const char* optionHeader, const char* optionFooter, DumpDefaultsOption);
</span><del>-    static void dumpOption(StringBuilder&amp;, DumpLevel, OptionID,
</del><ins>+    static void dumpOption(StringBuilder&amp;, 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&amp; other) const;
</span><span class="cx">     bool operator!=(const Option&amp; 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&amp; entry)
</del><ins>+    Option(Options::ID id, Options::Entry&amp; 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&amp; 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  &lt;mark.lam@apple.com&gt;
+
+        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  &lt;romain.bellessort@crf.canon.fr&gt;
</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 &quot;WorkQueueItem.h&quot;
</span><span class="cx"> #import &lt;CoreFoundation/CoreFoundation.h&gt;
</span><span class="cx"> #import &lt;JavaScriptCore/HeapStatistics.h&gt;
</span><ins>+#import &lt;JavaScriptCore/LLIntData.h&gt;
</ins><span class="cx"> #import &lt;JavaScriptCore/Options.h&gt;
</span><span class="cx"> #import &lt;WebCore/Logging.h&gt;
</span><span class="cx"> #import &lt;WebKit/DOMElement.h&gt;
</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>