Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (99903 => 99904)
--- trunk/Source/_javascript_Core/ChangeLog 2011-11-10 23:01:27 UTC (rev 99903)
+++ trunk/Source/_javascript_Core/ChangeLog 2011-11-10 23:02:33 UTC (rev 99904)
@@ -1,3 +1,55 @@
+2011-11-10 Gavin Barraclough <[email protected]>
+
+ Add ARMv7 support to the DFG JIT
+ https://bugs.webkit.org/show_bug.cgi?id=72061
+
+ Reviewed by Geoff Garen.
+
+ * dfg/DFGAssemblyHelpers.h:
+ (JSC::DFG::AssemblyHelpers::preserveReturnAddressAfterCall):
+ (JSC::DFG::AssemblyHelpers::restoreReturnAddressBeforeReturn):
+ (JSC::DFG::AssemblyHelpers::emitPutImmediateToCallFrameHeader):
+ (JSC::DFG::AssemblyHelpers::boxDouble):
+ (JSC::DFG::AssemblyHelpers::unboxDouble):
+ - Add CPU(ARM) copies of these functions.
+ * dfg/DFGJITCodeGenerator.h:
+ (JSC::DFG::JITCodeGenerator::spill):
+ - Fix matching of '}' re #if blocks, makes some tools happy.
+ (JSC::DFG::JITCodeGenerator::setupArguments):
+ (JSC::DFG::JITCodeGenerator::setupArgumentsWithExecState):
+ (JSC::DFG::JITCodeGenerator::appendCallWithExceptionCheckSetResult):
+ (JSC::DFG::JITCodeGenerator::appendCallSetResult):
+ - Add CPU(ARM) / 4 argument register copies of these functions.
+ * dfg/DFGJITCodeGenerator32_64.cpp:
+ (JSC::DFG::JITCodeGenerator::nonSpeculativeValueToInt32):
+ - Should use callOperation to plant a call to a DFG_OPERATION.
+ (JSC::DFG::JITCodeGenerator::cachedGetById):
+ (JSC::DFG::JITCodeGenerator::cachedPutById):
+ - These methods need to plant a relinkable jump; we currently do so
+ using beginUninterruptedSequence() / endUninterruptedSequence().
+ * dfg/DFGJITCodeGenerator64.cpp:
+ (JSC::DFG::JITCodeGenerator::nonSpeculativeValueToInt32):
+ - Should use callOperation to plant a call to a DFG_OPERATION.
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::linkOSRExits):
+ - This method needs to plant a relinkable jump; we currently do so
+ using beginUninterruptedSequence() / endUninterruptedSequence().
+ (JSC::DFG::JITCompiler::compileBody):
+ - Add abstraction to retrieve the pc after a call.
+ * dfg/DFGOSRExitCompiler.cpp:
+ - Fix a bug - CodeLocationLabel needs a data address rather than an
+ executable one, but can just take a MacroAssemblerCodePtr instead!
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::compileClampDoubleToByte):
+ - Add FIXME comment to come back to! - bug#72054.
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::speculationCheck):
+ - Add missing method (ooops, required by bug#72047)
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ - Need to wrap fmod on ARMv7.
+
+
2011-11-10 Filip Pizlo <[email protected]>
DFG should not reparse code that was just parsed
Modified: trunk/Source/_javascript_Core/dfg/DFGAssemblyHelpers.h (99903 => 99904)
--- trunk/Source/_javascript_Core/dfg/DFGAssemblyHelpers.h 2011-11-10 23:01:27 UTC (rev 99903)
+++ trunk/Source/_javascript_Core/dfg/DFGAssemblyHelpers.h 2011-11-10 23:02:33 UTC (rev 99904)
@@ -71,6 +71,34 @@
push(address);
}
+ void getPCAfterCall(GPRReg gpr)
+ {
+ peek(gpr, -1);
+ }
+#endif // CPU(X86_64) || CPU(X86)
+
+#if CPU(ARM)
+ ALWAYS_INLINE void preserveReturnAddressAfterCall(RegisterID reg)
+ {
+ move(linkRegister, reg);
+ }
+
+ ALWAYS_INLINE void restoreReturnAddressBeforeReturn(RegisterID reg)
+ {
+ move(reg, linkRegister);
+ }
+
+ ALWAYS_INLINE void restoreReturnAddressBeforeReturn(Address address)
+ {
+ loadPtr(address, linkRegister);
+ }
+
+ ALWAYS_INLINE void getPCAfterCall(GPRReg gpr)
+ {
+ move(ARMRegisters::lr, gpr);
+ }
+#endif
+
void emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, GPRReg to)
{
loadPtr(Address(GPRInfo::callFrameRegister, entry * sizeof(Register)), to);
@@ -84,7 +112,6 @@
{
storePtr(TrustedImmPtr(value), Address(GPRInfo::callFrameRegister, entry * sizeof(Register)));
}
-#endif // CPU(X86_64) || CPU(X86)
Jump branchIfNotCell(GPRReg reg)
{
@@ -132,6 +159,7 @@
#ifndef NDEBUG
// Add a debug call. This call has no effect on JIT code execution state.
+#if CPU(X86_64) || CPU(X86)
void debugCall(V_DFGDebugOperation_EP function, void* argument)
{
EncodedJSValue* buffer = static_cast<EncodedJSValue*>(m_globalData->scratchBufferForSize(sizeof(EncodedJSValue) * (GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters)));
@@ -160,7 +188,16 @@
for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i)
loadPtr(buffer + i, GPRInfo::toRegister(i));
}
+#else
+ void debugCall(V_DFGDebugOperation_EP function, void* argument) NO_RETURN_DUE_TO_ASSERT
+ {
+ // debugCall not supported on this platform.
+ UNUSED_PARAM(function);
+ UNUSED_PARAM(argument);
+ ASSERT_NOT_REACHED();
+ }
#endif
+#endif
// These methods JIT generate dynamic, debug-only checks - akin to ASSERTs.
#if DFG_ENABLE(JIT_ASSERT)
@@ -192,25 +229,36 @@
movePtrToDouble(gpr, fpr);
return fpr;
}
-#elif USE(JSVALUE32_64)
+#endif
+
+#if USE(JSVALUE32_64) && CPU(X86)
void boxDouble(FPRReg fpr, GPRReg tagGPR, GPRReg payloadGPR)
{
-#if CPU(X86)
movePackedToInt32(fpr, payloadGPR);
rshiftPacked(TrustedImm32(32), fpr);
movePackedToInt32(fpr, tagGPR);
-#endif
}
void unboxDouble(GPRReg tagGPR, GPRReg payloadGPR, FPRReg fpr, FPRReg scratchFPR)
{
jitAssertIsJSDouble(tagGPR);
-#if CPU(X86)
moveInt32ToPacked(payloadGPR, fpr);
moveInt32ToPacked(tagGPR, scratchFPR);
lshiftPacked(TrustedImm32(32), scratchFPR);
orPacked(scratchFPR, fpr);
+ }
#endif
+
+#if USE(JSVALUE32_64) && CPU(ARM)
+ void boxDouble(FPRReg fpr, GPRReg tagGPR, GPRReg payloadGPR)
+ {
+ m_assembler.vmov(payloadGPR, tagGPR, fpr);
}
+ void unboxDouble(GPRReg tagGPR, GPRReg payloadGPR, FPRReg fpr, FPRReg scratchFPR)
+ {
+ jitAssertIsJSDouble(tagGPR);
+ UNUSED_PARAM(scratchFPR);
+ m_assembler.vmov(fpr, payloadGPR, tagGPR);
+ }
#endif
#if ENABLE(SAMPLING_COUNTERS)
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h (99903 => 99904)
--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h 2011-11-10 23:01:27 UTC (rev 99903)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h 2011-11-10 23:02:33 UTC (rev 99904)
@@ -592,7 +592,6 @@
m_jit.storePtr(reg, JITCompiler::addressFor(spillMe));
info.spill((DataFormat)(spillFormat | DataFormatJS));
return;
- }
#elif USE(JSVALUE32_64)
case DataFormatDouble:
case DataFormatJSDouble: {
@@ -621,8 +620,8 @@
}
info.spill((DataFormat)(spillFormat | DataFormatJS));
return;
+#endif
}
-#endif
}
bool isStrictInt32(NodeIndex);
@@ -972,7 +971,7 @@
// On X86 we use cdecl calling conventions, which pass all arguments on the
// stack. On other architectures we may need to sort values into the
// correct registers.
-#if CPU(X86)
+#if !NUMBER_OF_ARGUMENT_REGISTERS
unsigned m_callArgumentIndex;
void resetCallArguments() { m_callArgumentIndex = 0; }
@@ -1128,7 +1127,10 @@
addCallArgument(arg4);
addCallArgument(arg5);
}
-#else
+#endif // !NUMBER_OF_ARGUMENT_REGISTERS
+ // These methods are suitable for any calling convention that provides for
+ // at least 4 argument registers, e.g. X86_64, ARMv7.
+#if NUMBER_OF_ARGUMENT_REGISTERS >= 4
template<GPRReg destA, GPRReg destB>
void setupTwoStubArgs(GPRReg srcA, GPRReg srcB)
{
@@ -1157,6 +1159,7 @@
} else
m_jit.swap(destA, destB);
}
+#if CPU(X86_64)
template<FPRReg destA, FPRReg destB>
void setupTwoStubArgs(FPRReg srcA, FPRReg srcB)
{
@@ -1203,6 +1206,7 @@
m_jit.moveDouble(destB, destA);
m_jit.moveDouble(temp, destB);
}
+#endif
void setupStubArguments(GPRReg arg1, GPRReg arg2)
{
setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(arg1, arg2);
@@ -1259,6 +1263,7 @@
m_jit.swap(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3);
}
+#if CPU(X86_64)
ALWAYS_INLINE void setupArguments(FPRReg arg1)
{
m_jit.moveDouble(arg1, FPRInfo::argumentFPR0);
@@ -1268,7 +1273,19 @@
{
setupTwoStubArgs<FPRInfo::argumentFPR0, FPRInfo::argumentFPR1>(arg1, arg2);
}
+#else
+ ALWAYS_INLINE void setupArguments(FPRReg arg1)
+ {
+ m_jit.assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1);
+ }
+ ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
+ {
+ m_jit.assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1);
+ m_jit.assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg2);
+ }
+#endif
+
ALWAYS_INLINE void setupArgumentsExecState()
{
m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
@@ -1326,14 +1343,64 @@
m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
}
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3)
+ {
+ setupStubArguments(arg1, arg2);
+ m_jit.move(arg3, GPRInfo::argumentGPR3);
+ m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3)
{
setupStubArguments(arg1, arg2);
m_jit.move(arg3, GPRInfo::argumentGPR3);
m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
}
-#endif
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3)
+ {
+ m_jit.move(arg1, GPRInfo::argumentGPR1);
+ m_jit.move(arg2, GPRInfo::argumentGPR2);
+ m_jit.move(arg3, GPRInfo::argumentGPR3);
+ m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
+#endif // NUMBER_OF_ARGUMENT_REGISTERS >= 4
+ // These methods are suitable for any calling convention that provides for
+ // exactly 4 argument registers, e.g. ARMv7.
+#if NUMBER_OF_ARGUMENT_REGISTERS == 4
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
+ {
+ m_jit.poke(arg4);
+ setupArgumentsWithExecState(arg1, arg2, arg3);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4)
+ {
+ m_jit.poke(arg4);
+ setupArgumentsWithExecState(arg1, arg2, arg3);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3, GPRReg arg4)
+ {
+ m_jit.poke(arg4);
+ setupArgumentsWithExecState(arg1, arg2, arg3);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
+ {
+ m_jit.poke(arg4);
+ setupArgumentsWithExecState(arg1, arg2, arg3);
+ }
+
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
+ {
+ m_jit.poke(arg5, 1);
+ m_jit.poke(arg4);
+ setupArgumentsWithExecState(arg1, arg2, arg3);
+ }
+#endif // NUMBER_OF_ARGUMENT_REGISTERS == 4
+
// These methods add calls to C++ helper functions.
// These methods are broadly value representation specific (i.e.
// deal with the fact that a JSValue may be passed in one or two
@@ -1687,6 +1754,19 @@
m_jit.loadDouble(JITCompiler::stackPointerRegister, result);
return call;
}
+#elif CPU(ARM)
+ JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, FPRReg result)
+ {
+ JITCompiler::Call call = appendCallWithExceptionCheck(function);
+ m_jit.assembler().vmov(result, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
+ return call;
+ }
+ JITCompiler::Call appendCallSetResult(const FunctionPtr& function, FPRReg result)
+ {
+ JITCompiler::Call call = m_jit.appendCall(function);
+ m_jit.assembler().vmov(result, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
+ return call;
+ }
#else
JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, FPRReg result)
{
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator32_64.cpp (99903 => 99904)
--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator32_64.cpp 2011-11-10 23:01:27 UTC (rev 99903)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator32_64.cpp 2011-11-10 23:02:33 UTC (rev 99904)
@@ -421,13 +421,7 @@
JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);
silentSpillAllRegisters(gpr);
-
- m_jit.subPtr(TrustedImm32(sizeof(double)), JITCompiler::stackPointerRegister);
- m_jit.storeDouble(fpr, JITCompiler::stackPointerRegister);
- appendCallWithExceptionCheck(toInt32);
- m_jit.move(GPRInfo::returnValueGPR, gpr);
- m_jit.addPtr(TrustedImm32(sizeof(double)), JITCompiler::stackPointerRegister);
-
+ callOperation(toInt32, gpr, fpr);
silentFillAllRegisters(gpr);
truncatedToInteger.link(&m_jit);
@@ -857,8 +851,10 @@
{
ASSERT(nodeType == GetById || nodeType == GetMethod);
+ m_jit.beginUninterruptedSequence();
JITCompiler::DataLabelPtr structureToCompare;
JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(basePayloadGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
+ m_jit.endUninterruptedSequence();
m_jit.loadPtr(JITCompiler::Address(basePayloadGPR, JSObject::offsetOfPropertyStorage()), resultPayloadGPR);
JITCompiler::DataLabelCompact tagLoadWithPatch = m_jit.load32WithCompactAddressOffsetPatch(JITCompiler::Address(resultPayloadGPR, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR);
@@ -888,8 +884,10 @@
void JITCodeGenerator::cachedPutById(GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)
{
+ m_jit.beginUninterruptedSequence();
JITCompiler::DataLabelPtr structureToCompare;
JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(basePayloadGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
+ m_jit.endUninterruptedSequence();
writeBarrier(basePayloadGPR, valueTagGPR, valueIndex, WriteBarrierForPropertyAccess, scratchGPR);
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator64.cpp (99903 => 99904)
--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator64.cpp 2011-11-10 23:01:27 UTC (rev 99903)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator64.cpp 2011-11-10 23:02:33 UTC (rev 99904)
@@ -426,11 +426,7 @@
JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);
silentSpillAllRegisters(gpr);
-
- m_jit.moveDouble(fpr, FPRInfo::argumentFPR0);
- appendCallWithExceptionCheck(toInt32);
- m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, gpr);
-
+ callOperation(toInt32, gpr, fpr);
silentFillAllRegisters(gpr);
truncatedToInteger.link(&m_jit);
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp (99903 => 99904)
--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp 2011-11-10 23:01:27 UTC (rev 99903)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp 2011-11-10 23:02:33 UTC (rev 99904)
@@ -46,7 +46,9 @@
OSRExit& exit = codeBlock()->osrExit(i);
exit.m_check.initialJump().link(this);
store32(Imm32(i), &globalData()->osrExitIndex);
+ beginUninterruptedSequence();
exit.m_check.switchToLateJump(jump());
+ endUninterruptedSequence();
}
}
@@ -98,7 +100,7 @@
// of the call out from JIT code that threw the exception; this is still
// available on the stack, just below the stack pointer!
move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- peek(GPRInfo::argumentGPR1, -1);
+ getPCAfterCall(GPRInfo::argumentGPR1);
m_calls.append(CallLinkRecord(call(), lookupExceptionHandler));
// lookupExceptionHandler leaves the handler CallFrame* in the returnValueGPR,
// and the address of the handler in returnValueGPR2.
Modified: trunk/Source/_javascript_Core/dfg/DFGOSRExitCompiler.cpp (99903 => 99904)
--- trunk/Source/_javascript_Core/dfg/DFGOSRExitCompiler.cpp 2011-11-10 23:01:27 UTC (rev 99903)
+++ trunk/Source/_javascript_Core/dfg/DFGOSRExitCompiler.cpp 2011-11-10 23:02:33 UTC (rev 99904)
@@ -64,7 +64,7 @@
{
RepatchBuffer repatchBuffer(codeBlock);
- repatchBuffer.relink(exit.m_check.codeLocationForRepatch(codeBlock), CodeLocationLabel(exit.m_code.code().executableAddress()));
+ repatchBuffer.relink(exit.m_check.codeLocationForRepatch(codeBlock), CodeLocationLabel(exit.m_code.code()));
}
globalData->osrExitJumpDestination = exit.m_code.code().executableAddress();
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (99903 => 99904)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2011-11-10 23:01:27 UTC (rev 99903)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2011-11-10 23:02:33 UTC (rev 99904)
@@ -64,6 +64,47 @@
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 16)
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 24)
+#elif COMPILER(GCC) && CPU(ARM_THUMB2)
+
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) \
+ asm ( \
+ ".text" "\n" \
+ ".align 2" "\n" \
+ ".globl " SYMBOL_STRING(function) "\n" \
+ HIDE_SYMBOL(function) "\n" \
+ ".thumb" "\n" \
+ ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
+ SYMBOL_STRING(function) ":" "\n" \
+ "cpy a2, lr" "\n" \
+ "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
+ );
+
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) \
+ asm ( \
+ ".text" "\n" \
+ ".align 2" "\n" \
+ ".globl " SYMBOL_STRING(function) "\n" \
+ HIDE_SYMBOL(function) "\n" \
+ ".thumb" "\n" \
+ ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
+ SYMBOL_STRING(function) ":" "\n" \
+ "cpy a4, lr" "\n" \
+ "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
+ );
+
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) \
+ asm ( \
+ ".text" "\n" \
+ ".align 2" "\n" \
+ ".globl " SYMBOL_STRING(function) "\n" \
+ HIDE_SYMBOL(function) "\n" \
+ ".thumb" "\n" \
+ ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
+ SYMBOL_STRING(function) ":" "\n" \
+ "str lr, [sp, #4]" "\n" \
+ "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
+ );
+
#endif
#define P_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) \
@@ -522,6 +563,19 @@
"mov %edi, 4(%esp)\n"
"jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
);
+#elif CPU(ARM_THUMB2)
+asm (
+".text" "\n"
+".align 2" "\n"
+".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
+HIDE_SYMBOL(getHostCallReturnValue) "\n"
+".thumb" "\n"
+".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n"
+SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
+ "ldr r5, [r5, #-40]" "\n"
+ "cpy r0, r5" "\n"
+ "b " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
+);
#endif
EncodedJSValue DFG_OPERATION getHostCallReturnValueWithExecState(ExecState* exec)
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (99903 => 99904)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2011-11-10 23:01:27 UTC (rev 99903)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2011-11-10 23:02:33 UTC (rev 99904)
@@ -652,6 +652,8 @@
MacroAssembler::Jump tooBig = jit.branchDouble(MacroAssembler::DoubleGreaterThan, source, scratch);
jit.loadDouble(&half, scratch);
+ // FIXME: This should probably just use a floating point round!
+ // https://bugs.webkit.org/show_bug.cgi?id=72054
jit.addDouble(source, scratch);
jit.truncateDoubleToInt32(scratch, result);
MacroAssembler::Jump truncatedInt = jit.jump();
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (99903 => 99904)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2011-11-10 23:01:27 UTC (rev 99903)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2011-11-10 23:02:33 UTC (rev 99904)
@@ -228,6 +228,13 @@
return;
m_jit.codeBlock()->appendOSRExit(OSRExit(jsValueSource, m_jit.valueProfileFor(nodeIndex), jumpToFail, this));
}
+ // Add a set of speculation checks without additional recovery.
+ void speculationCheck(JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail)
+ {
+ Vector<MacroAssembler::Jump, 16> JumpVector = jumpsToFail.jumps();
+ for (unsigned i = 0; i < JumpVector.size(); ++i)
+ speculationCheck(jsValueSource, nodeIndex, JumpVector[i]);
+ }
// Add a speculation check with additional recovery.
void speculationCheck(JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
{
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (99903 => 99904)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2011-11-10 23:01:27 UTC (rev 99903)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2011-11-10 23:02:33 UTC (rev 99904)
@@ -35,7 +35,8 @@
namespace JSC { namespace DFG {
// On Windows we need to wrap fmod; on other platforms we can call it directly.
-#if CALLING_CONVENTION_IS_STDCALL
+// On ARMv7 we assert that all function pointers have to low bit set (point to thumb code).
+#if CALLING_CONVENTION_IS_STDCALL || CPU(ARM_THUMB2)
static double DFG_OPERATION fmodAsDFGOperation(double x, double y)
{
return fmod(x, y);