From 7983454299a3e2ee89fd5e3ae20f4a389d39a4b1 Mon Sep 17 00:00:00 2001 From: Stephen Adams Date: Thu, 18 May 2017 14:16:40 -0700 Subject: [PATCH] js_runtime: loadDeferredLibrary: don't call initializer of repeated empty parts Pre-filtering hunks to initialized ended up calling some initializations multiple times. This happened for empty parts, so was harmless after https://github.com/dart-lang/sdk/commit/4af03b1a658675c8490e8c4c3721e6a2991c17e9 Simplify logic to reduce use of corelib functions. There is no real need to be creating closures and calling all of List.generate, where, and map. BUG= R=sigmund@google.com Review-Url: https://codereview.chromium.org/2893653005 . --- .../_internal/js_runtime/lib/js_helper.dart | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart index fc1987ad7e4..f44f922f496 100644 --- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart +++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart @@ -3653,27 +3653,32 @@ Future loadDeferredLibrary(String loadId) { // list of hashes. These are stored in the app-global scope. var urisMap = JS_EMBEDDED_GLOBAL('', DEFERRED_LIBRARY_URIS); List uris = JS('JSExtendableArray|Null', '#[#]', urisMap, loadId); + if (uris == null) return new Future.value(null); + var hashesMap = JS_EMBEDDED_GLOBAL('', DEFERRED_LIBRARY_HASHES); List hashes = JS('JSExtendableArray|Null', '#[#]', hashesMap, loadId); - if (uris == null) return new Future.value(null); - // The indices into `uris` and `hashes` that we want to load. - List indices = new List.generate(uris.length, (i) => i); + + List urisToLoad = []; + var isHunkLoaded = JS_EMBEDDED_GLOBAL('', IS_HUNK_LOADED); - var isHunkInitialized = JS_EMBEDDED_GLOBAL('', IS_HUNK_INITIALIZED); - // Filter away indices for hunks that have already been loaded. - List indicesToLoad = indices - .where((int i) => !JS('bool', '#(#)', isHunkLoaded, hashes[i])) - .toList(); - return Future - .wait(indicesToLoad.map((int i) => _loadHunk(uris[i]))) - .then((_) { + for (int i = 0; i < uris.length; ++i) { + if (JS('bool', '#(#)', isHunkLoaded, hashes[i])) continue; + urisToLoad.add(uris[i]); + } + + return Future.wait(urisToLoad.map(_loadHunk)).then((_) { // Now all hunks have been loaded, we run the needed initializers. - List indicesToInitialize = indices - .where((int i) => !JS('bool', '#(#)', isHunkInitialized, hashes[i])) - .toList(); // Load the needed hunks. - for (int i in indicesToInitialize) { - var initializer = JS_EMBEDDED_GLOBAL('', INITIALIZE_LOADED_HUNK); - JS('void', '#(#)', initializer, hashes[i]); + var isHunkInitialized = JS_EMBEDDED_GLOBAL('', IS_HUNK_INITIALIZED); + var initializer = JS_EMBEDDED_GLOBAL('', INITIALIZE_LOADED_HUNK); + for (String hash in hashes) { + // It is possible for a hash to be repeated. This happens when two + // different parts both end up empty. Checking in the loop rather than + // pre-filtering prevents duplicate hashes leading to duplicated + // initializations. + // TODO(29572): Merge small parts. + // TODO(29635): Remove duplicate parts from tables and output files. + if (JS('bool', '#(#)', isHunkInitialized, hash)) continue; + JS('void', '#(#)', initializer, hash); } bool updated = _loadedLibraries.add(loadId); if (updated && deferredLoadHook != null) {