<!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>[179392] trunk/Source/JavaScriptCore</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/179392">179392</a></dd>
<dt>Author</dt> <dd>akling@apple.com</dd>
<dt>Date</dt> <dd>2015-01-29 20:28:36 -0800 (Thu, 29 Jan 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Unreviewed, rolling out <a href="http://trac.webkit.org/projects/webkit/changeset/179357">r179357</a> and <a href="http://trac.webkit.org/projects/webkit/changeset/179358">r179358</a>.
https://bugs.webkit.org/show_bug.cgi?id=141062
Suspect this caused WebGL tests to start flaking (Requested by
kling on #webkit).
Reverted changesets:
"Polymorphic call inlining should be based on polymorphic call
inline caching rather than logging"
https://bugs.webkit.org/show_bug.cgi?id=140660
http://trac.webkit.org/changeset/179357
"Unreviewed, fix no-JIT build."
http://trac.webkit.org/changeset/179358
Patch by Commit Queue <commit-queue@webkit.org> on 2015-01-29</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallEdgeh">trunk/Source/JavaScriptCore/bytecode/CallEdge.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallLinkInfocpp">trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallLinkInfoh">trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallLinkStatuscpp">trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallLinkStatush">trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallVariantcpp">trunk/Source/JavaScriptCore/bytecode/CallVariant.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallVarianth">trunk/Source/JavaScriptCore/bytecode/CallVariant.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockh">trunk/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDoesGCcpp">trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDrivercpp">trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSafeToExecuteh">trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGTierUpCheckInjectionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapcpp">trunk/Source/JavaScriptCore/heap/Heap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitBinarySwitchh">trunk/Source/JavaScriptCore/jit/BinarySwitch.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCallcpp">trunk/Source/JavaScriptCore/jit/JITCall.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCall32_64cpp">trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationsh">trunk/Source/JavaScriptCore/jit/JITOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITStubRoutineh">trunk/Source/JavaScriptCore/jit/JITStubRoutine.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITWriteBarrierh">trunk/Source/JavaScriptCore/jit/JITWriteBarrier.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRepatchcpp">trunk/Source/JavaScriptCore/jit/Repatch.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRepatchh">trunk/Source/JavaScriptCore/jit/Repatch.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitThunkGeneratorscpp">trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitThunkGeneratorsh">trunk/Source/JavaScriptCore/jit/ThunkGenerators.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMcpp">trunk/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallEdgeProfilecpp">trunk/Source/JavaScriptCore/bytecode/CallEdgeProfile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallEdgeProfileh">trunk/Source/JavaScriptCore/bytecode/CallEdgeProfile.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallEdgeProfileInlinesh">trunk/Source/JavaScriptCore/bytecode/CallEdgeProfileInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitClosureCallStubRoutinecpp">trunk/Source/JavaScriptCore/jit/ClosureCallStubRoutine.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitClosureCallStubRoutineh">trunk/Source/JavaScriptCore/jit/ClosureCallStubRoutine.h</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCorejitPolymorphicCallStubRoutinecpp">trunk/Source/JavaScriptCore/jit/PolymorphicCallStubRoutine.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitPolymorphicCallStubRoutineh">trunk/Source/JavaScriptCore/jit/PolymorphicCallStubRoutine.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -66,6 +66,7 @@
</span><span class="cx"> bytecode/BytecodeBasicBlock.cpp
</span><span class="cx"> bytecode/BytecodeLivenessAnalysis.cpp
</span><span class="cx"> bytecode/CallEdge.cpp
</span><ins>+ bytecode/CallEdgeProfile.cpp
</ins><span class="cx"> bytecode/CallLinkInfo.cpp
</span><span class="cx"> bytecode/CallLinkStatus.cpp
</span><span class="cx"> bytecode/CallVariant.cpp
</span><span class="lines">@@ -326,6 +327,7 @@
</span><span class="cx"> jit/AssemblyHelpers.cpp
</span><span class="cx"> jit/ArityCheckFailReturnThunks.cpp
</span><span class="cx"> jit/BinarySwitch.cpp
</span><ins>+ jit/ClosureCallStubRoutine.cpp
</ins><span class="cx"> jit/ExecutableAllocator.cpp
</span><span class="cx"> jit/ExecutableAllocatorFixedVMPool.cpp
</span><span class="cx"> jit/GCAwareJITStubRoutine.cpp
</span><span class="lines">@@ -348,7 +350,6 @@
</span><span class="cx"> jit/JITStubs.cpp
</span><span class="cx"> jit/JITThunks.cpp
</span><span class="cx"> jit/JITToDFGDeferredCompilationCallback.cpp
</span><del>- jit/PolymorphicCallStubRoutine.cpp
</del><span class="cx"> jit/Reg.cpp
</span><span class="cx"> jit/RegisterPreservationWrapperGenerator.cpp
</span><span class="cx"> jit/RegisterSet.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2015-01-29 Commit Queue <commit-queue@webkit.org>
+
+ Unreviewed, rolling out r179357 and r179358.
+ https://bugs.webkit.org/show_bug.cgi?id=141062
+
+ Suspect this caused WebGL tests to start flaking (Requested by
+ kling on #webkit).
+
+ Reverted changesets:
+
+ "Polymorphic call inlining should be based on polymorphic call
+ inline caching rather than logging"
+ https://bugs.webkit.org/show_bug.cgi?id=140660
+ http://trac.webkit.org/changeset/179357
+
+ "Unreviewed, fix no-JIT build."
+ http://trac.webkit.org/changeset/179358
+
</ins><span class="cx"> 2015-01-29 Geoffrey Garen <ggaren@apple.com>
</span><span class="cx">
</span><span class="cx"> Removed op_ret_object_or_this
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -314,6 +314,7 @@
</span><span class="cx"> <ClCompile Include="..\bytecode\BytecodeBasicBlock.cpp" />
</span><span class="cx"> <ClCompile Include="..\bytecode\BytecodeLivenessAnalysis.cpp" />
</span><span class="cx"> <ClCompile Include="..\bytecode\CallEdge.cpp" />
</span><ins>+ <ClCompile Include="..\bytecode\CallEdgeProfile.cpp" />
</ins><span class="cx"> <ClCompile Include="..\bytecode\CallLinkInfo.cpp" />
</span><span class="cx"> <ClCompile Include="..\bytecode\CallLinkStatus.cpp" />
</span><span class="cx"> <ClCompile Include="..\bytecode\CallVariant.cpp" />
</span><span class="lines">@@ -597,6 +598,7 @@
</span><span class="cx"> <ClCompile Include="..\jit\ArityCheckFailReturnThunks.cpp" />
</span><span class="cx"> <ClCompile Include="..\jit\AssemblyHelpers.cpp" />
</span><span class="cx"> <ClCompile Include="..\jit\BinarySwitch.cpp" />
</span><ins>+ <ClCompile Include="..\jit\ClosureCallStubRoutine.cpp" />
</ins><span class="cx"> <ClCompile Include="..\jit\ExecutableAllocator.cpp" />
</span><span class="cx"> <ClCompile Include="..\jit\GCAwareJITStubRoutine.cpp" />
</span><span class="cx"> <ClCompile Include="..\jit\HostCallReturnValue.cpp" />
</span><span class="lines">@@ -619,7 +621,6 @@
</span><span class="cx"> <ClCompile Include="..\jit\JITStubs.cpp" />
</span><span class="cx"> <ClCompile Include="..\jit\JITThunks.cpp" />
</span><span class="cx"> <ClCompile Include="..\jit\JITToDFGDeferredCompilationCallback.cpp" />
</span><del>- <ClCompile Include="..\jit\PolymorphicCallStubRoutine.cpp" />
</del><span class="cx"> <ClCompile Include="..\jit\Reg.cpp" />
</span><span class="cx"> <ClCompile Include="..\jit\RegisterPreservationWrapperGenerator.cpp" />
</span><span class="cx"> <ClCompile Include="..\jit\RegisterSet.cpp" />
</span><span class="lines">@@ -930,6 +931,8 @@
</span><span class="cx"> <ClInclude Include="..\bytecode\BytecodeLivenessAnalysis.h" />
</span><span class="cx"> <ClInclude Include="..\bytecode\BytecodeUseDef.h" />
</span><span class="cx"> <ClInclude Include="..\bytecode\CallEdge.h" />
</span><ins>+ <ClInclude Include="..\bytecode\CallEdgeProfile.h" />
+ <ClInclude Include="..\bytecode\CallEdgeProfileInlines.h" />
</ins><span class="cx"> <ClInclude Include="..\bytecode\CallLinkInfo.h" />
</span><span class="cx"> <ClInclude Include="..\bytecode\CallLinkStatus.h" />
</span><span class="cx"> <ClInclude Include="..\bytecode\CallReturnOffsetToBytecodeOffset.h" />
</span><span class="lines">@@ -1330,6 +1333,7 @@
</span><span class="cx"> <ClInclude Include="..\jit\AssemblyHelpers.h" />
</span><span class="cx"> <ClInclude Include="..\jit\BinarySwitch.h" />
</span><span class="cx"> <ClInclude Include="..\jit\CCallHelpers.h" />
</span><ins>+ <ClInclude Include="..\jit\ClosureCallStubRoutine.h" />
</ins><span class="cx"> <ClInclude Include="..\jit\CompactJITCodeMap.h" />
</span><span class="cx"> <ClInclude Include="..\jit\ExecutableAllocator.h" />
</span><span class="cx"> <ClInclude Include="..\jit\FPRInfo.h" />
</span><span class="lines">@@ -1353,7 +1357,6 @@
</span><span class="cx"> <ClInclude Include="..\jit\JITToDFGDeferredCompilationCallback.h" />
</span><span class="cx"> <ClInclude Include="..\jit\JITWriteBarrier.h" />
</span><span class="cx"> <ClInclude Include="..\jit\JSInterfaceJIT.h" />
</span><del>- <ClInclude Include="..\jit\PolymorphicCallStubRoutine.h" />
</del><span class="cx"> <ClInclude Include="..\jit\Reg.h" />
</span><span class="cx"> <ClInclude Include="..\jit\RegisterPreservationWrapperGenerator.h" />
</span><span class="cx"> <ClInclude Include="..\jit\RegisterSet.h" />
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -281,8 +281,13 @@
</span><span class="cx">                 0F3B3A281544C997003ED0FF /* DFGCFGSimplificationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B3A251544C991003ED0FF /* DFGCFGSimplificationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F3B3A2B15475000003ED0FF /* DFGValidate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3B3A2915474FF4003ED0FF /* DFGValidate.cpp */; };
</span><span class="cx">                 0F3B3A2C15475002003ED0FF /* DFGValidate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B3A2A15474FF4003ED0FF /* DFGValidate.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F3B7E2619A11B8000D9BC56 /* CallEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B7E2019A11B8000D9BC56 /* CallEdge.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F3B7E2719A11B8000D9BC56 /* CallEdgeProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3B7E2119A11B8000D9BC56 /* CallEdgeProfile.cpp */; };
+                0F3B7E2819A11B8000D9BC56 /* CallEdgeProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B7E2219A11B8000D9BC56 /* CallEdgeProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F3B7E2919A11B8000D9BC56 /* CallEdgeProfileInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B7E2319A11B8000D9BC56 /* CallEdgeProfileInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F3B7E2A19A11B8000D9BC56 /* CallVariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3B7E2419A11B8000D9BC56 /* CallVariant.cpp */; };
</span><span class="cx">                 0F3B7E2B19A11B8000D9BC56 /* CallVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B7E2519A11B8000D9BC56 /* CallVariant.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F3B7E2D19A12AAE00D9BC56 /* CallEdge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3B7E2C19A12AAE00D9BC56 /* CallEdge.cpp */; };
</ins><span class="cx">                 0F3D0BBC194A414300FC9CF9 /* ConstantStructureCheck.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3D0BBA194A414300FC9CF9 /* ConstantStructureCheck.cpp */; };
</span><span class="cx">                 0F3D0BBD194A414300FC9CF9 /* ConstantStructureCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3D0BBB194A414300FC9CF9 /* ConstantStructureCheck.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F3E01AA19D353A500F61B7F /* DFGPrePostNumbering.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3E01A819D353A500F61B7F /* DFGPrePostNumbering.cpp */; };
</span><span class="lines">@@ -350,8 +355,6 @@
</span><span class="cx">                 0F63948515E4811B006A597C /* DFGArrayMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F63948215E48114006A597C /* DFGArrayMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F64B2711A784BAF006E4E66 /* BinarySwitch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F64B26F1A784BAF006E4E66 /* BinarySwitch.cpp */; };
</span><span class="cx">                 0F64B2721A784BAF006E4E66 /* BinarySwitch.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F64B2701A784BAF006E4E66 /* BinarySwitch.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><del>-                0F64B2791A7957B2006E4E66 /* CallEdge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F64B2771A7957B2006E4E66 /* CallEdge.cpp */; };
-                0F64B27A1A7957B2006E4E66 /* CallEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F64B2781A7957B2006E4E66 /* CallEdge.h */; settings = {ATTRIBUTES = (Private, ); }; };
</del><span class="cx">                 0F666EC0183566F900D017F1 /* BytecodeLivenessAnalysisInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F666EBE183566F900D017F1 /* BytecodeLivenessAnalysisInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F666EC1183566F900D017F1 /* FullBytecodeLiveness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F666EBF183566F900D017F1 /* FullBytecodeLiveness.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F666EC61835672B00D017F1 /* DFGAvailability.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F666EC21835672B00D017F1 /* DFGAvailability.cpp */; };
</span><span class="lines">@@ -383,6 +386,8 @@
</span><span class="cx">                 0F7025AA1714B0FC00382C0E /* DFGOSRExitCompilerCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7025A81714B0F800382C0E /* DFGOSRExitCompilerCommon.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F714CA416EA92F000F3EBEB /* DFGBackwardsPropagationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F714CA116EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.cpp */; };
</span><span class="cx">                 0F714CA516EA92F200F3EBEB /* DFGBackwardsPropagationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F714CA216EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F73D7AE165A142D00ACAB71 /* ClosureCallStubRoutine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F73D7AB165A142A00ACAB71 /* ClosureCallStubRoutine.cpp */; };
+                0F73D7AF165A143000ACAB71 /* ClosureCallStubRoutine.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F73D7AC165A142A00ACAB71 /* ClosureCallStubRoutine.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F743BAA16B88249009F9277 /* ARM64Disassembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 652A3A201651C66100A80AFE /* ARM64Disassembler.cpp */; };
</span><span class="cx">                 0F7576D218E1FEE9002EF4CD /* AccessorCallJITStubRoutine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7576D018E1FEE9002EF4CD /* AccessorCallJITStubRoutine.cpp */; };
</span><span class="cx">                 0F7576D318E1FEE9002EF4CD /* AccessorCallJITStubRoutine.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7576D118E1FEE9002EF4CD /* AccessorCallJITStubRoutine.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -597,8 +602,6 @@
</span><span class="cx">                 0FE228EE1436AB2C00196C48 /* Options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE228EA1436AB2300196C48 /* Options.cpp */; };
</span><span class="cx">                 0FE7211D193B9C590031F6ED /* DFGTransition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE7211B193B9C590031F6ED /* DFGTransition.cpp */; };
</span><span class="cx">                 0FE7211E193B9C590031F6ED /* DFGTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE7211C193B9C590031F6ED /* DFGTransition.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><del>-                0FE834171A6EF97B00D04847 /* PolymorphicCallStubRoutine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE834151A6EF97B00D04847 /* PolymorphicCallStubRoutine.cpp */; };
-                0FE834181A6EF97B00D04847 /* PolymorphicCallStubRoutine.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE834161A6EF97B00D04847 /* PolymorphicCallStubRoutine.h */; settings = {ATTRIBUTES = (Private, ); }; };
</del><span class="cx">                 0FE8534B1723CDA500B618F5 /* DFGDesiredWatchpoints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */; };
</span><span class="cx">                 0FE8534C1723CDA500B618F5 /* DFGDesiredWatchpoints.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE8534A1723CDA500B618F5 /* DFGDesiredWatchpoints.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FE95F7918B5694700B531FB /* FTLDataSection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE95F7718B5694700B531FB /* FTLDataSection.cpp */; };
</span><span class="lines">@@ -1947,8 +1950,13 @@
</span><span class="cx">                 0F3B3A251544C991003ED0FF /* DFGCFGSimplificationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCFGSimplificationPhase.h; path = dfg/DFGCFGSimplificationPhase.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F3B3A2915474FF4003ED0FF /* DFGValidate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGValidate.cpp; path = dfg/DFGValidate.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0F3B3A2A15474FF4003ED0FF /* DFGValidate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGValidate.h; path = dfg/DFGValidate.h; sourceTree = "<group>"; };
</span><ins>+                0F3B7E2019A11B8000D9BC56 /* CallEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallEdge.h; sourceTree = "<group>"; };
+                0F3B7E2119A11B8000D9BC56 /* CallEdgeProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallEdgeProfile.cpp; sourceTree = "<group>"; };
+                0F3B7E2219A11B8000D9BC56 /* CallEdgeProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallEdgeProfile.h; sourceTree = "<group>"; };
+                0F3B7E2319A11B8000D9BC56 /* CallEdgeProfileInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallEdgeProfileInlines.h; sourceTree = "<group>"; };
</ins><span class="cx">                 0F3B7E2419A11B8000D9BC56 /* CallVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallVariant.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0F3B7E2519A11B8000D9BC56 /* CallVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallVariant.h; sourceTree = "<group>"; };
</span><ins>+                0F3B7E2C19A12AAE00D9BC56 /* CallEdge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallEdge.cpp; sourceTree = "<group>"; };
</ins><span class="cx">                 0F3D0BBA194A414300FC9CF9 /* ConstantStructureCheck.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConstantStructureCheck.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0F3D0BBB194A414300FC9CF9 /* ConstantStructureCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantStructureCheck.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F3E01A819D353A500F61B7F /* DFGPrePostNumbering.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGPrePostNumbering.cpp; path = dfg/DFGPrePostNumbering.cpp; sourceTree = "<group>"; };
</span><span class="lines">@@ -2017,8 +2025,6 @@
</span><span class="cx">                 0F63948215E48114006A597C /* DFGArrayMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayMode.h; path = dfg/DFGArrayMode.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F64B26F1A784BAF006E4E66 /* BinarySwitch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BinarySwitch.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0F64B2701A784BAF006E4E66 /* BinarySwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BinarySwitch.h; sourceTree = "<group>"; };
</span><del>-                0F64B2771A7957B2006E4E66 /* CallEdge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallEdge.cpp; sourceTree = "<group>"; };
-                0F64B2781A7957B2006E4E66 /* CallEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallEdge.h; sourceTree = "<group>"; };
</del><span class="cx">                 0F666EBE183566F900D017F1 /* BytecodeLivenessAnalysisInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeLivenessAnalysisInlines.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F666EBF183566F900D017F1 /* FullBytecodeLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FullBytecodeLiveness.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F666EC21835672B00D017F1 /* DFGAvailability.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAvailability.cpp; path = dfg/DFGAvailability.cpp; sourceTree = "<group>"; };
</span><span class="lines">@@ -2050,6 +2056,8 @@
</span><span class="cx">                 0F7025A81714B0F800382C0E /* DFGOSRExitCompilerCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSRExitCompilerCommon.h; path = dfg/DFGOSRExitCompilerCommon.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F714CA116EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGBackwardsPropagationPhase.cpp; path = dfg/DFGBackwardsPropagationPhase.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0F714CA216EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBackwardsPropagationPhase.h; path = dfg/DFGBackwardsPropagationPhase.h; sourceTree = "<group>"; };
</span><ins>+                0F73D7AB165A142A00ACAB71 /* ClosureCallStubRoutine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClosureCallStubRoutine.cpp; sourceTree = "<group>"; };
+                0F73D7AC165A142A00ACAB71 /* ClosureCallStubRoutine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClosureCallStubRoutine.h; sourceTree = "<group>"; };
</ins><span class="cx">                 0F7576D018E1FEE9002EF4CD /* AccessorCallJITStubRoutine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AccessorCallJITStubRoutine.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0F7576D118E1FEE9002EF4CD /* AccessorCallJITStubRoutine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessorCallJITStubRoutine.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F766D1C15A5028D008F363E /* JITStubRoutine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITStubRoutine.h; sourceTree = "<group>"; };
</span><span class="lines">@@ -2276,8 +2284,6 @@
</span><span class="cx">                 0FE228EB1436AB2300196C48 /* Options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Options.h; sourceTree = "<group>"; };
</span><span class="cx">                 0FE7211B193B9C590031F6ED /* DFGTransition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGTransition.cpp; path = dfg/DFGTransition.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0FE7211C193B9C590031F6ED /* DFGTransition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGTransition.h; path = dfg/DFGTransition.h; sourceTree = "<group>"; };
</span><del>-                0FE834151A6EF97B00D04847 /* PolymorphicCallStubRoutine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolymorphicCallStubRoutine.cpp; sourceTree = "<group>"; };
-                0FE834161A6EF97B00D04847 /* PolymorphicCallStubRoutine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolymorphicCallStubRoutine.h; sourceTree = "<group>"; };
</del><span class="cx">                 0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDesiredWatchpoints.cpp; path = dfg/DFGDesiredWatchpoints.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0FE8534A1723CDA500B618F5 /* DFGDesiredWatchpoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDesiredWatchpoints.h; path = dfg/DFGDesiredWatchpoints.h; sourceTree = "<group>"; };
</span><span class="cx">                 0FE95F7718B5694700B531FB /* FTLDataSection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLDataSection.cpp; path = ftl/FTLDataSection.cpp; sourceTree = "<group>"; };
</span><span class="lines">@@ -3741,6 +3747,8 @@
</span><span class="cx">                                 0F64B26F1A784BAF006E4E66 /* BinarySwitch.cpp */,
</span><span class="cx">                                 0F64B2701A784BAF006E4E66 /* BinarySwitch.h */,
</span><span class="cx">                                 0F24E53D17EA9F5900ABB217 /* CCallHelpers.h */,
</span><ins>+                                0F73D7AB165A142A00ACAB71 /* ClosureCallStubRoutine.cpp */,
+                                0F73D7AC165A142A00ACAB71 /* ClosureCallStubRoutine.h */,
</ins><span class="cx">                                 0FD82E37141AB14200179C94 /* CompactJITCodeMap.h */,
</span><span class="cx">                                 A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */,
</span><span class="cx">                                 A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */,
</span><span class="lines">@@ -3788,8 +3796,6 @@
</span><span class="cx">                                 0FC712E117CD878F008CC93C /* JITToDFGDeferredCompilationCallback.h */,
</span><span class="cx">                                 A76F54A213B28AAB00EF2BCE /* JITWriteBarrier.h */,
</span><span class="cx">                                 A76C51741182748D00715B05 /* JSInterfaceJIT.h */,
</span><del>-                                0FE834151A6EF97B00D04847 /* PolymorphicCallStubRoutine.cpp */,
-                                0FE834161A6EF97B00D04847 /* PolymorphicCallStubRoutine.h */,
</del><span class="cx">                                 0FA7A8E918B413C80052371D /* Reg.cpp */,
</span><span class="cx">                                 0FA7A8EA18B413C80052371D /* Reg.h */,
</span><span class="cx">                                 0F6B1CBB1861246A00845D97 /* RegisterPreservationWrapperGenerator.cpp */,
</span><span class="lines">@@ -5021,8 +5027,11 @@
</span><span class="cx">                                 0F666EBE183566F900D017F1 /* BytecodeLivenessAnalysisInlines.h */,
</span><span class="cx">                                 0F885E101849A3BE00F1E3FA /* BytecodeUseDef.h */,
</span><span class="cx">                                 0F8023E91613832300A0BA45 /* ByValInfo.h */,
</span><del>-                                0F64B2771A7957B2006E4E66 /* CallEdge.cpp */,
-                                0F64B2781A7957B2006E4E66 /* CallEdge.h */,
</del><ins>+                                0F3B7E2C19A12AAE00D9BC56 /* CallEdge.cpp */,
+                                0F3B7E2019A11B8000D9BC56 /* CallEdge.h */,
+                                0F3B7E2119A11B8000D9BC56 /* CallEdgeProfile.cpp */,
+                                0F3B7E2219A11B8000D9BC56 /* CallEdgeProfile.h */,
+                                0F3B7E2319A11B8000D9BC56 /* CallEdgeProfileInlines.h */,
</ins><span class="cx">                                 0F0B83AE14BCF71400885B4F /* CallLinkInfo.cpp */,
</span><span class="cx">                                 0F0B83AF14BCF71400885B4F /* CallLinkInfo.h */,
</span><span class="cx">                                 0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */,
</span><span class="lines">@@ -5474,6 +5483,7 @@
</span><span class="cx">                                 0F69CC89193AC60A0045759E /* DFGFrozenValue.h in Headers */,
</span><span class="cx">                                 0F24E54217EA9F5900ABB217 /* CCallHelpers.h in Headers */,
</span><span class="cx">                                 BC6AAAE50E1F426500AD87D8 /* ClassInfo.h in Headers */,
</span><ins>+                                0F73D7AF165A143000ACAB71 /* ClosureCallStubRoutine.h in Headers */,
</ins><span class="cx">                                 969A07970ED1D3AE00F1F681 /* CodeBlock.h in Headers */,
</span><span class="cx">                                 0F8F94411667633200D61971 /* CodeBlockHash.h in Headers */,
</span><span class="cx">                                 0FC97F34182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h in Headers */,
</span><span class="lines">@@ -5517,7 +5527,6 @@
</span><span class="cx">                                 BCD2034A0E17135E002C7E82 /* DateConstructor.h in Headers */,
</span><span class="cx">                                 41359CF30FDD89AD00206180 /* DateConversion.h in Headers */,
</span><span class="cx">                                 BC1166020E1997B4008066DD /* DateInstance.h in Headers */,
</span><del>-                                0F64B27A1A7957B2006E4E66 /* CallEdge.h in Headers */,
</del><span class="cx">                                 14A1563210966365006FA260 /* DateInstanceCache.h in Headers */,
</span><span class="cx">                                 BCD2034C0E17135E002C7E82 /* DatePrototype.h in Headers */,
</span><span class="cx">                                 BCD203E80E1718F4002C7E82 /* DatePrototype.lut.h in Headers */,
</span><span class="lines">@@ -5565,6 +5574,7 @@
</span><span class="cx">                                 0FFFC95A14EF90A900C72532 /* DFGCSEPhase.h in Headers */,
</span><span class="cx">                                 0F2FC77316E12F740038D976 /* DFGDCEPhase.h in Headers */,
</span><span class="cx">                                 0F8F2B9A172F0501007DBDA5 /* DFGDesiredIdentifiers.h in Headers */,
</span><ins>+                                0F3B7E2819A11B8000D9BC56 /* CallEdgeProfile.h in Headers */,
</ins><span class="cx">                                 C2C0F7CE17BBFC5B00464FE4 /* DFGDesiredTransitions.h in Headers */,
</span><span class="cx">                                 0FE8534C1723CDA500B618F5 /* DFGDesiredWatchpoints.h in Headers */,
</span><span class="cx">                                 C2981FD917BAEE4B00A3BC98 /* DFGDesiredWeakReferences.h in Headers */,
</span><span class="lines">@@ -5855,6 +5865,7 @@
</span><span class="cx">                                 A76F54A313B28AAB00EF2BCE /* JITWriteBarrier.h in Headers */,
</span><span class="cx">                                 BC18C4160E16F5CD00B34460 /* JSLexicalEnvironment.h in Headers */,
</span><span class="cx">                                 840480131021A1D9008E7F01 /* JSAPIValueWrapper.h in Headers */,
</span><ins>+                                0F3B7E2919A11B8000D9BC56 /* CallEdgeProfileInlines.h in Headers */,
</ins><span class="cx">                                 C2CF39C216E15A8100DD69BE /* JSAPIWrapperObject.h in Headers */,
</span><span class="cx">                                 A76140D2182982CB00750624 /* JSArgumentsIterator.h in Headers */,
</span><span class="cx">                                 BC18C4170E16F5CD00B34460 /* JSArray.h in Headers */,
</span><span class="lines">@@ -6178,6 +6189,7 @@
</span><span class="cx">                                 E49DC16C12EF294E00184A1F /* SourceProviderCache.h in Headers */,
</span><span class="cx">                                 E49DC16D12EF295300184A1F /* SourceProviderCacheItem.h in Headers */,
</span><span class="cx">                                 0FB7F39E15ED8E4600F167B2 /* SparseArrayValueMap.h in Headers */,
</span><ins>+                                0F3B7E2619A11B8000D9BC56 /* CallEdge.h in Headers */,
</ins><span class="cx">                                 A7386554118697B400540279 /* SpecializedThunkJIT.h in Headers */,
</span><span class="cx">                                 0F5541B21613C1FB00CE3E25 /* SpecialPointer.h in Headers */,
</span><span class="cx">                                 0FD82E54141DAEEE00179C94 /* SpeculatedType.h in Headers */,
</span><span class="lines">@@ -6224,7 +6236,6 @@
</span><span class="cx">                                 0FF42749158EBE91004CB9FF /* udis86_types.h in Headers */,
</span><span class="cx">                                 A7E5AB391799E4B200D2833D /* UDis86Disassembler.h in Headers */,
</span><span class="cx">                                 A7A8AF4117ADB5F3005AB174 /* Uint16Array.h in Headers */,
</span><del>-                                0FE834181A6EF97B00D04847 /* PolymorphicCallStubRoutine.h in Headers */,
</del><span class="cx">                                 866739D313BFDE710023D87C /* Uint16WithFraction.h in Headers */,
</span><span class="cx">                                 A7A8AF4217ADB5F3005AB174 /* Uint32Array.h in Headers */,
</span><span class="cx">                                 A7A8AF3F17ADB5F3005AB174 /* Uint8Array.h in Headers */,
</span><span class="lines">@@ -6763,6 +6774,7 @@
</span><span class="cx">                                 0F0B83B014BCF71600885B4F /* CallLinkInfo.cpp in Sources */,
</span><span class="cx">                                 0F93329D14CA7DC30085F3C6 /* CallLinkStatus.cpp in Sources */,
</span><span class="cx">                                 0F2B9CE419D0BA7D00B1D1B5 /* DFGInsertOSRHintsForUpdate.cpp in Sources */,
</span><ins>+                                0F73D7AE165A142D00ACAB71 /* ClosureCallStubRoutine.cpp in Sources */,
</ins><span class="cx">                                 969A07960ED1D3AE00F1F681 /* CodeBlock.cpp in Sources */,
</span><span class="cx">                                 0F8F94401667633000D61971 /* CodeBlockHash.cpp in Sources */,
</span><span class="cx">                                 0FC97F33182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp in Sources */,
</span><span class="lines">@@ -6777,7 +6789,6 @@
</span><span class="cx">                                 0F9C5E5E18E35F5E00D431C3 /* FTLDWARFRegister.cpp in Sources */,
</span><span class="cx">                                 A709F2F217A0AC2A00512E98 /* CommonSlowPaths.cpp in Sources */,
</span><span class="cx">                                 6553A33117A1F1EE008CF6F3 /* CommonSlowPathsExceptions.cpp in Sources */,
</span><del>-                                0F64B2791A7957B2006E4E66 /* CallEdge.cpp in Sources */,
</del><span class="cx">                                 A7E5A3A71797432D00E893C0 /* CompilationResult.cpp in Sources */,
</span><span class="cx">                                 147F39C2107EC37600427A48 /* Completion.cpp in Sources */,
</span><span class="cx">                                 146B16D812EB5B59001BEC1B /* ConservativeRoots.cpp in Sources */,
</span><span class="lines">@@ -6949,8 +6960,8 @@
</span><span class="cx">                                 0F235BD517178E1C00690C7F /* FTLExitArgumentForOperand.cpp in Sources */,
</span><span class="cx">                                 0F235BD817178E1C00690C7F /* FTLExitThunkGenerator.cpp in Sources */,
</span><span class="cx">                                 0F235BDA17178E1C00690C7F /* FTLExitValue.cpp in Sources */,
</span><ins>+                                0F3B7E2719A11B8000D9BC56 /* CallEdgeProfile.cpp in Sources */,
</ins><span class="cx">                                 A7F2996B17A0BB670010417A /* FTLFail.cpp in Sources */,
</span><del>-                                0FE834171A6EF97B00D04847 /* PolymorphicCallStubRoutine.cpp in Sources */,
</del><span class="cx">                                 0FD8A31917D51F2200CA2C40 /* FTLForOSREntryJITCode.cpp in Sources */,
</span><span class="cx">                                 0F25F1AF181635F300522F39 /* FTLInlineCacheSize.cpp in Sources */,
</span><span class="cx">                                 0FEA0A281709623B00BB722C /* FTLIntrinsicRepository.cpp in Sources */,
</span><span class="lines">@@ -7142,6 +7153,7 @@
</span><span class="cx">                                 0F4680D214BBD16500BFE272 /* LLIntData.cpp in Sources */,
</span><span class="cx">                                 0F38B01117CF078000B144D3 /* LLIntEntrypoint.cpp in Sources */,
</span><span class="cx">                                 0F4680A814BA7FAB00BFE272 /* LLIntExceptions.cpp in Sources */,
</span><ins>+                                0F3B7E2D19A12AAE00D9BC56 /* CallEdge.cpp in Sources */,
</ins><span class="cx">                                 0F4680A414BA7F8D00BFE272 /* LLIntSlowPaths.cpp in Sources */,
</span><span class="cx">                                 0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */,
</span><span class="cx">                                 0FCEFACD1805E75500472CE4 /* LLVMAPI.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallEdgeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallEdge.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallEdge.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/bytecode/CallEdge.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014 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">@@ -30,15 +30,17 @@
</span><span class="cx">
</span><span class="cx"> namespace JSC {
</span><span class="cx">
</span><ins>+typedef uint16_t CallEdgeCountType;
+
</ins><span class="cx"> class CallEdge {
</span><span class="cx"> public:
</span><span class="cx"> CallEdge();
</span><del>- CallEdge(CallVariant, uint32_t);
</del><ins>+ CallEdge(CallVariant, CallEdgeCountType);
</ins><span class="cx">
</span><span class="cx"> bool operator!() const { return !m_callee; }
</span><span class="cx">
</span><span class="cx"> CallVariant callee() const { return m_callee; }
</span><del>- uint32_t count() const { return m_count; }
</del><ins>+ CallEdgeCountType count() const { return m_count; }
</ins><span class="cx">
</span><span class="cx"> CallEdge despecifiedClosure() const
</span><span class="cx"> {
</span><span class="lines">@@ -47,12 +49,12 @@
</span><span class="cx">
</span><span class="cx"> void dump(PrintStream&) const;
</span><span class="cx">
</span><del>-private:
</del><ins>+public:
</ins><span class="cx"> CallVariant m_callee;
</span><del>- uint32_t m_count;
</del><ins>+ CallEdgeCountType m_count;
</ins><span class="cx"> };
</span><span class="cx">
</span><del>-inline CallEdge::CallEdge(CallVariant callee, uint32_t count)
</del><ins>+inline CallEdge::CallEdge(CallVariant callee, CallEdgeCountType count)
</ins><span class="cx"> : m_callee(callee)
</span><span class="cx"> , m_count(count)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallEdgeProfilecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/CallEdgeProfile.cpp (0 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallEdgeProfile.cpp         (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/CallEdgeProfile.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -0,0 +1,360 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CallEdgeProfile.h"
+
+#include "CCallHelpers.h"
+#include "CallEdgeProfileInlines.h"
+#include "JITOperations.h"
+#include "JSCInlines.h"
+
+namespace JSC {
+
+CallEdgeList CallEdgeProfile::callEdges() const
+{
+ ConcurrentJITLocker locker(m_lock);
+
+ CallEdgeList result;
+
+ CallVariant primaryCallee = m_primaryCallee;
+ CallEdgeCountType numCallsToPrimary = m_numCallsToPrimary;
+ // Defend against races. These fields are modified by the log processor without locking.
+ if (!!primaryCallee && numCallsToPrimary)
+ result.append(CallEdge(primaryCallee, numCallsToPrimary));
+
+ if (m_otherCallees) {
+ // Make sure that if the primary thread had just created a m_otherCalles while log
+ // processing, we see a consistently created one. The lock being held is insufficient for
+ // this, since the log processor will only grab the lock when merging the secondary
+ // spectrum into the primary one but may still create the data structure without holding
+ // locks.
+ WTF::loadLoadFence();
+ for (CallEdge& entry : m_otherCallees->m_processed) {
+ // Defend against the possibility that the primary duplicates an entry in the secondary
+ // spectrum. That can happen when the GC removes the primary. We could have the GC fix
+ // the situation by changing the primary to be something from the secondary spectrum,
+ // but this fix seems simpler to implement and also cheaper.
+ if (entry.callee() == result[0].callee()) {
+ result[0] = CallEdge(result[0].callee(), entry.count() + result[0].count());
+ continue;
+ }
+
+ result.append(entry);
+ }
+ }
+
+ std::sort(result.begin(), result.end(), [] (const CallEdge& a, const CallEdge& b) -> bool {
+ return a.count() > b.count();
+ });
+
+ if (result.size() >= 2)
+ ASSERT(result[0].count() >= result.last().count());
+
+ return result;
+}
+
+CallEdgeCountType CallEdgeProfile::numCallsToKnownCells() const
+{
+ CallEdgeCountType result = 0;
+ for (CallEdge& edge : callEdges())
+ result += edge.count();
+ return result;
+}
+
+static bool worthDespecifying(const CallVariant& variant)
+{
+ return !Heap::isMarked(variant.rawCalleeCell())
+ && Heap::isMarked(variant.despecifiedClosure().rawCalleeCell());
+}
+
+bool CallEdgeProfile::worthDespecifying()
+{
+ if (m_closuresAreDespecified)
+ return false;
+
+ bool didSeeEntry = false;
+
+ if (!!m_primaryCallee) {
+ didSeeEntry = true;
+ if (!JSC::worthDespecifying(m_primaryCallee))
+ return false;
+ }
+
+ if (m_otherCallees) {
+ for (unsigned i = m_otherCallees->m_processed.size(); i--;) {
+ didSeeEntry = true;
+ if (!JSC::worthDespecifying(m_otherCallees->m_processed[i].callee()))
+ return false;
+ }
+ }
+
+ return didSeeEntry;
+}
+
+void CallEdgeProfile::visitWeak()
+{
+ if (!m_primaryCallee && !m_otherCallees)
+ return;
+
+ ConcurrentJITLocker locker(m_lock);
+
+ // See if anything is dead and if that can be rectified by despecifying.
+ if (worthDespecifying()) {
+ CallSpectrum newSpectrum;
+
+ if (!!m_primaryCallee)
+ newSpectrum.add(m_primaryCallee.despecifiedClosure(), m_numCallsToPrimary);
+
+ if (m_otherCallees) {
+ for (unsigned i = m_otherCallees->m_processed.size(); i--;) {
+ newSpectrum.add(
+ m_otherCallees->m_processed[i].callee().despecifiedClosure(),
+ m_otherCallees->m_processed[i].count());
+ }
+ }
+
+ Vector<CallSpectrum::KeyAndCount> list = newSpectrum.buildList();
+ RELEASE_ASSERT(list.size());
+ m_primaryCallee = list.last().key;
+ m_numCallsToPrimary = list.last().count;
+
+ if (m_otherCallees) {
+ m_otherCallees->m_processed.clear();
+
+ // We could have a situation where the GC clears the primary and then log processing
+ // reinstates it without ever doing an addSlow and subsequent mergeBack. In such a case
+ // the primary could duplicate an entry in otherCallees, which means that even though we
+ // had an otherCallees object, the list size is just 1.
+ if (list.size() >= 2) {
+ for (unsigned i = list.size() - 1; i--;)
+ m_otherCallees->m_processed.append(CallEdge(list[i].key, list[i].count));
+ }
+ }
+
+ m_closuresAreDespecified = true;
+
+ return;
+ }
+
+ if (!!m_primaryCallee && !Heap::isMarked(m_primaryCallee.rawCalleeCell())) {
+ m_numCallsToUnknownCell += m_numCallsToPrimary;
+
+ m_primaryCallee = CallVariant();
+ m_numCallsToPrimary = 0;
+ }
+
+ if (m_otherCallees) {
+ for (unsigned i = 0; i < m_otherCallees->m_processed.size(); i++) {
+ if (Heap::isMarked(m_otherCallees->m_processed[i].callee().rawCalleeCell()))
+ continue;
+
+ m_numCallsToUnknownCell += m_otherCallees->m_processed[i].count();
+ m_otherCallees->m_processed[i--] = m_otherCallees->m_processed.last();
+ m_otherCallees->m_processed.removeLast();
+ }
+
+ // Only exists while we are processing the log.
+ RELEASE_ASSERT(!m_otherCallees->m_temporarySpectrum);
+ }
+}
+
+void CallEdgeProfile::addSlow(CallVariant callee, CallEdgeProfileVector& mergeBackLog)
+{
+ // This exists to handle cases where the spectrum wasn't created yet, or we're storing to a
+ // particular spectrum for the first time during a log processing iteration.
+
+ if (!m_otherCallees) {
+ m_otherCallees = std::make_unique<Secondary>();
+ // If a compiler thread notices the m_otherCallees being non-null, we want to make sure
+ // that it sees a fully created one.
+ WTF::storeStoreFence();
+ }
+
+ if (!m_otherCallees->m_temporarySpectrum) {
+ m_otherCallees->m_temporarySpectrum = std::make_unique<CallSpectrum>();
+ for (unsigned i = m_otherCallees->m_processed.size(); i--;) {
+ m_otherCallees->m_temporarySpectrum->add(
+ m_otherCallees->m_processed[i].callee(),
+ m_otherCallees->m_processed[i].count());
+ }
+
+ // This means that this is the first time we're seeing this profile during this log
+ // processing iteration.
+ mergeBackLog.append(this);
+ }
+
+ m_otherCallees->m_temporarySpectrum->add(callee);
+}
+
+void CallEdgeProfile::mergeBack()
+{
+ ConcurrentJITLocker locker(m_lock);
+
+ RELEASE_ASSERT(m_otherCallees);
+ RELEASE_ASSERT(m_otherCallees->m_temporarySpectrum);
+
+ if (!!m_primaryCallee)
+ m_otherCallees->m_temporarySpectrum->add(m_primaryCallee, m_numCallsToPrimary);
+
+ if (!m_closuresAreDespecified) {
+ CallSpectrum newSpectrum;
+ for (auto& entry : *m_otherCallees->m_temporarySpectrum)
+ newSpectrum.add(entry.key.despecifiedClosure(), entry.value);
+
+ if (newSpectrum.size() < m_otherCallees->m_temporarySpectrum->size()) {
+ *m_otherCallees->m_temporarySpectrum = newSpectrum;
+ m_closuresAreDespecified = true;
+ }
+ }
+
+ Vector<CallSpectrum::KeyAndCount> list = m_otherCallees->m_temporarySpectrum->buildList();
+ m_otherCallees->m_temporarySpectrum = nullptr;
+
+ m_primaryCallee = list.last().key;
+ m_numCallsToPrimary = list.last().count;
+ list.removeLast();
+
+ m_otherCallees->m_processed.clear();
+ for (unsigned count = maxKnownCallees; count-- && !list.isEmpty();) {
+ m_otherCallees->m_processed.append(CallEdge(list.last().key, list.last().count));
+ list.removeLast();
+ }
+
+ for (unsigned i = list.size(); i--;)
+ m_numCallsToUnknownCell += list[i].count;
+}
+
+void CallEdgeProfile::fadeByHalf()
+{
+ m_numCallsToPrimary >>= 1;
+ m_numCallsToNotCell >>= 1;
+ m_numCallsToUnknownCell >>= 1;
+ m_totalCount >>= 1;
+
+ if (m_otherCallees) {
+ for (unsigned i = m_otherCallees->m_processed.size(); i--;) {
+ m_otherCallees->m_processed[i] = CallEdge(
+ m_otherCallees->m_processed[i].callee(),
+ m_otherCallees->m_processed[i].count() >> 1);
+ }
+
+ if (m_otherCallees->m_temporarySpectrum) {
+ for (auto& entry : *m_otherCallees->m_temporarySpectrum)
+ entry.value >>= 1;
+ }
+ }
+}
+
+CallEdgeLog::CallEdgeLog()
+ : m_scaledLogIndex(logSize * sizeof(Entry))
+{
+ ASSERT(!(m_scaledLogIndex % sizeof(Entry)));
+}
+
+CallEdgeLog::~CallEdgeLog() { }
+
+bool CallEdgeLog::isEnabled()
+{
+ return Options::enableCallEdgeProfiling() && Options::useFTLJIT();
+}
+
+#if ENABLE(JIT)
+
+extern "C" JIT_OPERATION void operationProcessCallEdgeLog(CallEdgeLog*) WTF_INTERNAL;
+extern "C" JIT_OPERATION void operationProcessCallEdgeLog(CallEdgeLog* log)
+{
+ log->processLog();
+}
+
+void CallEdgeLog::emitLogCode(CCallHelpers& jit, CallEdgeProfile& profile, JSValueRegs calleeRegs)
+{
+ const unsigned numberOfArguments = 1;
+
+ GPRReg scratchGPR;
+ if (!calleeRegs.uses(GPRInfo::regT0))
+ scratchGPR = GPRInfo::regT0;
+ else if (!calleeRegs.uses(GPRInfo::regT1))
+ scratchGPR = GPRInfo::regT1;
+ else
+ scratchGPR = GPRInfo::regT2;
+
+ jit.load32(&m_scaledLogIndex, scratchGPR);
+
+ CCallHelpers::Jump ok = jit.branchTest32(CCallHelpers::NonZero, scratchGPR);
+
+ ASSERT_UNUSED(numberOfArguments, stackAlignmentRegisters() >= 1 + numberOfArguments);
+
+ jit.subPtr(CCallHelpers::TrustedImm32(stackAlignmentBytes()), CCallHelpers::stackPointerRegister);
+
+ jit.storeValue(calleeRegs, CCallHelpers::Address(CCallHelpers::stackPointerRegister, sizeof(JSValue)));
+ jit.setupArguments(CCallHelpers::TrustedImmPtr(this));
+ jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast<void*>(operationProcessCallEdgeLog)), GPRInfo::nonArgGPR0);
+ jit.call(GPRInfo::nonArgGPR0);
+ jit.loadValue(CCallHelpers::Address(CCallHelpers::stackPointerRegister, sizeof(JSValue)), calleeRegs);
+
+ jit.addPtr(CCallHelpers::TrustedImm32(stackAlignmentBytes()), CCallHelpers::stackPointerRegister);
+
+ jit.move(CCallHelpers::TrustedImm32(logSize * sizeof(Entry)), scratchGPR);
+ ok.link(&jit);
+
+ jit.sub32(CCallHelpers::TrustedImm32(sizeof(Entry)), scratchGPR);
+ jit.store32(scratchGPR, &m_scaledLogIndex);
+ jit.addPtr(CCallHelpers::TrustedImmPtr(m_log), scratchGPR);
+ jit.storeValue(calleeRegs, CCallHelpers::Address(scratchGPR, OBJECT_OFFSETOF(Entry, m_value)));
+ jit.storePtr(CCallHelpers::TrustedImmPtr(&profile), CCallHelpers::Address(scratchGPR, OBJECT_OFFSETOF(Entry, m_profile)));
+}
+
+void CallEdgeLog::emitLogCode(
+ CCallHelpers& jit, OwnPtr<CallEdgeProfile>& profilePointer, JSValueRegs calleeRegs)
+{
+ if (!isEnabled())
+ return;
+
+ profilePointer.createTransactionally();
+ emitLogCode(jit, *profilePointer, calleeRegs);
+}
+
+#endif // ENABLE(JIT)
+
+void CallEdgeLog::processLog()
+{
+ ASSERT(!(m_scaledLogIndex % sizeof(Entry)));
+
+ if (Options::callEdgeProfileReallyProcessesLog()) {
+ CallEdgeProfileVector mergeBackLog;
+
+ for (unsigned i = m_scaledLogIndex / sizeof(Entry); i < logSize; ++i)
+ m_log[i].m_profile->add(m_log[i].m_value, mergeBackLog);
+
+ for (unsigned i = mergeBackLog.size(); i--;)
+ mergeBackLog[i]->mergeBack();
+ }
+
+ m_scaledLogIndex = logSize * sizeof(Entry);
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallEdgeProfileh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/CallEdgeProfile.h (0 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallEdgeProfile.h         (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/CallEdgeProfile.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -0,0 +1,131 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CallEdgeProfile_h
+#define CallEdgeProfile_h
+
+#include "CallEdge.h"
+#include "CallVariant.h"
+#include "ConcurrentJITLock.h"
+#include "GPRInfo.h"
+#include "JSCell.h"
+#include <wtf/OwnPtr.h>
+
+namespace JSC {
+
+class CCallHelpers;
+class LLIntOffsetsExtractor;
+
+class CallEdgeLog;
+class CallEdgeProfile;
+typedef Vector<CallEdgeProfile*, 10> CallEdgeProfileVector;
+
+class CallEdgeProfile {
+public:
+ CallEdgeProfile();
+
+ CallEdgeCountType numCallsToNotCell() const { return m_numCallsToNotCell; }
+ CallEdgeCountType numCallsToUnknownCell() const { return m_numCallsToUnknownCell; }
+ CallEdgeCountType numCallsToKnownCells() const;
+
+ CallEdgeCountType totalCalls() const { return m_totalCount; }
+
+ // Call while holding the owning CodeBlock's lock.
+ CallEdgeList callEdges() const;
+
+ void visitWeak();
+
+private:
+ friend class CallEdgeLog;
+
+ static const unsigned maxKnownCallees = 5;
+
+ void add(JSValue, CallEdgeProfileVector& mergeBackLog);
+
+ bool worthDespecifying();
+ void addSlow(CallVariant, CallEdgeProfileVector& mergeBackLog);
+ void mergeBack();
+ void fadeByHalf();
+
+ // It's cheaper to let this have its own lock. It needs to be able to find which lock to
+ // lock. Normally it would lock the owning CodeBlock's lock, but that would require a
+ // pointer-width word to point at the CodeBlock. Having the byte-sized lock here is
+ // cheaper. However, this means that the relationship with the CodeBlock lock is:
+ // acquire the CodeBlock lock before this one.
+ mutable ConcurrentJITLock m_lock;
+
+ bool m_closuresAreDespecified;
+
+ CallEdgeCountType m_numCallsToPrimary;
+ CallEdgeCountType m_numCallsToNotCell;
+ CallEdgeCountType m_numCallsToUnknownCell;
+ CallEdgeCountType m_totalCount;
+ CallVariant m_primaryCallee;
+
+ typedef Spectrum<CallVariant, CallEdgeCountType> CallSpectrum;
+
+ struct Secondary {
+ Vector<CallEdge> m_processed; // Processed but not necessarily sorted.
+ std::unique_ptr<CallSpectrum> m_temporarySpectrum;
+ };
+
+ std::unique_ptr<Secondary> m_otherCallees;
+};
+
+class CallEdgeLog {
+public:
+ CallEdgeLog();
+ ~CallEdgeLog();
+
+ static bool isEnabled();
+
+#if ENABLE(JIT)
+ void emitLogCode(CCallHelpers&, CallEdgeProfile&, JSValueRegs calleeRegs); // Assumes that stack is aligned, all volatile registers - other than calleeGPR - are clobberable, and the parameter space is in use.
+
+ // Same as above but creates a CallEdgeProfile instance if one did not already exist. Does
+ // this in a thread-safe manner by calling OwnPtr::createTransactionally.
+ void emitLogCode(CCallHelpers&, OwnPtr<CallEdgeProfile>&, JSValueRegs calleeRegs);
+#endif // ENABLE(JIT)
+
+ void processLog();
+
+private:
+ friend class LLIntOffsetsExtractor;
+
+ static const unsigned logSize = 10000;
+
+ struct Entry {
+ JSValue m_value;
+ CallEdgeProfile* m_profile;
+ };
+
+ unsigned m_scaledLogIndex;
+ Entry m_log[logSize];
+};
+
+} // namespace JSC
+
+#endif // CallEdgeProfile_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallEdgeProfileInlinesh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/CallEdgeProfileInlines.h (0 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallEdgeProfileInlines.h         (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/CallEdgeProfileInlines.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -0,0 +1,91 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CallEdgeProfileInlines_h
+#define CallEdgeProfileInlines_h
+
+#include "CallEdgeProfile.h"
+
+namespace JSC {
+
+inline CallEdgeProfile::CallEdgeProfile()
+ : m_closuresAreDespecified(false)
+ , m_numCallsToPrimary(0)
+ , m_numCallsToNotCell(0)
+ , m_numCallsToUnknownCell(0)
+ , m_totalCount(0)
+ , m_primaryCallee(nullptr)
+{
+}
+
+ALWAYS_INLINE void CallEdgeProfile::add(JSValue value, CallEdgeProfileVector& mergeBackLog)
+{
+ unsigned newTotalCount = m_totalCount + 1;
+ if (UNLIKELY(!newTotalCount)) {
+ fadeByHalf(); // Tackle overflows by dividing all counts by two.
+ newTotalCount = m_totalCount + 1;
+ }
+ ASSERT(newTotalCount);
+ m_totalCount = newTotalCount;
+
+ if (UNLIKELY(!value.isCell())) {
+ m_numCallsToNotCell++;
+ return;
+ }
+
+ CallVariant callee = CallVariant(value.asCell());
+
+ if (m_closuresAreDespecified)
+ callee = callee.despecifiedClosure();
+
+ if (UNLIKELY(!m_primaryCallee)) {
+ m_primaryCallee = callee;
+ m_numCallsToPrimary = 1;
+ return;
+ }
+
+ if (LIKELY(m_primaryCallee == callee)) {
+ m_numCallsToPrimary++;
+ return;
+ }
+
+ if (UNLIKELY(!m_otherCallees)) {
+ addSlow(callee, mergeBackLog);
+ return;
+ }
+
+ CallSpectrum* secondary = m_otherCallees->m_temporarySpectrum.get();
+ if (!secondary) {
+ addSlow(callee, mergeBackLog);
+ return;
+ }
+
+ secondary->add(callee);
+}
+
+} // namespace JSC
+
+#endif // CallEdgeProfileInlines_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkInfocpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -29,9 +29,7 @@
</span><span class="cx"> #include "DFGOperations.h"
</span><span class="cx"> #include "DFGThunks.h"
</span><span class="cx"> #include "JSCInlines.h"
</span><del>-#include "Repatch.h"
</del><span class="cx"> #include "RepatchBuffer.h"
</span><del>-#include <wtf/ListDump.h>
</del><span class="cx"> #include <wtf/NeverDestroyed.h>
</span><span class="cx">
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="lines">@@ -39,18 +37,21 @@
</span><span class="cx">
</span><span class="cx"> void CallLinkInfo::unlink(RepatchBuffer& repatchBuffer)
</span><span class="cx"> {
</span><del>- if (!isLinked()) {
- // We could be called even if we're not linked anymore because of how polymorphic calls
- // work. Each callsite within the polymorphic call stub may separately ask us to unlink().
- RELEASE_ASSERT(!isOnList());
- return;
- }
</del><ins>+ ASSERT(isLinked());
</ins><span class="cx">
</span><del>- unlinkFor(
- repatchBuffer, *this,
- (callType == Construct || callType == ConstructVarargs)? CodeForConstruct : CodeForCall,
- isFTL ? MustPreserveRegisters : RegisterPreservationNotRequired);
</del><ins>+ if (Options::showDisassembly())
+ dataLog("Unlinking call from ", callReturnLocation, " to ", pointerDump(repatchBuffer.codeBlock()), "\n");
</ins><span class="cx">
</span><ins>+ repatchBuffer.revertJumpReplacementToBranchPtrWithPatch(RepatchBuffer::startOfBranchPtrWithPatchOnRegister(hotPathBegin), static_cast<MacroAssembler::RegisterID>(calleeGPR), 0);
+ repatchBuffer.relink(
+ callReturnLocation,
+ repatchBuffer.codeBlock()->vm()->getCTIStub(linkThunkGeneratorFor(
+ (callType == Construct || callType == ConstructVarargs)? CodeForConstruct : CodeForCall,
+ isFTL ? MustPreserveRegisters : RegisterPreservationNotRequired)).code());
+ hasSeenShouldRepatch = false;
+ callee.clear();
+ stub.clear();
+
</ins><span class="cx"> // It will be on a list if the callee has a code block.
</span><span class="cx"> if (isOnList())
</span><span class="cx"> remove();
</span><span class="lines">@@ -60,12 +61,12 @@
</span><span class="cx"> {
</span><span class="cx"> if (isLinked()) {
</span><span class="cx"> if (stub) {
</span><del>- if (!stub->visitWeak(repatchBuffer)) {
</del><ins>+ if (!Heap::isMarked(stub->executable())) {
</ins><span class="cx"> if (Options::verboseOSR()) {
</span><span class="cx"> dataLog(
</span><span class="cx"> "Clearing closure call from ", *repatchBuffer.codeBlock(), " to ",
</span><del>- listDump(stub->variants()), ", stub routine ", RawPointer(stub.get()),
- ".\n");
</del><ins>+ stub->executable()->hashFor(specializationKind()),
+ ", stub routine ", RawPointer(stub.get()), ".\n");
</ins><span class="cx"> }
</span><span class="cx"> unlink(repatchBuffer);
</span><span class="cx"> }
</span><span class="lines">@@ -82,6 +83,11 @@
</span><span class="cx"> }
</span><span class="cx"> if (!!lastSeenCallee && !Heap::isMarked(lastSeenCallee.get()))
</span><span class="cx"> lastSeenCallee.clear();
</span><ins>+
+ if (callEdgeProfile) {
+ WTF::loadLoadFence();
+ callEdgeProfile->visitWeak();
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> CallLinkInfo& CallLinkInfo::dummy()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012, 2014, 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 2014 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,12 +26,13 @@
</span><span class="cx"> #ifndef CallLinkInfo_h
</span><span class="cx"> #define CallLinkInfo_h
</span><span class="cx">
</span><ins>+#include "CallEdgeProfile.h"
+#include "ClosureCallStubRoutine.h"
</ins><span class="cx"> #include "CodeLocation.h"
</span><span class="cx"> #include "CodeSpecializationKind.h"
</span><span class="cx"> #include "JITWriteBarrier.h"
</span><span class="cx"> #include "JSFunction.h"
</span><span class="cx"> #include "Opcode.h"
</span><del>-#include "PolymorphicCallStubRoutine.h"
</del><span class="cx"> #include "WriteBarrier.h"
</span><span class="cx"> #include <wtf/OwnPtr.h>
</span><span class="cx"> #include <wtf/SentinelLinkedList.h>
</span><span class="lines">@@ -81,14 +82,15 @@
</span><span class="cx"> CodeLocationNearCall hotPathOther;
</span><span class="cx"> JITWriteBarrier<JSFunction> callee;
</span><span class="cx"> WriteBarrier<JSFunction> lastSeenCallee;
</span><del>- RefPtr<PolymorphicCallStubRoutine> stub;
</del><ins>+ RefPtr<ClosureCallStubRoutine> stub;
</ins><span class="cx"> bool isFTL : 1;
</span><span class="cx"> bool hasSeenShouldRepatch : 1;
</span><span class="cx"> bool hasSeenClosure : 1;
</span><span class="cx"> unsigned callType : 5; // CallType
</span><span class="cx"> unsigned calleeGPR : 8;
</span><del>- uint32_t slowPathCount;
</del><ins>+ unsigned slowPathCount;
</ins><span class="cx"> CodeOrigin codeOrigin;
</span><ins>+ OwnPtr<CallEdgeProfile> callEdgeProfile;
</ins><span class="cx">
</span><span class="cx"> bool isLinked() { return stub || callee; }
</span><span class="cx"> void unlink(RepatchBuffer&);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkStatuscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 2013, 2014 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">@@ -47,7 +47,7 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- m_variants.append(CallVariant(value.asCell()));
</del><ins>+ m_edges.append(CallEdge(CallVariant(value.asCell()), 1));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> CallLinkStatus CallLinkStatus::computeFromLLInt(const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, unsigned bytecodeIndex)
</span><span class="lines">@@ -129,6 +129,23 @@
</span><span class="cx"> // We don't really need this, but anytime we have to debug this code, it becomes indispensable.
</span><span class="cx"> UNUSED_PARAM(profiledBlock);
</span><span class="cx">
</span><ins>+ if (Options::callStatusShouldUseCallEdgeProfile()) {
+ // Always trust the call edge profile over anything else since this has precise counts.
+ // It can make the best possible decision because it never "forgets" what happened for any
+ // call, with the exception of fading out the counts of old calls (for example if the
+ // counter type is 16-bit then calls that happened more than 2^16 calls ago are given half
+ // weight, and this compounds for every 2^15 [sic] calls after that). The combination of
+ // high fidelity for recent calls and fading for older calls makes this the most useful
+ // mechamism of choosing how to optimize future calls.
+ CallEdgeProfile* edgeProfile = callLinkInfo.callEdgeProfile.get();
+ WTF::loadLoadFence();
+ if (edgeProfile) {
+ CallLinkStatus result = computeFromCallEdgeProfile(edgeProfile);
+ if (!!result)
+ return result;
+ }
+ }
+
</ins><span class="cx"> return computeFromCallLinkInfo(locker, callLinkInfo);
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -148,68 +165,12 @@
</span><span class="cx"> // that is still marginally valid (i.e. the pointers ain't stale). This kind of raciness
</span><span class="cx"> // is probably OK for now.
</span><span class="cx">
</span><del>- // PolymorphicCallStubRoutine is a GCAwareJITStubRoutine, so if non-null, it will stay alive
- // until next GC even if the CallLinkInfo is concurrently cleared. Also, the variants list is
- // never mutated after the PolymorphicCallStubRoutine is instantiated. We have some conservative
- // fencing in place to make sure that we see the variants list after construction.
- if (PolymorphicCallStubRoutine* stub = callLinkInfo.stub.get()) {
- WTF::loadLoadFence();
-
- CallEdgeList edges = stub->edges();
-
- // Now that we've loaded the edges list, there are no further concurrency concerns. We will
- // just manipulate and prune this list to our liking - mostly removing entries that are too
- // infrequent and ensuring that it's sorted in descending order of frequency.
-
- RELEASE_ASSERT(edges.size());
-
- std::sort(
- edges.begin(), edges.end(),
- [] (CallEdge a, CallEdge b) {
- return a.count() > b.count();
- });
- RELEASE_ASSERT(edges.first().count() >= edges.last().count());
-
- double totalCallsToKnown = 0;
- double totalCallsToUnknown = callLinkInfo.slowPathCount;
- CallVariantList variants;
- for (size_t i = 0; i < edges.size(); ++i) {
- CallEdge edge = edges[i];
- // If the call is at the tail of the distribution, then we don't optimize it and we
- // treat it as if it was a call to something unknown. We define the tail as being either
- // a call that doesn't belong to the N most frequent callees (N =
- // maxPolymorphicCallVariantsForInlining) or that has a total call count that is too
- // small.
- if (i >= Options::maxPolymorphicCallVariantsForInlining()
- || edge.count() < Options::frequentCallThreshold())
- totalCallsToUnknown += edge.count();
- else {
- totalCallsToKnown += edge.count();
- variants.append(edge.callee());
- }
- }
-
- // Bail if we didn't find any calls that qualified.
- RELEASE_ASSERT(!!totalCallsToKnown == !!variants.size());
- if (variants.isEmpty())
- return takesSlowPath();
-
- // We require that the distribution of callees is skewed towards a handful of common ones.
- if (totalCallsToKnown / totalCallsToUnknown < Options::minimumCallToKnownRate())
- return takesSlowPath();
-
- RELEASE_ASSERT(totalCallsToKnown);
- RELEASE_ASSERT(variants.size());
-
- CallLinkStatus result;
- result.m_variants = variants;
- result.m_couldTakeSlowPath = !!totalCallsToUnknown;
- return result;
- }
-
</del><span class="cx"> if (callLinkInfo.slowPathCount >= Options::couldTakeSlowCaseMinimumCount())
</span><span class="cx"> return takesSlowPath();
</span><span class="cx">
</span><ins>+ if (ClosureCallStubRoutine* stub = callLinkInfo.stub.get())
+ return CallLinkStatus(stub->executable());
+
</ins><span class="cx"> JSFunction* target = callLinkInfo.lastSeenCallee.get();
</span><span class="cx"> if (!target)
</span><span class="cx"> return takesSlowPath();
</span><span class="lines">@@ -220,6 +181,34 @@
</span><span class="cx"> return CallLinkStatus(target);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+CallLinkStatus CallLinkStatus::computeFromCallEdgeProfile(CallEdgeProfile* edgeProfile)
+{
+ // In cases where the call edge profile saw nothing, use the CallLinkInfo instead.
+ if (!edgeProfile->totalCalls())
+ return CallLinkStatus();
+
+ // To do anything meaningful, we require that the majority of calls are to something we
+ // know how to handle.
+ unsigned numCallsToKnown = edgeProfile->numCallsToKnownCells();
+ unsigned numCallsToUnknown = edgeProfile->numCallsToNotCell() + edgeProfile->numCallsToUnknownCell();
+
+ // We require that the majority of calls were to something that we could possibly inline.
+ if (numCallsToKnown <= numCallsToUnknown)
+ return takesSlowPath();
+
+ // We require that the number of such calls is greater than some minimal threshold, so that we
+ // avoid inlining completely cold calls.
+ if (numCallsToKnown < Options::frequentCallThreshold())
+ return takesSlowPath();
+
+ CallLinkStatus result;
+ result.m_edges = edgeProfile->callEdges();
+ result.m_couldTakeSlowPath = !!numCallsToUnknown;
+ result.m_canTrustCounts = true;
+
+ return result;
+}
+
</ins><span class="cx"> CallLinkStatus CallLinkStatus::computeFor(
</span><span class="cx"> const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, CallLinkInfo& callLinkInfo,
</span><span class="cx"> ExitSiteData exitSiteData)
</span><span class="lines">@@ -293,8 +282,8 @@
</span><span class="cx">
</span><span class="cx"> bool CallLinkStatus::isClosureCall() const
</span><span class="cx"> {
</span><del>- for (unsigned i = m_variants.size(); i--;) {
- if (m_variants[i].isClosureCall())
</del><ins>+ for (unsigned i = m_edges.size(); i--;) {
+ if (m_edges[i].callee().isClosureCall())
</ins><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx"> return false;
</span><span class="lines">@@ -302,7 +291,18 @@
</span><span class="cx">
</span><span class="cx"> void CallLinkStatus::makeClosureCall()
</span><span class="cx"> {
</span><del>- m_variants = despecifiedVariantList(m_variants);
</del><ins>+ ASSERT(!m_isProved);
+ for (unsigned i = m_edges.size(); i--;)
+ m_edges[i] = m_edges[i].despecifiedClosure();
+
+ if (!ASSERT_DISABLED) {
+ // Doing this should not have created duplicates, because the CallEdgeProfile
+ // should despecify closures if doing so would reduce the number of known callees.
+ for (unsigned i = 0; i < m_edges.size(); ++i) {
+ for (unsigned j = i + 1; j < m_edges.size(); ++j)
+ ASSERT(m_edges[i].callee() != m_edges[j].callee());
+ }
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void CallLinkStatus::dump(PrintStream& out) const
</span><span class="lines">@@ -320,8 +320,7 @@
</span><span class="cx"> if (m_couldTakeSlowPath)
</span><span class="cx"> out.print(comma, "Could Take Slow Path");
</span><span class="cx">
</span><del>- if (!m_variants.isEmpty())
- out.print(comma, listDump(m_variants));
</del><ins>+ out.print(listDump(m_edges));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkStatush"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 2013, 2014 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">@@ -27,7 +27,6 @@
</span><span class="cx"> #define CallLinkStatus_h
</span><span class="cx">
</span><span class="cx"> #include "CallLinkInfo.h"
</span><del>-#include "CallVariant.h"
</del><span class="cx"> #include "CodeOrigin.h"
</span><span class="cx"> #include "CodeSpecializationKind.h"
</span><span class="cx"> #include "ConcurrentJITLock.h"
</span><span class="lines">@@ -49,6 +48,7 @@
</span><span class="cx"> CallLinkStatus()
</span><span class="cx"> : m_couldTakeSlowPath(false)
</span><span class="cx"> , m_isProved(false)
</span><ins>+ , m_canTrustCounts(false)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -62,9 +62,10 @@
</span><span class="cx"> explicit CallLinkStatus(JSValue);
</span><span class="cx">
</span><span class="cx"> CallLinkStatus(CallVariant variant)
</span><del>- : m_variants(1, variant)
</del><ins>+ : m_edges(1, CallEdge(variant, 1))
</ins><span class="cx"> , m_couldTakeSlowPath(false)
</span><span class="cx"> , m_isProved(false)
</span><ins>+ , m_canTrustCounts(false)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -108,18 +109,19 @@
</span><span class="cx"> static CallLinkStatus computeFor(
</span><span class="cx"> CodeBlock*, CodeOrigin, const CallLinkInfoMap&, const ContextMap&);
</span><span class="cx">
</span><del>- bool isSet() const { return !m_variants.isEmpty() || m_couldTakeSlowPath; }
</del><ins>+ bool isSet() const { return !m_edges.isEmpty() || m_couldTakeSlowPath; }
</ins><span class="cx">
</span><span class="cx"> bool operator!() const { return !isSet(); }
</span><span class="cx">
</span><span class="cx"> bool couldTakeSlowPath() const { return m_couldTakeSlowPath; }
</span><span class="cx">
</span><del>- CallVariantList variants() const { return m_variants; }
- unsigned size() const { return m_variants.size(); }
- CallVariant at(unsigned i) const { return m_variants[i]; }
- CallVariant operator[](unsigned i) const { return at(i); }
</del><ins>+ CallEdgeList edges() const { return m_edges; }
+ unsigned size() const { return m_edges.size(); }
+ CallEdge at(unsigned i) const { return m_edges[i]; }
+ CallEdge operator[](unsigned i) const { return at(i); }
</ins><span class="cx"> bool isProved() const { return m_isProved; }
</span><del>- bool canOptimize() const { return !m_variants.isEmpty(); }
</del><ins>+ bool canOptimize() const { return !m_edges.isEmpty(); }
+ bool canTrustCounts() const { return m_canTrustCounts; }
</ins><span class="cx">
</span><span class="cx"> bool isClosureCall() const; // Returns true if any callee is a closure call.
</span><span class="cx">
</span><span class="lines">@@ -130,13 +132,15 @@
</span><span class="cx">
</span><span class="cx"> static CallLinkStatus computeFromLLInt(const ConcurrentJITLocker&, CodeBlock*, unsigned bytecodeIndex);
</span><span class="cx"> #if ENABLE(JIT)
</span><ins>+ static CallLinkStatus computeFromCallEdgeProfile(CallEdgeProfile*);
</ins><span class="cx"> static CallLinkStatus computeFromCallLinkInfo(
</span><span class="cx"> const ConcurrentJITLocker&, CallLinkInfo&);
</span><span class="cx"> #endif
</span><span class="cx">
</span><del>- CallVariantList m_variants;
</del><ins>+ CallEdgeList m_edges;
</ins><span class="cx"> bool m_couldTakeSlowPath;
</span><span class="cx"> bool m_isProved;
</span><ins>+ bool m_canTrustCounts;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallVariantcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallVariant.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallVariant.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/bytecode/CallVariant.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014 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">@@ -50,34 +50,5 @@
</span><span class="cx"> out.print("Executable: ", *executable());
</span><span class="cx"> }
</span><span class="cx">
</span><del>-CallVariantList variantListWithVariant(const CallVariantList& list, CallVariant variantToAdd)
-{
- ASSERT(variantToAdd);
- CallVariantList result;
- for (CallVariant variant : list) {
- ASSERT(variant);
- if (!!variantToAdd) {
- if (variant == variantToAdd)
- variantToAdd = CallVariant();
- else if (variant.despecifiedClosure() == variantToAdd.despecifiedClosure()) {
- variant = variant.despecifiedClosure();
- variantToAdd = CallVariant();
- }
- }
- result.append(variant);
- }
- if (!!variantToAdd)
- result.append(variantToAdd);
- return result;
-}
-
-CallVariantList despecifiedVariantList(const CallVariantList& list)
-{
- CallVariantList result;
- for (CallVariant variant : list)
- result = variantListWithVariant(result, variant.despecifiedClosure());
- return result;
-}
-
</del><span class="cx"> } // namespace JSC
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallVarianth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallVariant.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallVariant.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/bytecode/CallVariant.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014 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">@@ -56,8 +56,11 @@
</span><span class="cx"> // than the fact that they don't fall into any of the above categories.
</span><span class="cx"> //
</span><span class="cx"> // This class serves as a kind of union over these four things. It does so by just holding a
</span><del>-// JSCell*. We determine which of the modes its in by doing type checks on the cell. Note that we
-// cannot use WriteBarrier<> here because this gets used inside the compiler.
</del><ins>+// JSCell*. We determine which of the modes its in by doing type checks on the cell. Note that there
+// is no lifecycle management for the cell because this class is always used in contexts where we
+// either do custom weak reference logic over instances of this class (see CallEdgeProfile), or we
+// are inside the compiler and we assume that the compiler runs in between collections and so can
+// touch the heap without notifying anyone.
</ins><span class="cx">
</span><span class="cx"> class CallVariant {
</span><span class="cx"> public:
</span><span class="lines">@@ -178,13 +181,6 @@
</span><span class="cx">
</span><span class="cx"> typedef Vector<CallVariant, 1> CallVariantList;
</span><span class="cx">
</span><del>-// Returns a new variant list by attempting to either append the given variant or merge it with one
-// of the variants we already have by despecifying closures.
-CallVariantList variantListWithVariant(const CallVariantList&, CallVariant);
-
-// Returns a new list where every element is despecified, and the list is deduplicated.
-CallVariantList despecifiedVariantList(const CallVariantList&);
-
</del><span class="cx"> } // namespace JSC
</span><span class="cx">
</span><span class="cx"> namespace WTF {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008-2010, 2012-2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008, 2009, 2010, 2012, 2013, 2014 Apple Inc. All rights reserved.
</ins><span class="cx"> * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
</span><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="lines">@@ -2174,8 +2174,6 @@
</span><span class="cx"> // destructor will try to remove nodes from our (no longer valid) linked list.
</span><span class="cx"> while (m_incomingCalls.begin() != m_incomingCalls.end())
</span><span class="cx"> m_incomingCalls.begin()->remove();
</span><del>- while (m_incomingPolymorphicCalls.begin() != m_incomingPolymorphicCalls.end())
- m_incomingPolymorphicCalls.begin()->remove();
</del><span class="cx">
</span><span class="cx"> // Note that our outgoing calls will be removed from other CodeBlocks'
</span><span class="cx"> // m_incomingCalls linked lists through the execution of the ~CallLinkInfo
</span><span class="lines">@@ -3042,12 +3040,6 @@
</span><span class="cx"> noticeIncomingCall(callerFrame);
</span><span class="cx"> m_incomingCalls.push(incoming);
</span><span class="cx"> }
</span><del>-
-void CodeBlock::linkIncomingPolymorphicCall(ExecState* callerFrame, PolymorphicCallNode* incoming)
-{
- noticeIncomingCall(callerFrame);
- m_incomingPolymorphicCalls.push(incoming);
-}
</del><span class="cx"> #endif // ENABLE(JIT)
</span><span class="cx">
</span><span class="cx"> void CodeBlock::unlinkIncomingCalls()
</span><span class="lines">@@ -3055,13 +3047,11 @@
</span><span class="cx"> while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
</span><span class="cx"> m_incomingLLIntCalls.begin()->unlink();
</span><span class="cx"> #if ENABLE(JIT)
</span><del>- if (m_incomingCalls.isEmpty() && m_incomingPolymorphicCalls.isEmpty())
</del><ins>+ if (m_incomingCalls.isEmpty())
</ins><span class="cx"> return;
</span><span class="cx"> RepatchBuffer repatchBuffer(this);
</span><span class="cx"> while (m_incomingCalls.begin() != m_incomingCalls.end())
</span><span class="cx"> m_incomingCalls.begin()->unlink(repatchBuffer);
</span><del>- while (m_incomingPolymorphicCalls.begin() != m_incomingPolymorphicCalls.end())
- m_incomingPolymorphicCalls.begin()->unlink(repatchBuffer);
</del><span class="cx"> #endif // ENABLE(JIT)
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -3255,19 +3245,12 @@
</span><span class="cx"> CodeBlock* callerCodeBlock = callerFrame->codeBlock();
</span><span class="cx">
</span><span class="cx"> if (Options::verboseCallLink())
</span><del>- dataLog("Noticing call link from ", pointerDump(callerCodeBlock), " to ", *this, "\n");
</del><ins>+ dataLog("Noticing call link from ", *callerCodeBlock, " to ", *this, "\n");
</ins><span class="cx">
</span><del>-#if ENABLE(DFG_JIT)
</del><span class="cx"> if (!m_shouldAlwaysBeInlined)
</span><span class="cx"> return;
</span><del>-
- if (!callerCodeBlock) {
- m_shouldAlwaysBeInlined = false;
- if (Options::verboseCallLink())
- dataLog(" Clearing SABI because caller is native.\n");
- return;
- }
</del><span class="cx">
</span><ins>+#if ENABLE(DFG_JIT)
</ins><span class="cx"> if (!hasBaselineJITProfiling())
</span><span class="cx"> return;
</span><span class="cx">
</span><span class="lines">@@ -3295,13 +3278,6 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if (JITCode::isOptimizingJIT(callerCodeBlock->jitType())) {
- m_shouldAlwaysBeInlined = false;
- if (Options::verboseCallLink())
- dataLog(" Clearing SABI bcause caller was already optimized.\n");
- return;
- }
-
</del><span class="cx"> if (callerCodeBlock->codeType() != FunctionCode) {
</span><span class="cx"> // If the caller is either eval or global code, assume that that won't be
</span><span class="cx"> // optimized anytime soon. For eval code this is particularly true since we
</span><span class="lines">@@ -3322,12 +3298,9 @@
</span><span class="cx"> m_shouldAlwaysBeInlined = false;
</span><span class="cx"> return;
</span><span class="cx"> }
</span><ins>+
+ RELEASE_ASSERT(callerCodeBlock->m_capabilityLevelState != DFG::CapabilityLevelNotSet);
</ins><span class="cx">
</span><del>- if (callerCodeBlock->m_capabilityLevelState == DFG::CapabilityLevelNotSet) {
- dataLog("In call from ", *callerCodeBlock, " ", callerFrame->codeOrigin(), " to ", *this, ": caller's DFG capability level is not set.\n");
- CRASH();
- }
-
</del><span class="cx"> if (canCompile(callerCodeBlock->m_capabilityLevelState))
</span><span class="cx"> return;
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -229,7 +229,11 @@
</span><span class="cx"> void unlinkCalls();
</span><span class="cx">
</span><span class="cx"> void linkIncomingCall(ExecState* callerFrame, CallLinkInfo*);
</span><del>- void linkIncomingPolymorphicCall(ExecState* callerFrame, PolymorphicCallNode*);
</del><ins>+
+ bool isIncomingCallAlreadyLinked(CallLinkInfo* incoming)
+ {
+ return m_incomingCalls.isOnList(incoming);
+ }
</ins><span class="cx"> #endif // ENABLE(JIT)
</span><span class="cx">
</span><span class="cx"> void linkIncomingCall(ExecState* callerFrame, LLIntCallLinkInfo*);
</span><span class="lines">@@ -1073,7 +1077,6 @@
</span><span class="cx"> Vector<ByValInfo> m_byValInfos;
</span><span class="cx"> Bag<CallLinkInfo> m_callLinkInfos;
</span><span class="cx"> SentinelLinkedList<CallLinkInfo, BasicRawSentinelNode<CallLinkInfo>> m_incomingCalls;
</span><del>- SentinelLinkedList<PolymorphicCallNode, BasicRawSentinelNode<PolymorphicCallNode>> m_incomingPolymorphicCalls;
</del><span class="cx"> #endif
</span><span class="cx"> std::unique_ptr<CompactJITCodeMap> m_jitCodeMap;
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -1968,6 +1968,14 @@
</span><span class="cx"> forNode(node).makeHeapTop();
</span><span class="cx"> break;
</span><span class="cx">
</span><ins>+ case ProfiledCall:
+ case ProfiledConstruct:
+ if (forNode(m_graph.varArgChild(node, 0)).m_value)
+ m_state.setFoundConstants(true);
+ clobberWorld(node->origin.semantic, clobberLimit);
+ forNode(node).makeHeapTop();
+ break;
+
</ins><span class="cx"> case ForceOSRExit:
</span><span class="cx"> case CheckBadCell:
</span><span class="cx"> m_state.setIsValid(false);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011-2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011, 2012, 2013, 2014 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">@@ -675,7 +675,7 @@
</span><span class="cx"> if (parameterSlots > m_parameterSlots)
</span><span class="cx"> m_parameterSlots = parameterSlots;
</span><span class="cx">
</span><del>- int dummyThisArgument = op == Call || op == NativeCall ? 0 : 1;
</del><ins>+ int dummyThisArgument = op == Call || op == NativeCall || op == ProfiledCall ? 0 : 1;
</ins><span class="cx"> for (int i = 0 + dummyThisArgument; i < argCount; ++i)
</span><span class="cx"> addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
</span><span class="cx">
</span><span class="lines">@@ -1044,8 +1044,17 @@
</span><span class="cx"> if (callTarget->hasConstant())
</span><span class="cx"> callLinkStatus = CallLinkStatus(callTarget->asJSValue()).setIsProved(true);
</span><span class="cx">
</span><del>- if (Options::verboseDFGByteCodeParsing())
- dataLog(" Handling call at ", currentCodeOrigin(), ": ", callLinkStatus, "\n");
</del><ins>+ if ((!callLinkStatus.canOptimize() || callLinkStatus.size() != 1)
+ && !isFTL(m_graph.m_plan.mode) && Options::useFTLJIT()
+ && InlineCallFrame::isNormalCall(kind)
+ && CallEdgeLog::isEnabled()
+ && Options::dfgDoesCallEdgeProfiling()) {
+ ASSERT(op == Call || op == Construct);
+ if (op == Call)
+ op = ProfiledCall;
+ else
+ op = ProfiledConstruct;
+ }
</ins><span class="cx">
</span><span class="cx"> if (!callLinkStatus.canOptimize()) {
</span><span class="cx"> // Oddly, this conflates calls that haven't executed with calls that behaved sufficiently polymorphically
</span><span class="lines">@@ -1067,17 +1076,17 @@
</span><span class="cx">
</span><span class="cx"> #if ENABLE(FTL_NATIVE_CALL_INLINING)
</span><span class="cx"> if (isFTL(m_graph.m_plan.mode) && Options::optimizeNativeCalls() && callLinkStatus.size() == 1 && !callLinkStatus.couldTakeSlowPath()) {
</span><del>- CallVariant callee = callLinkStatus[0];
</del><ins>+ CallVariant callee = callLinkStatus[0].callee();
</ins><span class="cx"> JSFunction* function = callee.function();
</span><span class="cx"> CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
</span><span class="cx"> if (function && function->isHostFunction()) {
</span><span class="cx"> emitFunctionChecks(callee, callTarget, registerOffset, specializationKind);
</span><span class="cx"> callOpInfo = OpInfo(m_graph.freeze(function));
</span><span class="cx">
</span><del>- if (op == Call)
</del><ins>+ if (op == Call || op == ProfiledCall)
</ins><span class="cx"> op = NativeCall;
</span><span class="cx"> else {
</span><del>- ASSERT(op == Construct);
</del><ins>+ ASSERT(op == Construct || op == ProfiledConstruct);
</ins><span class="cx"> op = NativeConstruct;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -1417,13 +1426,13 @@
</span><span class="cx"> // this in cases where we don't need control flow diamonds to check the callee.
</span><span class="cx"> if (!callLinkStatus.couldTakeSlowPath() && callLinkStatus.size() == 1) {
</span><span class="cx"> emitFunctionChecks(
</span><del>- callLinkStatus[0], callTargetNode, registerOffset, specializationKind);
</del><ins>+ callLinkStatus[0].callee(), callTargetNode, registerOffset, specializationKind);
</ins><span class="cx"> bool result = attemptToInlineCall(
</span><del>- callTargetNode, resultOperand, callLinkStatus[0], registerOffset,
</del><ins>+ callTargetNode, resultOperand, callLinkStatus[0].callee(), registerOffset,
</ins><span class="cx"> argumentCountIncludingThis, nextOffset, kind, CallerDoesNormalLinking, prediction,
</span><span class="cx"> inliningBalance);
</span><span class="cx"> if (!result && !callLinkStatus.isProved())
</span><del>- undoFunctionChecks(callLinkStatus[0]);
</del><ins>+ undoFunctionChecks(callLinkStatus[0].callee());
</ins><span class="cx"> if (verbose) {
</span><span class="cx"> dataLog("Done inlining (simple).\n");
</span><span class="cx"> dataLog("Stack: ", currentCodeOrigin(), "\n");
</span><span class="lines">@@ -1453,7 +1462,7 @@
</span><span class="cx"> bool allAreClosureCalls = true;
</span><span class="cx"> bool allAreDirectCalls = true;
</span><span class="cx"> for (unsigned i = callLinkStatus.size(); i--;) {
</span><del>- if (callLinkStatus[i].isClosureCall())
</del><ins>+ if (callLinkStatus[i].callee().isClosureCall())
</ins><span class="cx"> allAreDirectCalls = false;
</span><span class="cx"> else
</span><span class="cx"> allAreClosureCalls = false;
</span><span class="lines">@@ -1466,8 +1475,9 @@
</span><span class="cx"> thingToSwitchOn = addToGraph(GetExecutable, callTargetNode);
</span><span class="cx"> else {
</span><span class="cx"> // FIXME: We should be able to handle this case, but it's tricky and we don't know of cases
</span><del>- // where it would be beneficial. It might be best to handle these cases as if all calls were
- // closure calls.
</del><ins>+ // where it would be beneficial. Also, CallLinkStatus would make all callees appear like
+ // closure calls if any calls were closure calls - except for calls to internal functions.
+ // So this will only arise if some callees are internal functions and others are closures.
</ins><span class="cx"> // https://bugs.webkit.org/show_bug.cgi?id=136020
</span><span class="cx"> if (verbose) {
</span><span class="cx"> dataLog("Bailing inlining (mix).\n");
</span><span class="lines">@@ -1507,7 +1517,7 @@
</span><span class="cx"> // to the continuation block, which we create last.
</span><span class="cx"> Vector<BasicBlock*> landingBlocks;
</span><span class="cx">
</span><del>- // We may force this true if we give up on inlining any of the edges.
</del><ins>+ // We make force this true if we give up on inlining any of the edges.
</ins><span class="cx"> bool couldTakeSlowPath = callLinkStatus.couldTakeSlowPath();
</span><span class="cx">
</span><span class="cx"> if (verbose)
</span><span class="lines">@@ -1523,7 +1533,7 @@
</span><span class="cx"> Node* myCallTargetNode = getDirect(calleeReg);
</span><span class="cx">
</span><span class="cx"> bool inliningResult = attemptToInlineCall(
</span><del>- myCallTargetNode, resultOperand, callLinkStatus[i], registerOffset,
</del><ins>+ myCallTargetNode, resultOperand, callLinkStatus[i].callee(), registerOffset,
</ins><span class="cx"> argumentCountIncludingThis, nextOffset, kind, CallerLinksManually, prediction,
</span><span class="cx"> inliningBalance);
</span><span class="cx">
</span><span class="lines">@@ -1542,10 +1552,10 @@
</span><span class="cx">
</span><span class="cx"> JSCell* thingToCaseOn;
</span><span class="cx"> if (allAreDirectCalls)
</span><del>- thingToCaseOn = callLinkStatus[i].nonExecutableCallee();
</del><ins>+ thingToCaseOn = callLinkStatus[i].callee().nonExecutableCallee();
</ins><span class="cx"> else {
</span><span class="cx"> ASSERT(allAreClosureCalls);
</span><del>- thingToCaseOn = callLinkStatus[i].executable();
</del><ins>+ thingToCaseOn = callLinkStatus[i].callee().executable();
</ins><span class="cx"> }
</span><span class="cx"> data.cases.append(SwitchCase(m_graph.freeze(thingToCaseOn), block.get()));
</span><span class="cx"> m_currentIndex = nextOffset;
</span><span class="lines">@@ -1557,7 +1567,7 @@
</span><span class="cx"> landingBlocks.append(m_currentBlock);
</span><span class="cx">
</span><span class="cx"> if (verbose)
</span><del>- dataLog("Finished inlining ", callLinkStatus[i], " at ", currentCodeOrigin(), ".\n");
</del><ins>+ dataLog("Finished inlining ", callLinkStatus[i].callee(), " at ", currentCodeOrigin(), ".\n");
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> RefPtr<BasicBlock> slowPathBlock = adoptRef(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -363,6 +363,8 @@
</span><span class="cx"> case ArrayPop:
</span><span class="cx"> case Call:
</span><span class="cx"> case Construct:
</span><ins>+ case ProfiledCall:
+ case ProfiledConstruct:
</ins><span class="cx"> case NativeCall:
</span><span class="cx"> case NativeConstruct:
</span><span class="cx"> case ToPrimitive:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -420,6 +420,20 @@
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ case ProfiledCall:
+ case ProfiledConstruct: {
+ if (!m_state.forNode(m_graph.varArgChild(node, 0)).m_value)
+ break;
+
+ // If we were able to prove that the callee is a constant then the normal call
+ // inline cache will record this callee. This means that there is no need to do any
+ // additional profiling.
+ m_interpreter.execute(indexInBlock);
+ node->setOp(node->op() == ProfiledCall ? Call : Construct);
+ eliminated = true;
+ break;
+ }
+
</ins><span class="cx"> default:
</span><span class="cx"> break;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -118,6 +118,8 @@
</span><span class="cx"> case Construct:
</span><span class="cx"> case NativeCall:
</span><span class="cx"> case NativeConstruct:
</span><ins>+ case ProfiledCall:
+ case ProfiledConstruct:
</ins><span class="cx"> case Breakpoint:
</span><span class="cx"> case ProfileWillCall:
</span><span class="cx"> case ProfileDidCall:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDrivercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -79,17 +79,20 @@
</span><span class="cx"> if (mode == DFGMode) {
</span><span class="cx"> vm.getCTIStub(linkCallThunkGenerator);
</span><span class="cx"> vm.getCTIStub(linkConstructThunkGenerator);
</span><del>- vm.getCTIStub(linkPolymorphicCallThunkGenerator);
</del><ins>+ vm.getCTIStub(linkClosureCallThunkGenerator);
</ins><span class="cx"> vm.getCTIStub(virtualCallThunkGenerator);
</span><span class="cx"> vm.getCTIStub(virtualConstructThunkGenerator);
</span><span class="cx"> } else {
</span><span class="cx"> vm.getCTIStub(linkCallThatPreservesRegsThunkGenerator);
</span><span class="cx"> vm.getCTIStub(linkConstructThatPreservesRegsThunkGenerator);
</span><del>- vm.getCTIStub(linkPolymorphicCallThatPreservesRegsThunkGenerator);
</del><ins>+ vm.getCTIStub(linkClosureCallThatPreservesRegsThunkGenerator);
</ins><span class="cx"> vm.getCTIStub(virtualCallThatPreservesRegsThunkGenerator);
</span><span class="cx"> vm.getCTIStub(virtualConstructThatPreservesRegsThunkGenerator);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ if (CallEdgeLog::isEnabled())
+ vm.ensureCallEdgeLog().processLog();
+
</ins><span class="cx"> if (vm.typeProfiler())
</span><span class="cx"> vm.typeProfilerLog()->processLogEntries(ASCIILiteral("Preparing for DFG compilation."));
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -1202,6 +1202,8 @@
</span><span class="cx"> case AllocationProfileWatchpoint:
</span><span class="cx"> case Call:
</span><span class="cx"> case Construct:
</span><ins>+ case ProfiledCall:
+ case ProfiledConstruct:
</ins><span class="cx"> case ProfileControlFlow:
</span><span class="cx"> case NativeCall:
</span><span class="cx"> case NativeConstruct:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -1057,6 +1057,8 @@
</span><span class="cx"> case GetMyArgumentByValSafe:
</span><span class="cx"> case Call:
</span><span class="cx"> case Construct:
</span><ins>+ case ProfiledCall:
+ case ProfiledConstruct:
</ins><span class="cx"> case NativeCall:
</span><span class="cx"> case NativeConstruct:
</span><span class="cx"> case GetByOffset:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -217,6 +217,8 @@
</span><span class="cx"> /* Calls. */\
</span><span class="cx"> macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
</span><span class="cx"> macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
</span><ins>+ macro(ProfiledCall, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
+ macro(ProfiledConstruct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
</ins><span class="cx"> macro(NativeCall, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
</span><span class="cx"> macro(NativeConstruct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
</span><span class="cx"> \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -1219,11 +1219,6 @@
</span><span class="cx"> DeferGC deferGC(vm->heap);
</span><span class="cx"> CodeBlock* codeBlock = exec->codeBlock();
</span><span class="cx">
</span><del>- if (codeBlock->jitType() != JITCode::DFGJIT) {
- dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
- RELEASE_ASSERT_NOT_REACHED();
- }
-
</del><span class="cx"> JITCode* jitCode = codeBlock->jitCode()->dfg();
</span><span class="cx">
</span><span class="cx"> if (Options::verboseOSR()) {
</span><span class="lines">@@ -1243,11 +1238,6 @@
</span><span class="cx"> DeferGC deferGC(vm->heap);
</span><span class="cx"> CodeBlock* codeBlock = exec->codeBlock();
</span><span class="cx">
</span><del>- if (codeBlock->jitType() != JITCode::DFGJIT) {
- dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
- RELEASE_ASSERT_NOT_REACHED();
- }
-
</del><span class="cx"> JITCode* jitCode = codeBlock->jitCode()->dfg();
</span><span class="cx">
</span><span class="cx"> if (Options::verboseOSR()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -188,6 +188,8 @@
</span><span class="cx"> case GetDirectPname:
</span><span class="cx"> case Call:
</span><span class="cx"> case Construct:
</span><ins>+ case ProfiledCall:
+ case ProfiledConstruct:
</ins><span class="cx"> case NativeCall:
</span><span class="cx"> case NativeConstruct:
</span><span class="cx"> case GetGlobalVar:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -189,6 +189,8 @@
</span><span class="cx"> case CompareStrictEq:
</span><span class="cx"> case Call:
</span><span class="cx"> case Construct:
</span><ins>+ case ProfiledCall:
+ case ProfiledConstruct:
</ins><span class="cx"> case NewObject:
</span><span class="cx"> case NewArray:
</span><span class="cx"> case NewArrayWithSize:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -638,9 +638,9 @@
</span><span class="cx">
</span><span class="cx"> void SpeculativeJIT::emitCall(Node* node)
</span><span class="cx"> {
</span><del>- bool isCall = node->op() == Call;
</del><ins>+ bool isCall = node->op() == Call || node->op() == ProfiledCall;
</ins><span class="cx"> if (!isCall)
</span><del>- ASSERT(node->op() == Construct);
</del><ins>+ ASSERT(node->op() == Construct || node->op() == ProfiledConstruct);
</ins><span class="cx">
</span><span class="cx"> // For constructors, the this argument is not passed but we have to make space
</span><span class="cx"> // for it.
</span><span class="lines">@@ -689,6 +689,11 @@
</span><span class="cx">
</span><span class="cx"> CallLinkInfo* info = m_jit.codeBlock()->addCallLinkInfo();
</span><span class="cx">
</span><ins>+ if (node->op() == ProfiledCall || node->op() == ProfiledConstruct) {
+ m_jit.vm()->callEdgeLog->emitLogCode(
+ m_jit, info->callEdgeProfile, callee.jsValueRegs());
+ }
+
</ins><span class="cx"> slowPath.append(branchNotCell(callee.jsValueRegs()));
</span><span class="cx"> slowPath.append(m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleePayloadGPR, targetToCheck));
</span><span class="cx">
</span><span class="lines">@@ -4164,6 +4169,8 @@
</span><span class="cx">
</span><span class="cx"> case Call:
</span><span class="cx"> case Construct:
</span><ins>+ case ProfiledCall:
+ case ProfiledConstruct:
</ins><span class="cx"> emitCall(node);
</span><span class="cx"> break;
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -624,9 +624,9 @@
</span><span class="cx">
</span><span class="cx"> void SpeculativeJIT::emitCall(Node* node)
</span><span class="cx"> {
</span><del>- bool isCall = node->op() == Call;
</del><ins>+ bool isCall = node->op() == Call || node->op() == ProfiledCall;
</ins><span class="cx"> if (!isCall)
</span><del>- DFG_ASSERT(m_jit.graph(), node, node->op() == Construct);
</del><ins>+ DFG_ASSERT(m_jit.graph(), node, node->op() == Construct || node->op() == ProfiledConstruct);
</ins><span class="cx">
</span><span class="cx"> // For constructors, the this argument is not passed but we have to make space
</span><span class="cx"> // for it.
</span><span class="lines">@@ -669,6 +669,11 @@
</span><span class="cx">
</span><span class="cx"> CallLinkInfo* callLinkInfo = m_jit.codeBlock()->addCallLinkInfo();
</span><span class="cx">
</span><ins>+ if (node->op() == ProfiledCall || node->op() == ProfiledConstruct) {
+ m_jit.vm()->callEdgeLog->emitLogCode(
+ m_jit, callLinkInfo->callEdgeProfile, JSValueRegs(calleeGPR));
+ }
+
</ins><span class="cx"> slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(0));
</span><span class="cx">
</span><span class="cx"> JITCompiler::Call fastCall = m_jit.nearCall();
</span><span class="lines">@@ -4231,6 +4236,8 @@
</span><span class="cx">
</span><span class="cx"> case Call:
</span><span class="cx"> case Construct:
</span><ins>+ case ProfiledCall:
+ case ProfiledConstruct:
</ins><span class="cx"> emitCall(node);
</span><span class="cx"> break;
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGTierUpCheckInjectionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -50,13 +50,17 @@
</span><span class="cx"> if (!Options::useFTLJIT())
</span><span class="cx"> return false;
</span><span class="cx">
</span><del>- if (m_graph.m_profiledBlock->m_didFailFTLCompilation)
</del><ins>+ if (m_graph.m_profiledBlock->m_didFailFTLCompilation) {
+ removeFTLProfiling();
</ins><span class="cx"> return false;
</span><ins>+ }
</ins><span class="cx">
</span><span class="cx"> #if ENABLE(FTL_JIT)
</span><span class="cx"> FTL::CapabilityLevel level = FTL::canCompile(m_graph);
</span><del>- if (level == FTL::CannotCompile)
</del><ins>+ if (level == FTL::CannotCompile) {
+ removeFTLProfiling();
</ins><span class="cx"> return false;
</span><ins>+ }
</ins><span class="cx">
</span><span class="cx"> if (!Options::enableOSREntryToFTL())
</span><span class="cx"> level = FTL::CanCompile;
</span><span class="lines">@@ -118,6 +122,32 @@
</span><span class="cx"> return false;
</span><span class="cx"> #endif // ENABLE(FTL_JIT)
</span><span class="cx"> }
</span><ins>+
+private:
+ void removeFTLProfiling()
+ {
+ for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+ BasicBlock* block = m_graph.block(blockIndex);
+ if (!block)
+ continue;
+
+ for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
+ Node* node = block->at(nodeIndex);
+ switch (node->op()) {
+ case ProfiledCall:
+ node->setOp(Call);
+ break;
+
+ case ProfiledConstruct:
+ node->setOp(Construct);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> bool performTierUpCheckInjection(Graph& graph)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -176,6 +176,11 @@
</span><span class="cx"> case MaterializeNewObject:
</span><span class="cx"> // These are OK.
</span><span class="cx"> break;
</span><ins>+ case ProfiledCall:
+ case ProfiledConstruct:
+ // These are OK not because the FTL can support them, but because if the DFG sees one of
+ // these then the FTL will see a normal Call/Construct.
+ break;
</ins><span class="cx"> case Identity:
</span><span class="cx"> // No backend handles this because it will be optimized out. But we may check
</span><span class="cx"> // for capabilities before optimization. It would be a deep error to remove this
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -992,6 +992,11 @@
</span><span class="cx"> vm()->typeProfilerLog()->processLogEntries(ASCIILiteral("GC"));
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ if (vm()->callEdgeLog) {
+ DeferGCForAWhile awhile(*this);
+ vm()->callEdgeLog->processLog();
+ }
+
</ins><span class="cx"> RELEASE_ASSERT(!m_deferralDepth);
</span><span class="cx"> ASSERT(vm()->currentThreadIsHoldingAPILock());
</span><span class="cx"> RELEASE_ASSERT(vm()->atomicStringTable() == wtfThreadData().atomicStringTable());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitBinarySwitchh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/BinarySwitch.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/BinarySwitch.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/jit/BinarySwitch.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -54,7 +54,6 @@
</span><span class="cx"> // int value = switch.caseValue();
</span><span class="cx"> // unsigned index = switch.caseIndex(); // index into casesVector, above
</span><span class="cx"> // ... // generate code for this case
</span><del>-// ... = jit.jump(); // you have to jump out yourself; falling through causes undefined behavior
</del><span class="cx"> // }
</span><span class="cx"> // switch.fallThrough().link(&jit);
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitClosureCallStubRoutinecppfromrev179391trunkSourceJavaScriptCorebytecodeCallEdgeh"></a>
<div class="copfile"><h4>Copied: trunk/Source/JavaScriptCore/jit/ClosureCallStubRoutine.cpp (from rev 179391, trunk/Source/JavaScriptCore/bytecode/CallEdge.h) (0 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ClosureCallStubRoutine.cpp         (rev 0)
+++ trunk/Source/JavaScriptCore/jit/ClosureCallStubRoutine.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -0,0 +1,60 @@
</span><ins>+/*
+ * Copyright (C) 2012, 2014, 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ClosureCallStubRoutine.h"
+
+#if ENABLE(JIT)
+
+#include "Executable.h"
+#include "Heap.h"
+#include "VM.h"
+#include "JSCInlines.h"
+#include "SlotVisitor.h"
+#include "Structure.h"
+
+namespace JSC {
+
+ClosureCallStubRoutine::ClosureCallStubRoutine(
+ const MacroAssemblerCodeRef& code, VM& vm, const JSCell* owner,
+ ExecutableBase* executable)
+ : GCAwareJITStubRoutine(code, vm)
+ , m_executable(vm, owner, executable)
+{
+}
+
+ClosureCallStubRoutine::~ClosureCallStubRoutine()
+{
+}
+
+void ClosureCallStubRoutine::markRequiredObjectsInternal(SlotVisitor& visitor)
+{
+ visitor.append(&m_executable);
+}
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorejitClosureCallStubRoutinehfromrev179391trunkSourceJavaScriptCorebytecodeCallEdgeh"></a>
<div class="copfile"><h4>Copied: trunk/Source/JavaScriptCore/jit/ClosureCallStubRoutine.h (from rev 179391, trunk/Source/JavaScriptCore/bytecode/CallEdge.h) (0 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ClosureCallStubRoutine.h         (rev 0)
+++ trunk/Source/JavaScriptCore/jit/ClosureCallStubRoutine.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -0,0 +1,58 @@
</span><ins>+/*
+ * Copyright (C) 2012, 2014, 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ClosureCallStubRoutine_h
+#define ClosureCallStubRoutine_h
+
+#if ENABLE(JIT)
+
+#include "CodeOrigin.h"
+#include "GCAwareJITStubRoutine.h"
+
+namespace JSC {
+
+class ClosureCallStubRoutine : public GCAwareJITStubRoutine {
+public:
+ ClosureCallStubRoutine(
+ const MacroAssemblerCodeRef&, VM&, const JSCell* owner,
+ ExecutableBase*);
+
+ virtual ~ClosureCallStubRoutine();
+
+ ExecutableBase* executable() const { return m_executable.get(); }
+
+protected:
+ virtual void markRequiredObjectsInternal(SlotVisitor&) override;
+
+private:
+ WriteBarrier<ExecutableBase> m_executable;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
+#endif // ClosureCallStubRoutine_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCallcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCall.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/jit/JITCall.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -214,6 +214,10 @@
</span><span class="cx">
</span><span class="cx"> CallLinkInfo* info = m_codeBlock->addCallLinkInfo();
</span><span class="cx">
</span><ins>+ if (CallEdgeLog::isEnabled() && shouldEmitProfiling()
+ && Options::baselineDoesCallEdgeProfiling())
+ m_vm->ensureCallEdgeLog().emitLogCode(*this, info->callEdgeProfile, JSValueRegs(regT0));
+
</ins><span class="cx"> if (opcodeID == op_call_eval) {
</span><span class="cx"> compileCallEval(instruction);
</span><span class="cx"> return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCall32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -278,6 +278,12 @@
</span><span class="cx">
</span><span class="cx"> CallLinkInfo* info = m_codeBlock->addCallLinkInfo();
</span><span class="cx">
</span><ins>+ if (CallEdgeLog::isEnabled() && shouldEmitProfiling()
+ && Options::baselineDoesCallEdgeProfiling()) {
+ m_vm->ensureCallEdgeLog().emitLogCode(
+ *this, info->callEdgeProfile, JSValueRegs(regT1, regT0));
+ }
+
</ins><span class="cx"> if (opcodeID == op_call_eval) {
</span><span class="cx"> compileCallEval(instruction);
</span><span class="cx"> return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2014 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">@@ -776,12 +776,47 @@
</span><span class="cx"> return virtualForWithFunction(execCallee, kind, registers, calleeAsFunctionCellIgnored);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-char* JIT_OPERATION operationLinkPolymorphicCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
</del><ins>+static bool attemptToOptimizeClosureCall(
+ ExecState* execCallee, RegisterPreservationMode registers, JSCell* calleeAsFunctionCell,
+ CallLinkInfo& callLinkInfo)
</ins><span class="cx"> {
</span><ins>+ if (!calleeAsFunctionCell)
+ return false;
+
+ JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
+ JSFunction* oldCallee = callLinkInfo.callee.get();
+
+ if (!oldCallee || oldCallee->executable() != callee->executable())
+ return false;
+
+ ASSERT(callee->executable()->hasJITCodeForCall());
+ MacroAssemblerCodePtr codePtr =
+ callee->executable()->generatedJITCodeForCall()->addressForCall(
+ *execCallee->callerFrame()->codeBlock()->vm(), callee->executable(),
+ ArityCheckNotRequired, registers);
+
+ CodeBlock* codeBlock;
+ if (callee->executable()->isHostFunction())
+ codeBlock = 0;
+ else {
+ codeBlock = jsCast<FunctionExecutable*>(callee->executable())->codeBlockForCall();
+ if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo.callType == CallLinkInfo::CallVarargs || callLinkInfo.callType == CallLinkInfo::ConstructVarargs)
+ return false;
+ }
+
+ linkClosureCall(
+ execCallee, callLinkInfo, codeBlock, callee->executable(), codePtr, registers);
+
+ return true;
+}
+
+char* JIT_OPERATION operationLinkClosureCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
+{
</ins><span class="cx"> JSCell* calleeAsFunctionCell;
</span><span class="cx"> char* result = virtualForWithFunction(execCallee, CodeForCall, RegisterPreservationNotRequired, calleeAsFunctionCell);
</span><span class="cx">
</span><del>- linkPolymorphicCall(execCallee, *callLinkInfo, CallVariant(calleeAsFunctionCell), RegisterPreservationNotRequired);
</del><ins>+ if (!attemptToOptimizeClosureCall(execCallee, RegisterPreservationNotRequired, calleeAsFunctionCell, *callLinkInfo))
+ linkSlowFor(execCallee, *callLinkInfo, CodeForCall, RegisterPreservationNotRequired);
</ins><span class="cx">
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="lines">@@ -796,12 +831,13 @@
</span><span class="cx"> return virtualFor(execCallee, CodeForConstruct, RegisterPreservationNotRequired);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-char* JIT_OPERATION operationLinkPolymorphicCallThatPreservesRegs(ExecState* execCallee, CallLinkInfo* callLinkInfo)
</del><ins>+char* JIT_OPERATION operationLinkClosureCallThatPreservesRegs(ExecState* execCallee, CallLinkInfo* callLinkInfo)
</ins><span class="cx"> {
</span><span class="cx"> JSCell* calleeAsFunctionCell;
</span><span class="cx"> char* result = virtualForWithFunction(execCallee, CodeForCall, MustPreserveRegisters, calleeAsFunctionCell);
</span><span class="cx">
</span><del>- linkPolymorphicCall(execCallee, *callLinkInfo, CallVariant(calleeAsFunctionCell), MustPreserveRegisters);
</del><ins>+ if (!attemptToOptimizeClosureCall(execCallee, MustPreserveRegisters, calleeAsFunctionCell, *callLinkInfo))
+ linkSlowFor(execCallee, *callLinkInfo, CodeForCall, MustPreserveRegisters);
</ins><span class="cx">
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="lines">@@ -997,10 +1033,6 @@
</span><span class="cx"> DeferGCForAWhile deferGC(vm.heap);
</span><span class="cx">
</span><span class="cx"> CodeBlock* codeBlock = exec->codeBlock();
</span><del>- if (codeBlock->jitType() != JITCode::BaselineJIT) {
- dataLog("Unexpected code block in Baseline->DFG tier-up: ", *codeBlock, "\n");
- RELEASE_ASSERT_NOT_REACHED();
- }
</del><span class="cx">
</span><span class="cx"> if (bytecodeIndex) {
</span><span class="cx"> // If we're attempting to OSR from a loop, assume that this should be
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -246,12 +246,12 @@
</span><span class="cx"> void JIT_OPERATION operationDirectPutByValGeneric(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationCallEval(ExecState*, ExecState*) WTF_INTERNAL;
</span><span class="cx"> char* JIT_OPERATION operationLinkCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
</span><del>-char* JIT_OPERATION operationLinkPolymorphicCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
</del><ins>+char* JIT_OPERATION operationLinkClosureCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
</ins><span class="cx"> char* JIT_OPERATION operationVirtualCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
</span><span class="cx"> char* JIT_OPERATION operationVirtualConstruct(ExecState*, CallLinkInfo*) WTF_INTERNAL;
</span><span class="cx"> char* JIT_OPERATION operationLinkConstruct(ExecState*, CallLinkInfo*) WTF_INTERNAL;
</span><span class="cx"> char* JIT_OPERATION operationLinkCallThatPreservesRegs(ExecState*, CallLinkInfo*) WTF_INTERNAL;
</span><del>-char* JIT_OPERATION operationLinkPolymorphicCallThatPreservesRegs(ExecState*, CallLinkInfo*) WTF_INTERNAL;
</del><ins>+char* JIT_OPERATION operationLinkClosureCallThatPreservesRegs(ExecState*, CallLinkInfo*) WTF_INTERNAL;
</ins><span class="cx"> char* JIT_OPERATION operationVirtualCallThatPreservesRegs(ExecState*, CallLinkInfo*) WTF_INTERNAL;
</span><span class="cx"> char* JIT_OPERATION operationVirtualConstructThatPreservesRegs(ExecState*, CallLinkInfo*) WTF_INTERNAL;
</span><span class="cx"> char* JIT_OPERATION operationLinkConstructThatPreservesRegs(ExecState*, CallLinkInfo*) WTF_INTERNAL;
</span><span class="lines">@@ -391,13 +391,13 @@
</span><span class="cx"> return 0;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-inline P_JITOperation_ECli operationLinkPolymorphicCallFor(RegisterPreservationMode registers)
</del><ins>+inline P_JITOperation_ECli operationLinkClosureCallFor(RegisterPreservationMode registers)
</ins><span class="cx"> {
</span><span class="cx"> switch (registers) {
</span><span class="cx"> case RegisterPreservationNotRequired:
</span><del>- return operationLinkPolymorphicCall;
</del><ins>+ return operationLinkClosureCall;
</ins><span class="cx"> case MustPreserveRegisters:
</span><del>- return operationLinkPolymorphicCallThatPreservesRegs;
</del><ins>+ return operationLinkClosureCallThatPreservesRegs;
</ins><span class="cx"> }
</span><span class="cx"> RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> return 0;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITStubRoutineh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITStubRoutine.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITStubRoutine.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/jit/JITStubRoutine.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -141,9 +141,6 @@
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- // Return true if you are still valid after. Return false if you are now invalid. If you return
- // false, you will usually not do any clearing because the idea is that you will simply be
- // destroyed.
</del><span class="cx"> virtual bool visitWeak(RepatchBuffer&);
</span><span class="cx">
</span><span class="cx"> protected:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITWriteBarrierh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITWriteBarrier.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITWriteBarrier.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/jit/JITWriteBarrier.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -31,7 +31,6 @@
</span><span class="cx"> #include "MacroAssembler.h"
</span><span class="cx"> #include "SlotVisitor.h"
</span><span class="cx"> #include "UnusedPointer.h"
</span><del>-#include "VM.h"
</del><span class="cx"> #include "WriteBarrier.h"
</span><span class="cx">
</span><span class="cx"> namespace JSC {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitPolymorphicCallStubRoutinecpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/jit/PolymorphicCallStubRoutine.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/PolymorphicCallStubRoutine.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/jit/PolymorphicCallStubRoutine.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -1,117 +0,0 @@
</span><del>-/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "PolymorphicCallStubRoutine.h"
-
-#if ENABLE(JIT)
-
-#include "CallLinkInfo.h"
-#include "CodeBlock.h"
-#include "JSCInlines.h"
-#include "LinkBuffer.h"
-
-namespace JSC {
-
-PolymorphicCallNode::~PolymorphicCallNode()
-{
- if (isOnList())
- remove();
-}
-
-void PolymorphicCallNode::unlink(RepatchBuffer& repatchBuffer)
-{
- if (Options::showDisassembly())
- dataLog("Unlinking polymorphic call at ", m_callLinkInfo->callReturnLocation, ", ", m_callLinkInfo->codeOrigin, "\n");
-
- m_callLinkInfo->unlink(repatchBuffer);
-
- if (isOnList())
- remove();
-}
-
-void PolymorphicCallCase::dump(PrintStream& out) const
-{
- out.print("<variant = ", m_variant, ", codeBlock = ", pointerDump(m_codeBlock), ">");
-}
-
-PolymorphicCallStubRoutine::PolymorphicCallStubRoutine(
- const MacroAssemblerCodeRef& codeRef, VM& vm, const JSCell* owner, ExecState* callerFrame,
- CallLinkInfo& info, const Vector<PolymorphicCallCase>& cases,
- std::unique_ptr<uint32_t[]> fastCounts)
- : GCAwareJITStubRoutine(codeRef, vm)
- , m_fastCounts(WTF::move(fastCounts))
-{
- for (PolymorphicCallCase callCase : cases) {
- m_variants.append(WriteBarrier<JSCell>(vm, owner, callCase.variant().rawCalleeCell()));
- if (shouldShowDisassemblyFor(callerFrame->codeBlock()))
- dataLog("Linking polymorphic call in ", *callerFrame->codeBlock(), " at ", callerFrame->codeOrigin(), " to ", callCase.variant(), ", codeBlock = ", pointerDump(callCase.codeBlock()), "\n");
- if (CodeBlock* codeBlock = callCase.codeBlock())
- codeBlock->linkIncomingPolymorphicCall(callerFrame, m_callNodes.add(&info));
- }
- m_variants.shrinkToFit();
- WTF::storeStoreFence();
-}
-
-PolymorphicCallStubRoutine::~PolymorphicCallStubRoutine() { }
-
-CallVariantList PolymorphicCallStubRoutine::variants() const
-{
- CallVariantList result;
- for (size_t i = 0; i < m_variants.size(); ++i)
- result.append(CallVariant(m_variants[i].get()));
- return result;
-}
-
-CallEdgeList PolymorphicCallStubRoutine::edges() const
-{
- // We wouldn't have these if this was an FTL stub routine. We shouldn't be asking for profiling
- // from the FTL.
- RELEASE_ASSERT(m_fastCounts);
-
- CallEdgeList result;
- for (size_t i = 0; i < m_variants.size(); ++i)
- result.append(CallEdge(CallVariant(m_variants[i].get()), m_fastCounts[i]));
- return result;
-}
-
-bool PolymorphicCallStubRoutine::visitWeak(RepatchBuffer&)
-{
- for (auto& variant : m_variants) {
- if (!Heap::isMarked(variant.get()))
- return false;
- }
- return true;
-}
-
-void PolymorphicCallStubRoutine::markRequiredObjectsInternal(SlotVisitor& visitor)
-{
- for (auto& variant : m_variants)
- visitor.append(&variant);
-}
-
-} // namespace JSC
-
-#endif // ENABLE(JIT)
</del></span></pre></div>
<a id="trunkSourceJavaScriptCorejitPolymorphicCallStubRoutineh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/jit/PolymorphicCallStubRoutine.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/PolymorphicCallStubRoutine.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/jit/PolymorphicCallStubRoutine.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -1,110 +0,0 @@
</span><del>-/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef PolymorphicCallStubRoutine_h
-#define PolymorphicCallStubRoutine_h
-
-#if ENABLE(JIT)
-
-#include "CallEdge.h"
-#include "CallVariant.h"
-#include "CodeOrigin.h"
-#include "GCAwareJITStubRoutine.h"
-#include <wtf/FastMalloc.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/Vector.h>
-
-namespace JSC {
-
-struct CallLinkInfo;
-
-class PolymorphicCallNode : public BasicRawSentinelNode<PolymorphicCallNode> {
- WTF_MAKE_NONCOPYABLE(PolymorphicCallNode);
-public:
- PolymorphicCallNode(CallLinkInfo* info)
- : m_callLinkInfo(info)
- {
- }
-
- ~PolymorphicCallNode();
-
- void unlink(RepatchBuffer&);
-
-private:
- CallLinkInfo* m_callLinkInfo;
-};
-
-class PolymorphicCallCase {
-public:
- PolymorphicCallCase()
- : m_codeBlock(nullptr)
- {
- }
-
- PolymorphicCallCase(CallVariant variant, CodeBlock* codeBlock)
- : m_variant(variant)
- , m_codeBlock(codeBlock)
- {
- }
-
- CallVariant variant() const { return m_variant; }
- CodeBlock* codeBlock() const { return m_codeBlock; }
-
- void dump(PrintStream&) const;
-
-private:
- CallVariant m_variant;
- CodeBlock* m_codeBlock;
-};
-
-class PolymorphicCallStubRoutine : public GCAwareJITStubRoutine {
-public:
- PolymorphicCallStubRoutine(
- const MacroAssemblerCodeRef&, VM&, const JSCell* owner,
- ExecState* callerFrame, CallLinkInfo&, const Vector<PolymorphicCallCase>&,
- std::unique_ptr<uint32_t[]> fastCounts);
-
- virtual ~PolymorphicCallStubRoutine();
-
- CallVariantList variants() const;
- CallEdgeList edges() const;
-
- bool visitWeak(RepatchBuffer&) override;
-
-protected:
- virtual void markRequiredObjectsInternal(SlotVisitor&) override;
-
-private:
- Vector<WriteBarrier<JSCell>, 2> m_variants;
- std::unique_ptr<uint32_t[]> m_fastCounts;
- Bag<PolymorphicCallNode> m_callNodes;
-};
-
-} // namespace JSC
-
-#endif // ENABLE(JIT)
-
-#endif // PolymorphicCallStubRoutine_h
-
</del></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/jit/Repatch.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -29,7 +29,6 @@
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">
</span><span class="cx"> #include "AccessorCallJITStubRoutine.h"
</span><del>-#include "BinarySwitch.h"
</del><span class="cx"> #include "CCallHelpers.h"
</span><span class="cx"> #include "DFGOperations.h"
</span><span class="cx"> #include "DFGSpeculativeJIT.h"
</span><span class="lines">@@ -1576,17 +1575,12 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static void linkSlowFor(
</span><del>- RepatchBuffer& repatchBuffer, VM* vm, CallLinkInfo& callLinkInfo, ThunkGenerator generator)
-{
- repatchBuffer.relink(
- callLinkInfo.callReturnLocation, vm->getCTIStub(generator).code());
-}
-
-static void linkSlowFor(
</del><span class="cx"> RepatchBuffer& repatchBuffer, VM* vm, CallLinkInfo& callLinkInfo,
</span><span class="cx"> CodeSpecializationKind kind, RegisterPreservationMode registers)
</span><span class="cx"> {
</span><del>- linkSlowFor(repatchBuffer, vm, callLinkInfo, virtualThunkGeneratorFor(kind, registers));
</del><ins>+ repatchBuffer.relink(
+ callLinkInfo.callReturnLocation,
+ vm->getCTIStub(virtualThunkGeneratorFor(kind, registers)).code());
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void linkFor(
</span><span class="lines">@@ -1598,6 +1592,10 @@
</span><span class="cx">
</span><span class="cx"> CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock();
</span><span class="cx">
</span><ins>+ // If you're being call-linked from a DFG caller then you obviously didn't get inlined.
+ if (calleeCodeBlock && JITCode::isOptimizingJIT(callerCodeBlock->jitType()))
+ calleeCodeBlock->m_shouldAlwaysBeInlined = false;
+
</ins><span class="cx"> VM* vm = callerCodeBlock->vm();
</span><span class="cx">
</span><span class="cx"> RepatchBuffer repatchBuffer(callerCodeBlock);
</span><span class="lines">@@ -1613,8 +1611,7 @@
</span><span class="cx"> calleeCodeBlock->linkIncomingCall(exec->callerFrame(), &callLinkInfo);
</span><span class="cx">
</span><span class="cx"> if (kind == CodeForCall) {
</span><del>- linkSlowFor(
- repatchBuffer, vm, callLinkInfo, linkPolymorphicCallThunkGeneratorFor(registers));
</del><ins>+ repatchBuffer.relink(callLinkInfo.callReturnLocation, vm->getCTIStub(linkClosureCallThunkGeneratorFor(registers)).code());
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1634,122 +1631,16 @@
</span><span class="cx"> linkSlowFor(repatchBuffer, vm, callLinkInfo, kind, registers);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-static void revertCall(
- RepatchBuffer& repatchBuffer, VM* vm, CallLinkInfo& callLinkInfo, ThunkGenerator generator)
-{
- repatchBuffer.revertJumpReplacementToBranchPtrWithPatch(
- RepatchBuffer::startOfBranchPtrWithPatchOnRegister(callLinkInfo.hotPathBegin),
- static_cast<MacroAssembler::RegisterID>(callLinkInfo.calleeGPR), 0);
- linkSlowFor(repatchBuffer, vm, callLinkInfo, generator);
- callLinkInfo.hasSeenShouldRepatch = false;
- callLinkInfo.callee.clear();
- callLinkInfo.stub.clear();
- if (callLinkInfo.isOnList())
- callLinkInfo.remove();
-}
-
-void unlinkFor(
- RepatchBuffer& repatchBuffer, CallLinkInfo& callLinkInfo,
- CodeSpecializationKind kind, RegisterPreservationMode registers)
-{
- if (Options::showDisassembly())
- dataLog("Unlinking call from ", callLinkInfo.callReturnLocation, " in request from ", pointerDump(repatchBuffer.codeBlock()), "\n");
-
- revertCall(
- repatchBuffer, repatchBuffer.codeBlock()->vm(), callLinkInfo,
- linkThunkGeneratorFor(kind, registers));
-}
-
-void linkVirtualFor(
- ExecState* exec, CallLinkInfo& callLinkInfo,
- CodeSpecializationKind kind, RegisterPreservationMode registers)
-{
- // FIXME: We could generate a virtual call stub here. This would lead to faster virtual calls
- // by eliminating the branch prediction bottleneck inside the shared virtual call thunk.
-
- CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock();
- VM* vm = callerCodeBlock->vm();
-
- if (shouldShowDisassemblyFor(callerCodeBlock))
- dataLog("Linking virtual call at ", *callerCodeBlock, " ", exec->callerFrame()->codeOrigin(), "\n");
-
- RepatchBuffer repatchBuffer(callerCodeBlock);
- revertCall(repatchBuffer, vm, callLinkInfo, virtualThunkGeneratorFor(kind, registers));
-}
-
-namespace {
-struct CallToCodePtr {
- CCallHelpers::Call call;
- MacroAssemblerCodePtr codePtr;
-};
-} // annonymous namespace
-
-void linkPolymorphicCall(
- ExecState* exec, CallLinkInfo& callLinkInfo, CallVariant newVariant,
</del><ins>+void linkClosureCall(
+ ExecState* exec, CallLinkInfo& callLinkInfo, CodeBlock* calleeCodeBlock,
+ ExecutableBase* executable, MacroAssemblerCodePtr codePtr,
</ins><span class="cx"> RegisterPreservationMode registers)
</span><span class="cx"> {
</span><del>- // Currently we can't do anything for non-function callees.
- // https://bugs.webkit.org/show_bug.cgi?id=140685
- if (!newVariant || !newVariant.executable()) {
- linkVirtualFor(exec, callLinkInfo, CodeForCall, registers);
- return;
- }
</del><ins>+ ASSERT(!callLinkInfo.stub);
</ins><span class="cx">
</span><span class="cx"> CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock();
</span><span class="cx"> VM* vm = callerCodeBlock->vm();
</span><span class="cx">
</span><del>- CallVariantList list;
- if (PolymorphicCallStubRoutine* stub = callLinkInfo.stub.get())
- list = stub->variants();
- else if (JSFunction* oldCallee = callLinkInfo.callee.get())
- list = CallVariantList{ CallVariant(oldCallee) };
-
- list = variantListWithVariant(list, newVariant);
-
- // If there are any closure calls then it makes sense to treat all of them as closure calls.
- // This makes switching on callee cheaper. It also produces profiling that's easier on the DFG;
- // the DFG doesn't really want to deal with a combination of closure and non-closure callees.
- bool isClosureCall = false;
- for (CallVariant variant : list) {
- if (variant.isClosureCall()) {
- list = despecifiedVariantList(list);
- isClosureCall = true;
- break;
- }
- }
-
- Vector<PolymorphicCallCase> callCases;
-
- // Figure out what our cases are.
- for (CallVariant variant : list) {
- CodeBlock* codeBlock;
- if (variant.executable()->isHostFunction())
- codeBlock = nullptr;
- else {
- codeBlock = jsCast<FunctionExecutable*>(variant.executable())->codeBlockForCall();
-
- // If we cannot handle a callee, assume that it's better for this whole thing to be a
- // virtual call.
- if (exec->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo.callType == CallLinkInfo::CallVarargs || callLinkInfo.callType == CallLinkInfo::ConstructVarargs) {
- linkVirtualFor(exec, callLinkInfo, CodeForCall, registers);
- return;
- }
- }
-
- callCases.append(PolymorphicCallCase(variant, codeBlock));
- }
-
- // If we are over the limit, just use a normal virtual call.
- unsigned maxPolymorphicCallVariantListSize;
- if (callerCodeBlock->jitType() == JITCode::topTierJIT())
- maxPolymorphicCallVariantListSize = Options::maxPolymorphicCallVariantListSizeForTopTier();
- else
- maxPolymorphicCallVariantListSize = Options::maxPolymorphicCallVariantListSize();
- if (list.size() > maxPolymorphicCallVariantListSize) {
- linkVirtualFor(exec, callLinkInfo, CodeForCall, registers);
- return;
- }
-
</del><span class="cx"> GPRReg calleeGPR = static_cast<GPRReg>(callLinkInfo.calleeGPR);
</span><span class="cx">
</span><span class="cx"> CCallHelpers stubJit(vm, callerCodeBlock);
</span><span class="lines">@@ -1764,82 +1655,33 @@
</span><span class="cx"> stubJit.abortWithReason(RepatchInsaneArgumentCount);
</span><span class="cx"> okArgumentCount.link(&stubJit);
</span><span class="cx"> }
</span><del>-
- GPRReg scratch = AssemblyHelpers::selectScratchGPR(calleeGPR);
- GPRReg comparisonValueGPR;
-
- if (isClosureCall) {
- // Verify that we have a function and stash the executable in scratch.
</del><span class="cx">
</span><span class="cx"> #if USE(JSVALUE64)
</span><del>- // We can safely clobber everything except the calleeGPR. We can't rely on tagMaskRegister
- // being set. So we do this the hard way.
- stubJit.move(MacroAssembler::TrustedImm64(TagMask), scratch);
- slowPath.append(stubJit.branchTest64(CCallHelpers::NonZero, calleeGPR, scratch));
</del><ins>+ // We can safely clobber everything except the calleeGPR. We can't rely on tagMaskRegister
+ // being set. So we do this the hard way.
+ GPRReg scratch = AssemblyHelpers::selectScratchGPR(calleeGPR);
+ stubJit.move(MacroAssembler::TrustedImm64(TagMask), scratch);
+ slowPath.append(stubJit.branchTest64(CCallHelpers::NonZero, calleeGPR, scratch));
</ins><span class="cx"> #else
</span><del>- // We would have already checked that the callee is a cell.
</del><ins>+ // We would have already checked that the callee is a cell.
</ins><span class="cx"> #endif
</span><span class="cx">
</span><del>- slowPath.append(
- stubJit.branch8(
- CCallHelpers::NotEqual,
- CCallHelpers::Address(calleeGPR, JSCell::typeInfoTypeOffset()),
- CCallHelpers::TrustedImm32(JSFunctionType)));
</del><ins>+ slowPath.append(
+ stubJit.branch8(
+ CCallHelpers::NotEqual,
+ CCallHelpers::Address(calleeGPR, JSCell::typeInfoTypeOffset()),
+ CCallHelpers::TrustedImm32(JSFunctionType)));
</ins><span class="cx">
</span><del>- stubJit.loadPtr(
</del><ins>+ slowPath.append(
+ stubJit.branchPtr(
+ CCallHelpers::NotEqual,
</ins><span class="cx"> CCallHelpers::Address(calleeGPR, JSFunction::offsetOfExecutable()),
</span><del>- scratch);
-
- comparisonValueGPR = scratch;
- } else
- comparisonValueGPR = calleeGPR;
</del><ins>+ CCallHelpers::TrustedImmPtr(executable)));
</ins><span class="cx">
</span><del>- Vector<int64_t> caseValues(callCases.size());
- Vector<CallToCodePtr> calls(callCases.size());
- std::unique_ptr<uint32_t[]> fastCounts;
</del><ins>+ AssemblyHelpers::Call call = stubJit.nearCall();
+ AssemblyHelpers::Jump done = stubJit.jump();
</ins><span class="cx">
</span><del>- if (callerCodeBlock->jitType() != JITCode::topTierJIT())
- fastCounts = std::make_unique<uint32_t[]>(callCases.size());
-
- for (size_t i = callCases.size(); i--;) {
- if (fastCounts)
- fastCounts[i] = 0;
-
- CallVariant variant = callCases[i].variant();
- if (isClosureCall)
- caseValues[i] = bitwise_cast<intptr_t>(variant.executable());
- else
- caseValues[i] = bitwise_cast<intptr_t>(variant.function());
- }
-
- GPRReg fastCountsBaseGPR =
- AssemblyHelpers::selectScratchGPR(calleeGPR, comparisonValueGPR, GPRInfo::regT3);
- stubJit.move(CCallHelpers::TrustedImmPtr(fastCounts.get()), fastCountsBaseGPR);
-
- BinarySwitch binarySwitch(comparisonValueGPR, caseValues, BinarySwitch::IntPtr);
- CCallHelpers::JumpList done;
- while (binarySwitch.advance(stubJit)) {
- size_t caseIndex = binarySwitch.caseIndex();
-
- CallVariant variant = callCases[caseIndex].variant();
-
- ASSERT(variant.executable()->hasJITCodeForCall());
- MacroAssemblerCodePtr codePtr =
- variant.executable()->generatedJITCodeForCall()->addressForCall(
- *vm, variant.executable(), ArityCheckNotRequired, registers);
-
- if (fastCounts) {
- stubJit.add32(
- CCallHelpers::TrustedImm32(1),
- CCallHelpers::Address(fastCountsBaseGPR, caseIndex * sizeof(uint32_t)));
- }
- calls[caseIndex].call = stubJit.nearCall();
- calls[caseIndex].codePtr = codePtr;
- done.append(stubJit.jump());
- }
-
</del><span class="cx"> slowPath.link(&stubJit);
</span><del>- binarySwitch.fallThrough().link(&stubJit);
</del><span class="cx"> stubJit.move(calleeGPR, GPRInfo::regT0);
</span><span class="cx"> #if USE(JSVALUE32_64)
</span><span class="cx"> stubJit.move(CCallHelpers::TrustedImm32(JSValue::CellTag), GPRInfo::regT1);
</span><span class="lines">@@ -1849,45 +1691,34 @@
</span><span class="cx">
</span><span class="cx"> stubJit.restoreReturnAddressBeforeReturn(GPRInfo::regT4);
</span><span class="cx"> AssemblyHelpers::Jump slow = stubJit.jump();
</span><del>-
</del><ins>+
</ins><span class="cx"> LinkBuffer patchBuffer(*vm, stubJit, callerCodeBlock);
</span><span class="cx">
</span><del>- RELEASE_ASSERT(callCases.size() == calls.size());
- for (CallToCodePtr callToCodePtr : calls) {
- patchBuffer.link(
- callToCodePtr.call, FunctionPtr(callToCodePtr.codePtr.executableAddress()));
- }
</del><ins>+ patchBuffer.link(call, FunctionPtr(codePtr.executableAddress()));
</ins><span class="cx"> if (JITCode::isOptimizingJIT(callerCodeBlock->jitType()))
</span><span class="cx"> patchBuffer.link(done, callLinkInfo.callReturnLocation.labelAtOffset(0));
</span><span class="cx"> else
</span><span class="cx"> patchBuffer.link(done, callLinkInfo.hotPathOther.labelAtOffset(0));
</span><del>- patchBuffer.link(slow, CodeLocationLabel(vm->getCTIStub(linkPolymorphicCallThunkGeneratorFor(registers)).code()));
</del><ins>+ patchBuffer.link(slow, CodeLocationLabel(vm->getCTIStub(virtualThunkGeneratorFor(CodeForCall, registers)).code()));
</ins><span class="cx">
</span><del>- RefPtr<PolymorphicCallStubRoutine> stubRoutine = adoptRef(new PolymorphicCallStubRoutine(
</del><ins>+ RefPtr<ClosureCallStubRoutine> stubRoutine = adoptRef(new ClosureCallStubRoutine(
</ins><span class="cx"> FINALIZE_CODE_FOR(
</span><span class="cx"> callerCodeBlock, patchBuffer,
</span><del>- ("Polymorphic call stub for %s, return point %p, targets %s",
</del><ins>+ ("Closure call stub for %s, return point %p, target %p (%s)",
</ins><span class="cx"> toCString(*callerCodeBlock).data(), callLinkInfo.callReturnLocation.labelAtOffset(0).executableAddress(),
</span><del>- toCString(listDump(callCases)).data())),
- *vm, callerCodeBlock->ownerExecutable(), exec->callerFrame(), callLinkInfo, callCases,
- WTF::move(fastCounts)));
</del><ins>+ codePtr.executableAddress(), toCString(pointerDump(calleeCodeBlock)).data())),
+ *vm, callerCodeBlock->ownerExecutable(), executable));
</ins><span class="cx">
</span><span class="cx"> RepatchBuffer repatchBuffer(callerCodeBlock);
</span><span class="cx">
</span><span class="cx"> repatchBuffer.replaceWithJump(
</span><span class="cx"> RepatchBuffer::startOfBranchPtrWithPatchOnRegister(callLinkInfo.hotPathBegin),
</span><span class="cx"> CodeLocationLabel(stubRoutine->code().code()));
</span><del>- // This is weird. The original slow path should no longer be reachable.
</del><span class="cx"> linkSlowFor(repatchBuffer, vm, callLinkInfo, CodeForCall, registers);
</span><span class="cx">
</span><del>- // If there had been a previous stub routine, that one will die as soon as the GC runs and sees
- // that it's no longer on stack.
</del><span class="cx"> callLinkInfo.stub = stubRoutine.release();
</span><span class="cx">
</span><del>- // The call link info no longer has a call cache apart from the jump to the polymorphic call
- // stub.
- if (callLinkInfo.isOnList())
- callLinkInfo.remove();
</del><ins>+ ASSERT(!calleeCodeBlock || calleeCodeBlock->isIncomingCallAlreadyLinked(&callLinkInfo));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void resetGetByID(RepatchBuffer& repatchBuffer, StructureStubInfo& stubInfo)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/jit/Repatch.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011, 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011 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">@@ -29,7 +29,6 @@
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">
</span><span class="cx"> #include "CCallHelpers.h"
</span><del>-#include "CallVariant.h"
</del><span class="cx"> #include "JITOperations.h"
</span><span class="cx">
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -42,9 +41,7 @@
</span><span class="cx"> void repatchIn(ExecState*, JSCell*, const Identifier&, bool wasFound, const PropertySlot&, StructureStubInfo&);
</span><span class="cx"> void linkFor(ExecState*, CallLinkInfo&, CodeBlock*, JSFunction* callee, MacroAssemblerCodePtr, CodeSpecializationKind, RegisterPreservationMode);
</span><span class="cx"> void linkSlowFor(ExecState*, CallLinkInfo&, CodeSpecializationKind, RegisterPreservationMode);
</span><del>-void unlinkFor(RepatchBuffer&, CallLinkInfo&, CodeSpecializationKind, RegisterPreservationMode);
-void linkVirtualFor(ExecState*, CallLinkInfo&, CodeSpecializationKind, RegisterPreservationMode);
-void linkPolymorphicCall(ExecState*, CallLinkInfo&, CallVariant, RegisterPreservationMode);
</del><ins>+void linkClosureCall(ExecState*, CallLinkInfo&, CodeBlock*, ExecutableBase*, MacroAssemblerCodePtr, RegisterPreservationMode);
</ins><span class="cx"> void resetGetByID(RepatchBuffer&, StructureStubInfo&);
</span><span class="cx"> void resetPutByID(RepatchBuffer&, StructureStubInfo&);
</span><span class="cx"> void resetIn(RepatchBuffer&, StructureStubInfo&);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitThunkGeneratorscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -137,27 +137,27 @@
</span><span class="cx"> return linkForThunkGenerator(vm, CodeForConstruct, MustPreserveRegisters);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-static MacroAssemblerCodeRef linkPolymorphicCallForThunkGenerator(
</del><ins>+static MacroAssemblerCodeRef linkClosureCallForThunkGenerator(
</ins><span class="cx"> VM* vm, RegisterPreservationMode registers)
</span><span class="cx"> {
</span><span class="cx"> CCallHelpers jit(vm);
</span><span class="cx">
</span><del>- slowPathFor(jit, vm, operationLinkPolymorphicCallFor(registers));
</del><ins>+ slowPathFor(jit, vm, operationLinkClosureCallFor(registers));
</ins><span class="cx">
</span><span class="cx"> LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
</span><del>- return FINALIZE_CODE(patchBuffer, ("Link polymorphic call %s slow path thunk", registers == MustPreserveRegisters ? " that preserves registers" : ""));
</del><ins>+ return FINALIZE_CODE(patchBuffer, ("Link closure call %s slow path thunk", registers == MustPreserveRegisters ? " that preserves registers" : ""));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // For closure optimizations, we only include calls, since if you're using closures for
</span><span class="cx"> // object construction then you're going to lose big time anyway.
</span><del>-MacroAssemblerCodeRef linkPolymorphicCallThunkGenerator(VM* vm)
</del><ins>+MacroAssemblerCodeRef linkClosureCallThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><del>- return linkPolymorphicCallForThunkGenerator(vm, RegisterPreservationNotRequired);
</del><ins>+ return linkClosureCallForThunkGenerator(vm, RegisterPreservationNotRequired);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-MacroAssemblerCodeRef linkPolymorphicCallThatPreservesRegsThunkGenerator(VM* vm)
</del><ins>+MacroAssemblerCodeRef linkClosureCallThatPreservesRegsThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><del>- return linkPolymorphicCallForThunkGenerator(vm, MustPreserveRegisters);
</del><ins>+ return linkClosureCallForThunkGenerator(vm, MustPreserveRegisters);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static MacroAssemblerCodeRef virtualForThunkGenerator(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitThunkGeneratorsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ThunkGenerators.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -65,16 +65,16 @@
</span><span class="cx"> return 0;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-MacroAssemblerCodeRef linkPolymorphicCallThunkGenerator(VM*);
-MacroAssemblerCodeRef linkPolymorphicCallThatPreservesRegsThunkGenerator(VM*);
</del><ins>+MacroAssemblerCodeRef linkClosureCallThunkGenerator(VM*);
+MacroAssemblerCodeRef linkClosureCallThatPreservesRegsThunkGenerator(VM*);
</ins><span class="cx">
</span><del>-inline ThunkGenerator linkPolymorphicCallThunkGeneratorFor(RegisterPreservationMode registers)
</del><ins>+inline ThunkGenerator linkClosureCallThunkGeneratorFor(RegisterPreservationMode registers)
</ins><span class="cx"> {
</span><span class="cx"> switch (registers) {
</span><span class="cx"> case RegisterPreservationNotRequired:
</span><del>- return linkPolymorphicCallThunkGenerator;
</del><ins>+ return linkClosureCallThunkGenerator;
</ins><span class="cx"> case MustPreserveRegisters:
</span><del>- return linkPolymorphicCallThatPreservesRegsThunkGenerator;
</del><ins>+ return linkClosureCallThatPreservesRegsThunkGenerator;
</ins><span class="cx"> }
</span><span class="cx"> RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> return 0;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -332,7 +332,6 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx"> default:
</span><del>- dataLog("Unexpected code block in LLInt: ", *codeBlock, "\n");
</del><span class="cx"> RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> return false;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -170,11 +170,12 @@
</span><span class="cx"> v(bool, enablePolyvariantDevirtualization, true) \
</span><span class="cx"> v(bool, enablePolymorphicAccessInlining, true) \
</span><span class="cx"> v(bool, enablePolymorphicCallInlining, true) \
</span><del>- v(unsigned, maxPolymorphicCallVariantListSize, 15) \
- v(unsigned, maxPolymorphicCallVariantListSizeForTopTier, 5) \
- v(unsigned, maxPolymorphicCallVariantsForInlining, 5) \
</del><ins>+ v(bool, callStatusShouldUseCallEdgeProfile, true) \
+ v(bool, callEdgeProfileReallyProcessesLog, true) \
+ v(bool, baselineDoesCallEdgeProfiling, false) \
+ v(bool, dfgDoesCallEdgeProfiling, true) \
+ v(bool, enableCallEdgeProfiling, true) \
</ins><span class="cx"> v(unsigned, frequentCallThreshold, 2) \
</span><del>- v(double, minimumCallToKnownRate, 0.51) \
</del><span class="cx"> v(bool, optimizeNativeCalls, false) \
</span><span class="cx"> v(bool, enableObjectAllocationSinking, true) \
</span><span class="cx"> \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -369,6 +369,13 @@
</span><span class="cx"> return sharedInstance;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+CallEdgeLog& VM::ensureCallEdgeLog()
+{
+ if (!callEdgeLog)
+ callEdgeLog = std::make_unique<CallEdgeLog>();
+ return *callEdgeLog;
+}
+
</ins><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> static ThunkGenerator thunkGeneratorForIntrinsic(Intrinsic intrinsic)
</span><span class="cx"> {
</span><span class="lines">@@ -452,6 +459,9 @@
</span><span class="cx">
</span><span class="cx"> void VM::prepareToDiscardCode()
</span><span class="cx"> {
</span><ins>+ if (callEdgeLog)
+ callEdgeLog->processLog();
+
</ins><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx"> for (unsigned i = DFG::numberOfWorklists(); i--;) {
</span><span class="cx"> if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i))
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (179391 => 179392)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2015-01-30 04:23:51 UTC (rev 179391)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2015-01-30 04:28:36 UTC (rev 179392)
</span><span class="lines">@@ -73,6 +73,7 @@
</span><span class="cx">
</span><span class="cx"> class ArityCheckFailReturnThunks;
</span><span class="cx"> class BuiltinExecutables;
</span><ins>+class CallEdgeLog;
</ins><span class="cx"> class CodeBlock;
</span><span class="cx"> class CodeCache;
</span><span class="cx"> class CommonIdentifiers;
</span><span class="lines">@@ -237,6 +238,9 @@
</span><span class="cx"> std::unique_ptr<DFG::LongLivedState> dfgState;
</span><span class="cx"> #endif // ENABLE(DFG_JIT)
</span><span class="cx">
</span><ins>+ std::unique_ptr<CallEdgeLog> callEdgeLog;
+ CallEdgeLog& ensureCallEdgeLog();
+
</ins><span class="cx"> VMType vmType;
</span><span class="cx"> ClientData* clientData;
</span><span class="cx"> VMEntryFrame* topVMEntryFrame;
</span></span></pre>
</div>
</div>
</body>
</html>