Chromium Code Reviews| Index: runtime/lib/string_patch.dart |
| diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart |
| index 3ac78a8fd9404faa5724cd771666eb61053110d5..fcdaa4974fa32ffe043bdc6d0f4e5c01ac0546cf 100644 |
| --- a/runtime/lib/string_patch.dart |
| +++ b/runtime/lib/string_patch.dart |
| @@ -518,32 +518,59 @@ class _StringBase { |
| return buffer.toString(); |
| } |
| - |
| /** |
| * Convert all objects in [values] to strings and concat them |
| * into a result string. |
| + * Modifies the input list if it contains non-`String` values. |
| */ |
| - static String _interpolate(List<String> values) { |
| + static String _interpolate(final List values) { |
| final numValues = values.length; |
| - _List stringList = new List<String>(numValues); |
| - bool isOneByteString = true; |
| + if (numValues <= 2) { |
| + // If possible, do this optimization at compiler level and call a |
| + // specialized _interpolateSingle when there is only one argument, |
| + // and _interpolateTwo with two. |
| + // Call here only with three or more arguments. |
| + // That would avoid allocating a list for the values if there are |
| + // only one or two. |
| + if (numValues == 0) return ""; |
| + final first = values[0]; |
| + final firstString = first.toString(); |
| + if (firstString is! String) { |
| + throw new ArgumentError(first); |
|
srdjan
2014/09/11 18:43:17
Use types for checked mode (final String firstStri
|
| + } |
| + if (numValues == 1) return firstString; |
| + final second = values[1]; |
| + final secondString = second.toString(); |
| + if (secondString is! String) { |
| + throw new ArgumentError(second); |
| + } |
| + return firstString + secondString; |
| + } |
| int totalLength = 0; |
| for (int i = 0; i < numValues; i++) { |
| - var s = values[i].toString(); |
| - if (isOneByteString && (ClassID.getID(s) == ClassID.cidOneByteString)) { |
| + final e = values[i]; |
| + final s = e.toString(); |
| + values[i] = s; |
| + if (ClassID.getID(s) == ClassID.cidOneByteString) { |
| totalLength += s.length; |
| - } else { |
| - isOneByteString = false; |
| + continue; |
| + } |
| + // Loops while the values convert to one-byte strings. |
| + if (s is! String) { |
| + throw new ArgumentError(s); |
| + } |
| + i++; |
| + for (;i < numValues; i++) { |
| + final e = values[i]; |
| + final s = e.toString(); |
| + values[i] = s; |
| if (s is! String) { |
| throw new ArgumentError(s); |
| } |
| } |
| - stringList[i] = s; |
| + return _concatRangeNative(values, 0, numValues); |
| } |
| - if (isOneByteString) { |
| - return _OneByteString._concatAll(stringList, totalLength); |
| - } |
| - return _concatRangeNative(stringList, 0, stringList.length); |
| + return _OneByteString._concatAll(values, totalLength); |
| } |
| Iterable<Match> allMatches(String string, [int start = 0]) { |
| @@ -661,6 +688,29 @@ class _OneByteString extends _StringBase implements String { |
| return super == other; |
| } |
| + String operator +(String other) { |
| + if (ClassID.getID(other) != ClassID.cidOneByteString) { |
| + return super + other; |
| + } |
| + final thisLength = this.length; |
| + final otherLength = other.length; |
| + final length = thisLength + otherLength; |
| + if (length > 128) { |
| + final list = new _List(2); |
| + list[0] = this; |
| + list[1] = other; |
| + return _concatAll(list, 0, 2); |
| + } |
| + final _OneByteString result = _allocate(length); |
| + for (int i = 0; i < thisLength; i++) { |
| + result._setAt(i, this.codeUnitAt(i)); |
| + } |
| + for (int i = 0; i < otherLength; i++) { |
| + result._setAt(thisLength + i, other.codeUnitAt(i)); |
| + } |
| + return result; |
| + } |
| + |
| String _substringUncheckedNative(int startIndex, int endIndex) |
| native "OneByteString_substringUnchecked"; |
| @@ -682,11 +732,11 @@ class _OneByteString extends _StringBase implements String { |
| // Native is quicker. |
| return _StringBase._concatRangeNative(strings, 0, strings.length); |
| } |
| - var res = _OneByteString._allocate(totalLength); |
| + final res = _OneByteString._allocate(totalLength); |
| final stringsLength = strings.length; |
| int rIx = 0; |
| for (int i = 0; i < stringsLength; i++) { |
| - _OneByteString e = strings[i]; |
| + final _OneByteString e = strings[i]; |
| final eLength = e.length; |
| for (int s = 0; s < eLength; s++) { |
| res._setAt(rIx++, e.codeUnitAt(s)); |