diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/cssjit/FunctionCall.h | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/cssjit/FunctionCall.h')
-rw-r--r-- | Source/WebCore/cssjit/FunctionCall.h | 129 |
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 = ®isterID; + 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 |