diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-22 09:09:45 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-22 09:10:13 +0100 |
commit | 470286ecfe79d59df14944e5b5d34630fc739391 (patch) | |
tree | 43983212872e06cebefd2ae474418fa2908ca54c /Source/JavaScriptCore/assembler | |
parent | 23037105e948c2065da5a937d3a2396b0ff45c1e (diff) | |
download | qtwebkit-470286ecfe79d59df14944e5b5d34630fc739391.tar.gz |
Imported WebKit commit e89504fa9195b2063b2530961d4b73dd08de3242 (http://svn.webkit.org/repository/webkit/trunk@135485)
Change-Id: I03774e5ac79721c13ffa30d152537a74d0b12e66
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'Source/JavaScriptCore/assembler')
-rw-r--r-- | Source/JavaScriptCore/assembler/ARMv7Assembler.h | 112 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/AbstractMacroAssembler.h | 7 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/LinkBuffer.cpp | 23 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/LinkBuffer.h | 14 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/MacroAssemblerARM.h | 13 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h | 24 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h | 14 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/MacroAssemblerX86.h | 34 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h | 4 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h | 27 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/RepatchBuffer.h | 28 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/SH4Assembler.h | 2 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/X86Assembler.h | 78 |
13 files changed, 281 insertions, 99 deletions
diff --git a/Source/JavaScriptCore/assembler/ARMv7Assembler.h b/Source/JavaScriptCore/assembler/ARMv7Assembler.h index e9b9fcc50..b93ec6e63 100644 --- a/Source/JavaScriptCore/assembler/ARMv7Assembler.h +++ b/Source/JavaScriptCore/assembler/ARMv7Assembler.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2010, 2012 Apple Inc. All rights reserved. * Copyright (C) 2010 University of Szeged * * Redistribution and use in source and binary forms, with or without @@ -507,7 +507,7 @@ public: private: // ARMv7, Appx-A.6.3 - bool BadReg(RegisterID reg) + static bool BadReg(RegisterID reg) { return (reg == ARMRegisters::sp) || (reg == ARMRegisters::pc); } @@ -1261,6 +1261,18 @@ public: m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm); } + + static void revertJumpTo_movT3(void* instructionStart, RegisterID rd, ARMThumbImmediate imm) + { + ASSERT(imm.isValid()); + ASSERT(!imm.isEncodedImm()); + ASSERT(!BadReg(rd)); + + uint16_t* address = static_cast<uint16_t*>(instructionStart); + address[0] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, imm); + address[1] = twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, imm); + cacheFlush(address, sizeof(uint16_t) * 2); + } ALWAYS_INLINE void mov(RegisterID rd, ARMThumbImmediate imm) { @@ -1928,7 +1940,6 @@ public: return LinkConditionalBX; const int paddingSize = JUMP_ENUM_SIZE(jumpType); - bool mayTriggerErrata = false; if (jumpType == JumpCondition) { // 2-byte conditional T1 @@ -1937,17 +1948,13 @@ public: return LinkJumpT1; // 4-byte conditional T3 const uint16_t* jumpT3Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT3))); - if (canBeJumpT3(jumpT3Location, to, mayTriggerErrata)) { - if (!mayTriggerErrata) - return LinkJumpT3; - } + if (canBeJumpT3(jumpT3Location, to)) + return LinkJumpT3; // 4-byte conditional T4 with IT const uint16_t* conditionalJumpT4Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkConditionalJumpT4))); - if (canBeJumpT4(conditionalJumpT4Location, to, mayTriggerErrata)) { - if (!mayTriggerErrata) - return LinkConditionalJumpT4; - } + if (canBeJumpT4(conditionalJumpT4Location, to)) + return LinkConditionalJumpT4; } else { // 2-byte unconditional T2 const uint16_t* jumpT2Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT2))); @@ -1955,10 +1962,8 @@ public: return LinkJumpT2; // 4-byte unconditional T4 const uint16_t* jumpT4Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT4))); - if (canBeJumpT4(jumpT4Location, to, mayTriggerErrata)) { - if (!mayTriggerErrata) - return LinkJumpT4; - } + if (canBeJumpT4(jumpT4Location, to)) + return LinkJumpT4; // use long jump sequence return LinkBX; } @@ -2057,12 +2062,12 @@ public: ASSERT(from.isSet()); ASSERT(reinterpret_cast<intptr_t>(to) & 1); - setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to); + setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to, false); } static void linkPointer(void* code, AssemblerLabel where, void* value) { - setPointer(reinterpret_cast<char*>(code) + where.m_offset, value); + setPointer(reinterpret_cast<char*>(code) + where.m_offset, value, false); } static void relinkJump(void* from, void* to) @@ -2080,7 +2085,7 @@ public: ASSERT(!(reinterpret_cast<intptr_t>(from) & 1)); ASSERT(reinterpret_cast<intptr_t>(to) & 1); - setPointer(reinterpret_cast<uint16_t*>(from) - 1, to); + setPointer(reinterpret_cast<uint16_t*>(from) - 1, to, true); } static void* readCallTarget(void* from) @@ -2092,7 +2097,7 @@ public: { ASSERT(!(reinterpret_cast<intptr_t>(where) & 1)); - setInt32(where, value); + setInt32(where, value, true); } static void repatchCompact(void* where, int32_t offset) @@ -2119,7 +2124,7 @@ public: { ASSERT(!(reinterpret_cast<intptr_t>(where) & 1)); - setPointer(where, value); + setPointer(where, value, true); } static void* readPointer(void* where) @@ -2133,22 +2138,13 @@ public: ASSERT(!(bitwise_cast<uintptr_t>(to) & 1)); uint16_t* ptr = reinterpret_cast<uint16_t*>(instructionStart) + 2; - // Ensure that we're not in one of those errata-triggering thingies. If we are, then - // prepend a nop. - bool spansTwo4K = ((reinterpret_cast<intptr_t>(ptr) & 0xfff) == 0x002); - - if (spansTwo4K) { - ptr[-2] = OP_NOP_T1; - ptr++; - } - linkJumpT4(ptr, to); cacheFlush(ptr - 2, sizeof(uint16_t) * 2); } static ptrdiff_t maxJumpReplacementSize() { - return 6; + return 4; } static void replaceWithLoad(void* instructionStart) @@ -2164,11 +2160,11 @@ public: ptr[0] |= OP_LDR_imm_T3; ptr[1] |= (ptr[1] & 0x0F00) << 4; ptr[1] &= 0xF0FF; + cacheFlush(ptr, sizeof(uint16_t) * 2); break; default: ASSERT_NOT_REACHED(); } - cacheFlush(ptr, sizeof(uint16_t) * 2); } static void replaceWithAddressComputation(void* instructionStart) @@ -2182,13 +2178,13 @@ public: ptr[0] |= OP_ADD_imm_T3; ptr[1] |= (ptr[1] & 0xF000) >> 4; ptr[1] &= 0x0FFF; + cacheFlush(ptr, sizeof(uint16_t) * 2); break; case OP_ADD_imm_T3: break; default: ASSERT_NOT_REACHED(); } - cacheFlush(ptr, sizeof(uint16_t) * 2); } unsigned debugOffset() { return m_formatter.debugOffset(); } @@ -2291,7 +2287,7 @@ private: return VFPOperand(op); } - static void setInt32(void* code, uint32_t value) + static void setInt32(void* code, uint32_t value, bool flush) { uint16_t* location = reinterpret_cast<uint16_t*>(code); ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2)); @@ -2303,7 +2299,8 @@ private: location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16); - cacheFlush(location - 4, 4 * sizeof(uint16_t)); + if (flush) + cacheFlush(location - 4, 4 * sizeof(uint16_t)); } static int32_t readInt32(void* code) @@ -2334,9 +2331,9 @@ private: cacheFlush(location, sizeof(uint16_t)); } - static void setPointer(void* code, void* value) + static void setPointer(void* code, void* value, bool flush) { - setInt32(code, reinterpret_cast<uint32_t>(value)); + setInt32(code, reinterpret_cast<uint32_t>(value), flush); } static bool isB(void* address) @@ -2401,46 +2398,22 @@ private: return ((relative << 20) >> 20) == relative; } - static bool canBeJumpT3(const uint16_t* instruction, const void* target, bool& mayTriggerErrata) + static bool canBeJumpT3(const uint16_t* instruction, const void* target) { ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); - // From Cortex-A8 errata: - // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and - // the target of the branch falls within the first region it is - // possible for the processor to incorrectly determine the branch - // instruction, and it is also possible in some cases for the processor - // to enter a deadlock state. - // The instruction is spanning two pages if it ends at an address ending 0x002 - bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002); - mayTriggerErrata = spansTwo4K; - // The target is in the first page if the jump branch back by [3..0x1002] bytes - bool targetInFirstPage = (relative >= -0x1002) && (relative < -2); - bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage; - return ((relative << 11) >> 11) == relative && !wouldTriggerA8Errata; + return ((relative << 11) >> 11) == relative; } - static bool canBeJumpT4(const uint16_t* instruction, const void* target, bool& mayTriggerErrata) + static bool canBeJumpT4(const uint16_t* instruction, const void* target) { ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); - // From Cortex-A8 errata: - // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and - // the target of the branch falls within the first region it is - // possible for the processor to incorrectly determine the branch - // instruction, and it is also possible in some cases for the processor - // to enter a deadlock state. - // The instruction is spanning two pages if it ends at an address ending 0x002 - bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002); - mayTriggerErrata = spansTwo4K; - // The target is in the first page if the jump branch back by [3..0x1002] bytes - bool targetInFirstPage = (relative >= -0x1002) && (relative < -2); - bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage; - return ((relative << 7) >> 7) == relative && !wouldTriggerA8Errata; + return ((relative << 7) >> 7) == relative; } void linkJumpT1(Condition cond, uint16_t* instruction, void* target) @@ -2484,9 +2457,7 @@ private: // FIMXE: this should be up in the MacroAssembler layer. :-( ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); - bool scratch; - UNUSED_PARAM(scratch); - ASSERT(canBeJumpT3(instruction, target, scratch)); + ASSERT(canBeJumpT3(instruction, target)); intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); @@ -2501,9 +2472,7 @@ private: // FIMXE: this should be up in the MacroAssembler layer. :-( ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); - bool scratch; - UNUSED_PARAM(scratch); - ASSERT(canBeJumpT4(instruction, target, scratch)); + ASSERT(canBeJumpT4(instruction, target)); intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); // ARM encoding for the top two bits below the sign bit is 'peculiar'. @@ -2561,8 +2530,7 @@ private: ASSERT((isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1)) || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2))); - bool scratch; - if (canBeJumpT4(instruction, target, scratch)) { + if (canBeJumpT4(instruction, target)) { // There may be a better way to fix this, but right now put the NOPs first, since in the // case of an conditional branch this will be coming after an ITTT predicating *three* // instructions! Looking backwards to modify the ITTT to an IT is not easy, due to diff --git a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h index c75adb7e9..673031b7a 100644 --- a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h +++ b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h @@ -586,6 +586,13 @@ public: public: typedef Vector<Jump, 16> JumpVector; + + JumpList() { } + + JumpList(Jump jump) + { + append(jump); + } void link(AbstractMacroAssembler<AssemblerType>* masm) { diff --git a/Source/JavaScriptCore/assembler/LinkBuffer.cpp b/Source/JavaScriptCore/assembler/LinkBuffer.cpp index 0176e4307..c269157ba 100644 --- a/Source/JavaScriptCore/assembler/LinkBuffer.cpp +++ b/Source/JavaScriptCore/assembler/LinkBuffer.cpp @@ -45,16 +45,15 @@ LinkBuffer::CodeRef LinkBuffer::finalizeCodeWithDisassembly(const char* format, CodeRef result = finalizeCodeWithoutDisassembly(); - dataLog("Generated JIT code for "); + dataLogF("Generated JIT code for "); va_list argList; va_start(argList, format); - WTF::dataLogV(format, argList); + WTF::dataLogFV(format, argList); va_end(argList); - dataLog(":\n"); + dataLogF(":\n"); - dataLog(" Code at [%p, %p):\n", result.code().executableAddress(), static_cast<char*>(result.code().executableAddress()) + result.size()); - if (!tryToDisassemble(result.code(), m_size, " ", WTF::dataFile())) - dataLog(" <no disassembly available>\n"); + dataLogF(" Code at [%p, %p):\n", result.code().executableAddress(), static_cast<char*>(result.code().executableAddress()) + result.size()); + disassemble(result.code(), m_size, " ", WTF::dataFile()); return result; } @@ -169,11 +168,11 @@ void LinkBuffer::dumpLinkStatistics(void* code, size_t initializeSize, size_t fi linkCount++; totalInitialSize += initialSize; totalFinalSize += finalSize; - dataLog("link %p: orig %u, compact %u (delta %u, %.2f%%)\n", + dataLogF("link %p: orig %u, compact %u (delta %u, %.2f%%)\n", code, static_cast<unsigned>(initialSize), static_cast<unsigned>(finalSize), static_cast<unsigned>(initialSize - finalSize), 100.0 * (initialSize - finalSize) / initialSize); - dataLog("\ttotal %u: orig %u, compact %u (delta %u, %.2f%%)\n", + dataLogF("\ttotal %u: orig %u, compact %u (delta %u, %.2f%%)\n", linkCount, totalInitialSize, totalFinalSize, totalInitialSize - totalFinalSize, 100.0 * (totalInitialSize - totalFinalSize) / totalInitialSize); } @@ -192,7 +191,7 @@ void LinkBuffer::dumpCode(void* code, size_t size) size_t tsize = size / sizeof(short); char nameBuf[128]; snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++); - dataLog("\t.syntax unified\n" + dataLogF("\t.syntax unified\n" "\t.section\t__TEXT,__text,regular,pure_instructions\n" "\t.globl\t%s\n" "\t.align 2\n" @@ -202,7 +201,7 @@ void LinkBuffer::dumpCode(void* code, size_t size) "%s:\n", nameBuf, nameBuf, code, nameBuf); for (unsigned i = 0; i < tsize; i++) - dataLog("\t.short\t0x%x\n", tcode[i]); + dataLogF("\t.short\t0x%x\n", tcode[i]); #elif CPU(ARM_TRADITIONAL) // gcc -c jit.s // objdump -D jit.o @@ -211,7 +210,7 @@ void LinkBuffer::dumpCode(void* code, size_t size) size_t tsize = size / sizeof(unsigned int); char nameBuf[128]; snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++); - dataLog("\t.globl\t%s\n" + dataLogF("\t.globl\t%s\n" "\t.align 4\n" "\t.code 32\n" "\t.text\n" @@ -219,7 +218,7 @@ void LinkBuffer::dumpCode(void* code, size_t size) "%s:\n", nameBuf, code, nameBuf); for (unsigned i = 0; i < tsize; i++) - dataLog("\t.long\t0x%x\n", tcode[i]); + dataLogF("\t.long\t0x%x\n", tcode[i]); #endif } #endif diff --git a/Source/JavaScriptCore/assembler/LinkBuffer.h b/Source/JavaScriptCore/assembler/LinkBuffer.h index 770144d64..e1882433c 100644 --- a/Source/JavaScriptCore/assembler/LinkBuffer.h +++ b/Source/JavaScriptCore/assembler/LinkBuffer.h @@ -263,9 +263,9 @@ private: #endif }; -#define FINALIZE_CODE_IF(condition, linkBufferReference, dataLogArgumentsForHeading) \ +#define FINALIZE_CODE_IF(condition, linkBufferReference, dataLogFArgumentsForHeading) \ (UNLIKELY((condition)) \ - ? ((linkBufferReference).finalizeCodeWithDisassembly dataLogArgumentsForHeading) \ + ? ((linkBufferReference).finalizeCodeWithDisassembly dataLogFArgumentsForHeading) \ : (linkBufferReference).finalizeCodeWithoutDisassembly()) // Use this to finalize code, like so: @@ -281,14 +281,14 @@ private: // // ... and so on. // -// Note that the dataLogArgumentsForHeading are only evaluated when showDisassembly +// Note that the dataLogFArgumentsForHeading are only evaluated when showDisassembly // is true, so you can hide expensive disassembly-only computations inside there. -#define FINALIZE_CODE(linkBufferReference, dataLogArgumentsForHeading) \ - FINALIZE_CODE_IF(Options::showDisassembly(), linkBufferReference, dataLogArgumentsForHeading) +#define FINALIZE_CODE(linkBufferReference, dataLogFArgumentsForHeading) \ + FINALIZE_CODE_IF(Options::showDisassembly(), linkBufferReference, dataLogFArgumentsForHeading) -#define FINALIZE_DFG_CODE(linkBufferReference, dataLogArgumentsForHeading) \ - FINALIZE_CODE_IF(Options::showDFGDisassembly(), linkBufferReference, dataLogArgumentsForHeading) +#define FINALIZE_DFG_CODE(linkBufferReference, dataLogFArgumentsForHeading) \ + FINALIZE_CODE_IF((Options::showDisassembly() || Options::showDFGDisassembly()), linkBufferReference, dataLogFArgumentsForHeading) } // namespace JSC diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h index 39d94adea..0ebdbda0c 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h @@ -1266,6 +1266,19 @@ public: return 0; } + static bool canJumpReplacePatchableBranchPtrWithPatch() { return false; } + + static CodeLocationLabel startOfPatchableBranchPtrWithPatch(CodeLocationDataLabelPtr label) + { + UNREACHABLE_FOR_PLATFORM(); + return CodeLocationLabel(); + } + + static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart, Address, void* initialValue) + { + UNREACHABLE_FOR_PLATFORM(); + } + protected: ARMAssembler::Condition ARMCondition(RelationalCondition cond) { diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h index 1301038e5..8d7a3a69a 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h @@ -1758,6 +1758,30 @@ public: { return FunctionPtr(reinterpret_cast<void(*)()>(ARMv7Assembler::readCallTarget(call.dataLocation()))); } + + static bool canJumpReplacePatchableBranchPtrWithPatch() { return false; } + + static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label) + { + const unsigned twoWordOpSize = 4; + return label.labelAtOffset(-twoWordOpSize * 2); + } + + static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID, void* initialValue) + { + ARMv7Assembler::revertJumpTo_movT3(instructionStart.dataLocation(), dataTempRegister, ARMThumbImmediate::makeUInt16(reinterpret_cast<uintptr_t>(initialValue) & 0xffff)); + } + + static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr) + { + UNREACHABLE_FOR_PLATFORM(); + return CodeLocationLabel(); + } + + static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel, Address, void*) + { + UNREACHABLE_FOR_PLATFORM(); + } protected: ALWAYS_INLINE Jump jump() diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h index fc6f9f40d..5b6da9663 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h @@ -2242,6 +2242,20 @@ public: return 0; } + static bool canJumpReplacePatchableBranchPtrWithPatch() { return false; } + + static CodeLocationLabel startOfPatchableBranchPtrWithPatch(CodeLocationDataLabelPtr label) + { + UNREACHABLE_FOR_PLATFORM(); + return CodeLocationLabel(); + } + + static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart, Address, void* initialValue) + { + UNREACHABLE_FOR_PLATFORM(); + } + + private: // If m_fixedWidth is true, we will generate a fixed number of instructions. // Otherwise, we can emit any number of instructions. diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86.h index 8fd31466d..27a030edf 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86.h @@ -253,6 +253,40 @@ public: return FunctionPtr(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(call.dataLocation()) + offset)); } + static bool canJumpReplacePatchableBranchPtrWithPatch() { return true; } + + static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label) + { + const int opcodeBytes = 1; + const int modRMBytes = 1; + const int immediateBytes = 4; + const int totalBytes = opcodeBytes + modRMBytes + immediateBytes; + ASSERT(totalBytes >= maxJumpReplacementSize()); + return label.labelAtOffset(-totalBytes); + } + + static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr label) + { + const int opcodeBytes = 1; + const int modRMBytes = 1; + const int offsetBytes = 0; + const int immediateBytes = 4; + const int totalBytes = opcodeBytes + modRMBytes + offsetBytes + immediateBytes; + ASSERT(totalBytes >= maxJumpReplacementSize()); + return label.labelAtOffset(-totalBytes); + } + + static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID reg, void* initialValue) + { + X86Assembler::revertJumpTo_cmpl_ir_force32(instructionStart.executableAddress(), reinterpret_cast<intptr_t>(initialValue), reg); + } + + static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart, Address address, void* initialValue) + { + ASSERT(!address.offset); + X86Assembler::revertJumpTo_cmpl_im_force32(instructionStart.executableAddress(), reinterpret_cast<intptr_t>(initialValue), 0, address.base); + } + private: friend class LinkBuffer; friend class RepatchBuffer; diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h index 66db26acb..53cb80c21 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h @@ -826,11 +826,15 @@ public: m_assembler.ucomisd_rr(right, left); if (cond == DoubleEqual) { + if (left == right) + return Jump(m_assembler.jnp()); Jump isUnordered(m_assembler.jp()); Jump result = Jump(m_assembler.je()); isUnordered.link(this); return result; } else if (cond == DoubleNotEqualOrUnordered) { + if (left == right) + return Jump(m_assembler.jp()); Jump isUnordered(m_assembler.jp()); Jump isEqual(m_assembler.je()); isUnordered.link(this); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h index ceacf6aa8..c711e6f8d 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h @@ -585,6 +585,33 @@ public: static RegisterID scratchRegisterForBlinding() { return scratchRegister; } + static bool canJumpReplacePatchableBranchPtrWithPatch() { return true; } + + static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label) + { + const int rexBytes = 1; + const int opcodeBytes = 1; + const int immediateBytes = 8; + const int totalBytes = rexBytes + opcodeBytes + immediateBytes; + ASSERT(totalBytes >= maxJumpReplacementSize()); + return label.labelAtOffset(-totalBytes); + } + + static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr label) + { + return startOfBranchPtrWithPatchOnRegister(label); + } + + static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart, Address, void* initialValue) + { + X86Assembler::revertJumpTo_movq_i64r(instructionStart.executableAddress(), reinterpret_cast<intptr_t>(initialValue), scratchRegister); + } + + static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID, void* initialValue) + { + X86Assembler::revertJumpTo_movq_i64r(instructionStart.executableAddress(), reinterpret_cast<intptr_t>(initialValue), scratchRegister); + } + private: friend class LinkBuffer; friend class RepatchBuffer; diff --git a/Source/JavaScriptCore/assembler/RepatchBuffer.h b/Source/JavaScriptCore/assembler/RepatchBuffer.h index 531dda934..dbb56f9ad 100644 --- a/Source/JavaScriptCore/assembler/RepatchBuffer.h +++ b/Source/JavaScriptCore/assembler/RepatchBuffer.h @@ -141,6 +141,34 @@ public: replaceWithAddressComputation(label); } + static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label) + { + return MacroAssembler::startOfBranchPtrWithPatchOnRegister(label); + } + + static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr label) + { + return MacroAssembler::startOfPatchableBranchPtrWithPatchOnAddress(label); + } + + void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination) + { + MacroAssembler::replaceWithJump(instructionStart, destination); + } + + // This is a *bit* of a silly API, since we currently always also repatch the + // immediate after calling this. But I'm fine with that, since this just feels + // less yucky. + void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, MacroAssembler::RegisterID reg, void* value) + { + MacroAssembler::revertJumpReplacementToBranchPtrWithPatch(instructionStart, reg, value); + } + + void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart, MacroAssembler::Address address, void* value) + { + MacroAssembler::revertJumpReplacementToPatchableBranchPtrWithPatch(instructionStart, address, value); + } + private: void* m_start; size_t m_size; diff --git a/Source/JavaScriptCore/assembler/SH4Assembler.h b/Source/JavaScriptCore/assembler/SH4Assembler.h index 373f469dc..3dbde2fa5 100644 --- a/Source/JavaScriptCore/assembler/SH4Assembler.h +++ b/Source/JavaScriptCore/assembler/SH4Assembler.h @@ -2070,7 +2070,7 @@ public: static void vprintfStdoutInstr(const char* format, va_list args) { if (getenv("JavaScriptCoreDumpJIT")) - WTF::dataLogV(format, args); + WTF::dataLogFV(format, args); } static void printBlockInstr(uint16_t* first, unsigned int offset, int nbInstr) diff --git a/Source/JavaScriptCore/assembler/X86Assembler.h b/Source/JavaScriptCore/assembler/X86Assembler.h index ecb178e88..25ff6f0a5 100644 --- a/Source/JavaScriptCore/assembler/X86Assembler.h +++ b/Source/JavaScriptCore/assembler/X86Assembler.h @@ -1475,6 +1475,12 @@ public: return m_formatter.immediateRel32(); } + AssemblerLabel jnp() + { + m_formatter.twoByteOp(jccRel32(ConditionNP)); + return m_formatter.immediateRel32(); + } + AssemblerLabel jp() { m_formatter.twoByteOp(jccRel32(ConditionP)); @@ -1877,6 +1883,61 @@ public: return 5; } +#if CPU(X86_64) + static void revertJumpTo_movq_i64r(void* instructionStart, int64_t imm, RegisterID dst) + { + const int rexBytes = 1; + const int opcodeBytes = 1; + ASSERT(rexBytes + opcodeBytes <= maxJumpReplacementSize()); + uint8_t* ptr = reinterpret_cast<uint8_t*>(instructionStart); + ptr[0] = PRE_REX | (1 << 3) | (dst >> 3); + ptr[1] = OP_MOV_EAXIv | (dst & 7); + + union { + uint64_t asWord; + uint8_t asBytes[8]; + } u; + u.asWord = imm; + for (unsigned i = rexBytes + opcodeBytes; i < static_cast<unsigned>(maxJumpReplacementSize()); ++i) + ptr[i] = u.asBytes[i - rexBytes - opcodeBytes]; + } +#endif + + static void revertJumpTo_cmpl_ir_force32(void* instructionStart, int32_t imm, RegisterID dst) + { + const int opcodeBytes = 1; + const int modRMBytes = 1; + ASSERT(opcodeBytes + modRMBytes <= maxJumpReplacementSize()); + uint8_t* ptr = reinterpret_cast<uint8_t*>(instructionStart); + ptr[0] = OP_GROUP1_EvIz; + ptr[1] = (X86InstructionFormatter::ModRmRegister << 6) | (GROUP1_OP_CMP << 3) | dst; + union { + uint32_t asWord; + uint8_t asBytes[4]; + } u; + u.asWord = imm; + for (unsigned i = opcodeBytes + modRMBytes; i < static_cast<unsigned>(maxJumpReplacementSize()); ++i) + ptr[i] = u.asBytes[i - opcodeBytes - modRMBytes]; + } + + static void revertJumpTo_cmpl_im_force32(void* instructionStart, int32_t imm, int offset, RegisterID dst) + { + ASSERT_UNUSED(offset, !offset); + const int opcodeBytes = 1; + const int modRMBytes = 1; + ASSERT(opcodeBytes + modRMBytes <= maxJumpReplacementSize()); + uint8_t* ptr = reinterpret_cast<uint8_t*>(instructionStart); + ptr[0] = OP_GROUP1_EvIz; + ptr[1] = (X86InstructionFormatter::ModRmMemoryNoDisp << 6) | (GROUP1_OP_CMP << 3) | dst; + union { + uint32_t asWord; + uint8_t asBytes[4]; + } u; + u.asWord = imm; + for (unsigned i = opcodeBytes + modRMBytes; i < static_cast<unsigned>(maxJumpReplacementSize()); ++i) + ptr[i] = u.asBytes[i - opcodeBytes - modRMBytes]; + } + static void replaceWithLoad(void* instructionStart) { uint8_t* ptr = reinterpret_cast<uint8_t*>(instructionStart); @@ -1976,6 +2037,13 @@ private: public: + enum ModRmMode { + ModRmMemoryNoDisp, + ModRmMemoryDisp8, + ModRmMemoryDisp32, + ModRmRegister, + }; + // Legacy prefix bytes: // // These are emmitted prior to the instruction. @@ -2314,6 +2382,9 @@ private: // Format a REX prefix byte. inline void emitRex(bool w, int r, int x, int b) { + ASSERT(r >= 0); + ASSERT(x >= 0); + ASSERT(b >= 0); m_buffer.putByteUnchecked(PRE_REX | ((int)w << 3) | ((r>>3)<<2) | ((x>>3)<<1) | (b>>3)); } @@ -2343,13 +2414,6 @@ private: inline void emitRexIfNeeded(int, int, int) {} #endif - enum ModRmMode { - ModRmMemoryNoDisp, - ModRmMemoryDisp8, - ModRmMemoryDisp32, - ModRmRegister, - }; - void putModRm(ModRmMode mode, int reg, RegisterID rm) { m_buffer.putByteUnchecked((mode << 6) | ((reg & 7) << 3) | (rm & 7)); |