c6362da241
Currently `convertSingle` converts the input to `U8List`, but `convertChunked` works on `Uint8List`. This makes functions common in both (`decode8`, `decode16`) polymorphic in input. Update `convertChunked` to also convert the input to `U8List`. With this `decode8` and `decode16` becomes monomorphic in the input type. Also update array accesses in these methods to avoid bounds checks. Check for a few fast cases in `List<int>` to `U8List` copying. If the list is a `WasmI8ArrayBase` (used in typed data) or `WasmListBase` (used in lists), we avoid polymorphism, indirections, and bounds checks during copying. Golem reports up to 600% improvement in some chunked parsing micro- benchmarks. Change-Id: Iddf6dae1a5d77cf574be77313dff779b4715e283 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/395980 Commit-Queue: Ömer Ağacan <omersa@google.com> Reviewed-by: Slava Egorov <vegorov@google.com>
63 lines
1.4 KiB
Dart
63 lines
1.4 KiB
Dart
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import "dart:convert";
|
|
import "dart:typed_data";
|
|
|
|
import "package:expect/expect.dart";
|
|
|
|
void main() {
|
|
// "é"
|
|
final bytes = [195, 169];
|
|
|
|
// Same as `bytes` when interpreted as unsigned bytes.
|
|
final negativeBytes = [-61, -87];
|
|
|
|
final decoded = "é";
|
|
|
|
final shouldSucceed = [
|
|
bytes,
|
|
Uint8List.fromList(bytes),
|
|
Uint8List.fromList(negativeBytes),
|
|
];
|
|
|
|
final shouldFail = [
|
|
negativeBytes,
|
|
Int8List.fromList(bytes),
|
|
Int8List.fromList(negativeBytes),
|
|
];
|
|
|
|
for (var bytes in shouldSucceed) {
|
|
Expect.equals(utf8.decoder.convert(bytes), decoded);
|
|
|
|
final stringSink = StringSink();
|
|
utf8.decoder.startChunkedConversion(stringSink)
|
|
..add(bytes)
|
|
..close();
|
|
Expect.equals(stringSink.buffer.toString(), decoded);
|
|
}
|
|
|
|
for (var bytes in shouldFail) {
|
|
Expect.throwsFormatException(() => utf8.decoder.convert(bytes));
|
|
|
|
final stringSink = StringSink();
|
|
Expect.throwsFormatException(
|
|
() => utf8.decoder.startChunkedConversion(stringSink)
|
|
..add(bytes)
|
|
..close());
|
|
}
|
|
}
|
|
|
|
class StringSink implements Sink<String> {
|
|
StringBuffer buffer = StringBuffer();
|
|
|
|
StringSink();
|
|
|
|
void add(String str) {
|
|
buffer.write(str);
|
|
}
|
|
|
|
void close() {}
|
|
}
|