<!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>[215073] 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/215073">215073</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2017-04-06 17:26:53 -0700 (Thu, 06 Apr 2017)</dd>
</dl>
<h3>Log Message</h3>
<pre>Rename allocateStack to allocateStackByGraphColoring.
Rubber stamped by Saam Barati.
* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* b3/air/AirAllocateStack.cpp: Removed.
* b3/air/AirAllocateStack.h: Removed.
* b3/air/AirAllocateStackByGraphColoring.cpp: Copied from Source/JavaScriptCore/b3/air/AirAllocateStack.cpp.
(JSC::B3::Air::allocateStackByGraphColoring):
(JSC::B3::Air::allocateStack): Deleted.
* b3/air/AirAllocateStackByGraphColoring.h: Copied from Source/JavaScriptCore/b3/air/AirAllocateStack.h.
* b3/air/AirGenerate.cpp:
(JSC::B3::Air::prepareForGeneration):</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="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirGeneratecpp">trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreb3airAirAllocateStackByGraphColoringcpp">trunk/Source/JavaScriptCore/b3/air/AirAllocateStackByGraphColoring.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirAllocateStackByGraphColoringh">trunk/Source/JavaScriptCore/b3/air/AirAllocateStackByGraphColoring.h</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreb3airAirAllocateStackcpp">trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirAllocateStackh">trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.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 (215072 => 215073)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2017-04-07 00:16:18 UTC (rev 215072)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2017-04-07 00:26:53 UTC (rev 215073)
</span><span class="lines">@@ -75,7 +75,7 @@
</span><span class="cx">
</span><span class="cx"> b3/air/AirAllocateRegistersByGraphColoring.cpp
</span><span class="cx"> b3/air/AirAllocateRegistersByLinearScan.cpp
</span><del>- b3/air/AirAllocateStack.cpp
</del><ins>+ b3/air/AirAllocateStackByGraphColoring.cpp
</ins><span class="cx"> b3/air/AirArg.cpp
</span><span class="cx"> b3/air/AirBasicBlock.cpp
</span><span class="cx"> b3/air/AirBlockInsertionSet.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (215072 => 215073)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-04-07 00:16:18 UTC (rev 215072)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-04-07 00:26:53 UTC (rev 215073)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2017-04-06 Filip Pizlo <fpizlo@apple.com>
+
+ Rename allocateStack to allocateStackByGraphColoring.
+
+ Rubber stamped by Saam Barati.
+
+ * CMakeLists.txt:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * b3/air/AirAllocateStack.cpp: Removed.
+ * b3/air/AirAllocateStack.h: Removed.
+ * b3/air/AirAllocateStackByGraphColoring.cpp: Copied from Source/JavaScriptCore/b3/air/AirAllocateStack.cpp.
+ (JSC::B3::Air::allocateStackByGraphColoring):
+ (JSC::B3::Air::allocateStack): Deleted.
+ * b3/air/AirAllocateStackByGraphColoring.h: Copied from Source/JavaScriptCore/b3/air/AirAllocateStack.h.
+ * b3/air/AirGenerate.cpp:
+ (JSC::B3::Air::prepareForGeneration):
+
</ins><span class="cx"> 2017-04-06 Michael Saboff <msaboff@apple.com>
</span><span class="cx">
</span><span class="cx"> Cannot Object.seal() or Object.freeze() global "this"
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (215072 => 215073)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-04-07 00:16:18 UTC (rev 215072)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-04-07 00:26:53 UTC (rev 215073)
</span><span class="lines">@@ -934,8 +934,8 @@
</span><span class="cx">                 0FEC85451BDACDAC0080FF74 /* B3ValueInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84FB1BDACDAC0080FF74 /* B3ValueInlines.h */; };
</span><span class="cx">                 0FEC85461BDACDAC0080FF74 /* B3ValueRep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC84FC1BDACDAC0080FF74 /* B3ValueRep.cpp */; };
</span><span class="cx">                 0FEC85471BDACDAC0080FF74 /* B3ValueRep.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84FD1BDACDAC0080FF74 /* B3ValueRep.h */; };
</span><del>-                0FEC856D1BDACDC70080FF74 /* AirAllocateStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC85481BDACDC70080FF74 /* AirAllocateStack.cpp */; };
-                0FEC856E1BDACDC70080FF74 /* AirAllocateStack.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC85491BDACDC70080FF74 /* AirAllocateStack.h */; };
</del><ins>+                0FEC856D1BDACDC70080FF74 /* AirAllocateStackByGraphColoring.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC85481BDACDC70080FF74 /* AirAllocateStackByGraphColoring.cpp */; };
+                0FEC856E1BDACDC70080FF74 /* AirAllocateStackByGraphColoring.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC85491BDACDC70080FF74 /* AirAllocateStackByGraphColoring.h */; };
</ins><span class="cx">                 0FEC856F1BDACDC70080FF74 /* AirArg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC854A1BDACDC70080FF74 /* AirArg.cpp */; };
</span><span class="cx">                 0FEC85701BDACDC70080FF74 /* AirArg.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC854B1BDACDC70080FF74 /* AirArg.h */; };
</span><span class="cx">                 0FEC85711BDACDC70080FF74 /* AirBasicBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC854C1BDACDC70080FF74 /* AirBasicBlock.cpp */; };
</span><span class="lines">@@ -3483,8 +3483,8 @@
</span><span class="cx">                 0FEC84FB1BDACDAC0080FF74 /* B3ValueInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3ValueInlines.h; path = b3/B3ValueInlines.h; sourceTree = "<group>"; };
</span><span class="cx">                 0FEC84FC1BDACDAC0080FF74 /* B3ValueRep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3ValueRep.cpp; path = b3/B3ValueRep.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0FEC84FD1BDACDAC0080FF74 /* B3ValueRep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3ValueRep.h; path = b3/B3ValueRep.h; sourceTree = "<group>"; };
</span><del>-                0FEC85481BDACDC70080FF74 /* AirAllocateStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirAllocateStack.cpp; path = b3/air/AirAllocateStack.cpp; sourceTree = "<group>"; };
-                0FEC85491BDACDC70080FF74 /* AirAllocateStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirAllocateStack.h; path = b3/air/AirAllocateStack.h; sourceTree = "<group>"; };
</del><ins>+                0FEC85481BDACDC70080FF74 /* AirAllocateStackByGraphColoring.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirAllocateStackByGraphColoring.cpp; path = b3/air/AirAllocateStackByGraphColoring.cpp; sourceTree = "<group>"; };
+                0FEC85491BDACDC70080FF74 /* AirAllocateStackByGraphColoring.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirAllocateStackByGraphColoring.h; path = b3/air/AirAllocateStackByGraphColoring.h; sourceTree = "<group>"; };
</ins><span class="cx">                 0FEC854A1BDACDC70080FF74 /* AirArg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirArg.cpp; path = b3/air/AirArg.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0FEC854B1BDACDC70080FF74 /* AirArg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirArg.h; path = b3/air/AirArg.h; sourceTree = "<group>"; };
</span><span class="cx">                 0FEC854C1BDACDC70080FF74 /* AirBasicBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirBasicBlock.cpp; path = b3/air/AirBasicBlock.cpp; sourceTree = "<group>"; };
</span><span class="lines">@@ -5573,8 +5573,8 @@
</span><span class="cx">                                 7965C2151E5D799600B7591D /* AirAllocateRegistersByGraphColoring.h */,
</span><span class="cx">                                 0F2AC5681E8A0BD10001EE3F /* AirAllocateRegistersByLinearScan.cpp */,
</span><span class="cx">                                 0F2AC5691E8A0BD10001EE3F /* AirAllocateRegistersByLinearScan.h */,
</span><del>-                                0FEC85481BDACDC70080FF74 /* AirAllocateStack.cpp */,
-                                0FEC85491BDACDC70080FF74 /* AirAllocateStack.h */,
</del><ins>+                                0FEC85481BDACDC70080FF74 /* AirAllocateStackByGraphColoring.cpp */,
+                                0FEC85491BDACDC70080FF74 /* AirAllocateStackByGraphColoring.h */,
</ins><span class="cx">                                 0FEC854A1BDACDC70080FF74 /* AirArg.cpp */,
</span><span class="cx">                                 0FEC854B1BDACDC70080FF74 /* AirArg.h */,
</span><span class="cx">                                 0F64EAF21C4ECD0600621E9B /* AirArgInlines.h */,
</span><span class="lines">@@ -8089,7 +8089,7 @@
</span><span class="cx">                                 AD4937C41DDBE6140077C807 /* AbstractModuleRecord.h in Headers */,
</span><span class="cx">                                 0F55F0F514D1063C00AC7649 /* AbstractPC.h in Headers */,
</span><span class="cx">                                 5370B4F61BF26205005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h in Headers */,
</span><del>-                                0FEC856E1BDACDC70080FF74 /* AirAllocateStack.h in Headers */,
</del><ins>+                                0FEC856E1BDACDC70080FF74 /* AirAllocateStackByGraphColoring.h in Headers */,
</ins><span class="cx">                                 0FEC85701BDACDC70080FF74 /* AirArg.h in Headers */,
</span><span class="cx">                                 0F64EAF31C4ECD0600621E9B /* AirArgInlines.h in Headers */,
</span><span class="cx">                                 0FEC85721BDACDC70080FF74 /* AirBasicBlock.h in Headers */,
</span><span class="lines">@@ -9982,7 +9982,7 @@
</span><span class="cx">                                 AD4937C31DDBE6140077C807 /* AbstractModuleRecord.cpp in Sources */,
</span><span class="cx">                                 0F55F0F414D1063900AC7649 /* AbstractPC.cpp in Sources */,
</span><span class="cx">                                 5370B4F51BF26202005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp in Sources */,
</span><del>-                                0FEC856D1BDACDC70080FF74 /* AirAllocateStack.cpp in Sources */,
</del><ins>+                                0FEC856D1BDACDC70080FF74 /* AirAllocateStackByGraphColoring.cpp in Sources */,
</ins><span class="cx">                                 0FEC856F1BDACDC70080FF74 /* AirArg.cpp in Sources */,
</span><span class="cx">                                 0FEC85711BDACDC70080FF74 /* AirBasicBlock.cpp in Sources */,
</span><span class="cx">                                 0F6183291C45BF070072450B /* AirCCallingConvention.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirAllocateStackcpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp (215072 => 215073)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp        2017-04-07 00:16:18 UTC (rev 215072)
+++ trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp        2017-04-07 00:26:53 UTC (rev 215073)
</span><span class="lines">@@ -1,464 +0,0 @@
</span><del>-/*
- * Copyright (C) 2015-2017 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 "AirAllocateStack.h"
-
-#if ENABLE(B3_JIT)
-
-#include "AirArgInlines.h"
-#include "AirCode.h"
-#include "AirInsertionSet.h"
-#include "AirInstInlines.h"
-#include "AirLiveness.h"
-#include "AirPhaseScope.h"
-#include "StackAlignment.h"
-#include <wtf/ListDump.h>
-
-namespace JSC { namespace B3 { namespace Air {
-
-namespace {
-
-const bool verbose = false;
-
-bool attemptAssignment(
- StackSlot* slot, intptr_t offsetFromFP, const Vector<StackSlot*>& otherSlots)
-{
- if (verbose)
- dataLog("Attempting to assign ", pointerDump(slot), " to ", offsetFromFP, " with interference ", pointerListDump(otherSlots), "\n");
-
- // Need to align it to the slot's desired alignment.
- offsetFromFP = -WTF::roundUpToMultipleOf(slot->alignment(), -offsetFromFP);
-
- for (StackSlot* otherSlot : otherSlots) {
- if (!otherSlot->offsetFromFP())
- continue;
- bool overlap = WTF::rangesOverlap(
- offsetFromFP,
- offsetFromFP + static_cast<intptr_t>(slot->byteSize()),
- otherSlot->offsetFromFP(),
- otherSlot->offsetFromFP() + static_cast<intptr_t>(otherSlot->byteSize()));
- if (overlap)
- return false;
- }
-
- if (verbose)
- dataLog("Assigned ", pointerDump(slot), " to ", offsetFromFP, "\n");
- slot->setOffsetFromFP(offsetFromFP);
- return true;
-}
-
-void assign(StackSlot* slot, const Vector<StackSlot*>& otherSlots)
-{
- if (verbose)
- dataLog("Attempting to assign ", pointerDump(slot), " with interference ", pointerListDump(otherSlots), "\n");
-
- if (attemptAssignment(slot, -static_cast<intptr_t>(slot->byteSize()), otherSlots))
- return;
-
- for (StackSlot* otherSlot : otherSlots) {
- if (!otherSlot->offsetFromFP())
- continue;
- bool didAssign = attemptAssignment(
- slot, otherSlot->offsetFromFP() - static_cast<intptr_t>(slot->byteSize()), otherSlots);
- if (didAssign)
- return;
- }
-
- RELEASE_ASSERT_NOT_REACHED();
-}
-
-struct CoalescableMove {
- CoalescableMove()
- {
- }
-
- CoalescableMove(StackSlot* src, StackSlot* dst, double frequency)
- : src(src)
- , dst(dst)
- , frequency(frequency)
- {
- }
-
- bool operator==(const CoalescableMove& other) const
- {
- return src == other.src
- && dst == other.dst
- && frequency == other.frequency;
- }
-
- bool operator!=(const CoalescableMove& other) const
- {
- return !(*this == other);
- }
-
- explicit operator bool() const
- {
- return *this != CoalescableMove();
- }
-
- void dump(PrintStream& out) const
- {
- out.print(pointerDump(src), "->", pointerDump(dst), "(", frequency, ")");
- }
-
- StackSlot* src { nullptr };
- StackSlot* dst { nullptr };
- double frequency { PNaN };
-};
-
-} // anonymous namespace
-
-void allocateStack(Code& code)
-{
- PhaseScope phaseScope(code, "allocateStack");
-
- // Allocate all of the escaped slots in order. This is kind of a crazy algorithm to allow for
- // the possibility of stack slots being assigned frame offsets before we even get here.
- ASSERT(!code.frameSize());
- Vector<StackSlot*> assignedEscapedStackSlots;
- Vector<StackSlot*> escapedStackSlotsWorklist;
- for (StackSlot* slot : code.stackSlots()) {
- if (slot->isLocked()) {
- if (slot->offsetFromFP())
- assignedEscapedStackSlots.append(slot);
- else
- escapedStackSlotsWorklist.append(slot);
- } else {
- // It would be super strange to have an unlocked stack slot that has an offset already.
- ASSERT(!slot->offsetFromFP());
- }
- }
- // This is a fairly expensive loop, but it's OK because we'll usually only have a handful of
- // escaped stack slots.
- while (!escapedStackSlotsWorklist.isEmpty()) {
- StackSlot* slot = escapedStackSlotsWorklist.takeLast();
- assign(slot, assignedEscapedStackSlots);
- assignedEscapedStackSlots.append(slot);
- }
-
- // Now we handle the spill slots.
- StackSlotLiveness liveness(code);
- IndexMap<StackSlot*, HashSet<StackSlot*>> interference(code.stackSlots().size());
- Vector<StackSlot*> slots;
-
- // We will perform some spill coalescing. To make that effective, we need to be able to identify
- // coalescable moves and handle them specially in interference analysis.
- auto isCoalescableMove = [&] (Inst& inst) -> bool {
- Width width;
- switch (inst.kind.opcode) {
- case Move:
- width = pointerWidth();
- break;
- case Move32:
- case MoveFloat:
- width = Width32;
- break;
- case MoveDouble:
- width = Width64;
- break;
- default:
- return false;
- }
-
- if (!Options::coalesceSpillSlots())
- return false;
-
- if (inst.args.size() != 3)
- return false;
-
- for (unsigned i = 0; i < 2; ++i) {
- Arg arg = inst.args[i];
- if (!arg.isStack())
- return false;
- StackSlot* slot = arg.stackSlot();
- if (slot->kind() != StackSlotKind::Spill)
- return false;
- if (slot->byteSize() != bytes(width))
- return false;
- }
-
- return true;
- };
-
- auto isUselessMove = [&] (Inst& inst) -> bool {
- return isCoalescableMove(inst) && inst.args[0] == inst.args[1];
- };
-
- auto addEdge = [&] (StackSlot* a, StackSlot* b) {
- interference[a].add(b);
- interference[b].add(a);
- };
-
- Vector<CoalescableMove> coalescableMoves;
-
- for (BasicBlock* block : code) {
- StackSlotLiveness::LocalCalc localCalc(liveness, block);
-
- auto interfere = [&] (unsigned instIndex) {
- if (verbose)
- dataLog("Interfering: ", WTF::pointerListDump(localCalc.live()), "\n");
-
- Inst* prevInst = block->get(instIndex);
- Inst* nextInst = block->get(instIndex + 1);
- if (prevInst && isCoalescableMove(*prevInst)) {
- CoalescableMove move(prevInst->args[0].stackSlot(), prevInst->args[1].stackSlot(), block->frequency());
-
- coalescableMoves.append(move);
-
- for (StackSlot* otherSlot : localCalc.live()) {
- if (otherSlot != move.src)
- addEdge(move.dst, otherSlot);
- }
-
- prevInst = nullptr;
- }
- Inst::forEachDef<Arg>(
- prevInst, nextInst,
- [&] (Arg& arg, Arg::Role, Bank, Width) {
- if (!arg.isStack())
- return;
- StackSlot* slot = arg.stackSlot();
- if (slot->kind() != StackSlotKind::Spill)
- return;
-
- for (StackSlot* otherSlot : localCalc.live())
- addEdge(slot, otherSlot);
- });
- };
-
- for (unsigned instIndex = block->size(); instIndex--;) {
- if (verbose)
- dataLog("Analyzing: ", block->at(instIndex), "\n");
-
- // Kill dead stores. For simplicity we say that a store is killable if it has only late
- // defs and those late defs are to things that are dead right now. We only do that
- // because that's the only kind of dead stack store we will see here.
- Inst& inst = block->at(instIndex);
- if (!inst.hasNonArgEffects()) {
- bool ok = true;
- inst.forEachArg(
- [&] (Arg& arg, Arg::Role role, Bank, Width) {
- if (Arg::isEarlyDef(role)) {
- ok = false;
- return;
- }
- if (!Arg::isLateDef(role))
- return;
- if (!arg.isStack()) {
- ok = false;
- return;
- }
- StackSlot* slot = arg.stackSlot();
- if (slot->kind() != StackSlotKind::Spill) {
- ok = false;
- return;
- }
-
- if (localCalc.isLive(slot)) {
- ok = false;
- return;
- }
- });
- if (ok)
- inst = Inst();
- }
-
- interfere(instIndex);
- localCalc.execute(instIndex);
- }
- interfere(-1);
-
- block->insts().removeAllMatching(
- [&] (const Inst& inst) -> bool {
- return !inst;
- });
- }
-
- if (verbose) {
- for (StackSlot* slot : code.stackSlots())
- dataLog("Interference of ", pointerDump(slot), ": ", pointerListDump(interference[slot]), "\n");
- }
-
- // Now try to coalesce some moves.
- std::sort(
- coalescableMoves.begin(), coalescableMoves.end(),
- [&] (CoalescableMove& a, CoalescableMove& b) -> bool {
- return a.frequency > b.frequency;
- });
-
- IndexMap<StackSlot*, StackSlot*> remappedStackSlots(code.stackSlots().size());
- auto remap = [&] (StackSlot* slot) -> StackSlot* {
- if (!slot)
- return nullptr;
- for (;;) {
- StackSlot* remappedSlot = remappedStackSlots[slot];
- if (!remappedSlot)
- return slot;
- slot = remappedSlot;
- }
- };
-
- for (CoalescableMove& move : coalescableMoves) {
- move.src = remap(move.src);
- move.dst = remap(move.dst);
- if (move.src == move.dst)
- continue;
- if (interference[move.src].contains(move.dst))
- continue;
-
- StackSlot* slotToKill = move.src;
- StackSlot* slotToKeep = move.dst;
-
- remappedStackSlots[slotToKill] = slotToKeep;
- for (StackSlot* interferingSlot : interference[slotToKill]) {
- if (interferingSlot == slotToKill)
- continue;
- interference[interferingSlot].remove(slotToKill);
- interference[interferingSlot].add(slotToKeep);
- }
- interference[slotToKeep].add(interference[slotToKill].begin(), interference[slotToKill].end());
- interference[slotToKill].clear();
- }
-
- for (BasicBlock* block : code) {
- for (Inst& inst : *block) {
- for (Arg& arg : inst.args) {
- if (arg.isStack())
- arg = Arg::stack(remap(arg.stackSlot()), arg.offset());
- }
- if (isUselessMove(inst))
- inst = Inst();
- }
- }
-
- // Now we assign stack locations. At its heart this algorithm is just first-fit. For each
- // StackSlot we just want to find the offsetFromFP that is closest to zero while ensuring no
- // overlap with other StackSlots that this overlaps with.
- Vector<StackSlot*> otherSlots = assignedEscapedStackSlots;
- for (StackSlot* slot : code.stackSlots()) {
- if (remappedStackSlots[slot])
- continue;
-
- if (slot->offsetFromFP()) {
- // Already assigned an offset.
- continue;
- }
-
- HashSet<StackSlot*>& interferingSlots = interference[slot];
- otherSlots.resize(assignedEscapedStackSlots.size());
- otherSlots.resize(assignedEscapedStackSlots.size() + interferingSlots.size());
- unsigned nextIndex = assignedEscapedStackSlots.size();
- for (StackSlot* otherSlot : interferingSlots)
- otherSlots[nextIndex++] = otherSlot;
-
- assign(slot, otherSlots);
- }
-
- // Figure out how much stack we're using for stack slots.
- unsigned frameSizeForStackSlots = 0;
- for (StackSlot* slot : code.stackSlots()) {
- frameSizeForStackSlots = std::max(
- frameSizeForStackSlots,
- static_cast<unsigned>(-slot->offsetFromFP()));
- }
-
- frameSizeForStackSlots = WTF::roundUpToMultipleOf(stackAlignmentBytes(), frameSizeForStackSlots);
-
- // Now we need to deduce how much argument area we need.
- for (BasicBlock* block : code) {
- for (Inst& inst : *block) {
- for (Arg& arg : inst.args) {
- if (arg.isCallArg()) {
- // For now, we assume that we use 8 bytes of the call arg. But that's not
- // such an awesome assumption.
- // FIXME: https://bugs.webkit.org/show_bug.cgi?id=150454
- ASSERT(arg.offset() >= 0);
- code.requestCallArgAreaSizeInBytes(arg.offset() + 8);
- }
- }
- }
- }
-
- code.setFrameSize(frameSizeForStackSlots + code.callArgAreaSizeInBytes());
-
- // Finally, transform the code to use Addr's instead of StackSlot's. This is a lossless
- // transformation since we can search the StackSlots array to figure out which StackSlot any
- // offset-from-FP refers to.
-
- // FIXME: This may produce addresses that aren't valid if we end up with a ginormous stack frame.
- // We would have to scavenge for temporaries if this happened. Fortunately, this case will be
- // extremely rare so we can do crazy things when it arises.
- // https://bugs.webkit.org/show_bug.cgi?id=152530
-
- InsertionSet insertionSet(code);
- for (BasicBlock* block : code) {
- for (unsigned instIndex = 0; instIndex < block->size(); ++instIndex) {
- Inst& inst = block->at(instIndex);
- inst.forEachArg(
- [&] (Arg& arg, Arg::Role role, Bank, Width width) {
- auto stackAddr = [&] (int32_t offset) -> Arg {
- return Arg::stackAddr(offset, code.frameSize(), width);
- };
-
- switch (arg.kind()) {
- case Arg::Stack: {
- StackSlot* slot = arg.stackSlot();
- if (Arg::isZDef(role)
- && slot->kind() == StackSlotKind::Spill
- && slot->byteSize() > bytes(width)) {
- // Currently we only handle this simple case because it's the only one
- // that arises: ZDef's are only 32-bit right now. So, when we hit these
- // assertions it means that we need to implement those other kinds of
- // zero fills.
- RELEASE_ASSERT(slot->byteSize() == 8);
- RELEASE_ASSERT(width == Width32);
-
- RELEASE_ASSERT(isValidForm(StoreZero32, Arg::Stack));
- insertionSet.insert(
- instIndex + 1, StoreZero32, inst.origin,
- stackAddr(arg.offset() + 4 + slot->offsetFromFP()));
- }
- arg = stackAddr(arg.offset() + slot->offsetFromFP());
- break;
- }
- case Arg::CallArg:
- arg = stackAddr(arg.offset() - code.frameSize());
- break;
- default:
- break;
- }
- }
- );
- }
- insertionSet.execute(block);
- }
-}
-
-} } } // namespace JSC::B3::Air
-
-#endif // ENABLE(B3_JIT)
-
-
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirAllocateStackh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.h (215072 => 215073)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.h        2017-04-07 00:16:18 UTC (rev 215072)
+++ trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.h        2017-04-07 00:26:53 UTC (rev 215073)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-/*
- * Copyright (C) 2015-2016 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.
- */
-
-#pragma once
-
-#if ENABLE(B3_JIT)
-
-namespace JSC { namespace B3 { namespace Air {
-
-class Code;
-
-// This allocates StackSlots to places on the stack. It first allocates the pinned ones in index
-// order and then it allocates the rest using first fit. Takes the opportunity to kill dead
-// assignments to stack slots, since it knows which ones are live. Also fixes ZDefs to anonymous
-// stack slots.
-
-void allocateStack(Code&);
-
-} } } // namespace JSC::B3::Air
-
-#endif // ENABLE(B3_JIT)
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirAllocateStackByGraphColoringcppfromrev215072trunkSourceJavaScriptCoreb3airAirAllocateStackcpp"></a>
<div class="copfile"><h4>Copied: trunk/Source/JavaScriptCore/b3/air/AirAllocateStackByGraphColoring.cpp (from rev 215072, trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp) (0 => 215073)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirAllocateStackByGraphColoring.cpp         (rev 0)
+++ trunk/Source/JavaScriptCore/b3/air/AirAllocateStackByGraphColoring.cpp        2017-04-07 00:26:53 UTC (rev 215073)
</span><span class="lines">@@ -0,0 +1,464 @@
</span><ins>+/*
+ * Copyright (C) 2015-2017 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 "AirAllocateStackByGraphColoring.h"
+
+#if ENABLE(B3_JIT)
+
+#include "AirArgInlines.h"
+#include "AirCode.h"
+#include "AirInsertionSet.h"
+#include "AirInstInlines.h"
+#include "AirLiveness.h"
+#include "AirPhaseScope.h"
+#include "StackAlignment.h"
+#include <wtf/ListDump.h>
+
+namespace JSC { namespace B3 { namespace Air {
+
+namespace {
+
+const bool verbose = false;
+
+bool attemptAssignment(
+ StackSlot* slot, intptr_t offsetFromFP, const Vector<StackSlot*>& otherSlots)
+{
+ if (verbose)
+ dataLog("Attempting to assign ", pointerDump(slot), " to ", offsetFromFP, " with interference ", pointerListDump(otherSlots), "\n");
+
+ // Need to align it to the slot's desired alignment.
+ offsetFromFP = -WTF::roundUpToMultipleOf(slot->alignment(), -offsetFromFP);
+
+ for (StackSlot* otherSlot : otherSlots) {
+ if (!otherSlot->offsetFromFP())
+ continue;
+ bool overlap = WTF::rangesOverlap(
+ offsetFromFP,
+ offsetFromFP + static_cast<intptr_t>(slot->byteSize()),
+ otherSlot->offsetFromFP(),
+ otherSlot->offsetFromFP() + static_cast<intptr_t>(otherSlot->byteSize()));
+ if (overlap)
+ return false;
+ }
+
+ if (verbose)
+ dataLog("Assigned ", pointerDump(slot), " to ", offsetFromFP, "\n");
+ slot->setOffsetFromFP(offsetFromFP);
+ return true;
+}
+
+void assign(StackSlot* slot, const Vector<StackSlot*>& otherSlots)
+{
+ if (verbose)
+ dataLog("Attempting to assign ", pointerDump(slot), " with interference ", pointerListDump(otherSlots), "\n");
+
+ if (attemptAssignment(slot, -static_cast<intptr_t>(slot->byteSize()), otherSlots))
+ return;
+
+ for (StackSlot* otherSlot : otherSlots) {
+ if (!otherSlot->offsetFromFP())
+ continue;
+ bool didAssign = attemptAssignment(
+ slot, otherSlot->offsetFromFP() - static_cast<intptr_t>(slot->byteSize()), otherSlots);
+ if (didAssign)
+ return;
+ }
+
+ RELEASE_ASSERT_NOT_REACHED();
+}
+
+struct CoalescableMove {
+ CoalescableMove()
+ {
+ }
+
+ CoalescableMove(StackSlot* src, StackSlot* dst, double frequency)
+ : src(src)
+ , dst(dst)
+ , frequency(frequency)
+ {
+ }
+
+ bool operator==(const CoalescableMove& other) const
+ {
+ return src == other.src
+ && dst == other.dst
+ && frequency == other.frequency;
+ }
+
+ bool operator!=(const CoalescableMove& other) const
+ {
+ return !(*this == other);
+ }
+
+ explicit operator bool() const
+ {
+ return *this != CoalescableMove();
+ }
+
+ void dump(PrintStream& out) const
+ {
+ out.print(pointerDump(src), "->", pointerDump(dst), "(", frequency, ")");
+ }
+
+ StackSlot* src { nullptr };
+ StackSlot* dst { nullptr };
+ double frequency { PNaN };
+};
+
+} // anonymous namespace
+
+void allocateStackByGraphColoring(Code& code)
+{
+ PhaseScope phaseScope(code, "allocateStackByGraphColoring");
+
+ // Allocate all of the escaped slots in order. This is kind of a crazy algorithm to allow for
+ // the possibility of stack slots being assigned frame offsets before we even get here.
+ ASSERT(!code.frameSize());
+ Vector<StackSlot*> assignedEscapedStackSlots;
+ Vector<StackSlot*> escapedStackSlotsWorklist;
+ for (StackSlot* slot : code.stackSlots()) {
+ if (slot->isLocked()) {
+ if (slot->offsetFromFP())
+ assignedEscapedStackSlots.append(slot);
+ else
+ escapedStackSlotsWorklist.append(slot);
+ } else {
+ // It would be super strange to have an unlocked stack slot that has an offset already.
+ ASSERT(!slot->offsetFromFP());
+ }
+ }
+ // This is a fairly expensive loop, but it's OK because we'll usually only have a handful of
+ // escaped stack slots.
+ while (!escapedStackSlotsWorklist.isEmpty()) {
+ StackSlot* slot = escapedStackSlotsWorklist.takeLast();
+ assign(slot, assignedEscapedStackSlots);
+ assignedEscapedStackSlots.append(slot);
+ }
+
+ // Now we handle the spill slots.
+ StackSlotLiveness liveness(code);
+ IndexMap<StackSlot*, HashSet<StackSlot*>> interference(code.stackSlots().size());
+ Vector<StackSlot*> slots;
+
+ // We will perform some spill coalescing. To make that effective, we need to be able to identify
+ // coalescable moves and handle them specially in interference analysis.
+ auto isCoalescableMove = [&] (Inst& inst) -> bool {
+ Width width;
+ switch (inst.kind.opcode) {
+ case Move:
+ width = pointerWidth();
+ break;
+ case Move32:
+ case MoveFloat:
+ width = Width32;
+ break;
+ case MoveDouble:
+ width = Width64;
+ break;
+ default:
+ return false;
+ }
+
+ if (!Options::coalesceSpillSlots())
+ return false;
+
+ if (inst.args.size() != 3)
+ return false;
+
+ for (unsigned i = 0; i < 2; ++i) {
+ Arg arg = inst.args[i];
+ if (!arg.isStack())
+ return false;
+ StackSlot* slot = arg.stackSlot();
+ if (slot->kind() != StackSlotKind::Spill)
+ return false;
+ if (slot->byteSize() != bytes(width))
+ return false;
+ }
+
+ return true;
+ };
+
+ auto isUselessMove = [&] (Inst& inst) -> bool {
+ return isCoalescableMove(inst) && inst.args[0] == inst.args[1];
+ };
+
+ auto addEdge = [&] (StackSlot* a, StackSlot* b) {
+ interference[a].add(b);
+ interference[b].add(a);
+ };
+
+ Vector<CoalescableMove> coalescableMoves;
+
+ for (BasicBlock* block : code) {
+ StackSlotLiveness::LocalCalc localCalc(liveness, block);
+
+ auto interfere = [&] (unsigned instIndex) {
+ if (verbose)
+ dataLog("Interfering: ", WTF::pointerListDump(localCalc.live()), "\n");
+
+ Inst* prevInst = block->get(instIndex);
+ Inst* nextInst = block->get(instIndex + 1);
+ if (prevInst && isCoalescableMove(*prevInst)) {
+ CoalescableMove move(prevInst->args[0].stackSlot(), prevInst->args[1].stackSlot(), block->frequency());
+
+ coalescableMoves.append(move);
+
+ for (StackSlot* otherSlot : localCalc.live()) {
+ if (otherSlot != move.src)
+ addEdge(move.dst, otherSlot);
+ }
+
+ prevInst = nullptr;
+ }
+ Inst::forEachDef<Arg>(
+ prevInst, nextInst,
+ [&] (Arg& arg, Arg::Role, Bank, Width) {
+ if (!arg.isStack())
+ return;
+ StackSlot* slot = arg.stackSlot();
+ if (slot->kind() != StackSlotKind::Spill)
+ return;
+
+ for (StackSlot* otherSlot : localCalc.live())
+ addEdge(slot, otherSlot);
+ });
+ };
+
+ for (unsigned instIndex = block->size(); instIndex--;) {
+ if (verbose)
+ dataLog("Analyzing: ", block->at(instIndex), "\n");
+
+ // Kill dead stores. For simplicity we say that a store is killable if it has only late
+ // defs and those late defs are to things that are dead right now. We only do that
+ // because that's the only kind of dead stack store we will see here.
+ Inst& inst = block->at(instIndex);
+ if (!inst.hasNonArgEffects()) {
+ bool ok = true;
+ inst.forEachArg(
+ [&] (Arg& arg, Arg::Role role, Bank, Width) {
+ if (Arg::isEarlyDef(role)) {
+ ok = false;
+ return;
+ }
+ if (!Arg::isLateDef(role))
+ return;
+ if (!arg.isStack()) {
+ ok = false;
+ return;
+ }
+ StackSlot* slot = arg.stackSlot();
+ if (slot->kind() != StackSlotKind::Spill) {
+ ok = false;
+ return;
+ }
+
+ if (localCalc.isLive(slot)) {
+ ok = false;
+ return;
+ }
+ });
+ if (ok)
+ inst = Inst();
+ }
+
+ interfere(instIndex);
+ localCalc.execute(instIndex);
+ }
+ interfere(-1);
+
+ block->insts().removeAllMatching(
+ [&] (const Inst& inst) -> bool {
+ return !inst;
+ });
+ }
+
+ if (verbose) {
+ for (StackSlot* slot : code.stackSlots())
+ dataLog("Interference of ", pointerDump(slot), ": ", pointerListDump(interference[slot]), "\n");
+ }
+
+ // Now try to coalesce some moves.
+ std::sort(
+ coalescableMoves.begin(), coalescableMoves.end(),
+ [&] (CoalescableMove& a, CoalescableMove& b) -> bool {
+ return a.frequency > b.frequency;
+ });
+
+ IndexMap<StackSlot*, StackSlot*> remappedStackSlots(code.stackSlots().size());
+ auto remap = [&] (StackSlot* slot) -> StackSlot* {
+ if (!slot)
+ return nullptr;
+ for (;;) {
+ StackSlot* remappedSlot = remappedStackSlots[slot];
+ if (!remappedSlot)
+ return slot;
+ slot = remappedSlot;
+ }
+ };
+
+ for (CoalescableMove& move : coalescableMoves) {
+ move.src = remap(move.src);
+ move.dst = remap(move.dst);
+ if (move.src == move.dst)
+ continue;
+ if (interference[move.src].contains(move.dst))
+ continue;
+
+ StackSlot* slotToKill = move.src;
+ StackSlot* slotToKeep = move.dst;
+
+ remappedStackSlots[slotToKill] = slotToKeep;
+ for (StackSlot* interferingSlot : interference[slotToKill]) {
+ if (interferingSlot == slotToKill)
+ continue;
+ interference[interferingSlot].remove(slotToKill);
+ interference[interferingSlot].add(slotToKeep);
+ }
+ interference[slotToKeep].add(interference[slotToKill].begin(), interference[slotToKill].end());
+ interference[slotToKill].clear();
+ }
+
+ for (BasicBlock* block : code) {
+ for (Inst& inst : *block) {
+ for (Arg& arg : inst.args) {
+ if (arg.isStack())
+ arg = Arg::stack(remap(arg.stackSlot()), arg.offset());
+ }
+ if (isUselessMove(inst))
+ inst = Inst();
+ }
+ }
+
+ // Now we assign stack locations. At its heart this algorithm is just first-fit. For each
+ // StackSlot we just want to find the offsetFromFP that is closest to zero while ensuring no
+ // overlap with other StackSlots that this overlaps with.
+ Vector<StackSlot*> otherSlots = assignedEscapedStackSlots;
+ for (StackSlot* slot : code.stackSlots()) {
+ if (remappedStackSlots[slot])
+ continue;
+
+ if (slot->offsetFromFP()) {
+ // Already assigned an offset.
+ continue;
+ }
+
+ HashSet<StackSlot*>& interferingSlots = interference[slot];
+ otherSlots.resize(assignedEscapedStackSlots.size());
+ otherSlots.resize(assignedEscapedStackSlots.size() + interferingSlots.size());
+ unsigned nextIndex = assignedEscapedStackSlots.size();
+ for (StackSlot* otherSlot : interferingSlots)
+ otherSlots[nextIndex++] = otherSlot;
+
+ assign(slot, otherSlots);
+ }
+
+ // Figure out how much stack we're using for stack slots.
+ unsigned frameSizeForStackSlots = 0;
+ for (StackSlot* slot : code.stackSlots()) {
+ frameSizeForStackSlots = std::max(
+ frameSizeForStackSlots,
+ static_cast<unsigned>(-slot->offsetFromFP()));
+ }
+
+ frameSizeForStackSlots = WTF::roundUpToMultipleOf(stackAlignmentBytes(), frameSizeForStackSlots);
+
+ // Now we need to deduce how much argument area we need.
+ for (BasicBlock* block : code) {
+ for (Inst& inst : *block) {
+ for (Arg& arg : inst.args) {
+ if (arg.isCallArg()) {
+ // For now, we assume that we use 8 bytes of the call arg. But that's not
+ // such an awesome assumption.
+ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=150454
+ ASSERT(arg.offset() >= 0);
+ code.requestCallArgAreaSizeInBytes(arg.offset() + 8);
+ }
+ }
+ }
+ }
+
+ code.setFrameSize(frameSizeForStackSlots + code.callArgAreaSizeInBytes());
+
+ // Finally, transform the code to use Addr's instead of StackSlot's. This is a lossless
+ // transformation since we can search the StackSlots array to figure out which StackSlot any
+ // offset-from-FP refers to.
+
+ // FIXME: This may produce addresses that aren't valid if we end up with a ginormous stack frame.
+ // We would have to scavenge for temporaries if this happened. Fortunately, this case will be
+ // extremely rare so we can do crazy things when it arises.
+ // https://bugs.webkit.org/show_bug.cgi?id=152530
+
+ InsertionSet insertionSet(code);
+ for (BasicBlock* block : code) {
+ for (unsigned instIndex = 0; instIndex < block->size(); ++instIndex) {
+ Inst& inst = block->at(instIndex);
+ inst.forEachArg(
+ [&] (Arg& arg, Arg::Role role, Bank, Width width) {
+ auto stackAddr = [&] (int32_t offset) -> Arg {
+ return Arg::stackAddr(offset, code.frameSize(), width);
+ };
+
+ switch (arg.kind()) {
+ case Arg::Stack: {
+ StackSlot* slot = arg.stackSlot();
+ if (Arg::isZDef(role)
+ && slot->kind() == StackSlotKind::Spill
+ && slot->byteSize() > bytes(width)) {
+ // Currently we only handle this simple case because it's the only one
+ // that arises: ZDef's are only 32-bit right now. So, when we hit these
+ // assertions it means that we need to implement those other kinds of
+ // zero fills.
+ RELEASE_ASSERT(slot->byteSize() == 8);
+ RELEASE_ASSERT(width == Width32);
+
+ RELEASE_ASSERT(isValidForm(StoreZero32, Arg::Stack));
+ insertionSet.insert(
+ instIndex + 1, StoreZero32, inst.origin,
+ stackAddr(arg.offset() + 4 + slot->offsetFromFP()));
+ }
+ arg = stackAddr(arg.offset() + slot->offsetFromFP());
+ break;
+ }
+ case Arg::CallArg:
+ arg = stackAddr(arg.offset() - code.frameSize());
+ break;
+ default:
+ break;
+ }
+ }
+ );
+ }
+ insertionSet.execute(block);
+ }
+}
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirAllocateStackByGraphColoringhfromrev215072trunkSourceJavaScriptCoreb3airAirAllocateStackh"></a>
<div class="copfile"><h4>Copied: trunk/Source/JavaScriptCore/b3/air/AirAllocateStackByGraphColoring.h (from rev 215072, trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.h) (0 => 215073)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirAllocateStackByGraphColoring.h         (rev 0)
+++ trunk/Source/JavaScriptCore/b3/air/AirAllocateStackByGraphColoring.h        2017-04-07 00:26:53 UTC (rev 215073)
</span><span class="lines">@@ -0,0 +1,46 @@
</span><ins>+/*
+ * Copyright (C) 2015-2017 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.
+ */
+
+#pragma once
+
+#if ENABLE(B3_JIT)
+
+namespace JSC { namespace B3 { namespace Air {
+
+class Code;
+
+// This allocates StackSlots to places on the stack. It first allocates the pinned ones in index
+// order and then it allocates the rest using first fit. Takes the opportunity to kill dead
+// assignments to stack slots, since it knows which ones are live. Also fixes ZDefs to anonymous
+// stack slots. Also coalesces spill slots whenever possible.
+//
+// This is meant to be an optimal stack allocator, focused on generating great code. It's not
+// particularly fast, though.
+
+void allocateStackByGraphColoring(Code&);
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirGeneratecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp (215072 => 215073)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp        2017-04-07 00:16:18 UTC (rev 215072)
+++ trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp        2017-04-07 00:26:53 UTC (rev 215073)
</span><span class="lines">@@ -30,7 +30,7 @@
</span><span class="cx">
</span><span class="cx"> #include "AirAllocateRegistersByGraphColoring.h"
</span><span class="cx"> #include "AirAllocateRegistersByLinearScan.h"
</span><del>-#include "AirAllocateStack.h"
</del><ins>+#include "AirAllocateStackByGraphColoring.h"
</ins><span class="cx"> #include "AirCode.h"
</span><span class="cx"> #include "AirEliminateDeadCode.h"
</span><span class="cx"> #include "AirFixObviousSpills.h"
</span><span class="lines">@@ -116,7 +116,7 @@
</span><span class="cx"> // This turns all Stack and CallArg Args into Addr args that use the frame pointer. It does
</span><span class="cx"> // this by first-fit allocating stack slots. It should be pretty darn close to optimal, so we
</span><span class="cx"> // shouldn't have to worry about this very much.
</span><del>- allocateStack(code);
</del><ins>+ allocateStackByGraphColoring(code);
</ins><span class="cx">
</span><span class="cx"> // If we coalesced moves then we can unbreak critical edges. This is the main reason for this
</span><span class="cx"> // phase.
</span></span></pre>
</div>
</div>
</body>
</html>