source: webkit/trunk/JavaScriptCore/assembler/AbstractMacroAssembler.h@ 44341

Last change on this file since 44341 was 44341, checked in by [email protected], 16 years ago

2009-06-01 Gavin Barraclough <[email protected]>

Reviewed by Sam "WX" Weinig.

Allow the JIT to operate without relying on use of RWX memory, on platforms where this is supported.

This patch adds a switch to Platform.h (ENABLE_ASSEMBLER_WX_EXCLUSIVE) which enables this mode of operation.
When this flag is set, all executable memory will be allocated RX, and switched to RW only whilst being
modified. Upon completion of code generation the protection is switched back to RX to allow execution.

Further optimization will be required before it is desirable to enable this mode of operation by default;
enabling this presently incurs a 5%-10% regression.

(Submitting disabled - no performance impact).

  • assembler/AbstractMacroAssembler.h: (JSC::AbstractMacroAssembler::CodeLocationInstruction::repatchLoadToLEA): (JSC::AbstractMacroAssembler::CodeLocationLabel::fromFunctionPointer): (JSC::AbstractMacroAssembler::CodeLocationJump::relink): (JSC::AbstractMacroAssembler::CodeLocationCall::relink): (JSC::AbstractMacroAssembler::CodeLocationNearCall::relink): (JSC::AbstractMacroAssembler::CodeLocationDataLabel32::repatch): (JSC::AbstractMacroAssembler::CodeLocationDataLabelPtr::repatch): (JSC::AbstractMacroAssembler::ProcessorReturnAddress::relinkCallerToTrampoline): (JSC::AbstractMacroAssembler::ProcessorReturnAddress::relinkCallerToFunction): (JSC::AbstractMacroAssembler::ProcessorReturnAddress::relinkNearCallerToTrampoline): (JSC::AbstractMacroAssembler::ProcessorReturnAddress::relinkNearCallerToFunction): (JSC::AbstractMacroAssembler::PatchBuffer::PatchBuffer): (JSC::AbstractMacroAssembler::PatchBuffer::~PatchBuffer): (JSC::AbstractMacroAssembler::PatchBuffer::link): (JSC::AbstractMacroAssembler::PatchBuffer::patch): (JSC::AbstractMacroAssembler::PatchBuffer::performFinalization): (JSC::::CodeLocationCommon::nearCallAtOffset): (JSC::::CodeLocationCall::CodeLocationCall): (JSC::::CodeLocationNearCall::CodeLocationNearCall):
  • assembler/AssemblerBuffer.h: (JSC::AssemblerBuffer::executableCopy):
  • assembler/X86Assembler.h: (JSC::CAN_SIGN_EXTEND_U32_64): (JSC::X86Assembler::linkJump): (JSC::X86Assembler::linkCall): (JSC::X86Assembler::patchPointer): (JSC::X86Assembler::relinkJump): (JSC::X86Assembler::relinkCall): (JSC::X86Assembler::repatchInt32): (JSC::X86Assembler::repatchPointer): (JSC::X86Assembler::repatchLoadToLEA): (JSC::X86Assembler::patchInt32): (JSC::X86Assembler::patchRel32):
  • jit/ExecutableAllocator.h: (JSC::ExecutableAllocator::): (JSC::ExecutableAllocator::makeWritable): (JSC::ExecutableAllocator::makeExecutable):
  • jit/ExecutableAllocatorFixedVMPool.cpp: (JSC::FixedVMPoolAllocator::FixedVMPoolAllocator):
  • jit/ExecutableAllocatorPosix.cpp: (JSC::ExecutablePool::systemAlloc): (JSC::ExecutablePool::systemRelease): (JSC::ExecutableAllocator::reprotectRegion):
  • jit/ExecutableAllocatorWin.cpp:
  • jit/JITPropertyAccess.cpp: (JSC::JIT::patchGetByIdSelf): (JSC::JIT::patchPutByIdReplace):
  • wtf/Platform.h:
