Skip to content

Commit 117fce1

Browse files
authored
Merge pull request #1692 from alexcrichton/fix-anyref-bugs
Fix a number of `anyref` related bugs in our passes
2 parents 36db788 + adde6c2 commit 117fce1

File tree

6 files changed

+80
-64
lines changed

6 files changed

+80
-64
lines changed

crates/anyref-xform/src/lib.rs

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,6 @@ impl Transform<'_> {
254254
// functions and make sure everything is still hooked up right.
255255
self.rewrite_calls(module);
256256

257-
// Inject initialization routine to set up default slots in the table
258-
// (things like null/undefined/true/false)
259-
self.inject_initialization(module);
260-
261257
Ok(())
262258
}
263259

@@ -514,14 +510,14 @@ impl Transform<'_> {
514510
// Store an anyref at an offset from our function's stack
515511
// pointer frame.
516512
let get_fp = builder.local_get(fp);
517-
next_stack_offset += 1;
518-
let (index, idx_local) = if next_stack_offset == 1 {
513+
let (index, idx_local) = if next_stack_offset == 0 {
519514
(get_fp, fp)
520515
} else {
521516
let rhs = builder.i32_const(next_stack_offset);
522517
let add = builder.binop(BinaryOp::I32Add, get_fp, rhs);
523518
(builder.local_tee(scratch_i32, add), scratch_i32)
524519
};
520+
next_stack_offset += 1;
525521
let store = builder.table_set(self.table, index, local);
526522
let get = builder.local_get(idx_local);
527523
builder.with_side_effects(vec![store], get, Vec::new())
@@ -669,31 +665,4 @@ impl Transform<'_> {
669665
}
670666
}
671667
}
672-
673-
// Ensure that the `start` function for this module calls the
674-
// `__wbindgen_init_anyref_table` function. This'll ensure that all
675-
// instances of this module have the initial slots of the anyref table
676-
// initialized correctly.
677-
fn inject_initialization(&mut self, module: &mut Module) {
678-
let ty = module.types.add(&[], &[]);
679-
let (import, _) = module.add_import_func(
680-
"__wbindgen_placeholder__",
681-
"__wbindgen_init_anyref_table",
682-
ty,
683-
);
684-
685-
let prev_start = match module.start {
686-
Some(f) => f,
687-
None => {
688-
module.start = Some(import);
689-
return;
690-
}
691-
};
692-
693-
let mut builder = walrus::FunctionBuilder::new();
694-
let call_init = builder.call(import, Box::new([]));
695-
let call_prev = builder.call(prev_start, Box::new([]));
696-
let new_start = builder.finish(ty, Vec::new(), vec![call_init, call_prev], module);
697-
module.start = Some(new_start);
698-
}
699668
}

crates/cli-support/src/intrinsic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ intrinsics! {
145145
#[symbol = "__wbindgen_anyref_heap_live_count"]
146146
#[signature = fn() -> I32]
147147
AnyrefHeapLiveCount,
148-
#[symbol = "__wbindgen_init_nyref_table"]
148+
#[symbol = "__wbindgen_init_anyref_table"]
149149
#[signature = fn() -> Unit]
150150
InitAnyrefTable,
151151
}

