2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef RegisterAllocator_h
27 #define RegisterAllocator_h
29 #if ENABLE(CSS_SELECTOR_JIT)
31 #include <JavaScriptCore/MacroAssembler.h>
32 #include <wtf/HashSet.h>
33 #include <wtf/Vector.h>
38 static const JSC::MacroAssembler::RegisterID callerSavedRegisters[] = {
39 JSC::ARM64Registers::x0,
40 JSC::ARM64Registers::x1,
41 JSC::ARM64Registers::x2,
42 JSC::ARM64Registers::x3,
43 JSC::ARM64Registers::x4,
44 JSC::ARM64Registers::x5,
45 JSC::ARM64Registers::x6,
46 JSC::ARM64Registers::x7,
47 JSC::ARM64Registers::x8,
48 JSC::ARM64Registers::x9,
49 JSC::ARM64Registers::x10,
50 JSC::ARM64Registers::x11,
51 JSC::ARM64Registers::x12,
52 JSC::ARM64Registers::x13,
53 JSC::ARM64Registers::x14,
54 JSC::ARM64Registers::x15,
56 static const JSC::MacroAssembler::RegisterID calleeSavedRegisters[] = {
57 JSC::ARM64Registers::x19
60 static const JSC::MacroAssembler::RegisterID callerSavedRegisters[] = {
61 JSC::X86Registers::eax,
62 JSC::X86Registers::ecx,
63 JSC::X86Registers::edx,
64 JSC::X86Registers::esi,
65 JSC::X86Registers::edi,
66 JSC::X86Registers::r8,
67 JSC::X86Registers::r9,
68 JSC::X86Registers::r10,
69 JSC::X86Registers::r11
71 static const JSC::MacroAssembler::RegisterID calleeSavedRegisters[] = {
72 JSC::X86Registers::r12,
73 JSC::X86Registers::r13,
74 JSC::X86Registers::r14,
75 JSC::X86Registers::r15
78 #error RegisterAllocator has no defined registers for the architecture.
80 static const unsigned calleeSavedRegisterCount = WTF_ARRAY_LENGTH(calleeSavedRegisters);
81 static const unsigned registerCount = calleeSavedRegisterCount + WTF_ARRAY_LENGTH(callerSavedRegisters);
83 class RegisterAllocator {
88 unsigned availableRegisterCount() const { return m_registers.size(); }
90 JSC::MacroAssembler::RegisterID allocateRegister()
92 auto first = m_registers.begin();
93 JSC::MacroAssembler::RegisterID registerID = static_cast<JSC::MacroAssembler::RegisterID>(*first);
94 RELEASE_ASSERT(m_registers.remove(first));
95 ASSERT(!m_allocatedRegisters.contains(registerID));
96 m_allocatedRegisters.append(registerID);
100 void allocateRegister(JSC::MacroAssembler::RegisterID registerID)
102 RELEASE_ASSERT(m_registers.remove(registerID));
103 ASSERT(!m_allocatedRegisters.contains(registerID));
104 m_allocatedRegisters.append(registerID);
107 void deallocateRegister(JSC::MacroAssembler::RegisterID registerID)
109 ASSERT(m_allocatedRegisters.contains(registerID));
110 // Most allocation/deallocation happen in stack-like order. In the common case, this
111 // just removes the last item.
112 m_allocatedRegisters.remove(m_allocatedRegisters.reverseFind(registerID));
113 RELEASE_ASSERT(m_registers.add(registerID).isNewEntry);
116 const Vector<JSC::MacroAssembler::RegisterID, calleeSavedRegisterCount>& reserveCalleeSavedRegisters(unsigned count)
118 RELEASE_ASSERT(count <= WTF_ARRAY_LENGTH(calleeSavedRegisters));
119 RELEASE_ASSERT(!m_reservedCalleeSavedRegisters.size());
120 for (unsigned i = 0; i < count; ++i) {
121 JSC::MacroAssembler::RegisterID registerId = calleeSavedRegisters[i];
122 m_reservedCalleeSavedRegisters.append(registerId);
123 m_registers.add(registerId);
125 return m_reservedCalleeSavedRegisters;
128 Vector<JSC::MacroAssembler::RegisterID, calleeSavedRegisterCount> restoreCalleeSavedRegisters()
130 Vector<JSC::MacroAssembler::RegisterID, calleeSavedRegisterCount> registers(m_reservedCalleeSavedRegisters);
131 m_reservedCalleeSavedRegisters.clear();
135 const Vector<JSC::MacroAssembler::RegisterID, registerCount>& allocatedRegisters() const { return m_allocatedRegisters; }
137 static bool isValidRegister(JSC::MacroAssembler::RegisterID registerID)
140 return registerID >= JSC::ARM64Registers::x0 && registerID <= JSC::ARM64Registers::x15;
142 return registerID >= JSC::X86Registers::eax && registerID <= JSC::X86Registers::r15;
144 #error RegisterAllocator does not define the valid register range for the current architecture.
149 HashSet<unsigned, DefaultHash<unsigned>::Hash, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> m_registers;
150 Vector<JSC::MacroAssembler::RegisterID, registerCount> m_allocatedRegisters;
151 Vector<JSC::MacroAssembler::RegisterID, calleeSavedRegisterCount> m_reservedCalleeSavedRegisters;
154 class LocalRegister {
156 explicit LocalRegister(RegisterAllocator& allocator)
157 : m_allocator(allocator)
158 , m_register(allocator.allocateRegister())
164 m_allocator.deallocateRegister(m_register);
167 operator JSC::MacroAssembler::RegisterID() const
173 RegisterAllocator& m_allocator;
174 JSC::MacroAssembler::RegisterID m_register;
177 inline RegisterAllocator::RegisterAllocator()
179 for (unsigned i = 0; i < WTF_ARRAY_LENGTH(callerSavedRegisters); ++i)
180 m_registers.add(callerSavedRegisters[i]);
183 inline RegisterAllocator::~RegisterAllocator()
185 RELEASE_ASSERT(m_reservedCalleeSavedRegisters.isEmpty());
188 } // namespace WebCore
190 #endif // ENABLE(CSS_SELECTOR_JIT)
192 #endif // RegisterAllocator_h