diff options
Diffstat (limited to 'Source/WebCore/cssjit/StackAllocator.h')
-rw-r--r-- | Source/WebCore/cssjit/StackAllocator.h | 161 |
1 files changed, 135 insertions, 26 deletions
diff --git a/Source/WebCore/cssjit/StackAllocator.h b/Source/WebCore/cssjit/StackAllocator.h index 2a228f687..e8c80ed37 100644 --- a/Source/WebCore/cssjit/StackAllocator.h +++ b/Source/WebCore/cssjit/StackAllocator.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,12 +23,13 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef StackAllocator_h -#define StackAllocator_h +#pragma once #if ENABLE(CSS_SELECTOR_JIT) +#include "RegisterAllocator.h" #include <JavaScriptCore/MacroAssembler.h> +#include <limits> namespace WebCore { @@ -37,16 +38,19 @@ public: class StackReference { public: StackReference() - : m_offsetFromTop(-1) + : m_offsetFromTop(std::numeric_limits<unsigned>::max()) { } explicit StackReference(unsigned offset) : m_offsetFromTop(offset) { } operator unsigned() const { return m_offsetFromTop; } + bool isValid() const { return m_offsetFromTop != std::numeric_limits<unsigned>::max(); } private: unsigned m_offsetFromTop; }; + typedef Vector<StackReference, maximumRegisterCount> StackReferenceVector; + StackAllocator(JSC::MacroAssembler& assembler) : m_assembler(assembler) , m_offsetFromTop(0) @@ -54,59 +58,147 @@ public: { } + StackReference stackTop() + { + return StackReference(m_offsetFromTop + stackUnitInBytes()); + } + ~StackAllocator() { RELEASE_ASSERT(!m_offsetFromTop); RELEASE_ASSERT(!m_hasFunctionCallPadding); } + StackReference allocateUninitialized() + { + return allocateUninitialized(1)[0]; + } + + StackReferenceVector allocateUninitialized(unsigned count) + { + RELEASE_ASSERT(!m_hasFunctionCallPadding); + StackReferenceVector stackReferences; + unsigned oldOffsetFromTop = m_offsetFromTop; +#if CPU(ARM64) + for (unsigned i = 0; i < count - 1; i += 2) { + m_offsetFromTop += stackUnitInBytes(); + stackReferences.append(StackReference(m_offsetFromTop - stackUnitInBytes() / 2)); + stackReferences.append(StackReference(m_offsetFromTop)); + } + if (count % 2) { + m_offsetFromTop += stackUnitInBytes(); + stackReferences.append(StackReference(m_offsetFromTop)); + } +#else + for (unsigned i = 0; i < count; ++i) { + m_offsetFromTop += stackUnitInBytes(); + stackReferences.append(StackReference(m_offsetFromTop)); + } +#endif + m_assembler.addPtrNoFlags(JSC::MacroAssembler::TrustedImm32(-(m_offsetFromTop - oldOffsetFromTop)), JSC::MacroAssembler::stackPointerRegister); + return stackReferences; + } + + template<size_t inlineCapacity, typename OverflowHandler> + StackReferenceVector push(const Vector<JSC::MacroAssembler::RegisterID, inlineCapacity, OverflowHandler>& registerIDs) + { + RELEASE_ASSERT(!m_hasFunctionCallPadding); + + StackReferenceVector stackReferences; + + if (registerIDs.isEmpty()) + return stackReferences; + +#if CPU(ARM64) + unsigned pushRegisterCount = registerIDs.size(); + for (unsigned i = 0; i < pushRegisterCount - 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 (pushRegisterCount % 2) + stackReferences.append(push(registerIDs[pushRegisterCount - 1])); +#else + for (auto registerID : registerIDs) + stackReferences.append(push(registerID)); +#endif + return stackReferences; + } + StackReference push(JSC::MacroAssembler::RegisterID registerID) { RELEASE_ASSERT(!m_hasFunctionCallPadding); - m_assembler.push(registerID); - m_offsetFromTop += 8; + m_assembler.pushToSave(registerID); + m_offsetFromTop += stackUnitInBytes(); return StackReference(m_offsetFromTop); } + template<size_t inlineCapacity, typename OverflowHandler> + void pop(const StackReferenceVector& stackReferences, const Vector<JSC::MacroAssembler::RegisterID, inlineCapacity, OverflowHandler>& registerIDs) + { + RELEASE_ASSERT(!m_hasFunctionCallPadding); + + unsigned popRegisterCount = registerIDs.size(); + RELEASE_ASSERT(stackReferences.size() == popRegisterCount); +#if CPU(ARM64) + ASSERT(m_offsetFromTop >= stackUnitInBytes() * ((popRegisterCount + 1) / 2)); + unsigned popRegisterCountOdd = popRegisterCount % 2; + if (popRegisterCountOdd) + pop(stackReferences[popRegisterCount - 1], registerIDs[popRegisterCount - 1]); + for (unsigned i = popRegisterCount - popRegisterCountOdd; 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 + ASSERT(m_offsetFromTop >= stackUnitInBytes() * popRegisterCount); + for (unsigned i = popRegisterCount; i > 0; --i) + pop(stackReferences[i - 1], registerIDs[i - 1]); +#endif + } + void pop(StackReference stackReference, JSC::MacroAssembler::RegisterID registerID) { RELEASE_ASSERT(stackReference == m_offsetFromTop); RELEASE_ASSERT(!m_hasFunctionCallPadding); - ASSERT(m_offsetFromTop > 0); - m_offsetFromTop -= 8; - m_assembler.pop(registerID); + RELEASE_ASSERT(m_offsetFromTop >= stackUnitInBytes()); + m_offsetFromTop -= stackUnitInBytes(); + m_assembler.popToRestore(registerID); } - void popAndDiscard(StackReference stackReference) + void popAndDiscardUpTo(StackReference stackReference) { - RELEASE_ASSERT(stackReference == m_offsetFromTop); - m_assembler.addPtr(JSC::MacroAssembler::TrustedImm32(8), JSC::MacroAssembler::stackPointerRegister); - m_offsetFromTop -= 8; + unsigned positionBeforeStackReference = stackReference - stackUnitInBytes(); + RELEASE_ASSERT(positionBeforeStackReference < m_offsetFromTop); + + unsigned stackDelta = m_offsetFromTop - positionBeforeStackReference; + m_assembler.addPtr(JSC::MacroAssembler::TrustedImm32(stackDelta), JSC::MacroAssembler::stackPointerRegister); + m_offsetFromTop -= stackDelta; } void alignStackPreFunctionCall() { +#if CPU(X86_64) RELEASE_ASSERT(!m_hasFunctionCallPadding); - unsigned topAlignment = 8; + unsigned topAlignment = stackUnitInBytes(); if ((topAlignment + m_offsetFromTop) % 16) { m_hasFunctionCallPadding = true; - m_assembler.addPtrNoFlags(JSC::MacroAssembler::TrustedImm32(-8), JSC::MacroAssembler::stackPointerRegister); + m_assembler.addPtrNoFlags(JSC::MacroAssembler::TrustedImm32(-stackUnitInBytes()), JSC::MacroAssembler::stackPointerRegister); } +#endif } void unalignStackPostFunctionCall() { +#if CPU(X86_64) if (m_hasFunctionCallPadding) { - m_assembler.addPtrNoFlags(JSC::MacroAssembler::TrustedImm32(8), JSC::MacroAssembler::stackPointerRegister); + m_assembler.addPtrNoFlags(JSC::MacroAssembler::TrustedImm32(stackUnitInBytes()), JSC::MacroAssembler::stackPointerRegister); m_hasFunctionCallPadding = false; } - } - - void discard() - { - if (m_offsetFromTop) - m_assembler.addPtr(JSC::MacroAssembler::TrustedImm32(m_offsetFromTop), JSC::MacroAssembler::stackPointerRegister); - m_offsetFromTop = 0; +#endif } void merge(StackAllocator&& stackA, StackAllocator&& stackB) @@ -141,13 +233,32 @@ public: stackC.reset(); } + JSC::MacroAssembler::Address addressOf(StackReference stackReference) + { + return JSC::MacroAssembler::Address(JSC::MacroAssembler::stackPointerRegister, offsetToStackReference(stackReference)); + } + + StackAllocator& operator=(const StackAllocator& other) + { + RELEASE_ASSERT(&m_assembler == &other.m_assembler); + m_offsetFromTop = other.m_offsetFromTop; + m_hasFunctionCallPadding = other.m_hasFunctionCallPadding; + return *this; + } + + +private: + static unsigned stackUnitInBytes() + { + return JSC::MacroAssembler::pushToSaveByteOffset(); + } + unsigned offsetToStackReference(StackReference stackReference) { RELEASE_ASSERT(m_offsetFromTop >= stackReference); return m_offsetFromTop - stackReference; } -private: void reset() { m_offsetFromTop = 0; @@ -162,5 +273,3 @@ private: } // namespace WebCore #endif // ENABLE(CSS_SELECTOR_JIT) - -#endif // StackAllocator_h |