Changeset 65042 in webkit for trunk/JavaScriptCore/assembler/LinkBuffer.h
- Timestamp:
- Aug 9, 2010, 8:19:19 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/assembler/LinkBuffer.h
r64608 r65042 50 50 class LinkBuffer : public Noncopyable { 51 51 typedef MacroAssemblerCodeRef CodeRef; 52 typedef MacroAssemblerCodePtr CodePtr; 52 53 typedef MacroAssembler::Label Label; 53 54 typedef MacroAssembler::Jump Jump; … … 56 57 typedef MacroAssembler::DataLabel32 DataLabel32; 57 58 typedef MacroAssembler::DataLabelPtr DataLabelPtr; 59 typedef MacroAssembler::JmpDst JmpDst; 60 #if ENABLE(BRANCH_COMPACTION) 61 typedef MacroAssembler::LinkRecord LinkRecord; 62 typedef MacroAssembler::JumpLinkType JumpLinkType; 63 #endif 58 64 59 65 enum LinkBufferState { … … 67 73 // First, executablePool is copied into m_executablePool, then the initialization of 68 74 // m_code uses m_executablePool, *not* executablePool, since this is no longer valid. 69 LinkBuffer(MacroAssembler* masm, PassRefPtr<ExecutablePool> executablePool) 75 // The linkOffset parameter should only be non-null when recompiling for exception info 76 LinkBuffer(MacroAssembler* masm, PassRefPtr<ExecutablePool> executablePool, void* linkOffset) 70 77 : m_executablePool(executablePool) 71 , m_code(masm->m_assembler.executableCopy(m_executablePool.get())) 72 , m_size(masm->m_assembler.size()) 78 , m_size(0) 79 , m_code(0) 80 , m_assembler(masm) 73 81 #ifndef NDEBUG 74 82 , m_state(StateInit) 75 83 #endif 76 84 { 85 linkCode(linkOffset); 77 86 } 78 87 … … 98 107 { 99 108 ASSERT(call.isFlagSet(Call::Linkable)); 109 call.m_jmp = applyOffset(call.m_jmp); 100 110 MacroAssembler::linkCall(code(), call, function); 101 111 } … … 103 113 void link(Jump jump, CodeLocationLabel label) 104 114 { 115 jump.m_jmp = applyOffset(jump.m_jmp); 105 116 MacroAssembler::linkJump(code(), jump, label); 106 117 } … … 109 120 { 110 121 for (unsigned i = 0; i < list.m_jumps.size(); ++i) 111 MacroAssembler::linkJump(code(),list.m_jumps[i], label);122 link(list.m_jumps[i], label); 112 123 } 113 124 114 125 void patch(DataLabelPtr label, void* value) 115 126 { 116 MacroAssembler::linkPointer(code(), label.m_label, value); 127 JmpDst target = applyOffset(label.m_label); 128 MacroAssembler::linkPointer(code(), target, value); 117 129 } 118 130 119 131 void patch(DataLabelPtr label, CodeLocationLabel value) 120 132 { 121 MacroAssembler::linkPointer(code(), label.m_label, value.executableAddress()); 133 JmpDst target = applyOffset(label.m_label); 134 MacroAssembler::linkPointer(code(), target, value.executableAddress()); 122 135 } 123 136 … … 128 141 ASSERT(call.isFlagSet(Call::Linkable)); 129 142 ASSERT(!call.isFlagSet(Call::Near)); 130 return CodeLocationCall(MacroAssembler::getLinkerAddress(code(), call.m_jmp));143 return CodeLocationCall(MacroAssembler::getLinkerAddress(code(), applyOffset(call.m_jmp))); 131 144 } 132 145 … … 135 148 ASSERT(call.isFlagSet(Call::Linkable)); 136 149 ASSERT(call.isFlagSet(Call::Near)); 137 return CodeLocationNearCall(MacroAssembler::getLinkerAddress(code(), call.m_jmp));150 return CodeLocationNearCall(MacroAssembler::getLinkerAddress(code(), applyOffset(call.m_jmp))); 138 151 } 139 152 140 153 CodeLocationLabel locationOf(Label label) 141 154 { 142 return CodeLocationLabel(MacroAssembler::getLinkerAddress(code(), label.m_label));155 return CodeLocationLabel(MacroAssembler::getLinkerAddress(code(), applyOffset(label.m_label))); 143 156 } 144 157 145 158 CodeLocationDataLabelPtr locationOf(DataLabelPtr label) 146 159 { 147 return CodeLocationDataLabelPtr(MacroAssembler::getLinkerAddress(code(), label.m_label));160 return CodeLocationDataLabelPtr(MacroAssembler::getLinkerAddress(code(), applyOffset(label.m_label))); 148 161 } 149 162 150 163 CodeLocationDataLabel32 locationOf(DataLabel32 label) 151 164 { 152 return CodeLocationDataLabel32(MacroAssembler::getLinkerAddress(code(), label.m_label));165 return CodeLocationDataLabel32(MacroAssembler::getLinkerAddress(code(), applyOffset(label.m_label))); 153 166 } 154 167 … … 157 170 unsigned returnAddressOffset(Call call) 158 171 { 172 call.m_jmp = applyOffset(call.m_jmp); 159 173 return MacroAssembler::getLinkerCallReturnOffset(call); 160 174 } … … 170 184 return CodeRef(m_code, m_executablePool, m_size); 171 185 } 186 172 187 CodeLocationLabel finalizeCodeAddendum() 173 188 { … … 177 192 } 178 193 194 CodePtr trampolineAt(Label label) 195 { 196 return CodePtr(MacroAssembler::AssemblerType_T::getRelocatedAddress(code(), applyOffset(label.m_label))); 197 } 198 179 199 private: 200 template <typename T> T applyOffset(T src) 201 { 202 #if ENABLE(BRANCH_COMPACTION) 203 src.m_offset -= m_assembler->executableOffsetFor(src.m_offset); 204 #endif 205 return src; 206 } 207 180 208 // Keep this private! - the underlying code should only be obtained externally via 181 209 // finalizeCode() or finalizeCodeAddendum(). … … 185 213 } 186 214 215 void linkCode(void* linkOffset) 216 { 217 UNUSED_PARAM(linkOffset); 218 ASSERT(!m_code); 219 #if !ENABLE(BRANCH_COMPACTION) 220 m_code = m_assembler->m_assembler.executableCopy(m_executablePool.get()); 221 m_size = m_assembler->size(); 222 #else 223 size_t initialSize = m_assembler->size(); 224 m_code = (uint8_t*)m_executablePool->alloc(initialSize); 225 if (!m_code) 226 return; 227 ExecutableAllocator::makeWritable(m_code, m_assembler->size()); 228 uint8_t* inData = (uint8_t*)m_assembler->unlinkedCode(); 229 uint8_t* outData = reinterpret_cast<uint8_t*>(m_code); 230 const uint8_t* linkBase = linkOffset ? reinterpret_cast<uint8_t*>(linkOffset) : outData; 231 int readPtr = 0; 232 int writePtr = 0; 233 Vector<LinkRecord>& jumpsToLink = m_assembler->jumpsToLink(); 234 unsigned jumpCount = jumpsToLink.size(); 235 for (unsigned i = 0; i < jumpCount; ++i) { 236 int offset = readPtr - writePtr; 237 ASSERT(!(offset & 1)); 238 239 // Copy the instructions from the last jump to the current one. 240 size_t regionSize = jumpsToLink[i].from() - readPtr; 241 memcpy(outData + writePtr, inData + readPtr, regionSize); 242 m_assembler->recordLinkOffsets(readPtr, jumpsToLink[i].from(), offset); 243 readPtr += regionSize; 244 writePtr += regionSize; 245 246 // Calculate absolute address of the jump target, in the case of backwards 247 // branches we need to be precise, forward branches we are pessimistic 248 const uint8_t* target; 249 if (jumpsToLink[i].to() >= jumpsToLink[i].from()) 250 target = linkBase + jumpsToLink[i].to() - offset; // Compensate for what we have collapsed so far 251 else 252 target = linkBase + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to()); 253 254 JumpLinkType jumpLinkType = m_assembler->computeJumpType(jumpsToLink[i], linkBase + writePtr, target); 255 256 // Step back in the write stream 257 int32_t delta = m_assembler->jumpSizeDelta(jumpLinkType); 258 if (delta) { 259 writePtr -= delta; 260 m_assembler->recordLinkOffsets(jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr); 261 } 262 jumpsToLink[i].setFrom(writePtr); 263 } 264 // Copy everything after the last jump 265 memcpy(outData + writePtr, inData + readPtr, m_assembler->size() - readPtr); 266 m_assembler->recordLinkOffsets(readPtr, m_assembler->size(), readPtr - writePtr); 267 268 // Actually link everything (don't link if we've be given a linkoffset as it's a 269 // waste of time: linkOffset is used for recompiling to get exception info) 270 if (!linkOffset) { 271 for (unsigned i = 0; i < jumpCount; ++i) { 272 uint8_t* location = outData + jumpsToLink[i].from(); 273 uint8_t* target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to()); 274 m_assembler->link(jumpsToLink[i], location, target); 275 } 276 } 277 278 jumpsToLink.clear(); 279 m_size = writePtr + m_assembler->size() - readPtr; 280 m_executablePool->returnLastBytes(initialSize - m_size); 281 #endif 282 } 283 187 284 void performFinalization() 188 285 { … … 197 294 198 295 RefPtr<ExecutablePool> m_executablePool; 296 size_t m_size; 199 297 void* m_code; 200 size_t m_size;298 MacroAssembler* m_assembler; 201 299 #ifndef NDEBUG 202 300 LinkBufferState m_state;
Note:
See TracChangeset
for help on using the changeset viewer.