Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (90176 => 90177)
--- trunk/Source/_javascript_Core/ChangeLog 2011-06-30 23:07:15 UTC (rev 90176)
+++ trunk/Source/_javascript_Core/ChangeLog 2011-06-30 23:08:11 UTC (rev 90177)
@@ -1,3 +1,50 @@
+2011-06-30 Oliver Hunt <[email protected]>
+
+ Reviewed by Gavin Barraclough.
+
+ Add optimised paths for a few maths functions
+ https://bugs.webkit.org/show_bug.cgi?id=63757
+
+ This adds specialised thunks for Math.abs, Math.round, Math.ceil,
+ Math.floor, Math.log, and Math.exp as they are apparently more
+ important in real web content than we thought, which is somewhat
+ mind-boggling. On average doubles the performance of the common
+ cases (eg. actually passing numbers in). They're not as efficient
+ as they could be, but this way gives them the most portability.
+
+ * assembler/MacroAssemblerARM.h:
+ (JSC::MacroAssemblerARM::supportsDoubleBitops):
+ (JSC::MacroAssemblerARM::andnotDouble):
+ * assembler/MacroAssemblerARMv7.h:
+ (JSC::MacroAssemblerARMv7::supportsDoubleBitops):
+ (JSC::MacroAssemblerARMv7::andnotDouble):
+ * assembler/MacroAssemblerMIPS.h:
+ (JSC::MacroAssemblerMIPS::andnotDouble):
+ (JSC::MacroAssemblerMIPS::supportsDoubleBitops):
+ * assembler/MacroAssemblerSH4.h:
+ (JSC::MacroAssemblerSH4::supportsDoubleBitops):
+ (JSC::MacroAssemblerSH4::andnotDouble):
+ * assembler/MacroAssemblerX86.h:
+ (JSC::MacroAssemblerX86::supportsDoubleBitops):
+ * assembler/MacroAssemblerX86Common.h:
+ (JSC::MacroAssemblerX86Common::andnotDouble):
+ * assembler/MacroAssemblerX86_64.h:
+ (JSC::MacroAssemblerX86_64::supportsDoubleBitops):
+ * assembler/X86Assembler.h:
+ (JSC::X86Assembler::andnpd_rr):
+ * create_hash_table:
+ * jit/SpecializedThunkJIT.h:
+ (JSC::SpecializedThunkJIT::finalize):
+ (JSC::SpecializedThunkJIT::callDoubleToDouble):
+ * jit/ThunkGenerators.cpp:
+ (JSC::floorThunkGenerator):
+ (JSC::ceilThunkGenerator):
+ (JSC::roundThunkGenerator):
+ (JSC::expThunkGenerator):
+ (JSC::logThunkGenerator):
+ (JSC::absThunkGenerator):
+ * jit/ThunkGenerators.h:
+
2011-06-30 Cary Clark <[email protected]>
Reviewed by James Robinson.
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM.h (90176 => 90177)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM.h 2011-06-30 23:07:15 UTC (rev 90176)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM.h 2011-06-30 23:08:11 UTC (rev 90177)
@@ -789,6 +789,7 @@
{
return s_isVFPPresent;
}
+ bool supportsDoubleBitops() const { return false; }
void loadDouble(ImplicitAddress address, FPRegisterID dest)
{
@@ -855,6 +856,11 @@
{
m_assembler.vsqrt_f64_r(dest, src);
}
+
+ void andnotDouble(FPRegisterID, FPRegisterID)
+ {
+ ASSERT_NOT_REACHED();
+ }
void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
{
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h (90176 => 90177)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h 2011-06-30 23:07:15 UTC (rev 90176)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h 2011-06-30 23:08:11 UTC (rev 90177)
@@ -567,6 +567,7 @@
{
return false;
}
+ bool supportsDoubleBitops() const { return false; }
void loadDouble(ImplicitAddress address, FPRegisterID dest)
{
@@ -646,6 +647,11 @@
{
ASSERT_NOT_REACHED();
}
+
+ void andnotDouble(FPRegisterID, FPRegisterID)
+ {
+ ASSERT_NOT_REACHED();
+ }
void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
{
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerMIPS.h (90176 => 90177)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerMIPS.h 2011-06-30 23:07:15 UTC (rev 90176)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerMIPS.h 2011-06-30 23:08:11 UTC (rev 90177)
@@ -460,6 +460,11 @@
{
m_assembler.sqrtd(dst, src);
}
+
+ void andnotDouble(FPRegisterID, FPRegisterID)
+ {
+ ASSERT_NOT_REACHED();
+ }
// Memory access operations:
//
@@ -816,6 +821,7 @@
return false;
#endif
}
+ bool supportsDoubleBitops() const { return false; }
// Stack manipulation operations:
//
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerSH4.h (90176 => 90177)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerSH4.h 2011-06-30 23:07:15 UTC (rev 90176)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerSH4.h 2011-06-30 23:08:11 UTC (rev 90177)
@@ -762,6 +762,7 @@
bool supportsFloatingPoint() const { return true; }
bool supportsFloatingPointTruncate() const { return true; }
bool supportsFloatingPointSqrt() const { return true; }
+ bool supportsDoubleBitops() const { return false; }
void loadDouble(ImplicitAddress address, FPRegisterID dest)
{
@@ -1100,6 +1101,11 @@
m_assembler.dmovRegReg(src, dest);
m_assembler.dsqrt(dest);
}
+
+ void andnotDouble(FPRegisterID, FPRegisterID)
+ {
+ ASSERT_NOT_REACHED();
+ }
Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
{
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86.h (90176 => 90177)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86.h 2011-06-30 23:07:15 UTC (rev 90176)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86.h 2011-06-30 23:08:11 UTC (rev 90177)
@@ -166,6 +166,7 @@
// See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
bool supportsFloatingPointTruncate() const { return m_isSSE2Present; }
bool supportsFloatingPointSqrt() const { return m_isSSE2Present; }
+ bool supportsDoubleBitops() const { return m_isSSE2Present; }
private:
const bool m_isSSE2Present;
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (90176 => 90177)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h 2011-06-30 23:07:15 UTC (rev 90176)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h 2011-06-30 23:08:11 UTC (rev 90177)
@@ -423,6 +423,11 @@
m_assembler.sqrtsd_rr(src, dst);
}
+ void andnotDouble(FPRegisterID src, FPRegisterID dst)
+ {
+ m_assembler.andnpd_rr(src, dst);
+ }
+
// Memory access operations:
//
// Loads are of the form load(address, destination) and stores of the form
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h (90176 => 90177)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h 2011-06-30 23:07:15 UTC (rev 90176)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h 2011-06-30 23:08:11 UTC (rev 90177)
@@ -456,6 +456,7 @@
// See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
bool supportsFloatingPointTruncate() const { return true; }
bool supportsFloatingPointSqrt() const { return true; }
+ bool supportsDoubleBitops() const { return true; }
private:
friend class LinkBuffer;
Modified: trunk/Source/_javascript_Core/assembler/X86Assembler.h (90176 => 90177)
--- trunk/Source/_javascript_Core/assembler/X86Assembler.h 2011-06-30 23:07:15 UTC (rev 90176)
+++ trunk/Source/_javascript_Core/assembler/X86Assembler.h 2011-06-30 23:08:11 UTC (rev 90177)
@@ -170,6 +170,7 @@
OP2_SUBSD_VsdWsd = 0x5C,
OP2_DIVSD_VsdWsd = 0x5E,
OP2_SQRTSD_VsdWsd = 0x51,
+ OP2_ANDNPD_VpdWpd = 0x55,
OP2_XORPD_VpdWpd = 0x57,
OP2_MOVD_VdEd = 0x6E,
OP2_MOVD_EdVd = 0x7E,
@@ -1457,6 +1458,12 @@
m_formatter.twoByteOp(OP2_XORPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
}
+ void andnpd_rr(XMMRegisterID src, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_66);
+ m_formatter.twoByteOp(OP2_ANDNPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
+ }
+
void sqrtsd_rr(XMMRegisterID src, XMMRegisterID dst)
{
m_formatter.prefix(PRE_SSE_F2);
Modified: trunk/Source/_javascript_Core/create_hash_table (90176 => 90177)
--- trunk/Source/_javascript_Core/create_hash_table 2011-06-30 23:07:15 UTC (rev 90176)
+++ trunk/Source/_javascript_Core/create_hash_table 2011-06-30 23:08:11 UTC (rev 90177)
@@ -278,15 +278,35 @@
if ($key eq "charAt") {
$thunkGenerator = "charAtThunkGenerator";
}
- if ($key eq "sqrt") {
- $thunkGenerator = "sqrtThunkGenerator";
- }
- if ($key eq "pow") {
- $thunkGenerator = "powThunkGenerator";
- }
if ($key eq "fromCharCode") {
$thunkGenerator = "fromCharCodeThunkGenerator";
}
+ if ($name eq "mathTable") {
+ if ($key eq "sqrt") {
+ $thunkGenerator = "sqrtThunkGenerator";
+ }
+ if ($key eq "pow") {
+ $thunkGenerator = "powThunkGenerator";
+ }
+ if ($key eq "abs") {
+ $thunkGenerator = "absThunkGenerator";
+ }
+ if ($key eq "floor") {
+ $thunkGenerator = "floorThunkGenerator";
+ }
+ if ($key eq "ceil") {
+ $thunkGenerator = "ceilThunkGenerator";
+ }
+ if ($key eq "round") {
+ $thunkGenerator = "roundThunkGenerator";
+ }
+ if ($key eq "exp") {
+ $thunkGenerator = "expThunkGenerator";
+ }
+ if ($key eq "log") {
+ $thunkGenerator = "logThunkGenerator";
+ }
+ }
print " { \"$key\", $attrs[$i], (intptr_t)" . $castStr . "($firstValue), (intptr_t)$secondValue THUNK_GENERATOR($thunkGenerator) },\n";
$i++;
}
Modified: trunk/Source/_javascript_Core/jit/JSInterfaceJIT.h (90176 => 90177)
--- trunk/Source/_javascript_Core/jit/JSInterfaceJIT.h 2011-06-30 23:07:15 UTC (rev 90176)
+++ trunk/Source/_javascript_Core/jit/JSInterfaceJIT.h 2011-06-30 23:08:11 UTC (rev 90177)
@@ -276,7 +276,8 @@
loadDouble(addressFor(virtualRegisterIndex), dst);
done.link(this);
return notInt;
- }
+ }
+
#endif
#if USE(JSVALUE64)
@@ -315,7 +316,7 @@
done.link(this);
return notNumber;
}
-
+
ALWAYS_INLINE void JSInterfaceJIT::emitFastArithImmToInt(RegisterID)
{
}
Modified: trunk/Source/_javascript_Core/jit/SpecializedThunkJIT.h (90176 => 90177)
--- trunk/Source/_javascript_Core/jit/SpecializedThunkJIT.h 2011-06-30 23:07:15 UTC (rev 90176)
+++ trunk/Source/_javascript_Core/jit/SpecializedThunkJIT.h 2011-06-30 23:08:11 UTC (rev 90177)
@@ -127,9 +127,18 @@
{
LinkBuffer patchBuffer(globalData, this, m_pool.get());
patchBuffer.link(m_failures, CodeLocationLabel(fallback));
+ for (unsigned i = 0; i < m_calls.size(); i++)
+ patchBuffer.link(m_calls[i].first, m_calls[i].second);
return patchBuffer.finalizeCode().m_code;
}
-
+
+ // Assumes that the target function uses fpRegister0 as the first argument
+ // and return value. Like any sensible architecture would.
+ void callDoubleToDouble(FunctionPtr function)
+ {
+ m_calls.append(std::make_pair(call(), function));
+ }
+
private:
int argumentToVirtualRegister(unsigned argument)
{
@@ -156,6 +165,7 @@
JSGlobalData* m_globalData;
RefPtr<ExecutablePool> m_pool;
MacroAssembler::JumpList m_failures;
+ Vector<std::pair<Call, FunctionPtr> > m_calls;
};
}
Modified: trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp (90176 => 90177)
--- trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp 2011-06-30 23:07:15 UTC (rev 90176)
+++ trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp 2011-06-30 23:08:11 UTC (rev 90177)
@@ -102,9 +102,196 @@
return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
}
+#if OS(DARWIN) || (OS(WINDOWS) && CPU(X86))
+#define SYMBOL_STRING(name) "_" #name
+#else
+#define SYMBOL_STRING(name) #name
+#endif
+
+#if (OS(LINUX) || OS(FREEBSD)) && CPU(X86_64)
+#define SYMBOL_STRING_RELOCATION(name) #name "@plt"
+#elif OS(DARWIN) || (CPU(X86_64) && COMPILER(MINGW) && !GCC_VERSION_AT_LEAST(4, 5, 0))
+#define SYMBOL_STRING_RELOCATION(name) "_" #name
+#elif CPU(X86) && COMPILER(MINGW)
+#define SYMBOL_STRING_RELOCATION(name) "@" #name "@4"
+#else
+#define SYMBOL_STRING_RELOCATION(name) #name
+#endif
+
+#define UnaryDoubleOpWrapper(function) function##Wrapper
+enum MathThunkCallingConvention { };
+typedef MathThunkCallingConvention(*MathThunk)(MathThunkCallingConvention);
+extern "C" {
+
+double jsRound(double);
+double jsRound(double d)
+{
+ double integer = ceil(d);
+ return integer - (integer - d > 0.5);
+}
+
+}
+
+#if CPU(X86_64) && COMPILER(GCC)
+
+#define defineUnaryDoubleOpWrapper(function) \
+ asm( \
+ ".globl " SYMBOL_STRING(function##Thunk) "\n" \
+ SYMBOL_STRING(function##Thunk) ":" "\n" \
+ "call " SYMBOL_STRING_RELOCATION(function) "\n" \
+ "ret\n" \
+ );\
+ extern "C" { \
+ MathThunkCallingConvention function##Thunk(MathThunkCallingConvention); \
+ } \
+ static MathThunk UnaryDoubleOpWrapper(function) = &function##Thunk;
+
+#elif CPU(X86) && COMPILER(GCC)
+#define defineUnaryDoubleOpWrapper(function) \
+ asm( \
+ ".globl " SYMBOL_STRING(function##Thunk) "\n" \
+ SYMBOL_STRING(function##Thunk) ":" "\n" \
+ "subl $8, %esp\n" \
+ "movsd %xmm0, (%esp) \n" \
+ "call " SYMBOL_STRING_RELOCATION(function) "\n" \
+ "fstpl (%esp) \n" \
+ "movsd (%esp), %xmm0 \n" \
+ "addl $8, %esp\n" \
+ "ret\n" \
+ );\
+ extern "C" { \
+ MathThunkCallingConvention function##Thunk(MathThunkCallingConvention); \
+ } \
+ static MathThunk UnaryDoubleOpWrapper(function) = &function##Thunk;
+
+#else
+
+#define defineUnaryDoubleOpWrapper(function) \
+ static MathThunk UnaryDoubleOpWrapper(function) = 0
+#endif
+
+defineUnaryDoubleOpWrapper(jsRound);
+defineUnaryDoubleOpWrapper(exp);
+defineUnaryDoubleOpWrapper(log);
+defineUnaryDoubleOpWrapper(floor);
+defineUnaryDoubleOpWrapper(ceil);
+
+MacroAssemblerCodePtr floorThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+{
+ SpecializedThunkJIT jit(1, globalData, pool);
+ MacroAssembler::Jump nonIntJump;
+ jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump);
+ jit.returnInt32(SpecializedThunkJIT::regT0);
+ if (!UnaryDoubleOpWrapper(floor) || !jit.supportsFloatingPoint()) {
+ jit.appendFailure(nonIntJump);
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+ }
+ nonIntJump.link(&jit);
+ jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
+ jit.callDoubleToDouble(UnaryDoubleOpWrapper(floor));
+ SpecializedThunkJIT::JumpList doubleResult;
+ jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT1);
+ jit.returnInt32(SpecializedThunkJIT::regT0);
+ doubleResult.link(&jit);
+ jit.returnDouble(SpecializedThunkJIT::fpRegT0);
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+}
+
+MacroAssemblerCodePtr ceilThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+{
+ SpecializedThunkJIT jit(1, globalData, pool);
+ MacroAssembler::Jump nonIntJump;
+ jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump);
+ jit.returnInt32(SpecializedThunkJIT::regT0);
+ if (!UnaryDoubleOpWrapper(ceil) || !jit.supportsFloatingPoint()) {
+ jit.appendFailure(nonIntJump);
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+ }
+ nonIntJump.link(&jit);
+ jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
+ jit.callDoubleToDouble(UnaryDoubleOpWrapper(ceil));
+ SpecializedThunkJIT::JumpList doubleResult;
+ jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT1);
+ jit.returnInt32(SpecializedThunkJIT::regT0);
+ doubleResult.link(&jit);
+ jit.returnDouble(SpecializedThunkJIT::fpRegT0);
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+}
+
+static const double negativeZeroConstant = -0.0;
static const double _oneConstant_ = 1.0;
static const double negativeHalfConstant = -0.5;
+
+MacroAssemblerCodePtr roundThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+{
+ SpecializedThunkJIT jit(1, globalData, pool);
+ MacroAssembler::Jump nonIntJump;
+ jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump);
+ jit.returnInt32(SpecializedThunkJIT::regT0);
+ if (!UnaryDoubleOpWrapper(jsRound) || !jit.supportsFloatingPoint()) {
+ jit.appendFailure(nonIntJump);
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+ }
+ nonIntJump.link(&jit);
+ jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
+ jit.callDoubleToDouble(UnaryDoubleOpWrapper(jsRound));
+ SpecializedThunkJIT::JumpList doubleResult;
+ jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT1);
+ jit.returnInt32(SpecializedThunkJIT::regT0);
+ doubleResult.link(&jit);
+ jit.returnDouble(SpecializedThunkJIT::fpRegT0);
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+}
+MacroAssemblerCodePtr expThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+{
+ if (!UnaryDoubleOpWrapper(exp))
+ return globalData->jitStubs->ctiNativeCall();
+ SpecializedThunkJIT jit(1, globalData, pool);
+ if (!jit.supportsFloatingPoint())
+ return globalData->jitStubs->ctiNativeCall();
+ jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
+ jit.callDoubleToDouble(UnaryDoubleOpWrapper(exp));
+ jit.returnDouble(SpecializedThunkJIT::fpRegT0);
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+}
+
+MacroAssemblerCodePtr logThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+{
+ if (!UnaryDoubleOpWrapper(log))
+ return globalData->jitStubs->ctiNativeCall();
+ SpecializedThunkJIT jit(1, globalData, pool);
+ if (!jit.supportsFloatingPoint())
+ return globalData->jitStubs->ctiNativeCall();
+ jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
+ jit.callDoubleToDouble(UnaryDoubleOpWrapper(log));
+ jit.returnDouble(SpecializedThunkJIT::fpRegT0);
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+}
+
+MacroAssemblerCodePtr absThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+{
+ SpecializedThunkJIT jit(1, globalData, pool);
+ MacroAssembler::Jump nonIntJump;
+ jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump);
+ jit.rshift32(SpecializedThunkJIT::regT0, MacroAssembler::TrustedImm32(31), SpecializedThunkJIT::regT1);
+ jit.add32(SpecializedThunkJIT::regT1, SpecializedThunkJIT::regT0);
+ jit.xor32(SpecializedThunkJIT::regT1, SpecializedThunkJIT::regT0);
+ jit.appendFailure(jit.branch32(MacroAssembler::Equal, SpecializedThunkJIT::regT0, MacroAssembler::TrustedImm32(1 << 31)));
+ jit.returnInt32(SpecializedThunkJIT::regT0);
+ if (!jit.supportsDoubleBitops()) {
+ jit.appendFailure(nonIntJump);
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+ }
+ nonIntJump.link(&jit);
+ // Shame about the double int conversion here.
+ jit.loadDouble(&negativeZeroConstant, SpecializedThunkJIT::fpRegT1);
+ jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
+ jit.andnotDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1);
+ jit.returnDouble(SpecializedThunkJIT::fpRegT1);
+ return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+}
+
MacroAssemblerCodePtr powThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
{
SpecializedThunkJIT jit(2, globalData, pool);
Modified: trunk/Source/_javascript_Core/jit/ThunkGenerators.h (90176 => 90177)
--- trunk/Source/_javascript_Core/jit/ThunkGenerators.h 2011-06-30 23:07:15 UTC (rev 90176)
+++ trunk/Source/_javascript_Core/jit/ThunkGenerators.h 2011-06-30 23:08:11 UTC (rev 90177)
@@ -37,6 +37,12 @@
MacroAssemblerCodePtr charCodeAtThunkGenerator(JSGlobalData*, ExecutablePool*);
MacroAssemblerCodePtr charAtThunkGenerator(JSGlobalData*, ExecutablePool*);
MacroAssemblerCodePtr fromCharCodeThunkGenerator(JSGlobalData*, ExecutablePool*);
+ MacroAssemblerCodePtr absThunkGenerator(JSGlobalData*, ExecutablePool*);
+ MacroAssemblerCodePtr ceilThunkGenerator(JSGlobalData*, ExecutablePool*);
+ MacroAssemblerCodePtr expThunkGenerator(JSGlobalData*, ExecutablePool*);
+ MacroAssemblerCodePtr floorThunkGenerator(JSGlobalData*, ExecutablePool*);
+ MacroAssemblerCodePtr logThunkGenerator(JSGlobalData*, ExecutablePool*);
+ MacroAssemblerCodePtr roundThunkGenerator(JSGlobalData*, ExecutablePool*);
MacroAssemblerCodePtr sqrtThunkGenerator(JSGlobalData*, ExecutablePool*);
MacroAssemblerCodePtr powThunkGenerator(JSGlobalData*, ExecutablePool*);
}