Preserve the function table explicitly (#1970)

The main gc pass of unused items in wasm-bindgen was accidentally
removing the function table because we weren't properly rooting it in
the auxiliary section which has a few ways that imports can reference
the function table via intrinsics and closures.

Closes #1967
This commit is contained in:
Alex Crichton
2020-01-21 13:02:13 -06:00
committed by GitHub
parent bb066e68a5
commit c5c7acc766
5 changed files with 33 additions and 1 deletions

View File

@ -2889,7 +2889,7 @@ impl<'a> Context<'a> {
}
fn export_function_table(&mut self) -> Result<String, Error> {
match self.module.tables.main_function_table()? {
match self.aux.function_table {
Some(id) => Ok(self.export_name_of(id)),
None => bail!("no function table found in module"),
}

View File

@ -164,6 +164,12 @@ impl<'a> Context<'a> {
// access to them while processing programs.
self.descriptors.extend(descriptors);
// If any closures exist we need to prevent the function table from
// getting gc'd
if closure_imports.len() > 0 {
self.aux.function_table = self.module.tables.main_function_table()?;
}
// Register all the injected closure imports as that they're expected
// to manufacture a particular type of closure.
//
@ -310,6 +316,9 @@ impl<'a> Context<'a> {
}
fn bind_intrinsic(&mut self, id: ImportId, intrinsic: Intrinsic) -> Result<(), Error> {
if let Intrinsic::FunctionTable = intrinsic {
self.aux.function_table = self.module.tables.main_function_table()?;
}
let id = self.import_adapter(id, intrinsic.signature(), AdapterJsImportKind::Normal)?;
self.aux
.import_map

View File

@ -50,6 +50,7 @@ pub struct WasmBindgenAux {
/// Information about various internal functions used to manage the `anyref`
/// table, later used to process JS bindings.
pub anyref_table: Option<walrus::TableId>,
pub function_table: Option<walrus::TableId>,
pub anyref_alloc: Option<walrus::FunctionId>,
pub anyref_drop_slice: Option<walrus::FunctionId>,
@ -366,6 +367,9 @@ impl walrus::CustomSection for WasmBindgenAux {
if let Some(id) = self.anyref_table {
roots.push_table(id);
}
if let Some(id) = self.function_table {
roots.push_table(id);
}
if let Some(id) = self.anyref_alloc {
roots.push_func(id);
}

View File

@ -50,6 +50,7 @@ pub fn add(module: &mut Module) -> Result<(), Error> {
anyref_drop_slice: _,
exn_store: _,
shadow_stack_pointer: _,
function_table: _,
} = *aux;
let adapter_context = |id: AdapterId| {