1/*
2 * Copyright (C) 2013-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#pragma once
27
28#if ENABLE(FTL_JIT)
29
30#include "CCallHelpers.h"
31#include "FTLSlowPathCallKey.h"
32#include "FTLState.h"
33
34namespace JSC { namespace FTL {
35
36class SlowPathCall {
37public:
38 SlowPathCall() { }
39
40 SlowPathCall(MacroAssembler::Call call, const SlowPathCallKey& key)
41 : m_call(call)
42 , m_key(key)
43 {
44 }
45
46 MacroAssembler::Call call() const { return m_call; }
47 SlowPathCallKey key() const { return m_key; }
48
49private:
50 MacroAssembler::Call m_call;
51 SlowPathCallKey m_key;
52};
53
54// This will be an RAII thingy that will set up the necessary stack sizes and offsets and such.
55class SlowPathCallContext {
56public:
57 SlowPathCallContext(RegisterSet usedRegisters, CCallHelpers&, unsigned numArgs, GPRReg returnRegister);
58 ~SlowPathCallContext();
59
60 // NOTE: The call that this returns is already going to be linked by the JIT using addLinkTask(),
61 // so there is no need for you to link it yourself.
62 SlowPathCall makeCall(VM&, FunctionPtr<CFunctionPtrTag> callTarget);
63
64private:
65 SlowPathCallKey keyWithTarget(FunctionPtr<CFunctionPtrTag> callTarget) const;
66
67 RegisterSet m_argumentRegisters;
68 RegisterSet m_callingConventionRegisters;
69 CCallHelpers& m_jit;
70 unsigned m_numArgs;
71 GPRReg m_returnRegister;
72 size_t m_offsetToSavingArea;
73 size_t m_stackBytesNeeded;
74 RegisterSet m_thunkSaveSet;
75 ptrdiff_t m_offset;
76};
77
78template<typename... ArgumentTypes>
79SlowPathCall callOperation(
80 VM& vm, const RegisterSet& usedRegisters, CCallHelpers& jit, CCallHelpers::JumpList* exceptionTarget,
81 FunctionPtr<CFunctionPtrTag> function, GPRReg resultGPR, ArgumentTypes... arguments)
82{
83 SlowPathCall call;
84 {
85 SlowPathCallContext context(usedRegisters, jit, sizeof...(ArgumentTypes) + 1, resultGPR);
86 jit.setupArguments<void(ExecState*, ArgumentTypes...)>(arguments...);
87 call = context.makeCall(vm, function);
88 }
89 if (exceptionTarget)
90 exceptionTarget->append(jit.emitExceptionCheck(vm));
91 return call;
92}
93
94template<typename... ArgumentTypes>
95SlowPathCall callOperation(
96 VM& vm, const RegisterSet& usedRegisters, CCallHelpers& jit, CallSiteIndex callSiteIndex,
97 CCallHelpers::JumpList* exceptionTarget, FunctionPtr<CFunctionPtrTag> function, GPRReg resultGPR,
98 ArgumentTypes... arguments)
99{
100 if (callSiteIndex) {
101 jit.store32(
102 CCallHelpers::TrustedImm32(callSiteIndex.bits()),
103 CCallHelpers::tagFor(CallFrameSlot::argumentCount));
104 }
105 return callOperation(vm, usedRegisters, jit, exceptionTarget, function, resultGPR, arguments...);
106}
107
108CallSiteIndex callSiteIndexForCodeOrigin(State&, CodeOrigin);
109
110template<typename... ArgumentTypes>
111SlowPathCall callOperation(
112 State& state, const RegisterSet& usedRegisters, CCallHelpers& jit, CodeOrigin codeOrigin,
113 CCallHelpers::JumpList* exceptionTarget, FunctionPtr<CFunctionPtrTag> function, GPRReg result, ArgumentTypes... arguments)
114{
115 return callOperation(
116 state.vm(), usedRegisters, jit, callSiteIndexForCodeOrigin(state, codeOrigin), exceptionTarget, function,
117 result, arguments...);
118}
119
120} } // namespace JSC::FTL
121
122#endif // ENABLE(FTL_JIT)
123