From 932ed2e364276e97f48acb6abfe9341be885ccc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Tue, 14 Nov 2023 11:42:23 +0000 Subject: [PATCH] [dart2wasm] Allocate TextDecoder once when decoding UTF-8 to JSStringImpl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Commit-Queue: Ömer Ağacan --- pkg/dart2wasm/lib/js/runtime_generator.dart | 3 +- pkg/dart2wasm/lib/target.dart | 2 + .../lib/convert_patch.dart | 61 ++++++++----------- 3 files changed, 30 insertions(+), 36 deletions(-) diff --git a/pkg/dart2wasm/lib/js/runtime_generator.dart b/pkg/dart2wasm/lib/js/runtime_generator.dart index 343d3f67129..d6708e28830 100644 --- a/pkg/dart2wasm/lib/js/runtime_generator.dart +++ b/pkg/dart2wasm/lib/js/runtime_generator.dart @@ -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); diff --git a/pkg/dart2wasm/lib/target.dart b/pkg/dart2wasm/lib/target.dart index ff4aec70d1e..d845d0ff36b 100644 --- a/pkg/dart2wasm/lib/target.dart +++ b/pkg/dart2wasm/lib/target.dart @@ -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"); diff --git a/sdk/lib/_internal/wasm_js_compatibility/lib/convert_patch.dart b/sdk/lib/_internal/wasm_js_compatibility/lib/convert_patch.dart index f4fd5876bec..6147ae0fb25 100644 --- a/sdk/lib/_internal/wasm_js_compatibility/lib/convert_patch.dart +++ b/sdk/lib/_internal/wasm_js_compatibility/lib/convert_patch.dart @@ -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( - '() => new TextDecoder("utf-8", {fatal: false})') - : js.JS( - '() => 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('() => 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('() => new TextDecoder("utf-8", {fatal: true})') + .toJS; + } catch (e) {} + return null; + }(); - // static final WasmExternRef? _decoderNonfatal = () { - // try { - // return js - // .JS('() => new TextDecoder("utf-8", {fatal: false})'); - // } catch (e) {} - // return null; - // }(); + static final JSAny? _decoderNonFatal = () { + try { + return js + .JS('() => new TextDecoder("utf-8", {fatal: false})') + .toJS; + } catch (e) {} + return null; + }(); } //// Implementation ///////////////////////////////////////////////////////////