Skip to content

Commit

Permalink
GC: Fix extern and host references
Browse files Browse the repository at this point in the history
  • Loading branch information
osa1 committed Apr 25, 2024
1 parent d4af443 commit 36f547b
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 76 deletions.
24 changes: 19 additions & 5 deletions crates/libwasmrun/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::module::{
use crate::stack::{Block, BlockKind, EndOrBreak, Stack, StackValue};
use crate::store::{Exception, ExnAddr, FunAddr, Global, ModuleAddr, Store, Table};
use crate::type_canonicalizer::TypeCanonicalizer;
use crate::value::{self, ExternKind, Ref, Value};
use crate::value::{self, Ref, Value};
use crate::wasi::allocate_wasi;
use crate::HostFunDecl;
use crate::{ExecError, Result};
Expand Down Expand Up @@ -3788,11 +3788,17 @@ fn exec_instr(rt: &mut Runtime, module_addr: ModuleAddr, instr: Instruction) ->
let ref_ = match ref_ {
Ref::Null(_, _) => Ref::Null(module_addr, wasm::HeapType::Extern),

Ref::BoxedExtern(ext) => Ref::Extern(ext), // any -> extern
Ref::Host {
value,
internal: true,
} => Ref::Host {
value,
internal: false,
},

_ => {
let extern_addr = rt.store.externalize(ref_);
Ref::Extern(ExternKind::Internal(extern_addr))
Ref::Extern(extern_addr)
}
};

Expand All @@ -3810,11 +3816,19 @@ fn exec_instr(rt: &mut Runtime, module_addr: ModuleAddr, instr: Instruction) ->
let ref_ = match ref_ {
Ref::Null(_, _) => Ref::Null(module_addr, wasm::HeapType::Any),

Ref::Extern(ext) => Ref::BoxedExtern(ext), // extern -> any
Ref::Extern(addr) => rt.store.internalize(addr),

Ref::Host {
value,
internal: false,
} => Ref::Host {
value,
internal: true,
},

_ => {
// validation error
exec_panic!("Non-extern reference in any.convert_extern")
exec_panic!("Non-extern reference in any.convert_extern: {:?}", ref_)
}
};

Expand Down
2 changes: 1 addition & 1 deletion crates/libwasmrun/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use libwasmrun_syntax as wasm;
pub use exec::Runtime;
pub use module::MemIdx;
pub use store::{ExternAddr, MemAddr};
pub use value::{ExternKind, Ref, Value};
pub use value::{Ref, Value};
pub use wasi_common::{virtfs, Handle, WasiCtx, WasiCtxBuilder};
pub use wasm::Module;
pub use wasm::ValueType;
Expand Down
42 changes: 22 additions & 20 deletions crates/libwasmrun/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,21 @@ pub enum Ref {
Struct(StructAddr),
Array(ArrayAddr),

/// A host reference, or an externalized internal reference.
/// A host reference.
///
/// Reference type: `extern`.
Extern(ExternKind),
/// When internalized (with `any.convert_extern`), this becomes an `any` that is not `eq`.
Host {
value: u32,
internal: bool,
},

/// Same as `Extern`, but converted to `any`.
///
/// Reference type: `any`.
BoxedExtern(ExternKind),
/// A Wasm heap reference.
Extern(ExternAddr),

/// A 31-bit integer disguised as a pointer.
I31(i32),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ExternKind {
/// An internal reference.
Internal(ExternAddr),

/// A host reference.
Host(u32),
}

impl Ref {
pub fn is_null(&self) -> bool {
matches!(self, Ref::Null(_, _))
Expand Down Expand Up @@ -85,9 +77,16 @@ impl Ref {
tag.rtt()
}

Ref::Extern(_) => (ModuleAddr(0), wasm::HeapType::Extern),
Ref::Host { value: _, internal } => (
ModuleAddr(0),
if *internal {
wasm::HeapType::Any
} else {
wasm::HeapType::Extern
},
),

Ref::BoxedExtern(_) => (ModuleAddr(0), wasm::HeapType::Any),
Ref::Extern { .. } => (ModuleAddr(0), wasm::HeapType::Extern),

Ref::Struct(struct_addr) => store.get_struct(*struct_addr).rtt(),

Expand Down Expand Up @@ -124,8 +123,11 @@ pub(crate) fn canonicalize_f64_nan(f: f64) -> f64 {
}

impl Value {
pub fn new_host_ref(addr: u32) -> Self {
Value::Ref(Ref::Extern(ExternKind::Host(addr)))
pub fn new_host_ref(value: u32) -> Self {
Value::Ref(Ref::Host {
value,
internal: true,
})
}

pub(crate) fn default_from_storage_type(
Expand Down
46 changes: 2 additions & 44 deletions crates/spec-test/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,58 +6,16 @@ use std::path::{Path, PathBuf};
use std::process::exit;

#[rustfmt::skip]
static TEST_FILES: [&str; 45] = [
static TEST_FILES: [&str; 6] = [
"tests/spec",
"tests/spec/proposals/exception-handling",
"tests/spec/proposals/extended-const",
"tests/spec/proposals/function-references",
"tests/spec/proposals/multi-memory",
"tests/spec/proposals/gc",

// Tail call tests take a long time to run, disabled for now
// "tests/spec/proposals/tail-call",

"tests/spec/proposals/gc/array.wast",
"tests/spec/proposals/gc/array_copy.wast",
"tests/spec/proposals/gc/array_fill.wast",
"tests/spec/proposals/gc/array_init_data.wast",
"tests/spec/proposals/gc/array_init_elem.wast",
"tests/spec/proposals/gc/binary-gc.wast",
"tests/spec/proposals/gc/binary.wast",
"tests/spec/proposals/gc/br_on_cast.wast",
"tests/spec/proposals/gc/br_on_cast_fail.wast",
"tests/spec/proposals/gc/br_on_non_null.wast",
"tests/spec/proposals/gc/br_table.wast",
"tests/spec/proposals/gc/call_ref.wast",
"tests/spec/proposals/gc/data.wast",
"tests/spec/proposals/gc/elem.wast",
"tests/spec/proposals/gc/func.wast",
"tests/spec/proposals/gc/global.wast",
"tests/spec/proposals/gc/i31.wast",
"tests/spec/proposals/gc/if.wast",
"tests/spec/proposals/gc/local_get.wast",
"tests/spec/proposals/gc/local_init.wast",
"tests/spec/proposals/gc/ref.wast",
"tests/spec/proposals/gc/ref_as_non_null.wast",
"tests/spec/proposals/gc/ref_cast.wast",
"tests/spec/proposals/gc/ref_eq.wast",
"tests/spec/proposals/gc/ref_is_null.wast",
"tests/spec/proposals/gc/ref_null.wast",
"tests/spec/proposals/gc/ref_test.wast",
"tests/spec/proposals/gc/return_call.wast",
"tests/spec/proposals/gc/return_call_indirect.wast",
"tests/spec/proposals/gc/return_call_ref.wast",
"tests/spec/proposals/gc/select.wast",
"tests/spec/proposals/gc/struct.wast",
"tests/spec/proposals/gc/table-sub.wast",
"tests/spec/proposals/gc/table.wast",
"tests/spec/proposals/gc/type-canon.wast",
"tests/spec/proposals/gc/type-equivalence.wast",
"tests/spec/proposals/gc/type-rec.wast",
"tests/spec/proposals/gc/type-subtyping.wast",
"tests/spec/proposals/gc/unreached-invalid.wast",
"tests/spec/proposals/gc/unreached-valid.wast",

// "tests/spec/proposals/gc/extern.wast",
];

fn main() {
Expand Down
40 changes: 34 additions & 6 deletions crates/spec-test/src/spec.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use libwasmrun::exec::{self, Runtime, Trap};
use libwasmrun::store::ModuleAddr;
use libwasmrun::{ExecError, ExternKind, Ref, Value};
use libwasmrun::{ExecError, Ref, Value};
use libwasmrun_syntax as wasm;

use fxhash::FxHashMap;
Expand Down Expand Up @@ -404,7 +404,16 @@ impl<'a> TestFileRunner<'a> {
},
)),

WastArgCore::RefHost(addr) | WastArgCore::RefExtern(addr) => Value::new_host_ref(*addr),
WastArgCore::RefHost(addr) => Value::Ref(Ref::Host {
value: *addr,
internal: true,
}),

// `ref.extern` = externalized `ref.host`
WastArgCore::RefExtern(addr) => Value::Ref(Ref::Host {
value: *addr,
internal: false,
}),
})
}
}
Expand Down Expand Up @@ -545,12 +554,31 @@ fn test_val(rt: &Runtime, module_addr: ModuleAddr, expected: &WastRetCore, found

(WastRetCore::RefFunc(None), Value::Ref(Ref::Func(_))) => true,

(WastRetCore::RefExtern(None), Value::Ref(Ref::Extern(_))) => true,
(
WastRetCore::RefExtern(None),
Value::Ref(
Ref::Extern(_)
| Ref::Host {
internal: false, ..
},
),
) => true,

(
WastRetCore::RefExtern(Some(ref1)),
Value::Ref(Ref::Host {
value: ref2,
internal: false,
}),
) => ref1 == ref2,

(
WastRetCore::RefExtern(Some(extern1)),
Value::Ref(Ref::Extern(ExternKind::Host(extern2))),
) => *extern1 == *extern2,
WastRetCore::RefHost(ref1),
Value::Ref(Ref::Host {
value: ref2,
internal: true,
}),
) => ref1 == ref2,

(WastRetCore::RefStruct, Value::Ref(Ref::Struct(_))) => true,

Expand Down

0 comments on commit 36f547b

Please sign in to comment.