Make CSS JIT run on ARM64.
[WebKit-https.git] / Source / WebCore / cssjit / StackAllocator.h
index baff9f0..54d47e5 100644 (file)
@@ -68,31 +68,83 @@ public:
         return StackReference(m_offsetFromTop);
     }
 
-    // FIXME: ARM64 needs an API take a list of register to push and pop to use strp and ldrp when possible.
-    StackReference push(JSC::MacroAssembler::RegisterID registerID)
+    Vector<StackReference> push(const Vector<JSC::MacroAssembler::RegisterID>& registerIDs)
     {
         RELEASE_ASSERT(!m_hasFunctionCallPadding);
+        unsigned registerCount = registerIDs.size();
+        Vector<StackReference> stackReferences;
+        stackReferences.reserveInitialCapacity(registerCount);
 #if CPU(ARM64)
-        m_assembler.m_assembler.str<64>(registerID, JSC::ARM64Registers::sp, JSC::PreIndex(-16));
+        for (unsigned i = 0; i < registerCount - 1; i += 2) {
+            m_assembler.pushPair(registerIDs[i + 1], registerIDs[i]);
+            m_offsetFromTop += stackUnitInBytes;
+            stackReferences.append(StackReference(m_offsetFromTop - stackUnitInBytes / 2));
+            stackReferences.append(StackReference(m_offsetFromTop));
+        }
+        if (registerCount % 2) {
+            m_assembler.pushToSave(registerIDs[registerCount - 1]);
+            m_offsetFromTop += stackUnitInBytes;
+            stackReferences.append(StackReference(m_offsetFromTop));
+        }
 #else
-        m_assembler.push(registerID);
+        for (auto registerID : registerIDs) {
+            m_assembler.pushToSave(registerID);
+            m_offsetFromTop += stackUnitInBytes;
+            stackReferences.append(StackReference(m_offsetFromTop));
+        }
 #endif
+        return stackReferences;
+    }
+
+    StackReference push(JSC::MacroAssembler::RegisterID registerID)
+    {
+        RELEASE_ASSERT(!m_hasFunctionCallPadding);
+        m_assembler.pushToSave(registerID);
         m_offsetFromTop += stackUnitInBytes;
         return StackReference(m_offsetFromTop);
     }
 
-    void pop(StackReference stackReference, JSC::MacroAssembler::RegisterID registerID)
+    void pop(const Vector<StackReference>& stackReferences, const Vector<JSC::MacroAssembler::RegisterID>& registerIDs)
     {
-        RELEASE_ASSERT(stackReference == m_offsetFromTop);
         RELEASE_ASSERT(!m_hasFunctionCallPadding);
-        ASSERT(m_offsetFromTop > 0);
-        m_offsetFromTop -= stackUnitInBytes;
+        
+        unsigned registerCount = registerIDs.size();
+        RELEASE_ASSERT(stackReferences.size() == registerCount);
 #if CPU(ARM64)
-        m_assembler.m_assembler.ldr<64>(registerID, JSC::ARM64Registers::sp, JSC::PostIndex(16));
+        ASSERT(m_offsetFromTop >= stackUnitInBytes * registerCount);
+        unsigned registerCountOdd = registerCount % 2;
+        if (registerCountOdd) {
+            RELEASE_ASSERT(stackReferences[registerCount - 1] == m_offsetFromTop);
+            RELEASE_ASSERT(m_offsetFromTop >= stackUnitInBytes);
+            m_offsetFromTop -= stackUnitInBytes;
+            m_assembler.popToRestore(registerIDs[registerCount - 1]);
+        }
+        for (unsigned i = registerCount - registerCountOdd; i > 0; i -= 2) {
+            RELEASE_ASSERT(stackReferences[i - 1] == m_offsetFromTop);
+            RELEASE_ASSERT(stackReferences[i - 2] == m_offsetFromTop - stackUnitInBytes / 2);
+            RELEASE_ASSERT(m_offsetFromTop >= stackUnitInBytes);
+            m_offsetFromTop -= stackUnitInBytes;
+            m_assembler.popPair(registerIDs[i - 1], registerIDs[i - 2]);
+        }
 #else
-        m_assembler.pop(registerID);
+        ASSERT(m_offsetFromTop >= stackUnitInBytes * registerCount);
+        for (unsigned i = registerCount; i > 0; --i) {
+            RELEASE_ASSERT(stackReferences[i - 1] == m_offsetFromTop);
+            RELEASE_ASSERT(m_offsetFromTop >= stackUnitInBytes);
+            m_offsetFromTop -= stackUnitInBytes;
+            m_assembler.popToRestore(registerIDs[i - 1]);
+        }
 #endif
     }
+    
+    void pop(StackReference stackReference, JSC::MacroAssembler::RegisterID registerID)
+    {
+        RELEASE_ASSERT(stackReference == m_offsetFromTop);
+        RELEASE_ASSERT(!m_hasFunctionCallPadding);
+        RELEASE_ASSERT(m_offsetFromTop >= stackUnitInBytes);
+        m_offsetFromTop -= stackUnitInBytes;
+        m_assembler.popToRestore(registerID);
+    }
 
     void popAndDiscard(StackReference stackReference)
     {