Diff
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (215309 => 215310)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2017-04-13 00:40:38 UTC (rev 215309)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2017-04-13 02:26:53 UTC (rev 215310)
@@ -109,6 +109,7 @@
b3/air/AirReportUsedRegisters.cpp
b3/air/AirSimplifyCFG.cpp
b3/air/AirSpecial.cpp
+ b3/air/AirStackAllocation.cpp
b3/air/AirStackSlot.cpp
b3/air/AirStackSlotKind.cpp
b3/air/AirTmp.cpp
Modified: trunk/Source/_javascript_Core/ChangeLog (215309 => 215310)
--- trunk/Source/_javascript_Core/ChangeLog 2017-04-13 00:40:38 UTC (rev 215309)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-04-13 02:26:53 UTC (rev 215310)
@@ -1,5 +1,46 @@
2017-04-12 Filip Pizlo <[email protected]>
+ Move common stack allocation utilities out of AirAllocateStackByGraphColoring.cpp
+ https://bugs.webkit.org/show_bug.cgi?id=170799
+
+ Reviewed by Michael Saboff and Keith Miller.
+
+ When I added stack allocation to allocateRegistersByLinearScan, I reused a handful of
+ utility functions from AirAllocateStackByGraphColoring.cpp. I accomplished this by
+ putting their declarations in AirAllocateStackByGraphColoring.h.
+
+ That was pretty weird.
+
+ This patch moves a family of stack allocation helper functions out of
+ AirAllocateStackByGraphColoring.cpp and into the new AirStackAllocation.h|cpp. The
+ linear scan stack allocator no longer has to include the other stack allocator's
+ header, which addresses my OCD.
+
+ I moved the functions transitively reachable from the two functions that the linear
+ scan allocator needed. This forced me to give them better names (i.e. no "fooBarImpl")
+ and short descriptive comments. I think that such comments are useful in code that is
+ doing a convoluted version of some theoretical concept.
+
+ No behavior change.
+
+ * CMakeLists.txt:
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * b3/air/AirAllocateRegistersAndStackByLinearScan.cpp:
+ * b3/air/AirAllocateStackByGraphColoring.cpp:
+ (JSC::B3::Air::allocateStackByGraphColoring):
+ (JSC::B3::Air::allocateEscapedStackSlots): Deleted.
+ (JSC::B3::Air::updateFrameSizeBasedOnStackSlots): Deleted.
+ * b3/air/AirAllocateStackByGraphColoring.h:
+ * b3/air/AirStackAllocation.cpp: Added.
+ (JSC::B3::Air::attemptAssignment):
+ (JSC::B3::Air::assign):
+ (JSC::B3::Air::allocateAndGetEscapedStackSlotsWithoutChangingFrameSize):
+ (JSC::B3::Air::allocateEscapedStackSlots):
+ (JSC::B3::Air::updateFrameSizeBasedOnStackSlots):
+ * b3/air/AirStackAllocation.h: Added.
+
+2017-04-12 Filip Pizlo <[email protected]>
+
B3 -O1 should not allocateStackByGraphColoring
https://bugs.webkit.org/show_bug.cgi?id=170742
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (215309 => 215310)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2017-04-13 00:40:38 UTC (rev 215309)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2017-04-13 02:26:53 UTC (rev 215310)
@@ -457,6 +457,8 @@
0F5CF9811E96F17F00C18692 /* AirTmpMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5CF9801E96F17D00C18692 /* AirTmpMap.h */; };
0F5CF9841E9D537700C18692 /* AirLowerStackArgs.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5CF9831E9D537500C18692 /* AirLowerStackArgs.h */; };
0F5CF9851E9D537A00C18692 /* AirLowerStackArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F5CF9821E9D537500C18692 /* AirLowerStackArgs.cpp */; };
+ 0F5CF9881E9ED65000C18692 /* AirStackAllocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F5CF9861E9ED64E00C18692 /* AirStackAllocation.cpp */; };
+ 0F5CF9891E9ED65200C18692 /* AirStackAllocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5CF9871E9ED64E00C18692 /* AirStackAllocation.h */; };
0F5D085D1B8CF99D001143B4 /* DFGNodeOrigin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F5D085C1B8CF99D001143B4 /* DFGNodeOrigin.cpp */; };
0F5EF91E16878F7A003E5C25 /* JITThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F5EF91B16878F78003E5C25 /* JITThunks.cpp */; };
0F5EF91F16878F7D003E5C25 /* JITThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5EF91C16878F78003E5C25 /* JITThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -2996,6 +2998,8 @@
0F5CF9801E96F17D00C18692 /* AirTmpMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirTmpMap.h; path = b3/air/AirTmpMap.h; sourceTree = "<group>"; };
0F5CF9821E9D537500C18692 /* AirLowerStackArgs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirLowerStackArgs.cpp; path = b3/air/AirLowerStackArgs.cpp; sourceTree = "<group>"; };
0F5CF9831E9D537500C18692 /* AirLowerStackArgs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirLowerStackArgs.h; path = b3/air/AirLowerStackArgs.h; sourceTree = "<group>"; };
+ 0F5CF9861E9ED64E00C18692 /* AirStackAllocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirStackAllocation.cpp; path = b3/air/AirStackAllocation.cpp; sourceTree = "<group>"; };
+ 0F5CF9871E9ED64E00C18692 /* AirStackAllocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirStackAllocation.h; path = b3/air/AirStackAllocation.h; sourceTree = "<group>"; };
0F5D085C1B8CF99D001143B4 /* DFGNodeOrigin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGNodeOrigin.cpp; path = dfg/DFGNodeOrigin.cpp; sourceTree = "<group>"; };
0F5EF91B16878F78003E5C25 /* JITThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITThunks.cpp; sourceTree = "<group>"; };
0F5EF91C16878F78003E5C25 /* JITThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITThunks.h; sourceTree = "<group>"; };
@@ -5656,6 +5660,8 @@
0F338DFC1BED51270013C88F /* AirSimplifyCFG.h */,
0FEC85621BDACDC70080FF74 /* AirSpecial.cpp */,
0FEC85631BDACDC70080FF74 /* AirSpecial.h */,
+ 0F5CF9861E9ED64E00C18692 /* AirStackAllocation.cpp */,
+ 0F5CF9871E9ED64E00C18692 /* AirStackAllocation.h */,
0FEC85661BDACDC70080FF74 /* AirStackSlot.cpp */,
0FEC85671BDACDC70080FF74 /* AirStackSlot.h */,
0F2BBD9B1C5FF4050023EF23 /* AirStackSlotKind.cpp */,
@@ -8613,6 +8619,7 @@
E3C79CAB1DB9A4DC00D1ECA4 /* DOMJITEffect.h in Headers */,
E3FF75331D9CEA1800C7E16D /* DOMJITGetterSetter.h in Headers */,
E35CA1541DBC3A5C00F83516 /* DOMJITHeapRange.h in Headers */,
+ 0F5CF9891E9ED65200C18692 /* AirStackAllocation.h in Headers */,
E3C08E3C1DA41B810039478F /* DOMJITPatchpoint.h in Headers */,
534638711E70CF3D00F12AC1 /* JSRunLoopTimer.h in Headers */,
FE6F56DE1E64EAD600D17801 /* VMTraps.h in Headers */,
@@ -10906,6 +10913,7 @@
AD2FCBF41DB58DAD00B3E736 /* WebAssemblyMemoryConstructor.cpp in Sources */,
AD2FCBF61DB58DAD00B3E736 /* WebAssemblyMemoryPrototype.cpp in Sources */,
AD2FCC001DB58DAD00B3E736 /* WebAssemblyModuleConstructor.cpp in Sources */,
+ 0F5CF9881E9ED65000C18692 /* AirStackAllocation.cpp in Sources */,
AD2FCC021DB58DAD00B3E736 /* WebAssemblyModulePrototype.cpp in Sources */,
AD4937C71DDD0AAE0077C807 /* WebAssemblyModuleRecord.cpp in Sources */,
AD2FCC2C1DB838FD00B3E736 /* WebAssemblyPrototype.cpp in Sources */,
Modified: trunk/Source/_javascript_Core/b3/air/AirAllocateRegistersAndStackByLinearScan.cpp (215309 => 215310)
--- trunk/Source/_javascript_Core/b3/air/AirAllocateRegistersAndStackByLinearScan.cpp 2017-04-13 00:40:38 UTC (rev 215309)
+++ trunk/Source/_javascript_Core/b3/air/AirAllocateRegistersAndStackByLinearScan.cpp 2017-04-13 02:26:53 UTC (rev 215310)
@@ -28,7 +28,6 @@
#if ENABLE(B3_JIT)
-#include "AirAllocateStackByGraphColoring.h"
#include "AirArgInlines.h"
#include "AirCode.h"
#include "AirFixSpillsAfterTerminals.h"
@@ -39,6 +38,7 @@
#include "AirPadInterference.h"
#include "AirPhaseScope.h"
#include "AirRegLiveness.h"
+#include "AirStackAllocation.h"
#include "AirTmpInlines.h"
#include "AirTmpMap.h"
#include <wtf/ListDump.h>
Modified: trunk/Source/_javascript_Core/b3/air/AirAllocateStackByGraphColoring.cpp (215309 => 215310)
--- trunk/Source/_javascript_Core/b3/air/AirAllocateStackByGraphColoring.cpp 2017-04-13 00:40:38 UTC (rev 215309)
+++ trunk/Source/_javascript_Core/b3/air/AirAllocateStackByGraphColoring.cpp 2017-04-13 02:26:53 UTC (rev 215310)
@@ -34,6 +34,7 @@
#include "AirInstInlines.h"
#include "AirLiveness.h"
#include "AirPhaseScope.h"
+#include "AirStackAllocation.h"
#include "StackAlignment.h"
#include <wtf/ListDump.h>
@@ -43,53 +44,6 @@
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()
{
@@ -129,55 +83,8 @@
double frequency { PNaN };
};
-Vector<StackSlot*> allocateEscapedStackSlotsImpl(Code& code)
-{
- // 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.
- RELEASE_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);
- }
- return assignedEscapedStackSlots;
-}
-
-template<typename Collection>
-void updateFrameSizeBasedOnStackSlotsImpl(Code& code, const Collection& collection)
-{
- unsigned frameSize = 0;
- for (StackSlot* slot : collection)
- frameSize = std::max(frameSize, static_cast<unsigned>(-slot->offsetFromFP()));
- code.setFrameSize(WTF::roundUpToMultipleOf(stackAlignmentBytes(), frameSize));
-}
-
} // anonymous namespace
-void allocateEscapedStackSlots(Code& code)
-{
- updateFrameSizeBasedOnStackSlotsImpl(code, allocateEscapedStackSlotsImpl(code));
-}
-
-void updateFrameSizeBasedOnStackSlots(Code& code)
-{
- updateFrameSizeBasedOnStackSlotsImpl(code, code.stackSlots());
-}
-
void allocateStackByGraphColoring(Code& code)
{
PhaseScope phaseScope(code, "allocateStackByGraphColoring");
@@ -184,7 +91,8 @@
handleCalleeSaves(code);
- Vector<StackSlot*> assignedEscapedStackSlots = allocateEscapedStackSlotsImpl(code);
+ Vector<StackSlot*> assignedEscapedStackSlots =
+ allocateAndGetEscapedStackSlotsWithoutChangingFrameSize(code);
// Now we handle the spill slots.
StackSlotLiveness liveness(code);
Modified: trunk/Source/_javascript_Core/b3/air/AirAllocateStackByGraphColoring.h (215309 => 215310)
--- trunk/Source/_javascript_Core/b3/air/AirAllocateStackByGraphColoring.h 2017-04-13 00:40:38 UTC (rev 215309)
+++ trunk/Source/_javascript_Core/b3/air/AirAllocateStackByGraphColoring.h 2017-04-13 02:26:53 UTC (rev 215310)
@@ -41,10 +41,6 @@
void allocateStackByGraphColoring(Code&);
-// These are utilities shared by this phase and allocateRegistersAndStackByLinearScan().
-void allocateEscapedStackSlots(Code&);
-void updateFrameSizeBasedOnStackSlots(Code&);
-
} } } // namespace JSC::B3::Air
#endif // ENABLE(B3_JIT)
Added: trunk/Source/_javascript_Core/b3/air/AirStackAllocation.cpp (0 => 215310)
--- trunk/Source/_javascript_Core/b3/air/AirStackAllocation.cpp (rev 0)
+++ trunk/Source/_javascript_Core/b3/air/AirStackAllocation.cpp 2017-04-13 02:26:53 UTC (rev 215310)
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 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 "AirStackAllocation.h"
+
+#if ENABLE(B3_JIT)
+
+#include "AirArgInlines.h"
+#include "AirCode.h"
+#include "AirInstInlines.h"
+#include "StackAlignment.h"
+#include <wtf/ListDump.h>
+
+namespace JSC { namespace B3 { namespace Air {
+
+namespace {
+
+const bool verbose = false;
+
+template<typename Collection>
+void updateFrameSizeBasedOnStackSlotsImpl(Code& code, const Collection& collection)
+{
+ unsigned frameSize = 0;
+ for (StackSlot* slot : collection)
+ frameSize = std::max(frameSize, static_cast<unsigned>(-slot->offsetFromFP()));
+ code.setFrameSize(WTF::roundUpToMultipleOf(stackAlignmentBytes(), frameSize));
+}
+
+} // anonymous namespace
+
+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();
+}
+
+Vector<StackSlot*> allocateAndGetEscapedStackSlotsWithoutChangingFrameSize(Code& code)
+{
+ // 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.
+ RELEASE_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);
+ }
+ return assignedEscapedStackSlots;
+}
+
+void allocateEscapedStackSlots(Code& code)
+{
+ updateFrameSizeBasedOnStackSlotsImpl(
+ code, allocateAndGetEscapedStackSlotsWithoutChangingFrameSize(code));
+}
+
+void updateFrameSizeBasedOnStackSlots(Code& code)
+{
+ updateFrameSizeBasedOnStackSlotsImpl(code, code.stackSlots());
+}
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+
Added: trunk/Source/_javascript_Core/b3/air/AirStackAllocation.h (0 => 215310)
--- trunk/Source/_javascript_Core/b3/air/AirStackAllocation.h (rev 0)
+++ trunk/Source/_javascript_Core/b3/air/AirStackAllocation.h 2017-04-13 02:26:53 UTC (rev 215310)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 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)
+
+#include <wtf/Vector.h>
+
+namespace JSC { namespace B3 { namespace Air {
+
+class Code;
+class StackSlot;
+
+// This is a collection of utilities shared by both stack allocators
+// (allocateStackByGraphColoring and allocateRegistersAndStackByLinearScan).
+
+// Attempt to put the given stack slot at the given offset. Returns false if this would cause
+// the slot to overlap with any of the given slots.
+bool attemptAssignment(StackSlot*, intptr_t offsetFromFP, const Vector<StackSlot*>& adjacent);
+
+// Performs a first-fit assignment (smallest possible offset) of the given stack slot such that
+// it does not overlap with any of the adjacent slots.
+void assign(StackSlot*, const Vector<StackSlot*>& adjacent);
+
+// Allocates all stack slots that escape - that is, that don't have live ranges that can be
+// determined by looking at their uses. Returns a vector of slots that got assigned offsets.
+// This assumes that no stack allocation has happened previously, and so frame size is zero.
+Vector<StackSlot*> allocateAndGetEscapedStackSlotsWithoutChangingFrameSize(Code&);
+
+// Same as allocateAndGetEscapedStackSlotsWithoutChangingFrameSize, but does not return the
+// assigned slots, and does set the frame size based on the largest extent of any of the
+// allocated slots.
+void allocateEscapedStackSlots(Code&);
+
+// Updates Code::frameSize based on the largest extent of any stack slot. This is useful to
+// call after performing stack allocation.
+void updateFrameSizeBasedOnStackSlots(Code&);
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+