File size: 29.4 KB
Line 
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
29#include <wtf/Platform.h>
30
31#include <MacroAssemblerCodeRef.h>
32#include <wtf/Noncopyable.h>
33#include <wtf/UnusedParam.h>
34
35#if ENABLE(ASSEMBLER)
36
37// FIXME: keep transitioning this out into MacroAssemblerX86_64.
38#if PLATFORM(X86_64)
39#define REPTACH_OFFSET_CALL_R11 3
40#endif
41
42namespace JSC {
43
44template <class AssemblerType>
45class AbstractMacroAssembler {
46public:
47 typedef MacroAssemblerCodeRef CodeRef;
48
49 class Jump;
50 class PatchBuffer;
51 class CodeLocationInstruction;
52 class CodeLocationLabel;
53 class CodeLocationJump;
54 class CodeLocationCall;
55 class CodeLocationNearCall;
56 class CodeLocationDataLabel32;
57 class CodeLocationDataLabelPtr;
58 class ProcessorReturnAddress;
59
60 typedef typename AssemblerType::RegisterID RegisterID;
61 typedef typename AssemblerType::FPRegisterID FPRegisterID;
62 typedef typename AssemblerType::JmpSrc JmpSrc;
63 typedef typename AssemblerType::JmpDst JmpDst;
64
65
66 // Section 1: MacroAssembler operand types
67 //
68 // The following types are used as operands to MacroAssembler operations,
69 // describing immediate and memory operands to the instructions to be planted.
70
71
72 enum Scale {
73 TimesOne,
74 TimesTwo,
75 TimesFour,
76 TimesEight,
77 };
78
79 // Address:
80 //
81 // Describes a simple base-offset address.
82 struct Address {
83 explicit Address(RegisterID base, int32_t offset = 0)
84 : base(base)
85 , offset(offset)
86 {
87 }
88
89 RegisterID base;
90 int32_t offset;
91 };
92
93 // ImplicitAddress:
94 //
95 // This class is used for explicit 'load' and 'store' operations
96 // (as opposed to situations in which a memory operand is provided
97 // to a generic operation, such as an integer arithmetic instruction).
98 //
99 // In the case of a load (or store) operation we want to permit
100 // addresses to be implicitly constructed, e.g. the two calls:
101 //
102 // load32(Address(addrReg), destReg);
103 // load32(addrReg, destReg);
104 //
105 // Are equivalent, and the explicit wrapping of the Address in the former
106 // is unnecessary.
107 struct ImplicitAddress {
108 ImplicitAddress(RegisterID base)
109 : base(base)
110 , offset(0)
111 {
112 }
113
114 ImplicitAddress(Address address)
115 : base(address.base)
116 , offset(address.offset)
117 {
118 }
119
120 RegisterID base;
121 int32_t offset;
122 };
123
124 // BaseIndex:
125 //
126 // Describes a complex addressing mode.
127 struct BaseIndex {
128 BaseIndex(RegisterID base, RegisterID index, Scale scale, int32_t offset = 0)
129 : base(base)
130 , index(index)
131 , scale(scale)
132 , offset(offset)
133 {
134 }
135
136 RegisterID base;
137 RegisterID index;
138 Scale scale;
139 int32_t offset;
140 };
141
142 // AbsoluteAddress:
143 //
144 // Describes an memory operand given by a pointer. For regular load & store
145 // operations an unwrapped void* will be used, rather than using this.
146 struct AbsoluteAddress {
147 explicit AbsoluteAddress(void* ptr)
148 : m_ptr(ptr)
149 {
150 }
151
152 void* m_ptr;
153 };
154
155 // ImmPtr:
156 //
157 // A pointer sized immediate operand to an instruction - this is wrapped
158 // in a class requiring explicit construction in order to differentiate
159 // from pointers used as absolute addresses to memory operations
160 struct ImmPtr {
161 explicit ImmPtr(void* value)
162 : m_value(value)
163 {
164 }
165
166 intptr_t asIntptr()
167 {
168 return reinterpret_cast<intptr_t>(m_value);
169 }
170
171 void* m_value;
172 };
173
174 // Imm32:
175 //
176 // A 32bit immediate operand to an instruction - this is wrapped in a
177 // class requiring explicit construction in order to prevent RegisterIDs
178 // (which are implemented as an enum) from accidentally being passed as
179 // immediate values.
180 struct Imm32 {
181 explicit Imm32(int32_t value)
182 : m_value(value)
183 {
184 }
185
186#if !PLATFORM(X86_64)
187 explicit Imm32(ImmPtr ptr)
188 : m_value(ptr.asIntptr())
189 {
190 }
191#endif
192
193 int32_t m_value;
194 };
195
196
197 // Section 2: MacroAssembler code buffer handles
198 //
199 // The following types are used to reference items in the code buffer
200 // during JIT code generation. For example, the type Jump is used to
201 // track the location of a jump instruction so that it may later be
202 // linked to a label marking its destination.
203
204
205 // Label:
206 //
207 // A Label records a point in the generated instruction stream, typically such that
208 // it may be used as a destination for a jump.
209 class Label {
210 template<class TemplateAssemblerType>
211 friend class AbstractMacroAssembler;
212 friend class Jump;
213 friend class MacroAssemblerCodeRef;
214 friend class PatchBuffer;
215
216 public:
217 Label()
218 {
219 }
220
221 Label(AbstractMacroAssembler<AssemblerType>* masm)
222 : m_label(masm->m_assembler.label())
223 {
224 }
225
226 bool isUsed() const { return m_label.isUsed(); }
227 void used() { m_label.used(); }
228 private:
229 JmpDst m_label;
230 };
231
232 // DataLabelPtr:
233 //
234 // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
235 // patched after the code has been generated.
236 class DataLabelPtr {
237 template<class TemplateAssemblerType>
238 friend class AbstractMacroAssembler;
239 friend class PatchBuffer;
240 public:
241 DataLabelPtr()
242 {
243 }
244
245 DataLabelPtr(AbstractMacroAssembler<AssemblerType>* masm)
246 : m_label(masm->m_assembler.label())
247 {
248 }
249
250 private:
251 JmpDst m_label;
252 };
253
254 // DataLabel32:
255 //
256 // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
257 // patched after the code has been generated.
258 class DataLabel32 {
259 template<class TemplateAssemblerType>
260 friend class AbstractMacroAssembler;
261 friend class PatchBuffer;
262 public:
263 DataLabel32()
264 {
265 }
266
267 DataLabel32(AbstractMacroAssembler<AssemblerType>* masm)
268 : m_label(masm->m_assembler.label())
269 {
270 }
271
272 private:
273 JmpDst m_label;
274 };
275
276 // Call:
277 //
278 // A Call object is a reference to a call instruction that has been planted
279 // into the code buffer - it is typically used to link the call, setting the
280 // relative offset such that when executed it will call to the desired
281 // destination.
282 class Call {
283 template<class TemplateAssemblerType>
284 friend class AbstractMacroAssembler;
285 friend class PatchBuffer;
286 public:
287 enum Flags {
288 None = 0x0,
289 Linkable = 0x1,
290 Near = 0x2,
291 LinkableNear = 0x3,
292 };
293
294 Call()
295 : m_flags(None)
296 {
297 }
298
299 Call(JmpSrc jmp, Flags flags)
300 : m_jmp(jmp)
301 , m_flags(flags)
302 {
303 }
304
305 bool isFlagSet(Flags flag)
306 {
307 return m_flags & flag;
308 }
309
310 static Call fromTailJump(Jump jump)
311 {
312 return Call(jump.m_jmp, Linkable);
313 }
314
315 private:
316 JmpSrc m_jmp;
317 Flags m_flags;
318 };
319
320 // Jump:
321 //
322 // A jump object is a reference to a jump instruction that has been planted
323 // into the code buffer - it is typically used to link the jump, setting the
324 // relative offset such that when executed it will jump to the desired
325 // destination.
326 class Jump {
327 template<class TemplateAssemblerType>
328 friend class AbstractMacroAssembler;
329 friend class Call;
330 friend class PatchBuffer;
331 public:
332 Jump()
333 {
334 }
335
336 Jump(JmpSrc jmp)
337 : m_jmp(jmp)
338 {
339 }
340
341 void link(AbstractMacroAssembler<AssemblerType>* masm)
342 {
343 masm->m_assembler.linkJump(m_jmp, masm->m_assembler.label());
344 }
345
346 void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
347 {
348 masm->m_assembler.linkJump(m_jmp, label.m_label);
349 }
350
351 private:
352 JmpSrc m_jmp;
353 };
354
355 // JumpList:
356 //
357 // A JumpList is a set of Jump objects.
358 // All jumps in the set will be linked to the same destination.
359 class JumpList {
360 friend class PatchBuffer;
361
362 public:
363 void link(AbstractMacroAssembler<AssemblerType>* masm)
364 {
365 size_t size = m_jumps.size();
366 for (size_t i = 0; i < size; ++i)
367 m_jumps[i].link(masm);
368 m_jumps.clear();
369 }
370
371 void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
372 {
373 size_t size = m_jumps.size();
374 for (size_t i = 0; i < size; ++i)
375 m_jumps[i].linkTo(label, masm);
376 m_jumps.clear();
377 }
378
379 void append(Jump jump)
380 {
381 m_jumps.append(jump);
382 }
383
384 void append(JumpList& other)
385 {
386 m_jumps.append(other.m_jumps.begin(), other.m_jumps.size());
387 }
388
389 bool empty()
390 {
391 return !m_jumps.size();
392 }
393
394 private:
395 Vector<Jump, 16> m_jumps;
396 };
397
398
399 // Section 3: MacroAssembler JIT instruction stream handles.
400 //
401 // The MacroAssembler supported facilities to modify a JIT generated
402 // instruction stream after it has been generated (relinking calls and
403 // jumps, and repatching data values). The following types are used
404 // to store handles into the underlying instruction stream, the type
405 // providing semantic information as to what it is that is in the
406 // instruction stream at this point, and thus what operations may be
407 // performed on it.
408
409
410 // CodeLocationCommon:
411 //
412 // Base type for other CodeLocation* types. A postion in the JIT genertaed
413 // instruction stream, without any semantic information.
414 class CodeLocationCommon {
415 public:
416 CodeLocationCommon()
417 : m_location(0)
418 {
419 }
420
421 // In order to avoid the need to store multiple handles into the
422 // instructions stream, where the code generation is deterministic
423 // and the labels will always be a fixed distance apart, these
424 // methods may be used to recover a handle that has nopw been
425 // retained, based on a known fixed relative offset from one that has.
426 CodeLocationInstruction instructionAtOffset(int offset);
427 CodeLocationLabel labelAtOffset(int offset);
428 CodeLocationJump jumpAtOffset(int offset);
429 CodeLocationCall callAtOffset(int offset);
430 CodeLocationNearCall nearCallAtOffset(int offset);
431 CodeLocationDataLabelPtr dataLabelPtrAtOffset(int offset);
432 CodeLocationDataLabel32 dataLabel32AtOffset(int offset);
433
434 operator bool() { return m_location; }
435 void reset() { m_location = 0; }
436
437 protected:
438 explicit CodeLocationCommon(void* location)
439 : m_location(location)
440 {
441 }
442
443 void* m_location;
444 };
445
446 // CodeLocationInstruction:
447 //
448 // An arbitrary instruction in the JIT code.
449 class CodeLocationInstruction : public CodeLocationCommon {
450 friend class CodeLocationCommon;
451 public:
452 CodeLocationInstruction()
453 {
454 }
455
456 void repatchLoadToLEA()
457 {
458 AssemblerType::repatchLoadToLEA(this->m_location);
459 }
460
461 private:
462 explicit CodeLocationInstruction(void* location)
463 : CodeLocationCommon(location)
464 {
465 }
466 };
467
468 // CodeLocationLabel:
469 //
470 // A point in the JIT code maked with a label.
471 class CodeLocationLabel : public CodeLocationCommon {
472 friend class CodeLocationCommon;
473 friend class CodeLocationJump;
474 friend class CodeLocationCall;
475 friend class CodeLocationNearCall;
476 friend class PatchBuffer;
477 friend class ProcessorReturnAddress;
478
479 public:
480 CodeLocationLabel()
481 {
482 }
483
484 void* addressForSwitch() { return this->m_location; }
485 void* addressForExceptionHandler() { return this->m_location; }
486 void* addressForJSR() { return this->m_location; }
487
488 template<typename FunctionSig>
489 static CodeLocationLabel fromFunctionPointer(FunctionSig* function)
490 {
491 return CodeLocationLabel(reinterpret_cast<void*>(function));
492 }
493
494 private:
495 explicit CodeLocationLabel(void* location)
496 : CodeLocationCommon(location)
497 {
498 }
499
500 void* getJumpDestination() { return this->m_location; }
501 };
502
503 // CodeLocationJump:
504 //
505 // A point in the JIT code at which there is a jump instruction.
506 class CodeLocationJump : public CodeLocationCommon {
507 friend class CodeLocationCommon;
508 friend class PatchBuffer;
509 public:
510 CodeLocationJump()
511 {
512 }
513
514 void relink(CodeLocationLabel destination)
515 {
516 AssemblerType::relinkJump(this->m_location, destination.m_location);
517 }
518
519 private:
520 explicit CodeLocationJump(void* location)
521 : CodeLocationCommon(location)
522 {
523 }
524 };
525
526 // CodeLocationCall:
527 //
528 // A point in the JIT code at which there is a call instruction.
529 class CodeLocationCall : public CodeLocationCommon {
530 friend class CodeLocationCommon;
531 friend class PatchBuffer;
532 public:
533 CodeLocationCall()
534 {
535 }
536
537 CodeLocationCall(ProcessorReturnAddress*);
538
539 void relink(CodeLocationLabel destination)
540 {
541#if PLATFORM(X86_64)
542 CodeLocationCommon::dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11).repatch(destination.m_location);
543#else
544 AssemblerType::relinkCall(this->m_location, destination.m_location);
545#endif
546 }
547
548 template<typename FunctionSig>
549 void relink(FunctionSig* function)
550 {
551 relink(CodeLocationLabel::fromFunctionPointer(function));
552 }
553
554 // This methods returns the value that will be set as the return address
555 // within a function that has been called from this call instruction.
556 void* calleeReturnAddressValue()
557 {
558 return this->m_location;
559 }
560
561 private:
562 explicit CodeLocationCall(void* location)
563 : CodeLocationCommon(location)
564 {
565 }
566 };
567
568 // CodeLocationNearCall:
569 //
570 // A point in the JIT code at which there is a call instruction with near linkage.
571 class CodeLocationNearCall : public CodeLocationCommon {
572 friend class CodeLocationCommon;
573 friend class PatchBuffer;
574 public:
575 CodeLocationNearCall()
576 {
577 }
578
579 CodeLocationNearCall(ProcessorReturnAddress*);
580
581 void relink(CodeLocationLabel destination)
582 {
583 AssemblerType::relinkCall(this->m_location, destination.m_location);
584 }
585
586 template<typename FunctionSig>
587 void relink(FunctionSig* function)
588 {
589 relink(CodeLocationLabel::fromFunctionPointer(function));
590 }
591
592 // This methods returns the value that will be set as the return address
593 // within a function that has been called from this call instruction.
594 void* calleeReturnAddressValue()
595 {
596 return this->m_location;
597 }
598
599 private:
600 explicit CodeLocationNearCall(void* location)
601 : CodeLocationCommon(location)
602 {
603 }
604 };
605
606 // CodeLocationDataLabel32:
607 //
608 // A point in the JIT code at which there is an int32_t immediate that may be repatched.
609 class CodeLocationDataLabel32 : public CodeLocationCommon {
610 friend class CodeLocationCommon;
611 friend class PatchBuffer;
612 public:
613 CodeLocationDataLabel32()
614 {
615 }
616
617 void repatch(int32_t value)
618 {
619 AssemblerType::repatchInt32(this->m_location, value);
620 }
621
622 private:
623 explicit CodeLocationDataLabel32(void* location)
624 : CodeLocationCommon(location)
625 {
626 }
627 };
628
629 // CodeLocationDataLabelPtr:
630 //
631 // A point in the JIT code at which there is a void* immediate that may be repatched.
632 class CodeLocationDataLabelPtr : public CodeLocationCommon {
633 friend class CodeLocationCommon;
634 friend class PatchBuffer;
635 public:
636 CodeLocationDataLabelPtr()
637 {
638 }
639
640 void repatch(void* value)
641 {
642 AssemblerType::repatchPointer(this->m_location, value);
643 }
644
645 private:
646 explicit CodeLocationDataLabelPtr(void* location)
647 : CodeLocationCommon(location)
648 {
649 }
650 };
651
652 // ProcessorReturnAddress:
653 //
654 // This class can be used to relink a call identified by its return address.
655 class ProcessorReturnAddress {
656 friend class CodeLocationCall;
657 friend class CodeLocationNearCall;
658 public:
659 ProcessorReturnAddress(void* location)
660 : m_location(location)
661 {
662 }
663
664 void relinkCallerToTrampoline(CodeLocationLabel label)
665 {
666 CodeLocationCall(this).relink(label);
667 }
668
669 template<typename FunctionSig>
670 void relinkCallerToFunction(FunctionSig* newCalleeFunction)
671 {
672 relinkCallerToTrampoline(CodeLocationLabel::fromFunctionPointer(newCalleeFunction));
673 }
674
675 void relinkNearCallerToTrampoline(CodeLocationLabel label)
676 {
677 CodeLocationNearCall(this).relink(label);
678 }
679
680 template<typename FunctionSig>
681 void relinkNearCallerToFunction(FunctionSig* newCalleeFunction)
682 {
683 relinkNearCallerToTrampoline(CodeLocationLabel::fromFunctionPointer(newCalleeFunction));
684 }
685
686 operator void*()
687 {
688 return m_location;
689 }
690
691 private:
692 void* m_location;
693 };
694
695
696 // Section 4: PatchBuffer - utility to finalize code generation.
697
698 static void* trampolineAt(CodeRef ref, Label label)
699 {
700 return AssemblerType::getRelocatedAddress(ref.m_code, label.m_label);
701 }
702
703 // PatchBuffer:
704 //
705 // This class assists in linking code generated by the macro assembler, once code generation
706 // has been completed, and the code has been copied to is final location in memory. At this
707 // time pointers to labels within the code may be resolved, and relative offsets to external
708 // addresses may be fixed.
709 //
710 // Specifically:
711 // * Jump objects may be linked to external targets,
712 // * The address of Jump objects may taken, such that it can later be relinked.
713 // * The return address of a Jump object representing a call may be acquired.
714 // * The address of a Label pointing into the code may be resolved.
715 // * The value referenced by a DataLabel may be fixed.
716 //
717 // FIXME: distinguish between Calls & Jumps (make a specific call to obtain the return
718 // address of calls, as opposed to a point that can be used to later relink a Jump -
719 // possibly wrap the later up in an object that can do just that).
720 class PatchBuffer : public Noncopyable {
721 public:
722 PatchBuffer(AbstractMacroAssembler<AssemblerType>* masm, PassRefPtr<ExecutablePool> executablePool)
723 : m_ref(0, executablePool, masm->m_assembler.size())
724 , m_size(masm->m_assembler.size())
725#ifndef NDEBUG
726 , m_completed(false)
727#endif
728 {
729 m_ref.m_code = masm->m_assembler.executableCopy(m_ref.m_executablePool.get());
730 }
731
732 ~PatchBuffer()
733 {
734 ASSERT(m_completed);
735 }
736
737 // These methods are used to link or set values at code generation time.
738
739 template<typename FunctionSig>
740 void link(Call call, FunctionSig* function)
741 {
742 ASSERT(call.isFlagSet(Call::Linkable));
743#if PLATFORM(X86_64)
744 if (!call.isFlagSet(Call::Near)) {
745 intptr_t callLocation = reinterpret_cast<intptr_t>(AssemblerType::getRelocatedAddress(code(), call.m_jmp)) - REPTACH_OFFSET_CALL_R11;
746 AssemblerType::patchPointer(reinterpret_cast<void*>(callLocation), reinterpret_cast<void*>(function));
747 } else
748#endif
749 AssemblerType::linkCall(code(), call.m_jmp, reinterpret_cast<void*>(function));
750 }
751
752 template<typename FunctionSig>
753 void linkTailRecursive(Jump jump, FunctionSig* function)
754 {
755 AssemblerType::linkJump(code(), jump.m_jmp, reinterpret_cast<void*>(function));
756 }
757
758 template<typename FunctionSig>
759 void linkTailRecursive(JumpList list, FunctionSig* function)
760 {
761 for (unsigned i = 0; i < list.m_jumps.size(); ++i)
762 AssemblerType::linkJump(code(), list.m_jumps[i].m_jmp, reinterpret_cast<void*>(function));
763 }
764
765 void link(Jump jump, CodeLocationLabel label)
766 {
767 AssemblerType::linkJump(code(), jump.m_jmp, label.m_location);
768 }
769
770 void link(JumpList list, CodeLocationLabel label)
771 {
772 for (unsigned i = 0; i < list.m_jumps.size(); ++i)
773 AssemblerType::linkJump(code(), list.m_jumps[i].m_jmp, label.m_location);
774 }
775
776 void patch(DataLabelPtr label, void* value)
777 {
778 AssemblerType::patchPointer(code(), label.m_label, value);
779 }
780
781 void patch(DataLabelPtr label, CodeLocationLabel value)
782 {
783 AssemblerType::patchPointer(code(), label.m_label, value.getJumpDestination());
784 }
785
786 // These methods are used to obtain handles to allow the code to be relinked / repatched later.
787
788 CodeLocationCall locationOf(Call call)
789 {
790 ASSERT(call.isFlagSet(Call::Linkable));
791 ASSERT(!call.isFlagSet(Call::Near));
792 return CodeLocationCall(AssemblerType::getRelocatedAddress(code(), call.m_jmp));
793 }
794
795 CodeLocationNearCall locationOfNearCall(Call call)
796 {
797 ASSERT(call.isFlagSet(Call::Linkable));
798 ASSERT(call.isFlagSet(Call::Near));
799 return CodeLocationNearCall(AssemblerType::getRelocatedAddress(code(), call.m_jmp));
800 }
801
802 CodeLocationLabel locationOf(Label label)
803 {
804 return CodeLocationLabel(AssemblerType::getRelocatedAddress(code(), label.m_label));
805 }
806
807 CodeLocationDataLabelPtr locationOf(DataLabelPtr label)
808 {
809 return CodeLocationDataLabelPtr(AssemblerType::getRelocatedAddress(code(), label.m_label));
810 }
811
812 CodeLocationDataLabel32 locationOf(DataLabel32 label)
813 {
814 return CodeLocationDataLabel32(AssemblerType::getRelocatedAddress(code(), label.m_label));
815 }
816
817 // This method obtains the return address of the call, given as an offset from
818 // the start of the code.
819 unsigned returnAddressOffset(Call call)
820 {
821 return AssemblerType::getCallReturnOffset(call.m_jmp);
822 }
823
824 // Upon completion of all patching either 'finalizeCode()' or 'finalizeCodeAddendum()' should be called
825 // once to complete generation of the code. 'finalizeCode()' is suited to situations
826 // where the executable pool must also be retained, the lighter-weight 'finalizeCodeAddendum()' is
827 // suited to adding to an existing allocation.
828 CodeRef finalizeCode()
829 {
830 performFinalization();
831
832 return m_ref;
833 }
834 CodeLocationLabel finalizeCodeAddendum()
835 {
836 performFinalization();
837
838 return CodeLocationLabel(code());
839 }
840
841 private:
842 // Keep this private! - the underlying code should only be obtained externally via
843 // finalizeCode() or finalizeCodeAddendum().
844 void* code()
845 {
846 return m_ref.m_code;
847 }
848
849 void performFinalization()
850 {
851#ifndef NDEBUG
852 ASSERT(!m_completed);
853 m_completed = true;
854#endif
855
856 ExecutableAllocator::makeExecutable(m_ref.m_code, m_size);
857 }
858
859 CodeRef m_ref;
860 size_t m_size;
861#ifndef NDEBUG
862 bool m_completed;
863#endif
864 };
865
866
867 // Section 5: Misc admin methods
868
869 size_t size()
870 {
871 return m_assembler.size();
872 }
873
874 Label label()
875 {
876 return Label(this);
877 }
878
879 Label align()
880 {
881 m_assembler.align(16);
882 return Label(this);
883 }
884
885 ptrdiff_t differenceBetween(Label from, Jump to)
886 {
887 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
888 }
889
890 ptrdiff_t differenceBetween(Label from, Call to)
891 {
892 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
893 }
894
895 ptrdiff_t differenceBetween(Label from, Label to)
896 {
897 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
898 }
899
900 ptrdiff_t differenceBetween(Label from, DataLabelPtr to)
901 {
902 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
903 }
904
905 ptrdiff_t differenceBetween(Label from, DataLabel32 to)
906 {
907 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
908 }
909
910 ptrdiff_t differenceBetween(DataLabelPtr from, Jump to)
911 {
912 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
913 }
914
915 ptrdiff_t differenceBetween(DataLabelPtr from, DataLabelPtr to)
916 {
917 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
918 }
919
920 ptrdiff_t differenceBetween(DataLabelPtr from, Call to)
921 {
922 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
923 }
924
925protected:
926 AssemblerType m_assembler;
927};
928
929
930template <class AssemblerType>
931typename AbstractMacroAssembler<AssemblerType>::CodeLocationInstruction AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::instructionAtOffset(int offset)
932{
933 return typename AbstractMacroAssembler::CodeLocationInstruction(reinterpret_cast<char*>(m_location) + offset);
934}
935
936template <class AssemblerType>
937typename AbstractMacroAssembler<AssemblerType>::CodeLocationLabel AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::labelAtOffset(int offset)
938{
939 return typename AbstractMacroAssembler::CodeLocationLabel(reinterpret_cast<char*>(m_location) + offset);
940}
941
942template <class AssemblerType>
943typename AbstractMacroAssembler<AssemblerType>::CodeLocationJump AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::jumpAtOffset(int offset)
944{
945 return typename AbstractMacroAssembler::CodeLocationJump(reinterpret_cast<char*>(m_location) + offset);
946}
947
948template <class AssemblerType>
949typename AbstractMacroAssembler<AssemblerType>::CodeLocationCall AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::callAtOffset(int offset)
950{
951 return typename AbstractMacroAssembler::CodeLocationCall(reinterpret_cast<char*>(m_location) + offset);
952}
953
954template <class AssemblerType>
955typename AbstractMacroAssembler<AssemblerType>::CodeLocationNearCall AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::nearCallAtOffset(int offset)
956{
957 return typename AbstractMacroAssembler::CodeLocationNearCall(reinterpret_cast<char*>(m_location) + offset);
958}
959
960template <class AssemblerType>
961typename AbstractMacroAssembler<AssemblerType>::CodeLocationDataLabelPtr AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::dataLabelPtrAtOffset(int offset)
962{
963 return typename AbstractMacroAssembler::CodeLocationDataLabelPtr(reinterpret_cast<char*>(m_location) + offset);
964}
965
966template <class AssemblerType>
967typename AbstractMacroAssembler<AssemblerType>::CodeLocationDataLabel32 AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::dataLabel32AtOffset(int offset)
968{
969 return typename AbstractMacroAssembler::CodeLocationDataLabel32(reinterpret_cast<char*>(m_location) + offset);
970}
971
972template <class AssemblerType>
973AbstractMacroAssembler<AssemblerType>::CodeLocationCall::CodeLocationCall(AbstractMacroAssembler<AssemblerType>::ProcessorReturnAddress* ra)
974 : CodeLocationCommon(ra->m_location)
975{
976}
977
978template <class AssemblerType>
979AbstractMacroAssembler<AssemblerType>::CodeLocationNearCall::CodeLocationNearCall(AbstractMacroAssembler<AssemblerType>::ProcessorReturnAddress* ra)
980 : CodeLocationCommon(ra->m_location)
981{
982}
983
984} // namespace JSC
985
986#endif // ENABLE(ASSEMBLER)
987
988#endif // AbstractMacroAssembler_h
Note: See TracBrowser for help on using the repository browser.