| Index: runtime/lib/growable_array.dart
|
| diff --git a/runtime/lib/growable_array.dart b/runtime/lib/growable_array.dart
|
| index fd3426ccd95e1507a097c909608601291ddd5177..4d6b69785aa1f40549ac47f7e554bb0ddcb14606 100644
|
| --- a/runtime/lib/growable_array.dart
|
| +++ b/runtime/lib/growable_array.dart
|
| @@ -257,19 +257,68 @@ 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);
|
| + 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) {
|
| + i++;
|
| + if (i == length) {
|
| + return _StringBase._concatRangeNative(this, 0, length);
|
| + }
|
| + nextElement = this[i];
|
| + }
|
| + // return _StringBase._interpolate(this);
|
| + 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 element =
|
| + (nextElement is String) ? nextElement
|
| + :_forceToString(nextElement);
|
| + onebyteCanary |= (ClassID.getID(element) ^ ClassID.cidOneByteString);
|
| + list[i] = element;
|
| + codeUnitCount += element.length;
|
| + i++;
|
| + if (i == length) break;
|
| + nextElement = this[i];
|
| + }
|
| + if (onebyteCanary == 0) {
|
| + return _OneByteString._concatAll(list, codeUnitCount);
|
| + }
|
| + return _StringBase._concatRangeNative(list, 0, length);
|
| + }
|
| + return _OneByteString._concatAll(this, codeUnitCount);
|
| + }
|
| +
|
| + static String _forceToString(Object object) {
|
| + assert(object is! String);
|
| + final result = object.toString();
|
| + if (result is String) return result;
|
| + throw new ArgumentError(object);
|
| + }
|
| +
|
| + 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();
|
| }
|
|
|