Air should expose API for pinning registers
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 10 Oct 2016 17:12:34 +0000 (17:12 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 10 Oct 2016 17:12:34 +0000 (17:12 +0000)
https://bugs.webkit.org/show_bug.cgi?id=163175

Reviewed by Keith Miller.

You can now call Procedure::pinRegister(), or Code::pinRegister(), and it will make this
register behave as follows:

- B3 and Air will emit no code that modifies the value in this register, except if that
  happens via a Patchpoint or stackmap constraint (i.e. the user explicitly asked for it).
- B3 and Air will allow others to modify the register. For example, if the register is not
  callee-save, then the compiler knows that the register's value will be trashed by any
  C-style call.
- Air will be happy to emit code that reads from this register, including coalescing tmps
  with it, so longer as there is no interference (i.e. no chance of the register's value
  changing). For example, if we went back to having pinned tag registers, we would tell B3
  to use them by (1) excluding them from any clobber set (easy, since they're callee save)
  and (2) emitting ArgumentReg to grab their value. There's a test that does this.

This is accomplished by taking regsInPriorityOrder() and making it a method of Code. Air
already used this API when choosing registers in register allocation. Code now also vends a
mutableRegs() set, which is derived from regsInPriorityOrder(), that can quickly tell you if
a register can be mutated. Doing it this way means that most of this is a purely mechanical
change. The calls to mutableRegs() are the places where we had to change logic:

- The register allocators needs to know that coalescing with a precolored pinned tmp is free.
- The callee-save handler needs to know that we're not supposed to save/restore pinned
  registers.

Note that in this scheme, pinned registers are simply registers that do not appear in
regsInPriorityOrder(). This means, for example, that we will now say that FP is pinned. So,
this means that you can also pin registers by calling setRegsInPriorityOrder() and passing a
vector that excludes some registers. More generally, this means that clients can now tweak
the register allocator's register preferences, since the ordering in that list reflects the
order in which the allocator will try registers.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* b3/B3Procedure.cpp:
(JSC::B3::Procedure::pinRegister):
* b3/B3Procedure.h:
* b3/air/AirCode.cpp:
(JSC::B3::Air::Code::Code):
(JSC::B3::Air::Code::setRegsInPriorityOrder):
(JSC::B3::Air::Code::pinRegister):
* b3/air/AirCode.h:
(JSC::B3::Air::Code::regsInPriorityOrder):
(JSC::B3::Air::Code::mutableRegs):
(JSC::B3::Air::Code::isPinned):
(JSC::B3::Air::Code::regsInPriorityOrderImpl):
(JSC::B3::Air::Code::proc): Deleted.
* b3/air/AirEmitShuffle.cpp:
(JSC::B3::Air::emitShuffle):
* b3/air/AirEmitShuffle.h:
* b3/air/AirHandleCalleeSaves.cpp:
(JSC::B3::Air::handleCalleeSaves):
* b3/air/AirIteratedRegisterCoalescing.cpp:
* b3/air/AirLowerAfterRegAlloc.cpp:
(JSC::B3::Air::lowerAfterRegAlloc):
* b3/air/AirRegisterPriority.cpp: Removed.
* b3/air/AirRegisterPriority.h: Removed.
* b3/air/AirSpillEverything.cpp:
(JSC::B3::Air::spillEverything):
* b3/air/testair.cpp:
(JSC::B3::Air::testShuffleBroadcastAllRegs):
(JSC::B3::Air::testShuffleShiftAllRegs):
(JSC::B3::Air::testShuffleRotateAllRegs):
(JSC::B3::Air::testShuffleShiftMemoryAllRegs):
(JSC::B3::Air::testShuffleShiftMemoryAllRegs64):
(JSC::B3::Air::testShuffleShiftMemoryAllRegsMixedWidth):
(JSC::B3::Air::testShuffleRotateMemoryAllRegs64):
(JSC::B3::Air::testShuffleRotateMemoryAllRegsMixedWidth):
* b3/testb3.cpp:
(JSC::B3::testPinRegisters):
(JSC::B3::run):
* jit/RegisterSet.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207004 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/b3/B3Procedure.cpp
Source/JavaScriptCore/b3/B3Procedure.h
Source/JavaScriptCore/b3/air/AirCode.cpp
Source/JavaScriptCore/b3/air/AirCode.h
Source/JavaScriptCore/b3/air/AirEmitShuffle.cpp
Source/JavaScriptCore/b3/air/AirEmitShuffle.h
Source/JavaScriptCore/b3/air/AirHandleCalleeSaves.cpp
Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp
Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp
Source/JavaScriptCore/b3/air/AirRegisterPriority.cpp [deleted file]
Source/JavaScriptCore/b3/air/AirRegisterPriority.h [deleted file]
Source/JavaScriptCore/b3/air/AirSpillEverything.cpp
Source/JavaScriptCore/b3/air/testair.cpp
Source/JavaScriptCore/b3/testb3.cpp
Source/JavaScriptCore/jit/RegisterSet.h

index c409755..57ceff6 100644 (file)
@@ -96,7 +96,6 @@ set(JavaScriptCore_SOURCES
     b3/air/AirLowerMacros.cpp
     b3/air/AirOptimizeBlockOrder.cpp
     b3/air/AirPhaseScope.cpp
-    b3/air/AirRegisterPriority.cpp
     b3/air/AirReportUsedRegisters.cpp
     b3/air/AirSimplifyCFG.cpp
     b3/air/AirSpecial.cpp
index 6b3cd8e..c00aad9 100644 (file)
@@ -1,3 +1,82 @@
+2016-10-09  Filip Pizlo  <fpizlo@apple.com>
+
+        Air should expose API for pinning registers
+        https://bugs.webkit.org/show_bug.cgi?id=163175
+
+        Reviewed by Keith Miller.
+        
+        You can now call Procedure::pinRegister(), or Code::pinRegister(), and it will make this
+        register behave as follows:
+        
+        - B3 and Air will emit no code that modifies the value in this register, except if that
+          happens via a Patchpoint or stackmap constraint (i.e. the user explicitly asked for it).
+        - B3 and Air will allow others to modify the register. For example, if the register is not
+          callee-save, then the compiler knows that the register's value will be trashed by any
+          C-style call.
+        - Air will be happy to emit code that reads from this register, including coalescing tmps
+          with it, so longer as there is no interference (i.e. no chance of the register's value
+          changing). For example, if we went back to having pinned tag registers, we would tell B3
+          to use them by (1) excluding them from any clobber set (easy, since they're callee save)
+          and (2) emitting ArgumentReg to grab their value. There's a test that does this.
+        
+        This is accomplished by taking regsInPriorityOrder() and making it a method of Code. Air 
+        already used this API when choosing registers in register allocation. Code now also vends a
+        mutableRegs() set, which is derived from regsInPriorityOrder(), that can quickly tell you if
+        a register can be mutated. Doing it this way means that most of this is a purely mechanical
+        change. The calls to mutableRegs() are the places where we had to change logic:
+        
+        - The register allocators needs to know that coalescing with a precolored pinned tmp is free.
+        - The callee-save handler needs to know that we're not supposed to save/restore pinned
+          registers.
+        
+        Note that in this scheme, pinned registers are simply registers that do not appear in
+        regsInPriorityOrder(). This means, for example, that we will now say that FP is pinned. So,
+        this means that you can also pin registers by calling setRegsInPriorityOrder() and passing a
+        vector that excludes some registers. More generally, this means that clients can now tweak
+        the register allocator's register preferences, since the ordering in that list reflects the
+        order in which the allocator will try registers.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * b3/B3Procedure.cpp:
+        (JSC::B3::Procedure::pinRegister):
+        * b3/B3Procedure.h:
+        * b3/air/AirCode.cpp:
+        (JSC::B3::Air::Code::Code):
+        (JSC::B3::Air::Code::setRegsInPriorityOrder):
+        (JSC::B3::Air::Code::pinRegister):
+        * b3/air/AirCode.h:
+        (JSC::B3::Air::Code::regsInPriorityOrder):
+        (JSC::B3::Air::Code::mutableRegs):
+        (JSC::B3::Air::Code::isPinned):
+        (JSC::B3::Air::Code::regsInPriorityOrderImpl):
+        (JSC::B3::Air::Code::proc): Deleted.
+        * b3/air/AirEmitShuffle.cpp:
+        (JSC::B3::Air::emitShuffle):
+        * b3/air/AirEmitShuffle.h:
+        * b3/air/AirHandleCalleeSaves.cpp:
+        (JSC::B3::Air::handleCalleeSaves):
+        * b3/air/AirIteratedRegisterCoalescing.cpp:
+        * b3/air/AirLowerAfterRegAlloc.cpp:
+        (JSC::B3::Air::lowerAfterRegAlloc):
+        * b3/air/AirRegisterPriority.cpp: Removed.
+        * b3/air/AirRegisterPriority.h: Removed.
+        * b3/air/AirSpillEverything.cpp:
+        (JSC::B3::Air::spillEverything):
+        * b3/air/testair.cpp:
+        (JSC::B3::Air::testShuffleBroadcastAllRegs):
+        (JSC::B3::Air::testShuffleShiftAllRegs):
+        (JSC::B3::Air::testShuffleRotateAllRegs):
+        (JSC::B3::Air::testShuffleShiftMemoryAllRegs):
+        (JSC::B3::Air::testShuffleShiftMemoryAllRegs64):
+        (JSC::B3::Air::testShuffleShiftMemoryAllRegsMixedWidth):
+        (JSC::B3::Air::testShuffleRotateMemoryAllRegs64):
+        (JSC::B3::Air::testShuffleRotateMemoryAllRegsMixedWidth):
+        * b3/testb3.cpp:
+        (JSC::B3::testPinRegisters):
+        (JSC::B3::run):
+        * jit/RegisterSet.h:
+
 2016-10-08  Filip Pizlo  <fpizlo@apple.com>
 
         B3 should know about mutable pinned registers
index bed763c..e5727f5 100644 (file)
                0FEC85811BDACDC70080FF74 /* AirInstInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC855C1BDACDC70080FF74 /* AirInstInlines.h */; };
                0FEC85831BDACDC70080FF74 /* AirPhaseScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC855E1BDACDC70080FF74 /* AirPhaseScope.cpp */; };
                0FEC85841BDACDC70080FF74 /* AirPhaseScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC855F1BDACDC70080FF74 /* AirPhaseScope.h */; };
-               0FEC85851BDACDC70080FF74 /* AirRegisterPriority.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC85601BDACDC70080FF74 /* AirRegisterPriority.cpp */; };
-               0FEC85861BDACDC70080FF74 /* AirRegisterPriority.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC85611BDACDC70080FF74 /* AirRegisterPriority.h */; };
                0FEC85871BDACDC70080FF74 /* AirSpecial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC85621BDACDC70080FF74 /* AirSpecial.cpp */; };
                0FEC85881BDACDC70080FF74 /* AirSpecial.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC85631BDACDC70080FF74 /* AirSpecial.h */; };
                0FEC85891BDACDC70080FF74 /* AirSpillEverything.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC85641BDACDC70080FF74 /* AirSpillEverything.cpp */; };
                0FEC855C1BDACDC70080FF74 /* AirInstInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirInstInlines.h; path = b3/air/AirInstInlines.h; sourceTree = "<group>"; };
                0FEC855E1BDACDC70080FF74 /* AirPhaseScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirPhaseScope.cpp; path = b3/air/AirPhaseScope.cpp; sourceTree = "<group>"; };
                0FEC855F1BDACDC70080FF74 /* AirPhaseScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirPhaseScope.h; path = b3/air/AirPhaseScope.h; sourceTree = "<group>"; };
-               0FEC85601BDACDC70080FF74 /* AirRegisterPriority.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirRegisterPriority.cpp; path = b3/air/AirRegisterPriority.cpp; sourceTree = "<group>"; };
-               0FEC85611BDACDC70080FF74 /* AirRegisterPriority.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirRegisterPriority.h; path = b3/air/AirRegisterPriority.h; sourceTree = "<group>"; };
                0FEC85621BDACDC70080FF74 /* AirSpecial.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirSpecial.cpp; path = b3/air/AirSpecial.cpp; sourceTree = "<group>"; };
                0FEC85631BDACDC70080FF74 /* AirSpecial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirSpecial.h; path = b3/air/AirSpecial.h; sourceTree = "<group>"; };
                0FEC85641BDACDC70080FF74 /* AirSpillEverything.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirSpillEverything.cpp; path = b3/air/AirSpillEverything.cpp; sourceTree = "<group>"; };
                                0FB3878D1BFBC44D00E3AB1E /* AirOptimizeBlockOrder.h */,
                                0FEC855E1BDACDC70080FF74 /* AirPhaseScope.cpp */,
                                0FEC855F1BDACDC70080FF74 /* AirPhaseScope.h */,
