mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-09 19:11:21 +00:00
Communicate exceptions through global memory
Instead of allocating space on the stack and returning a pointer we should be able to use a single global memory location to communicate this error payload information. This shouldn't run into any reentrancy issues since it's only stored just before returning to wasm and it's always read just after returning from wasm.
This commit is contained in:
parent
535aa3193c
commit
6796bc6895
@ -974,28 +974,12 @@ impl TryToTokens for ast::ImportFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut exceptional_ret = quote!();
|
let mut exceptional_ret = quote!();
|
||||||
let exn_data = if self.catch {
|
if self.catch {
|
||||||
let exn_data = Ident::new("exn_data", Span::call_site());
|
|
||||||
let exn_data_ptr = Ident::new("exn_data_ptr", Span::call_site());
|
|
||||||
abi_argument_names.push(exn_data_ptr.clone());
|
|
||||||
abi_arguments.push(quote! { #exn_data_ptr: *mut u32 });
|
|
||||||
convert_ret = quote! { Ok(#convert_ret) };
|
convert_ret = quote! { Ok(#convert_ret) };
|
||||||
exceptional_ret = quote! {
|
exceptional_ret = quote! {
|
||||||
if #exn_data[0] == 1 {
|
wasm_bindgen::__rt::take_last_exception()?;
|
||||||
return Err(
|
|
||||||
<
|
|
||||||
wasm_bindgen::JsValue as wasm_bindgen::convert::FromWasmAbi
|
|
||||||
>::from_abi(#exn_data[1], &mut wasm_bindgen::convert::GlobalStack::new())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
quote! {
|
}
|
||||||
let mut #exn_data = [0; 2];
|
|
||||||
let #exn_data_ptr = #exn_data.as_mut_ptr();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
quote!()
|
|
||||||
};
|
|
||||||
|
|
||||||
let rust_name = &self.rust_name;
|
let rust_name = &self.rust_name;
|
||||||
let import_name = &self.shim;
|
let import_name = &self.shim;
|
||||||
@ -1055,7 +1039,6 @@ impl TryToTokens for ast::ImportFunction {
|
|||||||
#extern_fn
|
#extern_fn
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
#exn_data
|
|
||||||
let #ret_ident = {
|
let #ret_ident = {
|
||||||
let mut __stack = wasm_bindgen::convert::GlobalStack::new();
|
let mut __stack = wasm_bindgen::convert::GlobalStack::new();
|
||||||
#(#arg_conversions)*
|
#(#arg_conversions)*
|
||||||
|
@ -1419,16 +1419,14 @@ impl<'a> Context<'a> {
|
|||||||
if !self.should_write_global("handle_error") {
|
if !self.should_write_global("handle_error") {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
self.expose_uint32_memory();
|
self.require_internal_export("__wbindgen_exn_store")?;
|
||||||
if self.config.anyref {
|
if self.config.anyref {
|
||||||
self.expose_add_to_anyref_table()?;
|
self.expose_add_to_anyref_table()?;
|
||||||
self.global(
|
self.global(
|
||||||
"
|
"
|
||||||
function handleError(exnptr, e) {
|
function handleError(e) {
|
||||||
const idx = addToAnyrefTable(e);
|
const idx = addToAnyrefTable(e);
|
||||||
const view = getUint32Memory();
|
wasm.__wbindgen_exn_store(idx);
|
||||||
view[exnptr / 4] = 1;
|
|
||||||
view[exnptr / 4 + 1] = idx;
|
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
);
|
);
|
||||||
@ -1436,10 +1434,8 @@ impl<'a> Context<'a> {
|
|||||||
self.expose_add_heap_object();
|
self.expose_add_heap_object();
|
||||||
self.global(
|
self.global(
|
||||||
"
|
"
|
||||||
function handleError(exnptr, e) {
|
function handleError(e) {
|
||||||
const view = getUint32Memory();
|
wasm.__wbindgen_exn_store(addHeapObject(e));
|
||||||
view[exnptr / 4] = 1;
|
|
||||||
view[exnptr / 4 + 1] = addHeapObject(e);
|
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
);
|
);
|
||||||
@ -2115,7 +2111,7 @@ impl<'a> Context<'a> {
|
|||||||
|
|
||||||
fn export_function_table(&mut self) -> Result<(), Error> {
|
fn export_function_table(&mut self) -> Result<(), Error> {
|
||||||
if !self.should_write_global("wbg-function-table") {
|
if !self.should_write_global("wbg-function-table") {
|
||||||
return Ok(())
|
return Ok(());
|
||||||
}
|
}
|
||||||
let id = match self.module.tables.main_function_table()? {
|
let id = match self.module.tables.main_function_table()? {
|
||||||
Some(id) => id,
|
Some(id) => id,
|
||||||
@ -2192,7 +2188,7 @@ impl ExportedClass {
|
|||||||
field: &str,
|
field: &str,
|
||||||
js: &str,
|
js: &str,
|
||||||
prefix: &str,
|
prefix: &str,
|
||||||
ret_ty: &str
|
ret_ty: &str,
|
||||||
) -> &mut bool {
|
) -> &mut bool {
|
||||||
self.contents.push_str(docs);
|
self.contents.push_str(docs);
|
||||||
self.contents.push_str(prefix);
|
self.contents.push_str(prefix);
|
||||||
@ -2215,7 +2211,8 @@ impl ExportedClass {
|
|||||||
/// generated output is deterministic and we do so by ensuring that iteration of
|
/// generated output is deterministic and we do so by ensuring that iteration of
|
||||||
/// hash maps is consistently sorted.
|
/// hash maps is consistently sorted.
|
||||||
fn sorted_iter<K, V>(map: &HashMap<K, V>) -> impl Iterator<Item = (&K, &V)>
|
fn sorted_iter<K, V>(map: &HashMap<K, V>) -> impl Iterator<Item = (&K, &V)>
|
||||||
where K: Ord,
|
where
|
||||||
|
K: Ord,
|
||||||
{
|
{
|
||||||
let mut pairs = map.iter().collect::<Vec<_>>();
|
let mut pairs = map.iter().collect::<Vec<_>>();
|
||||||
pairs.sort_by_key(|(k, _)| *k);
|
pairs.sort_by_key(|(k, _)| *k);
|
||||||
|
@ -928,7 +928,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
|||||||
try {{\n\
|
try {{\n\
|
||||||
{}
|
{}
|
||||||
}} catch (e) {{\n\
|
}} catch (e) {{\n\
|
||||||
handleError(exnptr, e);\n\
|
handleError(e);\n\
|
||||||
}}\
|
}}\
|
||||||
",
|
",
|
||||||
&invoc
|
&invoc
|
||||||
@ -973,12 +973,6 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
|||||||
let mut ret = String::new();
|
let mut ret = String::new();
|
||||||
ret.push_str("function(");
|
ret.push_str("function(");
|
||||||
ret.push_str(&self.shim_arguments.join(", "));
|
ret.push_str(&self.shim_arguments.join(", "));
|
||||||
if self.catch {
|
|
||||||
if self.shim_arguments.len() > 0 {
|
|
||||||
ret.push_str(", ")
|
|
||||||
}
|
|
||||||
ret.push_str("exnptr");
|
|
||||||
}
|
|
||||||
ret.push_str(") {\n");
|
ret.push_str(") {\n");
|
||||||
ret.push_str(&self.prelude);
|
ret.push_str(&self.prelude);
|
||||||
|
|
||||||
|
22
src/lib.rs
22
src/lib.rs
@ -1067,6 +1067,28 @@ pub mod __rt {
|
|||||||
pub fn link_mem_intrinsics() {
|
pub fn link_mem_intrinsics() {
|
||||||
crate::anyref::link_intrinsics();
|
crate::anyref::link_intrinsics();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static mut GLOBAL_EXNDATA: [u32; 2] = [0; 2];
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn __wbindgen_exn_store(idx: u32) {
|
||||||
|
assert_eq!(GLOBAL_EXNDATA[0], 0);
|
||||||
|
GLOBAL_EXNDATA[0] = 1;
|
||||||
|
GLOBAL_EXNDATA[1] = idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn take_last_exception() -> Result<(), super::JsValue> {
|
||||||
|
unsafe {
|
||||||
|
let ret = if GLOBAL_EXNDATA[0] == 1 {
|
||||||
|
Err(super::JsValue:: _new(GLOBAL_EXNDATA[1]))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
GLOBAL_EXNDATA[0] = 0;
|
||||||
|
GLOBAL_EXNDATA[1] = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper type around slices and vectors for binding the `Uint8ClampedArray`
|
/// A wrapper type around slices and vectors for binding the `Uint8ClampedArray`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user