summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/jit/ScratchRegisterAllocator.h
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/jit/ScratchRegisterAllocator.h
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/JavaScriptCore/jit/ScratchRegisterAllocator.h')
-rw-r--r--Source/JavaScriptCore/jit/ScratchRegisterAllocator.h198
1 files changed, 46 insertions, 152 deletions
diff --git a/Source/JavaScriptCore/jit/ScratchRegisterAllocator.h b/Source/JavaScriptCore/jit/ScratchRegisterAllocator.h
index 1967226c5..5805c2f29 100644
--- a/Source/JavaScriptCore/jit/ScratchRegisterAllocator.h
+++ b/Source/JavaScriptCore/jit/ScratchRegisterAllocator.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 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,76 +23,35 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ScratchRegisterAllocator_h
-#define ScratchRegisterAllocator_h
-
-#include <wtf/Platform.h>
+#pragma once
#if ENABLE(JIT)
#include "MacroAssembler.h"
+#include "RegisterSet.h"
#include "TempRegisterSet.h"
namespace JSC {
+struct ScratchBuffer;
+
// This class provides a low-level register allocator for use in stubs.
class ScratchRegisterAllocator {
public:
- ScratchRegisterAllocator(const TempRegisterSet& usedRegisters)
- : m_usedRegisters(usedRegisters)
- , m_numberOfReusedRegisters(0)
- {
- }
+ ScratchRegisterAllocator() { }
+ ScratchRegisterAllocator(const RegisterSet& usedRegisters);
+ ~ScratchRegisterAllocator();
- void lock(GPRReg reg)
- {
- unsigned index = GPRInfo::toIndex(reg);
- if (index == GPRInfo::InvalidIndex)
- return;
- m_lockedRegisters.setGPRByIndex(index);
- }
- void lock(FPRReg reg)
- {
- unsigned index = FPRInfo::toIndex(reg);
- if (index == FPRInfo::InvalidIndex)
- return;
- m_lockedRegisters.setFPRByIndex(index);
- }
+ void lock(GPRReg);
+ void lock(FPRReg);
+ void lock(JSValueRegs);
template<typename BankInfo>
- typename BankInfo::RegisterType allocateScratch()
- {
- // First try to allocate a register that is totally free.
- for (unsigned i = 0; i < BankInfo::numberOfRegisters; ++i) {
- typename BankInfo::RegisterType reg = BankInfo::toRegister(i);
- if (!m_lockedRegisters.get(reg)
- && !m_usedRegisters.get(reg)
- && !m_scratchRegisters.get(reg)) {
- m_scratchRegisters.set(reg);
- return reg;
- }
- }
-
- // Since that failed, try to allocate a register that is not yet
- // locked or used for scratch.
- for (unsigned i = 0; i < BankInfo::numberOfRegisters; ++i) {
- typename BankInfo::RegisterType reg = BankInfo::toRegister(i);
- if (!m_lockedRegisters.get(reg) && !m_scratchRegisters.get(reg)) {
- m_scratchRegisters.set(reg);
- m_numberOfReusedRegisters++;
- return reg;
- }
- }
-
- // We failed.
- CRASH();
- // Make some silly compilers happy.
- return static_cast<typename BankInfo::RegisterType>(-1);
- }
+ typename BankInfo::RegisterType allocateScratch();
- GPRReg allocateScratchGPR() { return allocateScratch<GPRInfo>(); }
- FPRReg allocateScratchFPR() { return allocateScratch<FPRInfo>(); }
+ GPRReg allocateScratchGPR();
+ FPRReg allocateScratchFPR();
bool didReuseRegisters() const
{
@@ -103,105 +62,43 @@ public:
{
return m_numberOfReusedRegisters;
}
+
+ RegisterSet usedRegisters() const { return m_usedRegisters; }
- void preserveReusedRegistersByPushing(MacroAssembler& jit)
- {
- if (!didReuseRegisters())
- return;
-
- for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
- if (m_scratchRegisters.getFPRByIndex(i) && m_usedRegisters.getFPRByIndex(i))
- jit.pushToSave(FPRInfo::toRegister(i));
- }
- for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) {
- if (m_scratchRegisters.getGPRByIndex(i) && m_usedRegisters.getGPRByIndex(i))
- jit.pushToSave(GPRInfo::toRegister(i));
- }
- }
-
- void restoreReusedRegistersByPopping(MacroAssembler& jit)
- {
- if (!didReuseRegisters())
- return;
-
- for (unsigned i = GPRInfo::numberOfRegisters; i--;) {
- if (m_scratchRegisters.getGPRByIndex(i) && m_usedRegisters.getGPRByIndex(i))
- jit.popToRestore(GPRInfo::toRegister(i));
- }
- for (unsigned i = FPRInfo::numberOfRegisters; i--;) {
- if (m_scratchRegisters.getFPRByIndex(i) && m_usedRegisters.getFPRByIndex(i))
- jit.popToRestore(FPRInfo::toRegister(i));
- }
- }
-
- unsigned desiredScratchBufferSize() const { return m_usedRegisters.numberOfSetRegisters() * sizeof(JSValue); }
+ enum class ExtraStackSpace { SpaceForCCall, NoExtraSpace };
+
+ struct PreservedState {
+ PreservedState()
+ : numberOfBytesPreserved(std::numeric_limits<unsigned>::max())
+ , extraStackSpaceRequirement(ExtraStackSpace::SpaceForCCall)
+ { }
+
+ PreservedState(unsigned numberOfBytes, ExtraStackSpace extraStackSpace)
+ : numberOfBytesPreserved(numberOfBytes)
+ , extraStackSpaceRequirement(extraStackSpace)
+ { }
+
+ explicit operator bool() const { return numberOfBytesPreserved != std::numeric_limits<unsigned>::max(); }
+
+ unsigned numberOfBytesPreserved;
+ ExtraStackSpace extraStackSpaceRequirement;
+ };
+
+ PreservedState preserveReusedRegistersByPushing(MacroAssembler& jit, ExtraStackSpace);
+ void restoreReusedRegistersByPopping(MacroAssembler& jit, const PreservedState&);
- void preserveUsedRegistersToScratchBuffer(MacroAssembler& jit, ScratchBuffer* scratchBuffer, GPRReg scratchGPR = InvalidGPRReg)
- {
- unsigned count = 0;
- for (unsigned i = GPRInfo::numberOfRegisters; i--;) {
- if (m_usedRegisters.getGPRByIndex(i)) {
-#if USE(JSVALUE64)
- jit.store64(GPRInfo::toRegister(i), static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) + (count++));
-#else
- jit.store32(GPRInfo::toRegister(i), static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) + (count++));
-#endif
- }
- if (scratchGPR == InvalidGPRReg && !m_lockedRegisters.getGPRByIndex(i) && !m_scratchRegisters.getGPRByIndex(i))
- scratchGPR = GPRInfo::toRegister(i);
- }
- RELEASE_ASSERT(scratchGPR != InvalidGPRReg);
- for (unsigned i = FPRInfo::numberOfRegisters; i--;) {
- if (m_usedRegisters.getFPRByIndex(i)) {
- jit.move(MacroAssembler::TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) + (count++)), scratchGPR);
- jit.storeDouble(FPRInfo::toRegister(i), scratchGPR);
- }
- }
- RELEASE_ASSERT(count * sizeof(JSValue) == desiredScratchBufferSize());
-
- jit.move(MacroAssembler::TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratchGPR);
- jit.storePtr(MacroAssembler::TrustedImmPtr(static_cast<size_t>(count * sizeof(JSValue))), scratchGPR);
- }
+ RegisterSet usedRegistersForCall() const;
- void restoreUsedRegistersFromScratchBuffer(MacroAssembler& jit, ScratchBuffer* scratchBuffer, GPRReg scratchGPR = InvalidGPRReg)
- {
- if (scratchGPR == InvalidGPRReg) {
- // Find a scratch register.
- for (unsigned i = GPRInfo::numberOfRegisters; i--;) {
- if (m_lockedRegisters.getGPRByIndex(i) || m_scratchRegisters.getGPRByIndex(i))
- continue;
- scratchGPR = GPRInfo::toRegister(i);
- break;
- }
- }
- RELEASE_ASSERT(scratchGPR != InvalidGPRReg);
-
- jit.move(MacroAssembler::TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratchGPR);
- jit.storePtr(MacroAssembler::TrustedImmPtr(0), scratchGPR);
-
- // Restore double registers first.
- unsigned count = m_usedRegisters.numberOfSetGPRs();
- for (unsigned i = FPRInfo::numberOfRegisters; i--;) {
- if (m_usedRegisters.getFPRByIndex(i)) {
- jit.move(MacroAssembler::TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) + (count++)), scratchGPR);
- jit.loadDouble(scratchGPR, FPRInfo::toRegister(i));
- }
- }
-
- count = 0;
- for (unsigned i = GPRInfo::numberOfRegisters; i--;) {
- if (m_usedRegisters.getGPRByIndex(i)) {
-#if USE(JSVALUE64)
- jit.load64(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) + (count++), GPRInfo::toRegister(i));
-#else
- jit.load32(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) + (count++), GPRInfo::toRegister(i));
-#endif
- }
- }
- }
+ unsigned desiredScratchBufferSizeForCall() const;
+ void preserveUsedRegistersToScratchBufferForCall(MacroAssembler& jit, ScratchBuffer* scratchBuffer, GPRReg scratchGPR = InvalidGPRReg);
+ void restoreUsedRegistersFromScratchBufferForCall(MacroAssembler& jit, ScratchBuffer* scratchBuffer, GPRReg scratchGPR = InvalidGPRReg);
+
+ static unsigned preserveRegistersToStackForCall(MacroAssembler& jit, const RegisterSet& usedRegisters, unsigned extraPaddingInBytes);
+ static void restoreRegistersFromStackForCall(MacroAssembler& jit, const RegisterSet& usedRegisters, const RegisterSet& ignore, unsigned numberOfStackBytesUsedForRegisterPreservation, unsigned extraPaddingInBytes);
+
private:
- TempRegisterSet m_usedRegisters;
+ RegisterSet m_usedRegisters;
TempRegisterSet m_lockedRegisters;
TempRegisterSet m_scratchRegisters;
unsigned m_numberOfReusedRegisters;
@@ -210,6 +107,3 @@ private:
} // namespace JSC
#endif // ENABLE(JIT)
-
-#endif // ScratchRegisterAllocator_h
-