Teach Call ICs how to call Wasm
[WebKit-https.git] / Source / JavaScriptCore / jit / RegisterSet.h
index 22f403f..ae42323 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-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
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
-#ifndef RegisterSet_h
-#define RegisterSet_h
+#pragma once
 
-#if ENABLE(JIT)
+#if !ENABLE(C_LOOP)
 
-#include "FPRInfo.h"
 #include "GPRInfo.h"
 #include "MacroAssembler.h"
 #include "Reg.h"
 #include "TempRegisterSet.h"
-#include <wtf/BitVector.h>
+#include <wtf/Bitmap.h>
 
 namespace JSC {
 
+typedef Bitmap<MacroAssembler::numGPRs + MacroAssembler::numFPRs + 1> RegisterBitmap;
+class RegisterAtOffsetList;
+
 class RegisterSet {
 public:
-    RegisterSet() { }
+    constexpr RegisterSet() { }
+
+    template<typename... Regs>
+    constexpr explicit RegisterSet(Regs... regs)
+    {
+        setMany(regs...);
+    }
     
-    static RegisterSet stackRegisters();
-    static RegisterSet reservedHardwareRegisters();
-    static RegisterSet runtimeRegisters();
+    JS_EXPORT_PRIVATE static RegisterSet stackRegisters();
+    JS_EXPORT_PRIVATE static RegisterSet reservedHardwareRegisters();
+    static RegisterSet runtimeTagRegisters();
     static RegisterSet specialRegisters(); // The union of stack, reserved hardware, and runtime registers.
-    static RegisterSet calleeSaveRegisters();
-    static RegisterSet allGPRs();
-    static RegisterSet allFPRs();
+    JS_EXPORT_PRIVATE static RegisterSet calleeSaveRegisters();
+    static RegisterSet vmCalleeSaveRegisters(); // Callee save registers that might be saved and used by any tier.
+    static RegisterAtOffsetList* vmCalleeSaveRegisterOffsets();
+    static RegisterSet llintBaselineCalleeSaveRegisters(); // Registers saved and used by the LLInt.
+    static RegisterSet dfgCalleeSaveRegisters(); // Registers saved and used by the DFG JIT.
+    static RegisterSet ftlCalleeSaveRegisters(); // Registers that might be saved and used by the FTL JIT.
+#if ENABLE(WEBASSEMBLY)
+    static RegisterSet webAssemblyCalleeSaveRegisters(); // Registers saved and used by the WebAssembly JIT.
+#endif
+    static RegisterSet volatileRegistersForJSCall();
+    static RegisterSet stubUnavailableRegisters(); // The union of callee saves and special registers.
+    JS_EXPORT_PRIVATE static RegisterSet macroScratchRegisters();
+    JS_EXPORT_PRIVATE static RegisterSet allGPRs();
+    JS_EXPORT_PRIVATE static RegisterSet allFPRs();
     static RegisterSet allRegisters();
+    JS_EXPORT_PRIVATE static RegisterSet argumentGPRS();
+
+    static RegisterSet registersToNotSaveForJSCall();
+    static RegisterSet registersToNotSaveForCCall();
     
     void set(Reg reg, bool value = true)
     {
         ASSERT(!!reg);
-        m_vector.set(reg.index(), value);
+        m_bits.set(reg.index(), value);
     }
-
-    void set(JSValueRegs regs)
+    
+    void set(JSValueRegs regs, bool value = true)
     {
         if (regs.tagGPR() != InvalidGPRReg)
-            set(regs.tagGPR());
-        set(regs.payloadGPR());
+            set(regs.tagGPR(), value);
+        set(regs.payloadGPR(), value);
     }
     
     void clear(Reg reg)
@@ -72,40 +94,136 @@ public:
     bool get(Reg reg) const
     {
         ASSERT(!!reg);
-        return m_vector.get(reg.index());
+        return m_bits.get(reg.index());
+    }
+    
+    template<typename Iterable>
+    void setAll(const Iterable& iterable)
+    {
+        for (Reg reg : iterable)
+            set(reg);
+    }
+    
+    // Also allow add/remove/contains terminology, which means the same thing as set/clear/get.
+    bool add(Reg reg)
+    {
+        ASSERT(!!reg);
+        return !m_bits.testAndSet(reg.index());
     }
+    bool remove(Reg reg)
+    {
+        ASSERT(!!reg);
+        return m_bits.testAndClear(reg.index());
+    }
+    bool contains(Reg reg) const { return get(reg); }
+    
+    void merge(const RegisterSet& other) { m_bits.merge(other.m_bits); }
+    void filter(const RegisterSet& other) { m_bits.filter(other.m_bits); }
+    void exclude(const RegisterSet& other) { m_bits.exclude(other.m_bits); }
     
-    void merge(const RegisterSet& other) { m_vector.merge(other.m_vector); }
-    void filter(const RegisterSet& other) { m_vector.filter(other.m_vector); }
-    void exclude(const RegisterSet& other) { m_vector.exclude(other.m_vector); }
+    bool subsumes(const RegisterSet& other) const { return m_bits.subsumes(other.m_bits); }
     
     size_t numberOfSetGPRs() const;
     size_t numberOfSetFPRs() const;
-    size_t numberOfSetRegisters() const { return m_vector.bitCount(); }
+    size_t numberOfSetRegisters() const { return m_bits.count(); }
     
-    void dump(PrintStream&) const;
+    bool isEmpty() const { return m_bits.isEmpty(); }
+    
+    JS_EXPORT_PRIVATE void dump(PrintStream&) const;
     
     enum EmptyValueTag { EmptyValue };
     enum DeletedValueTag { DeletedValue };
     
     RegisterSet(EmptyValueTag)
-        : m_vector(BitVector::EmptyValue)
     {
+        m_bits.set(hashSpecialBitIndex);
     }
     
     RegisterSet(DeletedValueTag)
-        : m_vector(BitVector::DeletedValue)
     {
+        m_bits.set(hashSpecialBitIndex);
+        m_bits.set(deletedBitIndex);
+    }
+    
+    bool isEmptyValue() const
+    {
+        return m_bits.get(hashSpecialBitIndex) && !m_bits.get(deletedBitIndex);
+    }
+    
+    bool isDeletedValue() const
+    {
+        return m_bits.get(hashSpecialBitIndex) && m_bits.get(deletedBitIndex);
+    }
+    
+    bool operator==(const RegisterSet& other) const { return m_bits == other.m_bits; }
+    bool operator!=(const RegisterSet& other) const { return m_bits != other.m_bits; }
+    
+    unsigned hash() const { return m_bits.hash(); }
+    
+    template<typename Func>
+    void forEach(const Func& func) const
+    {
+        m_bits.forEachSetBit(
+            [&] (size_t index) {
+                func(Reg::fromIndex(index));
+            });
     }
     
-    bool isEmptyValue() const { return m_vector.isEmptyValue(); }
-    bool isDeletedValue() const { return m_vector.isDeletedValue(); }
+    class iterator {
+    public:
+        iterator()
+        {
+        }
+        
+        iterator(const RegisterBitmap::iterator& iter)
+            : m_iter(iter)
+        {
+        }
+        
+        Reg operator*() const { return Reg::fromIndex(*m_iter); }
+        
+        iterator& operator++()
+        {
+            ++m_iter;
+            return *this;
+        }
+        
+        bool operator==(const iterator& other)
+        {
+            return m_iter == other.m_iter;
+        }
+        
+        bool operator!=(const iterator& other)
+        {
+            return !(*this == other);
+        }
+        
+    private:
+        RegisterBitmap::iterator m_iter;
+    };
     
-    bool operator==(const RegisterSet& other) const { return m_vector == other.m_vector; }
-    unsigned hash() const { return m_vector.hash(); }
+    iterator begin() const { return iterator(m_bits.begin()); }
+    iterator end() const { return iterator(m_bits.end()); }
     
 private:
-    BitVector m_vector;
+    void setAny(Reg reg) { set(reg); }
+    void setAny(JSValueRegs regs) { set(regs); }
+    void setAny(const RegisterSet& set) { merge(set); }
+    void setMany() { }
+    template<typename RegType, typename... Regs>
+    void setMany(RegType reg, Regs... regs)
+    {
+        setAny(reg);
+        setMany(regs...);
+    }
+
+    // These offsets mirror the logic in Reg.h.
+    static const unsigned gprOffset = 0;
+    static const unsigned fprOffset = gprOffset + MacroAssembler::numGPRs;
+    static const unsigned hashSpecialBitIndex = fprOffset + MacroAssembler::numFPRs;
+    static const unsigned deletedBitIndex = 0;
+    
+    RegisterBitmap m_bits;
 };
 
 struct RegisterSetHash {
@@ -128,7 +246,4 @@ template<> struct HashTraits<JSC::RegisterSet> : public CustomHashTraits<JSC::Re
 
 } // namespace WTF
 
-#endif // ENABLE(JIT)
-
-#endif // RegisterSet_h
-
+#endif // !ENABLE(C_LOOP)