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

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

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

Reviewed by Sam Weinig.

Having introduced the RepatchBuffer, ProcessorReturnAddress is now a do-nothing
wrapper around ReturnAddressPtr. Remove it. In tugging on this piece of string
it made sense to roll out the use of ReturnAddressPtr a little further into
JITStubs (which had always been the intention).

No performance impact.

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