From f4ae669cadade57e6415d43a5ef45ab7e5eb11f8 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 24 Nov 2023 12:17:30 +0100 Subject: [PATCH 1/3] style: use find_map() instead of filter_map().next() --- crates/js-component-bindgen/src/transpile_bindgen.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/js-component-bindgen/src/transpile_bindgen.rs b/crates/js-component-bindgen/src/transpile_bindgen.rs index 3ccfd656b..063f99835 100644 --- a/crates/js-component-bindgen/src/transpile_bindgen.rs +++ b/crates/js-component-bindgen/src/transpile_bindgen.rs @@ -549,11 +549,10 @@ impl<'a> Instantiator<'a, '_> { .component .initializers .iter() - .filter_map(|i| match i { + .find_map(|i| match i { GlobalInitializer::Resource(r) if r.index == resource_idx => Some(r), _ => None, }) - .next() .unwrap(); if let Some(dtor) = &resource_def.dtor { @@ -707,11 +706,10 @@ impl<'a> Instantiator<'a, '_> { .component .initializers .iter() - .filter_map(|i| match i { + .find_map(|i| match i { GlobalInitializer::Resource(r) if r.index == resource_idx => Some(r), _ => None, }) - .next() .unwrap(); if let Some(dtor) = &resource_def.dtor { @@ -1054,11 +1052,10 @@ impl<'a> Instantiator<'a, '_> { .component .initializers .iter() - .filter_map(|i| match i { + .find_map(|i| match i { GlobalInitializer::Resource(r) if r.index == resource_idx => Some(r), _ => None, }) - .next() .unwrap(); if let Some(dtor) = &resource_def.dtor { From 53b2ff5e8e69b2ad604da69da99fbdc56538ef45 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 24 Nov 2023 12:45:49 +0100 Subject: [PATCH 2/3] feat: only generate instance flags globals when they're used --- crates/js-component-bindgen/src/source.rs | 17 ++++++++++ .../src/transpile_bindgen.rs | 32 +++++++++++++++---- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/crates/js-component-bindgen/src/source.rs b/crates/js-component-bindgen/src/source.rs index 4bb925286..737b44c42 100644 --- a/crates/js-component-bindgen/src/source.rs +++ b/crates/js-component-bindgen/src/source.rs @@ -39,6 +39,23 @@ impl Source { } } + pub fn prepend_str(&mut self, src: &str) { + // Infer the indent at start: it's the difference between the size of the first line, and + // its size if trimmed at the left. That raw difference is in number of spaces, not in + // units of indent; since each indent is 2 spaces, divide by 2 at the end. + let indent = self + .s + .lines() + .next() + .map_or(0, |line| (line.len() - line.trim_start().len()) / 2); + let mut new_start = Source { + s: String::new(), + indent, + }; + new_start.push_str(src); + self.s = new_start.s + &self.s; + } + pub fn indent(&mut self, amt: usize) { self.indent += amt; } diff --git a/crates/js-component-bindgen/src/transpile_bindgen.rs b/crates/js-component-bindgen/src/transpile_bindgen.rs index 063f99835..05a977727 100644 --- a/crates/js-component-bindgen/src/transpile_bindgen.rs +++ b/crates/js-component-bindgen/src/transpile_bindgen.rs @@ -11,11 +11,13 @@ use crate::{uwrite, uwriteln}; use base64::{engine::general_purpose, Engine as _}; use heck::*; use indexmap::IndexMap; +use std::cell::RefCell; use std::collections::{BTreeMap, BTreeSet, HashMap}; use std::fmt::Write; use std::mem; use wasmtime_environ::component::{ - ComponentTypes, InterfaceType, TypeDef, TypeFuncIndex, TypeResourceTableIndex, + ComponentTypes, InterfaceType, RuntimeComponentInstanceIndex, TypeDef, TypeFuncIndex, + TypeResourceTableIndex, }; use wasmtime_environ::{ component, @@ -141,6 +143,7 @@ pub fn transpile_bindgen( lowering_options: Default::default(), imports_resource_map: Default::default(), exports_resource_map: Default::default(), + used_instance_flags: Default::default(), defined_resource_classes: Default::default(), resource_dtors: Default::default(), resource_tables_initialized: (0..component.component.num_resource_tables) @@ -152,6 +155,7 @@ pub fn transpile_bindgen( instantiator.instantiate(); instantiator.ensure_resource_tables(); instantiator.destructors(); + instantiator.ensure_instance_flags(); instantiator.gen.src.js(&instantiator.src.js); instantiator.gen.src.js_init(&instantiator.src.js_init); @@ -353,6 +357,8 @@ struct Instantiator<'a, 'b> { imports: BTreeMap, imports_resource_map: ResourceMap, exports_resource_map: ResourceMap, + /// Instance flags which references have been emitted externally at least once. + used_instance_flags: RefCell>, defined_resource_classes: BTreeSet, resource_dtors: BTreeMap, lowering_options: @@ -475,10 +481,6 @@ impl<'a> Instantiator<'a, '_> { } fn instantiate(&mut self) { - for i in 0..self.component.num_runtime_component_instances { - uwriteln!(self.src.js_init, "const instanceFlags{i} = new WebAssembly.Global({{ value: \"i32\", mutable: true }}, {});", wasmtime_environ::component::FLAG_MAY_LEAVE | wasmtime_environ::component::FLAG_MAY_ENTER); - } - for (i, trampoline) in self.translation.trampolines.iter() { let Trampoline::LowerImport { index, @@ -598,6 +600,20 @@ impl<'a> Instantiator<'a, '_> { } } + fn ensure_instance_flags(&mut self) { + // SAFETY: short-lived borrow, and the refcell isn't mutably borrowed in the loop's body. + let mut instance_flag_defs = String::new(); + for used in self.used_instance_flags.borrow().iter() { + let i = used.as_u32(); + uwriteln!( + &mut instance_flag_defs, + "const instanceFlags{i} = new WebAssembly.Global({{ value: \"i32\", mutable: true }}, {});", + wasmtime_environ::component::FLAG_MAY_LEAVE + | wasmtime_environ::component::FLAG_MAY_ENTER); + } + self.src.js_init.prepend_str(&instance_flag_defs); + } + fn destructors(&mut self) { for (ty, dtor) in self.resource_dtors.iter() { let dtor_name_str = self.core_def(dtor); @@ -1432,7 +1448,11 @@ impl<'a> Instantiator<'a, '_> { match def { CoreDef::Export(e) => self.core_export(e), CoreDef::Trampoline(i) => format!("trampoline{}", i.as_u32()), - CoreDef::InstanceFlags(i) => format!("instanceFlags{}", i.as_u32()), + CoreDef::InstanceFlags(i) => { + // SAFETY: short-lived borrow-mut. + self.used_instance_flags.borrow_mut().insert(*i); + format!("instanceFlags{}", i.as_u32()) + } } } From ce4ef6a0d08f78a8b1490a0e538fd1f68e8a38ed Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Mon, 27 Nov 2023 12:05:59 +0100 Subject: [PATCH 3/3] review: rename ensure_instance_flags to instance_flags --- crates/js-component-bindgen/src/transpile_bindgen.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/js-component-bindgen/src/transpile_bindgen.rs b/crates/js-component-bindgen/src/transpile_bindgen.rs index 05a977727..96b0c46ff 100644 --- a/crates/js-component-bindgen/src/transpile_bindgen.rs +++ b/crates/js-component-bindgen/src/transpile_bindgen.rs @@ -155,7 +155,7 @@ pub fn transpile_bindgen( instantiator.instantiate(); instantiator.ensure_resource_tables(); instantiator.destructors(); - instantiator.ensure_instance_flags(); + instantiator.instance_flags(); instantiator.gen.src.js(&instantiator.src.js); instantiator.gen.src.js_init(&instantiator.src.js_init); @@ -600,7 +600,7 @@ impl<'a> Instantiator<'a, '_> { } } - fn ensure_instance_flags(&mut self) { + fn instance_flags(&mut self) { // SAFETY: short-lived borrow, and the refcell isn't mutably borrowed in the loop's body. let mut instance_flag_defs = String::new(); for used in self.used_instance_flags.borrow().iter() {