From 39b42553a5bbf8cf0ff60ae3480ec5174cc53bf4 Mon Sep 17 00:00:00 2001 From: "commit-queue@webkit.org" Date: Thu, 17 Sep 2015 17:38:08 +0000 Subject: [PATCH] Save and restore callee save registers in WebAssembly https://bugs.webkit.org/show_bug.cgi?id=149247 Patch by Sukolsak Sakshuwong on 2015-09-17 Reviewed by Michael Saboff. Save callee save registers when entering WebAssembly functions and restore them when returning. * jit/RegisterSet.cpp: (JSC::RegisterSet::webAssemblyCalleeSaveRegisters): * jit/RegisterSet.h: * wasm/WASMFunctionCompiler.h: (JSC::WASMFunctionCompiler::startFunction): (JSC::WASMFunctionCompiler::endFunction): (JSC::WASMFunctionCompiler::buildReturn): (JSC::WASMFunctionCompiler::localAddress): (JSC::WASMFunctionCompiler::temporaryAddress): (JSC::WASMFunctionCompiler::boxArgumentsAndAdjustStackPointer): (JSC::WASMFunctionCompiler::callAndUnboxResult): git-svn-id: https://svn.webkit.org/repository/webkit/trunk@189917 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- Source/JavaScriptCore/ChangeLog | 22 +++++++++++++++ Source/JavaScriptCore/jit/RegisterSet.cpp | 33 +++++++++++++++++++++++ Source/JavaScriptCore/jit/RegisterSet.h | 3 +++ Source/JavaScriptCore/wasm/WASMFunctionCompiler.h | 21 +++++++++++---- 4 files changed, 74 insertions(+), 5 deletions(-) diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index 8ffb49c..b2a5dd4 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,3 +1,25 @@ +2015-09-17 Sukolsak Sakshuwong + + Save and restore callee save registers in WebAssembly + https://bugs.webkit.org/show_bug.cgi?id=149247 + + Reviewed by Michael Saboff. + + Save callee save registers when entering WebAssembly functions + and restore them when returning. + + * jit/RegisterSet.cpp: + (JSC::RegisterSet::webAssemblyCalleeSaveRegisters): + * jit/RegisterSet.h: + * wasm/WASMFunctionCompiler.h: + (JSC::WASMFunctionCompiler::startFunction): + (JSC::WASMFunctionCompiler::endFunction): + (JSC::WASMFunctionCompiler::buildReturn): + (JSC::WASMFunctionCompiler::localAddress): + (JSC::WASMFunctionCompiler::temporaryAddress): + (JSC::WASMFunctionCompiler::boxArgumentsAndAdjustStackPointer): + (JSC::WASMFunctionCompiler::callAndUnboxResult): + 2015-09-16 Sukolsak Sakshuwong Implement indirect calls in WebAssembly diff --git a/Source/JavaScriptCore/jit/RegisterSet.cpp b/Source/JavaScriptCore/jit/RegisterSet.cpp index a0d0dbe..be4c68b 100644 --- a/Source/JavaScriptCore/jit/RegisterSet.cpp +++ b/Source/JavaScriptCore/jit/RegisterSet.cpp @@ -274,6 +274,39 @@ RegisterSet RegisterSet::ftlCalleeSaveRegisters() return result; } +#if ENABLE(WEBASSEMBLY) +RegisterSet RegisterSet::webAssemblyCalleeSaveRegisters() +{ + RegisterSet result; +#if CPU(X86) +#elif CPU(X86_64) +#if !OS(WINDOWS) + ASSERT(GPRInfo::regCS3 == GPRInfo::tagTypeNumberRegister); + ASSERT(GPRInfo::regCS4 == GPRInfo::tagMaskRegister); + result.set(GPRInfo::regCS3); + result.set(GPRInfo::regCS4); +#else + ASSERT(GPRInfo::regCS5 == GPRInfo::tagTypeNumberRegister); + ASSERT(GPRInfo::regCS6 == GPRInfo::tagMaskRegister); + result.set(GPRInfo::regCS5); + result.set(GPRInfo::regCS6); +#endif +#elif CPU(ARM_THUMB2) +#elif CPU(ARM_TRADITIONAL) +#elif CPU(ARM64) + ASSERT(GPRInfo::regCS8 == GPRInfo::tagTypeNumberRegister); + ASSERT(GPRInfo::regCS9 == GPRInfo::tagMaskRegister); + result.set(GPRInfo::regCS8); + result.set(GPRInfo::regCS9); +#elif CPU(MIPS) +#elif CPU(SH4) +#else + UNREACHABLE_FOR_PLATFORM(); +#endif + return result; +} +#endif + RegisterSet RegisterSet::allGPRs() { RegisterSet result; diff --git a/Source/JavaScriptCore/jit/RegisterSet.h b/Source/JavaScriptCore/jit/RegisterSet.h index 36630d1..9f5cd5e 100644 --- a/Source/JavaScriptCore/jit/RegisterSet.h +++ b/Source/JavaScriptCore/jit/RegisterSet.h @@ -54,6 +54,9 @@ public: static RegisterSet llintBaselineCalleeSaveRegisters(); // Registers saved and used by the LLInt. static RegisterSet dfgCalleeSaveRegisters(); // Registers saved and used by the DFG JIT. static RegisterSet ftlCalleeSaveRegisters(); // Registers that might be saved and used by the FTL JIT. +#if ENABLE(WEBASSEMBLY) + static RegisterSet webAssemblyCalleeSaveRegisters(); // Registers saved and used by the WebAssembly JIT. +#endif static RegisterSet stubUnavailableRegisters(); // The union of callee saves and special registers. static RegisterSet allGPRs(); static RegisterSet allFPRs(); diff --git a/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h b/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h index 35dee74..a0c27b8 100644 --- a/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h +++ b/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h @@ -91,17 +91,23 @@ public: void startFunction(const Vector& arguments, uint32_t numberOfI32LocalVariables, uint32_t numberOfF32LocalVariables, uint32_t numberOfF64LocalVariables) { + m_calleeSaveSpace = WTF::roundUpToMultipleOf(sizeof(StackSlot), RegisterSet::webAssemblyCalleeSaveRegisters().numberOfSetRegisters() * sizeof(void*)); + m_codeBlock->setCalleeSaveRegisters(RegisterSet::webAssemblyCalleeSaveRegisters()); + emitFunctionPrologue(); emitPutImmediateToCallFrameHeader(m_codeBlock, JSStack::CodeBlock); m_beginLabel = label(); - addPtr(TrustedImm32(-WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_stackHeight) * sizeof(StackSlot) - maxFrameExtentForSlowPathCall), GPRInfo::callFrameRegister, GPRInfo::regT1); + addPtr(TrustedImm32(-m_calleeSaveSpace - WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_stackHeight) * sizeof(StackSlot) - maxFrameExtentForSlowPathCall), GPRInfo::callFrameRegister, GPRInfo::regT1); m_stackOverflow = branchPtr(Above, AbsoluteAddress(m_vm->addressOfStackLimit()), GPRInfo::regT1); move(GPRInfo::regT1, stackPointerRegister); checkStackPointerAlignment(); + emitSaveCalleeSaves(); + emitMaterializeTagCheckRegisters(); + m_numberOfLocals = arguments.size() + numberOfI32LocalVariables + numberOfF32LocalVariables + numberOfF64LocalVariables; unsigned localIndex = 0; @@ -159,6 +165,7 @@ public: JSValueRegs returnValueRegs(GPRInfo::returnValueGPR2, GPRInfo::returnValueGPR); #endif moveTrustedValue(jsUndefined(), returnValueRegs); + emitRestoreCalleeSaves(); emitFunctionEpilogue(); ret(); @@ -184,6 +191,8 @@ public: if (!m_exceptionChecks.empty()) { m_exceptionChecks.link(this); + copyCalleeSavesToVMCalleeSavesBuffer(); + // lookupExceptionHandler is passed two arguments, the VM and the exec (the CallFrame*). move(TrustedImmPtr(vm()), GPRInfo::argumentGPR0); move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1); @@ -289,6 +298,7 @@ public: default: ASSERT_NOT_REACHED(); } + emitRestoreCalleeSaves(); emitFunctionEpilogue(); ret(); } @@ -804,13 +814,13 @@ private: Address localAddress(unsigned localIndex) const { ASSERT(localIndex < m_numberOfLocals); - return Address(GPRInfo::callFrameRegister, -(localIndex + 1) * sizeof(StackSlot)); + return Address(GPRInfo::callFrameRegister, -m_calleeSaveSpace - (localIndex + 1) * sizeof(StackSlot)); } Address temporaryAddress(unsigned temporaryIndex) const { ASSERT(m_numberOfLocals + temporaryIndex < m_stackHeight); - return Address(GPRInfo::callFrameRegister, -(m_numberOfLocals + temporaryIndex + 1) * sizeof(StackSlot)); + return Address(GPRInfo::callFrameRegister, -m_calleeSaveSpace - (m_numberOfLocals + temporaryIndex + 1) * sizeof(StackSlot)); } void appendCall(const FunctionPtr& function) @@ -913,7 +923,7 @@ private: void boxArgumentsAndAdjustStackPointer(const Vector& arguments) { size_t argumentCount = arguments.size(); - int stackOffset = -WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_numberOfLocals + m_tempStackTop + argumentCount + 1 + JSStack::CallFrameHeaderSize); + int stackOffset = -m_calleeSaveSpace - WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_numberOfLocals + m_tempStackTop + argumentCount + 1 + JSStack::CallFrameHeaderSize); storeTrustedValue(jsUndefined(), Address(GPRInfo::callFrameRegister, (stackOffset + CallFrame::thisArgumentOffset()) * sizeof(Register))); @@ -966,7 +976,7 @@ private: m_callCompilationInfo.last().callReturnLocation = emitNakedCall(m_vm->getCTIStub(linkCallThunkGenerator).code()); end.link(this); - addPtr(TrustedImm32(-WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_stackHeight) * sizeof(StackSlot) - maxFrameExtentForSlowPathCall), GPRInfo::callFrameRegister, stackPointerRegister); + addPtr(TrustedImm32(-m_calleeSaveSpace - WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_stackHeight) * sizeof(StackSlot) - maxFrameExtentForSlowPathCall), GPRInfo::callFrameRegister, stackPointerRegister); checkStackPointerAlignment(); switch (returnType) { @@ -1048,6 +1058,7 @@ private: unsigned m_stackHeight; unsigned m_numberOfLocals; unsigned m_tempStackTop { 0 }; + unsigned m_calleeSaveSpace; Vector m_breakTargets; Vector m_continueTargets; -- 1.8.3.1