summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/assembler
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2012-11-22 09:09:45 +0100
committerSimon Hausmann <simon.hausmann@digia.com>2012-11-22 09:10:13 +0100
commit470286ecfe79d59df14944e5b5d34630fc739391 (patch)
tree43983212872e06cebefd2ae474418fa2908ca54c /Source/JavaScriptCore/assembler
parent23037105e948c2065da5a937d3a2396b0ff45c1e (diff)
downloadqtwebkit-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.h112
-rw-r--r--Source/JavaScriptCore/assembler/AbstractMacroAssembler.h7
-rw-r--r--Source/JavaScriptCore/assembler/LinkBuffer.cpp23
-rw-r--r--Source/JavaScriptCore/assembler/LinkBuffer.h14
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerARM.h13
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h24
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h14
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerX86.h34
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h4
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h27
-rw-r--r--Source/JavaScriptCore/assembler/RepatchBuffer.h28
-rw-r--r--Source/JavaScriptCore/assembler/SH4Assembler.h2
-rw-r--r--Source/JavaScriptCore/assembler/X86Assembler.h78
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));