Changeset 189744 in webkit
- Timestamp:
- Sep 14, 2015 11:30:08 AM (9 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r189731 r189744 1 2015-09-14 Sukolsak Sakshuwong <sukolsak@gmail.com> 2 3 Implement the arithmetic instructions for floats in WebAssembly 4 https://bugs.webkit.org/show_bug.cgi?id=149102 5 6 Reviewed by Geoffrey Garen. 7 8 This patch implements the arithmetic instructions for floats (float32) 9 in WebAssembly by converting the float operands to doubles, performing 10 the equivalent double instructions, and converting the result back to 11 float. The asm.js spec says that "As proved in 'When is double rounding 12 innocuous?' (Figueroa 1995), both the 32- and 64-bit versions of 13 standard arithmetic operations produce equivalent results when given 14 32-bit inputs and coerced to 32-bit outputs." 15 (http://asmjs.org/spec/latest/#floatish) 16 17 This patch also pads WebAssembly call frames by maxFrameExtentForSlowPathCall, 18 so that there is no need to adjust the stack pointer every time we make 19 a slow path call. 20 21 * tests/stress/wasm-arithmetic-float32.js: 22 * tests/stress/wasm/arithmetic-float32.wasm: 23 * wasm/WASMFunctionCompiler.h: 24 (JSC::WASMFunctionCompiler::startFunction): 25 (JSC::WASMFunctionCompiler::buildUnaryF32): 26 (JSC::WASMFunctionCompiler::buildBinaryF32): 27 (JSC::WASMFunctionCompiler::callOperation): 28 (JSC::WASMFunctionCompiler::callAndUnboxResult): 29 (JSC::WASMFunctionCompiler::endFunction): Deleted. 30 (JSC::WASMFunctionCompiler::buildBinaryI32): Deleted. 31 * wasm/WASMFunctionParser.cpp: 32 (JSC::WASMFunctionParser::parseExpressionF32): 33 (JSC::WASMFunctionParser::parseUnaryExpressionF32): 34 (JSC::WASMFunctionParser::parseBinaryExpressionF32): 35 * wasm/WASMFunctionParser.h: 36 * wasm/WASMFunctionSyntaxChecker.h: 37 (JSC::WASMFunctionSyntaxChecker::buildUnaryF32): 38 (JSC::WASMFunctionSyntaxChecker::buildBinaryF32): 39 1 40 2015-09-13 Geoffrey Garen <ggaren@apple.com> 2 41 -
trunk/Source/JavaScriptCore/tests/stress/wasm-arithmetic-float32.js
r189624 r189744 13 13 14 14 var fround = global.Math.fround; 15 var abs = global.Math.abs; 16 var ceil = global.Math.ceil; 17 var floor = global.Math.floor; 18 var sqrt = global.Math.sqrt; 15 19 16 20 function number() { … … 18 22 } 19 23 24 function negate(x) { 25 x = fround(x); 26 return fround(-x); 27 } 28 29 function add(x, y) { 30 x = fround(x); 31 y = fround(y); 32 return fround(x + y); 33 } 34 35 function subtract(x, y) { 36 x = fround(x); 37 y = fround(y); 38 return fround(x - y); 39 } 40 41 function multiply(x, y) { 42 x = fround(x); 43 y = fround(y); 44 return fround(x * y); 45 } 46 47 function divide(x, y) { 48 x = fround(x); 49 y = fround(y); 50 return fround(x / y); 51 } 52 53 function absolute(x) { 54 x = fround(x); 55 return fround(abs(x)); 56 } 57 58 function ceilNumber(x) { 59 x = fround(x); 60 return fround(ceil(x)); 61 } 62 63 function floorNumber(x) { 64 x = fround(x); 65 return fround(floor(x)); 66 } 67 68 function squareRoot(x) { 69 x = fround(x); 70 return fround(sqrt(x)); 71 } 72 20 73 return { 21 74 number: number, 75 negate: negate, 76 add: add, 77 subtract: subtract, 78 multiply: multiply, 79 divide: divide, 80 absolute: absolute, 81 ceilNumber: ceilNumber, 82 floorNumber: floorNumber, 83 squareRoot: squareRoot, 22 84 }; 23 85 } … … 27 89 28 90 shouldBe(module.number(), 0.5); 91 shouldBe(module.negate(0.1), -0.10000000149011612); 92 shouldBe(module.add(0.1, 0.5), 0.6000000238418579); 93 shouldBe(isNaN(module.add(0.1, NaN)), true); 94 shouldBe(module.add(0.1, Infinity), Infinity); 95 shouldBe(isNaN(module.add(Infinity, -Infinity)), true); 96 shouldBe(module.subtract(0.1, 0.5), -0.4000000059604645); 97 shouldBe(module.multiply(0.1, 0.5), 0.05000000074505806); 98 shouldBe(module.divide(0.1, 0.5), 0.20000000298023224); 99 shouldBe(module.divide(0.1, 0), Infinity); 100 shouldBe(module.divide(0.1, -0), -Infinity); 101 shouldBe(module.absolute(-4.2), 4.199999809265137); 102 shouldBe(module.absolute(4.2), 4.199999809265137); 103 shouldBe(module.ceilNumber(4.2), 5); 104 shouldBe(module.floorNumber(4.2), 4); 105 shouldBe(module.squareRoot(0.09), 0.30000001192092896); -
trunk/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h
r189645 r189744 97 97 m_beginLabel = label(); 98 98 99 addPtr(TrustedImm32(-WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_stackHeight) * sizeof(StackSlot) ), GPRInfo::callFrameRegister, GPRInfo::regT1);99 addPtr(TrustedImm32(-WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_stackHeight) * sizeof(StackSlot) - maxFrameExtentForSlowPathCall), GPRInfo::callFrameRegister, GPRInfo::regT1); 100 100 m_stackOverflow = branchPtr(Above, AbsoluteAddress(m_vm->addressOfStackLimit()), GPRInfo::regT1); 101 101 … … 166 166 m_divideErrorJumpList.link(this); 167 167 168 if (maxFrameExtentForSlowPathCall)169 addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);170 168 setupArgumentsExecState(); 171 169 appendCallWithExceptionCheck(operationThrowDivideError); … … 378 376 } 379 377 store32(GPRInfo::regT0, temporaryAddress(m_tempStackTop - 1)); 378 return UNUSED; 379 } 380 381 int buildUnaryF32(int, WASMOpExpressionF32 op) 382 { 383 loadDouble(temporaryAddress(m_tempStackTop - 1), FPRInfo::fpRegT1); 384 switch (op) { 385 case WASMOpExpressionF32::Negate: 386 convertFloatToDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT1); 387 negateDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); 388 convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0); 389 break; 390 case WASMOpExpressionF32::Abs: 391 convertFloatToDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT1); 392 absDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); 393 convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0); 394 break; 395 case WASMOpExpressionF32::Ceil: 396 callOperation(ceilf, FPRInfo::fpRegT1, FPRInfo::fpRegT0); 397 break; 398 case WASMOpExpressionF32::Floor: 399 callOperation(floorf, FPRInfo::fpRegT1, FPRInfo::fpRegT0); 400 break; 401 case WASMOpExpressionF32::Sqrt: 402 convertFloatToDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT1); 403 sqrtDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); 404 convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0); 405 break; 406 default: 407 ASSERT_NOT_REACHED(); 408 } 409 storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_tempStackTop - 1)); 380 410 return UNUSED; 381 411 } … … 420 450 #else 421 451 // FIXME: We should be able to do an inline div on ARMv7 and ARM64. 422 if (maxFrameExtentForSlowPathCall)423 addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);424 452 switch (op) { 425 453 case WASMOpExpressionI32::SDiv: … … 438 466 ASSERT_NOT_REACHED(); 439 467 } 440 if (maxFrameExtentForSlowPathCall)441 addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);442 468 #endif 443 469 break; … … 466 492 m_tempStackTop--; 467 493 store32(GPRInfo::regT0, temporaryAddress(m_tempStackTop - 1)); 494 return UNUSED; 495 } 496 497 int buildBinaryF32(int, int, WASMOpExpressionF32 op) 498 { 499 loadDouble(temporaryAddress(m_tempStackTop - 2), FPRInfo::fpRegT0); 500 loadDouble(temporaryAddress(m_tempStackTop - 1), FPRInfo::fpRegT1); 501 convertFloatToDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT0); 502 convertFloatToDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT1); 503 switch (op) { 504 case WASMOpExpressionF32::Add: 505 addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); 506 break; 507 case WASMOpExpressionF32::Sub: 508 subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); 509 break; 510 case WASMOpExpressionF32::Mul: 511 mulDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); 512 break; 513 case WASMOpExpressionF32::Div: 514 divDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); 515 break; 516 default: 517 RELEASE_ASSERT_NOT_REACHED(); 518 } 519 convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0); 520 m_tempStackTop--; 521 storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_tempStackTop - 1)); 468 522 return UNUSED; 469 523 } … … 787 841 } 788 842 #endif 843 844 void callOperation(float JIT_OPERATION (*operation)(float), FPRegisterID src, FPRegisterID dst) 845 { 846 setupArguments(src); 847 appendCallSetResult(operation, dst); 848 } 789 849 790 850 void callOperation(int32_t JIT_OPERATION (*operation)(int32_t, int32_t), GPRReg src1, GPRReg src2, GPRReg dst) … … 856 916 857 917 end.link(this); 858 addPtr(TrustedImm32(-WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_stackHeight) * sizeof(StackSlot) ), GPRInfo::callFrameRegister, stackPointerRegister);918 addPtr(TrustedImm32(-WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_stackHeight) * sizeof(StackSlot) - maxFrameExtentForSlowPathCall), GPRInfo::callFrameRegister, stackPointerRegister); 859 919 checkStackPointerAlignment(); 860 920 -
trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.cpp
r189645 r189744 751 751 case WASMOpExpressionF32::GetGlobal: 752 752 return parseGetGlobalExpressionF32(context); 753 case WASMOpExpressionF32::Negate: 754 case WASMOpExpressionF32::Abs: 755 case WASMOpExpressionF32::Ceil: 756 case WASMOpExpressionF32::Floor: 757 case WASMOpExpressionF32::Sqrt: 758 return parseUnaryExpressionF32(context, op); 759 case WASMOpExpressionF32::Add: 760 case WASMOpExpressionF32::Sub: 761 case WASMOpExpressionF32::Mul: 762 case WASMOpExpressionF32::Div: 763 return parseBinaryExpressionF32(context, op); 753 764 case WASMOpExpressionF32::SetLocal: 754 765 case WASMOpExpressionF32::SetGlobal: … … 764 775 case WASMOpExpressionF32::FromU32: 765 776 case WASMOpExpressionF32::FromF64: 766 case WASMOpExpressionF32::Negate:767 case WASMOpExpressionF32::Add:768 case WASMOpExpressionF32::Sub:769 case WASMOpExpressionF32::Mul:770 case WASMOpExpressionF32::Div:771 case WASMOpExpressionF32::Abs:772 case WASMOpExpressionF32::Ceil:773 case WASMOpExpressionF32::Floor:774 case WASMOpExpressionF32::Sqrt:775 777 // FIXME: Implement these instructions. 776 778 FAIL_WITH_MESSAGE("Unsupported instruction."); … … 838 840 FAIL_IF_FALSE(m_module->globalVariableTypes()[globalIndex] == WASMType::F32, "Expected a global variable of type float32."); 839 841 return context.buildGetGlobal(globalIndex, WASMType::F32); 842 } 843 844 template <class Context> 845 ContextExpression WASMFunctionParser::parseUnaryExpressionF32(Context& context, WASMOpExpressionF32 op) 846 { 847 ContextExpression expression = parseExpressionF32(context); 848 PROPAGATE_ERROR(); 849 return context.buildUnaryF32(expression, op); 850 } 851 852 template <class Context> 853 ContextExpression WASMFunctionParser::parseBinaryExpressionF32(Context& context, WASMOpExpressionF32 op) 854 { 855 ContextExpression left = parseExpressionF32(context); 856 PROPAGATE_ERROR(); 857 ContextExpression right = parseExpressionF32(context); 858 PROPAGATE_ERROR(); 859 return context.buildBinaryF32(left, right, op); 840 860 } 841 861 -
trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h
r189645 r189744 104 104 template <class Context> ContextExpression parseGetLocalExpressionF32(Context&); 105 105 template <class Context> ContextExpression parseGetGlobalExpressionF32(Context&); 106 template <class Context> ContextExpression parseUnaryExpressionF32(Context&, WASMOpExpressionF32); 107 template <class Context> ContextExpression parseBinaryExpressionF32(Context&, WASMOpExpressionF32); 106 108 107 109 template <class Context> ContextExpression parseExpressionF64(Context&); -
trunk/Source/JavaScriptCore/wasm/WASMFunctionSyntaxChecker.h
r189645 r189744 107 107 } 108 108 109 int buildUnaryF32(int, WASMOpExpressionF32) 110 { 111 return UNUSED; 112 } 113 109 114 int buildBinaryI32(int, int, WASMOpExpressionI32) 115 { 116 m_tempStackTop--; 117 return UNUSED; 118 } 119 120 int buildBinaryF32(int, int, WASMOpExpressionF32) 110 121 { 111 122 m_tempStackTop--;
Note: See TracChangeset
for help on using the changeset viewer.