Changeset 211128 in webkit
- Timestamp:
- Jan 24, 2017, 6:40:52 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 4 edited
-
JSTests/ChangeLog (modified) (1 diff)
-
JSTests/stress/to-string-with-int52.js (added)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Source/JavaScriptCore/runtime/JSCJSValue.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/NumberPrototype.cpp (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r211122 r211128 1 2017-01-24 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [JSC] Optimize Number#toString with Int52 4 https://bugs.webkit.org/show_bug.cgi?id=167303 5 6 Reviewed by Sam Weinig. 7 8 * stress/to-string-with-int52.js: Added. 9 (shouldBe): 10 1 11 2017-01-24 Filip Pizlo <fpizlo@apple.com> 2 12 -
trunk/Source/JavaScriptCore/ChangeLog
r211124 r211128 1 2017-01-24 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [JSC] Optimize Number#toString with Int52 4 https://bugs.webkit.org/show_bug.cgi?id=167303 5 6 Reviewed by Sam Weinig. 7 8 In kraken crypto-sha256-iterative, we frequently call Number.prototype.toString with 9 Int52. In that case, toString handles it in the generic double path. But we should 10 have a fast path for this since it can be represented in int64_t. 11 12 The stanford-crypto-sha256-iterative shows 1.6% performance improvement (on Linux machine hanayamata). 13 14 Collected 100 samples per benchmark/VM, with 100 VM invocations per benchmark. Emitted a call to gc() between 15 sample measurements. Used 1 benchmark iteration per VM invocation for warm-up. Used the jsc-specific preciseTime() 16 function to get microsecond-level timing. Reporting benchmark execution times with 95% confidence intervals in 17 milliseconds. 18 19 baseline patched 20 21 stanford-crypto-sha256-iterative 32.853+-0.075 ^ 32.325+-0.055 ^ definitely 1.0163x faster 22 23 * runtime/JSCJSValue.h: 24 * runtime/NumberPrototype.cpp: 25 (JSC::int52ToStringWithRadix): 26 (JSC::toStringWithRadix): 27 1 28 2017-01-24 Michael Saboff <msaboff@apple.com> 2 29 -
trunk/Source/JavaScriptCore/runtime/JSCJSValue.h
r208985 r211128 317 317 // Constants used for Int52. Int52 isn't part of JSValue right now, but JSValues may be 318 318 // converted to Int52s and back again. 319 static const unsigned numberOfInt52Bits = 52;320 static const int64_t notInt52 = static_cast<int64_t>(1) << numberOfInt52Bits;321 static const unsigned int52ShiftAmount = 12;319 static constexpr const unsigned numberOfInt52Bits = 52; 320 static constexpr const int64_t notInt52 = static_cast<int64_t>(1) << numberOfInt52Bits; 321 static constexpr const unsigned int52ShiftAmount = 12; 322 322 323 323 static ptrdiff_t offsetOfPayload() { return OBJECT_OFFSETOF(JSValue, u.asBits.payload); } -
trunk/Source/JavaScriptCore/runtime/NumberPrototype.cpp
r209906 r211128 145 145 static const char radixDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; 146 146 147 static char* toStringWithRadix(RadixBuffer& buffer, double number, unsigned radix) 148 { 149 ASSERT(std::isfinite(number)); 147 static char* int52ToStringWithRadix(char* startOfResultString, int64_t int52Value, unsigned radix) 148 { 149 bool negative = false; 150 uint64_t positiveNumber = int52Value; 151 if (int52Value < 0) { 152 negative = true; 153 positiveNumber = -int52Value; 154 } 155 156 do { 157 uint64_t index = positiveNumber % radix; 158 ASSERT(index < sizeof(radixDigits)); 159 *--startOfResultString = radixDigits[index]; 160 positiveNumber /= radix; 161 } while (positiveNumber); 162 if (negative) 163 *--startOfResultString = '-'; 164 165 return startOfResultString; 166 } 167 168 static char* toStringWithRadix(RadixBuffer& buffer, double originalNumber, unsigned radix) 169 { 170 ASSERT(std::isfinite(originalNumber)); 150 171 ASSERT(radix >= 2 && radix <= 36); 151 172 … … 156 177 157 178 // Extract the sign. 158 bool isNegative = number < 0; 159 if (std::signbit(number)) 160 number = -number; 179 bool isNegative = originalNumber < 0; 180 double number = originalNumber; 181 if (std::signbit(originalNumber)) 182 number = -originalNumber; 161 183 double integerPart = floor(number); 162 163 // We use this to test for odd values in odd radix bases.164 // Where the base is even, (e.g. 10), to determine whether a value is even we need only165 // consider the least significant digit. For example, 124 in base 10 is even, because '4'166 // is even. if the radix is odd, then the radix raised to an integer power is also odd.167 // E.g. in base 5, 124 represents (1 * 125 + 2 * 25 + 4 * 5). Since each digit in the value168 // is multiplied by an odd number, the result is even if the sum of all digits is even.169 //170 // For the integer portion of the result, we only need test whether the integer value is171 // even or odd. For each digit of the fraction added, we should invert our idea of whether172 // the number is odd if the new digit is odd.173 //174 // Also initialize digit to this value; for even radix values we only need track whether175 // the last individual digit was odd.176 bool integerPartIsOdd = integerPart <= static_cast<double>(0x1FFFFFFFFFFFFFull) && static_cast<int64_t>(integerPart) & 1;177 ASSERT(integerPartIsOdd == static_cast<bool>(fmod(integerPart, 2)));178 bool isOddInOddRadix = integerPartIsOdd;179 uint32_t digit = integerPartIsOdd;180 184 181 185 // Check if the value has a fractional part to convert. 182 186 double fractionPart = number - integerPart; 183 if (fractionPart) { 187 if (!fractionPart) { 188 *decimalPoint = '\0'; 189 // We do not need to care the negative zero (-0) since it is also converted to "0" in all the radix. 190 if (integerPart < (static_cast<int64_t>(1) << (JSValue::numberOfInt52Bits - 1))) 191 return int52ToStringWithRadix(startOfResultString, static_cast<int64_t>(originalNumber), radix); 192 } else { 193 // We use this to test for odd values in odd radix bases. 194 // Where the base is even, (e.g. 10), to determine whether a value is even we need only 195 // consider the least significant digit. For example, 124 in base 10 is even, because '4' 196 // is even. if the radix is odd, then the radix raised to an integer power is also odd. 197 // E.g. in base 5, 124 represents (1 * 125 + 2 * 25 + 4 * 5). Since each digit in the value 198 // is multiplied by an odd number, the result is even if the sum of all digits is even. 199 // 200 // For the integer portion of the result, we only need test whether the integer value is 201 // even or odd. For each digit of the fraction added, we should invert our idea of whether 202 // the number is odd if the new digit is odd. 203 // 204 // Also initialize digit to this value; for even radix values we only need track whether 205 // the last individual digit was odd. 206 bool integerPartIsOdd = integerPart <= static_cast<double>(0x1FFFFFFFFFFFFFull) && static_cast<int64_t>(integerPart) & 1; 207 ASSERT(integerPartIsOdd == static_cast<bool>(fmod(integerPart, 2))); 208 bool isOddInOddRadix = integerPartIsOdd; 209 uint32_t digit = integerPartIsOdd; 210 184 211 // Write the decimal point now. 185 212 *decimalPoint = '.'; … … 311 338 *endOfResultString = '\0'; 312 339 ASSERT(endOfResultString < buffer + sizeof(buffer)); 313 } else 314 *decimalPoint = '\0'; 340 } 315 341 316 342 BigInteger units(integerPart); … … 322 348 // Read a single digit and write it to the front of the string. 323 349 // Divide by radix to remove one digit from the value. 324 digit = units.divide(radix);350 uint32_t digit = units.divide(radix); 325 351 *--startOfResultString = radixDigits[digit]; 326 352 } while (!!units);
Note:
See TracChangeset
for help on using the changeset viewer.