]>
Commit | Line | Data |
---|---|---|
ba379fdc A |
1 | /* |
2 | * Copyright (C) 2008 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 | #ifndef AbstractMacroAssembler_h | |
27 | #define AbstractMacroAssembler_h | |
28 | ||
6fe7ccc8 | 29 | #include "AssemblerBuffer.h" |
14957cd0 A |
30 | #include "CodeLocation.h" |
31 | #include "MacroAssemblerCodeRef.h" | |
6fe7ccc8 | 32 | #include <wtf/CryptographicallyRandomNumber.h> |
ba379fdc A |
33 | #include <wtf/Noncopyable.h> |
34 | #include <wtf/UnusedParam.h> | |
35 | ||
36 | #if ENABLE(ASSEMBLER) | |
37 | ||
6fe7ccc8 A |
38 | |
39 | #if PLATFORM(QT) | |
40 | #define ENABLE_JIT_CONSTANT_BLINDING 0 | |
41 | #endif | |
42 | ||
43 | #ifndef ENABLE_JIT_CONSTANT_BLINDING | |
44 | #define ENABLE_JIT_CONSTANT_BLINDING 1 | |
45 | #endif | |
46 | ||
ba379fdc A |
47 | namespace JSC { |
48 | ||
49 | class LinkBuffer; | |
50 | class RepatchBuffer; | |
6fe7ccc8 A |
51 | namespace DFG { |
52 | class CorrectableJumpPoint; | |
53 | } | |
ba379fdc A |
54 | |
55 | template <class AssemblerType> | |
56 | class AbstractMacroAssembler { | |
57 | public: | |
14957cd0 | 58 | friend class JITWriteBarrierBase; |
ba379fdc A |
59 | typedef AssemblerType AssemblerType_T; |
60 | ||
61 | typedef MacroAssemblerCodePtr CodePtr; | |
62 | typedef MacroAssemblerCodeRef CodeRef; | |
63 | ||
64 | class Jump; | |
65 | ||
66 | typedef typename AssemblerType::RegisterID RegisterID; | |
ba379fdc A |
67 | |
68 | // Section 1: MacroAssembler operand types | |
69 | // | |
70 | // The following types are used as operands to MacroAssembler operations, | |
71 | // describing immediate and memory operands to the instructions to be planted. | |
72 | ||
73 | ||
74 | enum Scale { | |
75 | TimesOne, | |
76 | TimesTwo, | |
77 | TimesFour, | |
78 | TimesEight, | |
79 | }; | |
80 | ||
81 | // Address: | |
82 | // | |
83 | // Describes a simple base-offset address. | |
84 | struct Address { | |
85 | explicit Address(RegisterID base, int32_t offset = 0) | |
86 | : base(base) | |
87 | , offset(offset) | |
88 | { | |
89 | } | |
90 | ||
91 | RegisterID base; | |
92 | int32_t offset; | |
93 | }; | |
94 | ||
4e4e5a6f A |
95 | struct ExtendedAddress { |
96 | explicit ExtendedAddress(RegisterID base, intptr_t offset = 0) | |
97 | : base(base) | |
98 | , offset(offset) | |
99 | { | |
100 | } | |
101 | ||
102 | RegisterID base; | |
103 | intptr_t offset; | |
104 | }; | |
105 | ||
ba379fdc A |
106 | // ImplicitAddress: |
107 | // | |
108 | // This class is used for explicit 'load' and 'store' operations | |
109 | // (as opposed to situations in which a memory operand is provided | |
110 | // to a generic operation, such as an integer arithmetic instruction). | |
111 | // | |
112 | // In the case of a load (or store) operation we want to permit | |
113 | // addresses to be implicitly constructed, e.g. the two calls: | |
114 | // | |
115 | // load32(Address(addrReg), destReg); | |
116 | // load32(addrReg, destReg); | |
117 | // | |
118 | // Are equivalent, and the explicit wrapping of the Address in the former | |
119 | // is unnecessary. | |
120 | struct ImplicitAddress { | |
121 | ImplicitAddress(RegisterID base) | |
122 | : base(base) | |
123 | , offset(0) | |
124 | { | |
125 | } | |
126 | ||
127 | ImplicitAddress(Address address) | |
128 | : base(address.base) | |
129 | , offset(address.offset) | |
130 | { | |
131 | } | |
132 | ||
133 | RegisterID base; | |
134 | int32_t offset; | |
135 | }; | |
136 | ||
137 | // BaseIndex: | |
138 | // | |
139 | // Describes a complex addressing mode. | |
140 | struct BaseIndex { | |
141 | BaseIndex(RegisterID base, RegisterID index, Scale scale, int32_t offset = 0) | |
142 | : base(base) | |
143 | , index(index) | |
144 | , scale(scale) | |
145 | , offset(offset) | |
146 | { | |
147 | } | |
148 | ||
149 | RegisterID base; | |
150 | RegisterID index; | |
151 | Scale scale; | |
152 | int32_t offset; | |
153 | }; | |
154 | ||
155 | // AbsoluteAddress: | |
156 | // | |
157 | // Describes an memory operand given by a pointer. For regular load & store | |
158 | // operations an unwrapped void* will be used, rather than using this. | |
159 | struct AbsoluteAddress { | |
14957cd0 | 160 | explicit AbsoluteAddress(const void* ptr) |
ba379fdc A |
161 | : m_ptr(ptr) |
162 | { | |
163 | } | |
164 | ||
14957cd0 | 165 | const void* m_ptr; |
ba379fdc A |
166 | }; |
167 | ||
14957cd0 | 168 | // TrustedImmPtr: |
ba379fdc A |
169 | // |
170 | // A pointer sized immediate operand to an instruction - this is wrapped | |
171 | // in a class requiring explicit construction in order to differentiate | |
172 | // from pointers used as absolute addresses to memory operations | |
14957cd0 A |
173 | struct TrustedImmPtr { |
174 | explicit TrustedImmPtr(const void* value) | |
ba379fdc A |
175 | : m_value(value) |
176 | { | |
177 | } | |
6fe7ccc8 A |
178 | |
179 | // This is only here so that TrustedImmPtr(0) does not confuse the C++ | |
180 | // overload handling rules. | |
181 | explicit TrustedImmPtr(int value) | |
182 | : m_value(0) | |
183 | { | |
184 | ASSERT_UNUSED(value, !value); | |
185 | } | |
186 | ||
187 | explicit TrustedImmPtr(size_t value) | |
188 | : m_value(reinterpret_cast<void*>(value)) | |
189 | { | |
190 | } | |
ba379fdc A |
191 | |
192 | intptr_t asIntptr() | |
193 | { | |
194 | return reinterpret_cast<intptr_t>(m_value); | |
195 | } | |
196 | ||
4e4e5a6f | 197 | const void* m_value; |
ba379fdc A |
198 | }; |
199 | ||
6fe7ccc8 A |
200 | struct ImmPtr : |
201 | #if ENABLE(JIT_CONSTANT_BLINDING) | |
202 | private TrustedImmPtr | |
203 | #else | |
204 | public TrustedImmPtr | |
205 | #endif | |
206 | { | |
14957cd0 A |
207 | explicit ImmPtr(const void* value) |
208 | : TrustedImmPtr(value) | |
209 | { | |
210 | } | |
6fe7ccc8 A |
211 | |
212 | TrustedImmPtr asTrustedImmPtr() { return *this; } | |
14957cd0 A |
213 | }; |
214 | ||
215 | // TrustedImm32: | |
ba379fdc A |
216 | // |
217 | // A 32bit immediate operand to an instruction - this is wrapped in a | |
218 | // class requiring explicit construction in order to prevent RegisterIDs | |
219 | // (which are implemented as an enum) from accidentally being passed as | |
220 | // immediate values. | |
14957cd0 A |
221 | struct TrustedImm32 { |
222 | explicit TrustedImm32(int32_t value) | |
ba379fdc | 223 | : m_value(value) |
4e4e5a6f | 224 | #if CPU(ARM) || CPU(MIPS) |
ba379fdc A |
225 | , m_isPointer(false) |
226 | #endif | |
227 | { | |
228 | } | |
229 | ||
f9bf01c6 | 230 | #if !CPU(X86_64) |
14957cd0 | 231 | explicit TrustedImm32(TrustedImmPtr ptr) |
ba379fdc | 232 | : m_value(ptr.asIntptr()) |
4e4e5a6f | 233 | #if CPU(ARM) || CPU(MIPS) |
ba379fdc A |
234 | , m_isPointer(true) |
235 | #endif | |
236 | { | |
237 | } | |
238 | #endif | |
239 | ||
240 | int32_t m_value; | |
4e4e5a6f | 241 | #if CPU(ARM) || CPU(MIPS) |
ba379fdc A |
242 | // We rely on being able to regenerate code to recover exception handling |
243 | // information. Since ARMv7 supports 16-bit immediates there is a danger | |
244 | // that if pointer values change the layout of the generated code will change. | |
245 | // To avoid this problem, always generate pointers (and thus Imm32s constructed | |
246 | // from ImmPtrs) with a code sequence that is able to represent any pointer | |
247 | // value - don't use a more compact form in these cases. | |
4e4e5a6f | 248 | // Same for MIPS. |
ba379fdc A |
249 | bool m_isPointer; |
250 | #endif | |
251 | }; | |
252 | ||
253 | ||
6fe7ccc8 A |
254 | struct Imm32 : |
255 | #if ENABLE(JIT_CONSTANT_BLINDING) | |
256 | private TrustedImm32 | |
257 | #else | |
258 | public TrustedImm32 | |
259 | #endif | |
260 | { | |
14957cd0 A |
261 | explicit Imm32(int32_t value) |
262 | : TrustedImm32(value) | |
263 | { | |
264 | } | |
265 | #if !CPU(X86_64) | |
266 | explicit Imm32(TrustedImmPtr ptr) | |
267 | : TrustedImm32(ptr) | |
268 | { | |
269 | } | |
270 | #endif | |
6fe7ccc8 A |
271 | const TrustedImm32& asTrustedImm32() const { return *this; } |
272 | ||
14957cd0 A |
273 | }; |
274 | ||
ba379fdc A |
275 | // Section 2: MacroAssembler code buffer handles |
276 | // | |
277 | // The following types are used to reference items in the code buffer | |
278 | // during JIT code generation. For example, the type Jump is used to | |
279 | // track the location of a jump instruction so that it may later be | |
280 | // linked to a label marking its destination. | |
281 | ||
282 | ||
283 | // Label: | |
284 | // | |
285 | // A Label records a point in the generated instruction stream, typically such that | |
286 | // it may be used as a destination for a jump. | |
287 | class Label { | |
288 | template<class TemplateAssemblerType> | |
289 | friend class AbstractMacroAssembler; | |
6fe7ccc8 | 290 | friend class DFG::CorrectableJumpPoint; |
ba379fdc A |
291 | friend class Jump; |
292 | friend class MacroAssemblerCodeRef; | |
293 | friend class LinkBuffer; | |
294 | ||
295 | public: | |
296 | Label() | |
297 | { | |
298 | } | |
299 | ||
300 | Label(AbstractMacroAssembler<AssemblerType>* masm) | |
301 | : m_label(masm->m_assembler.label()) | |
302 | { | |
303 | } | |
304 | ||
14957cd0 | 305 | bool isSet() const { return m_label.isSet(); } |
ba379fdc | 306 | private: |
14957cd0 | 307 | AssemblerLabel m_label; |
ba379fdc A |
308 | }; |
309 | ||
310 | // DataLabelPtr: | |
311 | // | |
312 | // A DataLabelPtr is used to refer to a location in the code containing a pointer to be | |
313 | // patched after the code has been generated. | |
314 | class DataLabelPtr { | |
315 | template<class TemplateAssemblerType> | |
316 | friend class AbstractMacroAssembler; | |
317 | friend class LinkBuffer; | |
318 | public: | |
319 | DataLabelPtr() | |
320 | { | |
321 | } | |
322 | ||
323 | DataLabelPtr(AbstractMacroAssembler<AssemblerType>* masm) | |
324 | : m_label(masm->m_assembler.label()) | |
325 | { | |
326 | } | |
327 | ||
14957cd0 A |
328 | bool isSet() const { return m_label.isSet(); } |
329 | ||
ba379fdc | 330 | private: |
14957cd0 | 331 | AssemblerLabel m_label; |
ba379fdc A |
332 | }; |
333 | ||
334 | // DataLabel32: | |
335 | // | |
336 | // A DataLabelPtr is used to refer to a location in the code containing a pointer to be | |
337 | // patched after the code has been generated. | |
338 | class DataLabel32 { | |
339 | template<class TemplateAssemblerType> | |
340 | friend class AbstractMacroAssembler; | |
341 | friend class LinkBuffer; | |
342 | public: | |
343 | DataLabel32() | |
344 | { | |
345 | } | |
346 | ||
347 | DataLabel32(AbstractMacroAssembler<AssemblerType>* masm) | |
348 | : m_label(masm->m_assembler.label()) | |
349 | { | |
350 | } | |
351 | ||
14957cd0 A |
352 | AssemblerLabel label() const { return m_label; } |
353 | ||
354 | private: | |
355 | AssemblerLabel m_label; | |
356 | }; | |
357 | ||
358 | // DataLabelCompact: | |
359 | // | |
360 | // A DataLabelCompact is used to refer to a location in the code containing a | |
361 | // compact immediate to be patched after the code has been generated. | |
362 | class DataLabelCompact { | |
363 | template<class TemplateAssemblerType> | |
364 | friend class AbstractMacroAssembler; | |
365 | friend class LinkBuffer; | |
366 | public: | |
367 | DataLabelCompact() | |
368 | { | |
369 | } | |
370 | ||
371 | DataLabelCompact(AbstractMacroAssembler<AssemblerType>* masm) | |
372 | : m_label(masm->m_assembler.label()) | |
373 | { | |
374 | } | |
375 | ||
376 | DataLabelCompact(AssemblerLabel label) | |
377 | : m_label(label) | |
378 | { | |
379 | } | |
380 | ||
ba379fdc | 381 | private: |
14957cd0 | 382 | AssemblerLabel m_label; |
ba379fdc A |
383 | }; |
384 | ||
385 | // Call: | |
386 | // | |
387 | // A Call object is a reference to a call instruction that has been planted | |
388 | // into the code buffer - it is typically used to link the call, setting the | |
389 | // relative offset such that when executed it will call to the desired | |
390 | // destination. | |
391 | class Call { | |
392 | template<class TemplateAssemblerType> | |
393 | friend class AbstractMacroAssembler; | |
394 | ||
395 | public: | |
396 | enum Flags { | |
397 | None = 0x0, | |
398 | Linkable = 0x1, | |
399 | Near = 0x2, | |
400 | LinkableNear = 0x3, | |
401 | }; | |
402 | ||
403 | Call() | |
404 | : m_flags(None) | |
405 | { | |
406 | } | |
407 | ||
14957cd0 | 408 | Call(AssemblerLabel jmp, Flags flags) |
6fe7ccc8 | 409 | : m_label(jmp) |
ba379fdc A |
410 | , m_flags(flags) |
411 | { | |
412 | } | |
413 | ||
414 | bool isFlagSet(Flags flag) | |
415 | { | |
416 | return m_flags & flag; | |
417 | } | |
418 | ||
419 | static Call fromTailJump(Jump jump) | |
420 | { | |
6fe7ccc8 | 421 | return Call(jump.m_label, Linkable); |
ba379fdc A |
422 | } |
423 | ||
6fe7ccc8 | 424 | AssemblerLabel m_label; |
ba379fdc A |
425 | private: |
426 | Flags m_flags; | |
427 | }; | |
428 | ||
429 | // Jump: | |
430 | // | |
431 | // A jump object is a reference to a jump instruction that has been planted | |
432 | // into the code buffer - it is typically used to link the jump, setting the | |
433 | // relative offset such that when executed it will jump to the desired | |
434 | // destination. | |
435 | class Jump { | |
436 | template<class TemplateAssemblerType> | |
437 | friend class AbstractMacroAssembler; | |
438 | friend class Call; | |
6fe7ccc8 | 439 | friend class DFG::CorrectableJumpPoint; |
ba379fdc A |
440 | friend class LinkBuffer; |
441 | public: | |
442 | Jump() | |
443 | { | |
444 | } | |
445 | ||
14957cd0 A |
446 | #if CPU(ARM_THUMB2) |
447 | // Fixme: this information should be stored in the instruction stream, not in the Jump object. | |
448 | Jump(AssemblerLabel jmp, ARMv7Assembler::JumpType type, ARMv7Assembler::Condition condition = ARMv7Assembler::ConditionInvalid) | |
6fe7ccc8 | 449 | : m_label(jmp) |
14957cd0 A |
450 | , m_type(type) |
451 | , m_condition(condition) | |
ba379fdc A |
452 | { |
453 | } | |
6fe7ccc8 A |
454 | #elif CPU(SH4) |
455 | Jump(AssemblerLabel jmp, SH4Assembler::JumpType type = SH4Assembler::JumpFar) | |
456 | : m_label(jmp) | |
457 | , m_type(type) | |
458 | { | |
459 | } | |
14957cd0 A |
460 | #else |
461 | Jump(AssemblerLabel jmp) | |
6fe7ccc8 | 462 | : m_label(jmp) |
14957cd0 A |
463 | { |
464 | } | |
465 | #endif | |
466 | ||
467 | void link(AbstractMacroAssembler<AssemblerType>* masm) const | |
ba379fdc | 468 | { |
14957cd0 | 469 | #if CPU(ARM_THUMB2) |
6fe7ccc8 A |
470 | masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition); |
471 | #elif CPU(SH4) | |
472 | masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type); | |
14957cd0 | 473 | #else |
6fe7ccc8 | 474 | masm->m_assembler.linkJump(m_label, masm->m_assembler.label()); |
14957cd0 | 475 | #endif |
ba379fdc A |
476 | } |
477 | ||
14957cd0 | 478 | void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm) const |
ba379fdc | 479 | { |
14957cd0 | 480 | #if CPU(ARM_THUMB2) |
6fe7ccc8 | 481 | masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition); |
14957cd0 | 482 | #else |
6fe7ccc8 | 483 | masm->m_assembler.linkJump(m_label, label.m_label); |
14957cd0 | 484 | #endif |
ba379fdc A |
485 | } |
486 | ||
6fe7ccc8 | 487 | bool isSet() const { return m_label.isSet(); } |
14957cd0 | 488 | |
ba379fdc | 489 | private: |
6fe7ccc8 | 490 | AssemblerLabel m_label; |
14957cd0 A |
491 | #if CPU(ARM_THUMB2) |
492 | ARMv7Assembler::JumpType m_type; | |
493 | ARMv7Assembler::Condition m_condition; | |
494 | #endif | |
6fe7ccc8 A |
495 | #if CPU(SH4) |
496 | SH4Assembler::JumpType m_type; | |
497 | #endif | |
498 | }; | |
499 | ||
500 | struct PatchableJump { | |
501 | PatchableJump() | |
502 | { | |
503 | } | |
504 | ||
505 | explicit PatchableJump(Jump jump) | |
506 | : m_jump(jump) | |
507 | { | |
508 | } | |
509 | ||
510 | operator Jump&() { return m_jump; } | |
511 | ||
512 | Jump m_jump; | |
ba379fdc A |
513 | }; |
514 | ||
515 | // JumpList: | |
516 | // | |
517 | // A JumpList is a set of Jump objects. | |
518 | // All jumps in the set will be linked to the same destination. | |
519 | class JumpList { | |
520 | friend class LinkBuffer; | |
521 | ||
522 | public: | |
523 | typedef Vector<Jump, 16> JumpVector; | |
524 | ||
525 | void link(AbstractMacroAssembler<AssemblerType>* masm) | |
526 | { | |
527 | size_t size = m_jumps.size(); | |
528 | for (size_t i = 0; i < size; ++i) | |
529 | m_jumps[i].link(masm); | |
530 | m_jumps.clear(); | |
531 | } | |
532 | ||
533 | void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm) | |
534 | { | |
535 | size_t size = m_jumps.size(); | |
536 | for (size_t i = 0; i < size; ++i) | |
537 | m_jumps[i].linkTo(label, masm); | |
538 | m_jumps.clear(); | |
539 | } | |
540 | ||
541 | void append(Jump jump) | |
542 | { | |
543 | m_jumps.append(jump); | |
544 | } | |
545 | ||
546 | void append(JumpList& other) | |
547 | { | |
548 | m_jumps.append(other.m_jumps.begin(), other.m_jumps.size()); | |
549 | } | |
550 | ||
551 | bool empty() | |
552 | { | |
553 | return !m_jumps.size(); | |
554 | } | |
555 | ||
14957cd0 A |
556 | void clear() |
557 | { | |
558 | m_jumps.clear(); | |
559 | } | |
560 | ||
ba379fdc A |
561 | const JumpVector& jumps() { return m_jumps; } |
562 | ||
563 | private: | |
564 | JumpVector m_jumps; | |
565 | }; | |
566 | ||
567 | ||
568 | // Section 3: Misc admin methods | |
ba379fdc A |
569 | Label label() |
570 | { | |
571 | return Label(this); | |
572 | } | |
573 | ||
574 | Label align() | |
575 | { | |
576 | m_assembler.align(16); | |
577 | return Label(this); | |
578 | } | |
579 | ||
6fe7ccc8 A |
580 | template<typename T, typename U> |
581 | static ptrdiff_t differenceBetween(T from, U to) | |
ba379fdc A |
582 | { |
583 | return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label); | |
584 | } | |
585 | ||
6fe7ccc8 | 586 | static ptrdiff_t differenceBetweenCodePtr(const MacroAssemblerCodePtr& a, const MacroAssemblerCodePtr& b) |
ba379fdc | 587 | { |
6fe7ccc8 | 588 | return reinterpret_cast<ptrdiff_t>(b.executableAddress()) - reinterpret_cast<ptrdiff_t>(a.executableAddress()); |
ba379fdc A |
589 | } |
590 | ||
6fe7ccc8 | 591 | unsigned debugOffset() { return m_assembler.debugOffset(); } |
ba379fdc | 592 | |
6fe7ccc8 | 593 | ALWAYS_INLINE static void cacheFlush(void* code, size_t size) |
ba379fdc | 594 | { |
6fe7ccc8 | 595 | AssemblerType::cacheFlush(code, size); |
ba379fdc | 596 | } |
6fe7ccc8 A |
597 | protected: |
598 | AbstractMacroAssembler() | |
599 | : m_randomSource(cryptographicallyRandomNumber()) | |
ba379fdc | 600 | { |
ba379fdc A |
601 | } |
602 | ||
6fe7ccc8 A |
603 | AssemblerType m_assembler; |
604 | ||
605 | uint32_t random() | |
ba379fdc | 606 | { |
6fe7ccc8 | 607 | return m_randomSource.getUint32(); |
ba379fdc | 608 | } |
14957cd0 | 609 | |
6fe7ccc8 | 610 | WeakRandom m_randomSource; |
ba379fdc | 611 | |
6fe7ccc8 A |
612 | #if ENABLE(JIT_CONSTANT_BLINDING) |
613 | static bool scratchRegisterForBlinding() { return false; } | |
614 | static bool shouldBlindForSpecificArch(uint32_t) { return true; } | |
615 | static bool shouldBlindForSpecificArch(uint64_t) { return true; } | |
14957cd0 A |
616 | #endif |
617 | ||
ba379fdc A |
618 | friend class LinkBuffer; |
619 | friend class RepatchBuffer; | |
620 | ||
621 | static void linkJump(void* code, Jump jump, CodeLocationLabel target) | |
622 | { | |
6fe7ccc8 | 623 | AssemblerType::linkJump(code, jump.m_label, target.dataLocation()); |
ba379fdc A |
624 | } |
625 | ||
14957cd0 | 626 | static void linkPointer(void* code, AssemblerLabel label, void* value) |
ba379fdc A |
627 | { |
628 | AssemblerType::linkPointer(code, label, value); | |
629 | } | |
630 | ||
14957cd0 | 631 | static void* getLinkerAddress(void* code, AssemblerLabel label) |
ba379fdc A |
632 | { |
633 | return AssemblerType::getRelocatedAddress(code, label); | |
634 | } | |
635 | ||
636 | static unsigned getLinkerCallReturnOffset(Call call) | |
637 | { | |
6fe7ccc8 | 638 | return AssemblerType::getCallReturnOffset(call.m_label); |
ba379fdc A |
639 | } |
640 | ||
641 | static void repatchJump(CodeLocationJump jump, CodeLocationLabel destination) | |
642 | { | |
643 | AssemblerType::relinkJump(jump.dataLocation(), destination.dataLocation()); | |
644 | } | |
645 | ||
646 | static void repatchNearCall(CodeLocationNearCall nearCall, CodeLocationLabel destination) | |
647 | { | |
648 | AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress()); | |
649 | } | |
650 | ||
14957cd0 A |
651 | static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value) |
652 | { | |
653 | AssemblerType::repatchCompact(dataLabelCompact.dataLocation(), value); | |
654 | } | |
655 | ||
ba379fdc A |
656 | static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value) |
657 | { | |
658 | AssemblerType::repatchInt32(dataLabel32.dataLocation(), value); | |
659 | } | |
660 | ||
661 | static void repatchPointer(CodeLocationDataLabelPtr dataLabelPtr, void* value) | |
662 | { | |
663 | AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value); | |
664 | } | |
14957cd0 A |
665 | |
666 | static void* readPointer(CodeLocationDataLabelPtr dataLabelPtr) | |
ba379fdc | 667 | { |
14957cd0 | 668 | return AssemblerType::readPointer(dataLabelPtr.dataLocation()); |
ba379fdc | 669 | } |
6fe7ccc8 A |
670 | |
671 | static void unreachableForPlatform() | |
672 | { | |
673 | #if COMPILER(CLANG) | |
674 | #pragma clang diagnostic push | |
675 | #pragma clang diagnostic ignored "-Wmissing-noreturn" | |
676 | ASSERT_NOT_REACHED(); | |
677 | #pragma clang diagnostic pop | |
678 | #else | |
679 | ASSERT_NOT_REACHED(); | |
680 | #endif | |
681 | } | |
ba379fdc A |
682 | }; |
683 | ||
684 | } // namespace JSC | |
685 | ||
686 | #endif // ENABLE(ASSEMBLER) | |
687 | ||
688 | #endif // AbstractMacroAssembler_h |