[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: { additionalCoreLibraries: {
'_js_helper', '_js_helper',
'_js_types', '_js_types',
'convert',
'js_interop', 'js_interop',
'js_interop_unsafe' 'js_interop_unsafe',
}); });
for (Library library in interopDependentLibraries) { for (Library library in interopDependentLibraries) {
staticInteropClassEraser.visitLibrary(library); staticInteropClassEraser.visitLibrary(library);

View file

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

View file

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