]> git.saurik.com Git - apple/javascriptcore.git/blame - assembler/LinkBuffer.h
JavaScriptCore-576.tar.gz
[apple/javascriptcore.git] / assembler / LinkBuffer.h
CommitLineData
ba379fdc
A
1/*
2 * Copyright (C) 2009 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 LinkBuffer_h
27#define LinkBuffer_h
28
29#include <wtf/Platform.h>
30
31#if ENABLE(ASSEMBLER)
32
33#include <MacroAssembler.h>
34#include <wtf/Noncopyable.h>
35
36namespace JSC {
37
38// LinkBuffer:
39//
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.
44//
45// Specifically:
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.
51//
52class 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;
60
61public:
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())
69#ifndef NDEBUG
70 , m_completed(false)
71#endif
72 {
73 }
74
75 ~LinkBuffer()
76 {
77 ASSERT(m_completed);
78 }
79
80 // These methods are used to link or set values at code generation time.
81
82 void link(Call call, FunctionPtr function)
83 {
84 ASSERT(call.isFlagSet(Call::Linkable));
85 MacroAssembler::linkCall(code(), call, function);
86 }
87
88 void link(Jump jump, CodeLocationLabel label)
89 {
90 MacroAssembler::linkJump(code(), jump, label);
91 }
92
93 void link(JumpList list, CodeLocationLabel label)
94 {
95 for (unsigned i = 0; i < list.m_jumps.size(); ++i)
96 MacroAssembler::linkJump(code(), list.m_jumps[i], label);
97 }
98
99 void patch(DataLabelPtr label, void* value)
100 {
101 MacroAssembler::linkPointer(code(), label.m_label, value);
102 }
103
104 void patch(DataLabelPtr label, CodeLocationLabel value)
105 {
106 MacroAssembler::linkPointer(code(), label.m_label, value.executableAddress());
107 }
108
109 // These methods are used to obtain handles to allow the code to be relinked / repatched later.
110
111 CodeLocationCall locationOf(Call call)
112 {
113 ASSERT(call.isFlagSet(Call::Linkable));
114 ASSERT(!call.isFlagSet(Call::Near));
115 return CodeLocationCall(MacroAssembler::getLinkerAddress(code(), call.m_jmp));
116 }
117
118 CodeLocationNearCall locationOfNearCall(Call call)
119 {
120 ASSERT(call.isFlagSet(Call::Linkable));
121 ASSERT(call.isFlagSet(Call::Near));
122 return CodeLocationNearCall(MacroAssembler::getLinkerAddress(code(), call.m_jmp));
123 }
124
125 CodeLocationLabel locationOf(Label label)
126 {
127 return CodeLocationLabel(MacroAssembler::getLinkerAddress(code(), label.m_label));
128 }
129
130 CodeLocationDataLabelPtr locationOf(DataLabelPtr label)
131 {
132 return CodeLocationDataLabelPtr(MacroAssembler::getLinkerAddress(code(), label.m_label));
133 }
134
135 CodeLocationDataLabel32 locationOf(DataLabel32 label)
136 {
137 return CodeLocationDataLabel32(MacroAssembler::getLinkerAddress(code(), label.m_label));
138 }
139
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)
143 {
144 return MacroAssembler::getLinkerCallReturnOffset(call);
145 }
146
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()
152 {
153 performFinalization();
154
155 return CodeRef(m_code, m_executablePool, m_size);
156 }
157 CodeLocationLabel finalizeCodeAddendum()
158 {
159 performFinalization();
160
161 return CodeLocationLabel(code());
162 }
163
164private:
165 // Keep this private! - the underlying code should only be obtained externally via
166 // finalizeCode() or finalizeCodeAddendum().
167 void* code()
168 {
169 return m_code;
170 }
171
172 void performFinalization()
173 {
174#ifndef NDEBUG
175 ASSERT(!m_completed);
176 m_completed = true;
177#endif
178
179 ExecutableAllocator::makeExecutable(code(), m_size);
180 ExecutableAllocator::cacheFlush(code(), m_size);
181 }
182
183 RefPtr<ExecutablePool> m_executablePool;
184 void* m_code;
185 size_t m_size;
186#ifndef NDEBUG
187 bool m_completed;
188#endif
189};
190
191} // namespace JSC
192
193#endif // ENABLE(ASSEMBLER)
194
195#endif // LinkBuffer_h