crates/cli-support/src/js/mod.rs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,7 @@ impl<'a> Context<'a> {
194194
// up we always remove the `start` function if one is present. The JS
195195
// bindings glue then manually calls the start function (if it was
196196
// previously present).
197-
let mut needs_manual_start = false;
198-
if self.config.emit_start {
199-
needs_manual_start = self.unstart_start_function();
200-
}
197+
let needs_manual_start = self.unstart_start_function();
201198

202199
// After all we've done, especially
203200
// `unexport_unused_internal_exports()`, we probably have a bunch of
@@ -517,7 +514,10 @@ impl<'a> Context<'a> {
517514
for (i, extra) in extra_modules.iter().enumerate() {
518515
let imports = match &mut imports {
519516
Some(list) => list,
520-
None => bail!("cannot import from modules (`{}`) with `--no-modules`", extra),
517+
None => bail!(
518+
"cannot import from modules (`{}`) with `--no-modules`",
519+
extra
520+
),
521521
};
522522
imports.push_str(&format!("import * as __wbg_star{} from '{}';\n", i, extra));
523523
imports_init.push_str(&format!("imports['{}'] = __wbg_star{};\n", extra, i));
@@ -2641,16 +2641,23 @@ impl<'a> Context<'a> {
26412641

26422642
Intrinsic::InitAnyrefTable => {
26432643
self.expose_anyref_table();
2644-
String::from(
2644+
2645+
// Grow the table to insert our initial values, and then also
2646+
// set the 0th slot to `undefined` since that's what we've
2647+
// historically used for our ABI which is that the index of 0
2648+
// returns `undefined` for types like `None` going out.
2649+
let mut base = format!(
26452650
"
26462651
const table = wasm.__wbg_anyref_table;
2647-
const offset = table.grow(4);
2648-
table.set(offset + 0, undefined);
2649-
table.set(offset + 1, null);
2650-
table.set(offset + 2, true);
2651-
table.set(offset + 3, false);
2652+
const offset = table.grow({});
2653+
table.set(0, undefined);
26522654
",
2653-
)
2655+
INITIAL_HEAP_VALUES.len(),
2656+
);
2657+
for (i, value) in INITIAL_HEAP_VALUES.iter().enumerate() {
2658+
base.push_str(&format!("table.set(offset + {}, {});\n", i, value));
2659+
}
2660+
base
26542661
}
26552662
};
26562663
Ok(expr)

crates/cli-support/src/lib.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ impl Bindgen {
313313
// the webidl bindings proposal) as well as an auxiliary section for all
314314
// sorts of miscellaneous information and features #[wasm_bindgen]
315315
// supports that aren't covered by WebIDL bindings.
316-
webidl::process(&mut module)?;
316+
webidl::process(&mut module, self.anyref, self.emit_start)?;
317317

318318
// Now that we've got type information from the webidl processing pass,
319319
// touch up the output of rustc to insert anyref shims where necessary.
@@ -324,12 +324,6 @@ impl Bindgen {
324324
anyref::process(&mut module)?;
325325
}
326326

327-
// If we're in a testing mode then remove the start function since we
328-
// shouldn't execute it.
329-
if !self.emit_start {
330-
module.start = None;
331-
}
332-
333327
let aux = module
334328
.customs
335329
.delete_typed::<webidl::WasmBindgenAux>()

crates/cli-support/src/webidl/mod.rs

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -473,10 +473,14 @@ struct Context<'a> {
473473
vendor_prefixes: HashMap<String, Vec<String>>,
474474
unique_crate_identifier: &'a str,
475475
descriptors: HashMap<String, Descriptor>,
476+
anyref_enabled: bool,
477+
support_start: bool,
476478
}
477479

478480
pub fn process(
479481
module: &mut Module,
482+
anyref_enabled: bool,
483+
support_start: bool,
480484
) -> Result<(NonstandardWebidlSectionId, WasmBindgenAuxId), Error> {
481485
let mut storage = Vec::new();
482486
let programs = extract_programs(module, &mut storage)?;
@@ -491,6 +495,8 @@ pub fn process(
491495
unique_crate_identifier: "",
492496
module,
493497
start_found: false,
498+
anyref_enabled,
499+
support_start,
494500
};
495501
cx.init()?;
496502

@@ -532,18 +538,11 @@ impl<'a> Context<'a> {
532538
}
533539
}
534540
for (id, intrinsic) in intrinsics {
535-
bindings::register_import(
536-
self.module,
537-
&mut self.bindings,
538-
id,
539-
intrinsic.binding(),
540-
ast::WebidlFunctionKind::Static,
541-
)?;
542-
self.aux
543-
.import_map
544-
.insert(id, AuxImport::Intrinsic(intrinsic));
541+
self.bind_intrinsic(id, intrinsic)?;
545542
}
546543

544+
self.inject_anyref_initialization()?;
545+
547546
if let Some(custom) = self
548547
.module
549548
.customs
@@ -612,6 +611,48 @@ impl<'a> Context<'a> {
612611
Ok(())
613612
}
614613

614+
// Ensure that the `start` function for this module calls the
615+
// `__wbindgen_init_anyref_table` function. This'll ensure that all
616+
// instances of this module have the initial slots of the anyref table
617+
// initialized correctly.
618+
fn inject_anyref_initialization(&mut self) -> Result<(), Error> {
619+
if !self.anyref_enabled {
620+
return Ok(());
621+
}
622+
let ty = self.module.types.add(&[], &[]);
623+
let (import, import_id) = self.module.add_import_func(
624+
PLACEHOLDER_MODULE,
625+
"__wbindgen_init_anyref_table",
626+
ty,
627+
);
628+
629+
self.module.start = Some(match self.module.start {
630+
Some(prev_start) => {
631+
let mut builder = walrus::FunctionBuilder::new();
632+
let call_init = builder.call(import, Box::new([]));
633+
let call_prev = builder.call(prev_start, Box::new([]));
634+
builder.finish(ty, Vec::new(), vec![call_init, call_prev], self.module)
635+
}
636+
None => import,
637+
});
638+
self.bind_intrinsic(import_id, Intrinsic::InitAnyrefTable)?;
639+
Ok(())
640+
}
641+
642+
fn bind_intrinsic(&mut self, id: ImportId, intrinsic: Intrinsic) -> Result<(), Error> {
643+
bindings::register_import(
644+
self.module,
645+
&mut self.bindings,
646+
id,
647+
intrinsic.binding(),
648+
ast::WebidlFunctionKind::Static,
649+
)?;
650+
self.aux
651+
.import_map
652+
.insert(id, AuxImport::Intrinsic(intrinsic));
653+
Ok(())
654+
}
655+
615656
fn program(&mut self, program: decode::Program<'a>) -> Result<(), Error> {
616657
self.unique_crate_identifier = program.unique_crate_identifier;
617658
let decode::Program {
@@ -752,6 +793,11 @@ impl<'a> Context<'a> {
752793
}
753794
self.start_found = true;
754795

796+
// Skip this when we're generating tests
797+
if !self.support_start {
798+
return Ok(());
799+
}
800+
755801
let prev_start = match self.module.start {
756802
Some(f) => f,
757803
None => {

src/anyref.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ impl Slab {
3939
internal_error("table grow failure")
4040
}
4141
if self.base == 0 {
42-
self.base = r as usize + (super::JSIDX_RESERVED as usize);
42+
self.base = r as usize;
4343
} else if self.base + self.data.len() != r as usize {
4444
internal_error("someone else allocated table entires?")
4545
}

0 commit comments

Comments
 (0)