barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 1 | /* |
fpizlo@apple.com | 28c7100 | 2016-01-15 19:41:56 +0000 | [diff] [blame] | 2 | * Copyright (C) 2008, 2012, 2014-2016 Apple Inc. All rights reserved. |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 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 | #ifndef AbstractMacroAssembler_h |
| 27 | #define AbstractMacroAssembler_h |
| 28 | |
fpizlo@apple.com | fac5bed | 2014-05-14 03:57:18 +0000 | [diff] [blame] | 29 | #include "AbortReason.h" |
barraclough@apple.com | f280e17 | 2012-03-28 22:18:20 +0000 | [diff] [blame] | 30 | #include "AssemblerBuffer.h" |
ddkilzer@apple.com | 6dc6a37 | 2010-11-09 23:36:19 +0000 | [diff] [blame] | 31 | #include "CodeLocation.h" |
| 32 | #include "MacroAssemblerCodeRef.h" |
fpizlo@apple.com | 5120492 | 2013-12-11 06:50:19 +0000 | [diff] [blame] | 33 | #include "Options.h" |
oliver@apple.com | d5c4868 | 2012-03-06 02:40:05 +0000 | [diff] [blame] | 34 | #include <wtf/CryptographicallyRandomNumber.h> |
barraclough@apple.com | 04b762d | 2009-05-22 02:34:41 +0000 | [diff] [blame] | 35 | #include <wtf/Noncopyable.h> |
fpizlo@apple.com | 6e69796 | 2015-10-12 17:56:26 +0000 | [diff] [blame] | 36 | #include <wtf/SharedTask.h> |
fpizlo@apple.com | 5f86606 | 2015-09-26 18:07:09 +0000 | [diff] [blame] | 37 | #include <wtf/WeakRandom.h> |
barraclough@apple.com | 04b762d | 2009-05-22 02:34:41 +0000 | [diff] [blame] | 38 | |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 39 | #if ENABLE(ASSEMBLER) |
| 40 | |
| 41 | namespace JSC { |
| 42 | |
ossy@webkit.org | d3a3de9 | 2015-03-16 18:44:46 +0000 | [diff] [blame] | 43 | inline bool isARMv7IDIVSupported() |
rniwa@webkit.org | 3b9e15c | 2013-04-30 20:18:46 +0000 | [diff] [blame] | 44 | { |
ossy@webkit.org | d3a3de9 | 2015-03-16 18:44:46 +0000 | [diff] [blame] | 45 | #if HAVE(ARM_IDIV_INSTRUCTIONS) |
rniwa@webkit.org | 3b9e15c | 2013-04-30 20:18:46 +0000 | [diff] [blame] | 46 | return true; |
| 47 | #else |
| 48 | return false; |
| 49 | #endif |
| 50 | } |
| 51 | |
dbates@webkit.org | 98f0de0 | 2013-10-15 22:16:39 +0000 | [diff] [blame] | 52 | inline bool isARM64() |
| 53 | { |
| 54 | #if CPU(ARM64) |
| 55 | return true; |
| 56 | #else |
| 57 | return false; |
| 58 | #endif |
| 59 | } |
| 60 | |
fpizlo@apple.com | b42fcb1 | 2013-04-25 01:26:35 +0000 | [diff] [blame] | 61 | inline bool isX86() |
| 62 | { |
| 63 | #if CPU(X86_64) || CPU(X86) |
| 64 | return true; |
| 65 | #else |
| 66 | return false; |
| 67 | #endif |
| 68 | } |
| 69 | |
fpizlo@apple.com | a68bc3a | 2015-12-21 16:16:01 +0000 | [diff] [blame] | 70 | inline bool isX86_64() |
| 71 | { |
| 72 | #if CPU(X86_64) |
| 73 | return true; |
| 74 | #else |
| 75 | return false; |
| 76 | #endif |
| 77 | } |
| 78 | |
ossy@webkit.org | d3a3de9 | 2015-03-16 18:44:46 +0000 | [diff] [blame] | 79 | inline bool optimizeForARMv7IDIVSupported() |
fpizlo@apple.com | 5120492 | 2013-12-11 06:50:19 +0000 | [diff] [blame] | 80 | { |
mark.lam@apple.com | ee3c410 | 2015-10-14 18:57:07 +0000 | [diff] [blame] | 81 | return isARMv7IDIVSupported() && Options::useArchitectureSpecificOptimizations(); |
fpizlo@apple.com | 5120492 | 2013-12-11 06:50:19 +0000 | [diff] [blame] | 82 | } |
| 83 | |
| 84 | inline bool optimizeForARM64() |
| 85 | { |
mark.lam@apple.com | ee3c410 | 2015-10-14 18:57:07 +0000 | [diff] [blame] | 86 | return isARM64() && Options::useArchitectureSpecificOptimizations(); |
fpizlo@apple.com | 5120492 | 2013-12-11 06:50:19 +0000 | [diff] [blame] | 87 | } |
| 88 | |
| 89 | inline bool optimizeForX86() |
| 90 | { |
mark.lam@apple.com | ee3c410 | 2015-10-14 18:57:07 +0000 | [diff] [blame] | 91 | return isX86() && Options::useArchitectureSpecificOptimizations(); |
fpizlo@apple.com | 5120492 | 2013-12-11 06:50:19 +0000 | [diff] [blame] | 92 | } |
| 93 | |
fpizlo@apple.com | a68bc3a | 2015-12-21 16:16:01 +0000 | [diff] [blame] | 94 | inline bool optimizeForX86_64() |
| 95 | { |
| 96 | return isX86_64() && Options::useArchitectureSpecificOptimizations(); |
| 97 | } |
| 98 | |
fpizlo@apple.com | d9a4e74 | 2015-11-30 20:07:18 +0000 | [diff] [blame] | 99 | class AllowMacroScratchRegisterUsage; |
| 100 | class DisallowMacroScratchRegisterUsage; |
barraclough@apple.com | ba92ede | 2009-07-22 00:37:03 +0000 | [diff] [blame] | 101 | class LinkBuffer; |
fpizlo@apple.com | b75911b | 2012-06-13 20:53:52 +0000 | [diff] [blame] | 102 | class Watchpoint; |
fpizlo@apple.com | 4621171 | 2011-11-10 01:08:50 +0000 | [diff] [blame] | 103 | namespace DFG { |
msaboff@apple.com | 064257d | 2012-12-18 03:51:07 +0000 | [diff] [blame] | 104 | struct OSRExit; |
fpizlo@apple.com | 4621171 | 2011-11-10 01:08:50 +0000 | [diff] [blame] | 105 | } |
barraclough@apple.com | ba92ede | 2009-07-22 00:37:03 +0000 | [diff] [blame] | 106 | |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 107 | template <class AssemblerType, class MacroAssemblerType> |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 108 | class AbstractMacroAssembler { |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 109 | public: |
oliver@apple.com | 6695274 | 2011-06-23 22:47:04 +0000 | [diff] [blame] | 110 | friend class JITWriteBarrierBase; |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 111 | typedef AbstractMacroAssembler<AssemblerType, MacroAssemblerType> AbstractMacroAssemblerType; |
barraclough@apple.com | ba92ede | 2009-07-22 00:37:03 +0000 | [diff] [blame] | 112 | typedef AssemblerType AssemblerType_T; |
| 113 | |
barraclough@apple.com | 97bacef | 2009-06-05 07:55:38 +0000 | [diff] [blame] | 114 | typedef MacroAssemblerCodePtr CodePtr; |
barraclough@apple.com | 04b762d | 2009-05-22 02:34:41 +0000 | [diff] [blame] | 115 | typedef MacroAssemblerCodeRef CodeRef; |
| 116 | |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 117 | class Jump; |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 118 | |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 119 | typedef typename AssemblerType::RegisterID RegisterID; |
fpizlo@apple.com | 50cd41c | 2013-10-10 22:57:10 +0000 | [diff] [blame] | 120 | typedef typename AssemblerType::FPRegisterID FPRegisterID; |
fpizlo@apple.com | ea92c20 | 2013-10-10 04:24:57 +0000 | [diff] [blame] | 121 | |
basile_clement@apple.com | 38ddaa7 | 2015-09-04 18:00:24 +0000 | [diff] [blame] | 122 | static constexpr RegisterID firstRegister() { return AssemblerType::firstRegister(); } |
| 123 | static constexpr RegisterID lastRegister() { return AssemblerType::lastRegister(); } |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 124 | |
basile_clement@apple.com | 38ddaa7 | 2015-09-04 18:00:24 +0000 | [diff] [blame] | 125 | static constexpr FPRegisterID firstFPRegister() { return AssemblerType::firstFPRegister(); } |
| 126 | static constexpr FPRegisterID lastFPRegister() { return AssemblerType::lastFPRegister(); } |
fpizlo@apple.com | 50cd41c | 2013-10-10 22:57:10 +0000 | [diff] [blame] | 127 | |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 128 | // Section 1: MacroAssembler operand types |
| 129 | // |
| 130 | // The following types are used as operands to MacroAssembler operations, |
| 131 | // describing immediate and memory operands to the instructions to be planted. |
| 132 | |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 133 | enum Scale { |
| 134 | TimesOne, |
| 135 | TimesTwo, |
| 136 | TimesFour, |
| 137 | TimesEight, |
| 138 | }; |
oliver@apple.com | 9b7647b | 2013-07-25 04:03:00 +0000 | [diff] [blame] | 139 | |
| 140 | static Scale timesPtr() |
| 141 | { |
| 142 | if (sizeof(void*) == 4) |
| 143 | return TimesFour; |
| 144 | return TimesEight; |
| 145 | } |
fpizlo@apple.com | f41fc90 | 2016-04-23 02:00:38 +0000 | [diff] [blame] | 146 | |
| 147 | struct BaseIndex; |
| 148 | |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 149 | // Address: |
| 150 | // |
| 151 | // Describes a simple base-offset address. |
| 152 | struct Address { |
| 153 | explicit Address(RegisterID base, int32_t offset = 0) |
| 154 | : base(base) |
| 155 | , offset(offset) |
| 156 | { |
| 157 | } |
oliver@apple.com | ea77149 | 2013-07-25 03:58:38 +0000 | [diff] [blame] | 158 | |
| 159 | Address withOffset(int32_t additionalOffset) |
| 160 | { |
| 161 | return Address(base, offset + additionalOffset); |
| 162 | } |
msaboff@apple.com | 9589433 | 2014-01-29 19:18:54 +0000 | [diff] [blame] | 163 | |
fpizlo@apple.com | f41fc90 | 2016-04-23 02:00:38 +0000 | [diff] [blame] | 164 | BaseIndex indexedBy(RegisterID index, Scale) const; |
| 165 | |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 166 | RegisterID base; |
| 167 | int32_t offset; |
| 168 | }; |
| 169 | |
oliver@apple.com | 4ec290d | 2010-04-20 22:05:43 +0000 | [diff] [blame] | 170 | struct ExtendedAddress { |
| 171 | explicit ExtendedAddress(RegisterID base, intptr_t offset = 0) |
| 172 | : base(base) |
| 173 | , offset(offset) |
| 174 | { |
| 175 | } |
| 176 | |
| 177 | RegisterID base; |
| 178 | intptr_t offset; |
| 179 | }; |
| 180 | |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 181 | // ImplicitAddress: |
| 182 | // |
| 183 | // This class is used for explicit 'load' and 'store' operations |
| 184 | // (as opposed to situations in which a memory operand is provided |
| 185 | // to a generic operation, such as an integer arithmetic instruction). |
| 186 | // |
| 187 | // In the case of a load (or store) operation we want to permit |
| 188 | // addresses to be implicitly constructed, e.g. the two calls: |
| 189 | // |
| 190 | // load32(Address(addrReg), destReg); |
| 191 | // load32(addrReg, destReg); |
| 192 | // |
| 193 | // Are equivalent, and the explicit wrapping of the Address in the former |
| 194 | // is unnecessary. |
| 195 | struct ImplicitAddress { |
| 196 | ImplicitAddress(RegisterID base) |
| 197 | : base(base) |
| 198 | , offset(0) |
| 199 | { |
| 200 | } |
| 201 | |
| 202 | ImplicitAddress(Address address) |
| 203 | : base(address.base) |
| 204 | , offset(address.offset) |
| 205 | { |
| 206 | } |
| 207 | |
| 208 | RegisterID base; |
| 209 | int32_t offset; |
| 210 | }; |
| 211 | |
| 212 | // BaseIndex: |
| 213 | // |
| 214 | // Describes a complex addressing mode. |
| 215 | struct BaseIndex { |
| 216 | BaseIndex(RegisterID base, RegisterID index, Scale scale, int32_t offset = 0) |
| 217 | : base(base) |
| 218 | , index(index) |
| 219 | , scale(scale) |
| 220 | , offset(offset) |
| 221 | { |
| 222 | } |
fpizlo@apple.com | f41fc90 | 2016-04-23 02:00:38 +0000 | [diff] [blame] | 223 | |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 224 | RegisterID base; |
| 225 | RegisterID index; |
| 226 | Scale scale; |
| 227 | int32_t offset; |
fpizlo@apple.com | da834ae | 2015-03-26 04:28:43 +0000 | [diff] [blame] | 228 | |
| 229 | BaseIndex withOffset(int32_t additionalOffset) |
| 230 | { |
| 231 | return BaseIndex(base, index, scale, offset + additionalOffset); |
| 232 | } |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 233 | }; |
| 234 | |
| 235 | // AbsoluteAddress: |
| 236 | // |
| 237 | // Describes an memory operand given by a pointer. For regular load & store |
| 238 | // operations an unwrapped void* will be used, rather than using this. |
| 239 | struct AbsoluteAddress { |
barraclough@apple.com | 66184e2 | 2011-03-13 21:16:29 +0000 | [diff] [blame] | 240 | explicit AbsoluteAddress(const void* ptr) |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 241 | : m_ptr(ptr) |
| 242 | { |
| 243 | } |
| 244 | |
barraclough@apple.com | 66184e2 | 2011-03-13 21:16:29 +0000 | [diff] [blame] | 245 | const void* m_ptr; |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 246 | }; |
| 247 | |
oliver@apple.com | be4e067 | 2011-03-28 17:14:57 +0000 | [diff] [blame] | 248 | // TrustedImmPtr: |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 249 | // |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 250 | // A pointer sized immediate operand to an instruction - this is wrapped |
| 251 | // in a class requiring explicit construction in order to differentiate |
| 252 | // from pointers used as absolute addresses to memory operations |
oliver@apple.com | be4e067 | 2011-03-28 17:14:57 +0000 | [diff] [blame] | 253 | struct TrustedImmPtr { |
fpizlo@apple.com | 59d857c | 2012-05-18 20:42:14 +0000 | [diff] [blame] | 254 | TrustedImmPtr() { } |
| 255 | |
oliver@apple.com | be4e067 | 2011-03-28 17:14:57 +0000 | [diff] [blame] | 256 | explicit TrustedImmPtr(const void* value) |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 257 | : m_value(value) |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 258 | { |
| 259 | } |
fpizlo@apple.com | 90e5f0e | 2011-09-22 22:42:54 +0000 | [diff] [blame] | 260 | |
| 261 | // This is only here so that TrustedImmPtr(0) does not confuse the C++ |
| 262 | // overload handling rules. |
| 263 | explicit TrustedImmPtr(int value) |
| 264 | : m_value(0) |
| 265 | { |
| 266 | ASSERT_UNUSED(value, !value); |
| 267 | } |
| 268 | |
| 269 | explicit TrustedImmPtr(size_t value) |
| 270 | : m_value(reinterpret_cast<void*>(value)) |
| 271 | { |
| 272 | } |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 273 | |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 274 | intptr_t asIntptr() |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 275 | { |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 276 | return reinterpret_cast<intptr_t>(m_value); |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 277 | } |
| 278 | |
oliver@apple.com | 2bd947e | 2010-04-29 03:57:16 +0000 | [diff] [blame] | 279 | const void* m_value; |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 280 | }; |
| 281 | |
andersca@apple.com | 467391d | 2013-10-02 18:17:46 +0000 | [diff] [blame] | 282 | struct ImmPtr : private TrustedImmPtr |
oliver@apple.com | b2a14ec | 2012-03-08 01:07:34 +0000 | [diff] [blame] | 283 | { |
oliver@apple.com | be4e067 | 2011-03-28 17:14:57 +0000 | [diff] [blame] | 284 | explicit ImmPtr(const void* value) |
| 285 | : TrustedImmPtr(value) |
| 286 | { |
| 287 | } |
oliver@apple.com | b2a14ec | 2012-03-08 01:07:34 +0000 | [diff] [blame] | 288 | |
| 289 | TrustedImmPtr asTrustedImmPtr() { return *this; } |
oliver@apple.com | be4e067 | 2011-03-28 17:14:57 +0000 | [diff] [blame] | 290 | }; |
| 291 | |
| 292 | // TrustedImm32: |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 293 | // |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 294 | // A 32bit immediate operand to an instruction - this is wrapped in a |
| 295 | // class requiring explicit construction in order to prevent RegisterIDs |
| 296 | // (which are implemented as an enum) from accidentally being passed as |
| 297 | // immediate values. |
oliver@apple.com | be4e067 | 2011-03-28 17:14:57 +0000 | [diff] [blame] | 298 | struct TrustedImm32 { |
fpizlo@apple.com | 59d857c | 2012-05-18 20:42:14 +0000 | [diff] [blame] | 299 | TrustedImm32() { } |
| 300 | |
oliver@apple.com | be4e067 | 2011-03-28 17:14:57 +0000 | [diff] [blame] | 301 | explicit TrustedImm32(int32_t value) |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 302 | : m_value(value) |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 303 | { |
| 304 | } |
| 305 | |
mjs@apple.com | cc66821 | 2010-01-04 11:38:56 +0000 | [diff] [blame] | 306 | #if !CPU(X86_64) |
oliver@apple.com | be4e067 | 2011-03-28 17:14:57 +0000 | [diff] [blame] | 307 | explicit TrustedImm32(TrustedImmPtr ptr) |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 308 | : m_value(ptr.asIntptr()) |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 309 | { |
| 310 | } |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 311 | #endif |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 312 | |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 313 | int32_t m_value; |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 314 | }; |
| 315 | |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 316 | |
andersca@apple.com | 467391d | 2013-10-02 18:17:46 +0000 | [diff] [blame] | 317 | struct Imm32 : private TrustedImm32 { |
oliver@apple.com | be4e067 | 2011-03-28 17:14:57 +0000 | [diff] [blame] | 318 | explicit Imm32(int32_t value) |
| 319 | : TrustedImm32(value) |
| 320 | { |
| 321 | } |
| 322 | #if !CPU(X86_64) |
| 323 | explicit Imm32(TrustedImmPtr ptr) |
| 324 | : TrustedImm32(ptr) |
| 325 | { |
| 326 | } |
| 327 | #endif |
oliver@apple.com | d5c4868 | 2012-03-06 02:40:05 +0000 | [diff] [blame] | 328 | const TrustedImm32& asTrustedImm32() const { return *this; } |
| 329 | |
oliver@apple.com | be4e067 | 2011-03-28 17:14:57 +0000 | [diff] [blame] | 330 | }; |
| 331 | |
yuqiang.xian@intel.com | 43d80f3 | 2012-10-16 08:41:31 +0000 | [diff] [blame] | 332 | // TrustedImm64: |
| 333 | // |
| 334 | // A 64bit immediate operand to an instruction - this is wrapped in a |
| 335 | // class requiring explicit construction in order to prevent RegisterIDs |
| 336 | // (which are implemented as an enum) from accidentally being passed as |
| 337 | // immediate values. |
| 338 | struct TrustedImm64 { |
| 339 | TrustedImm64() { } |
| 340 | |
| 341 | explicit TrustedImm64(int64_t value) |
| 342 | : m_value(value) |
| 343 | { |
| 344 | } |
| 345 | |
dbates@webkit.org | 98f0de0 | 2013-10-15 22:16:39 +0000 | [diff] [blame] | 346 | #if CPU(X86_64) || CPU(ARM64) |
yuqiang.xian@intel.com | 43d80f3 | 2012-10-16 08:41:31 +0000 | [diff] [blame] | 347 | explicit TrustedImm64(TrustedImmPtr ptr) |
| 348 | : m_value(ptr.asIntptr()) |
| 349 | { |
| 350 | } |
| 351 | #endif |
| 352 | |
| 353 | int64_t m_value; |
| 354 | }; |
| 355 | |
andersca@apple.com | 467391d | 2013-10-02 18:17:46 +0000 | [diff] [blame] | 356 | struct Imm64 : private TrustedImm64 |
yuqiang.xian@intel.com | 43d80f3 | 2012-10-16 08:41:31 +0000 | [diff] [blame] | 357 | { |
| 358 | explicit Imm64(int64_t value) |
| 359 | : TrustedImm64(value) |
| 360 | { |
| 361 | } |
dbates@webkit.org | 98f0de0 | 2013-10-15 22:16:39 +0000 | [diff] [blame] | 362 | #if CPU(X86_64) || CPU(ARM64) |
yuqiang.xian@intel.com | 43d80f3 | 2012-10-16 08:41:31 +0000 | [diff] [blame] | 363 | explicit Imm64(TrustedImmPtr ptr) |
| 364 | : TrustedImm64(ptr) |
| 365 | { |
| 366 | } |
| 367 | #endif |
| 368 | const TrustedImm64& asTrustedImm64() const { return *this; } |
| 369 | }; |
| 370 | |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 371 | // Section 2: MacroAssembler code buffer handles |
| 372 | // |
| 373 | // The following types are used to reference items in the code buffer |
| 374 | // during JIT code generation. For example, the type Jump is used to |
| 375 | // track the location of a jump instruction so that it may later be |
| 376 | // linked to a label marking its destination. |
| 377 | |
| 378 | |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 379 | // Label: |
| 380 | // |
| 381 | // A Label records a point in the generated instruction stream, typically such that |
| 382 | // it may be used as a destination for a jump. |
| 383 | class Label { |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 384 | template<class TemplateAssemblerType, class TemplateMacroAssemblerType> |
barraclough@apple.com | cef2b1c | 2009-05-18 20:22:52 +0000 | [diff] [blame] | 385 | friend class AbstractMacroAssembler; |
msaboff@apple.com | 064257d | 2012-12-18 03:51:07 +0000 | [diff] [blame] | 386 | friend struct DFG::OSRExit; |
barraclough@apple.com | 04b762d | 2009-05-22 02:34:41 +0000 | [diff] [blame] | 387 | friend class Jump; |
| 388 | friend class MacroAssemblerCodeRef; |
barraclough@apple.com | 73c571d | 2009-06-16 06:52:49 +0000 | [diff] [blame] | 389 | friend class LinkBuffer; |
fpizlo@apple.com | b75911b | 2012-06-13 20:53:52 +0000 | [diff] [blame] | 390 | friend class Watchpoint; |
barraclough@apple.com | 04b762d | 2009-05-22 02:34:41 +0000 | [diff] [blame] | 391 | |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 392 | public: |
| 393 | Label() |
| 394 | { |
| 395 | } |
| 396 | |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 397 | Label(AbstractMacroAssemblerType* masm) |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 398 | : m_label(masm->m_assembler.label()) |
| 399 | { |
dbates@webkit.org | 98f0de0 | 2013-10-15 22:16:39 +0000 | [diff] [blame] | 400 | masm->invalidateAllTempRegisters(); |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 401 | } |
dbates@webkit.org | 98f0de0 | 2013-10-15 22:16:39 +0000 | [diff] [blame] | 402 | |
sbarati@apple.com | d3d0c00 | 2016-01-30 01:11:05 +0000 | [diff] [blame] | 403 | bool operator==(const Label& other) const { return m_label == other.m_label; } |
| 404 | |
msaboff@apple.com | c518d8b | 2010-12-03 22:48:19 +0000 | [diff] [blame] | 405 | bool isSet() const { return m_label.isSet(); } |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 406 | private: |
barraclough@apple.com | 4836c7a | 2011-05-01 22:20:59 +0000 | [diff] [blame] | 407 | AssemblerLabel m_label; |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 408 | }; |
fpizlo@apple.com | d68b1f8 | 2012-07-05 22:55:51 +0000 | [diff] [blame] | 409 | |
| 410 | // ConvertibleLoadLabel: |
| 411 | // |
| 412 | // A ConvertibleLoadLabel records a loadPtr instruction that can be patched to an addPtr |
| 413 | // so that: |
| 414 | // |
| 415 | // loadPtr(Address(a, i), b) |
| 416 | // |
| 417 | // becomes: |
| 418 | // |
| 419 | // addPtr(TrustedImmPtr(i), a, b) |
| 420 | class ConvertibleLoadLabel { |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 421 | template<class TemplateAssemblerType, class TemplateMacroAssemblerType> |
fpizlo@apple.com | d68b1f8 | 2012-07-05 22:55:51 +0000 | [diff] [blame] | 422 | friend class AbstractMacroAssembler; |
| 423 | friend class LinkBuffer; |
| 424 | |
| 425 | public: |
| 426 | ConvertibleLoadLabel() |
| 427 | { |
| 428 | } |
| 429 | |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 430 | ConvertibleLoadLabel(AbstractMacroAssemblerType* masm) |
fpizlo@apple.com | d68b1f8 | 2012-07-05 22:55:51 +0000 | [diff] [blame] | 431 | : m_label(masm->m_assembler.labelIgnoringWatchpoints()) |
| 432 | { |
| 433 | } |
| 434 | |
| 435 | bool isSet() const { return m_label.isSet(); } |
| 436 | private: |
| 437 | AssemblerLabel m_label; |
| 438 | }; |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 439 | |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 440 | // DataLabelPtr: |
| 441 | // |
| 442 | // A DataLabelPtr is used to refer to a location in the code containing a pointer to be |
| 443 | // patched after the code has been generated. |
| 444 | class DataLabelPtr { |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 445 | template<class TemplateAssemblerType, class TemplateMacroAssemblerType> |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 446 | friend class AbstractMacroAssembler; |
barraclough@apple.com | 73c571d | 2009-06-16 06:52:49 +0000 | [diff] [blame] | 447 | friend class LinkBuffer; |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 448 | public: |
| 449 | DataLabelPtr() |
| 450 | { |
| 451 | } |
| 452 | |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 453 | DataLabelPtr(AbstractMacroAssemblerType* masm) |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 454 | : m_label(masm->m_assembler.label()) |
| 455 | { |
| 456 | } |
dbates@webkit.org | 98f0de0 | 2013-10-15 22:16:39 +0000 | [diff] [blame] | 457 | |
msaboff@apple.com | c518d8b | 2010-12-03 22:48:19 +0000 | [diff] [blame] | 458 | bool isSet() const { return m_label.isSet(); } |
| 459 | |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 460 | private: |
barraclough@apple.com | 4836c7a | 2011-05-01 22:20:59 +0000 | [diff] [blame] | 461 | AssemblerLabel m_label; |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 462 | }; |
| 463 | |
| 464 | // DataLabel32: |
| 465 | // |
mhahnenberg@apple.com | b6f8519 | 2014-02-27 01:27:18 +0000 | [diff] [blame] | 466 | // A DataLabel32 is used to refer to a location in the code containing a 32-bit constant to be |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 467 | // patched after the code has been generated. |
| 468 | class DataLabel32 { |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 469 | template<class TemplateAssemblerType, class TemplateMacroAssemblerType> |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 470 | friend class AbstractMacroAssembler; |
barraclough@apple.com | 73c571d | 2009-06-16 06:52:49 +0000 | [diff] [blame] | 471 | friend class LinkBuffer; |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 472 | public: |
| 473 | DataLabel32() |
| 474 | { |
| 475 | } |
| 476 | |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 477 | DataLabel32(AbstractMacroAssemblerType* masm) |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 478 | : m_label(masm->m_assembler.label()) |
| 479 | { |
| 480 | } |
| 481 | |
oliver@apple.com | 2c012fa | 2011-05-17 20:02:41 +0000 | [diff] [blame] | 482 | AssemblerLabel label() const { return m_label; } |
| 483 | |
| 484 | private: |
| 485 | AssemblerLabel m_label; |
| 486 | }; |
| 487 | |
| 488 | // DataLabelCompact: |
| 489 | // |
| 490 | // A DataLabelCompact is used to refer to a location in the code containing a |
| 491 | // compact immediate to be patched after the code has been generated. |
| 492 | class DataLabelCompact { |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 493 | template<class TemplateAssemblerType, class TemplateMacroAssemblerType> |
oliver@apple.com | 2c012fa | 2011-05-17 20:02:41 +0000 | [diff] [blame] | 494 | friend class AbstractMacroAssembler; |
| 495 | friend class LinkBuffer; |
| 496 | public: |
| 497 | DataLabelCompact() |
| 498 | { |
| 499 | } |
| 500 | |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 501 | DataLabelCompact(AbstractMacroAssemblerType* masm) |
oliver@apple.com | 2c012fa | 2011-05-17 20:02:41 +0000 | [diff] [blame] | 502 | : m_label(masm->m_assembler.label()) |
| 503 | { |
| 504 | } |
dbates@webkit.org | 98f0de0 | 2013-10-15 22:16:39 +0000 | [diff] [blame] | 505 | |
oliver@apple.com | 2c012fa | 2011-05-17 20:02:41 +0000 | [diff] [blame] | 506 | DataLabelCompact(AssemblerLabel label) |
| 507 | : m_label(label) |
| 508 | { |
| 509 | } |
| 510 | |
fpizlo@apple.com | 5ba0788 | 2013-10-19 23:13:23 +0000 | [diff] [blame] | 511 | AssemblerLabel label() const { return m_label; } |
| 512 | |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 513 | private: |
barraclough@apple.com | 4836c7a | 2011-05-01 22:20:59 +0000 | [diff] [blame] | 514 | AssemblerLabel m_label; |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 515 | }; |
| 516 | |
| 517 | // Call: |
| 518 | // |
| 519 | // A Call object is a reference to a call instruction that has been planted |
| 520 | // into the code buffer - it is typically used to link the call, setting the |
| 521 | // relative offset such that when executed it will call to the desired |
| 522 | // destination. |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 523 | class Call { |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 524 | template<class TemplateAssemblerType, class TemplateMacroAssemblerType> |
barraclough@apple.com | cef2b1c | 2009-05-18 20:22:52 +0000 | [diff] [blame] | 525 | friend class AbstractMacroAssembler; |
barraclough@apple.com | 96e7343 | 2009-07-22 03:24:34 +0000 | [diff] [blame] | 526 | |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 527 | public: |
barraclough@apple.com | d7e1338 | 2009-02-19 22:51:40 +0000 | [diff] [blame] | 528 | enum Flags { |
| 529 | None = 0x0, |
| 530 | Linkable = 0x1, |
| 531 | Near = 0x2, |
msaboff@apple.com | c15ae7e | 2015-09-16 23:40:35 +0000 | [diff] [blame] | 532 | Tail = 0x4, |
barraclough@apple.com | d7e1338 | 2009-02-19 22:51:40 +0000 | [diff] [blame] | 533 | LinkableNear = 0x3, |
msaboff@apple.com | c15ae7e | 2015-09-16 23:40:35 +0000 | [diff] [blame] | 534 | LinkableNearTail = 0x7, |
barraclough@apple.com | d7e1338 | 2009-02-19 22:51:40 +0000 | [diff] [blame] | 535 | }; |
| 536 | |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 537 | Call() |
barraclough@apple.com | d7e1338 | 2009-02-19 22:51:40 +0000 | [diff] [blame] | 538 | : m_flags(None) |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 539 | { |
| 540 | } |
| 541 | |
barraclough@apple.com | 4836c7a | 2011-05-01 22:20:59 +0000 | [diff] [blame] | 542 | Call(AssemblerLabel jmp, Flags flags) |
barraclough@apple.com | 0d15b9e | 2011-05-26 04:12:41 +0000 | [diff] [blame] | 543 | : m_label(jmp) |
barraclough@apple.com | d7e1338 | 2009-02-19 22:51:40 +0000 | [diff] [blame] | 544 | , m_flags(flags) |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 545 | { |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 546 | } |
barraclough@apple.com | d7e1338 | 2009-02-19 22:51:40 +0000 | [diff] [blame] | 547 | |
| 548 | bool isFlagSet(Flags flag) |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 549 | { |
barraclough@apple.com | d7e1338 | 2009-02-19 22:51:40 +0000 | [diff] [blame] | 550 | return m_flags & flag; |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 551 | } |
barraclough@apple.com | d7e1338 | 2009-02-19 22:51:40 +0000 | [diff] [blame] | 552 | |
| 553 | static Call fromTailJump(Jump jump) |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 554 | { |
barraclough@apple.com | 0d15b9e | 2011-05-26 04:12:41 +0000 | [diff] [blame] | 555 | return Call(jump.m_label, Linkable); |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 556 | } |
| 557 | |
barraclough@apple.com | 0d15b9e | 2011-05-26 04:12:41 +0000 | [diff] [blame] | 558 | AssemblerLabel m_label; |
barraclough@apple.com | 96e7343 | 2009-07-22 03:24:34 +0000 | [diff] [blame] | 559 | private: |
barraclough@apple.com | d7e1338 | 2009-02-19 22:51:40 +0000 | [diff] [blame] | 560 | Flags m_flags; |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 561 | }; |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 562 | |
| 563 | // Jump: |
| 564 | // |
| 565 | // A jump object is a reference to a jump instruction that has been planted |
| 566 | // into the code buffer - it is typically used to link the jump, setting the |
| 567 | // relative offset such that when executed it will jump to the desired |
| 568 | // destination. |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 569 | class Jump { |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 570 | template<class TemplateAssemblerType, class TemplateMacroAssemblerType> |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 571 | friend class AbstractMacroAssembler; |
barraclough@apple.com | d7e1338 | 2009-02-19 22:51:40 +0000 | [diff] [blame] | 572 | friend class Call; |
msaboff@apple.com | 064257d | 2012-12-18 03:51:07 +0000 | [diff] [blame] | 573 | friend struct DFG::OSRExit; |
barraclough@apple.com | 73c571d | 2009-06-16 06:52:49 +0000 | [diff] [blame] | 574 | friend class LinkBuffer; |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 575 | public: |
| 576 | Jump() |
| 577 | { |
| 578 | } |
| 579 | |
barraclough@apple.com | 1146b41 | 2011-05-03 00:24:22 +0000 | [diff] [blame] | 580 | #if CPU(ARM_THUMB2) |
barraclough@apple.com | 4836c7a | 2011-05-01 22:20:59 +0000 | [diff] [blame] | 581 | // Fixme: this information should be stored in the instruction stream, not in the Jump object. |
msaboff@apple.com | 30495b6 | 2012-12-18 17:55:41 +0000 | [diff] [blame] | 582 | Jump(AssemblerLabel jmp, ARMv7Assembler::JumpType type = ARMv7Assembler::JumpNoCondition, ARMv7Assembler::Condition condition = ARMv7Assembler::ConditionInvalid) |
barraclough@apple.com | 0d15b9e | 2011-05-26 04:12:41 +0000 | [diff] [blame] | 583 | : m_label(jmp) |
barraclough@apple.com | 4836c7a | 2011-05-01 22:20:59 +0000 | [diff] [blame] | 584 | , m_type(type) |
| 585 | , m_condition(condition) |
| 586 | { |
| 587 | } |
dbates@webkit.org | 98f0de0 | 2013-10-15 22:16:39 +0000 | [diff] [blame] | 588 | #elif CPU(ARM64) |
| 589 | Jump(AssemblerLabel jmp, ARM64Assembler::JumpType type = ARM64Assembler::JumpNoCondition, ARM64Assembler::Condition condition = ARM64Assembler::ConditionInvalid) |
| 590 | : m_label(jmp) |
| 591 | , m_type(type) |
| 592 | , m_condition(condition) |
| 593 | { |
| 594 | } |
| 595 | |
| 596 | Jump(AssemblerLabel jmp, ARM64Assembler::JumpType type, ARM64Assembler::Condition condition, bool is64Bit, ARM64Assembler::RegisterID compareRegister) |
| 597 | : m_label(jmp) |
| 598 | , m_type(type) |
| 599 | , m_condition(condition) |
| 600 | , m_is64Bit(is64Bit) |
| 601 | , m_compareRegister(compareRegister) |
| 602 | { |
| 603 | ASSERT((type == ARM64Assembler::JumpCompareAndBranch) || (type == ARM64Assembler::JumpCompareAndBranchFixedSize)); |
| 604 | } |
| 605 | |
| 606 | Jump(AssemblerLabel jmp, ARM64Assembler::JumpType type, ARM64Assembler::Condition condition, unsigned bitNumber, ARM64Assembler::RegisterID compareRegister) |
| 607 | : m_label(jmp) |
| 608 | , m_type(type) |
| 609 | , m_condition(condition) |
| 610 | , m_bitNumber(bitNumber) |
| 611 | , m_compareRegister(compareRegister) |
| 612 | { |
| 613 | ASSERT((type == ARM64Assembler::JumpTestBit) || (type == ARM64Assembler::JumpTestBitFixedSize)); |
| 614 | } |
commit-queue@webkit.org | 3437809 | 2012-03-27 02:03:47 +0000 | [diff] [blame] | 615 | #elif CPU(SH4) |
| 616 | Jump(AssemblerLabel jmp, SH4Assembler::JumpType type = SH4Assembler::JumpFar) |
| 617 | : m_label(jmp) |
| 618 | , m_type(type) |
| 619 | { |
| 620 | } |
barraclough@apple.com | 4836c7a | 2011-05-01 22:20:59 +0000 | [diff] [blame] | 621 | #else |
| 622 | Jump(AssemblerLabel jmp) |
barraclough@apple.com | 0d15b9e | 2011-05-26 04:12:41 +0000 | [diff] [blame] | 623 | : m_label(jmp) |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 624 | { |
| 625 | } |
barraclough@apple.com | 4836c7a | 2011-05-01 22:20:59 +0000 | [diff] [blame] | 626 | #endif |
fpizlo@apple.com | d2deec8 | 2012-12-10 18:17:46 +0000 | [diff] [blame] | 627 | |
| 628 | Label label() const |
| 629 | { |
| 630 | Label result; |
| 631 | result.m_label = m_label; |
| 632 | return result; |
| 633 | } |
barraclough@apple.com | 4836c7a | 2011-05-01 22:20:59 +0000 | [diff] [blame] | 634 | |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 635 | void link(AbstractMacroAssemblerType* masm) const |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 636 | { |
dbates@webkit.org | 98f0de0 | 2013-10-15 22:16:39 +0000 | [diff] [blame] | 637 | masm->invalidateAllTempRegisters(); |
| 638 | |
msaboff@apple.com | 278a60c | 2013-03-15 19:33:25 +0000 | [diff] [blame] | 639 | #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION) |
| 640 | masm->checkRegisterAllocationAgainstBranchRange(m_label.m_offset, masm->debugOffset()); |
| 641 | #endif |
| 642 | |
barraclough@apple.com | 1146b41 | 2011-05-03 00:24:22 +0000 | [diff] [blame] | 643 | #if CPU(ARM_THUMB2) |
barraclough@apple.com | 0d15b9e | 2011-05-26 04:12:41 +0000 | [diff] [blame] | 644 | masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition); |
dbates@webkit.org | 98f0de0 | 2013-10-15 22:16:39 +0000 | [diff] [blame] | 645 | #elif CPU(ARM64) |
| 646 | if ((m_type == ARM64Assembler::JumpCompareAndBranch) || (m_type == ARM64Assembler::JumpCompareAndBranchFixedSize)) |
| 647 | masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition, m_is64Bit, m_compareRegister); |
| 648 | else if ((m_type == ARM64Assembler::JumpTestBit) || (m_type == ARM64Assembler::JumpTestBitFixedSize)) |
| 649 | masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition, m_bitNumber, m_compareRegister); |
| 650 | else |
| 651 | masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition); |
commit-queue@webkit.org | 3437809 | 2012-03-27 02:03:47 +0000 | [diff] [blame] | 652 | #elif CPU(SH4) |
| 653 | masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type); |
barraclough@apple.com | 4836c7a | 2011-05-01 22:20:59 +0000 | [diff] [blame] | 654 | #else |
barraclough@apple.com | 0d15b9e | 2011-05-26 04:12:41 +0000 | [diff] [blame] | 655 | masm->m_assembler.linkJump(m_label, masm->m_assembler.label()); |
barraclough@apple.com | 4836c7a | 2011-05-01 22:20:59 +0000 | [diff] [blame] | 656 | #endif |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 657 | } |
| 658 | |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 659 | void linkTo(Label label, AbstractMacroAssemblerType* masm) const |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 660 | { |
msaboff@apple.com | 278a60c | 2013-03-15 19:33:25 +0000 | [diff] [blame] | 661 | #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION) |
| 662 | masm->checkRegisterAllocationAgainstBranchRange(label.m_label.m_offset, m_label.m_offset); |
| 663 | #endif |
| 664 | |
barraclough@apple.com | 1146b41 | 2011-05-03 00:24:22 +0000 | [diff] [blame] | 665 | #if CPU(ARM_THUMB2) |
barraclough@apple.com | 0d15b9e | 2011-05-26 04:12:41 +0000 | [diff] [blame] | 666 | masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition); |
dbates@webkit.org | 98f0de0 | 2013-10-15 22:16:39 +0000 | [diff] [blame] | 667 | #elif CPU(ARM64) |
| 668 | if ((m_type == ARM64Assembler::JumpCompareAndBranch) || (m_type == ARM64Assembler::JumpCompareAndBranchFixedSize)) |
| 669 | masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition, m_is64Bit, m_compareRegister); |
| 670 | else if ((m_type == ARM64Assembler::JumpTestBit) || (m_type == ARM64Assembler::JumpTestBitFixedSize)) |
| 671 | masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition, m_bitNumber, m_compareRegister); |
| 672 | else |
| 673 | masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition); |
barraclough@apple.com | 4836c7a | 2011-05-01 22:20:59 +0000 | [diff] [blame] | 674 | #else |
barraclough@apple.com | 0d15b9e | 2011-05-26 04:12:41 +0000 | [diff] [blame] | 675 | masm->m_assembler.linkJump(m_label, label.m_label); |
barraclough@apple.com | 4836c7a | 2011-05-01 22:20:59 +0000 | [diff] [blame] | 676 | #endif |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 677 | } |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 678 | |
barraclough@apple.com | 0d15b9e | 2011-05-26 04:12:41 +0000 | [diff] [blame] | 679 | bool isSet() const { return m_label.isSet(); } |
barraclough@apple.com | 8af7a53 | 2011-03-13 22:11:13 +0000 | [diff] [blame] | 680 | |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 681 | private: |
barraclough@apple.com | 0d15b9e | 2011-05-26 04:12:41 +0000 | [diff] [blame] | 682 | AssemblerLabel m_label; |
barraclough@apple.com | 1146b41 | 2011-05-03 00:24:22 +0000 | [diff] [blame] | 683 | #if CPU(ARM_THUMB2) |
barraclough@apple.com | 4836c7a | 2011-05-01 22:20:59 +0000 | [diff] [blame] | 684 | ARMv7Assembler::JumpType m_type; |
| 685 | ARMv7Assembler::Condition m_condition; |
dbates@webkit.org | 98f0de0 | 2013-10-15 22:16:39 +0000 | [diff] [blame] | 686 | #elif CPU(ARM64) |
| 687 | ARM64Assembler::JumpType m_type; |
| 688 | ARM64Assembler::Condition m_condition; |
| 689 | bool m_is64Bit; |
| 690 | unsigned m_bitNumber; |
| 691 | ARM64Assembler::RegisterID m_compareRegister; |
barraclough@apple.com | 4836c7a | 2011-05-01 22:20:59 +0000 | [diff] [blame] | 692 | #endif |
commit-queue@webkit.org | 3437809 | 2012-03-27 02:03:47 +0000 | [diff] [blame] | 693 | #if CPU(SH4) |
| 694 | SH4Assembler::JumpType m_type; |
| 695 | #endif |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 696 | }; |
| 697 | |
barraclough@apple.com | 959b92e | 2012-04-25 00:06:04 +0000 | [diff] [blame] | 698 | struct PatchableJump { |
| 699 | PatchableJump() |
| 700 | { |
| 701 | } |
| 702 | |
| 703 | explicit PatchableJump(Jump jump) |
| 704 | : m_jump(jump) |
| 705 | { |
| 706 | } |
| 707 | |
| 708 | operator Jump&() { return m_jump; } |
| 709 | |
| 710 | Jump m_jump; |
| 711 | }; |
| 712 | |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 713 | // JumpList: |
| 714 | // |
| 715 | // A JumpList is a set of Jump objects. |
| 716 | // All jumps in the set will be linked to the same destination. |
| 717 | class JumpList { |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 718 | public: |
fpizlo@apple.com | d3955a4 | 2012-12-20 19:14:39 +0000 | [diff] [blame] | 719 | typedef Vector<Jump, 2> JumpVector; |
fpizlo@apple.com | 75c91a7 | 2012-11-08 22:28:25 +0000 | [diff] [blame] | 720 | |
| 721 | JumpList() { } |
| 722 | |
| 723 | JumpList(Jump jump) |
| 724 | { |
fpizlo@apple.com | 385a33a | 2014-03-18 20:53:07 +0000 | [diff] [blame] | 725 | if (jump.isSet()) |
| 726 | append(jump); |
fpizlo@apple.com | 75c91a7 | 2012-11-08 22:28:25 +0000 | [diff] [blame] | 727 | } |
ggaren@apple.com | 540d71a6 | 2009-07-30 20:57:44 +0000 | [diff] [blame] | 728 | |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 729 | void link(AbstractMacroAssemblerType* masm) |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 730 | { |
| 731 | size_t size = m_jumps.size(); |
| 732 | for (size_t i = 0; i < size; ++i) |
| 733 | m_jumps[i].link(masm); |
| 734 | m_jumps.clear(); |
| 735 | } |
| 736 | |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 737 | void linkTo(Label label, AbstractMacroAssemblerType* masm) |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 738 | { |
| 739 | size_t size = m_jumps.size(); |
| 740 | for (size_t i = 0; i < size; ++i) |
| 741 | m_jumps[i].linkTo(label, masm); |
| 742 | m_jumps.clear(); |
| 743 | } |
| 744 | |
| 745 | void append(Jump jump) |
| 746 | { |
| 747 | m_jumps.append(jump); |
| 748 | } |
| 749 | |
fpizlo@apple.com | 0e9910a | 2012-10-09 23:39:53 +0000 | [diff] [blame] | 750 | void append(const JumpList& other) |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 751 | { |
| 752 | m_jumps.append(other.m_jumps.begin(), other.m_jumps.size()); |
| 753 | } |
| 754 | |
| 755 | bool empty() |
| 756 | { |
| 757 | return !m_jumps.size(); |
| 758 | } |
ggaren@apple.com | 540d71a6 | 2009-07-30 20:57:44 +0000 | [diff] [blame] | 759 | |
msaboff@apple.com | c518d8b | 2010-12-03 22:48:19 +0000 | [diff] [blame] | 760 | void clear() |
| 761 | { |
| 762 | m_jumps.clear(); |
| 763 | } |
| 764 | |
fpizlo@apple.com | b9aa7ba | 2012-10-14 22:05:16 +0000 | [diff] [blame] | 765 | const JumpVector& jumps() const { return m_jumps; } |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 766 | |
| 767 | private: |
ggaren@apple.com | 540d71a6 | 2009-07-30 20:57:44 +0000 | [diff] [blame] | 768 | JumpVector m_jumps; |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 769 | }; |
| 770 | |
| 771 | |
barraclough@apple.com | ba92ede | 2009-07-22 00:37:03 +0000 | [diff] [blame] | 772 | // Section 3: Misc admin methods |
fpizlo@apple.com | 3d51767 | 2012-06-20 17:48:23 +0000 | [diff] [blame] | 773 | #if ENABLE(DFG_JIT) |
| 774 | Label labelIgnoringWatchpoints() |
| 775 | { |
| 776 | Label result; |
| 777 | result.m_label = m_assembler.labelIgnoringWatchpoints(); |
| 778 | return result; |
| 779 | } |
fpizlo@apple.com | d68b1f8 | 2012-07-05 22:55:51 +0000 | [diff] [blame] | 780 | #else |
| 781 | Label labelIgnoringWatchpoints() |
| 782 | { |
| 783 | return label(); |
| 784 | } |
fpizlo@apple.com | 3d51767 | 2012-06-20 17:48:23 +0000 | [diff] [blame] | 785 | #endif |
| 786 | |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 787 | Label label() |
| 788 | { |
| 789 | return Label(this); |
| 790 | } |
| 791 | |
fpizlo@apple.com | 0712be8 | 2012-08-21 23:30:19 +0000 | [diff] [blame] | 792 | void padBeforePatch() |
| 793 | { |
| 794 | // Rely on the fact that asking for a label already does the padding. |
| 795 | (void)label(); |
| 796 | } |
| 797 | |
fpizlo@apple.com | b75911b | 2012-06-13 20:53:52 +0000 | [diff] [blame] | 798 | Label watchpointLabel() |
| 799 | { |
| 800 | Label result; |
| 801 | result.m_label = m_assembler.labelForWatchpoint(); |
| 802 | return result; |
| 803 | } |
| 804 | |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 805 | Label align() |
| 806 | { |
| 807 | m_assembler.align(16); |
| 808 | return Label(this); |
| 809 | } |
| 810 | |
msaboff@apple.com | 278a60c | 2013-03-15 19:33:25 +0000 | [diff] [blame] | 811 | #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION) |
| 812 | class RegisterAllocationOffset { |
| 813 | public: |
| 814 | RegisterAllocationOffset(unsigned offset) |
| 815 | : m_offset(offset) |
| 816 | { |
| 817 | } |
| 818 | |
fpizlo@apple.com | 35432f0 | 2013-10-30 20:59:18 +0000 | [diff] [blame] | 819 | void checkOffsets(unsigned low, unsigned high) |
msaboff@apple.com | 278a60c | 2013-03-15 19:33:25 +0000 | [diff] [blame] | 820 | { |
| 821 | RELEASE_ASSERT_WITH_MESSAGE(!(low <= m_offset && m_offset <= high), "Unsafe branch over register allocation at instruction offset %u in jump offset range %u..%u", m_offset, low, high); |
| 822 | } |
| 823 | |
| 824 | private: |
| 825 | unsigned m_offset; |
| 826 | }; |
| 827 | |
| 828 | void addRegisterAllocationAtOffset(unsigned offset) |
| 829 | { |
| 830 | m_registerAllocationForOffsets.append(RegisterAllocationOffset(offset)); |
| 831 | } |
| 832 | |
| 833 | void clearRegisterAllocationOffsets() |
| 834 | { |
| 835 | m_registerAllocationForOffsets.clear(); |
| 836 | } |
| 837 | |
| 838 | void checkRegisterAllocationAgainstBranchRange(unsigned offset1, unsigned offset2) |
| 839 | { |
| 840 | if (offset1 > offset2) |
| 841 | std::swap(offset1, offset2); |
| 842 | |
| 843 | size_t size = m_registerAllocationForOffsets.size(); |
| 844 | for (size_t i = 0; i < size; ++i) |
fpizlo@apple.com | 35432f0 | 2013-10-30 20:59:18 +0000 | [diff] [blame] | 845 | m_registerAllocationForOffsets[i].checkOffsets(offset1, offset2); |
msaboff@apple.com | 278a60c | 2013-03-15 19:33:25 +0000 | [diff] [blame] | 846 | } |
| 847 | #endif |
| 848 | |
barraclough@apple.com | 0d15b9e | 2011-05-26 04:12:41 +0000 | [diff] [blame] | 849 | template<typename T, typename U> |
barraclough@apple.com | f14ef92 | 2012-04-13 19:24:14 +0000 | [diff] [blame] | 850 | static ptrdiff_t differenceBetween(T from, U to) |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 851 | { |
| 852 | return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label); |
| 853 | } |
| 854 | |
barraclough@apple.com | 03571d7 | 2011-11-08 23:45:05 +0000 | [diff] [blame] | 855 | static ptrdiff_t differenceBetweenCodePtr(const MacroAssemblerCodePtr& a, const MacroAssemblerCodePtr& b) |
| 856 | { |
| 857 | return reinterpret_cast<ptrdiff_t>(b.executableAddress()) - reinterpret_cast<ptrdiff_t>(a.executableAddress()); |
| 858 | } |
| 859 | |
barraclough@apple.com | 9cb663d | 2011-04-15 00:25:59 +0000 | [diff] [blame] | 860 | unsigned debugOffset() { return m_assembler.debugOffset(); } |
barraclough@apple.com | 9cb663d | 2011-04-15 00:25:59 +0000 | [diff] [blame] | 861 | |
barraclough@apple.com | efdbf47 | 2012-05-24 21:14:07 +0000 | [diff] [blame] | 862 | ALWAYS_INLINE static void cacheFlush(void* code, size_t size) |
| 863 | { |
| 864 | AssemblerType::cacheFlush(code, size); |
| 865 | } |
fpizlo@apple.com | 2e7ada0 | 2013-10-23 18:22:09 +0000 | [diff] [blame] | 866 | |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 867 | #if ENABLE(MASM_PROBE) |
| 868 | |
| 869 | struct CPUState { |
| 870 | #define DECLARE_REGISTER(_type, _regName) \ |
| 871 | _type _regName; |
| 872 | FOR_EACH_CPU_REGISTER(DECLARE_REGISTER) |
| 873 | #undef DECLARE_REGISTER |
mark.lam@apple.com | 8b8b5fe | 2014-11-17 22:03:04 +0000 | [diff] [blame] | 874 | |
mark.lam@apple.com | c882c03 | 2015-10-15 18:37:38 +0000 | [diff] [blame] | 875 | static const char* gprName(RegisterID regID) |
mark.lam@apple.com | 8b8b5fe | 2014-11-17 22:03:04 +0000 | [diff] [blame] | 876 | { |
| 877 | switch (regID) { |
| 878 | #define DECLARE_REGISTER(_type, _regName) \ |
| 879 | case RegisterID::_regName: \ |
| 880 | return #_regName; |
| 881 | FOR_EACH_CPU_GPREGISTER(DECLARE_REGISTER) |
| 882 | #undef DECLARE_REGISTER |
mark.lam@apple.com | c21f14b | 2015-10-15 19:54:02 +0000 | [diff] [blame] | 883 | default: |
| 884 | RELEASE_ASSERT_NOT_REACHED(); |
mark.lam@apple.com | 8b8b5fe | 2014-11-17 22:03:04 +0000 | [diff] [blame] | 885 | } |
mark.lam@apple.com | 8b8b5fe | 2014-11-17 22:03:04 +0000 | [diff] [blame] | 886 | } |
| 887 | |
mark.lam@apple.com | c882c03 | 2015-10-15 18:37:38 +0000 | [diff] [blame] | 888 | static const char* fprName(FPRegisterID regID) |
mark.lam@apple.com | 8b8b5fe | 2014-11-17 22:03:04 +0000 | [diff] [blame] | 889 | { |
| 890 | switch (regID) { |
| 891 | #define DECLARE_REGISTER(_type, _regName) \ |
| 892 | case FPRegisterID::_regName: \ |
| 893 | return #_regName; |
| 894 | FOR_EACH_CPU_FPREGISTER(DECLARE_REGISTER) |
| 895 | #undef DECLARE_REGISTER |
mark.lam@apple.com | c21f14b | 2015-10-15 19:54:02 +0000 | [diff] [blame] | 896 | default: |
| 897 | RELEASE_ASSERT_NOT_REACHED(); |
mark.lam@apple.com | 8b8b5fe | 2014-11-17 22:03:04 +0000 | [diff] [blame] | 898 | } |
mark.lam@apple.com | 8b8b5fe | 2014-11-17 22:03:04 +0000 | [diff] [blame] | 899 | } |
| 900 | |
mark.lam@apple.com | bb16769 | 2015-11-11 23:04:09 +0000 | [diff] [blame] | 901 | void*& gpr(RegisterID regID) |
mark.lam@apple.com | 8b8b5fe | 2014-11-17 22:03:04 +0000 | [diff] [blame] | 902 | { |
| 903 | switch (regID) { |
| 904 | #define DECLARE_REGISTER(_type, _regName) \ |
| 905 | case RegisterID::_regName: \ |
| 906 | return _regName; |
| 907 | FOR_EACH_CPU_GPREGISTER(DECLARE_REGISTER) |
| 908 | #undef DECLARE_REGISTER |
mark.lam@apple.com | c21f14b | 2015-10-15 19:54:02 +0000 | [diff] [blame] | 909 | default: |
| 910 | RELEASE_ASSERT_NOT_REACHED(); |
mark.lam@apple.com | 8b8b5fe | 2014-11-17 22:03:04 +0000 | [diff] [blame] | 911 | } |
mark.lam@apple.com | 8b8b5fe | 2014-11-17 22:03:04 +0000 | [diff] [blame] | 912 | } |
| 913 | |
mark.lam@apple.com | bb16769 | 2015-11-11 23:04:09 +0000 | [diff] [blame] | 914 | double& fpr(FPRegisterID regID) |
mark.lam@apple.com | 8b8b5fe | 2014-11-17 22:03:04 +0000 | [diff] [blame] | 915 | { |
| 916 | switch (regID) { |
| 917 | #define DECLARE_REGISTER(_type, _regName) \ |
| 918 | case FPRegisterID::_regName: \ |
| 919 | return _regName; |
| 920 | FOR_EACH_CPU_FPREGISTER(DECLARE_REGISTER) |
| 921 | #undef DECLARE_REGISTER |
mark.lam@apple.com | c21f14b | 2015-10-15 19:54:02 +0000 | [diff] [blame] | 922 | default: |
| 923 | RELEASE_ASSERT_NOT_REACHED(); |
mark.lam@apple.com | 8b8b5fe | 2014-11-17 22:03:04 +0000 | [diff] [blame] | 924 | } |
mark.lam@apple.com | 8b8b5fe | 2014-11-17 22:03:04 +0000 | [diff] [blame] | 925 | } |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 926 | }; |
| 927 | |
| 928 | struct ProbeContext; |
| 929 | typedef void (*ProbeFunction)(struct ProbeContext*); |
| 930 | |
| 931 | struct ProbeContext { |
| 932 | ProbeFunction probeFunction; |
| 933 | void* arg1; |
| 934 | void* arg2; |
| 935 | CPUState cpu; |
mark.lam@apple.com | 5bb8a12 | 2015-10-16 20:36:44 +0000 | [diff] [blame] | 936 | |
| 937 | // Convenience methods: |
mark.lam@apple.com | bb16769 | 2015-11-11 23:04:09 +0000 | [diff] [blame] | 938 | void*& gpr(RegisterID regID) { return cpu.gpr(regID); } |
| 939 | double& fpr(FPRegisterID regID) { return cpu.fpr(regID); } |
mark.lam@apple.com | 5bb8a12 | 2015-10-16 20:36:44 +0000 | [diff] [blame] | 940 | const char* gprName(RegisterID regID) { return cpu.gprName(regID); } |
| 941 | const char* fprName(FPRegisterID regID) { return cpu.fprName(regID); } |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 942 | }; |
| 943 | |
mark.lam@apple.com | 8b8b5fe | 2014-11-17 22:03:04 +0000 | [diff] [blame] | 944 | // This function emits code to preserve the CPUState (e.g. registers), |
| 945 | // call a user supplied probe function, and restore the CPUState before |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 946 | // continuing with other JIT generated code. |
| 947 | // |
| 948 | // The user supplied probe function will be called with a single pointer to |
| 949 | // a ProbeContext struct (defined above) which contains, among other things, |
mark.lam@apple.com | 8b8b5fe | 2014-11-17 22:03:04 +0000 | [diff] [blame] | 950 | // the preserved CPUState. This allows the user probe function to inspect |
| 951 | // the CPUState at that point in the JIT generated code. |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 952 | // |
| 953 | // If the user probe function alters the register values in the ProbeContext, |
| 954 | // the altered values will be loaded into the CPU registers when the probe |
| 955 | // returns. |
| 956 | // |
| 957 | // The ProbeContext is stack allocated and is only valid for the duration |
| 958 | // of the call to the user probe function. |
| 959 | // |
| 960 | // Note: probe() should be implemented by the target specific MacroAssembler. |
| 961 | // This prototype is only provided here to document the interface. |
| 962 | |
mark.lam@apple.com | a8e3a48 | 2015-10-28 22:59:03 +0000 | [diff] [blame] | 963 | void probe(ProbeFunction, void* arg1, void* arg2); |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 964 | |
| 965 | #endif // ENABLE(MASM_PROBE) |
| 966 | |
fpizlo@apple.com | 2e7ada0 | 2013-10-23 18:22:09 +0000 | [diff] [blame] | 967 | AssemblerType m_assembler; |
| 968 | |
fpizlo@apple.com | 7a79726 | 2015-09-03 21:11:59 +0000 | [diff] [blame] | 969 | static void linkJump(void* code, Jump jump, CodeLocationLabel target) |
| 970 | { |
| 971 | AssemblerType::linkJump(code, jump.m_label, target.dataLocation()); |
| 972 | } |
| 973 | |
| 974 | static void linkPointer(void* code, AssemblerLabel label, void* value) |
| 975 | { |
| 976 | AssemblerType::linkPointer(code, label, value); |
| 977 | } |
| 978 | |
| 979 | static void* getLinkerAddress(void* code, AssemblerLabel label) |
| 980 | { |
| 981 | return AssemblerType::getRelocatedAddress(code, label); |
| 982 | } |
| 983 | |
| 984 | static unsigned getLinkerCallReturnOffset(Call call) |
| 985 | { |
| 986 | return AssemblerType::getCallReturnOffset(call.m_label); |
| 987 | } |
| 988 | |
| 989 | static void repatchJump(CodeLocationJump jump, CodeLocationLabel destination) |
| 990 | { |
| 991 | AssemblerType::relinkJump(jump.dataLocation(), destination.dataLocation()); |
| 992 | } |
| 993 | |
| 994 | static void repatchNearCall(CodeLocationNearCall nearCall, CodeLocationLabel destination) |
| 995 | { |
msaboff@apple.com | c15ae7e | 2015-09-16 23:40:35 +0000 | [diff] [blame] | 996 | switch (nearCall.callMode()) { |
| 997 | case NearCallMode::Tail: |
commit-queue@webkit.org | c857681 | 2016-04-15 09:07:36 +0000 | [diff] [blame] | 998 | AssemblerType::relinkJump(nearCall.dataLocation(), destination.dataLocation()); |
msaboff@apple.com | c15ae7e | 2015-09-16 23:40:35 +0000 | [diff] [blame] | 999 | return; |
| 1000 | case NearCallMode::Regular: |
| 1001 | AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress()); |
| 1002 | return; |
| 1003 | } |
| 1004 | RELEASE_ASSERT_NOT_REACHED(); |
fpizlo@apple.com | 7a79726 | 2015-09-03 21:11:59 +0000 | [diff] [blame] | 1005 | } |
| 1006 | |
| 1007 | static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value) |
| 1008 | { |
| 1009 | AssemblerType::repatchCompact(dataLabelCompact.dataLocation(), value); |
| 1010 | } |
| 1011 | |
| 1012 | static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value) |
| 1013 | { |
| 1014 | AssemblerType::repatchInt32(dataLabel32.dataLocation(), value); |
| 1015 | } |
| 1016 | |
| 1017 | static void repatchPointer(CodeLocationDataLabelPtr dataLabelPtr, void* value) |
| 1018 | { |
| 1019 | AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value); |
| 1020 | } |
| 1021 | |
| 1022 | static void* readPointer(CodeLocationDataLabelPtr dataLabelPtr) |
| 1023 | { |
| 1024 | return AssemblerType::readPointer(dataLabelPtr.dataLocation()); |
| 1025 | } |
| 1026 | |
| 1027 | static void replaceWithLoad(CodeLocationConvertibleLoad label) |
| 1028 | { |
| 1029 | AssemblerType::replaceWithLoad(label.dataLocation()); |
| 1030 | } |
| 1031 | |
| 1032 | static void replaceWithAddressComputation(CodeLocationConvertibleLoad label) |
| 1033 | { |
| 1034 | AssemblerType::replaceWithAddressComputation(label.dataLocation()); |
| 1035 | } |
| 1036 | |
fpizlo@apple.com | 6e69796 | 2015-10-12 17:56:26 +0000 | [diff] [blame] | 1037 | template<typename Functor> |
| 1038 | void addLinkTask(const Functor& functor) |
| 1039 | { |
| 1040 | m_linkTasks.append(createSharedTask<void(LinkBuffer&)>(functor)); |
| 1041 | } |
| 1042 | |
barraclough@apple.com | 8c4ea6b | 2009-02-11 04:57:08 +0000 | [diff] [blame] | 1043 | protected: |
oliver@apple.com | d5c4868 | 2012-03-06 02:40:05 +0000 | [diff] [blame] | 1044 | AbstractMacroAssembler() |
commit-queue@webkit.org | 8f20787 | 2016-04-19 06:54:25 +0000 | [diff] [blame] | 1045 | : m_randomSource(0) |
oliver@apple.com | d5c4868 | 2012-03-06 02:40:05 +0000 | [diff] [blame] | 1046 | { |
msaboff@apple.com | 1d8f622 | 2014-03-04 06:38:09 +0000 | [diff] [blame] | 1047 | invalidateAllTempRegisters(); |
oliver@apple.com | d5c4868 | 2012-03-06 02:40:05 +0000 | [diff] [blame] | 1048 | } |
| 1049 | |
oliver@apple.com | d5c4868 | 2012-03-06 02:40:05 +0000 | [diff] [blame] | 1050 | uint32_t random() |
| 1051 | { |
commit-queue@webkit.org | 8f20787 | 2016-04-19 06:54:25 +0000 | [diff] [blame] | 1052 | if (!m_randomSourceIsInitialized) { |
| 1053 | m_randomSourceIsInitialized = true; |
| 1054 | m_randomSource.setSeed(cryptographicallyRandomNumber()); |
| 1055 | } |
oliver@apple.com | d5c4868 | 2012-03-06 02:40:05 +0000 | [diff] [blame] | 1056 | return m_randomSource.getUint32(); |
| 1057 | } |
| 1058 | |
commit-queue@webkit.org | 8f20787 | 2016-04-19 06:54:25 +0000 | [diff] [blame] | 1059 | bool m_randomSourceIsInitialized { false }; |
oliver@apple.com | d5c4868 | 2012-03-06 02:40:05 +0000 | [diff] [blame] | 1060 | WeakRandom m_randomSource; |
oliver@apple.com | 567de6f | 2012-03-08 22:29:09 +0000 | [diff] [blame] | 1061 | |
msaboff@apple.com | 278a60c | 2013-03-15 19:33:25 +0000 | [diff] [blame] | 1062 | #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION) |
| 1063 | Vector<RegisterAllocationOffset, 10> m_registerAllocationForOffsets; |
| 1064 | #endif |
| 1065 | |
fpizlo@apple.com | 0cd2462 | 2013-11-09 00:39:03 +0000 | [diff] [blame] | 1066 | static bool haveScratchRegisterForBlinding() |
| 1067 | { |
| 1068 | return false; |
| 1069 | } |
| 1070 | static RegisterID scratchRegisterForBlinding() |
| 1071 | { |
| 1072 | UNREACHABLE_FOR_PLATFORM(); |
| 1073 | return firstRegister(); |
| 1074 | } |
| 1075 | static bool canBlind() { return false; } |
| 1076 | static bool shouldBlindForSpecificArch(uint32_t) { return false; } |
| 1077 | static bool shouldBlindForSpecificArch(uint64_t) { return false; } |
oliver@apple.com | d5c4868 | 2012-03-06 02:40:05 +0000 | [diff] [blame] | 1078 | |
dbates@webkit.org | 98f0de0 | 2013-10-15 22:16:39 +0000 | [diff] [blame] | 1079 | class CachedTempRegister { |
| 1080 | friend class DataLabelPtr; |
| 1081 | friend class DataLabel32; |
| 1082 | friend class DataLabelCompact; |
| 1083 | friend class Jump; |
| 1084 | friend class Label; |
| 1085 | |
| 1086 | public: |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 1087 | CachedTempRegister(AbstractMacroAssemblerType* masm, RegisterID registerID) |
dbates@webkit.org | 98f0de0 | 2013-10-15 22:16:39 +0000 | [diff] [blame] | 1088 | : m_masm(masm) |
| 1089 | , m_registerID(registerID) |
| 1090 | , m_value(0) |
| 1091 | , m_validBit(1 << static_cast<unsigned>(registerID)) |
| 1092 | { |
| 1093 | ASSERT(static_cast<unsigned>(registerID) < (sizeof(unsigned) * 8)); |
| 1094 | } |
| 1095 | |
| 1096 | ALWAYS_INLINE RegisterID registerIDInvalidate() { invalidate(); return m_registerID; } |
| 1097 | |
| 1098 | ALWAYS_INLINE RegisterID registerIDNoInvalidate() { return m_registerID; } |
| 1099 | |
| 1100 | bool value(intptr_t& value) |
| 1101 | { |
| 1102 | value = m_value; |
| 1103 | return m_masm->isTempRegisterValid(m_validBit); |
| 1104 | } |
| 1105 | |
| 1106 | void setValue(intptr_t value) |
| 1107 | { |
| 1108 | m_value = value; |
| 1109 | m_masm->setTempRegisterValid(m_validBit); |
| 1110 | } |
| 1111 | |
| 1112 | ALWAYS_INLINE void invalidate() { m_masm->clearTempRegisterValid(m_validBit); } |
| 1113 | |
| 1114 | private: |
mark.lam@apple.com | 79a027b | 2014-11-14 20:24:55 +0000 | [diff] [blame] | 1115 | AbstractMacroAssemblerType* m_masm; |
dbates@webkit.org | 98f0de0 | 2013-10-15 22:16:39 +0000 | [diff] [blame] | 1116 | RegisterID m_registerID; |
| 1117 | intptr_t m_value; |
| 1118 | unsigned m_validBit; |
| 1119 | }; |
| 1120 | |
| 1121 | ALWAYS_INLINE void invalidateAllTempRegisters() |
| 1122 | { |
| 1123 | m_tempRegistersValidBits = 0; |
| 1124 | } |
| 1125 | |
| 1126 | ALWAYS_INLINE bool isTempRegisterValid(unsigned registerMask) |
| 1127 | { |
| 1128 | return (m_tempRegistersValidBits & registerMask); |
| 1129 | } |
| 1130 | |
| 1131 | ALWAYS_INLINE void clearTempRegisterValid(unsigned registerMask) |
| 1132 | { |
| 1133 | m_tempRegistersValidBits &= ~registerMask; |
| 1134 | } |
| 1135 | |
| 1136 | ALWAYS_INLINE void setTempRegisterValid(unsigned registerMask) |
| 1137 | { |
| 1138 | m_tempRegistersValidBits |= registerMask; |
| 1139 | } |
| 1140 | |
fpizlo@apple.com | d9a4e74 | 2015-11-30 20:07:18 +0000 | [diff] [blame] | 1141 | friend class AllowMacroScratchRegisterUsage; |
| 1142 | friend class DisallowMacroScratchRegisterUsage; |
dbates@webkit.org | 98f0de0 | 2013-10-15 22:16:39 +0000 | [diff] [blame] | 1143 | unsigned m_tempRegistersValidBits; |
fpizlo@apple.com | d9a4e74 | 2015-11-30 20:07:18 +0000 | [diff] [blame] | 1144 | bool m_allowScratchRegister { true }; |
dbates@webkit.org | 98f0de0 | 2013-10-15 22:16:39 +0000 | [diff] [blame] | 1145 | |
fpizlo@apple.com | 6e69796 | 2015-10-12 17:56:26 +0000 | [diff] [blame] | 1146 | Vector<RefPtr<SharedTask<void(LinkBuffer&)>>> m_linkTasks; |
| 1147 | |
barraclough@apple.com | ba92ede | 2009-07-22 00:37:03 +0000 | [diff] [blame] | 1148 | friend class LinkBuffer; |
mark.lam@apple.com | 8b8b5fe | 2014-11-17 22:03:04 +0000 | [diff] [blame] | 1149 | }; // class AbstractMacroAssembler |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 1150 | |
fpizlo@apple.com | f41fc90 | 2016-04-23 02:00:38 +0000 | [diff] [blame] | 1151 | template <class AssemblerType, class MacroAssemblerType> |
| 1152 | inline typename AbstractMacroAssembler<AssemblerType, MacroAssemblerType>::BaseIndex |
| 1153 | AbstractMacroAssembler<AssemblerType, MacroAssemblerType>::Address::indexedBy( |
| 1154 | typename AbstractMacroAssembler<AssemblerType, MacroAssemblerType>::RegisterID index, |
| 1155 | typename AbstractMacroAssembler<AssemblerType, MacroAssemblerType>::Scale scale) const |
| 1156 | { |
| 1157 | return BaseIndex(base, index, scale, offset); |
| 1158 | } |
| 1159 | |
barraclough@apple.com | a36d999 | 2009-02-05 03:40:39 +0000 | [diff] [blame] | 1160 | } // namespace JSC |
| 1161 | |
| 1162 | #endif // ENABLE(ASSEMBLER) |
| 1163 | |
| 1164 | #endif // AbstractMacroAssembler_h |