summaryrefslogtreecommitdiff
path: root/Source/WebCore/cssjit/RegisterAllocator.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/cssjit/RegisterAllocator.h')
-rw-r--r--Source/WebCore/cssjit/RegisterAllocator.h186
1 files changed, 164 insertions, 22 deletions
diff --git a/Source/WebCore/cssjit/RegisterAllocator.h b/Source/WebCore/cssjit/RegisterAllocator.h
index 4ba9c0fde..79923010f 100644
--- a/Source/WebCore/cssjit/RegisterAllocator.h
+++ b/Source/WebCore/cssjit/RegisterAllocator.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,8 +23,7 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef RegisterAllocator_h
-#define RegisterAllocator_h
+#pragma once
#if ENABLE(CSS_SELECTOR_JIT)
@@ -34,10 +33,51 @@
namespace WebCore {
-#if CPU(X86_64)
+#if CPU(ARM64)
+static const JSC::MacroAssembler::RegisterID callerSavedRegisters[] = {
+ JSC::ARM64Registers::x0,
+ JSC::ARM64Registers::x1,
+ JSC::ARM64Registers::x2,
+ JSC::ARM64Registers::x3,
+ JSC::ARM64Registers::x4,
+ JSC::ARM64Registers::x5,
+ JSC::ARM64Registers::x6,
+ JSC::ARM64Registers::x7,
+ JSC::ARM64Registers::x8,
+ JSC::ARM64Registers::x9,
+ JSC::ARM64Registers::x10,
+ JSC::ARM64Registers::x11,
+ JSC::ARM64Registers::x12,
+ JSC::ARM64Registers::x13,
+ JSC::ARM64Registers::x14,
+};
+static const JSC::MacroAssembler::RegisterID calleeSavedRegisters[] = {
+ JSC::ARM64Registers::x19
+};
+static const JSC::MacroAssembler::RegisterID tempRegister = JSC::ARM64Registers::x15;
+#elif CPU(ARM_THUMB2)
+static const JSC::MacroAssembler::RegisterID callerSavedRegisters[] {
+ JSC::ARMRegisters::r0,
+ JSC::ARMRegisters::r1,
+ JSC::ARMRegisters::r2,
+ JSC::ARMRegisters::r3,
+ JSC::ARMRegisters::r9,
+};
+static const JSC::MacroAssembler::RegisterID calleeSavedRegisters[] = {
+ JSC::ARMRegisters::r4,
+ JSC::ARMRegisters::r5,
+ JSC::ARMRegisters::r7,
+ JSC::ARMRegisters::r8,
+ JSC::ARMRegisters::r10,
+ JSC::ARMRegisters::r11,
+};
+// r6 is also used as addressTempRegister in the macro assembler. It is saved in the prologue and restored in the epilogue.
+static const JSC::MacroAssembler::RegisterID tempRegister = JSC::ARMRegisters::r6;
+#elif CPU(X86_64)
static const JSC::MacroAssembler::RegisterID callerSavedRegisters[] = {
JSC::X86Registers::eax,
JSC::X86Registers::ecx,
+ JSC::X86Registers::edx,
JSC::X86Registers::esi,
JSC::X86Registers::edi,
JSC::X86Registers::r8,
@@ -45,19 +85,32 @@ static const JSC::MacroAssembler::RegisterID callerSavedRegisters[] = {
JSC::X86Registers::r10,
JSC::X86Registers::r11
};
+static const JSC::MacroAssembler::RegisterID calleeSavedRegisters[] = {
+ JSC::X86Registers::r12,
+ JSC::X86Registers::r13,
+ JSC::X86Registers::r14,
+ JSC::X86Registers::r15
+};
#else
#error RegisterAllocator has no defined registers for the architecture.
#endif
+static const unsigned calleeSavedRegisterCount = WTF_ARRAY_LENGTH(calleeSavedRegisters);
+static const unsigned maximumRegisterCount = calleeSavedRegisterCount + WTF_ARRAY_LENGTH(callerSavedRegisters);
+
+typedef Vector<JSC::MacroAssembler::RegisterID, maximumRegisterCount> RegisterVector;
class RegisterAllocator {
public:
- RegisterAllocator();
+ RegisterAllocator() { }
+ ~RegisterAllocator();
+
+ unsigned availableRegisterCount() const { return m_registers.size(); }
JSC::MacroAssembler::RegisterID allocateRegister()
{
- RELEASE_ASSERT(!m_registers.isEmpty());
-
- JSC::MacroAssembler::RegisterID registerID = m_registers.takeFirst();
+ RELEASE_ASSERT(m_registers.size());
+ JSC::MacroAssembler::RegisterID registerID = m_registers.first();
+ m_registers.removeFirst();
ASSERT(!m_allocatedRegisters.contains(registerID));
m_allocatedRegisters.append(registerID);
return registerID;
@@ -65,14 +118,28 @@ public:
void allocateRegister(JSC::MacroAssembler::RegisterID registerID)
{
- ASSERT(!m_allocatedRegisters.contains(registerID));
- for (auto it = m_registers.begin(), end = m_registers.end(); it != end; ++it) {
+ for (auto it = m_registers.begin(); it != m_registers.end(); ++it) {
if (*it == registerID) {
m_registers.remove(it);
- break;
+ ASSERT(!m_allocatedRegisters.contains(registerID));
+ m_allocatedRegisters.append(registerID);
+ return;
}
}
- m_allocatedRegisters.append(registerID);
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+
+ JSC::MacroAssembler::RegisterID allocateRegisterWithPreference(JSC::MacroAssembler::RegisterID preferredRegister)
+ {
+ for (auto it = m_registers.begin(); it != m_registers.end(); ++it) {
+ if (*it == preferredRegister) {
+ m_registers.remove(it);
+ ASSERT(!m_allocatedRegisters.contains(preferredRegister));
+ m_allocatedRegisters.append(preferredRegister);
+ return preferredRegister;
+ }
+ }
+ return allocateRegister();
}
void deallocateRegister(JSC::MacroAssembler::RegisterID registerID)
@@ -81,14 +148,80 @@ public:
// Most allocation/deallocation happen in stack-like order. In the common case, this
// just removes the last item.
m_allocatedRegisters.remove(m_allocatedRegisters.reverseFind(registerID));
+ for (auto unallocatedRegister : m_registers)
+ RELEASE_ASSERT(unallocatedRegister != registerID);
m_registers.append(registerID);
}
- const Vector<JSC::MacroAssembler::RegisterID, 8>& allocatedRegisters() const { return m_allocatedRegisters; }
+ unsigned reserveCallerSavedRegisters(unsigned count)
+ {
+#ifdef NDEBUG
+ UNUSED_PARAM(count);
+ unsigned numberToAllocate = WTF_ARRAY_LENGTH(callerSavedRegisters);
+#else
+ unsigned numberToAllocate = std::min<unsigned>(WTF_ARRAY_LENGTH(callerSavedRegisters), count);
+#endif
+ for (unsigned i = 0; i < numberToAllocate; ++i)
+ m_registers.append(callerSavedRegisters[i]);
+ return numberToAllocate;
+ }
+
+ const Vector<JSC::MacroAssembler::RegisterID, calleeSavedRegisterCount>& reserveCalleeSavedRegisters(unsigned count)
+ {
+ RELEASE_ASSERT(count <= WTF_ARRAY_LENGTH(calleeSavedRegisters));
+ RELEASE_ASSERT(!m_reservedCalleeSavedRegisters.size());
+ for (unsigned i = 0; i < count; ++i) {
+ JSC::MacroAssembler::RegisterID registerId = calleeSavedRegisters[i];
+ m_reservedCalleeSavedRegisters.append(registerId);
+ m_registers.append(registerId);
+ }
+ return m_reservedCalleeSavedRegisters;
+ }
+
+ Vector<JSC::MacroAssembler::RegisterID, calleeSavedRegisterCount> restoreCalleeSavedRegisters()
+ {
+ Vector<JSC::MacroAssembler::RegisterID, calleeSavedRegisterCount> registers(m_reservedCalleeSavedRegisters);
+ m_reservedCalleeSavedRegisters.clear();
+ return registers;
+ }
+
+ const RegisterVector& allocatedRegisters() const { return m_allocatedRegisters; }
+
+ static bool isValidRegister(JSC::MacroAssembler::RegisterID registerID)
+ {
+#if CPU(ARM64)
+ return (registerID >= JSC::ARM64Registers::x0 && registerID <= JSC::ARM64Registers::x14)
+ || registerID == JSC::ARM64Registers::x19;
+#elif CPU(ARM_THUMB2)
+ return registerID >= JSC::ARMRegisters::r0 && registerID <= JSC::ARMRegisters::r11 && registerID != JSC::ARMRegisters::r6;
+#elif CPU(X86_64)
+ return (registerID >= JSC::X86Registers::eax && registerID <= JSC::X86Registers::edx)
+ || (registerID >= JSC::X86Registers::esi && registerID <= JSC::X86Registers::r15);
+#else
+#error RegisterAllocator does not define the valid register range for the current architecture.
+#endif
+ }
+
+ static bool isCallerSavedRegister(JSC::MacroAssembler::RegisterID registerID)
+ {
+ ASSERT(isValidRegister(registerID));
+#if CPU(ARM64)
+ return registerID >= JSC::ARM64Registers::x0 && registerID <= JSC::ARM64Registers::x14;
+#elif CPU(ARM_THUMB2)
+ return (registerID >= JSC::ARMRegisters::r0 && registerID <= JSC::ARMRegisters::r3)
+ || registerID == JSC::ARMRegisters::r9;
+#elif CPU(X86_64)
+ return (registerID >= JSC::X86Registers::eax && registerID <= JSC::X86Registers::edx)
+ || (registerID >= JSC::X86Registers::esi && registerID <= JSC::X86Registers::r11);
+#else
+#error RegisterAllocator does not define the valid caller saved register range for the current architecture.
+#endif
+ }
private:
- Deque<JSC::MacroAssembler::RegisterID, WTF_ARRAY_LENGTH(callerSavedRegisters)> m_registers;
- Vector<JSC::MacroAssembler::RegisterID, WTF_ARRAY_LENGTH(callerSavedRegisters)> m_allocatedRegisters;
+ Deque<JSC::MacroAssembler::RegisterID, maximumRegisterCount> m_registers;
+ RegisterVector m_allocatedRegisters;
+ Vector<JSC::MacroAssembler::RegisterID, calleeSavedRegisterCount> m_reservedCalleeSavedRegisters;
};
class LocalRegister {
@@ -109,20 +242,29 @@ public:
return m_register;
}
-private:
+protected:
+ explicit LocalRegister(RegisterAllocator& allocator, JSC::MacroAssembler::RegisterID registerID)
+ : m_allocator(allocator)
+ , m_register(registerID)
+ {
+ }
RegisterAllocator& m_allocator;
JSC::MacroAssembler::RegisterID m_register;
};
-inline RegisterAllocator::RegisterAllocator()
+class LocalRegisterWithPreference : public LocalRegister {
+public:
+ explicit LocalRegisterWithPreference(RegisterAllocator& allocator, JSC::MacroAssembler::RegisterID preferredRegister)
+ : LocalRegister(allocator, allocator.allocateRegisterWithPreference(preferredRegister))
+ {
+ }
+};
+
+inline RegisterAllocator::~RegisterAllocator()
{
- for (unsigned i = 0; i < WTF_ARRAY_LENGTH(callerSavedRegisters); ++i)
- m_registers.append(callerSavedRegisters[i]);
+ RELEASE_ASSERT(m_reservedCalleeSavedRegisters.isEmpty());
}
} // namespace WebCore
#endif // ENABLE(CSS_SELECTOR_JIT)
-
-#endif // RegisterAllocator_h
-