Changeset 120786 in webkit for trunk/Source/JavaScriptCore/assembler/LinkBuffer.h
- Timestamp:
- Jun 19, 2012, 6:33:30 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/assembler/LinkBuffer.h
r118413 r120786 1 1 /* 2 * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.2 * Copyright (C) 2009, 2010, 2012 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 194 194 } 195 195 196 // Upon completion of all patching ' finalizeCode()' should be called once to complete generation of the code.197 CodeRef finalizeCode()198 {199 performFinalization();200 201 return CodeRef(m_executableMemory);202 }196 // Upon completion of all patching 'FINALIZE_CODE()' should be called once to 197 // complete generation of the code. Alternatively, call 198 // finalizeCodeWithoutDisassembly() directly if you have your own way of 199 // displaying disassembly. 200 201 CodeRef finalizeCodeWithoutDisassembly(); 202 CodeRef finalizeCodeWithDisassembly(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3); 203 203 204 204 CodePtr trampolineAt(Label label) … … 232 232 } 233 233 234 void linkCode(void* ownerUID, JITCompilationEffort effort) 235 { 236 ASSERT(!m_code); 237 #if !ENABLE(BRANCH_COMPACTION) 238 m_executableMemory = m_assembler->m_assembler.executableCopy(*m_globalData, ownerUID, effort); 239 if (!m_executableMemory) 240 return; 241 m_code = m_executableMemory->start(); 242 m_size = m_assembler->m_assembler.codeSize(); 243 ASSERT(m_code); 244 #else 245 m_initialSize = m_assembler->m_assembler.codeSize(); 246 m_executableMemory = m_globalData->executableAllocator.allocate(*m_globalData, m_initialSize, ownerUID, effort); 247 if (!m_executableMemory) 248 return; 249 m_code = (uint8_t*)m_executableMemory->start(); 250 ASSERT(m_code); 251 ExecutableAllocator::makeWritable(m_code, m_initialSize); 252 uint8_t* inData = (uint8_t*)m_assembler->unlinkedCode(); 253 uint8_t* outData = reinterpret_cast<uint8_t*>(m_code); 254 int readPtr = 0; 255 int writePtr = 0; 256 Vector<LinkRecord>& jumpsToLink = m_assembler->jumpsToLink(); 257 unsigned jumpCount = jumpsToLink.size(); 258 for (unsigned i = 0; i < jumpCount; ++i) { 259 int offset = readPtr - writePtr; 260 ASSERT(!(offset & 1)); 261 262 // Copy the instructions from the last jump to the current one. 263 size_t regionSize = jumpsToLink[i].from() - readPtr; 264 uint16_t* copySource = reinterpret_cast_ptr<uint16_t*>(inData + readPtr); 265 uint16_t* copyEnd = reinterpret_cast_ptr<uint16_t*>(inData + readPtr + regionSize); 266 uint16_t* copyDst = reinterpret_cast_ptr<uint16_t*>(outData + writePtr); 267 ASSERT(!(regionSize % 2)); 268 ASSERT(!(readPtr % 2)); 269 ASSERT(!(writePtr % 2)); 270 while (copySource != copyEnd) 271 *copyDst++ = *copySource++; 272 m_assembler->recordLinkOffsets(readPtr, jumpsToLink[i].from(), offset); 273 readPtr += regionSize; 274 writePtr += regionSize; 275 276 // Calculate absolute address of the jump target, in the case of backwards 277 // branches we need to be precise, forward branches we are pessimistic 278 const uint8_t* target; 279 if (jumpsToLink[i].to() >= jumpsToLink[i].from()) 280 target = outData + jumpsToLink[i].to() - offset; // Compensate for what we have collapsed so far 281 else 282 target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to()); 283 284 JumpLinkType jumpLinkType = m_assembler->computeJumpType(jumpsToLink[i], outData + writePtr, target); 285 // Compact branch if we can... 286 if (m_assembler->canCompact(jumpsToLink[i].type())) { 287 // Step back in the write stream 288 int32_t delta = m_assembler->jumpSizeDelta(jumpsToLink[i].type(), jumpLinkType); 289 if (delta) { 290 writePtr -= delta; 291 m_assembler->recordLinkOffsets(jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr); 292 } 293 } 294 jumpsToLink[i].setFrom(writePtr); 295 } 296 // Copy everything after the last jump 297 memcpy(outData + writePtr, inData + readPtr, m_initialSize - readPtr); 298 m_assembler->recordLinkOffsets(readPtr, m_initialSize, readPtr - writePtr); 299 300 for (unsigned i = 0; i < jumpCount; ++i) { 301 uint8_t* location = outData + jumpsToLink[i].from(); 302 uint8_t* target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to()); 303 m_assembler->link(jumpsToLink[i], location, target); 304 } 305 306 jumpsToLink.clear(); 307 m_size = writePtr + m_initialSize - readPtr; 308 m_executableMemory->shrink(m_size); 234 void linkCode(void* ownerUID, JITCompilationEffort); 235 236 void performFinalization(); 309 237 310 238 #if DUMP_LINK_STATISTICS 311 dumpLinkStatistics(m_code, m_initialSize, m_size); 312 #endif 239 static void dumpLinkStatistics(void* code, size_t initialSize, size_t finalSize); 240 #endif 241 313 242 #if DUMP_CODE 314 dumpCode(m_code, m_size); 315 #endif 316 #endif 317 } 318 319 void performFinalization() 320 { 321 #ifndef NDEBUG 322 ASSERT(!m_completed); 323 ASSERT(isValid()); 324 m_completed = true; 325 #endif 326 327 #if ENABLE(BRANCH_COMPACTION) 328 ExecutableAllocator::makeExecutable(code(), m_initialSize); 329 #else 330 ExecutableAllocator::makeExecutable(code(), m_size); 331 #endif 332 MacroAssembler::cacheFlush(code(), m_size); 333 } 334 335 #if DUMP_LINK_STATISTICS 336 static void dumpLinkStatistics(void* code, size_t initialSize, size_t finalSize) 337 { 338 static unsigned linkCount = 0; 339 static unsigned totalInitialSize = 0; 340 static unsigned totalFinalSize = 0; 341 linkCount++; 342 totalInitialSize += initialSize; 343 totalFinalSize += finalSize; 344 dataLog("link %p: orig %u, compact %u (delta %u, %.2f%%)\n", 345 code, static_cast<unsigned>(initialSize), static_cast<unsigned>(finalSize), 346 static_cast<unsigned>(initialSize - finalSize), 347 100.0 * (initialSize - finalSize) / initialSize); 348 dataLog("\ttotal %u: orig %u, compact %u (delta %u, %.2f%%)\n", 349 linkCount, totalInitialSize, totalFinalSize, totalInitialSize - totalFinalSize, 350 100.0 * (totalInitialSize - totalFinalSize) / totalInitialSize); 351 } 352 #endif 353 354 #if DUMP_CODE 355 static void dumpCode(void* code, size_t size) 356 { 357 #if CPU(ARM_THUMB2) 358 // Dump the generated code in an asm file format that can be assembled and then disassembled 359 // for debugging purposes. For example, save this output as jit.s: 360 // gcc -arch armv7 -c jit.s 361 // otool -tv jit.o 362 static unsigned codeCount = 0; 363 unsigned short* tcode = static_cast<unsigned short*>(code); 364 size_t tsize = size / sizeof(short); 365 char nameBuf[128]; 366 snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++); 367 dataLog("\t.syntax unified\n" 368 "\t.section\t__TEXT,__text,regular,pure_instructions\n" 369 "\t.globl\t%s\n" 370 "\t.align 2\n" 371 "\t.code 16\n" 372 "\t.thumb_func\t%s\n" 373 "# %p\n" 374 "%s:\n", nameBuf, nameBuf, code, nameBuf); 375 376 for (unsigned i = 0; i < tsize; i++) 377 dataLog("\t.short\t0x%x\n", tcode[i]); 378 #elif CPU(ARM_TRADITIONAL) 379 // gcc -c jit.s 380 // objdump -D jit.o 381 static unsigned codeCount = 0; 382 unsigned int* tcode = static_cast<unsigned int*>(code); 383 size_t tsize = size / sizeof(unsigned int); 384 char nameBuf[128]; 385 snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++); 386 dataLog("\t.globl\t%s\n" 387 "\t.align 4\n" 388 "\t.code 32\n" 389 "\t.text\n" 390 "# %p\n" 391 "%s:\n", nameBuf, code, nameBuf); 392 393 for (unsigned i = 0; i < tsize; i++) 394 dataLog("\t.long\t0x%x\n", tcode[i]); 395 #endif 396 } 243 static void dumpCode(void* code, size_t); 397 244 #endif 398 245 … … 411 258 }; 412 259 260 // Use this to finalize code, like so: 261 // 262 // CodeRef code = FINALIZE_CODE(linkBuffer, ("my super thingy number %d", number)); 263 // 264 // Which, in disassembly mode, will print: 265 // 266 // Generated JIT code for my super thingy number 42: 267 // Code at [0x123456, 0x234567]: 268 // 0x123456: mov $0, 0 269 // 0x12345a: ret 270 // 271 // ... and so on. 272 // 273 // Note that the dataLogArgumentsForHeading are only evaluated when showDisassembly 274 // is true, so you can hide expensive disassembly-only computations inside there. 275 276 #define FINALIZE_CODE(linkBufferReference, dataLogArgumentsForHeading) \ 277 (UNLIKELY(Options::showDisassembly) \ 278 ? ((linkBufferReference).finalizeCodeWithDisassembly dataLogArgumentsForHeading) \ 279 : (linkBufferReference).finalizeCodeWithoutDisassembly()) 280 413 281 } // namespace JSC 414 282
Note:
See TracChangeset
for help on using the changeset viewer.