-                               0FEC85601BDACDC70080FF74 /* AirRegisterPriority.cpp */,
-                               0FEC85611BDACDC70080FF74 /* AirRegisterPriority.h */,
                                0F45703A1BE45F0A0062A629 /* AirReportUsedRegisters.cpp */,
                                0F45703B1BE45F0A0062A629 /* AirReportUsedRegisters.h */,
                                0F338DFB1BED51270013C88F /* AirSimplifyCFG.cpp */,
                                0FEC85801BDACDC70080FF74 /* AirInst.h in Headers */,
                                0FEC85811BDACDC70080FF74 /* AirInstInlines.h in Headers */,
                                0FEC85841BDACDC70080FF74 /* AirPhaseScope.h in Headers */,
-                               0FEC85861BDACDC70080FF74 /* AirRegisterPriority.h in Headers */,
                                0F45703D1BE45F0A0062A629 /* AirReportUsedRegisters.h in Headers */,
                                0FEC85881BDACDC70080FF74 /* AirSpecial.h in Headers */,
                                0FEC858A1BDACDC70080FF74 /* AirSpillEverything.h in Headers */,
                                0FEC857D1BDACDC70080FF74 /* AirInsertionSet.cpp in Sources */,
                                0FEC857F1BDACDC70080FF74 /* AirInst.cpp in Sources */,
                                0FEC85831BDACDC70080FF74 /* AirPhaseScope.cpp in Sources */,
