<!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>[199460] releases/WebKitGTK/webkit-2.12/Source</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/199460">199460</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2016-04-13 04:38:03 -0700 (Wed, 13 Apr 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/198778">r198778</a> - REGRESSION(<a href="http://trac.webkit.org/projects/webkit/changeset/192914">r192914</a>): 10% regression on Sunspider's date-format-tofte
https://bugs.webkit.org/show_bug.cgi?id=155559

Reviewed by Saam Barati.

Source/JavaScriptCore:

The fast path of the eval function is the super hot path in date-format-tofte.
Any performance regression is not allowed here.
Before this patch, we allocated SourceCode in the fast path.
This allocation incurs 10% performance regression.

This patch removes this allocation in the fast path.
And change the key of the EvalCodeCache to EvalCodeCache::CacheKey.
It combines RefPtr&lt;StringImpl&gt; and isArrowFunctionContext.
Since EvalCodeCache does not cache any eval code evaluated under the strict mode,
it is unnecessary to include several options (ThisTDZMode, and DerivedContextType) in the cache map's key.
But isArrowFunctionContext is necessary since the sloppy mode arrow function exists.

To validate this change, we add a new test that evaluates the same code
under the non-arrow function context and the arrow function context.

After introducing CacheKey, we observed 1% regression compared to the RefPtr&lt;StringImpl&gt; keyed case.
This is because HashMap&lt;RefPtr&lt;T&gt;, ...&gt;::get(T*) is specially optimized; this path is inlined while the normal ::get() is not inlined.
To avoid this performance regression, we introduce HashMap::fastGet, that aggressively encourages inlining.
The relationship between fastGet() and get() is similar to fastAdd() and add().
After applying this change, the evaluation shows no performance regression in comparison with the RefPtr&lt;StringImpl&gt; keyed case.

* bytecode/EvalCodeCache.h:
(JSC::EvalCodeCache::CacheKey::CacheKey):
(JSC::EvalCodeCache::CacheKey::hash):
(JSC::EvalCodeCache::CacheKey::isEmptyValue):
(JSC::EvalCodeCache::CacheKey::operator==):
(JSC::EvalCodeCache::CacheKey::isHashTableDeletedValue):
(JSC::EvalCodeCache::CacheKey::Hash::hash):
(JSC::EvalCodeCache::CacheKey::Hash::equal):
(JSC::EvalCodeCache::tryGet):
(JSC::EvalCodeCache::getSlow):
(JSC::EvalCodeCache::isCacheable):
* interpreter/Interpreter.cpp:
(JSC::eval):
* tests/stress/eval-in-arrow-function.js: Added.
(shouldBe):
(i):

Source/WTF:

Add HashTable::inlineLookup and HashMap::fastGet.

