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

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

Issue 42443002: Improve string library performance. String concat and indexOf. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month 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 | « runtime/lib/string_buffer_patch.dart ('k') | runtime/vm/bootstrap_natives.h » ('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 patch class String { 5 patch class String {
6 /* patch */ factory String.fromCharCodes(Iterable<int> charCodes) { 6 /* patch */ factory String.fromCharCodes(Iterable<int> charCodes) {
7 return _StringBase.createFromCharCodes(charCodes); 7 return _StringBase.createFromCharCodes(charCodes);
8 } 8 }
9 } 9 }
10 10
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 String operator +(String other) native "String_concat"; 77 String operator +(String other) native "String_concat";
78 78
79 String toString() { 79 String toString() {
80 return this; 80 return this;
81 } 81 }
82 82
83 bool operator ==(Object other) { 83 bool operator ==(Object other) {
84 if (identical(this, other)) { 84 if (identical(this, other)) {
85 return true; 85 return true;
86 } 86 }
87 if ((other is !String) || 87 if ((other is! String) ||
88 (this.length != other.length)) { 88 (this.length != other.length)) {
89 // TODO(5413632): Compare hash codes when both are present.
90 return false; 89 return false;
91 } 90 }
92 final len = this.length; 91 final len = this.length;
93 for (int i = 0; i < len; i++) { 92 for (int i = 0; i < len; i++) {
94 if (this.codeUnitAt(i) != other.codeUnitAt(i)) { 93 if (this.codeUnitAt(i) != other.codeUnitAt(i)) {
95 return false; 94 return false;
96 } 95 }
97 } 96 }
98 return true; 97 return true;
99 } 98 }
(...skipping 13 matching lines...) Expand all
113 return 1; 112 return 1;
114 } 113 }
115 } 114 }
116 if (thisLength < otherLength) return -1; 115 if (thisLength < otherLength) return -1;
117 if (thisLength > otherLength) return 1; 116 if (thisLength > otherLength) return 1;
118 return 0; 117 return 0;
119 } 118 }
120 119
121 bool _substringMatches(int start, String other) { 120 bool _substringMatches(int start, String other) {
122 if (other.isEmpty) return true; 121 if (other.isEmpty) return true;
123 final int len = other.length; 122 final len = other.length;
124 if ((start < 0) || (start + len > this.length)) { 123 if ((start < 0) || (start + len > this.length)) {
125 return false; 124 return false;
126 } 125 }
127 for (int i = 0; i < len; i++) { 126 for (int i = 0; i < len; i++) {
128 if (this.codeUnitAt(i + start) != other.codeUnitAt(i)) { 127 if (this.codeUnitAt(i + start) != other.codeUnitAt(i)) {
129 return false; 128 return false;
130 } 129 }
131 } 130 }
132 return true; 131 return true;
133 } 132 }
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 ((0x2000 <= codePoint) && (codePoint <= 0x200A)) || 257 ((0x2000 <= codePoint) && (codePoint <= 0x200A)) ||
259 (codePoint == 0x2028) || 258 (codePoint == 0x2028) ||
260 (codePoint == 0x2029) || 259 (codePoint == 0x2029) ||
261 (codePoint == 0x202F) || 260 (codePoint == 0x202F) ||
262 (codePoint == 0x205F) || 261 (codePoint == 0x205F) ||
263 (codePoint == 0x3000) || 262 (codePoint == 0x3000) ||
264 (codePoint == 0xFEFF); 263 (codePoint == 0xFEFF);
265 } 264 }
266 265
267 String trim() { 266 String trim() {
268 final int len = this.length; 267 final len = this.length;
269 int first = 0; 268 int first = 0;
270 for (; first < len; first++) { 269 for (; first < len; first++) {
271 if (!_isWhitespace(this.codeUnitAt(first))) { 270 if (!_isWhitespace(this.codeUnitAt(first))) {
272 break; 271 break;
273 } 272 }
274 } 273 }
275 if (len == first) { 274 if (len == first) {
276 // String contains only whitespaces. 275 // String contains only whitespaces.
277 return ""; 276 return "";
278 } 277 }
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 buffer.write(onNonMatch(this.substring(startIndex))); 397 buffer.write(onNonMatch(this.substring(startIndex)));
399 return buffer.toString(); 398 return buffer.toString();
400 } 399 }
401 400
402 401
403 /** 402 /**
404 * Convert all objects in [values] to strings and concat them 403 * Convert all objects in [values] to strings and concat them
405 * into a result string. 404 * into a result string.
406 */ 405 */
407 static String _interpolate(List<String> values) { 406 static String _interpolate(List<String> values) {
408 final int numValues = values.length; 407 final numValues = values.length;
409 _List stringList = new List<String>(numValues); 408 _List stringList = new List<String>(numValues);
410 bool isOneByteString = true; 409 bool isOneByteString = true;
411 int totalLength = 0; 410 int totalLength = 0;
412 for (int i = 0; i < numValues; i++) { 411 for (int i = 0; i < numValues; i++) {
413 var s = values[i].toString(); 412 var s = values[i].toString();
414 if (isOneByteString && (s._cid == _OneByteString._classId)) { 413 if (isOneByteString && (s._cid == _OneByteString._classId)) {
415 totalLength += s.length; 414 totalLength += s.length;
416 } else { 415 } else {
417 isOneByteString = false; 416 isOneByteString = false;
418 if (s is! String) { 417 if (s is! String) {
419 throw new ArgumentError(s); 418 throw new ArgumentError(s);
420 } 419 }
421 } 420 }
422 stringList[i] = s; 421 stringList[i] = s;
423 } 422 }
424 if (isOneByteString) { 423 if (isOneByteString) {
425 return _OneByteString._concatAll(stringList, totalLength); 424 return _OneByteString._concatAll(stringList, totalLength);
426 } 425 }
427 return _concatAllNative(stringList, 0, stringList.length); 426 return _concatRangeNative(stringList, 0, stringList.length);
428 } 427 }
429 428
430 Iterable<Match> allMatches(String str) { 429 Iterable<Match> allMatches(String str) {
431 List<Match> result = new List<Match>(); 430 List<Match> result = new List<Match>();
432 int length = str.length; 431 int length = str.length;
433 int patternLength = this.length; 432 int patternLength = this.length;
434 int startIndex = 0; 433 int startIndex = 0;
435 while (true) { 434 while (true) {
436 int position = str.indexOf(this, startIndex); 435 int position = str.indexOf(this, startIndex);
437 if (position == -1) { 436 if (position == -1) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 } 501 }
503 502
504 List<int> get codeUnits => new _CodeUnits(this); 503 List<int> get codeUnits => new _CodeUnits(this);
505 504
506 Runes get runes => new Runes(this); 505 Runes get runes => new Runes(this);
507 506
508 String toUpperCase() native "String_toUpperCase"; 507 String toUpperCase() native "String_toUpperCase";
509 508
510 String toLowerCase() native "String_toLowerCase"; 509 String toLowerCase() native "String_toLowerCase";
511 510
511 // Concatenate ['start', 'end'[ elements of 'strings'. 'strings' must contain
512 // String elements. Optimized for OneByteStrings.
513 static String _concatRange(List<String> strings, int start, int end) {
514 if ((end - start) == 1) {
515 return strings[start];
516 }
517 final numValues = strings.length;
518 if ((start == 0) && (end == numValues)) {
519 int totalLength = 0;
520 for (int i = 0; i < numValues; i++) {
521 String s = strings[i];
522 if (s._cid != _OneByteString._classId) {
523 return _concatRangeNative(strings, start, end);
524 }
525 totalLength += s.length;
526 }
527 return _OneByteString._concatAll(strings, totalLength);
528 }
529 return _concatRangeNative(strings, start, end);
530 }
531
512 // Call this method if not all list elements are known to be OneByteString(s). 532 // Call this method if not all list elements are known to be OneByteString(s).
513 // 'strings' must be an _List or _GrowableList. 533 // 'strings' must be an _List or _GrowableList.
514 static String _concatAllNative(List<String> strings, int start, int end) 534 static String _concatRangeNative(List<String> strings, int start, int end)
515 native "Strings_concatAll"; 535 native "String_concatRange";
516 } 536 }
517 537
518 538
519 class _OneByteString extends _StringBase implements String { 539 class _OneByteString extends _StringBase implements String {
520 static final int _classId = "A"._cid; 540 static final int _classId = "A"._cid;
521 541
522 factory _OneByteString._uninstantiable() { 542 factory _OneByteString._uninstantiable() {
523 throw new UnsupportedError( 543 throw new UnsupportedError(
524 "_OneByteString can only be allocated by the VM"); 544 "_OneByteString can only be allocated by the VM");
525 } 545 }
(...skipping 15 matching lines...) Expand all
541 native "OneByteString_splitWithCharCode"; 561 native "OneByteString_splitWithCharCode";
542 562
543 List<String> split(Pattern pattern) { 563 List<String> split(Pattern pattern) {
544 if ((pattern._cid == _OneByteString._classId) && (pattern.length == 1)) { 564 if ((pattern._cid == _OneByteString._classId) && (pattern.length == 1)) {
545 return _splitWithCharCode(pattern.codeUnitAt(0)); 565 return _splitWithCharCode(pattern.codeUnitAt(0));
546 } 566 }
547 return super.split(pattern); 567 return super.split(pattern);
548 } 568 }
549 569
550 // All element of 'strings' must be OneByteStrings. 570 // All element of 'strings' must be OneByteStrings.
551 static _concatAll(_List<String> strings, int totalLength) { 571 static _concatAll(List<String> strings, int totalLength) {
552 // TODO(srdjan): Improve code below and raise or eliminate the limit. 572 // TODO(srdjan): Improve code below and raise or eliminate the limit.
553 if (totalLength > 128) { 573 if (totalLength > 128) {
554 // Native is quicker. 574 // Native is quicker.
555 return _StringBase._concatAllNative(strings, 0, strings.length); 575 return _StringBase._concatRangeNative(strings, 0, strings.length);
556 } 576 }
557 var res = _OneByteString._allocate(totalLength); 577 var res = _OneByteString._allocate(totalLength);
558 final stringsLength = strings.length; 578 final stringsLength = strings.length;
559 int rIx = 0; 579 int rIx = 0;
560 for (int i = 0; i < stringsLength; i++) { 580 for (int i = 0; i < stringsLength; i++) {
561 _OneByteString e = strings[i]; 581 _OneByteString e = strings[i];
562 final eLength = e.length; 582 final eLength = e.length;
563 for (int s = 0; s < eLength; s++) { 583 for (int s = 0; s < eLength; s++) {
564 res._setAt(rIx++, e.codeUnitAt(s)); 584 res._setAt(rIx++, e.codeUnitAt(s));
565 } 585 }
566 } 586 }
567 return res; 587 return res;
568 } 588 }
569 589
590 int indexOf(Pattern pattern, [int start = 0]) {
591 final len = this.length;
592 // Specialize for single character pattern.
593 // TODO(srdjan): Implement for other string classes.
594 if ((pattern._cid == _OneByteString._classId) &&
595 (pattern.length == 1) &&
596 (start >= 0) && (start < len)) {
597 final patternCu0 = pattern.codeUnitAt(0);
598 for (int i = start; i < len; i++) {
599 if (this.codeUnitAt(i) == patternCu0) {
600 return i;
601 }
602 }
603 return -1;
604 }
605 return super.indexOf(pattern, start);
606 }
607
570 // Allocates a string of given length, expecting its content to be 608 // Allocates a string of given length, expecting its content to be
571 // set using _setAt. 609 // set using _setAt.
572 static _OneByteString _allocate(int length) native "OneByteString_allocate"; 610 static _OneByteString _allocate(int length) native "OneByteString_allocate";
573 611
574 // This is internal helper method. Code point value must be a valid 612 // This is internal helper method. Code point value must be a valid
575 // Latin1 value (0..0xFF), index must be valid. 613 // Latin1 value (0..0xFF), index must be valid.
576 void _setAt(int index, int codePoint) native "OneByteString_setAt"; 614 void _setAt(int index, int codePoint) native "OneByteString_setAt";
577 } 615 }
578 616
579 617
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 class _CodeUnits extends Object with ListMixin<int>, 698 class _CodeUnits extends Object with ListMixin<int>,
661 UnmodifiableListMixin<int> { 699 UnmodifiableListMixin<int> {
662 /** The string that this is the code units of. */ 700 /** The string that this is the code units of. */
663 String _string; 701 String _string;
664 702
665 _CodeUnits(this._string); 703 _CodeUnits(this._string);
666 704
667 int get length => _string.length; 705 int get length => _string.length;
668 int operator[](int i) => _string.codeUnitAt(i); 706 int operator[](int i) => _string.codeUnitAt(i);
669 } 707 }
OLDNEW
« no previous file with comments | « runtime/lib/string_buffer_patch.dart ('k') | runtime/vm/bootstrap_natives.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698