ArityCheckFailReturnThunks.cpp [plain text]
#include "config.h"
#include "ArityCheckFailReturnThunks.h"
#if ENABLE(JIT)
#include "AssemblyHelpers.h"
#include "LinkBuffer.h"
#include "JSCInlines.h"
#include "StackAlignment.h"
namespace JSC {
ArityCheckFailReturnThunks::ArityCheckFailReturnThunks()
: m_nextSize(0)
{
}
ArityCheckFailReturnThunks::~ArityCheckFailReturnThunks() { }
CodeLocationLabel* ArityCheckFailReturnThunks::returnPCsFor(
VM& vm, unsigned numExpectedArgumentsIncludingThis)
{
ASSERT(numExpectedArgumentsIncludingThis >= 1);
numExpectedArgumentsIncludingThis = WTF::roundUpToMultipleOf(
stackAlignmentRegisters(), numExpectedArgumentsIncludingThis);
{
ConcurrentJITLocker locker(m_lock);
if (numExpectedArgumentsIncludingThis < m_nextSize)
return m_returnPCArrays.last().get();
}
ASSERT(!isCompilationThread());
numExpectedArgumentsIncludingThis = std::max(numExpectedArgumentsIncludingThis, m_nextSize * 2);
AssemblyHelpers jit(&vm, 0);
Vector<AssemblyHelpers::Label> labels;
for (unsigned size = m_nextSize; size <= numExpectedArgumentsIncludingThis; size += stackAlignmentRegisters()) {
labels.append(jit.label());
jit.load32(
AssemblyHelpers::Address(
AssemblyHelpers::stackPointerRegister,
(JSStack::ArgumentCount - JSStack::CallerFrameAndPCSize) * sizeof(Register) +
PayloadOffset),
GPRInfo::regT4);
jit.add32(
AssemblyHelpers::TrustedImm32(
JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize + size - 1),
GPRInfo::regT4, GPRInfo::regT2);
jit.lshift32(AssemblyHelpers::TrustedImm32(3), GPRInfo::regT2);
jit.addPtr(AssemblyHelpers::stackPointerRegister, GPRInfo::regT2);
jit.loadPtr(GPRInfo::regT2, GPRInfo::regT2);
jit.addPtr(
AssemblyHelpers::TrustedImm32(size * sizeof(Register)),
AssemblyHelpers::stackPointerRegister);
jit.store32(
GPRInfo::regT4,
AssemblyHelpers::Address(
AssemblyHelpers::stackPointerRegister,
(JSStack::ArgumentCount - JSStack::CallerFrameAndPCSize) * sizeof(Register) +
PayloadOffset));
jit.jump(GPRInfo::regT2);
}
LinkBuffer linkBuffer(vm, jit, GLOBAL_THUNK_ID, JITCompilationMustSucceed);
unsigned returnPCsSize = numExpectedArgumentsIncludingThis / stackAlignmentRegisters() + 1;
std::unique_ptr<CodeLocationLabel[]> returnPCs =
std::make_unique<CodeLocationLabel[]>(returnPCsSize);
for (unsigned size = 0; size <= numExpectedArgumentsIncludingThis; size += stackAlignmentRegisters()) {
unsigned index = size / stackAlignmentRegisters();
RELEASE_ASSERT(index < returnPCsSize);
if (size < m_nextSize)
returnPCs[index] = m_returnPCArrays.last()[index];
else
returnPCs[index] = linkBuffer.locationOf(labels[(size - m_nextSize) / stackAlignmentRegisters()]);
}
CodeLocationLabel* result = returnPCs.get();
{
ConcurrentJITLocker locker(m_lock);
m_returnPCArrays.append(WTF::move(returnPCs));
m_refs.append(FINALIZE_CODE(linkBuffer, ("Arity check fail return thunks for up to numArgs = %u", numExpectedArgumentsIncludingThis)));
m_nextSize = numExpectedArgumentsIncludingThis + stackAlignmentRegisters();
}
return result;
}
CodeLocationLabel ArityCheckFailReturnThunks::returnPCFor(VM& vm, unsigned slotsToAdd)
{
return returnPCsFor(vm, slotsToAdd)[slotsToAdd / stackAlignmentRegisters()];
}
}
#endif // ENABLE(JIT)