1/*
2 * Copyright (C) 2009-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#include "MacroAssemblerCodeRef.h"
29
30#if ENABLE(ASSEMBLER)
31
32namespace JSC {
33
34enum class NearCallMode : uint8_t { Regular, Tail };
35
36template<PtrTag> class CodeLocationInstruction;
37template<PtrTag> class CodeLocationLabel;
38template<PtrTag> class CodeLocationJump;
39template<PtrTag> class CodeLocationCall;
40template<PtrTag> class CodeLocationNearCall;
41template<PtrTag> class CodeLocationDataLabelCompact;
42template<PtrTag> class CodeLocationDataLabel32;
43template<PtrTag> class CodeLocationDataLabelPtr;
44template<PtrTag> class CodeLocationConvertibleLoad;
45
46// The CodeLocation* types are all pretty much do-nothing wrappers around
47// CodePtr (or MacroAssemblerCodePtr, to give it its full name). These
48// classes only exist to provide type-safety when linking and patching code.
49//
50// The one new piece of functionallity introduced by these classes is the
51// ability to create (or put another way, to re-discover) another CodeLocation
52// at an offset from one you already know. When patching code to optimize it
53// we often want to patch a number of instructions that are short, fixed
54// offsets apart. To reduce memory overhead we will only retain a pointer to
55// one of the instructions, and we will use the *AtOffset methods provided by
56// CodeLocationCommon to find the other points in the code to modify.
57template<PtrTag tag>
58class CodeLocationCommon : public MacroAssemblerCodePtr<tag> {
59 using Base = MacroAssemblerCodePtr<tag>;
60public:
61 template<PtrTag resultTag = tag> CodeLocationInstruction<resultTag> instructionAtOffset(int offset);
62 template<PtrTag resultTag = tag> CodeLocationLabel<resultTag> labelAtOffset(int offset);
63 template<PtrTag resultTag = tag> CodeLocationJump<resultTag> jumpAtOffset(int offset);
64 template<PtrTag resultTag = tag> CodeLocationCall<resultTag> callAtOffset(int offset);
65 template<PtrTag resultTag = tag> CodeLocationNearCall<resultTag> nearCallAtOffset(int offset, NearCallMode);
66 template<PtrTag resultTag = tag> CodeLocationDataLabelPtr<resultTag> dataLabelPtrAtOffset(int offset);
67 template<PtrTag resultTag = tag> CodeLocationDataLabel32<resultTag> dataLabel32AtOffset(int offset);
68 template<PtrTag resultTag = tag> CodeLocationDataLabelCompact<resultTag> dataLabelCompactAtOffset(int offset);
69 template<PtrTag resultTag = tag> CodeLocationConvertibleLoad<resultTag> convertibleLoadAtOffset(int offset);
70
71 template<typename T = void*>
72 T dataLocation() const { return Base::template dataLocation<T>(); }
73
74 template<typename T, typename = std::enable_if_t<std::is_base_of<CodeLocationCommon<tag>, T>::value>>
75 operator T()
76 {
77 return T(MacroAssemblerCodePtr<tag>::createFromExecutableAddress(this->executableAddress()));
78 }
79
80protected:
81 CodeLocationCommon()
82 {
83 }
84
85 CodeLocationCommon(MacroAssemblerCodePtr<tag> location)
86 : MacroAssemblerCodePtr<tag>(location)
87 {
88 }
89};
90
91template<PtrTag tag>
92class CodeLocationInstruction : public CodeLocationCommon<tag> {
93public:
94 CodeLocationInstruction() { }
95 explicit CodeLocationInstruction(MacroAssemblerCodePtr<tag> location)
96 : CodeLocationCommon<tag>(location) { }
97 explicit CodeLocationInstruction(void* location)
98 : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
99};
100
101template<PtrTag tag>
102class CodeLocationLabel : public CodeLocationCommon<tag> {
103public:
104 CodeLocationLabel() { }
105 explicit CodeLocationLabel(MacroAssemblerCodePtr<tag> location)
106 : CodeLocationCommon<tag>(location) { }
107 explicit CodeLocationLabel(void* location)
108 : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
109
110 template<PtrTag newTag>
111 CodeLocationLabel<newTag> retagged() { return CodeLocationLabel<newTag>(CodeLocationCommon<tag>::template retagged<newTag>()); }
112
113 template<typename T = void*>
114 T untaggedExecutableAddress() const { return CodeLocationCommon<tag>::template untaggedExecutableAddress<T>(); }
115
116 template<typename T = void*>
117 T dataLocation() const { return CodeLocationCommon<tag>::template dataLocation<T>(); }
118};
119
120template<PtrTag tag>
121class CodeLocationJump : public CodeLocationCommon<tag> {
122public:
123 CodeLocationJump() { }
124 explicit CodeLocationJump(MacroAssemblerCodePtr<tag> location)
125 : CodeLocationCommon<tag>(location) { }
126 explicit CodeLocationJump(void* location)
127 : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
128
129 template<PtrTag newTag>
130 CodeLocationJump<newTag> retagged() { return CodeLocationJump<newTag>(MacroAssemblerCodePtr<tag>::template retagged<newTag>()); }
131};
132
133template<PtrTag tag>
134class CodeLocationCall : public CodeLocationCommon<tag> {
135public:
136 CodeLocationCall() { }
137 explicit CodeLocationCall(MacroAssemblerCodePtr<tag> location)
138 : CodeLocationCommon<tag>(location) { }
139 explicit CodeLocationCall(void* location)
140 : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
141
142 template<PtrTag newTag>
143 CodeLocationCall<newTag> retagged() { return CodeLocationCall<newTag>(CodeLocationCommon<tag>::template retagged<newTag>()); }
144};
145
146template<PtrTag tag>
147class CodeLocationNearCall : public CodeLocationCommon<tag> {
148public:
149 CodeLocationNearCall() { }
150 explicit CodeLocationNearCall(MacroAssemblerCodePtr<tag> location, NearCallMode callMode)
151 : CodeLocationCommon<tag>(location), m_callMode(callMode) { }
152 explicit CodeLocationNearCall(void* location, NearCallMode callMode)
153 : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)), m_callMode(callMode) { }
154 NearCallMode callMode() { return m_callMode; }
155private:
156 NearCallMode m_callMode { NearCallMode::Regular };
157};
158
159template<PtrTag tag>
160class CodeLocationDataLabel32 : public CodeLocationCommon<tag> {
161public:
162 CodeLocationDataLabel32() { }
163 explicit CodeLocationDataLabel32(MacroAssemblerCodePtr<tag> location)
164 : CodeLocationCommon<tag>(location) { }
165 explicit CodeLocationDataLabel32(void* location)
166 : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
167};
168
169template<PtrTag tag>
170class CodeLocationDataLabelCompact : public CodeLocationCommon<tag> {
171public:
172 CodeLocationDataLabelCompact() { }
173 explicit CodeLocationDataLabelCompact(MacroAssemblerCodePtr<tag> location)
174 : CodeLocationCommon<tag>(location) { }
175 explicit CodeLocationDataLabelCompact(void* location)
176 : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
177};
178
179template<PtrTag tag>
180class CodeLocationDataLabelPtr : public CodeLocationCommon<tag> {
181public:
182 CodeLocationDataLabelPtr() { }
183 explicit CodeLocationDataLabelPtr(MacroAssemblerCodePtr<tag> location)
184 : CodeLocationCommon<tag>(location) { }
185 explicit CodeLocationDataLabelPtr(void* location)
186 : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
187};
188
189template<PtrTag tag>
190class CodeLocationConvertibleLoad : public CodeLocationCommon<tag> {
191public:
192 CodeLocationConvertibleLoad() { }
193 explicit CodeLocationConvertibleLoad(MacroAssemblerCodePtr<tag> location)
194 : CodeLocationCommon<tag>(location) { }
195 explicit CodeLocationConvertibleLoad(void* location)
196 : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
197};
198
199template<PtrTag tag>
200template<PtrTag resultTag>
201inline CodeLocationInstruction<resultTag> CodeLocationCommon<tag>::instructionAtOffset(int offset)
202{
203 ASSERT_VALID_CODE_OFFSET(offset);
204 return CodeLocationInstruction<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
205}
206
207template<PtrTag tag>
208template<PtrTag resultTag>
209inline CodeLocationLabel<resultTag> CodeLocationCommon<tag>::labelAtOffset(int offset)
210{
211 ASSERT_VALID_CODE_OFFSET(offset);
212 return CodeLocationLabel<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
213}
214
215template<PtrTag tag>
216template<PtrTag resultTag>
217inline CodeLocationJump<resultTag> CodeLocationCommon<tag>::jumpAtOffset(int offset)
218{
219 ASSERT_VALID_CODE_OFFSET(offset);
220 return CodeLocationJump<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
221}
222
223template<PtrTag tag>
224template<PtrTag resultTag>
225inline CodeLocationCall<resultTag> CodeLocationCommon<tag>::callAtOffset(int offset)
226{
227 ASSERT_VALID_CODE_OFFSET(offset);
228 return CodeLocationCall<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
229}
230
231template<PtrTag tag>
232template<PtrTag resultTag>
233inline CodeLocationNearCall<resultTag> CodeLocationCommon<tag>::nearCallAtOffset(int offset, NearCallMode callMode)
234{
235 ASSERT_VALID_CODE_OFFSET(offset);
236 return CodeLocationNearCall<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset), callMode);
237}
238
239template<PtrTag tag>
240template<PtrTag resultTag>
241inline CodeLocationDataLabelPtr<resultTag> CodeLocationCommon<tag>::dataLabelPtrAtOffset(int offset)
242{
243 ASSERT_VALID_CODE_OFFSET(offset);
244 return CodeLocationDataLabelPtr<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
245}
246
247template<PtrTag tag>
248template<PtrTag resultTag>
249inline CodeLocationDataLabel32<resultTag> CodeLocationCommon<tag>::dataLabel32AtOffset(int offset)
250{
251 ASSERT_VALID_CODE_OFFSET(offset);
252 return CodeLocationDataLabel32<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
253}
254
255template<PtrTag tag>
256template<PtrTag resultTag>
257inline CodeLocationDataLabelCompact<resultTag> CodeLocationCommon<tag>::dataLabelCompactAtOffset(int offset)
258{
259 ASSERT_VALID_CODE_OFFSET(offset);
260 return CodeLocationDataLabelCompact<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
261}
262
263template<PtrTag tag>
264template<PtrTag resultTag>
265inline CodeLocationConvertibleLoad<resultTag> CodeLocationCommon<tag>::convertibleLoadAtOffset(int offset)
266{
267 ASSERT_VALID_CODE_OFFSET(offset);
268 return CodeLocationConvertibleLoad<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
269}
270
271} // namespace JSC
272
273#endif // ENABLE(ASSEMBLER)
274