Changeset 90237 in webkit
- Timestamp:
- Jul 1, 2011, 9:33:46 AM (15 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 14 edited
-
ChangeLog (modified) (1 diff)
-
assembler/MacroAssemblerARM.h (modified) (3 diffs)
-
assembler/MacroAssemblerARMv7.h (modified) (2 diffs)
-
assembler/MacroAssemblerMIPS.h (modified) (2 diffs)
-
assembler/MacroAssemblerSH4.h (modified) (2 diffs)
-
assembler/MacroAssemblerX86.h (modified) (1 diff)
-
assembler/MacroAssemblerX86Common.h (modified) (1 diff)
-
assembler/MacroAssemblerX86_64.h (modified) (1 diff)
-
assembler/X86Assembler.h (modified) (2 diffs)
-
create_hash_table (modified) (1 diff)
-
jit/JSInterfaceJIT.h (modified) (2 diffs)
-
jit/SpecializedThunkJIT.h (modified) (2 diffs)
-
jit/ThunkGenerators.cpp (modified) (1 diff)
-
jit/ThunkGenerators.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r90232 r90237 1 2011-06-30 Oliver Hunt <oliver@apple.com> 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 Relanding as a Mac only patch. 9 10 This adds specialised thunks for Math.abs, Math.round, Math.ceil, 11 Math.floor, Math.log, and Math.exp as they are apparently more 12 important in real web content than we thought, which is somewhat 13 mind-boggling. On average doubles the performance of the common 14 cases (eg. actually passing numbers in). They're not as efficient 15 as they could be, but this way gives them the most portability. 16 17 * assembler/MacroAssemblerARM.h: 18 (JSC::MacroAssemblerARM::supportsDoubleBitops): 19 (JSC::MacroAssemblerARM::andnotDouble): 20 * assembler/MacroAssemblerARMv7.h: 21 (JSC::MacroAssemblerARMv7::supportsDoubleBitops): 22 (JSC::MacroAssemblerARMv7::andnotDouble): 23 * assembler/MacroAssemblerMIPS.h: 24 (JSC::MacroAssemblerMIPS::andnotDouble): 25 (JSC::MacroAssemblerMIPS::supportsDoubleBitops): 26 * assembler/MacroAssemblerSH4.h: 27 (JSC::MacroAssemblerSH4::supportsDoubleBitops): 28 (JSC::MacroAssemblerSH4::andnotDouble): 29 * assembler/MacroAssemblerX86.h: 30 (JSC::MacroAssemblerX86::supportsDoubleBitops): 31 * assembler/MacroAssemblerX86Common.h: 32 (JSC::MacroAssemblerX86Common::andnotDouble): 33 * assembler/MacroAssemblerX86_64.h: 34 (JSC::MacroAssemblerX86_64::supportsDoubleBitops): 35 * assembler/X86Assembler.h: 36 (JSC::X86Assembler::andnpd_rr): 37 * create_hash_table: 38 * jit/SpecializedThunkJIT.h: 39 (JSC::SpecializedThunkJIT::finalize): 40 (JSC::SpecializedThunkJIT::callDoubleToDouble): 41 * jit/ThunkGenerators.cpp: 42 (JSC::floorThunkGenerator): 43 (JSC::ceilThunkGenerator): 44 (JSC::roundThunkGenerator): 45 (JSC::expThunkGenerator): 46 (JSC::logThunkGenerator): 47 (JSC::absThunkGenerator): 48 * jit/ThunkGenerators.h: 49 1 50 2011-07-01 David Kilzer <ddkilzer@apple.com> 2 51 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM.h
r90215 r90237 180 180 m_assembler.movs_r(dest, m_assembler.asr_r(dest, ARMRegisters::S0)); 181 181 } 182 182 183 183 void rshift32(TrustedImm32 imm, RegisterID dest) 184 184 { 185 m_assembler.movs_r(dest, m_assembler.asr(dest, imm.m_value & 0x1f)); 185 rshift32(dest, imm, dest); 186 } 187 188 void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) 189 { 190 m_assembler.movs_r(dest, m_assembler.asr(src, imm.m_value & 0x1f)); 186 191 } 187 192 … … 790 795 return s_isVFPPresent; 791 796 } 797 bool supportsDoubleBitops() const { return false; } 792 798 793 799 void loadDouble(ImplicitAddress address, FPRegisterID dest) … … 855 861 { 856 862 m_assembler.vsqrt_f64_r(dest, src); 863 } 864 865 void andnotDouble(FPRegisterID, FPRegisterID) 866 { 867 ASSERT_NOT_REACHED(); 857 868 } 858 869 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h
r90215 r90237 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
r90215 r90237 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
r90215 r90237 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
r90215 r90237 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
r90215 r90237 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
r90215 r90237 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
r90215 r90237 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
r90215 r90237 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
r90215 r90237 272 272 done.link(this); 273 273 return notInt; 274 } 274 } 275 275 276 #endif 276 277 … … 311 312 return notNumber; 312 313 } 313 314 314 315 ALWAYS_INLINE void JSInterfaceJIT::emitFastArithImmToInt(RegisterID) 315 316 { -
trunk/Source/JavaScriptCore/jit/SpecializedThunkJIT.h
r90215 r90237 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
r90215 r90237 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) && PLATFORM(MAC) 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) && PLATFORM(MAC) 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 if (!UnaryDoubleOpWrapper(floor) || !jit.supportsFloatingPoint()) 184 return globalData->jitStubs->ctiNativeCall(); 185 jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump); 186 jit.returnInt32(SpecializedThunkJIT::regT0); 187 nonIntJump.link(&jit); 188 jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0); 189 jit.callDoubleToDouble(UnaryDoubleOpWrapper(floor)); 190 SpecializedThunkJIT::JumpList doubleResult; 191 jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT1); 192 jit.returnInt32(SpecializedThunkJIT::regT0); 193 doubleResult.link(&jit); 194 jit.returnDouble(SpecializedThunkJIT::fpRegT0); 195 return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall()); 196 } 197 198 MacroAssemblerCodePtr ceilThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) 199 { 200 SpecializedThunkJIT jit(1, globalData, pool); 201 if (!UnaryDoubleOpWrapper(ceil) || !jit.supportsFloatingPoint()) 202 return globalData->jitStubs->ctiNativeCall(); 203 MacroAssembler::Jump nonIntJump; 204 jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump); 205 jit.returnInt32(SpecializedThunkJIT::regT0); 206 nonIntJump.link(&jit); 207 jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0); 208 jit.callDoubleToDouble(UnaryDoubleOpWrapper(ceil)); 209 SpecializedThunkJIT::JumpList doubleResult; 210 jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT1); 211 jit.returnInt32(SpecializedThunkJIT::regT0); 212 doubleResult.link(&jit); 213 jit.returnDouble(SpecializedThunkJIT::fpRegT0); 214 return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall()); 215 } 216 217 static const double negativeZeroConstant = -0.0; 105 218 static const double oneConstant = 1.0; 106 219 static const double negativeHalfConstant = -0.5; 220 221 MacroAssemblerCodePtr roundThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) 222 { 223 SpecializedThunkJIT jit(1, globalData, pool); 224 if (!UnaryDoubleOpWrapper(jsRound) || !jit.supportsFloatingPoint()) 225 return globalData->jitStubs->ctiNativeCall(); 226 MacroAssembler::Jump nonIntJump; 227 jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump); 228 jit.returnInt32(SpecializedThunkJIT::regT0); 229 nonIntJump.link(&jit); 230 jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0); 231 jit.callDoubleToDouble(UnaryDoubleOpWrapper(jsRound)); 232 SpecializedThunkJIT::JumpList doubleResult; 233 jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT1); 234 jit.returnInt32(SpecializedThunkJIT::regT0); 235 doubleResult.link(&jit); 236 jit.returnDouble(SpecializedThunkJIT::fpRegT0); 237 return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall()); 238 } 239 240 MacroAssemblerCodePtr expThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) 241 { 242 if (!UnaryDoubleOpWrapper(exp)) 243 return globalData->jitStubs->ctiNativeCall(); 244 SpecializedThunkJIT jit(1, globalData, pool); 245 if (!jit.supportsFloatingPoint()) 246 return globalData->jitStubs->ctiNativeCall(); 247 jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0); 248 jit.callDoubleToDouble(UnaryDoubleOpWrapper(exp)); 249 jit.returnDouble(SpecializedThunkJIT::fpRegT0); 250 return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall()); 251 } 252 253 MacroAssemblerCodePtr logThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) 254 { 255 if (!UnaryDoubleOpWrapper(log)) 256 return globalData->jitStubs->ctiNativeCall(); 257 SpecializedThunkJIT jit(1, globalData, pool); 258 if (!jit.supportsFloatingPoint()) 259 return globalData->jitStubs->ctiNativeCall(); 260 jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0); 261 jit.callDoubleToDouble(UnaryDoubleOpWrapper(log)); 262 jit.returnDouble(SpecializedThunkJIT::fpRegT0); 263 return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall()); 264 } 265 266 MacroAssemblerCodePtr absThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) 267 { 268 SpecializedThunkJIT jit(1, globalData, pool); 269 if (!jit.supportsDoubleBitops()) 270 return globalData->jitStubs->ctiNativeCall(); 271 MacroAssembler::Jump nonIntJump; 272 jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump); 273 jit.rshift32(SpecializedThunkJIT::regT0, MacroAssembler::TrustedImm32(31), SpecializedThunkJIT::regT1); 274 jit.add32(SpecializedThunkJIT::regT1, SpecializedThunkJIT::regT0); 275 jit.xor32(SpecializedThunkJIT::regT1, SpecializedThunkJIT::regT0); 276 jit.appendFailure(jit.branch32(MacroAssembler::Equal, SpecializedThunkJIT::regT0, MacroAssembler::TrustedImm32(1 << 31))); 277 jit.returnInt32(SpecializedThunkJIT::regT0); 278 nonIntJump.link(&jit); 279 // Shame about the double int conversion here. 280 jit.loadDouble(&negativeZeroConstant, SpecializedThunkJIT::fpRegT1); 281 jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0); 282 jit.andnotDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1); 283 jit.returnDouble(SpecializedThunkJIT::fpRegT1); 284 return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall()); 285 } 107 286 108 287 MacroAssemblerCodePtr powThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) -
trunk/Source/JavaScriptCore/jit/ThunkGenerators.h
r90215 r90237 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.