[EME] Add basic implementation of HTMLMediaElement::setMediaKeys()
[WebKit-https.git] / Source / JavaScriptCore / assembler / ProbeContext.h
1 /*
2  * Copyright (C) 2017 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 #include "MacroAssembler.h"
29 #include "ProbeStack.h"
30
31 namespace JSC {
32 namespace Probe {
33
34 struct CPUState {
35     using RegisterID = MacroAssembler::RegisterID;
36     using SPRegisterID = MacroAssembler::SPRegisterID;
37     using FPRegisterID = MacroAssembler::FPRegisterID;
38
39     static inline const char* gprName(RegisterID id) { return MacroAssembler::gprName(id); }
40     static inline const char* sprName(SPRegisterID id) { return MacroAssembler::sprName(id); }
41     static inline const char* fprName(FPRegisterID id) { return MacroAssembler::fprName(id); }
42     inline uintptr_t& gpr(RegisterID);
43     inline uintptr_t& spr(SPRegisterID);
44     inline double& fpr(FPRegisterID);
45
46     template<typename T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
47     T gpr(RegisterID) const;
48     template<typename T, typename std::enable_if<std::is_pointer<T>::value>::type* = nullptr>
49     T gpr(RegisterID) const;
50     template<typename T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
51     T spr(SPRegisterID) const;
52     template<typename T, typename std::enable_if<std::is_pointer<T>::value>::type* = nullptr>
53     T spr(SPRegisterID) const;
54     template<typename T> T fpr(FPRegisterID) const;
55
56     void*& pc();
57     void*& fp();
58     void*& sp();
59     template<typename T> T pc() const;
60     template<typename T> T fp() const;
61     template<typename T> T sp() const;
62
63     uintptr_t gprs[MacroAssembler::numberOfRegisters()];
64     uintptr_t sprs[MacroAssembler::numberOfSPRegisters()];
65     double fprs[MacroAssembler::numberOfFPRegisters()];
66 };
67
68 inline uintptr_t& CPUState::gpr(RegisterID id)
69 {
70     ASSERT(id >= MacroAssembler::firstRegister() && id <= MacroAssembler::lastRegister());
71     return gprs[id];
72 }
73
74 inline uintptr_t& CPUState::spr(SPRegisterID id)
75 {
76     ASSERT(id >= MacroAssembler::firstSPRegister() && id <= MacroAssembler::lastSPRegister());
77     return sprs[id];
78 }
79
80 inline double& CPUState::fpr(FPRegisterID id)
81 {
82     ASSERT(id >= MacroAssembler::firstFPRegister() && id <= MacroAssembler::lastFPRegister());
83     return fprs[id];
84 }
85
86 template<typename T, typename std::enable_if<std::is_integral<T>::value>::type*>
87 T CPUState::gpr(RegisterID id) const
88 {
89     CPUState* cpu = const_cast<CPUState*>(this);
90     return static_cast<T>(cpu->gpr(id));
91 }
92
93 template<typename T, typename std::enable_if<std::is_pointer<T>::value>::type*>
94 T CPUState::gpr(RegisterID id) const
95 {
96     CPUState* cpu = const_cast<CPUState*>(this);
97     return reinterpret_cast<T>(cpu->gpr(id));
98 }
99
100 template<typename T, typename std::enable_if<std::is_integral<T>::value>::type*>
101 T CPUState::spr(SPRegisterID id) const
102 {
103     CPUState* cpu = const_cast<CPUState*>(this);
104     return static_cast<T>(cpu->spr(id));
105 }
106
107 template<typename T, typename std::enable_if<std::is_pointer<T>::value>::type*>
108 T CPUState::spr(SPRegisterID id) const
109 {
110     CPUState* cpu = const_cast<CPUState*>(this);
111     return reinterpret_cast<T>(cpu->spr(id));
112 }
113
114 template<typename T>
115 T CPUState::fpr(FPRegisterID id) const
116 {
117     CPUState* cpu = const_cast<CPUState*>(this);
118     return bitwise_cast<T>(cpu->fpr(id));
119 }
120
121 inline void*& CPUState::pc()
122 {
123 #if CPU(X86) || CPU(X86_64)
124     return *reinterpret_cast<void**>(&spr(X86Registers::eip));
125 #elif CPU(ARM64)
126     return *reinterpret_cast<void**>(&spr(ARM64Registers::pc));
127 #elif CPU(ARM_THUMB2) || CPU(ARM_TRADITIONAL)
128     return *reinterpret_cast<void**>(&gpr(ARMRegisters::pc));
129 #elif CPU(MIPS)
130     RELEASE_ASSERT_NOT_REACHED();
131 #else
132 #error "Unsupported CPU"
133 #endif
134 }
135
136 inline void*& CPUState::fp()
137 {
138 #if CPU(X86) || CPU(X86_64)
139     return *reinterpret_cast<void**>(&gpr(X86Registers::ebp));
140 #elif CPU(ARM64)
141     return *reinterpret_cast<void**>(&gpr(ARM64Registers::fp));
142 #elif CPU(ARM_THUMB2) || CPU(ARM_TRADITIONAL)
143     return *reinterpret_cast<void**>(&gpr(ARMRegisters::fp));
144 #elif CPU(MIPS)
145     return *reinterpret_cast<void**>(&gpr(MIPSRegisters::fp));
146 #else
147 #error "Unsupported CPU"
148 #endif
149 }
150
151 inline void*& CPUState::sp()
152 {
153 #if CPU(X86) || CPU(X86_64)
154     return *reinterpret_cast<void**>(&gpr(X86Registers::esp));
155 #elif CPU(ARM64)
156     return *reinterpret_cast<void**>(&gpr(ARM64Registers::sp));
157 #elif CPU(ARM_THUMB2) || CPU(ARM_TRADITIONAL)
158     return *reinterpret_cast<void**>(&gpr(ARMRegisters::sp));
159 #elif CPU(MIPS)
160     return *reinterpret_cast<void**>(&gpr(MIPSRegisters::sp));
161 #else
162 #error "Unsupported CPU"
163 #endif
164 }
165
166 template<typename T>
167 T CPUState::pc() const
168 {
169     CPUState* cpu = const_cast<CPUState*>(this);
170     return reinterpret_cast<T>(cpu->pc());
171 }
172
173 template<typename T>
174 T CPUState::fp() const
175 {
176     CPUState* cpu = const_cast<CPUState*>(this);
177     return reinterpret_cast<T>(cpu->fp());
178 }
179
180 template<typename T>
181 T CPUState::sp() const
182 {
183     CPUState* cpu = const_cast<CPUState*>(this);
184     return reinterpret_cast<T>(cpu->sp());
185 }
186
187 struct State;
188 typedef void (*StackInitializationFunction)(State*);
189
190 struct State {
191     Probe::Function probeFunction;
192     void* arg;
193     StackInitializationFunction initializeStackFunction;
194     void* initializeStackArg;
195     CPUState cpu;
196 };
197
198 class Context {
199     WTF_MAKE_FAST_ALLOCATED;
200 public:
201     using RegisterID = MacroAssembler::RegisterID;
202     using SPRegisterID = MacroAssembler::SPRegisterID;
203     using FPRegisterID = MacroAssembler::FPRegisterID;
204
205     Context(State* state)
206         : m_state(state)
207         , arg(state->arg)
208         , cpu(state->cpu)
209     { }
210
211     uintptr_t& gpr(RegisterID id) { return m_state->cpu.gpr(id); }
212     uintptr_t& spr(SPRegisterID id) { return m_state->cpu.spr(id); }
213     double& fpr(FPRegisterID id) { return m_state->cpu.fpr(id); }
214     const char* gprName(RegisterID id) { return m_state->cpu.gprName(id); }
215     const char* sprName(SPRegisterID id) { return m_state->cpu.sprName(id); }
216     const char* fprName(FPRegisterID id) { return m_state->cpu.fprName(id); }
217
218     void*& pc() { return m_state->cpu.pc(); }
219     void*& fp() { return m_state->cpu.fp(); }
220     void*& sp() { return m_state->cpu.sp(); }
221
222     template<typename T> T pc() { return m_state->cpu.pc<T>(); }
223     template<typename T> T fp() { return m_state->cpu.fp<T>(); }
224     template<typename T> T sp() { return m_state->cpu.sp<T>(); }
225
226     Stack& stack()
227     {
228         ASSERT(m_stack.isValid());
229         return m_stack;
230     };
231
232     bool hasWritesToFlush() { return m_stack.hasWritesToFlush(); }
233     Stack* releaseStack() { return new Stack(WTFMove(m_stack)); }
234
235 private:
236     State* m_state;
237 public:
238     void* arg;
239     CPUState& cpu;
240
241 private:
242     Stack m_stack;
243
244     friend JS_EXPORT_PRIVATE void* probeStateForContext(Context&); // Not for general use. This should only be for writing tests.
245 };
246
247 void executeProbe(State*);
248
249 } // namespace Probe
250
251 } // namespace JSC