[dart2wasm] Allocate TextDecoder once when decoding UTF-8 to JSStringImpl

Improves a protobuf decoding benchmark from 348ms to 305ms.

Change-Id: Ib47d4271981c16c196594e435c807fecb8fb02f5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/336020
Reviewed-by: Aske Simon Christensen <askesc@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
This commit is contained in:
Ömer Sinan Ağacan 2023-11-14 11:42:23 +00:00 committed by Commit Queue
parent 1fccfb8be7
commit 932ed2e364
3 changed files with 30 additions and 36 deletions

View file

@ -35,8 +35,9 @@ JSMethods _performJSInteropTransformations(
additionalCoreLibraries: {
'_js_helper',
'_js_types',
'convert',
'js_interop',
'js_interop_unsafe'
'js_interop_unsafe',
});
for (Library library in interopDependentLibraries) {
staticInteropClassEraser.visitLibrary(library);

View file

@ -251,6 +251,8 @@ class WasmTarget extends Target {
component, Uri.parse("dart:_js_annotations")),
...?jsInteropHelper.calculateTransitiveImportsOfJsInteropIfUsed(
component, Uri.parse("dart:js_interop")),
...?jsInteropHelper.calculateTransitiveImportsOfJsInteropIfUsed(
component, Uri.parse("dart:convert")),
};
if (transitiveImportingJSInterop.isEmpty) {
logger?.call("Skipped JS interop transformations");

View file

@ -52,30 +52,19 @@ class Utf8Decoder {
static String? _convertInterceptedUint8List(
bool allowMalformed, JSUint8ArrayImpl codeUnits, int start, int end) {
// TODO(omersa): There's a bug somewhere when compiling lazy statics that
// return `WasmExternRef`?
// final WasmExternRef? decoder = allowMalformed ? _decoderNonfatal : _decoder;
// if (decoder == WasmExternRef.nullRef) {
// return null;
// }
final WasmExternRef? decoder;
try {
decoder = allowMalformed
? js.JS<WasmExternRef?>(
'() => new TextDecoder("utf-8", {fatal: false})')
: js.JS<WasmExternRef?>(
'() => new TextDecoder("utf-8", {fatal: true})');
} catch (e) {
final JSAny? decoder = allowMalformed ? _decoderNonFatal : _decoder;
if (decoder == null) {
return null;
}
if (0 == start && end == codeUnits.length) {
return _useTextDecoder(decoder, codeUnits.toJSArrayExternRef());
return _useTextDecoder(
externRefForJSAny(decoder), codeUnits.toJSArrayExternRef());
}
RangeError.checkValidRange(start, end, codeUnits.length);
final length = end - start;
return _useTextDecoder(
decoder, codeUnits.toJSArrayExternRef(start, length));
return _useTextDecoder(externRefForJSAny(decoder),
codeUnits.toJSArrayExternRef(start, length));
}
static String? _useTextDecoder(
@ -92,26 +81,28 @@ class Utf8Decoder {
return null;
}
// TODO(omersa): These values seem to be miscompiled at the use sites, see
// above.
// TextDecoder is not defined on some browsers and on the stand-alone d8 and
// jsshell engines. Use a lazy initializer to do feature detection once.
//
// // TextDecoder is not defined on some browsers and on the stand-alone d8 and
// // jsshell engines. Use a lazy initializer to do feature detection once.
// static final WasmExternRef? _decoder = () {
// try {
// return js
// .JS<WasmExternRef?>('() => new TextDecoder("utf-8", {fatal: true})');
// } catch (e) {}
// return null;
// }();
// Globls need to return boxed Dart values, so these return `JSAny?` instead
// of `WasmExternRef?`.
static final JSAny? _decoder = () {
try {
return js
.JS<WasmExternRef>('() => new TextDecoder("utf-8", {fatal: true})')
.toJS;
} catch (e) {}
return null;
}();
// static final WasmExternRef? _decoderNonfatal = () {
// try {
// return js
// .JS<WasmExternRef?>('() => new TextDecoder("utf-8", {fatal: false})');
// } catch (e) {}
// return null;
// }();
static final JSAny? _decoderNonFatal = () {
try {
return js
.JS<WasmExternRef>('() => new TextDecoder("utf-8", {fatal: false})')
.toJS;
} catch (e) {}
return null;
}();
}
//// Implementation ///////////////////////////////////////////////////////////