OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_ARM64_ASSEMBLER_ARM64_H_ | 5 #ifndef V8_ARM64_ASSEMBLER_ARM64_H_ |
6 #define V8_ARM64_ASSEMBLER_ARM64_H_ | 6 #define V8_ARM64_ASSEMBLER_ARM64_H_ |
7 | 7 |
8 #include <deque> | 8 #include <deque> |
9 #include <list> | 9 #include <list> |
10 #include <map> | 10 #include <map> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "src/arm64/instructions-arm64.h" | 13 #include "src/arm64/instructions-arm64.h" |
14 #include "src/assembler.h" | 14 #include "src/assembler.h" |
15 #include "src/compiler.h" | 15 #include "src/compiler.h" |
16 #include "src/globals.h" | 16 #include "src/globals.h" |
17 #include "src/utils.h" | 17 #include "src/utils.h" |
18 | 18 |
19 | 19 |
20 namespace v8 { | 20 namespace v8 { |
21 namespace internal { | 21 namespace internal { |
22 | 22 |
23 | 23 |
24 // ----------------------------------------------------------------------------- | 24 // ----------------------------------------------------------------------------- |
25 // Registers. | 25 // Registers. |
26 // clang-format off | 26 #define REGISTER_CODE_LIST(R) \ |
27 #define GENERAL_REGISTER_CODE_LIST(R) \ | 27 R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \ |
28 R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \ | 28 R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \ |
29 R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \ | 29 R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \ |
30 R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \ | 30 R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31) |
31 R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31) | |
32 | 31 |
33 #define GENERAL_REGISTERS(R) \ | |
34 R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \ | |
35 R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \ | |
36 R(x16) R(x17) R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) \ | |
37 R(x24) R(x25) R(x26) R(x27) R(x28) R(x29) R(x30) R(x31) | |
38 | |
39 #define ALLOCATABLE_GENERAL_REGISTERS(R) \ | |
40 R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \ | |
41 R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \ | |
42 R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) R(x24) R(x27) | |
43 | |
44 #define DOUBLE_REGISTERS(R) \ | |
45 R(d0) R(d1) R(d2) R(d3) R(d4) R(d5) R(d6) R(d7) \ | |
46 R(d8) R(d9) R(d10) R(d11) R(d12) R(d13) R(d14) R(d15) \ | |
47 R(d16) R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) \ | |
48 R(d24) R(d25) R(d26) R(d27) R(d28) R(d29) R(d30) R(d31) | |
49 | |
50 #define ALLOCATABLE_DOUBLE_REGISTERS(R) \ | |
51 R(d0) R(d1) R(d2) R(d3) R(d4) R(d5) R(d6) R(d7) \ | |
52 R(d8) R(d9) R(d10) R(d11) R(d12) R(d13) R(d14) R(d16) \ | |
53 R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) R(d24) \ | |
54 R(d25) R(d26) R(d27) R(d28) | |
55 // clang-format on | |
56 | 32 |
57 static const int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte; | 33 static const int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte; |
58 | 34 |
59 | 35 |
60 // Some CPURegister methods can return Register and FPRegister types, so we | 36 // Some CPURegister methods can return Register and FPRegister types, so we |
61 // need to declare them in advance. | 37 // need to declare them in advance. |
62 struct Register; | 38 struct Register; |
63 struct FPRegister; | 39 struct FPRegister; |
64 | 40 |
65 | 41 |
66 struct CPURegister { | 42 struct CPURegister { |
67 enum Code { | |
68 #define REGISTER_CODE(R) kCode_##R, | |
69 GENERAL_REGISTERS(REGISTER_CODE) | |
70 #undef REGISTER_CODE | |
71 kAfterLast, | |
72 kCode_no_reg = -1 | |
73 }; | |
74 | |
75 enum RegisterType { | 43 enum RegisterType { |
76 // The kInvalid value is used to detect uninitialized static instances, | 44 // The kInvalid value is used to detect uninitialized static instances, |
77 // which are always zero-initialized before any constructors are called. | 45 // which are always zero-initialized before any constructors are called. |
78 kInvalid = 0, | 46 kInvalid = 0, |
79 kRegister, | 47 kRegister, |
80 kFPRegister, | 48 kFPRegister, |
81 kNoRegister | 49 kNoRegister |
82 }; | 50 }; |
83 | 51 |
84 static CPURegister Create(unsigned code, unsigned size, RegisterType type) { | 52 static CPURegister Create(unsigned code, unsigned size, RegisterType type) { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 DCHECK(IsValidOrNone()); | 110 DCHECK(IsValidOrNone()); |
143 } | 111 } |
144 | 112 |
145 Register(const Register& r) { // NOLINT(runtime/explicit) | 113 Register(const Register& r) { // NOLINT(runtime/explicit) |
146 reg_code = r.reg_code; | 114 reg_code = r.reg_code; |
147 reg_size = r.reg_size; | 115 reg_size = r.reg_size; |
148 reg_type = r.reg_type; | 116 reg_type = r.reg_type; |
149 DCHECK(IsValidOrNone()); | 117 DCHECK(IsValidOrNone()); |
150 } | 118 } |
151 | 119 |
152 const char* ToString(); | |
153 bool IsAllocatable() const; | |
154 bool IsValid() const { | 120 bool IsValid() const { |
155 DCHECK(IsRegister() || IsNone()); | 121 DCHECK(IsRegister() || IsNone()); |
156 return IsValidRegister(); | 122 return IsValidRegister(); |
157 } | 123 } |
158 | 124 |
159 static Register XRegFromCode(unsigned code); | 125 static Register XRegFromCode(unsigned code); |
160 static Register WRegFromCode(unsigned code); | 126 static Register WRegFromCode(unsigned code); |
161 | 127 |
162 // Start of V8 compatibility section --------------------- | 128 // Start of V8 compatibility section --------------------- |
163 // These memebers are necessary for compilation. | 129 // These memebers are necessary for compilation. |
164 // A few of them may be unused for now. | 130 // A few of them may be unused for now. |
165 | 131 |
166 static const int kNumRegisters = kNumberOfRegisters; | 132 static const int kNumRegisters = kNumberOfRegisters; |
167 STATIC_ASSERT(kNumRegisters == Code::kAfterLast); | |
168 static int NumRegisters() { return kNumRegisters; } | 133 static int NumRegisters() { return kNumRegisters; } |
169 | 134 |
170 // We allow crankshaft to use the following registers: | 135 // We allow crankshaft to use the following registers: |
171 // - x0 to x15 | 136 // - x0 to x15 |
172 // - x18 to x24 | 137 // - x18 to x24 |
173 // - x27 (also context) | 138 // - x27 (also context) |
174 // | 139 // |
175 // TODO(all): Register x25 is currently free and could be available for | 140 // TODO(all): Register x25 is currently free and could be available for |
176 // crankshaft, but we don't use it as we might use it as a per function | 141 // crankshaft, but we don't use it as we might use it as a per function |
177 // literal pool pointer in the future. | 142 // literal pool pointer in the future. |
178 // | 143 // |
179 // TODO(all): Consider storing cp in x25 to have only two ranges. | 144 // TODO(all): Consider storing cp in x25 to have only two ranges. |
180 // We split allocatable registers in three ranges called | 145 // We split allocatable registers in three ranges called |
181 // - "low range" | 146 // - "low range" |
182 // - "high range" | 147 // - "high range" |
183 // - "context" | 148 // - "context" |
| 149 static const unsigned kAllocatableLowRangeBegin = 0; |
| 150 static const unsigned kAllocatableLowRangeEnd = 15; |
| 151 static const unsigned kAllocatableHighRangeBegin = 18; |
| 152 static const unsigned kAllocatableHighRangeEnd = 24; |
| 153 static const unsigned kAllocatableContext = 27; |
| 154 |
| 155 // Gap between low and high ranges. |
| 156 static const int kAllocatableRangeGapSize = |
| 157 (kAllocatableHighRangeBegin - kAllocatableLowRangeEnd) - 1; |
| 158 |
| 159 static const int kMaxNumAllocatableRegisters = |
| 160 (kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1) + |
| 161 (kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1) + 1; // cp |
| 162 static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; } |
| 163 |
| 164 // Return true if the register is one that crankshaft can allocate. |
| 165 bool IsAllocatable() const { |
| 166 return ((reg_code == kAllocatableContext) || |
| 167 (reg_code <= kAllocatableLowRangeEnd) || |
| 168 ((reg_code >= kAllocatableHighRangeBegin) && |
| 169 (reg_code <= kAllocatableHighRangeEnd))); |
| 170 } |
| 171 |
| 172 static Register FromAllocationIndex(unsigned index) { |
| 173 DCHECK(index < static_cast<unsigned>(NumAllocatableRegisters())); |
| 174 // cp is the last allocatable register. |
| 175 if (index == (static_cast<unsigned>(NumAllocatableRegisters() - 1))) { |
| 176 return from_code(kAllocatableContext); |
| 177 } |
| 178 |
| 179 // Handle low and high ranges. |
| 180 return (index <= kAllocatableLowRangeEnd) |
| 181 ? from_code(index) |
| 182 : from_code(index + kAllocatableRangeGapSize); |
| 183 } |
| 184 |
| 185 static const char* AllocationIndexToString(int index) { |
| 186 DCHECK((index >= 0) && (index < NumAllocatableRegisters())); |
| 187 DCHECK((kAllocatableLowRangeBegin == 0) && |
| 188 (kAllocatableLowRangeEnd == 15) && |
| 189 (kAllocatableHighRangeBegin == 18) && |
| 190 (kAllocatableHighRangeEnd == 24) && |
| 191 (kAllocatableContext == 27)); |
| 192 const char* const names[] = { |
| 193 "x0", "x1", "x2", "x3", "x4", |
| 194 "x5", "x6", "x7", "x8", "x9", |
| 195 "x10", "x11", "x12", "x13", "x14", |
| 196 "x15", "x18", "x19", "x20", "x21", |
| 197 "x22", "x23", "x24", "x27", |
| 198 }; |
| 199 return names[index]; |
| 200 } |
| 201 |
| 202 static int ToAllocationIndex(Register reg) { |
| 203 DCHECK(reg.IsAllocatable()); |
| 204 unsigned code = reg.code(); |
| 205 if (code == kAllocatableContext) { |
| 206 return NumAllocatableRegisters() - 1; |
| 207 } |
| 208 |
| 209 return (code <= kAllocatableLowRangeEnd) |
| 210 ? code |
| 211 : code - kAllocatableRangeGapSize; |
| 212 } |
184 | 213 |
185 static Register from_code(int code) { | 214 static Register from_code(int code) { |
186 // Always return an X register. | 215 // Always return an X register. |
187 return Register::Create(code, kXRegSizeInBits); | 216 return Register::Create(code, kXRegSizeInBits); |
188 } | 217 } |
189 | 218 |
190 // End of V8 compatibility section ----------------------- | 219 // End of V8 compatibility section ----------------------- |
191 }; | 220 }; |
192 | 221 |
193 | 222 |
194 struct FPRegister : public CPURegister { | 223 struct FPRegister : public CPURegister { |
195 enum Code { | |
196 #define REGISTER_CODE(R) kCode_##R, | |
197 DOUBLE_REGISTERS(REGISTER_CODE) | |
198 #undef REGISTER_CODE | |
199 kAfterLast, | |
200 kCode_no_reg = -1 | |
201 }; | |
202 | |
203 static FPRegister Create(unsigned code, unsigned size) { | 224 static FPRegister Create(unsigned code, unsigned size) { |
204 return FPRegister( | 225 return FPRegister( |
205 CPURegister::Create(code, size, CPURegister::kFPRegister)); | 226 CPURegister::Create(code, size, CPURegister::kFPRegister)); |
206 } | 227 } |
207 | 228 |
208 FPRegister() { | 229 FPRegister() { |
209 reg_code = 0; | 230 reg_code = 0; |
210 reg_size = 0; | 231 reg_size = 0; |
211 reg_type = CPURegister::kNoRegister; | 232 reg_type = CPURegister::kNoRegister; |
212 } | 233 } |
213 | 234 |
214 explicit FPRegister(const CPURegister& r) { | 235 explicit FPRegister(const CPURegister& r) { |
215 reg_code = r.reg_code; | 236 reg_code = r.reg_code; |
216 reg_size = r.reg_size; | 237 reg_size = r.reg_size; |
217 reg_type = r.reg_type; | 238 reg_type = r.reg_type; |
218 DCHECK(IsValidOrNone()); | 239 DCHECK(IsValidOrNone()); |
219 } | 240 } |
220 | 241 |
221 FPRegister(const FPRegister& r) { // NOLINT(runtime/explicit) | 242 FPRegister(const FPRegister& r) { // NOLINT(runtime/explicit) |
222 reg_code = r.reg_code; | 243 reg_code = r.reg_code; |
223 reg_size = r.reg_size; | 244 reg_size = r.reg_size; |
224 reg_type = r.reg_type; | 245 reg_type = r.reg_type; |
225 DCHECK(IsValidOrNone()); | 246 DCHECK(IsValidOrNone()); |
226 } | 247 } |
227 | 248 |
228 const char* ToString(); | |
229 bool IsAllocatable() const; | |
230 bool IsValid() const { | 249 bool IsValid() const { |
231 DCHECK(IsFPRegister() || IsNone()); | 250 DCHECK(IsFPRegister() || IsNone()); |
232 return IsValidFPRegister(); | 251 return IsValidFPRegister(); |
233 } | 252 } |
234 | 253 |
235 static FPRegister SRegFromCode(unsigned code); | 254 static FPRegister SRegFromCode(unsigned code); |
236 static FPRegister DRegFromCode(unsigned code); | 255 static FPRegister DRegFromCode(unsigned code); |
237 | 256 |
238 // Start of V8 compatibility section --------------------- | 257 // Start of V8 compatibility section --------------------- |
239 static const int kMaxNumRegisters = kNumberOfFPRegisters; | 258 static const int kMaxNumRegisters = kNumberOfFPRegisters; |
240 STATIC_ASSERT(kMaxNumRegisters == Code::kAfterLast); | |
241 | 259 |
242 // Crankshaft can use all the FP registers except: | 260 // Crankshaft can use all the FP registers except: |
243 // - d15 which is used to keep the 0 double value | 261 // - d15 which is used to keep the 0 double value |
244 // - d30 which is used in crankshaft as a double scratch register | 262 // - d30 which is used in crankshaft as a double scratch register |
245 // - d31 which is used in the MacroAssembler as a double scratch register | 263 // - d31 which is used in the MacroAssembler as a double scratch register |
| 264 static const unsigned kAllocatableLowRangeBegin = 0; |
| 265 static const unsigned kAllocatableLowRangeEnd = 14; |
| 266 static const unsigned kAllocatableHighRangeBegin = 16; |
| 267 static const unsigned kAllocatableHighRangeEnd = 28; |
| 268 |
| 269 static const RegList kAllocatableFPRegisters = 0x1fff7fff; |
| 270 |
| 271 // Gap between low and high ranges. |
| 272 static const int kAllocatableRangeGapSize = |
| 273 (kAllocatableHighRangeBegin - kAllocatableLowRangeEnd) - 1; |
| 274 |
| 275 static const int kMaxNumAllocatableRegisters = |
| 276 (kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1) + |
| 277 (kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1); |
| 278 static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; } |
| 279 |
| 280 // TODO(turbofan): Proper float32 support. |
| 281 static int NumAllocatableAliasedRegisters() { |
| 282 return NumAllocatableRegisters(); |
| 283 } |
| 284 |
| 285 // Return true if the register is one that crankshaft can allocate. |
| 286 bool IsAllocatable() const { |
| 287 return (Bit() & kAllocatableFPRegisters) != 0; |
| 288 } |
| 289 |
| 290 static FPRegister FromAllocationIndex(unsigned int index) { |
| 291 DCHECK(index < static_cast<unsigned>(NumAllocatableRegisters())); |
| 292 |
| 293 return (index <= kAllocatableLowRangeEnd) |
| 294 ? from_code(index) |
| 295 : from_code(index + kAllocatableRangeGapSize); |
| 296 } |
| 297 |
| 298 static const char* AllocationIndexToString(int index) { |
| 299 DCHECK((index >= 0) && (index < NumAllocatableRegisters())); |
| 300 DCHECK((kAllocatableLowRangeBegin == 0) && |
| 301 (kAllocatableLowRangeEnd == 14) && |
| 302 (kAllocatableHighRangeBegin == 16) && |
| 303 (kAllocatableHighRangeEnd == 28)); |
| 304 const char* const names[] = { |
| 305 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", |
| 306 "d8", "d9", "d10", "d11", "d12", "d13", "d14", |
| 307 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", |
| 308 "d24", "d25", "d26", "d27", "d28" |
| 309 }; |
| 310 return names[index]; |
| 311 } |
| 312 |
| 313 static int ToAllocationIndex(FPRegister reg) { |
| 314 DCHECK(reg.IsAllocatable()); |
| 315 unsigned code = reg.code(); |
| 316 |
| 317 return (code <= kAllocatableLowRangeEnd) |
| 318 ? code |
| 319 : code - kAllocatableRangeGapSize; |
| 320 } |
| 321 |
246 static FPRegister from_code(int code) { | 322 static FPRegister from_code(int code) { |
247 // Always return a D register. | 323 // Always return a D register. |
248 return FPRegister::Create(code, kDRegSizeInBits); | 324 return FPRegister::Create(code, kDRegSizeInBits); |
249 } | 325 } |
250 // End of V8 compatibility section ----------------------- | 326 // End of V8 compatibility section ----------------------- |
251 }; | 327 }; |
252 | 328 |
253 | 329 |
254 STATIC_ASSERT(sizeof(CPURegister) == sizeof(Register)); | 330 STATIC_ASSERT(sizeof(CPURegister) == sizeof(Register)); |
255 STATIC_ASSERT(sizeof(CPURegister) == sizeof(FPRegister)); | 331 STATIC_ASSERT(sizeof(CPURegister) == sizeof(FPRegister)); |
(...skipping 22 matching lines...) Expand all Loading... |
278 INITIALIZE_REGISTER(CPURegister, NoCPUReg, 0, 0, CPURegister::kNoRegister); | 354 INITIALIZE_REGISTER(CPURegister, NoCPUReg, 0, 0, CPURegister::kNoRegister); |
279 | 355 |
280 // v8 compatibility. | 356 // v8 compatibility. |
281 INITIALIZE_REGISTER(Register, no_reg, 0, 0, CPURegister::kNoRegister); | 357 INITIALIZE_REGISTER(Register, no_reg, 0, 0, CPURegister::kNoRegister); |
282 | 358 |
283 #define DEFINE_REGISTERS(N) \ | 359 #define DEFINE_REGISTERS(N) \ |
284 INITIALIZE_REGISTER(Register, w##N, N, \ | 360 INITIALIZE_REGISTER(Register, w##N, N, \ |
285 kWRegSizeInBits, CPURegister::kRegister); \ | 361 kWRegSizeInBits, CPURegister::kRegister); \ |
286 INITIALIZE_REGISTER(Register, x##N, N, \ | 362 INITIALIZE_REGISTER(Register, x##N, N, \ |
287 kXRegSizeInBits, CPURegister::kRegister); | 363 kXRegSizeInBits, CPURegister::kRegister); |
288 GENERAL_REGISTER_CODE_LIST(DEFINE_REGISTERS) | 364 REGISTER_CODE_LIST(DEFINE_REGISTERS) |
289 #undef DEFINE_REGISTERS | 365 #undef DEFINE_REGISTERS |
290 | 366 |
291 INITIALIZE_REGISTER(Register, wcsp, kSPRegInternalCode, kWRegSizeInBits, | 367 INITIALIZE_REGISTER(Register, wcsp, kSPRegInternalCode, kWRegSizeInBits, |
292 CPURegister::kRegister); | 368 CPURegister::kRegister); |
293 INITIALIZE_REGISTER(Register, csp, kSPRegInternalCode, kXRegSizeInBits, | 369 INITIALIZE_REGISTER(Register, csp, kSPRegInternalCode, kXRegSizeInBits, |
294 CPURegister::kRegister); | 370 CPURegister::kRegister); |
295 | 371 |
296 #define DEFINE_FPREGISTERS(N) \ | 372 #define DEFINE_FPREGISTERS(N) \ |
297 INITIALIZE_REGISTER(FPRegister, s##N, N, \ | 373 INITIALIZE_REGISTER(FPRegister, s##N, N, \ |
298 kSRegSizeInBits, CPURegister::kFPRegister); \ | 374 kSRegSizeInBits, CPURegister::kFPRegister); \ |
299 INITIALIZE_REGISTER(FPRegister, d##N, N, \ | 375 INITIALIZE_REGISTER(FPRegister, d##N, N, \ |
300 kDRegSizeInBits, CPURegister::kFPRegister); | 376 kDRegSizeInBits, CPURegister::kFPRegister); |
301 GENERAL_REGISTER_CODE_LIST(DEFINE_FPREGISTERS) | 377 REGISTER_CODE_LIST(DEFINE_FPREGISTERS) |
302 #undef DEFINE_FPREGISTERS | 378 #undef DEFINE_FPREGISTERS |
303 | 379 |
304 #undef INITIALIZE_REGISTER | 380 #undef INITIALIZE_REGISTER |
305 | 381 |
306 // Registers aliases. | 382 // Registers aliases. |
307 ALIAS_REGISTER(Register, ip0, x16); | 383 ALIAS_REGISTER(Register, ip0, x16); |
308 ALIAS_REGISTER(Register, ip1, x17); | 384 ALIAS_REGISTER(Register, ip1, x17); |
309 ALIAS_REGISTER(Register, wip0, w16); | 385 ALIAS_REGISTER(Register, wip0, w16); |
310 ALIAS_REGISTER(Register, wip1, w17); | 386 ALIAS_REGISTER(Register, wip1, w17); |
311 // Root register. | 387 // Root register. |
(...skipping 1905 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2217 public: | 2293 public: |
2218 explicit EnsureSpace(Assembler* assembler) { | 2294 explicit EnsureSpace(Assembler* assembler) { |
2219 assembler->CheckBufferSpace(); | 2295 assembler->CheckBufferSpace(); |
2220 } | 2296 } |
2221 }; | 2297 }; |
2222 | 2298 |
2223 } // namespace internal | 2299 } // namespace internal |
2224 } // namespace v8 | 2300 } // namespace v8 |
2225 | 2301 |
2226 #endif // V8_ARM64_ASSEMBLER_ARM64_H_ | 2302 #endif // V8_ARM64_ASSEMBLER_ARM64_H_ |
OLD | NEW |