[dart2wasm] StringBuffer improvements

Use `U16List` instead of `Uint16List` as the character buffer type.
Access the Wasm array directly when writing characters and converting
the final buffer to a String. This avoids bounds checks and uses
`array.copy` when allocating the final string.

Change-Id: I570494e8349adc7a268544544516c9947abc8604
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/371681
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
This commit is contained in:
Ömer Sinan Ağacan 2024-06-14 13:03:41 +00:00 committed by Commit Queue
parent 7078310249
commit 76f6a32432
2 changed files with 39 additions and 13 deletions

View file

@ -58,12 +58,39 @@ OneByteString createOneByteStringFromCharacters(
U8List bytes, int start, int end) =>
createOneByteStringFromCharactersArray(bytes.data, start, end);
/// Create a [OneByteString] with the [array] contents in the range from
/// [start] to [end] (exclusive).
@pragma("wasm:prefer-inline")
OneByteString createOneByteStringFromCharactersArray(
WasmArray<WasmI8> bytes, int start, int end) {
WasmArray<WasmI8> array, int start, int end) {
final len = end - start;
final s = OneByteString.withLength(len);
s._array.copy(0, bytes, start, len);
s._array.copy(0, array, start, len);
return s;
}
/// Same as [createOneByteStringFromCharactersArray], but the one-byte
/// character array is an `i16 array` instead of `i8 array`.
@pragma("wasm:prefer-inline")
OneByteString createOneByteStringFromTwoByteCharactersArray(
WasmArray<WasmI16> array, int start, int end) {
final len = end - start;
final s = OneByteString.withLength(len);
for (int i = 0; i < len; i += 1) {
final i16 = array.readUnsigned(start + i);
s._array.write(i, i16);
}
return s;
}
/// Create a [TwoByteString] with the [array] contents in the range from
/// [start] to [end] (exclusive).
@pragma("wasm:prefer-inline")
TwoByteString createTwoByteStringFromCharactersArray(
WasmArray<WasmI16> array, int start, int end) {
final len = end - start;
final s = TwoByteString.withLength(len);
s._array.copy(0, array, start, len);
return s;
}

View file

@ -3,11 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
import "dart:_internal" show patch;
import "dart:_string" show StringBase, TwoByteString;
import "dart:_string";
import "dart:_typed_data";
import "dart:_wasm";
import "dart:typed_data" show Uint16List;
@patch
class StringBuffer {
static const int _BUFFER_SIZE = 64;
@ -42,7 +41,7 @@ class StringBuffer {
* used when writing short strings or individual char codes to the
* buffer. The buffer is allocated on demand.
*/
Uint16List? _buffer;
WasmArray<WasmI16>? _buffer;
int _bufferPosition = 0;
/**
@ -80,7 +79,7 @@ class StringBuffer {
}
_ensureCapacity(1);
final localBuffer = _buffer!;
localBuffer[_bufferPosition++] = charCode;
localBuffer.write(_bufferPosition++, charCode);
_bufferCodeUnitMagnitude |= charCode;
} else {
if (charCode > 0x10FFFF) {
@ -89,8 +88,8 @@ class StringBuffer {
_ensureCapacity(2);
int bits = charCode - 0x10000;
final localBuffer = _buffer!;
localBuffer[_bufferPosition++] = 0xD800 | (bits >> 10);
localBuffer[_bufferPosition++] = 0xDC00 | (bits & 0x3FF);
localBuffer.write(_bufferPosition++, 0xD800 | (bits >> 10));
localBuffer.write(_bufferPosition++, 0xDC00 | (bits & 0x3FF));
_bufferCodeUnitMagnitude |= 0xFFFF;
}
}
@ -140,7 +139,7 @@ class StringBuffer {
void _ensureCapacity(int n) {
final localBuffer = _buffer;
if (localBuffer == null) {
_buffer = Uint16List(_BUFFER_SIZE);
_buffer = WasmArray<WasmI16>(_BUFFER_SIZE);
} else if (_bufferPosition + n > localBuffer.length) {
_consumeBuffer();
}
@ -212,11 +211,11 @@ class StringBuffer {
/**
* Create a [String] from the UFT-16 code units in buffer.
*/
static String _create(Uint16List buffer, int length, bool isLatin1) {
static String _create(WasmArray<WasmI16> buffer, int length, bool isLatin1) {
if (isLatin1) {
return StringBase.createOneByteString(buffer, 0, length);
return createOneByteStringFromTwoByteCharactersArray(buffer, 0, length);
} else {
return TwoByteString.allocateFromTwoByteList(buffer, 0, length);
return createTwoByteStringFromCharactersArray(buffer, 0, length);
}
}
}