2 * Copyright (C) 2009 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #include <wtf/Platform.h>
33 #include <MacroAssembler.h>
34 #include <wtf/Noncopyable.h>
40 // This class assists in linking code generated by the macro assembler, once code generation
41 // has been completed, and the code has been copied to is final location in memory. At this
42 // time pointers to labels within the code may be resolved, and relative offsets to external
43 // addresses may be fixed.
46 // * Jump objects may be linked to external targets,
47 // * The address of Jump objects may taken, such that it can later be relinked.
48 // * The return address of a Call may be acquired.
49 // * The address of a Label pointing into the code may be resolved.
50 // * The value referenced by a DataLabel may be set.
52 class LinkBuffer
: public Noncopyable
{
53 typedef MacroAssemblerCodeRef CodeRef
;
54 typedef MacroAssembler::Label Label
;
55 typedef MacroAssembler::Jump Jump
;
56 typedef MacroAssembler::JumpList JumpList
;
57 typedef MacroAssembler::Call Call
;
58 typedef MacroAssembler::DataLabel32 DataLabel32
;
59 typedef MacroAssembler::DataLabelPtr DataLabelPtr
;
62 // Note: Initialization sequence is significant, since executablePool is a PassRefPtr.
63 // First, executablePool is copied into m_executablePool, then the initialization of
64 // m_code uses m_executablePool, *not* executablePool, since this is no longer valid.
65 LinkBuffer(MacroAssembler
* masm
, PassRefPtr
<ExecutablePool
> executablePool
)
66 : m_executablePool(executablePool
)
67 , m_code(masm
->m_assembler
.executableCopy(m_executablePool
.get()))
68 , m_size(masm
->m_assembler
.size())
80 // These methods are used to link or set values at code generation time.
82 void link(Call call
, FunctionPtr function
)
84 ASSERT(call
.isFlagSet(Call::Linkable
));
85 MacroAssembler::linkCall(code(), call
, function
);
88 void link(Jump jump
, CodeLocationLabel label
)
90 MacroAssembler::linkJump(code(), jump
, label
);
93 void link(JumpList list
, CodeLocationLabel label
)
95 for (unsigned i
= 0; i
< list
.m_jumps
.size(); ++i
)
96 MacroAssembler::linkJump(code(), list
.m_jumps
[i
], label
);
99 void patch(DataLabelPtr label
, void* value
)
101 MacroAssembler::linkPointer(code(), label
.m_label
, value
);
104 void patch(DataLabelPtr label
, CodeLocationLabel value
)
106 MacroAssembler::linkPointer(code(), label
.m_label
, value
.executableAddress());
109 // These methods are used to obtain handles to allow the code to be relinked / repatched later.
111 CodeLocationCall
locationOf(Call call
)
113 ASSERT(call
.isFlagSet(Call::Linkable
));
114 ASSERT(!call
.isFlagSet(Call::Near
));
115 return CodeLocationCall(MacroAssembler::getLinkerAddress(code(), call
.m_jmp
));
118 CodeLocationNearCall
locationOfNearCall(Call call
)
120 ASSERT(call
.isFlagSet(Call::Linkable
));
121 ASSERT(call
.isFlagSet(Call::Near
));
122 return CodeLocationNearCall(MacroAssembler::getLinkerAddress(code(), call
.m_jmp
));
125 CodeLocationLabel
locationOf(Label label
)
127 return CodeLocationLabel(MacroAssembler::getLinkerAddress(code(), label
.m_label
));
130 CodeLocationDataLabelPtr
locationOf(DataLabelPtr label
)
132 return CodeLocationDataLabelPtr(MacroAssembler::getLinkerAddress(code(), label
.m_label
));
135 CodeLocationDataLabel32
locationOf(DataLabel32 label
)
137 return CodeLocationDataLabel32(MacroAssembler::getLinkerAddress(code(), label
.m_label
));
140 // This method obtains the return address of the call, given as an offset from
141 // the start of the code.
142 unsigned returnAddressOffset(Call call
)
144 return MacroAssembler::getLinkerCallReturnOffset(call
);
147 // Upon completion of all patching either 'finalizeCode()' or 'finalizeCodeAddendum()' should be called
148 // once to complete generation of the code. 'finalizeCode()' is suited to situations
149 // where the executable pool must also be retained, the lighter-weight 'finalizeCodeAddendum()' is
150 // suited to adding to an existing allocation.
151 CodeRef
finalizeCode()
153 performFinalization();
155 return CodeRef(m_code
, m_executablePool
, m_size
);
157 CodeLocationLabel
finalizeCodeAddendum()
159 performFinalization();
161 return CodeLocationLabel(code());
165 // Keep this private! - the underlying code should only be obtained externally via
166 // finalizeCode() or finalizeCodeAddendum().
172 void performFinalization()
175 ASSERT(!m_completed
);
179 ExecutableAllocator::makeExecutable(code(), m_size
);
180 ExecutableAllocator::cacheFlush(code(), m_size
);
183 RefPtr
<ExecutablePool
> m_executablePool
;
193 #endif // ENABLE(ASSEMBLER)
195 #endif // LinkBuffer_h