Chromium Code Reviews| Index: runtime/lib/growable_array.dart |
| diff --git a/runtime/lib/growable_array.dart b/runtime/lib/growable_array.dart |
| index fd3426ccd95e1507a097c909608601291ddd5177..64eeccef2b8467f2b45526e3b3bbf5b60d59cbec 100644 |
| --- a/runtime/lib/growable_array.dart |
| +++ b/runtime/lib/growable_array.dart |
| @@ -257,19 +257,61 @@ class _GrowableList<T> implements List<T> { |
| } |
| String join([String separator = ""]) { |
| - if (isEmpty) return ""; |
| - if (this.length == 1) return "${this[0]}"; |
| - StringBuffer buffer = new StringBuffer(); |
| - if (separator.isEmpty) { |
| - for (int i = 0; i < this.length; i++) { |
| - buffer.write(this[i]); |
| + final int length = this.length; |
| + if (length == 0) return ""; |
| + if (length == 1) return "${this[0]}"; |
| + if (separator.isNotEmpty) return _joinWithSeparator(separator); |
| + var i = 0; |
| + var codeUnitCount = 0; |
| + while (i < length) { |
| + final element = this[i]; |
| + final int cid = ClassID.getID(element); |
| + // While list contains one-byte strings. |
| + if (ClassID.cidOneByteString == cid) { |
| + codeUnitCount += element.length; |
| + i++; |
| + continue; |
| } |
| - } else { |
| - buffer.write(this[0]); |
| - for (int i = 1; i < this.length; i++) { |
| - buffer.write(separator); |
| - buffer.write(this[i]); |
| + final int firstNonOneByteStringLimit = i; |
| + var nextElement = element; |
| + while (nextElement is String) { |
|
Ivan Posva
2014/09/16 14:57:32
Please add comments where appropriate that this is
Lasse Reichstein Nielsen
2014/09/18 09:30:37
Done.
|
| + i++; |
| + if (i == length) { |
| + return _StringBase._concatRangeNative(this, 0, length); |
| + } |
| + nextElement = this[i]; |
| + } |
| + final list = new _List(length); |
| + for (int copyIndex = 0; copyIndex < i; copyIndex++) { |
| + list[copyIndex] = this[copyIndex]; |
| + } |
| + // Is non-zero if list contains a non-onebyte string. |
| + var onebyteCanary = i - firstNonOneByteStringLimit; |
| + while (true) { |
| + final String element = "$nextElement"; |
|
Ivan Posva
2014/09/16 14:57:32
Shadowing element makes this inner loop even more
Lasse Reichstein Nielsen
2014/09/18 09:30:37
Renamed to elementString.
|
| + onebyteCanary |= (ClassID.getID(element) ^ ClassID.cidOneByteString); |
| + list[i] = element; |
| + codeUnitCount += element.length; |
| + i++; |
| + if (i == length) break; |
| + nextElement = this[i]; |
| + } |
| + if (onebyteCanary == 0) { |
| + // All elements returned a one-byte string from toString. |
| + return _OneByteString._concatAll(list, codeUnitCount); |
| } |
| + return _StringBase._concatRangeNative(list, 0, length); |
|
Ivan Posva
2014/09/16 14:57:32
Might want to pass codeUnitCount? We already know
Lasse Reichstein Nielsen
2014/09/18 09:30:37
We probably always have that information, or could
|
| + } |
| + // All elements were one-byte strings. |
| + return _OneByteString._concatAll(this, codeUnitCount); |
| + } |
| + |
| + String _joinWithSeparator(String separator) { |
| + StringBuffer buffer = new StringBuffer(); |
| + buffer.write(this[0]); |
| + for (int i = 1; i < this.length; i++) { |
| + buffer.write(separator); |
| + buffer.write(this[i]); |
| } |
| return buffer.toString(); |
| } |