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

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: Using a list of integers is cheaper than looking up in a string. 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 static const digits = const [
Anders Johnsen 2014/03/05 14:41:33 better name? Also, all of this new stuff should b
Lasse Reichstein Nielsen 2014/03/06 12:25:37 -> digitTable. No *need* for private, it's all st
srdjan 2014/03/06 17:57:14 All public members of a private class are accessib
Lasse Reichstein Nielsen 2014/03/07 09:29:20 Private members are also accessible with the same
264 0x30,0x30,0x30,0x31,0x30,0x32,0x30,0x33,
265 0x30,0x34,0x30,0x35,0x30,0x36,0x30,0x37,
266 0x30,0x38,0x30,0x39,0x31,0x30,0x31,0x31,
267 0x31,0x32,0x31,0x33,0x31,0x34,0x31,0x35,
268 0x31,0x36,0x31,0x37,0x31,0x38,0x31,0x39,
269 0x32,0x30,0x32,0x31,0x32,0x32,0x32,0x33,
270 0x32,0x34,0x32,0x35,0x32,0x36,0x32,0x37,
271 0x32,0x38,0x32,0x39,0x33,0x30,0x33,0x31,
272 0x33,0x32,0x33,0x33,0x33,0x34,0x33,0x35,
273 0x33,0x36,0x33,0x37,0x33,0x38,0x33,0x39,
274 0x34,0x30,0x34,0x31,0x34,0x32,0x34,0x33,
275 0x34,0x34,0x34,0x35,0x34,0x36,0x34,0x37,
276 0x34,0x38,0x34,0x39,0x35,0x30,0x35,0x31,
277 0x35,0x32,0x35,0x33,0x35,0x34,0x35,0x35,
278 0x35,0x36,0x35,0x37,0x35,0x38,0x35,0x39,
279 0x36,0x30,0x36,0x31,0x36,0x32,0x36,0x33,
280 0x36,0x34,0x36,0x35,0x36,0x36,0x36,0x37,
281 0x36,0x38,0x36,0x39,0x37,0x30,0x37,0x31,
282 0x37,0x32,0x37,0x33,0x37,0x34,0x37,0x35,
283 0x37,0x36,0x37,0x37,0x37,0x38,0x37,0x39,
284 0x38,0x30,0x38,0x31,0x38,0x32,0x38,0x33,
285 0x38,0x34,0x38,0x35,0x38,0x36,0x38,0x37,
286 0x38,0x38,0x38,0x39,0x39,0x30,0x39,0x31,
287 0x39,0x32,0x39,0x33,0x39,0x34,0x39,0x35,
288 0x39,0x36,0x39,0x37,0x39,0x38,0x39,0x39
289 ];
290
291 static const int P01 = 10;
292 static const int P02 = 100;
293 static const int P03 = 1000;
294 static const int P04 = 10000;
295 static const int P05 = 100000;
296 static const int P06 = 1000000;
297 static const int P07 = 10000000;
298 static const int P08 = 100000000;
299 static const int P09 = 1000000000;
300 static const int P10 = 10000000000;
301
302 // Find the number of decimal digits in a positive smi.
303 static int positiveBase10Length(var smi) {
304 // A positive smi has length <= 19 if 63-bit, <=10 if 31-bit.
305 // Avoid comparing a 31-bit smi to a non-smi.
306 if (smi < P03) return 3;
307 if (smi < P04) return 4;
308 if (smi < P07) {
309 if (smi < P05) return 5;
310 if (smi < P06) return 6;
311 return 7;
312 }
313 if (smi < P10) {
314 if (smi < P08) return 8;
315 if (smi < P09) return 9;
316 return 10;
317 }
318 smi = smi ~/ P10;
319 if (smi < P01) return 11;
320 if (smi < P02) return 12;
321 return 10 + positiveBase10Length(smi);
322 }
323
263 String toString() { 324 String toString() {
264 if (this == 0) return "0"; 325 if (this == 0) return "0";
265 var reversed = _toStringBuffer; 326 if (this < 0) return negativeToString(this);
266 var negative = false; 327 // Inspired by Andrei Alexandrescu: "Three Optimization Tips for C++"
267 var val = this; 328 // Avoid expensive remainder operation by doing it on more than
268 int index = 0; 329 // one digit at a time.
330 int length = this < 10 ? 1 : this < 100 ? 2 : positiveBase10Length(this);
srdjan 2014/03/05 17:40:46 Please use parentheses.
Lasse Reichstein Nielsen 2014/03/06 12:25:37 Rewritten.
331 _OneByteString result = _OneByteString._allocate(length);
332 int index = length - 1;
333 var smi = this;
334 while (smi >= 100) {
335 // Two digits at a time.
336 var twoDigits = smi.remainder(100);
337 smi = smi ~/ 100;
338 int digitIndex = twoDigits * 2;
339 result._setAt(index, digits[digitIndex + 1]);
340 result._setAt(index - 1, digits[digitIndex]);
341 index -= 2;
342 }
343 if (smi >= 10) {
344 // No remainder for this case.
345 int digitIndex = smi * 2;
346 result._setAt(index, digits[digitIndex + 1]);
347 result._setAt(index - 1, digits[digitIndex]);
348 } else {
349 result._setAt(index, 0x30 + smi);
350 }
351 return result;
352 }
269 353
270 if (this < 0) { 354 // Find the number of decimal digits in a negative smi.
271 negative = true; 355 static int negativeBase10Length(var negSmi) {
272 // Handle the first digit as negative to avoid negating the minimum 356 // A negative smi has length <= 19 if 63-bit, <=10 if 31-bit.
273 // smi, for which the negation is not a smi. 357 // Avoid comparing a 31-bit smi to a non-smi.
274 int digit = -(val.remainder(10)); 358 if (negSmi > -P03) return 3;
275 reversed[index++] = digit + 0x30; 359 if (negSmi > -P04) return 4;
276 val = -(val ~/ 10); 360 if (negSmi > -P07) {
361 if (negSmi > -P05) return 5;
362 if (negSmi > -P06) return 6;
363 return 7;
277 } 364 }
365 if (negSmi > -P10) {
366 if (negSmi > -P08) return 8;
367 if (negSmi > -P09) return 9;
368 return 10;
369 }
370 negSmi = negSmi ~/ P10;
371 if (negSmi > -P01) return 11;
372 if (negSmi > -P02) return 12;
373 return 10 + negativeBase10Length(negSmi);
374 }
278 375
279 while (val > 0) { 376 // Convert a negative smi to a string.
280 int digit = val % 10; 377 // Doesn't negate the smi to avoid negating the most negative smi, which
281 val = val ~/ 10; 378 // would become a non-smi.
282 reversed[index++] = (digit + 0x30); 379 static String negativeToString(int negSmi) {
380 // Number of digits, not including minus.
381 int digitCount =
382 (negSmi > -10) ? 1 : (negSmi > -100) ? 2 : negativeBase10Length(negSmi);
383 _OneByteString result = _OneByteString._allocate(digitCount + 1);
384 result._setAt(0, 0x2D); // '-'.
385 int index = digitCount;
386 while (negSmi <= -100) {
387 var twoDigits = negSmi.remainder(100);
388 negSmi = negSmi ~/ 100;
389 int digitIndex = -twoDigits * 2;
390 result._setAt(index, digits[digitIndex + 1]);
391 result._setAt(index - 1, digits[digitIndex]);
392 index -= 2;
283 } 393 }
284 if (negative) reversed[index++] = 0x2D; // '-'. 394 if (negSmi <= -10) {
285 395 // No remainder necessary for this case.
286 _OneByteString string = _OneByteString._allocate(index); 396 int digitIndex = -negSmi * 2;
287 for (int i = 0, j = index; i < index; i++) { 397 result._setAt(index, digits[digitIndex + 1]);
288 string._setAt(i, reversed[--j]); 398 result._setAt(index - 1, digits[digitIndex]);
399 } else {
400 result._setAt(index, 0x30 - negSmi);
289 } 401 }
290 return string; 402 return result;
291 } 403 }
292 } 404 }
293 405
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. 406 // Represents integers that cannot be represented by Smi but fit into 64bits.
298 class _Mint extends _IntegerImplementation implements int { 407 class _Mint extends _IntegerImplementation implements int {
299 factory _Mint._uninstantiable() { 408 factory _Mint._uninstantiable() {
300 throw new UnsupportedError( 409 throw new UnsupportedError(
301 "_Mint can only be allocated by the VM"); 410 "_Mint can only be allocated by the VM");
302 } 411 }
303 int get _identityHashCode { 412 int get _identityHashCode {
304 return this; 413 return this;
305 } 414 }
306 int operator ~() native "Mint_bitNegate"; 415 int operator ~() native "Mint_bitNegate";
(...skipping 30 matching lines...) Expand all
337 } else { 446 } else {
338 return 0; 447 return 0;
339 } 448 }
340 } 449 }
341 int _shlFromInt(int other) native "Bigint_shlFromInt"; 450 int _shlFromInt(int other) native "Bigint_shlFromInt";
342 451
343 int pow(int exponent) { 452 int pow(int exponent) {
344 throw "Bigint.pow not implemented"; 453 throw "Bigint.pow not implemented";
345 } 454 }
346 } 455 }
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