-                               0FEC85851BDACDC70080FF74 /* AirRegisterPriority.cpp in Sources */,
                                0F45703C1BE45F0A0062A629 /* AirReportUsedRegisters.cpp in Sources */,
                                0FEC85871BDACDC70080FF74 /* AirSpecial.cpp in Sources */,
                                0FEC85891BDACDC70080FF74 /* AirSpillEverything.cpp in Sources */,
index 1c983d6..29fc1c4 100644 (file)
@@ -305,6 +305,11 @@ void Procedure::requestCallArgAreaSizeInBytes(unsigned size)
     code().requestCallArgAreaSizeInBytes(size);
 }
 
+void Procedure::pinRegister(Reg reg)
+{
+    code().pinRegister(reg);
+}
+
 unsigned Procedure::frameSize() const
 {
     return code().frameSize();
index 3975166..d1c722f 100644 (file)
@@ -212,8 +212,11 @@ public:
     unsigned callArgAreaSizeInBytes() const;
     void requestCallArgAreaSizeInBytes(unsigned size);
 
+    // This tells the register allocators to stay away from this register.
+    JS_EXPORT_PRIVATE void pinRegister(Reg);
+
     JS_EXPORT_PRIVATE unsigned frameSize() const;
-    const RegisterAtOffsetList& calleeSaveRegisters() const;
+    JS_EXPORT_PRIVATE const RegisterAtOffsetList& calleeSaveRegisters() const;
 
     PCToOriginMap& pcToOriginMap() { return m_pcToOriginMap; }
     PCToOriginMap releasePCToOriginMap() { return WTFMove(m_pcToOriginMap); }
index 0d0fda3..79e2c0c 100644 (file)
@@ -40,12 +40,51 @@ Code::Code(Procedure& proc)
     : m_proc(proc)
     , m_lastPhaseName("initial")
 {
+    // Come up with initial orderings of registers. The user may replace this with something else.
+    Arg::forEachType(
+        [&] (Arg::Type type) {
+            Vector<Reg> result;
+            RegisterSet all = type == Arg::GP ? RegisterSet::allGPRs() : RegisterSet::allFPRs();
+            all.exclude(RegisterSet::stackRegisters());
+            all.exclude(RegisterSet::reservedHardwareRegisters());
+            RegisterSet calleeSave = RegisterSet::calleeSaveRegisters();
+            all.forEach(
+                [&] (Reg reg) {
+                    if (!calleeSave.get(reg))
+                        result.append(reg);
+                });
+            all.forEach(
+                [&] (Reg reg) {
+                    if (calleeSave.get(reg))
+                        result.append(reg);
+                });
+            setRegsInPriorityOrder(type, result);
+        });
 }
 
 Code::~Code()
 {
 }
 
+void Code::setRegsInPriorityOrder(Arg::Type type, const Vector<Reg>& regs)
+{
+    regsInPriorityOrderImpl(type) = regs;
+    m_mutableRegs = RegisterSet();
+    Arg::forEachType(
+        [&] (Arg::Type type) {
+            for (Reg reg : regsInPriorityOrder(type))
+                m_mutableRegs.set(reg);
+        });
+}
+
+void Code::pinRegister(Reg reg)
+{
+    Vector<Reg>& regs = regsInPriorityOrderImpl(Arg(Tmp(reg)).type());
+    regs.removeFirst(reg);
+    m_mutableRegs.clear(reg);
+    ASSERT(!regs.contains(reg));
+}
+
 BasicBlock* Code::addBlock(double frequency)
 {
     std::unique_ptr<BasicBlock> block(new BasicBlock(m_blocks.size(), frequency));
index 48314b2..83cb2e1 100644 (file)
@@ -63,6 +63,27 @@ public:
     ~Code();
 
     Procedure& proc() { return m_proc; }
+    
+    const Vector<Reg>& regsInPriorityOrder(Arg::Type type) const
+    {
+        switch (type) {
+        case Arg::GP:
+            return m_gpRegsInPriorityOrder;
+        case Arg::FP:
+            return m_fpRegsInPriorityOrder;
+        }
+        ASSERT_NOT_REACHED();
+    }
+    
+    void setRegsInPriorityOrder(Arg::Type, const Vector<Reg>&);
+    
+    // This is the set of registers that Air is allowed to emit code to mutate. It's derived from
+    // regsInPriorityOrder. Any registers not in this set are said to be "pinned".
+    const RegisterSet& mutableRegs() const { return m_mutableRegs; }
+    
+    bool isPinned(Reg reg) const { return !mutableRegs().get(reg); }
+    
+    void pinRegister(Reg);
 
     JS_EXPORT_PRIVATE BasicBlock* addBlock(double frequency = 1);
 
@@ -250,7 +271,21 @@ private:
     
     Code(Procedure&);
 
+    Vector<Reg>& regsInPriorityOrderImpl(Arg::Type type)
+    {
+        switch (type) {
+        case Arg::GP:
+            return m_gpRegsInPriorityOrder;
+        case Arg::FP:
+            return m_fpRegsInPriorityOrder;
+        }
+        ASSERT_NOT_REACHED();
+    }
+
     Procedure& m_proc; // Some meta-data, like byproducts, is stored in the Procedure.
+    Vector<Reg> m_gpRegsInPriorityOrder;
+    Vector<Reg> m_fpRegsInPriorityOrder;
+    RegisterSet m_mutableRegs;
     SparseCollection<StackSlot> m_stackSlots;
     Vector<std::unique_ptr<BasicBlock>> m_blocks;
     SparseCollection<Special> m_specials;
index 5faf133..3184719 100644 (file)
@@ -28,8 +28,8 @@
 
 #if ENABLE(B3_JIT)
 
+#include "AirCode.h"
 #include "AirInstInlines.h"
-#include "AirRegisterPriority.h"
 #include <wtf/GraphNodeWorklist.h>
 #include <wtf/ListDump.h>
 
@@ -40,8 +40,8 @@ namespace {
 bool verbose = false;
 
 template<typename Functor>
-Tmp findPossibleScratch(Arg::Type type, const Functor& functor) {
-    for (Reg reg : regsInPriorityOrder(type)) {
+Tmp findPossibleScratch(Code& code, Arg::Type type, const Functor& functor) {
+    for (Reg reg : code.regsInPriorityOrder(type)) {
         Tmp tmp(reg);
         if (functor(tmp))
             return tmp;
@@ -49,9 +49,9 @@ Tmp findPossibleScratch(Arg::Type type, const Functor& functor) {
     return Tmp();
 }
 
-Tmp findPossibleScratch(Arg::Type type, const Arg& arg1, const Arg& arg2) {
+Tmp findPossibleScratch(Code& code, Arg::Type type, const Arg& arg1, const Arg& arg2) {
     return findPossibleScratch(
-        type,
+        code, type,
         [&] (Tmp tmp) -> bool {
             return !arg1.usesTmp(tmp) && !arg2.usesTmp(tmp);
         });
@@ -79,7 +79,8 @@ Inst createShuffle(Value* origin, const Vector<ShufflePair>& pairs)
 }
 
 Vector<Inst> emitShuffle(
-    Vector<ShufflePair> pairs, std::array<Arg, 2> scratches, Arg::Type type, Value* origin)
+    Code& code, Vector<ShufflePair> pairs, std::array<Arg, 2> scratches, Arg::Type type,
+    Value* origin)
 {
     if (verbose) {
         dataLog(
@@ -303,7 +304,7 @@ Vector<Inst> emitShuffle(
         
         if (!isValidForm(move, pair.src().kind(), pair.dst().kind())) {
             Tmp scratch =
-                getScratch(scratchIndex, findPossibleScratch(type, pair.src(), pair.dst()));
+                getScratch(scratchIndex, findPossibleScratch(code, type, pair.src(), pair.dst()));
             RELEASE_ASSERT(scratch);
             if (isValidForm(move, pair.src().kind(), Arg::Tmp))
                 result.append(Inst(moveForWidth(pair.width()), origin, pair.src(), scratch));
@@ -435,7 +436,7 @@ Vector<Inst> emitShuffle(
                     // Moving data between two spills is rare. To get here a lot of rare stuff has to
                     // all happen at once.
                     
-                    Tmp scratch = getScratch(0, findPossibleScratch(type, left, right));
+                    Tmp scratch = getScratch(0, findPossibleScratch(code, type, left, right));
                     RELEASE_ASSERT(scratch);
                     result.append(Inst(moveForWidth(swapWidth), origin, left, scratch));
                     result.append(Inst(swap, origin, scratch, right));
@@ -469,7 +470,7 @@ Vector<Inst> emitShuffle(
             // available register file.
 
             Tmp scratch = findPossibleScratch(
-                type,
+                code, type,
                 [&] (Tmp tmp) -> bool {
                     for (ShufflePair pair : rotate.loop) {
                         if (pair.src().usesTmp(tmp))
@@ -512,7 +513,7 @@ Vector<Inst> emitShuffle(
 }
 
 Vector<Inst> emitShuffle(
-    const Vector<ShufflePair>& pairs,
+    Code& code, const Vector<ShufflePair>& pairs,
     const std::array<Arg, 2>& gpScratch, const std::array<Arg, 2>& fpScratch,
     Value* origin)
 {
@@ -531,8 +532,8 @@ Vector<Inst> emitShuffle(
     }
 
     Vector<Inst> result;
-    result.appendVector(emitShuffle(gpPairs, gpScratch, Arg::GP, origin));
-    result.appendVector(emitShuffle(fpPairs, fpScratch, Arg::FP, origin));
+    result.appendVector(emitShuffle(code, gpPairs, gpScratch, Arg::GP, origin));
+    result.appendVector(emitShuffle(code, fpPairs, fpScratch, Arg::FP, origin));
     return result;
 }
 
index b8b57e0..b2c3bb0 100644 (file)
@@ -37,6 +37,8 @@ class Value;
 
 namespace Air {
 
+class Code;
+
 class ShufflePair {
 public:
     ShufflePair()
@@ -100,12 +102,12 @@ Inst createShuffle(Value* origin, const Vector<ShufflePair>&);
 // NOTE: Use this method (and its friend below) to emit shuffles after register allocation. Before
 // register allocation it is much better to simply use the Shuffle instruction.
 Vector<Inst> emitShuffle(
-    Vector<ShufflePair>, std::array<Arg, 2> scratch, Arg::Type, Value* origin);
+    Code& code, Vector<ShufflePair>, std::array<Arg, 2> scratch, Arg::Type, Value* origin);
 
 // Perform a shuffle that involves any number of types. Pass scratch registers or memory locations
 // for each type according to the rules above.
 Vector<Inst> emitShuffle(
-    const Vector<ShufflePair>&,
+    Code& code, const Vector<ShufflePair>&,
     const std::array<Arg, 2>& gpScratch, const std::array<Arg, 2>& fpScratch,
     Value* origin);
 
index 11c7aa4..97cdfa1 100644 (file)
@@ -55,6 +55,7 @@ void handleCalleeSaves(Code& code)
 
     // Now we filter to really get the callee saves.
     usedCalleeSaves.filter(RegisterSet::calleeSaveRegisters());
+    usedCalleeSaves.filter(code.mutableRegs());
     usedCalleeSaves.exclude(RegisterSet::stackRegisters()); // We don't need to save FP here.
 
     if (!usedCalleeSaves.numberOfSetRegisters())
index 2989d52..f561982 100644 (file)
@@ -33,7 +33,6 @@
 #include "AirInstInlines.h"
 #include "AirLiveness.h"
 #include "AirPhaseScope.h"
-#include "AirRegisterPriority.h"
 #include "AirTmpInlines.h"
 #include "AirTmpWidth.h"
 #include "AirUseCounts.h"
@@ -57,8 +56,11 @@ public:
         , m_lastPrecoloredRegisterIndex(lastPrecoloredRegisterIndex)
         , m_unspillableTmps(unspillableTmp)
     {
+        for (Reg reg : m_regsInPriorityOrder)
+            m_mutableRegs.set(reg);
+        
         initializeDegrees(tmpArraySize);
-
+        
         m_adjacencyList.resize(tmpArraySize);
         m_moveList.resize(tmpArraySize);
         m_coalescedTmps.fill(0, tmpArraySize);
@@ -161,7 +163,7 @@ protected:
             std::swap(u, v);
 
         if (traceDebug)
-            dataLog("Coalescing move at index", moveIndex, " u = ", u, " v = ", v, "\n");
+            dataLog("Coalescing move at index ", moveIndex, " u = ", u, " v = ", v, "\n");
 
         if (u == v) {
             addWorkList(u);
@@ -461,8 +463,15 @@ private:
 
     bool precoloredCoalescingHeuristic(IndexType u, IndexType v)
     {
+        if (traceDebug)
+            dataLog("    Checking precoloredCoalescingHeuristic\n");
         ASSERT(isPrecolored(u));
         ASSERT(!isPrecolored(v));
+        
+        // If u is a pinned register then it's always safe to coalesce. Note that when we call this,
+        // we have already proved that there is no interference between u and v.
+        if (!m_mutableRegs.get(m_coloredTmp[u]))
+            return true;
 
         // If any adjacent of the non-colored node is not an adjacent of the colored node AND has a degree >= K
         // there is a risk that this node needs to have the same color as our precolored node. If we coalesce such
@@ -549,6 +558,7 @@ protected:
     typedef SimpleClassHashTraits<InterferenceEdge> InterferenceEdgeHashTraits;
 
     const Vector<Reg>& m_regsInPriorityOrder;
+    RegisterSet m_mutableRegs;
     IndexType m_lastPrecoloredRegisterIndex { 0 };
 
     // The interference graph.
@@ -727,7 +737,7 @@ template<Arg::Type type>
 class ColoringAllocator : public AbstractColoringAllocator<unsigned> {
 public:
     ColoringAllocator(Code& code, TmpWidth& tmpWidth, const UseCounts<Tmp>& useCounts, const HashSet<unsigned>& unspillableTmp)
-        : AbstractColoringAllocator<unsigned>(regsInPriorityOrder(type), AbsoluteTmpMapper<type>::lastMachineRegisterIndex(), tmpArraySize(code), unspillableTmp)
+        : AbstractColoringAllocator<unsigned>(code.regsInPriorityOrder(type), AbsoluteTmpMapper<type>::lastMachineRegisterIndex(), tmpArraySize(code), unspillableTmp)
         , m_code(code)
         , m_tmpWidth(tmpWidth)
         , m_useCounts(useCounts)
@@ -839,7 +849,7 @@ public:
         if (!reg) {
             // We only care about Tmps that interfere. A Tmp that never interfere with anything
             // can take any register.
-            reg = regsInPriorityOrder(type).first();
+            reg = m_code.regsInPriorityOrder(type).first();
         }
         return reg;
     }
index a4a19a1..e001873 100644 (file)
@@ -36,7 +36,6 @@
 #include "AirInstInlines.h"
 #include "AirLiveness.h"
 #include "AirPhaseScope.h"
-#include "AirRegisterPriority.h"
 #include "B3CCallValue.h"
 #include "B3ValueInlines.h"
 #include "RegisterSet.h"
@@ -86,7 +85,7 @@ void lowerAfterRegAlloc(Code& code)
         std::array<Arg, 2> result;
         for (unsigned i = 0; i < 2; ++i) {
             bool found = false;
-            for (Reg reg : regsInPriorityOrder(type)) {
+            for (Reg reg : code.regsInPriorityOrder(type)) {
                 if (!set.get(reg)) {
                     result[i] = Tmp(reg);
                     set.set(reg);
@@ -134,7 +133,7 @@ void lowerAfterRegAlloc(Code& code)
                 std::array<Arg, 2> gpScratch = getScratches(set, Arg::GP);
                 std::array<Arg, 2> fpScratch = getScratches(set, Arg::FP);
                 insertionSet.insertInsts(
-                    instIndex, emitShuffle(pairs, gpScratch, fpScratch, inst.origin));
+                    instIndex, emitShuffle(code, pairs, gpScratch, fpScratch, inst.origin));
                 inst = Inst();
                 break;
             }
@@ -193,7 +192,7 @@ void lowerAfterRegAlloc(Code& code)
                     dataLog("Pre-call pairs for ", inst, ": ", listDump(pairs), "\n");
                 
                 insertionSet.insertInsts(
-                    instIndex, emitShuffle(pairs, gpScratch, fpScratch, inst.origin));
+                    instIndex, emitShuffle(code, pairs, gpScratch, fpScratch, inst.origin));
 
                 inst = buildCCall(code, inst.origin, destinations);
                 if (oldKind.traps)
@@ -224,7 +223,7 @@ void lowerAfterRegAlloc(Code& code)
                 fpScratch = getScratches(liveRegs, Arg::FP);
                 
                 insertionSet.insertInsts(
-                    instIndex + 1, emitShuffle(pairs, gpScratch, fpScratch, inst.origin));
+                    instIndex + 1, emitShuffle(code, pairs, gpScratch, fpScratch, inst.origin));
                 break;
             }
 
diff --git a/Source/JavaScriptCore/b3/air/AirRegisterPriority.cpp b/Source/JavaScriptCore/b3/air/AirRegisterPriority.cpp
deleted file mode 100644 (file)
index f535884..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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 "AirRegisterPriority.h"
-
-#if ENABLE(B3_JIT)
-
-#include "RegisterSet.h"
-
-namespace JSC { namespace B3 { namespace Air {
-
-const Vector<GPRReg>& gprsInPriorityOrder()
-{
-    static Vector<GPRReg>* result;
-    static std::once_flag once;
-    std::call_once(
-        once,
-        [] {
-            result = new Vector<GPRReg>();
-            RegisterSet all = RegisterSet::allGPRs();
-            all.exclude(RegisterSet::stackRegisters());
-            all.exclude(RegisterSet::reservedHardwareRegisters());
-            RegisterSet calleeSave = RegisterSet::calleeSaveRegisters();
-            all.forEach(
-                [&] (Reg reg) {
-                    if (!calleeSave.get(reg))
-                        result->append(reg.gpr());
-                });
-            all.forEach(
-                [&] (Reg reg) {
-                    if (calleeSave.get(reg))
-                        result->append(reg.gpr());
-                });
-        });
-    return *result;
-}
-
-const Vector<FPRReg>& fprsInPriorityOrder()
-{
-    static Vector<FPRReg>* result;
-    static std::once_flag once;
-    std::call_once(
-        once,
-        [] {
-            result = new Vector<FPRReg>();
-            RegisterSet all = RegisterSet::allFPRs();
-            RegisterSet calleeSave = RegisterSet::calleeSaveRegisters();
-            all.forEach(
-                [&] (Reg reg) {
-                    if (!calleeSave.get(reg))
-                        result->append(reg.fpr());
-                });
-            all.forEach(
-                [&] (Reg reg) {
-                    if (calleeSave.get(reg))
-                        result->append(reg.fpr());
-                });
-        });
-    return *result;
-}
-
-const Vector<Reg>& regsInPriorityOrder(Arg::Type type)
-{
-    static Vector<Reg>* result[Arg::numTypes];
-    static std::once_flag once;
-    std::call_once(
-        once,
-        [] {
-            result[Arg::GP] = new Vector<Reg>();
-            for (GPRReg reg : gprsInPriorityOrder())
-                result[Arg::GP]->append(Reg(reg));
-            result[Arg::FP] = new Vector<Reg>();
-            for (FPRReg reg : fprsInPriorityOrder())
-                result[Arg::FP]->append(Reg(reg));
-        });
-    return *result[type];
-}
-
-} } } // namespace JSC::B3::Air
-
-#endif // ENABLE(B3_JIT)
diff --git a/Source/JavaScriptCore/b3/air/AirRegisterPriority.h b/Source/JavaScriptCore/b3/air/AirRegisterPriority.h
deleted file mode 100644 (file)
index 842083c..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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)
-
-#include "AirArg.h"
-#include "FPRInfo.h"
-#include "GPRInfo.h"
-#include <wtf/Vector.h>
-
-namespace JSC { namespace B3 { namespace Air {
-
-const Vector<GPRReg>& gprsInPriorityOrder();
-const Vector<FPRReg>& fprsInPriorityOrder();
-
-template<typename Bank> struct RegistersInPriorityOrder;
-template<> struct RegistersInPriorityOrder<GPRInfo> {
-    const Vector<GPRReg>& inPriorityOrder() { return gprsInPriorityOrder(); }
-};
-template<> struct RegistersInPriorityOrder<FPRInfo> {
-    const Vector<FPRReg>& inPriorityOrder() { return fprsInPriorityOrder(); }
-};
-
-template<typename Bank>
-const Vector<typename Bank::RegisterType>& regsInPriorityOrder()
-{
-    return RegistersInPriorityOrder<Bank>::inPriorityOrder();
-}
-
-JS_EXPORT_PRIVATE const Vector<Reg>& regsInPriorityOrder(Arg::Type);
-
-} } } // namespace JSC::B3::Air
-
-#endif // ENABLE(B3_JIT)
index 1676705..35d412e 100644 (file)
@@ -34,7 +34,6 @@
 #include "AirInstInlines.h"
 #include "AirLiveness.h"
 #include "AirPhaseScope.h"
-#include "AirRegisterPriority.h"
 #include <wtf/IndexMap.h>
 
 namespace JSC { namespace B3 { namespace Air {
@@ -129,7 +128,7 @@ void spillEverything(Code& code)
                     switch (role) {
                     case Arg::Use:
                     case Arg::ColdUse:
-                        for (Reg reg : regsInPriorityOrder(type)) {
+                        for (Reg reg : code.regsInPriorityOrder(type)) {
                             if (!setBefore.get(reg)) {
                                 setBefore.set(reg);
                                 chosenReg = reg;
@@ -139,7 +138,7 @@ void spillEverything(Code& code)
                         break;
                     case Arg::Def:
                     case Arg::ZDef:
-                        for (Reg reg : regsInPriorityOrder(type)) {
+                        for (Reg reg : code.regsInPriorityOrder(type)) {
                             if (!setAfter.get(reg)) {
                                 setAfter.set(reg);
                                 chosenReg = reg;
@@ -153,7 +152,7 @@ void spillEverything(Code& code)
                     case Arg::LateColdUse:
                     case Arg::Scratch:
                     case Arg::EarlyDef:
-                        for (Reg reg : regsInPriorityOrder(type)) {
+                        for (Reg reg : code.regsInPriorityOrder(type)) {
                             if (!setBefore.get(reg) && !setAfter.get(reg)) {
                                 setAfter.set(reg);
                                 setBefore.set(reg);
index f77d50f..9f8a8d8 100644 (file)
@@ -28,7 +28,6 @@
 #include "AirCode.h"
 #include "AirGenerate.h"
 #include "AirInstInlines.h"
-#include "AirRegisterPriority.h"
 #include "AllowMacroScratchRegisterUsage.h"
 #include "B3Compilation.h"
 #include "B3Procedure.h"
@@ -393,7 +392,7 @@ void testShuffleBroadcastAllRegs()
     B3::Procedure proc;
     Code& code = proc.code();
 
-    const Vector<Reg>& regs = regsInPriorityOrder(Arg::GP);
+    const Vector<Reg>& regs = code.regsInPriorityOrder(Arg::GP);
 
     BasicBlock* root = code.addBlock();
     root->append(Move, nullptr, Arg::imm(35), Tmp(GPRInfo::regT0));
@@ -860,7 +859,7 @@ void testShuffleShiftAllRegs()
     B3::Procedure proc;
     Code& code = proc.code();
 
-    const Vector<Reg>& regs = regsInPriorityOrder(Arg::GP);
+    const Vector<Reg>& regs = code.regsInPriorityOrder(Arg::GP);
 
     BasicBlock* root = code.addBlock();
     for (unsigned i = 0; i < regs.size(); ++i)
@@ -896,7 +895,7 @@ void testShuffleRotateAllRegs()
     B3::Procedure proc;
     Code& code = proc.code();
 
-    const Vector<Reg>& regs = regsInPriorityOrder(Arg::GP);
+    const Vector<Reg>& regs = code.regsInPriorityOrder(Arg::GP);
 
     BasicBlock* root = code.addBlock();
     for (unsigned i = 0; i < regs.size(); ++i)
@@ -1168,7 +1167,7 @@ void testShuffleShiftMemoryAllRegs()
     memory[0] = 35;
     memory[1] = 36;
 
-    Vector<Reg> regs = regsInPriorityOrder(Arg::GP);
+    Vector<Reg> regs = code.regsInPriorityOrder(Arg::GP);
     regs.removeFirst(Reg(GPRInfo::regT0));
 
     BasicBlock* root = code.addBlock();
@@ -1218,7 +1217,7 @@ void testShuffleShiftMemoryAllRegs64()
     memory[0] = 35000000000000ll;
     memory[1] = 36000000000000ll;
 
-    Vector<Reg> regs = regsInPriorityOrder(Arg::GP);
+    Vector<Reg> regs = code.regsInPriorityOrder(Arg::GP);
     regs.removeFirst(Reg(GPRInfo::regT0));
 
     BasicBlock* root = code.addBlock();
@@ -1279,7 +1278,7 @@ void testShuffleShiftMemoryAllRegsMixedWidth()
     memory[0] = 35000000000000ll;
     memory[1] = 36000000000000ll;
 
-    Vector<Reg> regs = regsInPriorityOrder(Arg::GP);
+    Vector<Reg> regs = code.regsInPriorityOrder(Arg::GP);
     regs.removeFirst(Reg(GPRInfo::regT0));
 
     BasicBlock* root = code.addBlock();
@@ -1469,7 +1468,7 @@ void testShuffleRotateMemoryAllRegs64()
     memory[0] = 35000000000000ll;
     memory[1] = 36000000000000ll;
 
-    Vector<Reg> regs = regsInPriorityOrder(Arg::GP);
+    Vector<Reg> regs = code.regsInPriorityOrder(Arg::GP);
     regs.removeFirst(Reg(GPRInfo::regT0));
 
     BasicBlock* root = code.addBlock();
@@ -1521,7 +1520,7 @@ void testShuffleRotateMemoryAllRegsMixedWidth()
     memory[0] = 35000000000000ll;
     memory[1] = 36000000000000ll;
 
-    Vector<Reg> regs = regsInPriorityOrder(Arg::GP);
+    Vector<Reg> regs = code.regsInPriorityOrder(Arg::GP);
     regs.removeFirst(Reg(GPRInfo::regT0));
 
     BasicBlock* root = code.addBlock();
index 523dad8..4b47b13 100644 (file)
@@ -13327,6 +13327,60 @@ void testPCOriginMapDoesntInsertNops()
     compile(proc);
 }
 
+void testPinRegisters()
+{
+    auto go = [&] (bool pin) {
+        Procedure proc;
+        RegisterSet csrs;
+        csrs.merge(RegisterSet::calleeSaveRegisters());
+        csrs.exclude(RegisterSet::stackRegisters());
+        if (pin) {
+            csrs.forEach(
+                [&] (Reg reg) {
+                    proc.pinRegister(reg);
+                });
+        }
+        BasicBlock* root = proc.addBlock();
+        Value* a = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+        Value* b = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
+        Value* c = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
+        Value* d = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::regCS0);
+        root->appendNew<CCallValue>(
+            proc, Void, Origin(),
+            root->appendNew<ConstPtrValue>(proc, Origin(), static_cast<intptr_t>(0x1234)));
+        root->appendNew<CCallValue>(
+            proc, Void, Origin(),
+            root->appendNew<ConstPtrValue>(proc, Origin(), static_cast<intptr_t>(0x1235)),
+            a, b, c);
+        PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
+        patchpoint->appendSomeRegister(d);
+        patchpoint->setGenerator(
+            [&] (CCallHelpers&, const StackmapGenerationParams& params) {
+                CHECK_EQ(params[0].gpr(), GPRInfo::regCS0);
+            });
+        root->appendNew<Value>(proc, Return, Origin());
+        auto code = compile(proc);
+        bool usesCSRs = false;
+        for (Air::BasicBlock* block : proc.code()) {
+            for (Air::Inst& inst : *block) {
+                if (inst.kind.opcode == Air::Patch && inst.origin == patchpoint)
+                    continue;
+                inst.forEachTmpFast(
+                    [&] (Air::Tmp tmp) {
+                        if (tmp.isReg())
+                            usesCSRs |= csrs.get(tmp.reg());
+                    });
+            }
+        }
+        for (const RegisterAtOffset& regAtOffset : proc.calleeSaveRegisters())
+            usesCSRs |= csrs.get(regAtOffset.reg());
+        CHECK_EQ(usesCSRs, !pin);
+    };
+    
+    go(true);
+    go(false);
+}
+
 // Make sure the compiler does not try to optimize anything out.
 NEVER_INLINE double zero()
 {
@@ -14774,6 +14828,7 @@ void run(const char* filter)
     RUN(testTrappingStoreElimination());
     RUN(testMoveConstants());
     RUN(testPCOriginMapDoesntInsertNops());
+    RUN(testPinRegisters());
     
     if (tasks.isEmpty())
         usage();
index d788bf4..aec53c9 100644 (file)
@@ -48,7 +48,7 @@ public:
     JS_EXPORT_PRIVATE static RegisterSet reservedHardwareRegisters();
     static RegisterSet runtimeRegisters();
     static RegisterSet specialRegisters(); // The union of stack, reserved hardware, and runtime registers.
-    static RegisterSet calleeSaveRegisters();
+    JS_EXPORT_PRIVATE static RegisterSet calleeSaveRegisters();
     static RegisterSet vmCalleeSaveRegisters(); // Callee save registers that might be saved and used by any tier.
     static RegisterSet llintBaselineCalleeSaveRegisters(); // Registers saved and used by the LLInt.
     static RegisterSet dfgCalleeSaveRegisters(); // Registers saved and used by the DFG JIT.
@@ -107,7 +107,7 @@ public:
     size_t numberOfSetFPRs() const;
     size_t numberOfSetRegisters() const { return m_bits.count(); }
     
-    void dump(PrintStream&) const;
+    JS_EXPORT_PRIVATE void dump(PrintStream&) const;
     
     enum EmptyValueTag { EmptyValue };
     enum DeletedValueTag { DeletedValue };