Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(289)

Side by Side Diff: runtime/lib/integers.dart

Issue 183973030: Faster _Smi.toString() (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Make names private (even if they are static). Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/corelib/corelib.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 // TODO(srdjan): fix limitations. 5 // TODO(srdjan): fix limitations.
6 // - shift amount must be a Smi. 6 // - shift amount must be a Smi.
7 class _IntegerImplementation { 7 class _IntegerImplementation {
8 factory _IntegerImplementation._uninstantiable() { 8 factory _IntegerImplementation._uninstantiable() {
9 throw new UnsupportedError( 9 throw new UnsupportedError(
10 "_IntegerImplementation can only be allocated by the VM"); 10 "_IntegerImplementation can only be allocated by the VM");
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 } 253 }
254 int get _identityHashCode { 254 int get _identityHashCode {
255 return this; 255 return this;
256 } 256 }
257 int operator ~() native "Smi_bitNegate"; 257 int operator ~() native "Smi_bitNegate";
258 int get bitLength native "Smi_bitLength"; 258 int get bitLength native "Smi_bitLength";
259 259
260 int _shrFromInt(int other) native "Smi_shrFromInt"; 260 int _shrFromInt(int other) native "Smi_shrFromInt";
261 int _shlFromInt(int other) native "Smi_shlFromInt"; 261 int _shlFromInt(int other) native "Smi_shlFromInt";
262 262
263 /**
264 * The digits of '00', '01', ... '99' as a single array.
265 *
266 * Get the digits of `n`, with `0 <= n < 100`, as
267 * `_digitTable[n * 2]` and `_digitTable[n * 2 + 1]`.
268 */
269 static const _digitTable = const [
270 0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33,
271 0x30, 0x34, 0x30, 0x35, 0x30, 0x36, 0x30, 0x37,
272 0x30, 0x38, 0x30, 0x39, 0x31, 0x30, 0x31, 0x31,
273 0x31, 0x32, 0x31, 0x33, 0x31, 0x34, 0x31, 0x35,
274 0x31, 0x36, 0x31, 0x37, 0x31, 0x38, 0x31, 0x39,
275 0x32, 0x30, 0x32, 0x31, 0x32, 0x32, 0x32, 0x33,
276 0x32, 0x34, 0x32, 0x35, 0x32, 0x36, 0x32, 0x37,
277 0x32, 0x38, 0x32, 0x39, 0x33, 0x30, 0x33, 0x31,
278 0x33, 0x32, 0x33, 0x33, 0x33, 0x34, 0x33, 0x35,
279 0x33, 0x36, 0x33, 0x37, 0x33, 0x38, 0x33, 0x39,
280 0x34, 0x30, 0x34, 0x31, 0x34, 0x32, 0x34, 0x33,
281 0x34, 0x34, 0x34, 0x35, 0x34, 0x36, 0x34, 0x37,
282 0x34, 0x38, 0x34, 0x39, 0x35, 0x30, 0x35, 0x31,
283 0x35, 0x32, 0x35, 0x33, 0x35, 0x34, 0x35, 0x35,
284 0x35, 0x36, 0x35, 0x37, 0x35, 0x38, 0x35, 0x39,
285 0x36, 0x30, 0x36, 0x31, 0x36, 0x32, 0x36, 0x33,
286 0x36, 0x34, 0x36, 0x35, 0x36, 0x36, 0x36, 0x37,
287 0x36, 0x38, 0x36, 0x39, 0x37, 0x30, 0x37, 0x31,
288 0x37, 0x32, 0x37, 0x33, 0x37, 0x34, 0x37, 0x35,
289 0x37, 0x36, 0x37, 0x37, 0x37, 0x38, 0x37, 0x39,
290 0x38, 0x30, 0x38, 0x31, 0x38, 0x32, 0x38, 0x33,
291 0x38, 0x34, 0x38, 0x35, 0x38, 0x36, 0x38, 0x37,
292 0x38, 0x38, 0x38, 0x39, 0x39, 0x30, 0x39, 0x31,
293 0x39, 0x32, 0x39, 0x33, 0x39, 0x34, 0x39, 0x35,
294 0x39, 0x36, 0x39, 0x37, 0x39, 0x38, 0x39, 0x39
295 ];
296
297 // Powers of 10 above 1000000 are indistinguishable.
298 static const int _POW_10_7 = 10000000;
299 static const int _POW_10_8 = 100000000;
300 static const int _POW_10_9 = 1000000000;
301 static const int _POW_10_10 = 10000000000;
302
303 // Find the number of decimal digits in a positive smi.
304 static int _positiveBase10Length(var smi) {
305 // A positive smi has length <= 19 if 63-bit, <=10 if 31-bit.
306 // Avoid comparing a 31-bit smi to a non-smi.
307 if (smi < 1000) return 3;
308 if (smi < 10000) return 4;
309 if (smi < _POW_10_7) {
310 if (smi < 100000) return 5;
311 if (smi < 1000000) return 6;
312 return 7;
313 }
314 if (smi < _POW_10_10) {
315 if (smi < _POW_10_8) return 8;
316 if (smi < _POW_10_9) return 9;
317 return 10;
318 }
319 smi = smi ~/ _POW_10_10;
320 if (smi < 10) return 11;
321 if (smi < 100) return 12;
322 return 10 + _positiveBase10Length(smi);
323 }
324
263 String toString() { 325 String toString() {
264 if (this == 0) return "0"; 326 if (this < 0) return _negativeToString(this);
265 var reversed = _toStringBuffer; 327 // Inspired by Andrei Alexandrescu: "Three Optimization Tips for C++"
266 var negative = false; 328 // Avoid expensive remainder operation by doing it on more than
267 var val = this; 329 // one digit at a time.
268 int index = 0; 330 const int DIGIT_ZERO = 0x30;
331 if (this < 10) {
332 return _OneByteString._allocate(1).._setAt(0, DIGIT_ZERO + this);
333 }
334 if (this < 100) {
335 int digitIndex = 2 * this;
336 return _OneByteString._allocate(2)
337 .._setAt(0, _digitTable[digitIndex])
338 .._setAt(1, _digitTable[digitIndex + 1]);
339 }
340 int length = _positiveBase10Length(this);
341 _OneByteString result = _OneByteString._allocate(length);
342 int index = length - 1;
343 var smi = this;
344 do {
345 // Two digits at a time.
346 var twoDigits = smi.remainder(100);
347 smi = smi ~/ 100;
348 int digitIndex = twoDigits * 2;
349 result._setAt(index, _digitTable[digitIndex + 1]);
350 result._setAt(index - 1, _digitTable[digitIndex]);
351 index -= 2;
352 } while (smi >= 100);
353 if (smi < 10) {
354 // Character code for '0'.
355 result._setAt(index, DIGIT_ZERO + smi);
356 } else {
357 // No remainder for this case.
358 int digitIndex = smi * 2;
359 result._setAt(index, _digitTable[digitIndex + 1]);
360 result._setAt(index - 1, _digitTable[digitIndex]);
361 }
362 return result;
363 }
269 364
270 if (this < 0) { 365 // Find the number of decimal digits in a negative smi.
271 negative = true; 366 static int _negativeBase10Length(var negSmi) {
272 // Handle the first digit as negative to avoid negating the minimum 367 // A negative smi has length <= 19 if 63-bit, <=10 if 31-bit.
273 // smi, for which the negation is not a smi. 368 // Avoid comparing a 31-bit smi to a non-smi.
274 int digit = -(val.remainder(10)); 369 if (negSmi > -1000) return 3;
275 reversed[index++] = digit + 0x30; 370 if (negSmi > -10000) return 4;
276 val = -(val ~/ 10); 371 if (negSmi > -_POW_10_7) {
372 if (negSmi > -100000) return 5;
373 if (negSmi > -1000000) return 6;
374 return 7;
277 } 375 }
376 if (negSmi > -_POW_10_10) {
377 if (negSmi > -_POW_10_8) return 8;
378 if (negSmi > -_POW_10_9) return 9;
379 return 10;
380 }
381 negSmi = negSmi ~/ _POW_10_10;
382 if (negSmi > -10) return 11;
383 if (negSmi > -100) return 12;
384 return 10 + _negativeBase10Length(negSmi);
385 }
278 386
279 while (val > 0) { 387 // Convert a negative smi to a string.
280 int digit = val % 10; 388 // Doesn't negate the smi to avoid negating the most negative smi, which
281 val = val ~/ 10; 389 // would become a non-smi.
282 reversed[index++] = (digit + 0x30); 390 static String _negativeToString(int negSmi) {
391 // Character code for '-'
392 const int MINUS_SIGN = 0x2d;
393 // Character code for '0'.
394 const int DIGIT_ZERO = 0x30;
395 if (negSmi > -10) {
396 return _OneByteString._allocate(2).._setAt(0, MINUS_SIGN)
397 .._setAt(1, DIGIT_ZERO - negSmi);
283 } 398 }
284 if (negative) reversed[index++] = 0x2D; // '-'. 399 if (negSmi > -100) {
285 400 int digitIndex = 2 * -negSmi;
286 _OneByteString string = _OneByteString._allocate(index); 401 return _OneByteString._allocate(3)
287 for (int i = 0, j = index; i < index; i++) { 402 .._setAt(0, MINUS_SIGN)
288 string._setAt(i, reversed[--j]); 403 .._setAt(1, _digitTable[digitIndex])
404 .._setAt(2, _digitTable[digitIndex + 1]);
289 } 405 }
290 return string; 406 // Number of digits, not including minus.
407 int digitCount = _negativeBase10Length(negSmi);
408 _OneByteString result = _OneByteString._allocate(digitCount + 1);
409 result._setAt(0, MINUS_SIGN); // '-'.
410 int index = digitCount;
411 do {
412 var twoDigits = negSmi.remainder(100);
413 negSmi = negSmi ~/ 100;
414 int digitIndex = -twoDigits * 2;
415 result._setAt(index, _digitTable[digitIndex + 1]);
416 result._setAt(index - 1, _digitTable[digitIndex]);
417 index -= 2;
418 } while (negSmi <= -100);
419 if (negSmi > -10) {
420 result._setAt(index, DIGIT_ZERO - negSmi);
421 } else {
422 // No remainder necessary for this case.
423 int digitIndex = -negSmi * 2;
424 result._setAt(index, _digitTable[digitIndex + 1]);
425 result._setAt(index - 1, _digitTable[digitIndex]);
426 }
427 return result;
291 } 428 }
292 } 429 }
293 430
294 // Reusable buffer used by smi.toString.
295 final List _toStringBuffer = new Uint8List(20);
296
297 // Represents integers that cannot be represented by Smi but fit into 64bits. 431 // Represents integers that cannot be represented by Smi but fit into 64bits.
298 class _Mint extends _IntegerImplementation implements int { 432 class _Mint extends _IntegerImplementation implements int {
299 factory _Mint._uninstantiable() { 433 factory _Mint._uninstantiable() {
300 throw new UnsupportedError( 434 throw new UnsupportedError(
301 "_Mint can only be allocated by the VM"); 435 "_Mint can only be allocated by the VM");
302 } 436 }
303 int get _identityHashCode { 437 int get _identityHashCode {
304 return this; 438 return this;
305 } 439 }
306 int operator ~() native "Mint_bitNegate"; 440 int operator ~() native "Mint_bitNegate";
(...skipping 30 matching lines...) Expand all
337 } else { 471 } else {
338 return 0; 472 return 0;
339 } 473 }
340 } 474 }
341 int _shlFromInt(int other) native "Bigint_shlFromInt"; 475 int _shlFromInt(int other) native "Bigint_shlFromInt";
342 476
343 int pow(int exponent) { 477 int pow(int exponent) {
344 throw "Bigint.pow not implemented"; 478 throw "Bigint.pow not implemented";
345 } 479 }
346 } 480 }
OLDNEW
« no previous file with comments | « no previous file | tests/corelib/corelib.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698