summaryrefslogtreecommitdiff
path: root/Source/WebCore/cssjit/StackAllocator.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/cssjit/StackAllocator.h')
-rw-r--r--Source/WebCore/cssjit/StackAllocator.h161
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