AccessCaseSnippetParams.cpp
1 /* 2 * Copyright (C) 2016-2018 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "AccessCaseSnippetParams.h" 28 29 #include "LinkBuffer.h" 30 #include "PolymorphicAccess.h" 31 #include "StructureStubInfo.h" 32 33 #if ENABLE(JIT) 34 35 namespace JSC { 36 37 template<typename JumpType, typename FunctionType, typename ResultType, typename... Arguments> 38 class SlowPathCallGeneratorWithArguments final : public AccessCaseSnippetParams::SlowPathCallGenerator { 39 public: 40 SlowPathCallGeneratorWithArguments(JumpType from, CCallHelpers::Label to, FunctionType function, ResultType result, std::tuple<Arguments...> arguments) 41 : m_from(from) 42 , m_to(to) 43 , m_function(function) 44 , m_result(result) 45 , m_arguments(arguments) 46 { 47 } 48 49 template<size_t... ArgumentsIndex> 50 CCallHelpers::JumpList generateImpl(AccessGenerationState& state, const RegisterSet& usedRegistersBySnippet, CCallHelpers& jit, std::index_sequence<ArgumentsIndex...>) 51 { 52 CCallHelpers::JumpList exceptions; 53 // We spill (1) the used registers by IC and (2) the used registers by Snippet. 54 AccessGenerationState::SpillState spillState = state.preserveLiveRegistersToStackForCall(usedRegistersBySnippet); 55 56 jit.store32( 57 CCallHelpers::TrustedImm32(state.callSiteIndexForExceptionHandlingOrOriginal().bits()), 58 CCallHelpers::tagFor(CallFrameSlot::argumentCountIncludingThis)); 59 60 jit.makeSpaceOnStackForCCall(); 61 62 jit.setupArguments<FunctionType>(std::get<ArgumentsIndex>(m_arguments)...); 63 jit.prepareCallOperation(state.m_vm); 64 65 CCallHelpers::Call operationCall = jit.call(OperationPtrTag); 66 auto function = m_function; 67 jit.addLinkTask([=] (LinkBuffer& linkBuffer) { 68 linkBuffer.link(operationCall, FunctionPtr<OperationPtrTag>(function)); 69 }); 70 71 jit.setupResults(m_result); 72 jit.reclaimSpaceOnStackForCCall(); 73 74 CCallHelpers::Jump noException = jit.emitExceptionCheck(state.m_vm, CCallHelpers::InvertedExceptionCheck); 75 76 state.restoreLiveRegistersFromStackForCallWithThrownException(spillState); 77 exceptions.append(jit.jump()); 78 79 noException.link(&jit); 80 RegisterSet dontRestore; 81 dontRestore.set(m_result); 82 state.restoreLiveRegistersFromStackForCall(spillState, dontRestore); 83 84 return exceptions; 85 } 86 87 CCallHelpers::JumpList generate(AccessGenerationState& state, const RegisterSet& usedRegistersBySnippet, CCallHelpers& jit) final 88 { 89 m_from.link(&jit); 90 CCallHelpers::JumpList exceptions = generateImpl(state, usedRegistersBySnippet, jit, std::make_index_sequence<std::tuple_size<std::tuple<Arguments...>>::value>()); 91 jit.jump().linkTo(m_to, &jit); 92 return exceptions; 93 } 94 95 private: 96 JumpType m_from; 97 CCallHelpers::Label m_to; 98 FunctionType m_function; 99 ResultType m_result; 100 std::tuple<Arguments...> m_arguments; 101 }; 102 103 #define JSC_DEFINE_CALL_OPERATIONS(OperationType, ResultType, ...) \ 104 void AccessCaseSnippetParams::addSlowPathCallImpl(CCallHelpers::JumpList from, CCallHelpers& jit, OperationType operation, ResultType result, std::tuple<__VA_ARGS__> args) \ 105 { \ 106 CCallHelpers::Label to = jit.label(); \ 107 m_generators.append(makeUnique<SlowPathCallGeneratorWithArguments<CCallHelpers::JumpList, OperationType, ResultType, __VA_ARGS__>>(from, to, operation, result, args)); \ 108 } \ 109 110 SNIPPET_SLOW_PATH_CALLS(JSC_DEFINE_CALL_OPERATIONS) 111 #undef JSC_DEFINE_CALL_OPERATIONS 112 113 CCallHelpers::JumpList AccessCaseSnippetParams::emitSlowPathCalls(AccessGenerationState& state, const RegisterSet& usedRegistersBySnippet, CCallHelpers& jit) 114 { 115 CCallHelpers::JumpList exceptions; 116 for (auto& generator : m_generators) 117 exceptions.append(generator->generate(state, usedRegistersBySnippet, jit)); 118 return exceptions; 119 } 120 121 } 122 123 #endif