WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
the patch
blah.patch (text/plain), 49.92 KB, created by
Filip Pizlo
on 2013-12-20 15:22:38 PST
(
hide
)
Description:
the patch
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2013-12-20 15:22:38 PST
Size:
49.92 KB
patch
obsolete
>Index: Source/JavaScriptCore/ChangeLog >=================================================================== >--- Source/JavaScriptCore/ChangeLog (revision 160933) >+++ Source/JavaScriptCore/ChangeLog (working copy) >@@ -1,3 +1,56 @@ >+2013-12-20 Filip Pizlo <fpizlo@apple.com> >+ >+ Arity check slow path should ensure that when we return, we restore SP back to what the caller expects >+ https://bugs.webkit.org/show_bug.cgi?id=126043 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Implements proper stack restoration after return from a function that failed arity >+ check. >+ >+ * JavaScriptCore.xcodeproj/project.pbxproj: >+ * dfg/DFGJITCompiler.cpp: >+ (JSC::DFG::JITCompiler::compileFunction): >+ * ftl/FTLLink.cpp: >+ (JSC::FTL::link): >+ * ftl/FTLOSRExit.h: >+ * ftl/FTLOSRExitCompiler.cpp: >+ (JSC::FTL::compileStub): >+ * jit/ArityCheckFailReturnThunks.cpp: Added. >+ (JSC::ArityCheckFailReturnThunks::ArityCheckFailReturnThunks): >+ (JSC::ArityCheckFailReturnThunks::~ArityCheckFailReturnThunks): >+ (JSC::ArityCheckFailReturnThunks::returnPCsFor): >+ (JSC::ArityCheckFailReturnThunks::returnPCFor): >+ * jit/ArityCheckFailReturnThunks.h: Added. >+ * jit/JIT.cpp: >+ (JSC::JIT::privateCompile): >+ * jit/JITCode.cpp: >+ (JSC::DirectJITCode::addressForCall): >+ * jit/RegisterPreservationWrapperGenerator.cpp: >+ (JSC::generateRegisterPreservationWrapper): >+ (JSC::generateRegisterRestoration): >+ (JSC::registerRestorationThunkGenerator): >+ * jit/RegisterPreservationWrapperGenerator.h: >+ * jit/ThunkGenerators.cpp: >+ (JSC::arityFixup): >+ * llint/LLIntOffsetsExtractor.cpp: >+ * llint/LLIntSlowPaths.cpp: >+ (JSC::LLInt::LLINT_SLOW_PATH_DECL): >+ * llint/LowLevelInterpreter.asm: >+ * llint/LowLevelInterpreter32_64.asm: >+ * llint/LowLevelInterpreter64.asm: >+ * offlineasm/x86.rb: >+ * runtime/CommonSlowPaths.cpp: >+ (JSC::setupArityCheckData): >+ (JSC::SLOW_PATH_DECL): >+ * runtime/CommonSlowPaths.h: >+ (JSC::CommonSlowPaths::arityCheckFor): >+ * runtime/StackAlignment.h: >+ (JSC::logStackAlignmentRegisters): >+ * runtime/VM.cpp: >+ (JSC::VM::VM): >+ * runtime/VM.h: >+ > 2013-12-20 Mark Lam <mark.lam@apple.com> > > Fix broken non-FTL build. >Index: Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >=================================================================== >--- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (revision 160893) >+++ Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (working copy) >@@ -277,6 +277,8 @@ > 0F6B1CC41862C47800845D97 /* FTLRegisterAtOffset.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6B1CC01862C47800845D97 /* FTLRegisterAtOffset.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F6B1CC51862C47800845D97 /* FTLUnwindInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6B1CC11862C47800845D97 /* FTLUnwindInfo.cpp */; }; > 0F6B1CC61862C47800845D97 /* FTLUnwindInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6B1CC21862C47800845D97 /* FTLUnwindInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0F6B1CC918641DF800845D97 /* ArityCheckFailReturnThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6B1CC718641DF800845D97 /* ArityCheckFailReturnThunks.cpp */; }; >+ 0F6B1CCA18641DF800845D97 /* ArityCheckFailReturnThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6B1CC818641DF800845D97 /* ArityCheckFailReturnThunks.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F7025A91714B0FA00382C0E /* DFGOSRExitCompilerCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7025A71714B0F800382C0E /* DFGOSRExitCompilerCommon.cpp */; }; > 0F7025AA1714B0FC00382C0E /* DFGOSRExitCompilerCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7025A81714B0F800382C0E /* DFGOSRExitCompilerCommon.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F714CA416EA92F000F3EBEB /* DFGBackwardsPropagationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F714CA116EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.cpp */; }; >@@ -1599,6 +1601,8 @@ > 0F6B1CC01862C47800845D97 /* FTLRegisterAtOffset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLRegisterAtOffset.h; path = ftl/FTLRegisterAtOffset.h; sourceTree = "<group>"; }; > 0F6B1CC11862C47800845D97 /* FTLUnwindInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLUnwindInfo.cpp; path = ftl/FTLUnwindInfo.cpp; sourceTree = "<group>"; }; > 0F6B1CC21862C47800845D97 /* FTLUnwindInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLUnwindInfo.h; path = ftl/FTLUnwindInfo.h; sourceTree = "<group>"; }; >+ 0F6B1CC718641DF800845D97 /* ArityCheckFailReturnThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArityCheckFailReturnThunks.cpp; sourceTree = "<group>"; }; >+ 0F6B1CC818641DF800845D97 /* ArityCheckFailReturnThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArityCheckFailReturnThunks.h; sourceTree = "<group>"; }; > 0F7025A71714B0F800382C0E /* DFGOSRExitCompilerCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGOSRExitCompilerCommon.cpp; path = dfg/DFGOSRExitCompilerCommon.cpp; sourceTree = "<group>"; }; > 0F7025A81714B0F800382C0E /* DFGOSRExitCompilerCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSRExitCompilerCommon.h; path = dfg/DFGOSRExitCompilerCommon.h; sourceTree = "<group>"; }; > 0F714CA116EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGBackwardsPropagationPhase.cpp; path = dfg/DFGBackwardsPropagationPhase.cpp; sourceTree = "<group>"; }; >@@ -3005,6 +3009,8 @@ > 1429D92C0ED22D7000B89619 /* jit */ = { > isa = PBXGroup; > children = ( >+ 0F6B1CC718641DF800845D97 /* ArityCheckFailReturnThunks.cpp */, >+ 0F6B1CC818641DF800845D97 /* ArityCheckFailReturnThunks.h */, > 0F24E53B17EA9F5900ABB217 /* AssemblyHelpers.cpp */, > 0F24E53C17EA9F5900ABB217 /* AssemblyHelpers.h */, > 0F24E53D17EA9F5900ABB217 /* CCallHelpers.h */, >@@ -4979,6 +4985,7 @@ > 9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */, > 451539B912DC994500EF7AC4 /* Yarr.h in Headers */, > 0F666ECD1836B37E00D017F1 /* DFGResurrectionForValidationPhase.h in Headers */, >+ 0F6B1CCA18641DF800845D97 /* ArityCheckFailReturnThunks.h in Headers */, > 86704B8512DBA33700A9FE7B /* YarrInterpreter.h in Headers */, > 86704B8712DBA33700A9FE7B /* YarrJIT.h in Headers */, > 86704B8812DBA33700A9FE7B /* YarrParser.h in Headers */, >@@ -5805,6 +5812,7 @@ > 0F8F2B9E17306C8D007DBDA5 /* SourceCode.cpp in Sources */, > 0F493AFA16D0CAD30084508B /* SourceProvider.cpp in Sources */, > E49DC16B12EF293E00184A1F /* SourceProviderCache.cpp in Sources */, >+ 0F6B1CC918641DF800845D97 /* ArityCheckFailReturnThunks.cpp in Sources */, > 0F0CD4C415F6B6BB0032F1C0 /* SparseArrayValueMap.cpp in Sources */, > 0F5541B11613C1FB00CE3E25 /* SpecialPointer.cpp in Sources */, > 0FD82E86141F3FF100179C94 /* SpeculatedType.cpp in Sources */, >Index: Source/JavaScriptCore/dfg/DFGJITCompiler.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGJITCompiler.cpp (revision 160893) >+++ Source/JavaScriptCore/dfg/DFGJITCompiler.cpp (working copy) >@@ -28,6 +28,7 @@ > > #if ENABLE(DFG_JIT) > >+#include "ArityCheckFailReturnThunks.h" > #include "CodeBlock.h" > #include "DFGFailedFinalizer.h" > #include "DFGInlineCacheWrapperInlines.h" >@@ -368,6 +369,8 @@ void JITCompiler::compileFunction() > m_speculative->callOperationWithCallFrameRollbackOnException(m_codeBlock->m_isConstructor ? operationConstructArityCheck : operationCallArityCheck, GPRInfo::regT0); > branchTest32(Zero, GPRInfo::regT0).linkTo(fromArityCheck, this); > emitStoreCodeOrigin(CodeOrigin(0)); >+ move(TrustedImmPtr(m_vm->arityCheckFailReturnThunks->returnPCsFor(*m_vm, m_codeBlock->numParameters())), GPRInfo::regT5); >+ loadPtr(BaseIndex(GPRInfo::regT5, GPRInfo::regT0, timesPtr()), GPRInfo::regT5); > m_callArityFixup = call(); > jump(fromArityCheck); > >Index: Source/JavaScriptCore/ftl/FTLLink.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLLink.cpp (revision 160892) >+++ Source/JavaScriptCore/ftl/FTLLink.cpp (working copy) >@@ -28,6 +28,7 @@ > > #if ENABLE(FTL_JIT) > >+#include "ArityCheckFailReturnThunks.h" > #include "CCallHelpers.h" > #include "CallFrameInlines.h" > #include "CodeBlockWithJITType.h" >@@ -46,6 +47,7 @@ using namespace DFG; > void link(State& state) > { > CodeBlock* codeBlock = state.graph.m_codeBlock; >+ VM& vm = state.graph.m_vm; > > // LLVM will create its own jump tables as needed. > codeBlock->clearSwitchJumpTables(); >@@ -61,7 +63,7 @@ void link(State& state) > > // Create the entrypoint. Note that we use this entrypoint totally differently > // depending on whether we're doing OSR entry or not. >- CCallHelpers jit(&state.graph.m_vm, codeBlock); >+ CCallHelpers jit(&vm, codeBlock); > > OwnPtr<LinkBuffer> linkBuffer; > CCallHelpers::Label arityCheck; >@@ -84,27 +86,29 @@ void link(State& state) > jit.store32( > CCallHelpers::TrustedImm32(CallFrame::Location::encodeAsBytecodeOffset(0)), > CCallHelpers::tagFor(JSStack::ArgumentCount)); >- jit.storePtr(GPRInfo::callFrameRegister, &state.graph.m_vm.topCallFrame); >+ jit.storePtr(GPRInfo::callFrameRegister, &vm.topCallFrame); > CCallHelpers::Call callArityCheck = jit.call(); > #if !ASSERT_DISABLED > // FIXME: need to make this call register with exception handling somehow. This is > // part of a bigger problem: FTL should be able to handle exceptions. > // https://bugs.webkit.org/show_bug.cgi?id=113622 > // Until then, use a JIT ASSERT. >- jit.load64(state.graph.m_vm.addressOfException(), GPRInfo::regT1); >+ jit.load64(vm.addressOfException(), GPRInfo::regT1); > jit.jitAssertIsNull(GPRInfo::regT1); > #endif > jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0); > jit.emitFunctionEpilogue(); > mainPathJumps.append(jit.branchTest32(CCallHelpers::Zero, GPRInfo::regT0)); > jit.emitFunctionPrologue(); >+ jit.move(CCallHelpers::TrustedImmPtr(vm.arityCheckFailReturnThunks->returnPCsFor(vm, codeBlock->numParameters())), GPRInfo::regT5); >+ jit.loadPtr(CCallHelpers::BaseIndex(GPRInfo::regT5, GPRInfo::regT0, CCallHelpers::timesPtr()), GPRInfo::regT5); > CCallHelpers::Call callArityFixup = jit.call(); > jit.emitFunctionEpilogue(); > mainPathJumps.append(jit.jump()); > >- linkBuffer = adoptPtr(new LinkBuffer(state.graph.m_vm, &jit, codeBlock, JITCompilationMustSucceed)); >+ linkBuffer = adoptPtr(new LinkBuffer(vm, &jit, codeBlock, JITCompilationMustSucceed)); > linkBuffer->link(callArityCheck, codeBlock->m_isConstructor ? operationConstructArityCheck : operationCallArityCheck); >- linkBuffer->link(callArityFixup, FunctionPtr((state.graph.m_vm.getCTIStub(arityFixup)).code().executableAddress())); >+ linkBuffer->link(callArityFixup, FunctionPtr((vm.getCTIStub(arityFixup)).code().executableAddress())); > linkBuffer->link(mainPathJumps, CodeLocationLabel(bitwise_cast<void*>(state.generatedFunction))); > > state.jitCode->initializeAddressForCall(MacroAssemblerCodePtr(bitwise_cast<void*>(state.generatedFunction))); >@@ -120,8 +124,7 @@ void link(State& state) > jit.emitFunctionEpilogue(); > CCallHelpers::Jump mainPathJump = jit.jump(); > >- linkBuffer = adoptPtr(new LinkBuffer( >- state.graph.m_vm, &jit, codeBlock, JITCompilationMustSucceed)); >+ linkBuffer = adoptPtr(new LinkBuffer(vm, &jit, codeBlock, JITCompilationMustSucceed)); > linkBuffer->link(mainPathJump, CodeLocationLabel(bitwise_cast<void*>(state.generatedFunction))); > > state.jitCode->initializeAddressForCall(linkBuffer->locationOf(start)); >Index: Source/JavaScriptCore/ftl/FTLOSRExit.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLOSRExit.h (revision 160893) >+++ Source/JavaScriptCore/ftl/FTLOSRExit.h (working copy) >@@ -149,7 +149,6 @@ struct OSRExit : public DFG::OSRExitBase > unsigned numberOfArguments, unsigned numberOfLocals); > > MacroAssemblerCodeRef m_code; >- RefPtr<JITStubRoutine> m_registerRestoration; > > // The first argument to the exit call may be a value we wish to profile. > // If that's the case, the format will be not Invalid and we'll have a >Index: Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp (revision 160893) >+++ Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp (working copy) >@@ -46,14 +46,6 @@ using namespace DFG; > static void compileStub( > unsigned exitID, JITCode* jitCode, OSRExit& exit, VM* vm, CodeBlock* codeBlock) > { >- // Register restoration is a GC-aware JIT stub routine since we need it to stay alive >- // if it's on the stack but all of our other things (like the FTL::OSRExit) are dead. >- exit.m_registerRestoration = createJITStubRoutine( >- generateRegisterRestoration( >- *vm, codeBlock->ownerExecutable(), >- codeBlock->codeType() == FunctionCode ? MustCheckArity : ArityCheckNotRequired), >- *vm, codeBlock->ownerExecutable(), true); >- > StackMaps::Record* record; > > for (unsigned i = jitCode->stackmaps.records.size(); i--;) { >@@ -219,7 +211,7 @@ static void compileStub( > jit.loadPtr(MacroAssembler::Address(MacroAssembler::framePointerRegister, CallFrame::returnPCOffset()), GPRInfo::regT0); > jit.storePtr(GPRInfo::regT0, GPRInfo::regT1); > jit.storePtr( >- MacroAssembler::TrustedImmPtr(exit.m_registerRestoration->code().code().executableAddress()), >+ MacroAssembler::TrustedImmPtr(vm->getCTIStub(registerRestorationThunkGenerator).code().executableAddress()), > MacroAssembler::Address(MacroAssembler::framePointerRegister, CallFrame::returnPCOffset())); > > // Now get state out of the scratch buffer and place it back into the stack. This part does >Index: Source/JavaScriptCore/jit/ArityCheckFailReturnThunks.cpp >=================================================================== >--- Source/JavaScriptCore/jit/ArityCheckFailReturnThunks.cpp (revision 0) >+++ Source/JavaScriptCore/jit/ArityCheckFailReturnThunks.cpp (working copy) >@@ -0,0 +1,128 @@ >+/* >+ * Copyright (C) 2013 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "ArityCheckFailReturnThunks.h" >+ >+#if ENABLE(JIT) >+ >+#include "AssemblyHelpers.h" >+#include "LinkBuffer.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.nearCall(); >+ jit.pop(GPRInfo::regT2); >+ jit.load32( >+ AssemblyHelpers::Address( >+ AssemblyHelpers::stackPointerRegister, >+ (JSStack::ArgumentCount - JSStack::CallerFrameAndPCSize) * sizeof(Register) + >+ PayloadOffset), >+ GPRInfo::regT1); >+ jit.add32( >+ AssemblyHelpers::TrustedImm32( >+ JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize + size - 1), >+ GPRInfo::regT1); >+ jit.lshift32(AssemblyHelpers::TrustedImm32(3), GPRInfo::regT1); >+ jit.addPtr(AssemblyHelpers::stackPointerRegister, GPRInfo::regT1); >+ jit.loadPtr(GPRInfo::regT1, GPRInfo::regT1); >+ >+ jit.addPtr( >+ AssemblyHelpers::TrustedImm32(size * sizeof(Register)), >+ AssemblyHelpers::stackPointerRegister); >+ >+ jit.jump(GPRInfo::regT1); >+ } >+ >+ LinkBuffer linkBuffer(vm, &jit, GLOBAL_THUNK_ID); >+ >+ 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(std::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()]; >+} >+ >+} // namespace JSC >+ >+#endif // ENABLE(JIT) >+ >Index: Source/JavaScriptCore/jit/ArityCheckFailReturnThunks.h >=================================================================== >--- Source/JavaScriptCore/jit/ArityCheckFailReturnThunks.h (revision 0) >+++ Source/JavaScriptCore/jit/ArityCheckFailReturnThunks.h (working copy) >@@ -0,0 +1,59 @@ >+/* >+ * Copyright (C) 2013 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#ifndef ArityCheckFailReturnThunks_h >+#define ArityCheckFailReturnThunks_h >+ >+#if ENABLE(JIT) >+ >+#include "CodeLocation.h" >+#include "ConcurrentJITLock.h" >+#include <wtf/HashMap.h> >+ >+namespace JSC { >+ >+class ArityCheckFailReturnThunks { >+public: >+ ArityCheckFailReturnThunks(); >+ ~ArityCheckFailReturnThunks(); >+ >+ // Returns a pointer to an array of return labels indexed by missingArgs. >+ CodeLocationLabel* returnPCsFor(VM&, unsigned numExpectedArgumentsIncludingThis); >+ >+ CodeLocationLabel returnPCFor(VM&, unsigned slotsToAdd); >+ >+private: >+ Vector<std::unique_ptr<CodeLocationLabel[]>> m_returnPCArrays; >+ unsigned m_nextSize; >+ Vector<MacroAssemblerCodeRef> m_refs; >+ ConcurrentJITLock m_lock; >+}; >+ >+} // namespace JSC >+ >+#endif // ENABLE(JIT) >+ >+#endif // ArityCheckFailReturnThunks_h >+ >Index: Source/JavaScriptCore/jit/JIT.cpp >=================================================================== >--- Source/JavaScriptCore/jit/JIT.cpp (revision 160893) >+++ Source/JavaScriptCore/jit/JIT.cpp (working copy) >@@ -34,6 +34,7 @@ > JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse2CheckState = NotCheckedSSE2; > #endif > >+#include "ArityCheckFailReturnThunks.h" > #include "CodeBlock.h" > #include "DFGCapabilities.h" > #include "Interpreter.h" >@@ -576,6 +577,8 @@ CompilationResult JIT::privateCompile(JI > if (returnValueGPR != regT0) > move(returnValueGPR, regT0); > branchTest32(Zero, regT0).linkTo(beginLabel, this); >+ move(TrustedImmPtr(m_vm->arityCheckFailReturnThunks->returnPCsFor(*m_vm, m_codeBlock->numParameters())), regT5); >+ loadPtr(BaseIndex(regT5, regT0, timesPtr()), regT5); > emitNakedCall(m_vm->getCTIStub(arityFixup).code()); > > #if !ASSERT_DISABLED >@@ -664,20 +667,12 @@ CompilationResult JIT::privateCompile(JI > info.calleeGPR = regT0; > } > >-#if ENABLE(DFG_JIT) || ENABLE(LLINT) >- if (canBeOptimizedOrInlined() >-#if ENABLE(LLINT) >- || true >-#endif >- ) { >- CompactJITCodeMap::Encoder jitCodeMapEncoder; >- for (unsigned bytecodeOffset = 0; bytecodeOffset < m_labels.size(); ++bytecodeOffset) { >- if (m_labels[bytecodeOffset].isSet()) >- jitCodeMapEncoder.append(bytecodeOffset, patchBuffer.offsetOf(m_labels[bytecodeOffset])); >- } >- m_codeBlock->setJITCodeMap(jitCodeMapEncoder.finish()); >+ CompactJITCodeMap::Encoder jitCodeMapEncoder; >+ for (unsigned bytecodeOffset = 0; bytecodeOffset < m_labels.size(); ++bytecodeOffset) { >+ if (m_labels[bytecodeOffset].isSet()) >+ jitCodeMapEncoder.append(bytecodeOffset, patchBuffer.offsetOf(m_labels[bytecodeOffset])); > } >-#endif >+ m_codeBlock->setJITCodeMap(jitCodeMapEncoder.finish()); > > MacroAssemblerCodePtr withArityCheck; > if (m_codeBlock->codeType() == FunctionCode) >Index: Source/JavaScriptCore/jit/JITCode.cpp >=================================================================== >--- Source/JavaScriptCore/jit/JITCode.cpp (revision 160893) >+++ Source/JavaScriptCore/jit/JITCode.cpp (working copy) >@@ -168,7 +168,7 @@ JITCode::CodePtr DirectJITCode::addressF > case MustPreserveRegisters: { > RegisterPreservationWrappers* wrappers = ensureWrappers(); > if (!wrappers->withoutArityCheck) >- wrappers->withoutArityCheck = generateRegisterPreservationWrapper(vm, executable, m_ref.code(), ArityCheckNotRequired); >+ wrappers->withoutArityCheck = generateRegisterPreservationWrapper(vm, executable, m_ref.code()); > return wrappers->withoutArityCheck.code(); > } } > case MustCheckArity: >@@ -179,7 +179,7 @@ JITCode::CodePtr DirectJITCode::addressF > case MustPreserveRegisters: { > RegisterPreservationWrappers* wrappers = ensureWrappers(); > if (!wrappers->withArityCheck) >- wrappers->withArityCheck = generateRegisterPreservationWrapper(vm, executable, m_withArityCheck, MustCheckArity); >+ wrappers->withArityCheck = generateRegisterPreservationWrapper(vm, executable, m_withArityCheck); > return wrappers->withArityCheck.code(); > } } > } >Index: Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp >=================================================================== >--- Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp (revision 160893) >+++ Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp (working copy) >@@ -58,7 +58,7 @@ ptrdiff_t registerPreservationOffset() > return sizeof(Register) * numberOfNewStackSlots; > } > >-MacroAssemblerCodeRef generateRegisterPreservationWrapper(VM& vm, ExecutableBase* executable, MacroAssemblerCodePtr target, ArityCheckMode arity) >+MacroAssemblerCodeRef generateRegisterPreservationWrapper(VM& vm, ExecutableBase* executable, MacroAssemblerCodePtr target) > { > #if ENABLE(FTL_JIT) > // We shouldn't ever be generating wrappers for native functions. >@@ -114,7 +114,7 @@ MacroAssemblerCodeRef generateRegisterPr > > AssemblyHelpers::Call call = jit.nearCall(); > >- generateRegisterRestoration(jit, executable, arity); >+ generateRegisterRestoration(jit); > > LinkBuffer linkBuffer(vm, &jit, GLOBAL_THUNK_ID); > linkBuffer.link(call, CodeLocationLabel(target)); >@@ -130,7 +130,7 @@ MacroAssemblerCodeRef generateRegisterPr > #endif // ENABLE(FTL_JIT) > } > >-void generateRegisterRestoration(AssemblyHelpers& jit, ExecutableBase* executable, ArityCheckMode arity) >+void generateRegisterRestoration(AssemblyHelpers& jit) > { > RegisterSet toSave = registersToPreserve(); > ptrdiff_t offset = registerPreservationOffset(); >@@ -145,19 +145,6 @@ void generateRegisterRestoration(Assembl > (JSStack::ArgumentCount - JSStack::CallerFrameAndPCSize) * sizeof(Register) + PayloadOffset), > GPRInfo::regT2); > >- if (arity == MustCheckArity) { >- // It's possible that the arity checker had extended the stack. In that case, we need >- // to adjust the argument count to be the max of what the frame claims and what the >- // executable desired. >- FunctionExecutable* functionExecutable = jsCast<FunctionExecutable*>(executable); >- int parameterCount = functionExecutable->parameterCount() + 1; >- AssemblyHelpers::Jump ok = jit.branch32( >- AssemblyHelpers::AboveOrEqual, GPRInfo::regT2, >- AssemblyHelpers::TrustedImm32(parameterCount)); >- jit.move(AssemblyHelpers::TrustedImm32(parameterCount), GPRInfo::regT2); >- ok.link(&jit); >- } >- > jit.lshift32(AssemblyHelpers::TrustedImm32(3), GPRInfo::regT2); > > jit.addPtr(AssemblyHelpers::TrustedImm32(offset), AssemblyHelpers::stackPointerRegister); >@@ -199,14 +186,12 @@ void generateRegisterRestoration(Assembl > jit.jump(GPRInfo::regT1); > } > >-MacroAssemblerCodeRef generateRegisterRestoration( >- VM& vm, ExecutableBase* executable, ArityCheckMode arity) >+MacroAssemblerCodeRef registerRestorationThunkGenerator(VM* vm) > { >- ScriptExecutable* scriptExecutable = jsCast<ScriptExecutable*>(executable); >- AssemblyHelpers jit(&vm, 0); >- generateRegisterRestoration(jit, executable, arity); >- LinkBuffer linkBuffer(vm, &jit, GLOBAL_THUNK_ID); >- return FINALIZE_DFG_CODE(linkBuffer, ("Register restoration thunk for %s/%s", toCString(scriptExecutable->hashFor(CodeForCall)).data(), toCString(scriptExecutable->hashFor(CodeForConstruct)).data())); >+ AssemblyHelpers jit(vm, 0); >+ generateRegisterRestoration(jit); >+ LinkBuffer linkBuffer(*vm, &jit, GLOBAL_THUNK_ID); >+ return FINALIZE_CODE(linkBuffer, ("Register restoration thunk")); > } > > } // namespace JSC >Index: Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.h >=================================================================== >--- Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.h (revision 160893) >+++ Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.h (working copy) >@@ -39,11 +39,11 @@ RegisterSet registersToPreserve(); > > ptrdiff_t registerPreservationOffset(); > >-MacroAssemblerCodeRef generateRegisterPreservationWrapper(VM&, ExecutableBase*, MacroAssemblerCodePtr target, ArityCheckMode); >+MacroAssemblerCodeRef generateRegisterPreservationWrapper(VM&, ExecutableBase*, MacroAssemblerCodePtr target); > >-void generateRegisterRestoration(AssemblyHelpers&, ExecutableBase*, ArityCheckMode); >+void generateRegisterRestoration(AssemblyHelpers&); > >-MacroAssemblerCodeRef generateRegisterRestoration(VM&, ExecutableBase*, ArityCheckMode); >+MacroAssemblerCodeRef registerRestorationThunkGenerator(VM*); > > } // namespace JSC > >Index: Source/JavaScriptCore/jit/ThunkGenerators.cpp >=================================================================== >--- Source/JavaScriptCore/jit/ThunkGenerators.cpp (revision 160893) >+++ Source/JavaScriptCore/jit/ThunkGenerators.cpp (working copy) >@@ -440,14 +440,16 @@ MacroAssemblerCodeRef arityFixup(VM* vm) > { > JSInterfaceJIT jit(vm); > >- // We enter with fixup count in regT0 >+ // We enter with fixup count, in aligned stack units, in regT0 and the return thunk in >+ // regT5. We use VM::currentReturnThunkPC instead of regT5 on X86-32. > #if USE(JSVALUE64) > # if CPU(X86_64) > jit.pop(JSInterfaceJIT::regT4); > # endif >+ jit.lshift32(JSInterfaceJIT::TrustedImm32(logStackAlignmentRegisters()), JSInterfaceJIT::regT0); > jit.neg64(JSInterfaceJIT::regT0); > jit.move(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::regT3); >- jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * 8), JSInterfaceJIT::regT2); >+ jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * sizeof(Register)), JSInterfaceJIT::regT2); > jit.add32(JSInterfaceJIT::TrustedImm32(JSStack::CallFrameHeaderSize), JSInterfaceJIT::regT2); > > // Move current frame down regT0 number of slots >@@ -457,18 +459,27 @@ MacroAssemblerCodeRef arityFixup(VM* vm) > jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3); > jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2).linkTo(copyLoop, &jit); > >- // Fill in regT0 missing arg slots with undefined >+ // Fill in regT0 - 1 missing arg slots with undefined > jit.move(JSInterfaceJIT::regT0, JSInterfaceJIT::regT2); > jit.move(JSInterfaceJIT::TrustedImm64(ValueUndefined), JSInterfaceJIT::regT1); >+ jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2); > JSInterfaceJIT::Label fillUndefinedLoop(jit.label()); > jit.store64(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight)); > jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3); > jit.branchAdd32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2).linkTo(fillUndefinedLoop, &jit); >- >+ > // Adjust call frame register and stack pointer to account for missing args >- jit.lshift64(JSInterfaceJIT::TrustedImm32(3), JSInterfaceJIT::regT0); >- jit.addPtr(JSInterfaceJIT::regT0, JSInterfaceJIT::callFrameRegister); >- jit.addPtr(JSInterfaceJIT::regT0, JSInterfaceJIT::stackPointerRegister); >+ jit.move(JSInterfaceJIT::regT0, JSInterfaceJIT::regT1); >+ jit.lshift64(JSInterfaceJIT::TrustedImm32(3), JSInterfaceJIT::regT1); >+ jit.addPtr(JSInterfaceJIT::regT1, JSInterfaceJIT::callFrameRegister); >+ jit.addPtr(JSInterfaceJIT::regT1, JSInterfaceJIT::stackPointerRegister); >+ >+ // Save the original return PC. >+ jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset()), GPRInfo::regT1); >+ jit.storePtr(GPRInfo::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight)); >+ >+ // Install the new return PC. >+ jit.storePtr(GPRInfo::regT5, JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset())); > > # if CPU(X86_64) > jit.push(JSInterfaceJIT::regT4); >Index: Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp >=================================================================== >--- Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp (revision 160892) >+++ Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp (working copy) >@@ -27,6 +27,7 @@ > > #include "ArrayProfile.h" > #include "CodeBlock.h" >+#include "CommonSlowPaths.h" > #include "Debugger.h" > #include "Executable.h" > #include "Heap.h" >Index: Source/JavaScriptCore/llint/LLIntSlowPaths.cpp >=================================================================== >--- Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (revision 160893) >+++ Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (working copy) >@@ -256,6 +256,10 @@ LLINT_SLOW_PATH_DECL(trace) > static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()), > opcodeNames[exec->vm().interpreter->getOpcodeID(pc[0].u.opcode)], > exec->scope(), pc); >+ if (exec->vm().interpreter->getOpcodeID(pc[0].u.opcode) == op_enter) { >+ dataLogF("Frame will eventually return to %p\n", exec->returnPC().value()); >+ *bitwise_cast<volatile char*>(exec->returnPC().value()); >+ } > if (exec->vm().interpreter->getOpcodeID(pc[0].u.opcode) == op_ret) { > dataLogF("Will be returning to %p\n", exec->returnPC().value()); > dataLogF("The new cfr will be %p\n", exec->callerFrame()); >Index: Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm >=================================================================== >--- Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (revision 160892) >+++ Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (working copy) >@@ -172,9 +172,9 @@ end > > macro doCallToJavaScript(makeCall, doReturn) > if X86 >- const entry = t5 >+ const entry = t4 > const vmTopCallFrame = t2 >- const protoCallFrame = t4 >+ const protoCallFrame = t5 > > const extraStackSpace = 28 > const previousCFR = t0 >@@ -194,8 +194,8 @@ macro doCallToJavaScript(makeCall, doRet > const previousPC = lr > const temp1 = t3 # Same as previousCFR > const temp2 = a3 # Same as topOfStack >- const temp3 = t4 >- const temp4 = t5 >+ const temp3 = t5 >+ const temp4 = t4 > elsif ARMv7 > const entry = a0 > const vmTopCallFrame = a1 >@@ -207,8 +207,8 @@ macro doCallToJavaScript(makeCall, doRet > const previousPC = lr > const temp1 = t3 # Same as previousCFR > const temp2 = a3 # Same as topOfStack >- const temp3 = t4 >- const temp4 = t5 >+ const temp3 = t5 >+ const temp4 = t4 > elsif MIPS > const entry = a0 > const vmTopCallFrame = a1 >@@ -219,8 +219,8 @@ macro doCallToJavaScript(makeCall, doRet > const previousCFR = t2 > const previousPC = lr > const temp1 = t3 >- const temp2 = t4 >- const temp3 = t5 >+ const temp2 = t5 >+ const temp3 = t4 > const temp4 = t6 > elsif SH4 > const entry = a0 >@@ -519,10 +519,10 @@ end > # Entrypoints into the interpreter > > # Expects that CodeBlock is in t1, which is what prologue() leaves behind. >-macro functionArityCheck(doneLabel, slow_path) >+macro functionArityCheck(doneLabel, slowPath) > loadi PayloadOffset + ArgumentCount[cfr], t0 > biaeq t0, CodeBlock::m_numParameters[t1], doneLabel >- cCall2(slow_path, cfr, PC) # This slow_path has a simple protocol: t0 = 0 => no error, t0 != 0 => error >+ cCall2(slowPath, cfr, PC) # This slowPath has a simple protocol: t0 = 0 => no error, t0 != 0 => error > btiz t0, .isArityFixupNeeded > move t1, cfr # t1 contains caller frame > jmp _llint_throw_from_slow_path_trampoline >Index: Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >=================================================================== >--- Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (revision 160892) >+++ Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (working copy) >@@ -52,10 +52,10 @@ macro dispatchAfterCall() > end > > macro cCall2(function, arg1, arg2) >- checkStackPointerAlignment(t5, 0xbad0c002) >+ checkStackPointerAlignment(t4, 0xbad0c002) > if X86_64 >- move arg1, t5 >- move arg2, t4 >+ move arg1, t4 >+ move arg2, t5 > call function > elsif ARM64 > move arg1, t0 >@@ -70,10 +70,10 @@ end > > # This barely works. arg3 and arg4 should probably be immediates. > macro cCall4(function, arg1, arg2, arg3, arg4) >- checkStackPointerAlignment(t5, 0xbad0c004) >+ checkStackPointerAlignment(t4, 0xbad0c004) > if X86_64 >- move arg1, t5 >- move arg2, t4 >+ move arg1, t4 >+ move arg2, t5 > move arg3, t1 > move arg4, t2 > call function >@@ -150,8 +150,8 @@ end > > macro doCallToJavaScript(makeCall) > if X86_64 >- const entry = t5 >- const vmTopCallFrame = t4 >+ const entry = t4 >+ const vmTopCallFrame = t5 > const protoCallFrame = t1 > const topOfStack = t2 > >@@ -166,10 +166,10 @@ macro doCallToJavaScript(makeCall) > const protoCallFrame = a2 > const topOfStack = a3 > >- const previousCFR = t4 >+ const previousCFR = t5 > const previousPC = lr > const temp1 = t3 >- const temp2 = t5 >+ const temp2 = t4 > const temp3 = t6 > end > >@@ -264,7 +264,7 @@ end > macro makeHostFunctionCall(entry, temp) > move entry, temp > if X86_64 >- move sp, t5 >+ move sp, t4 > elsif ARM64 or C_LOOP > move sp, a0 > end >@@ -399,19 +399,35 @@ end > # Entrypoints into the interpreter. > > # Expects that CodeBlock is in t1, which is what prologue() leaves behind. >-macro functionArityCheck(doneLabel, slow_path) >+macro functionArityCheck(doneLabel, slowPath) > loadi PayloadOffset + ArgumentCount[cfr], t0 > biaeq t0, CodeBlock::m_numParameters[t1], doneLabel > prepareStateForCCall() >- cCall2(slow_path, cfr, PC) # This slow_path has a simple protocol: t0 = 0 => no error, t0 != 0 => error >- btiz t0, .isArityFixupNeeded >+ cCall2(slowPath, cfr, PC) # This slowPath has the protocol: t0 = 0 => no error, t0 != 0 => error >+ btiz t0, .noError > move t1, cfr # t1 contains caller frame > jmp _llint_throw_from_slow_path_trampoline > >-.isArityFixupNeeded: >+.noError: >+ # t1 points to ArityCheckData. >+ loadp CommonSlowPaths::ArityCheckData::thunkToCall[t1], t2 >+ btpz t2, .proceedInline >+ >+ loadp CommonSlowPaths::ArityCheckData::returnPC[t1], t5 >+ loadp CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t0 >+ call t2 >+ if ASSERT_ENABLED >+ loadp ReturnPC[cfr], t0 >+ loadp [t0], t0 >+ end >+ jmp .continue >+ >+.proceedInline: >+ loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t1 > btiz t1, .continue > >- // Move frame up "t1" slots >+ // Move frame up "t1 * 2" slots >+ lshiftp 1, t1 > negq t1 > move cfr, t3 > loadi PayloadOffset + ArgumentCount[cfr], t2 >@@ -1731,7 +1747,7 @@ macro doCall(slowPath) > storei PC, ArgumentCount + TagOffset[cfr] > storei t2, ArgumentCount + PayloadOffset[t3] > addp CallerFrameAndPCSize, t3 >- callTargetFunction(t1,t3) >+ callTargetFunction(t1, t3) > > .opCallSlow: > slowPathForCall(slowPath) >@@ -1903,9 +1919,9 @@ macro nativeCallTrampoline(executableOff > loadp CallerFrame[cfr], t0 > loadq ScopeChain[t0], t1 > storeq t1, ScopeChain[cfr] >- move cfr, t5 # t5 = rdi >- loadp Callee[cfr], t4 # t4 = rsi >- loadp JSFunction::m_executable[t4], t1 >+ move cfr, t4 # t4 = rdi >+ loadp Callee[cfr], t5 # t5 = rsi >+ loadp JSFunction::m_executable[t5], t1 > checkStackPointerAlignment(t3, 0xdead0001) > call executableOffsetToFunction[t1] > loadp ScopeChain[cfr], t3 >Index: Source/JavaScriptCore/llint/LowLevelInterpreter.asm >=================================================================== >--- Source/JavaScriptCore/llint/LowLevelInterpreter.asm (revision 160892) >+++ Source/JavaScriptCore/llint/LowLevelInterpreter.asm (working copy) >@@ -95,7 +95,7 @@ if JSVALUE64 > # to C functions. > # - C calls are still given the Instruction* rather than the PC index. > # This requires an add before the call, and a sub after. >- const PC = t4 >+ const PC = t5 > const PB = t6 > const tagTypeNumber = csr1 > const tagMask = csr2 >@@ -113,7 +113,7 @@ if JSVALUE64 > end > > else >- const PC = t4 >+ const PC = t5 > macro loadisFromInstruction(offset, dest) > loadis offset * 4[PC], dest > end >@@ -481,11 +481,11 @@ _callToNativeFunction: > # void sanitizeStackForVM(VM* vm) > _sanitizeStackForVM: > if X86_64 >- const vm = t5 >+ const vm = t4 > const address = t1 > const zeroValue = t0 > elsif X86 >- const vm = t5 >+ const vm = t4 > const address = t1 > const zeroValue = t0 > else >Index: Source/JavaScriptCore/offlineasm/x86.rb >=================================================================== >--- Source/JavaScriptCore/offlineasm/x86.rb (revision 160892) >+++ Source/JavaScriptCore/offlineasm/x86.rb (working copy) >@@ -150,15 +150,15 @@ class RegisterID > when "t4" > case kind > when :byte >- "%sil" >+ "%dil" > when :half >- "%si" >+ "%di" > when :int >- "%esi" >+ "%edi" > when :ptr >- isX64 ? "%rsi" : "%esi" >+ isX64 ? "%rdi" : "%edi" > when :quad >- isX64 ? "%rsi" : raise >+ isX64 ? "%rdi" : raise > else > raise > end >@@ -206,15 +206,15 @@ class RegisterID > when "t5" > case kind > when :byte >- "%dil" >+ "%sil" > when :half >- "%di" >+ "%si" > when :int >- "%edi" >+ "%esi" > when :ptr >- isX64 ? "%rdi" : "%edi" >+ isX64 ? "%rsi" : "%esi" > when :quad >- isX64 ? "%rdi" : raise >+ isX64 ? "%rsi" : raise > end > when "t6" > raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64 >Index: Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (revision 160892) >+++ Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (working copy) >@@ -29,6 +29,7 @@ > #if ENABLE(JIT) || ENABLE(LLINT) > > #include "Arguments.h" >+#include "ArityCheckFailReturnThunks.h" > #include "ArrayConstructor.h" > #include "CallFrame.h" > #include "CodeProfiling.h" >@@ -169,28 +170,42 @@ namespace JSC { > CALL_END_IMPL(crExec, crCallTarget); \ > } while (false) > >+static CommonSlowPaths::ArityCheckData* setupArityCheckData(VM& vm, int slotsToAdd) >+{ >+ CommonSlowPaths::ArityCheckData* result = vm.arityCheckData.get(); >+ result->paddedStackSpace = slotsToAdd; >+ if (vm.canUseJIT()) { >+ result->thunkToCall = vm.getCTIStub(arityFixup).code().executableAddress(); >+ result->returnPC = vm.arityCheckFailReturnThunks->returnPCFor(vm, slotsToAdd * stackAlignmentRegisters()).executableAddress(); >+ } else { >+ result->thunkToCall = 0; >+ result->returnPC = 0; >+ } >+ return result; >+} >+ > SLOW_PATH_DECL(slow_path_call_arityCheck) > { > BEGIN(); >- int SlotsToAdd = CommonSlowPaths::arityCheckFor(exec, &vm.interpreter->stack(), CodeForCall); >- if (SlotsToAdd < 0) { >+ int slotsToAdd = CommonSlowPaths::arityCheckFor(exec, &vm.interpreter->stack(), CodeForCall); >+ if (slotsToAdd < 0) { > exec = exec->callerFrame(); > CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec)); > RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec); > } >- RETURN_TWO(0, reinterpret_cast<ExecState*>(SlotsToAdd)); >+ RETURN_TWO(0, setupArityCheckData(vm, slotsToAdd)); > } > > SLOW_PATH_DECL(slow_path_construct_arityCheck) > { > BEGIN(); >- int SlotsToAdd = CommonSlowPaths::arityCheckFor(exec, &vm.interpreter->stack(), CodeForConstruct); >- if (SlotsToAdd < 0) { >+ int slotsToAdd = CommonSlowPaths::arityCheckFor(exec, &vm.interpreter->stack(), CodeForConstruct); >+ if (slotsToAdd < 0) { > exec = exec->callerFrame(); > CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec)); > RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec); > } >- RETURN_TWO(0, reinterpret_cast<ExecState*>(SlotsToAdd)); >+ RETURN_TWO(0, setupArityCheckData(vm, slotsToAdd)); > } > > SLOW_PATH_DECL(slow_path_touch_entry) >Index: Source/JavaScriptCore/runtime/CommonSlowPaths.h >=================================================================== >--- Source/JavaScriptCore/runtime/CommonSlowPaths.h (revision 160892) >+++ Source/JavaScriptCore/runtime/CommonSlowPaths.h (working copy) >@@ -49,6 +49,12 @@ namespace JSC { > > namespace CommonSlowPaths { > >+struct ArityCheckData { >+ unsigned paddedStackSpace; >+ void* thunkToCall; >+ void* returnPC; >+}; >+ > ALWAYS_INLINE int arityCheckFor(ExecState* exec, JSStack* stack, CodeSpecializationKind kind) > { > JSFunction* callee = jsCast<JSFunction*>(exec->callee()); >@@ -58,18 +64,19 @@ ALWAYS_INLINE int arityCheckFor(ExecStat > > ASSERT(argumentCountIncludingThis < newCodeBlock->numParameters()); > int missingArgumentCount = newCodeBlock->numParameters() - argumentCountIncludingThis; >- int paddedMissingArgumentCount = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), missingArgumentCount); >+ int neededStackSpace = missingArgumentCount + 1; // Allow space to save the original return PC. >+ int paddedStackSpace = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), neededStackSpace); > > #if ENABLE(LLINT_CLOOP) >- if (!stack->grow(exec->registers() - paddedMissingArgumentCount)) >+ if (!stack->grow(exec->registers() - passedStackSpace)) > return -1; > #else > UNUSED_PARAM(stack); >- if (!exec->vm().isSafeToRecurse(paddedMissingArgumentCount * sizeof(Register))) >+ if (!exec->vm().isSafeToRecurse(paddedStackSpace * sizeof(Register))) > return -1; > #endif // ENABLE(LLINT_CLOOP) > >- return paddedMissingArgumentCount; >+ return paddedStackSpace / stackAlignmentRegisters(); > } > > inline bool opIn(ExecState* exec, JSValue propName, JSValue baseVal) >Index: Source/JavaScriptCore/runtime/StackAlignment.h >=================================================================== >--- Source/JavaScriptCore/runtime/StackAlignment.h (revision 160892) >+++ Source/JavaScriptCore/runtime/StackAlignment.h (working copy) >@@ -27,6 +27,7 @@ > #define StackAlignment_h > > #include "JSCJSValue.h" >+#include <wtf/MathExtras.h> > > namespace JSC { > >@@ -38,6 +39,11 @@ inline unsigned stackAlignmentRegisters( > return stackAlignmentBytes() / sizeof(EncodedJSValue); > } > >+inline unsigned logStackAlignmentRegisters() >+{ >+ return WTF::fastLog2(stackAlignmentRegisters()); >+} >+ > } // namespace JSC > > #endif // StackAlignment_h >Index: Source/JavaScriptCore/runtime/VM.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/VM.cpp (revision 160892) >+++ Source/JavaScriptCore/runtime/VM.cpp (working copy) >@@ -30,11 +30,13 @@ > #include "VM.h" > > #include "ArgList.h" >+#include "ArityCheckFailReturnThunks.h" > #include "ArrayBufferNeuteringWatchpoint.h" > #include "CallFrameInlines.h" > #include "CodeBlock.h" > #include "CodeCache.h" > #include "CommonIdentifiers.h" >+#include "CommonSlowPaths.h" > #include "DFGLongLivedState.h" > #include "DFGWorklist.h" > #include "DebuggerActivation.h" >@@ -266,7 +268,9 @@ VM::VM(VMType vmType, HeapType heapType) > > #if ENABLE(JIT) > jitStubs = adoptPtr(new JITThunks()); >+ arityCheckFailReturnThunks = std::make_unique<ArityCheckFailReturnThunks>(); > #endif >+ arityCheckData = std::make_unique<CommonSlowPaths::ArityCheckData>(); > > #if ENABLE(FTL_JIT) > ftlThunks = std::make_unique<FTL::Thunks>(); >Index: Source/JavaScriptCore/runtime/VM.h >=================================================================== >--- Source/JavaScriptCore/runtime/VM.h (revision 160892) >+++ Source/JavaScriptCore/runtime/VM.h (working copy) >@@ -64,6 +64,7 @@ > > namespace JSC { > >+ class ArityCheckFailReturnThunks; > class CodeBlock; > class CodeCache; > class CommonIdentifiers; >@@ -104,6 +105,9 @@ namespace JSC { > class Thunks; > } > #endif // ENABLE(FTL_JIT) >+ namespace CommonSlowPaths { >+ struct ArityCheckData; >+ } > > struct HashTable; > struct Instruction; >@@ -332,7 +336,13 @@ namespace JSC { > return jitStubs->ctiStub(this, generator); > } > NativeExecutable* getHostFunction(NativeFunction, Intrinsic); >-#endif >+ >+ std::unique_ptr<ArityCheckFailReturnThunks> arityCheckFailReturnThunks; >+#if CPU(X86) >+ void* currentReturnThunkPC; >+#endif // CPU(X86) >+#endif // ENABLE(JIT) >+ std::unique_ptr<CommonSlowPaths::ArityCheckData> arityCheckData; > #if ENABLE(FTL_JIT) > std::unique_ptr<FTL::Thunks> ftlThunks; > #endif
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
ggaren
:
review+
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 126043
:
219723
|
219729
|
219739
|
219742
| 219803