Changeset 90177 in webkit
- Timestamp:
- Jun 30, 2011, 4:08:11 PM (14 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r90167 r90177 1 2011-06-30 Oliver Hunt <[email protected]> 2 3 Reviewed by Gavin Barraclough. 4 5 Add optimised paths for a few maths functions 6 https://bugs.webkit.org/show_bug.cgi?id=63757 7 8 This adds specialised thunks for Math.abs, Math.round, Math.ceil, 9 Math.floor, Math.log, and Math.exp as they are apparently more 10 important in real web content than we thought, which is somewhat 11 mind-boggling. On average doubles the performance of the common 12 cases (eg. actually passing numbers in). They're not as efficient 13 as they could be, but this way gives them the most portability. 14 15 * assembler/MacroAssemblerARM.h: 16 (JSC::MacroAssemblerARM::supportsDoubleBitops): 17 (JSC::MacroAssemblerARM::andnotDouble): 18 * assembler/MacroAssemblerARMv7.h: 19 (JSC::MacroAssemblerARMv7::supportsDoubleBitops): 20 (JSC::MacroAssemblerARMv7::andnotDouble): 21 * assembler/MacroAssemblerMIPS.h: 22 (JSC::MacroAssemblerMIPS::andnotDouble): 23 (JSC::MacroAssemblerMIPS::supportsDoubleBitops): 24 * assembler/MacroAssemblerSH4.h: 25 (JSC::MacroAssemblerSH4::supportsDoubleBitops): 26 (JSC::MacroAssemblerSH4::andnotDouble): 27 * assembler/MacroAssemblerX86.h: 28 (JSC::MacroAssemblerX86::supportsDoubleBitops): 29 * assembler/MacroAssemblerX86Common.h: 30 (JSC::MacroAssemblerX86Common::andnotDouble): 31 * assembler/MacroAssemblerX86_64.h: 32 (JSC::MacroAssemblerX86_64::supportsDoubleBitops): 33 * assembler/X86Assembler.h: 34 (JSC::X86Assembler::andnpd_rr): 35 * create_hash_table: 36 * jit/SpecializedThunkJIT.h: 37 (JSC::SpecializedThunkJIT::finalize): 38 (JSC::SpecializedThunkJIT::callDoubleToDouble): 39 * jit/ThunkGenerators.cpp: 40 (JSC::floorThunkGenerator): 41 (JSC::ceilThunkGenerator): 42 (JSC::roundThunkGenerator): 43 (JSC::expThunkGenerator): 44 (JSC::logThunkGenerator): 45 (JSC::absThunkGenerator): 46 * jit/ThunkGenerators.h: 47 1 48 2011-06-30 Cary Clark <[email protected]> 2 49 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM.h
r87702 r90177 790 790 return s_isVFPPresent; 791 791 } 792 bool supportsDoubleBitops() const { return false; } 792 793 793 794 void loadDouble(ImplicitAddress address, FPRegisterID dest) … … 855 856 { 856 857 m_assembler.vsqrt_f64_r(dest, src); 858 } 859 860 void andnotDouble(FPRegisterID, FPRegisterID) 861 { 862 ASSERT_NOT_REACHED(); 857 863 } 858 864 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h
r87356 r90177 568 568 return false; 569 569 } 570 bool supportsDoubleBitops() const { return false; } 570 571 571 572 void loadDouble(ImplicitAddress address, FPRegisterID dest) … … 644 645 645 646 void sqrtDouble(FPRegisterID, FPRegisterID) 647 { 648 ASSERT_NOT_REACHED(); 649 } 650 651 void andnotDouble(FPRegisterID, FPRegisterID) 646 652 { 647 653 ASSERT_NOT_REACHED(); -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h
r87356 r90177 461 461 m_assembler.sqrtd(dst, src); 462 462 } 463 464 void andnotDouble(FPRegisterID, FPRegisterID) 465 { 466 ASSERT_NOT_REACHED(); 467 } 463 468 464 469 // Memory access operations: … … 817 822 #endif 818 823 } 824 bool supportsDoubleBitops() const { return false; } 819 825 820 826 // Stack manipulation operations: -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h
r87076 r90177 763 763 bool supportsFloatingPointTruncate() const { return true; } 764 764 bool supportsFloatingPointSqrt() const { return true; } 765 bool supportsDoubleBitops() const { return false; } 765 766 766 767 void loadDouble(ImplicitAddress address, FPRegisterID dest) … … 1101 1102 m_assembler.dsqrt(dest); 1102 1103 } 1104 1105 void andnotDouble(FPRegisterID, FPRegisterID) 1106 { 1107 ASSERT_NOT_REACHED(); 1108 } 1103 1109 1104 1110 Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86.h
r87356 r90177 167 167 bool supportsFloatingPointTruncate() const { return m_isSSE2Present; } 168 168 bool supportsFloatingPointSqrt() const { return m_isSSE2Present; } 169 bool supportsDoubleBitops() const { return m_isSSE2Present; } 169 170 170 171 private: -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h
r86919 r90177 422 422 { 423 423 m_assembler.sqrtsd_rr(src, dst); 424 } 425 426 void andnotDouble(FPRegisterID src, FPRegisterID dst) 427 { 428 m_assembler.andnpd_rr(src, dst); 424 429 } 425 430 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h
r87356 r90177 457 457 bool supportsFloatingPointTruncate() const { return true; } 458 458 bool supportsFloatingPointSqrt() const { return true; } 459 bool supportsDoubleBitops() const { return true; } 459 460 460 461 private: -
trunk/Source/JavaScriptCore/assembler/X86Assembler.h
r90157 r90177 171 171 OP2_DIVSD_VsdWsd = 0x5E, 172 172 OP2_SQRTSD_VsdWsd = 0x51, 173 OP2_ANDNPD_VpdWpd = 0x55, 173 174 OP2_XORPD_VpdWpd = 0x57, 174 175 OP2_MOVD_VdEd = 0x6E, … … 1456 1457 m_formatter.prefix(PRE_SSE_66); 1457 1458 m_formatter.twoByteOp(OP2_XORPD_VpdWpd, (RegisterID)dst, (RegisterID)src); 1459 } 1460 1461 void andnpd_rr(XMMRegisterID src, XMMRegisterID dst) 1462 { 1463 m_formatter.prefix(PRE_SSE_66); 1464 m_formatter.twoByteOp(OP2_ANDNPD_VpdWpd, (RegisterID)dst, (RegisterID)src); 1458 1465 } 1459 1466 -
trunk/Source/JavaScriptCore/create_hash_table
r86727 r90177 279 279 $thunkGenerator = "charAtThunkGenerator"; 280 280 } 281 if ($key eq "sqrt") {282 $thunkGenerator = "sqrtThunkGenerator";283 }284 if ($key eq "pow") {285 $thunkGenerator = "powThunkGenerator";286 }287 281 if ($key eq "fromCharCode") { 288 282 $thunkGenerator = "fromCharCodeThunkGenerator"; 283 } 284 if ($name eq "mathTable") { 285 if ($key eq "sqrt") { 286 $thunkGenerator = "sqrtThunkGenerator"; 287 } 288 if ($key eq "pow") { 289 $thunkGenerator = "powThunkGenerator"; 290 } 291 if ($key eq "abs") { 292 $thunkGenerator = "absThunkGenerator"; 293 } 294 if ($key eq "floor") { 295 $thunkGenerator = "floorThunkGenerator"; 296 } 297 if ($key eq "ceil") { 298 $thunkGenerator = "ceilThunkGenerator"; 299 } 300 if ($key eq "round") { 301 $thunkGenerator = "roundThunkGenerator"; 302 } 303 if ($key eq "exp") { 304 $thunkGenerator = "expThunkGenerator"; 305 } 306 if ($key eq "log") { 307 $thunkGenerator = "logThunkGenerator"; 308 } 289 309 } 290 310 print " { \"$key\", $attrs[$i], (intptr_t)" . $castStr . "($firstValue), (intptr_t)$secondValue THUNK_GENERATOR($thunkGenerator) },\n"; -
trunk/Source/JavaScriptCore/jit/JSInterfaceJIT.h
r84052 r90177 277 277 done.link(this); 278 278 return notInt; 279 } 279 } 280 280 281 #endif 281 282 … … 316 317 return notNumber; 317 318 } 318 319 319 320 ALWAYS_INLINE void JSInterfaceJIT::emitFastArithImmToInt(RegisterID) 320 321 { -
trunk/Source/JavaScriptCore/jit/SpecializedThunkJIT.h
r87527 r90177 128 128 LinkBuffer patchBuffer(globalData, this, m_pool.get()); 129 129 patchBuffer.link(m_failures, CodeLocationLabel(fallback)); 130 for (unsigned i = 0; i < m_calls.size(); i++) 131 patchBuffer.link(m_calls[i].first, m_calls[i].second); 130 132 return patchBuffer.finalizeCode().m_code; 131 133 } 132 134 135 // Assumes that the target function uses fpRegister0 as the first argument 136 // and return value. Like any sensible architecture would. 137 void callDoubleToDouble(FunctionPtr function) 138 { 139 m_calls.append(std::make_pair(call(), function)); 140 } 141 133 142 private: 134 143 int argumentToVirtualRegister(unsigned argument) … … 157 166 RefPtr<ExecutablePool> m_pool; 158 167 MacroAssembler::JumpList m_failures; 168 Vector<std::pair<Call, FunctionPtr> > m_calls; 159 169 }; 160 170 -
trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp
r87527 r90177 103 103 } 104 104 105 #if OS(DARWIN) || (OS(WINDOWS) && CPU(X86)) 106 #define SYMBOL_STRING(name) "_" #name 107 #else 108 #define SYMBOL_STRING(name) #name 109 #endif 110 111 #if (OS(LINUX) || OS(FREEBSD)) && CPU(X86_64) 112 #define SYMBOL_STRING_RELOCATION(name) #name "@plt" 113 #elif OS(DARWIN) || (CPU(X86_64) && COMPILER(MINGW) && !GCC_VERSION_AT_LEAST(4, 5, 0)) 114 #define SYMBOL_STRING_RELOCATION(name) "_" #name 115 #elif CPU(X86) && COMPILER(MINGW) 116 #define SYMBOL_STRING_RELOCATION(name) "@" #name "@4" 117 #else 118 #define SYMBOL_STRING_RELOCATION(name) #name 119 #endif 120 121 #define UnaryDoubleOpWrapper(function) function##Wrapper 122 enum MathThunkCallingConvention { }; 123 typedef MathThunkCallingConvention(*MathThunk)(MathThunkCallingConvention); 124 extern "C" { 125 126 double jsRound(double); 127 double jsRound(double d) 128 { 129 double integer = ceil(d); 130 return integer - (integer - d > 0.5); 131 } 132 133 } 134 135 #if CPU(X86_64) && COMPILER(GCC) 136 137 #define defineUnaryDoubleOpWrapper(function) \ 138 asm( \ 139 ".globl " SYMBOL_STRING(function##Thunk) "\n" \ 140 SYMBOL_STRING(function##Thunk) ":" "\n" \ 141 "call " SYMBOL_STRING_RELOCATION(function) "\n" \ 142 "ret\n" \ 143 );\ 144 extern "C" { \ 145 MathThunkCallingConvention function##Thunk(MathThunkCallingConvention); \ 146 } \ 147 static MathThunk UnaryDoubleOpWrapper(function) = &function##Thunk; 148 149 #elif CPU(X86) && COMPILER(GCC) 150 #define defineUnaryDoubleOpWrapper(function) \ 151 asm( \ 152 ".globl " SYMBOL_STRING(function##Thunk) "\n" \ 153 SYMBOL_STRING(function##Thunk) ":" "\n" \ 154 "subl $8, %esp\n" \ 155 "movsd %xmm0, (%esp) \n" \ 156 "call " SYMBOL_STRING_RELOCATION(function) "\n" \ 157 "fstpl (%esp) \n" \ 158 "movsd (%esp), %xmm0 \n" \ 159 "addl $8, %esp\n" \ 160 "ret\n" \ 161 );\ 162 extern "C" { \ 163 MathThunkCallingConvention function##Thunk(MathThunkCallingConvention); \ 164 } \ 165 static MathThunk UnaryDoubleOpWrapper(function) = &function##Thunk; 166 167 #else 168 169 #define defineUnaryDoubleOpWrapper(function) \ 170 static MathThunk UnaryDoubleOpWrapper(function) = 0 171 #endif 172 173 defineUnaryDoubleOpWrapper(jsRound); 174 defineUnaryDoubleOpWrapper(exp); 175 defineUnaryDoubleOpWrapper(log); 176 defineUnaryDoubleOpWrapper(floor); 177 defineUnaryDoubleOpWrapper(ceil); 178 179 MacroAssemblerCodePtr floorThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) 180 { 181 SpecializedThunkJIT jit(1, globalData, pool); 182 MacroAssembler::Jump nonIntJump; 183 jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump); 184 jit.returnInt32(SpecializedThunkJIT::regT0); 185 if (!UnaryDoubleOpWrapper(floor) || !jit.supportsFloatingPoint()) { 186 jit.appendFailure(nonIntJump); 187 return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall()); 188 } 189 nonIntJump.link(&jit); 190 jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0); 191 jit.callDoubleToDouble(UnaryDoubleOpWrapper(floor)); 192 SpecializedThunkJIT::JumpList doubleResult; 193 jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT1); 194 jit.returnInt32(SpecializedThunkJIT::regT0); 195 doubleResult.link(&jit); 196 jit.returnDouble(SpecializedThunkJIT::fpRegT0); 197 return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall()); 198 } 199 200 MacroAssemblerCodePtr ceilThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) 201 { 202 SpecializedThunkJIT jit(1, globalData, pool); 203 MacroAssembler::Jump nonIntJump; 204 jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump); 205 jit.returnInt32(SpecializedThunkJIT::regT0); 206 if (!UnaryDoubleOpWrapper(ceil) || !jit.supportsFloatingPoint()) { 207 jit.appendFailure(nonIntJump); 208 return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall()); 209 } 210 nonIntJump.link(&jit); 211 jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0); 212 jit.callDoubleToDouble(UnaryDoubleOpWrapper(ceil)); 213 SpecializedThunkJIT::JumpList doubleResult; 214 jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT1); 215 jit.returnInt32(SpecializedThunkJIT::regT0); 216 doubleResult.link(&jit); 217 jit.returnDouble(SpecializedThunkJIT::fpRegT0); 218 return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall()); 219 } 220 221 static const double negativeZeroConstant = -0.0; 105 222 static const double oneConstant = 1.0; 106 223 static const double negativeHalfConstant = -0.5; 224 225 MacroAssemblerCodePtr roundThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) 226 { 227 SpecializedThunkJIT jit(1, globalData, pool); 228 MacroAssembler::Jump nonIntJump; 229 jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump); 230 jit.returnInt32(SpecializedThunkJIT::regT0); 231 if (!UnaryDoubleOpWrapper(jsRound) || !jit.supportsFloatingPoint()) { 232 jit.appendFailure(nonIntJump); 233 return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall()); 234 } 235 nonIntJump.link(&jit); 236 jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0); 237 jit.callDoubleToDouble(UnaryDoubleOpWrapper(jsRound)); 238 SpecializedThunkJIT::JumpList doubleResult; 239 jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT1); 240 jit.returnInt32(SpecializedThunkJIT::regT0); 241 doubleResult.link(&jit); 242 jit.returnDouble(SpecializedThunkJIT::fpRegT0); 243 return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall()); 244 } 245 246 MacroAssemblerCodePtr expThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) 247 { 248 if (!UnaryDoubleOpWrapper(exp)) 249 return globalData->jitStubs->ctiNativeCall(); 250 SpecializedThunkJIT jit(1, globalData, pool); 251 if (!jit.supportsFloatingPoint()) 252 return globalData->jitStubs->ctiNativeCall(); 253 jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0); 254 jit.callDoubleToDouble(UnaryDoubleOpWrapper(exp)); 255 jit.returnDouble(SpecializedThunkJIT::fpRegT0); 256 return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall()); 257 } 258 259 MacroAssemblerCodePtr logThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) 260 { 261 if (!UnaryDoubleOpWrapper(log)) 262 return globalData->jitStubs->ctiNativeCall(); 263 SpecializedThunkJIT jit(1, globalData, pool); 264 if (!jit.supportsFloatingPoint()) 265 return globalData->jitStubs->ctiNativeCall(); 266 jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0); 267 jit.callDoubleToDouble(UnaryDoubleOpWrapper(log)); 268 jit.returnDouble(SpecializedThunkJIT::fpRegT0); 269 return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall()); 270 } 271 272 MacroAssemblerCodePtr absThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) 273 { 274 SpecializedThunkJIT jit(1, globalData, pool); 275 MacroAssembler::Jump nonIntJump; 276 jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump); 277 jit.rshift32(SpecializedThunkJIT::regT0, MacroAssembler::TrustedImm32(31), SpecializedThunkJIT::regT1); 278 jit.add32(SpecializedThunkJIT::regT1, SpecializedThunkJIT::regT0); 279 jit.xor32(SpecializedThunkJIT::regT1, SpecializedThunkJIT::regT0); 280 jit.appendFailure(jit.branch32(MacroAssembler::Equal, SpecializedThunkJIT::regT0, MacroAssembler::TrustedImm32(1 << 31))); 281 jit.returnInt32(SpecializedThunkJIT::regT0); 282 if (!jit.supportsDoubleBitops()) { 283 jit.appendFailure(nonIntJump); 284 return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall()); 285 } 286 nonIntJump.link(&jit); 287 // Shame about the double int conversion here. 288 jit.loadDouble(&negativeZeroConstant, SpecializedThunkJIT::fpRegT1); 289 jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0); 290 jit.andnotDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1); 291 jit.returnDouble(SpecializedThunkJIT::fpRegT1); 292 return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall()); 293 } 107 294 108 295 MacroAssemblerCodePtr powThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) -
trunk/Source/JavaScriptCore/jit/ThunkGenerators.h
r59637 r90177 38 38 MacroAssemblerCodePtr charAtThunkGenerator(JSGlobalData*, ExecutablePool*); 39 39 MacroAssemblerCodePtr fromCharCodeThunkGenerator(JSGlobalData*, ExecutablePool*); 40 MacroAssemblerCodePtr absThunkGenerator(JSGlobalData*, ExecutablePool*); 41 MacroAssemblerCodePtr ceilThunkGenerator(JSGlobalData*, ExecutablePool*); 42 MacroAssemblerCodePtr expThunkGenerator(JSGlobalData*, ExecutablePool*); 43 MacroAssemblerCodePtr floorThunkGenerator(JSGlobalData*, ExecutablePool*); 44 MacroAssemblerCodePtr logThunkGenerator(JSGlobalData*, ExecutablePool*); 45 MacroAssemblerCodePtr roundThunkGenerator(JSGlobalData*, ExecutablePool*); 40 46 MacroAssemblerCodePtr sqrtThunkGenerator(JSGlobalData*, ExecutablePool*); 41 47 MacroAssemblerCodePtr powThunkGenerator(JSGlobalData*, ExecutablePool*);
Note:
See TracChangeset
for help on using the changeset viewer.