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 class NearCallMode : uint8_t { 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 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 80 protected: 81 CodeLocationCommon() 82 { 83 } 84 85 CodeLocationCommon(MacroAssemblerCodePtr<tag> location) 86 : MacroAssemblerCodePtr<tag>(location) 87 { 88 } 89 }; 90 91 template<PtrTag tag> 92 class CodeLocationInstruction : public CodeLocationCommon<tag> { 93 public: 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 101 template<PtrTag tag> 102 class CodeLocationLabel : public CodeLocationCommon<tag> { 103 public: 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 120 template<PtrTag tag> 121 class CodeLocationJump : public CodeLocationCommon<tag> { 122 public: 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 133 template<PtrTag tag> 134 class CodeLocationCall : public CodeLocationCommon<tag> { 135 public: 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 146 template<PtrTag tag> 147 class CodeLocationNearCall : public CodeLocationCommon<tag> { 148 public: 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; } 155 private: 156 NearCallMode m_callMode { NearCallMode::Regular }; 157 }; 158 159 template<PtrTag tag> 160 class CodeLocationDataLabel32 : public CodeLocationCommon<tag> { 161 public: 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 169 template<PtrTag tag> 170 class CodeLocationDataLabelCompact : public CodeLocationCommon<tag> { 171 public: 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 179 template<PtrTag tag> 180 class CodeLocationDataLabelPtr : public CodeLocationCommon<tag> { 181 public: 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 189 template<PtrTag tag> 190 class CodeLocationConvertibleLoad : public CodeLocationCommon<tag> { 191 public: 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 199 template<PtrTag tag> 200 template<PtrTag resultTag> 201 inline 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 207 template<PtrTag tag> 208 template<PtrTag resultTag> 209 inline 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 215 template<PtrTag tag> 216 template<PtrTag resultTag> 217 inline 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 223 template<PtrTag tag> 224 template<PtrTag resultTag> 225 inline 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 231 template<PtrTag tag> 232 template<PtrTag resultTag> 233 inline 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 239 template<PtrTag tag> 240 template<PtrTag resultTag> 241 inline 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 247 template<PtrTag tag> 248 template<PtrTag resultTag> 249 inline 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 255 template<PtrTag tag> 256 template<PtrTag resultTag> 257 inline 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 263 template<PtrTag tag> 264 template<PtrTag resultTag> 265 inline 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)