* wtf/HashMap.h:
* wtf/HashTable.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit212SourceJavaScriptCoreChangeLog">releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit212SourceJavaScriptCorebytecodeEvalCodeCacheh">releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/bytecode/EvalCodeCache.h</a></li>
<li><a href="#releasesWebKitGTKwebkit212SourceJavaScriptCoreinterpreterInterpretercpp">releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/interpreter/Interpreter.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit212SourceWTFChangeLog">releases/WebKitGTK/webkit-2.12/Source/WTF/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit212SourceWTFwtfHashMaph">releases/WebKitGTK/webkit-2.12/Source/WTF/wtf/HashMap.h</a></li>
<li><a href="#releasesWebKitGTKwebkit212SourceWTFwtfHashTableh">releases/WebKitGTK/webkit-2.12/Source/WTF/wtf/HashTable.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit212SourceJavaScriptCoretestsstressevalinarrowfunctionjs">releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/tests/stress/eval-in-arrow-function.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="releasesWebKitGTKwebkit212SourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/ChangeLog (199459 => 199460)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/ChangeLog        2016-04-13 11:16:24 UTC (rev 199459)
+++ releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/ChangeLog        2016-04-13 11:38:03 UTC (rev 199460)
</span><span class="lines">@@ -1,3 +1,48 @@
</span><ins>+2016-03-29  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        REGRESSION(r192914): 10% regression on Sunspider's date-format-tofte
+        https://bugs.webkit.org/show_bug.cgi?id=155559
+
+        Reviewed by Saam Barati.
+
+        The fast path of the eval function is the super hot path in date-format-tofte.
+        Any performance regression is not allowed here.
+        Before this patch, we allocated SourceCode in the fast path.
+        This allocation incurs 10% performance regression.
+
+        This patch removes this allocation in the fast path.
+        And change the key of the EvalCodeCache to EvalCodeCache::CacheKey.
+        It combines RefPtr&lt;StringImpl&gt; and isArrowFunctionContext.
+        Since EvalCodeCache does not cache any eval code evaluated under the strict mode,
+        it is unnecessary to include several options (ThisTDZMode, and DerivedContextType) in the cache map's key.
+        But isArrowFunctionContext is necessary since the sloppy mode arrow function exists.
+
+        To validate this change, we add a new test that evaluates the same code
+        under the non-arrow function context and the arrow function context.
+
+        After introducing CacheKey, we observed 1% regression compared to the RefPtr&lt;StringImpl&gt; keyed case.
+        This is because HashMap&lt;RefPtr&lt;T&gt;, ...&gt;::get(T*) is specially optimized; this path is inlined while the normal ::get() is not inlined.
+        To avoid this performance regression, we introduce HashMap::fastGet, that aggressively encourages inlining.
+        The relationship between fastGet() and get() is similar to fastAdd() and add().
+        After applying this change, the evaluation shows no performance regression in comparison with the RefPtr&lt;StringImpl&gt; keyed case.
+
+        * bytecode/EvalCodeCache.h:
+        (JSC::EvalCodeCache::CacheKey::CacheKey):
+        (JSC::EvalCodeCache::CacheKey::hash):
+        (JSC::EvalCodeCache::CacheKey::isEmptyValue):
+        (JSC::EvalCodeCache::CacheKey::operator==):
+        (JSC::EvalCodeCache::CacheKey::isHashTableDeletedValue):
+        (JSC::EvalCodeCache::CacheKey::Hash::hash):
+        (JSC::EvalCodeCache::CacheKey::Hash::equal):
+        (JSC::EvalCodeCache::tryGet):
+        (JSC::EvalCodeCache::getSlow):
+        (JSC::EvalCodeCache::isCacheable):
+        * interpreter/Interpreter.cpp:
+        (JSC::eval):
+        * tests/stress/eval-in-arrow-function.js: Added.
+        (shouldBe):
+        (i):
+
</ins><span class="cx"> 2016-03-20  Michael Saboff  &lt;msaboff@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Crash in stress/regexp-matches-array-slow-put.js due to stomping on memory when having bad time
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit212SourceJavaScriptCorebytecodeEvalCodeCacheh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/bytecode/EvalCodeCache.h (199459 => 199460)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/bytecode/EvalCodeCache.h        2016-04-13 11:16:24 UTC (rev 199459)
+++ releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/bytecode/EvalCodeCache.h        2016-04-13 11:38:03 UTC (rev 199460)
</span><span class="lines">@@ -34,7 +34,6 @@
</span><span class="cx"> #include &quot;JSScope.h&quot;
</span><span class="cx"> #include &quot;Options.h&quot;
</span><span class="cx"> #include &quot;SourceCode.h&quot;
</span><del>-#include &quot;SourceCodeKey.h&quot;
</del><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><span class="cx"> #include &lt;wtf/RefPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/text/StringHash.h&gt;
</span><span class="lines">@@ -45,29 +44,73 @@
</span><span class="cx"> 
</span><span class="cx">     class EvalCodeCache {
</span><span class="cx">     public:
</span><del>-        EvalExecutable* tryGet(bool inStrictContext, const SourceCode&amp; evalSource, ThisTDZMode thisTDZMode, JSScope* scope)
</del><ins>+        class CacheKey {
+        public:
+            CacheKey(const String&amp; source, bool isArrowFunctionContext)
+                : m_source(source.impl())
+                , m_isArrowFunctionContext(isArrowFunctionContext)
+            {
+            }
+
+            CacheKey(WTF::HashTableDeletedValueType)
+                : m_source(WTF::HashTableDeletedValue)
+            {
+            }
+
+            CacheKey() = default;
+
+            unsigned hash() const { return m_source-&gt;hash(); }
+
+            bool isEmptyValue() const { return !m_source; }
+
+            bool operator==(const CacheKey&amp; other) const
+            {
+                return m_source == other.m_source &amp;&amp; m_isArrowFunctionContext == other.m_isArrowFunctionContext;
+            }
+
+            bool isHashTableDeletedValue() const { return m_source.isHashTableDeletedValue(); }
+
+            struct Hash {
+                static unsigned hash(const CacheKey&amp; key)
+                {
+                    return key.hash();
+                }
+                static bool equal(const CacheKey&amp; lhs, const CacheKey&amp; rhs)
+                {
+                    return StringHash::equal(lhs.m_source, rhs.m_source) &amp;&amp; lhs.m_isArrowFunctionContext == rhs.m_isArrowFunctionContext;
+                }
+                static const bool safeToCompareToEmptyOrDeleted = false;
+            };
+
+            typedef SimpleClassHashTraits&lt;CacheKey&gt; HashTraits;
+
+        private:
+            RefPtr&lt;StringImpl&gt; m_source;
+            bool m_isArrowFunctionContext { false };
+        };
+
+        EvalExecutable* tryGet(bool inStrictContext, const String&amp; evalSource, bool isArrowFunctionContext, JSScope* scope)
</ins><span class="cx">         {
</span><span class="cx">             if (isCacheable(inStrictContext, evalSource, scope)) {
</span><span class="cx">                 ASSERT(!inStrictContext);
</span><del>-                SourceCodeKey sourceCodeKey(evalSource, String(), SourceCodeKey::EvalType, JSParserBuiltinMode::NotBuiltin, JSParserStrictMode::NotStrict, thisTDZMode);
-                return m_cacheMap.get(sourceCodeKey).get();
</del><ins>+                return m_cacheMap.fastGet(CacheKey(evalSource, isArrowFunctionContext)).get();
</ins><span class="cx">             }
</span><span class="cx">             return nullptr;
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        EvalExecutable* getSlow(ExecState* exec, JSCell* owner, bool inStrictContext, ThisTDZMode thisTDZMode, DerivedContextType derivedContextType, bool isArrowFunctionContext, const SourceCode&amp; evalSource, JSScope* scope)
</del><ins>+        EvalExecutable* getSlow(ExecState* exec, JSCell* owner, bool inStrictContext, ThisTDZMode thisTDZMode, DerivedContextType derivedContextType, bool isArrowFunctionContext, const String&amp; evalSource, JSScope* scope)
</ins><span class="cx">         {
</span><span class="cx">             VariableEnvironment variablesUnderTDZ;
</span><span class="cx">             JSScope::collectVariablesUnderTDZ(scope, variablesUnderTDZ);
</span><del>-            EvalExecutable* evalExecutable = EvalExecutable::create(exec, evalSource, inStrictContext, thisTDZMode, derivedContextType, isArrowFunctionContext, &amp;variablesUnderTDZ);
-
</del><ins>+            EvalExecutable* evalExecutable = EvalExecutable::create(exec, makeSource(evalSource), inStrictContext, thisTDZMode, derivedContextType, isArrowFunctionContext, &amp;variablesUnderTDZ);
</ins><span class="cx">             if (!evalExecutable)
</span><span class="cx">                 return nullptr;
</span><span class="cx"> 
</span><span class="cx">             if (isCacheable(inStrictContext, evalSource, scope) &amp;&amp; m_cacheMap.size() &lt; maxCacheEntries) {
</span><span class="cx">                 ASSERT(!inStrictContext);
</span><del>-                SourceCodeKey sourceCodeKey(evalSource, String(), SourceCodeKey::EvalType, JSParserBuiltinMode::NotBuiltin, JSParserStrictMode::NotStrict, thisTDZMode);
-                m_cacheMap.set(sourceCodeKey, WriteBarrier&lt;EvalExecutable&gt;(exec-&gt;vm(), owner, evalExecutable));
</del><ins>+                ASSERT_WITH_MESSAGE(thisTDZMode == ThisTDZMode::CheckIfNeeded, &quot;Always CheckIfNeeded because the caching is enabled only in the sloppy mode.&quot;);
+                ASSERT_WITH_MESSAGE(derivedContextType == DerivedContextType::None, &quot;derivedContextType is always None because class methods and class constructors are always evaluated as the strict code.&quot;);
+                m_cacheMap.set(CacheKey(evalSource, isArrowFunctionContext), WriteBarrier&lt;EvalExecutable&gt;(exec-&gt;vm(), owner, evalExecutable));
</ins><span class="cx">             }
</span><span class="cx">             
</span><span class="cx">             return evalExecutable;
</span><span class="lines">@@ -88,7 +131,7 @@
</span><span class="cx">             return scope-&gt;isGlobalLexicalEnvironment() || scope-&gt;isFunctionNameScopeObject() || scope-&gt;isVarScope();
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        ALWAYS_INLINE bool isCacheable(bool inStrictContext, const SourceCode&amp; evalSource, JSScope* scope)
</del><ins>+        ALWAYS_INLINE bool isCacheable(bool inStrictContext, const String&amp; evalSource, JSScope* scope)
</ins><span class="cx">         {
</span><span class="cx">             // If eval() is called and it has access to a lexical scope, we can't soundly cache it.
</span><span class="cx">             // If the eval() only has access to the &quot;var&quot; scope, then we can cache it.
</span><span class="lines">@@ -98,7 +141,7 @@
</span><span class="cx">         }
</span><span class="cx">         static const int maxCacheEntries = 64;
</span><span class="cx"> 
</span><del>-        typedef HashMap&lt;SourceCodeKey, WriteBarrier&lt;EvalExecutable&gt;, SourceCodeKeyHash, SourceCodeKeyHashTraits&gt; EvalCacheMap;
</del><ins>+        typedef HashMap&lt;CacheKey, WriteBarrier&lt;EvalExecutable&gt;, CacheKey::Hash, CacheKey::HashTraits&gt; EvalCacheMap;
</ins><span class="cx">         EvalCacheMap m_cacheMap;
</span><span class="cx">     };
</span><span class="cx"> 
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit212SourceJavaScriptCoreinterpreterInterpretercpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/interpreter/Interpreter.cpp (199459 => 199460)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/interpreter/Interpreter.cpp        2016-04-13 11:16:24 UTC (rev 199459)
+++ releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/interpreter/Interpreter.cpp        2016-04-13 11:38:03 UTC (rev 199460)
</span><span class="lines">@@ -159,13 +159,9 @@
</span><span class="cx">     JSScope* callerScopeChain = callerFrame-&gt;uncheckedR(callerCodeBlock-&gt;scopeRegister().offset()).Register::scope();
</span><span class="cx">     UnlinkedCodeBlock* callerUnlinkedCodeBlock = callerCodeBlock-&gt;unlinkedCodeBlock();
</span><span class="cx"> 
</span><del>-    ThisTDZMode thisTDZMode = ThisTDZMode::CheckIfNeeded;
-    if (callerUnlinkedCodeBlock-&gt;constructorKind() == ConstructorKind::Derived)
-        thisTDZMode = ThisTDZMode::AlwaysCheck;
</del><ins>+    bool isArrowFunctionContext = callerUnlinkedCodeBlock-&gt;isArrowFunction() || callerUnlinkedCodeBlock-&gt;isArrowFunctionContext();
+    EvalExecutable* eval = callerCodeBlock-&gt;evalCodeCache().tryGet(callerCodeBlock-&gt;isStrictMode(), programSource, isArrowFunctionContext, callerScopeChain);
</ins><span class="cx"> 
</span><del>-    SourceCode sourceCode(makeSource(programSource));
-    EvalExecutable* eval = callerCodeBlock-&gt;evalCodeCache().tryGet(callerCodeBlock-&gt;isStrictMode(), sourceCode, thisTDZMode, callerScopeChain);
-
</del><span class="cx">     if (!eval) {
</span><span class="cx">         if (!callerCodeBlock-&gt;isStrictMode()) {
</span><span class="cx">             if (programSource.is8Bit()) {
</span><span class="lines">@@ -182,8 +178,11 @@
</span><span class="cx">         // If the literal parser bailed, it should not have thrown exceptions.
</span><span class="cx">         ASSERT(!callFrame-&gt;vm().exception());
</span><span class="cx"> 
</span><del>-        eval = callerCodeBlock-&gt;evalCodeCache().getSlow(callFrame, callerCodeBlock, callerCodeBlock-&gt;isStrictMode(), thisTDZMode, callerCodeBlock-&gt;unlinkedCodeBlock()-&gt;derivedContextType(), callerCodeBlock-&gt;unlinkedCodeBlock()-&gt;isArrowFunction(), sourceCode, callerScopeChain);
</del><ins>+        ThisTDZMode thisTDZMode = ThisTDZMode::CheckIfNeeded;
+        if (callerUnlinkedCodeBlock-&gt;constructorKind() == ConstructorKind::Derived)
+            thisTDZMode = ThisTDZMode::AlwaysCheck;
</ins><span class="cx"> 
</span><ins>+        eval = callerCodeBlock-&gt;evalCodeCache().getSlow(callFrame, callerCodeBlock, callerCodeBlock-&gt;isStrictMode(), thisTDZMode, callerCodeBlock-&gt;unlinkedCodeBlock()-&gt;derivedContextType(), callerCodeBlock-&gt;unlinkedCodeBlock()-&gt;isArrowFunction(), programSource, callerScopeChain);
</ins><span class="cx">         if (!eval)
</span><span class="cx">             return jsUndefined();
</span><span class="cx">     }
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit212SourceJavaScriptCoretestsstressevalinarrowfunctionjs"></a>
<div class="addfile"><h4>Added: releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/tests/stress/eval-in-arrow-function.js (0 => 199460)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/tests/stress/eval-in-arrow-function.js                                (rev 0)
+++ releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/tests/stress/eval-in-arrow-function.js        2016-04-13 11:38:03 UTC (rev 199460)
</span><span class="lines">@@ -0,0 +1,35 @@
</span><ins>+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error(`bad value: ${String(actual)}`);
+}
+
+function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+
+var global = this;
+for (var i = 0; i &lt; 100; ++i) {
+    (() =&gt; {
+        // |this| should reference to the global one.
+        shouldBe(eval(&quot;this&quot;), global);
+    })();
+}
+
+for (var i = 0; i &lt; 100; ++i) {
+    var THIS = {};
+    (function test() {
+        // |this| should reference to the function's one.
+        shouldBe(eval(&quot;this&quot;), THIS);
+    }).call(THIS);
+}
</ins></span></pre></div>
<a id="releasesWebKitGTKwebkit212SourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.12/Source/WTF/ChangeLog (199459 => 199460)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.12/Source/WTF/ChangeLog        2016-04-13 11:16:24 UTC (rev 199459)
+++ releases/WebKitGTK/webkit-2.12/Source/WTF/ChangeLog        2016-04-13 11:38:03 UTC (rev 199460)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-03-29  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        REGRESSION(r192914): 10% regression on Sunspider's date-format-tofte
+        https://bugs.webkit.org/show_bug.cgi?id=155559
+
+        Reviewed by Saam Barati.
+
+        Add HashTable::inlineLookup and HashMap::fastGet.
+
+        * wtf/HashMap.h:
+        * wtf/HashTable.h:
+
</ins><span class="cx"> 2016-03-17  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Silence leaks in ParkingLot
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit212SourceWTFwtfHashMaph"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.12/Source/WTF/wtf/HashMap.h (199459 => 199460)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.12/Source/WTF/wtf/HashMap.h        2016-04-13 11:16:24 UTC (rev 199459)
+++ releases/WebKitGTK/webkit-2.12/Source/WTF/wtf/HashMap.h        2016-04-13 11:38:03 UTC (rev 199460)
</span><span class="lines">@@ -102,6 +102,9 @@
</span><span class="cx">     bool contains(const KeyType&amp;) const;
</span><span class="cx">     MappedPeekType get(const KeyType&amp;) const;
</span><span class="cx"> 
</span><ins>+    // Same as get(), but aggressively inlined.
+    MappedPeekType fastGet(const KeyType&amp;) const;
+
</ins><span class="cx">     // Replaces the value but not the key if the key is already present.
</span><span class="cx">     // Return value includes both an iterator to the key location,
</span><span class="cx">     // and an isNewEntry boolean that's true if a new entry was added.
</span><span class="lines">@@ -392,6 +395,15 @@
</span><span class="cx">     return MappedTraits::peek(entry-&gt;value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename T, typename U, typename V, typename W, typename MappedTraits&gt;
+ALWAYS_INLINE auto HashMap&lt;T, U, V, W, MappedTraits&gt;::fastGet(const KeyType&amp; key) const -&gt; MappedPeekType
+{
+    KeyValuePairType* entry = const_cast&lt;HashTableType&amp;&gt;(m_impl).template inlineLookup&lt;typename HashTableType::IdentityTranslatorType&gt;(key);
+    if (!entry)
+        return MappedTraits::peek(MappedTraits::emptyValue());
+    return MappedTraits::peek(entry-&gt;value);
+}
+
</ins><span class="cx"> template&lt;typename T, typename U, typename V, typename W, typename X&gt;
</span><span class="cx"> inline bool HashMap&lt;T, U, V, W, X&gt;::remove(iterator it)
</span><span class="cx"> {
</span><span class="lines">@@ -457,7 +469,7 @@
</span><span class="cx"> template&lt;typename K&gt;
</span><span class="cx"> inline auto HashMap&lt;T, U, V, W, X&gt;::inlineGet(typename GetPtrHelper&lt;K&gt;::PtrType key) const -&gt; typename std::enable_if&lt;IsSmartPtr&lt;K&gt;::value, MappedPeekType&gt;::type
</span><span class="cx"> {
</span><del>-    KeyValuePairType* entry = const_cast&lt;HashTableType&amp;&gt;(m_impl).template lookup&lt;HashMapTranslator&lt;KeyValuePairTraits, HashFunctions&gt;&gt;(key);
</del><ins>+    KeyValuePairType* entry = const_cast&lt;HashTableType&amp;&gt;(m_impl).template inlineLookup&lt;HashMapTranslator&lt;KeyValuePairTraits, HashFunctions&gt;&gt;(key);
</ins><span class="cx">     if (!entry)
</span><span class="cx">         return MappedTraits::peek(MappedTraits::emptyValue());
</span><span class="cx">     return MappedTraits::peek(entry-&gt;value);
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit212SourceWTFwtfHashTableh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.12/Source/WTF/wtf/HashTable.h (199459 => 199460)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.12/Source/WTF/wtf/HashTable.h        2016-04-13 11:16:24 UTC (rev 199459)
+++ releases/WebKitGTK/webkit-2.12/Source/WTF/wtf/HashTable.h        2016-04-13 11:38:03 UTC (rev 199460)
</span><span class="lines">@@ -412,6 +412,7 @@
</span><span class="cx"> 
</span><span class="cx">         ValueType* lookup(const Key&amp; key) { return lookup&lt;IdentityTranslatorType&gt;(key); }
</span><span class="cx">         template&lt;typename HashTranslator, typename T&gt; ValueType* lookup(const T&amp;);
</span><ins>+        template&lt;typename HashTranslator, typename T&gt; ValueType* inlineLookup(const T&amp;);
</ins><span class="cx"> 
</span><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx">         void checkTableConsistency() const;
</span><span class="lines">@@ -595,6 +596,13 @@
</span><span class="cx">     template&lt;typename HashTranslator, typename T&gt;
</span><span class="cx">     inline auto HashTable&lt;Key, Value, Extractor, HashFunctions, Traits, KeyTraits&gt;::lookup(const T&amp; key) -&gt; ValueType*
</span><span class="cx">     {
</span><ins>+        return inlineLookup&lt;HashTranslator&gt;(key);
+    }
+
+    template&lt;typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits&gt;
+    template&lt;typename HashTranslator, typename T&gt;
+    ALWAYS_INLINE auto HashTable&lt;Key, Value, Extractor, HashFunctions, Traits, KeyTraits&gt;::inlineLookup(const T&amp; key) -&gt; ValueType*
+    {
</ins><span class="cx">         checkKey&lt;HashTranslator&gt;(key);
</span><span class="cx"> 
</span><span class="cx">         unsigned k = 0;
</span></span></pre>
</div>
</div>

</body>
</html>