Templatize CodePtr/Refs/FunctionPtrs with PtrTags.
[WebKit-https.git] / Source / JavaScriptCore / assembler / CodeLocation.h
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
32 namespace JSC {
33
34 enum NearCallMode { Regular, Tail };
35
36 template<PtrTag> class CodeLocationInstruction;
37 template<PtrTag> class CodeLocationLabel;
38 template<PtrTag> class CodeLocationJump;
39 template<PtrTag> class CodeLocationCall;
40 template<PtrTag> class CodeLocationNearCall;
41 template<PtrTag> class CodeLocationDataLabelCompact;
42 template<PtrTag> class CodeLocationDataLabel32;
43 template<PtrTag> class CodeLocationDataLabelPtr;
44 template<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.
57 template<PtrTag tag>
58 class CodeLocationCommon : public MacroAssemblerCodePtr<tag> {
59     using Base = MacroAssemblerCodePtr<tag>;
60 public:
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 protected:
75     CodeLocationCommon()
76     {
77     }
78
79     CodeLocationCommon(MacroAssemblerCodePtr<tag> location)
80         : MacroAssemblerCodePtr<tag>(location)
81     {
82     }
83 };
84
85 template<PtrTag tag>
86 class CodeLocationInstruction : public CodeLocationCommon<tag> {
87 public:
88     CodeLocationInstruction() { }
89     explicit CodeLocationInstruction(MacroAssemblerCodePtr<tag> location)
90         : CodeLocationCommon<tag>(location) { }
91     explicit CodeLocationInstruction(void* location)
92         : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
93 };
94
95 template<PtrTag tag>
96 class CodeLocationLabel : public CodeLocationCommon<tag> {
97 public:
98     CodeLocationLabel() { }
99     explicit CodeLocationLabel(MacroAssemblerCodePtr<tag> location)
100         : CodeLocationCommon<tag>(location) { }
101     explicit CodeLocationLabel(void* location)
102         : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
103
104     template<PtrTag newTag>
105     CodeLocationLabel<newTag> retagged() { return CodeLocationLabel<newTag>(CodeLocationCommon<tag>::template retagged<newTag>()); }
106
107     template<typename T = void*>
108     T untaggedExecutableAddress() const { return CodeLocationCommon<tag>::template untaggedExecutableAddress<T>(); }
109
110     template<typename T = void*>
111     T dataLocation() const { return CodeLocationCommon<tag>::template dataLocation<T>(); }
112 };
113
114 template<PtrTag tag>
115 class CodeLocationJump : public CodeLocationCommon<tag> {
116 public:
117     CodeLocationJump() { }
118     explicit CodeLocationJump(MacroAssemblerCodePtr<tag> location)
119         : CodeLocationCommon<tag>(location) { }
120     explicit CodeLocationJump(void* location)
121         : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
122
123     template<PtrTag newTag>
124     CodeLocationJump<newTag> retagged() { return CodeLocationJump<newTag>(MacroAssemblerCodePtr<tag>::template retagged<newTag>()); }
125 };
126
127 template<PtrTag tag>
128 class CodeLocationCall : public CodeLocationCommon<tag> {
129 public:
130     CodeLocationCall() { }
131     explicit CodeLocationCall(MacroAssemblerCodePtr<tag> location)
132         : CodeLocationCommon<tag>(location) { }
133     explicit CodeLocationCall(void* location)
134         : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
135
136     template<PtrTag newTag>
137     CodeLocationCall<newTag> retagged() { return CodeLocationCall<newTag>(CodeLocationCommon<tag>::template retagged<newTag>()); }
138 };
139
140 template<PtrTag tag>
141 class CodeLocationNearCall : public CodeLocationCommon<tag> {
142 public:
143     CodeLocationNearCall() { }
144     explicit CodeLocationNearCall(MacroAssemblerCodePtr<tag> location, NearCallMode callMode)
145         : CodeLocationCommon<tag>(location), m_callMode(callMode) { }
146     explicit CodeLocationNearCall(void* location, NearCallMode callMode)
147         : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)), m_callMode(callMode) { }
148     NearCallMode callMode() { return m_callMode; }
149 private:
150     NearCallMode m_callMode = NearCallMode::Regular;
151 };
152
153 template<PtrTag tag>
154 class CodeLocationDataLabel32 : public CodeLocationCommon<tag> {
155 public:
156     CodeLocationDataLabel32() { }
157     explicit CodeLocationDataLabel32(MacroAssemblerCodePtr<tag> location)
158         : CodeLocationCommon<tag>(location) { }
159     explicit CodeLocationDataLabel32(void* location)
160         : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
161 };
162
163 template<PtrTag tag>
164 class CodeLocationDataLabelCompact : public CodeLocationCommon<tag> {
165 public:
166     CodeLocationDataLabelCompact() { }
167     explicit CodeLocationDataLabelCompact(MacroAssemblerCodePtr<tag> location)
168         : CodeLocationCommon<tag>(location) { }
169     explicit CodeLocationDataLabelCompact(void* location)
170         : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
171 };
172
173 template<PtrTag tag>
174 class CodeLocationDataLabelPtr : public CodeLocationCommon<tag> {
175 public:
176     CodeLocationDataLabelPtr() { }
177     explicit CodeLocationDataLabelPtr(MacroAssemblerCodePtr<tag> location)
178         : CodeLocationCommon<tag>(location) { }
179     explicit CodeLocationDataLabelPtr(void* location)
180         : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
181 };
182
183 template<PtrTag tag>
184 class CodeLocationConvertibleLoad : public CodeLocationCommon<tag> {
185 public:
186     CodeLocationConvertibleLoad() { }
187     explicit CodeLocationConvertibleLoad(MacroAssemblerCodePtr<tag> location)
188         : CodeLocationCommon<tag>(location) { }
189     explicit CodeLocationConvertibleLoad(void* location)
190         : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
191 };
192
193 template<PtrTag tag>
194 template<PtrTag resultTag>
195 inline CodeLocationInstruction<resultTag> CodeLocationCommon<tag>::instructionAtOffset(int offset)
196 {
197     ASSERT_VALID_CODE_OFFSET(offset);
198     return CodeLocationInstruction<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
199 }
200
201 template<PtrTag tag>
202 template<PtrTag resultTag>
203 inline CodeLocationLabel<resultTag> CodeLocationCommon<tag>::labelAtOffset(int offset)
204 {
205     ASSERT_VALID_CODE_OFFSET(offset);
206     return CodeLocationLabel<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
207 }
208
209 template<PtrTag tag>
210 template<PtrTag resultTag>
211 inline CodeLocationJump<resultTag> CodeLocationCommon<tag>::jumpAtOffset(int offset)
212 {
213     ASSERT_VALID_CODE_OFFSET(offset);
214     return CodeLocationJump<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
215 }
216
217 template<PtrTag tag>
218 template<PtrTag resultTag>
219 inline CodeLocationCall<resultTag> CodeLocationCommon<tag>::callAtOffset(int offset)
220 {
221     ASSERT_VALID_CODE_OFFSET(offset);
222     return CodeLocationCall<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
223 }
224
225 template<PtrTag tag>
226 template<PtrTag resultTag>
227 inline CodeLocationNearCall<resultTag> CodeLocationCommon<tag>::nearCallAtOffset(int offset, NearCallMode callMode)
228 {
229     ASSERT_VALID_CODE_OFFSET(offset);
230     return CodeLocationNearCall<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset), callMode);
231 }
232
233 template<PtrTag tag>
234 template<PtrTag resultTag>
235 inline CodeLocationDataLabelPtr<resultTag> CodeLocationCommon<tag>::dataLabelPtrAtOffset(int offset)
236 {
237     ASSERT_VALID_CODE_OFFSET(offset);
238     return CodeLocationDataLabelPtr<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
239 }
240
241 template<PtrTag tag>
242 template<PtrTag resultTag>
243 inline CodeLocationDataLabel32<resultTag> CodeLocationCommon<tag>::dataLabel32AtOffset(int offset)
244 {
245     ASSERT_VALID_CODE_OFFSET(offset);
246     return CodeLocationDataLabel32<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
247 }
248
249 template<PtrTag tag>
250 template<PtrTag resultTag>
251 inline CodeLocationDataLabelCompact<resultTag> CodeLocationCommon<tag>::dataLabelCompactAtOffset(int offset)
252 {
253     ASSERT_VALID_CODE_OFFSET(offset);
254     return CodeLocationDataLabelCompact<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
255 }
256
257 template<PtrTag tag>
258 template<PtrTag resultTag>
259 inline CodeLocationConvertibleLoad<resultTag> CodeLocationCommon<tag>::convertibleLoadAtOffset(int offset)
260 {
261     ASSERT_VALID_CODE_OFFSET(offset);
262     return CodeLocationConvertibleLoad<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
263 }
264
265 } // namespace JSC
266
267 #endif // ENABLE(ASSEMBLER)