summaryrefslogtreecommitdiff
path: root/Source/WebCore/cssjit/FunctionCall.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/WebCore/cssjit/FunctionCall.h
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/cssjit/FunctionCall.h')
-rw-r--r--Source/WebCore/cssjit/FunctionCall.h129
1 files changed, 97 insertions, 32 deletions
diff --git a/Source/WebCore/cssjit/FunctionCall.h b/Source/WebCore/cssjit/FunctionCall.h
index 6dfbc5c73..c29401683 100644
--- a/Source/WebCore/cssjit/FunctionCall.h
+++ b/Source/WebCore/cssjit/FunctionCall.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 FunctionCall_h
-#define FunctionCall_h
+#pragma once
#if ENABLE(CSS_SELECTOR_JIT)
@@ -37,12 +36,14 @@ namespace WebCore {
class FunctionCall {
public:
- FunctionCall(JSC::MacroAssembler& assembler, const RegisterAllocator& registerAllocator, StackAllocator& stackAllocator, Vector<std::pair<JSC::MacroAssembler::Call, JSC::FunctionPtr>>& callRegistry)
+ FunctionCall(JSC::MacroAssembler& assembler, RegisterAllocator& registerAllocator, StackAllocator& stackAllocator, Vector<std::pair<JSC::MacroAssembler::Call, JSC::FunctionPtr>, 32>& callRegistry)
: m_assembler(assembler)
, m_registerAllocator(registerAllocator)
, m_stackAllocator(stackAllocator)
, m_callRegistry(callRegistry)
- , m_firstArgument(0)
+ , m_argumentCount(0)
+ , m_firstArgument(InvalidGPRReg)
+ , m_secondArgument(InvalidGPRReg)
{
}
@@ -51,9 +52,17 @@ public:
m_functionAddress = functionAddress;
}
- void setFirstArgument(const JSC::MacroAssembler::RegisterID& registerID)
+ void setOneArgument(const JSC::MacroAssembler::RegisterID& registerID)
{
- m_firstArgument = &registerID;
+ m_argumentCount = 1;
+ m_firstArgument = registerID;
+ }
+
+ void setTwoArguments(const JSC::MacroAssembler::RegisterID& firstRegisterID, const JSC::MacroAssembler::RegisterID& secondRegisterID)
+ {
+ m_argumentCount = 2;
+ m_firstArgument = firstRegisterID;
+ m_secondArgument = secondRegisterID;
}
void call()
@@ -62,24 +71,81 @@ public:
cleanupPostCall();
}
- JSC::MacroAssembler::Jump callAndBranchOnCondition(JSC::MacroAssembler::ResultCondition condition)
+ JSC::MacroAssembler::Jump callAndBranchOnBooleanReturnValue(JSC::MacroAssembler::ResultCondition condition)
+ {
+#if CPU(X86) || CPU(X86_64)
+ return callAndBranchOnCondition(condition, JSC::MacroAssembler::TrustedImm32(0xff));
+#elif CPU(ARM64) || CPU(ARM)
+ return callAndBranchOnCondition(condition, JSC::MacroAssembler::TrustedImm32(-1));
+#else
+#error Missing implementationg for matching boolean return values.
+#endif
+ }
+
+private:
+ JSC::MacroAssembler::Jump callAndBranchOnCondition(JSC::MacroAssembler::ResultCondition condition, JSC::MacroAssembler::TrustedImm32 mask)
{
prepareAndCall();
- m_assembler.test32(JSC::GPRInfo::returnValueGPR, JSC::MacroAssembler::TrustedImm32(0xff));
+ m_assembler.test32(JSC::GPRInfo::returnValueGPR, mask);
cleanupPostCall();
return m_assembler.branch(condition);
}
-private:
+ void swapArguments()
+ {
+ JSC::MacroAssembler::RegisterID a = m_firstArgument;
+ JSC::MacroAssembler::RegisterID b = m_secondArgument;
+ // x86 can swap without a temporary register. On other architectures, we need allocate a temporary register to switch the values.
+#if CPU(X86) || CPU(X86_64)
+ m_assembler.swap(a, b);
+#elif CPU(ARM64) || CPU(ARM_THUMB2)
+ m_assembler.move(a, tempRegister);
+ m_assembler.move(b, a);
+ m_assembler.move(tempRegister, b);
+#else
+#error Missing implementationg for matching swapping argument registers.
+#endif
+ }
+
void prepareAndCall()
{
ASSERT(m_functionAddress.executableAddress());
+ ASSERT(!m_firstArgument || (m_firstArgument && !m_secondArgument) || (m_firstArgument && m_secondArgument));
- saveAllocatedRegisters();
+ saveAllocatedCallerSavedRegisters();
m_stackAllocator.alignStackPreFunctionCall();
- if (m_firstArgument && *m_firstArgument != JSC::GPRInfo::argumentGPR0)
- m_assembler.move(*m_firstArgument, JSC::GPRInfo::argumentGPR0);
+ if (m_argumentCount == 2) {
+ RELEASE_ASSERT(RegisterAllocator::isValidRegister(m_firstArgument));
+ RELEASE_ASSERT(RegisterAllocator::isValidRegister(m_secondArgument));
+
+ if (m_firstArgument != JSC::GPRInfo::argumentGPR0) {
+ // If firstArgument is not in argumentGPR0, we need to handle potential conflicts:
+ // -if secondArgument and firstArgument are in inversted registers, just swap the values.
+ // -if secondArgument is in argumentGPR0 but firstArgument is not taking argumentGPR1, we can move in order secondArgument->argumentGPR1, firstArgument->argumentGPR0
+ // -if secondArgument does not take argumentGPR0, firstArgument and secondArgument can be moved safely to destination.
+ if (m_secondArgument == JSC::GPRInfo::argumentGPR0) {
+ if (m_firstArgument == JSC::GPRInfo::argumentGPR1)
+ swapArguments();
+ else {
+ m_assembler.move(JSC::GPRInfo::argumentGPR0, JSC::GPRInfo::argumentGPR1);
+ m_assembler.move(m_firstArgument, JSC::GPRInfo::argumentGPR0);
+ }
+ } else {
+ m_assembler.move(m_firstArgument, JSC::GPRInfo::argumentGPR0);
+ if (m_secondArgument != JSC::GPRInfo::argumentGPR1)
+ m_assembler.move(m_secondArgument, JSC::GPRInfo::argumentGPR1);
+ }
+ } else {
+ // We know firstArgument is already in place, we can safely move secondArgument.
+ if (m_secondArgument != JSC::GPRInfo::argumentGPR1)
+ m_assembler.move(m_secondArgument, JSC::GPRInfo::argumentGPR1);
+ }
+ } else if (m_argumentCount == 1) {
+ RELEASE_ASSERT(RegisterAllocator::isValidRegister(m_firstArgument));
+ if (m_firstArgument != JSC::GPRInfo::argumentGPR0)
+ m_assembler.move(m_firstArgument, JSC::GPRInfo::argumentGPR0);
+ }
JSC::MacroAssembler::Call call = m_assembler.call();
m_callRegistry.append(std::make_pair(call, m_functionAddress));
@@ -88,42 +154,41 @@ private:
void cleanupPostCall()
{
m_stackAllocator.unalignStackPostFunctionCall();
- restoreAllocatedRegisters();
+ restoreAllocatedCallerSavedRegisters();
}
- void saveAllocatedRegisters()
+ void saveAllocatedCallerSavedRegisters()
{
ASSERT(m_savedRegisterStackReferences.isEmpty());
-
- unsigned allocatedRegistersCount = m_registerAllocator.allocatedRegisters().size();
- m_savedRegisterStackReferences.reserveCapacity(allocatedRegistersCount);
-
- for (unsigned i = 0; i < allocatedRegistersCount; ++i) {
- JSC::MacroAssembler::RegisterID registerID = m_registerAllocator.allocatedRegisters()[i];
- m_savedRegisterStackReferences.append(m_stackAllocator.push(registerID));
+ ASSERT(m_savedRegisters.isEmpty());
+ const RegisterVector& allocatedRegisters = m_registerAllocator.allocatedRegisters();
+ for (auto registerID : allocatedRegisters) {
+ if (RegisterAllocator::isCallerSavedRegister(registerID))
+ m_savedRegisters.append(registerID);
}
+ m_savedRegisterStackReferences = m_stackAllocator.push(m_savedRegisters);
}
- void restoreAllocatedRegisters()
+ void restoreAllocatedCallerSavedRegisters()
{
- for (unsigned i = m_registerAllocator.allocatedRegisters().size(); i > 0; --i)
- m_stackAllocator.pop(m_savedRegisterStackReferences[i - 1], m_registerAllocator.allocatedRegisters()[i - 1]);
+ m_stackAllocator.pop(m_savedRegisterStackReferences, m_savedRegisters);
m_savedRegisterStackReferences.clear();
}
JSC::MacroAssembler& m_assembler;
- const RegisterAllocator& m_registerAllocator;
+ RegisterAllocator& m_registerAllocator;
StackAllocator& m_stackAllocator;
- Vector<std::pair<JSC::MacroAssembler::Call, JSC::FunctionPtr>>& m_callRegistry;
-
- Vector<StackAllocator::StackReference> m_savedRegisterStackReferences;
+ Vector<std::pair<JSC::MacroAssembler::Call, JSC::FunctionPtr>, 32>& m_callRegistry;
+ RegisterVector m_savedRegisters;
+ StackAllocator::StackReferenceVector m_savedRegisterStackReferences;
+
JSC::FunctionPtr m_functionAddress;
- const JSC::MacroAssembler::RegisterID* m_firstArgument;
+ unsigned m_argumentCount;
+ JSC::MacroAssembler::RegisterID m_firstArgument;
+ JSC::MacroAssembler::RegisterID m_secondArgument;
};
} // namespace WebCore
#endif // ENABLE(CSS_SELECTOR_JIT)
-
-#endif // FunctionCall_h