Major fixes for WebAssembly
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
0961b199ff
commit
703fd2c147
|
@ -1,3 +1,4 @@
|
|||
/target
|
||||
Cargo.lock
|
||||
.idea/
|
||||
.idea/
|
||||
types.toml
|
|
@ -505,7 +505,7 @@ impl<'own, 'library> Pokemon<'own, 'library> {
|
|||
.set(ability_script)
|
||||
.as_ref()
|
||||
// Ensure the ability script gets initialized with the parameters for the ability.
|
||||
.on_initialize(self.active_ability().parameters())
|
||||
.on_initialize(self.library, self.active_ability().parameters())
|
||||
} else {
|
||||
self.ability_script.clear();
|
||||
}
|
||||
|
|
|
@ -225,6 +225,7 @@ mod tests {
|
|||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
|
||||
use crate::dynamic_data::script_handling::script::ScriptContainer;
|
||||
use crate::dynamic_data::DynamicLibrary;
|
||||
use crate::static_data::EffectParameter;
|
||||
use crate::StringKey;
|
||||
|
||||
|
@ -273,7 +274,7 @@ mod tests {
|
|||
|
||||
fn remove_suppression(&self) {}
|
||||
|
||||
fn on_initialize(&self, _pars: &[EffectParameter]) {
|
||||
fn stack(&self) {
|
||||
self.test_count.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
|
@ -292,7 +293,7 @@ mod tests {
|
|||
let scripts = vec![ScriptWrapper::from(&script)];
|
||||
let mut aggregator = ScriptIterator::new(&scripts as *const Vec<ScriptWrapper>);
|
||||
while let Some(v) = aggregator.get_next() {
|
||||
v.get().unwrap().read().as_ref().unwrap().on_initialize(&[]);
|
||||
v.get().unwrap().read().as_ref().unwrap().stack();
|
||||
}
|
||||
let a = script.get_as::<TestScript>();
|
||||
assert_eq!(a.test_count.load(Ordering::Relaxed), 1);
|
||||
|
@ -306,7 +307,7 @@ mod tests {
|
|||
for i in 1..11 {
|
||||
aggregator.reset();
|
||||
while let Some(v) = aggregator.get_next() {
|
||||
v.get().unwrap().read().as_ref().unwrap().on_initialize(&[]);
|
||||
v.get().unwrap().read().as_ref().unwrap().stack();
|
||||
}
|
||||
let a = script.get_as::<TestScript>();
|
||||
assert_eq!(a.test_count.load(Ordering::Relaxed), i);
|
||||
|
@ -325,7 +326,7 @@ mod tests {
|
|||
];
|
||||
let mut aggregator = ScriptIterator::new(&scripts as *const Vec<ScriptWrapper>);
|
||||
while let Some(v) = aggregator.get_next() {
|
||||
v.get().unwrap().read().as_ref().unwrap().on_initialize(&[]);
|
||||
v.get().unwrap().read().as_ref().unwrap().stack();
|
||||
}
|
||||
let a = script1.get_as::<TestScript>();
|
||||
assert_eq!(a.test_count.load(Ordering::Relaxed), 1);
|
||||
|
@ -349,7 +350,7 @@ mod tests {
|
|||
for i in 1..11 {
|
||||
aggregator.reset();
|
||||
while let Some(v) = aggregator.get_next() {
|
||||
v.get().unwrap().read().as_ref().unwrap().on_initialize(&[]);
|
||||
v.get().unwrap().read().as_ref().unwrap().stack();
|
||||
}
|
||||
let a = script1.get_as::<TestScript>();
|
||||
assert_eq!(a.test_count.load(Ordering::Relaxed), i);
|
||||
|
@ -372,7 +373,7 @@ mod tests {
|
|||
for i in 1..11 {
|
||||
aggregator.reset();
|
||||
while let Some(v) = aggregator.get_next() {
|
||||
v.get().unwrap().read().as_ref().unwrap().on_initialize(&[]);
|
||||
v.get().unwrap().read().as_ref().unwrap().stack();
|
||||
}
|
||||
let s = set.at(0);
|
||||
let s = s.get_as::<TestScript>();
|
||||
|
|
|
@ -8,10 +8,10 @@ use std::thread::JoinHandle;
|
|||
use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard};
|
||||
|
||||
use crate::dynamic_data::choices::{MoveChoice, TurnChoice};
|
||||
use crate::dynamic_data::Battle;
|
||||
use crate::dynamic_data::DamageSource;
|
||||
use crate::dynamic_data::ExecutingMove;
|
||||
use crate::dynamic_data::Pokemon;
|
||||
use crate::dynamic_data::{Battle, DynamicLibrary};
|
||||
use crate::static_data::{EffectParameter, TypeIdentifier};
|
||||
use crate::static_data::{Item, Statistic};
|
||||
use crate::StringKey;
|
||||
|
@ -64,7 +64,7 @@ pub trait Script: Send + Sync {
|
|||
/// This function is ran when this script stops being in effect, and is removed from its owner.
|
||||
fn on_remove(&self) {}
|
||||
/// This function is ran when this script starts being in effect.
|
||||
fn on_initialize(&self, _pars: &[EffectParameter]) {}
|
||||
fn on_initialize(&self, _library: &DynamicLibrary, _pars: &[EffectParameter]) {}
|
||||
/// This function is ran just before the start of the turn. Everyone has made its choices here,
|
||||
/// and the turn is about to start. This is a great place to initialize data if you need to know
|
||||
/// something has happened during a turn.
|
||||
|
@ -423,7 +423,7 @@ mod tests {
|
|||
&self.suppressed_count
|
||||
}
|
||||
|
||||
fn on_initialize(&self, _pars: &[EffectParameter]) {
|
||||
fn stack(&self) {
|
||||
unsafe { self.container.load(Ordering::Relaxed).as_ref().unwrap().clear() }
|
||||
}
|
||||
|
||||
|
@ -451,7 +451,7 @@ mod tests {
|
|||
drop(w);
|
||||
// Initialize with the script being taken as read lock. This prevents the script from actually
|
||||
// removing itself, as it's still doing things.
|
||||
container.script.read().as_ref().unwrap().on_initialize(&[]);
|
||||
container.script.read().as_ref().unwrap().stack();
|
||||
// If we now try and get the script, it will be none the first time. This has the side effect
|
||||
// of actually disposing of the script.
|
||||
assert!(container.get().is_none());
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use core::ffi::c_char;
|
||||
use std::ffi::CString;
|
||||
use std::mem::align_of;
|
||||
use std::mem::{align_of, forget};
|
||||
|
||||
use wasmer::{Exports, Function, Store};
|
||||
|
||||
|
@ -10,6 +9,7 @@ use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
|
|||
use crate::static_data::{DataLibrary, MoveData, MoveLibrary, StaticData};
|
||||
use crate::StringKey;
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! register_func {
|
||||
($exports: ident, $store: ident, $func: ident) => {
|
||||
$exports.insert(stringify!($func), Function::new_native($store, $func));
|
||||
|
@ -39,19 +39,22 @@ pub(crate) fn register_webassembly_funcs(exports: &mut Exports, store: &Store, e
|
|||
|
||||
fn _print(env: &WebAssemblyEnv, p: u32, len: u32) {
|
||||
unsafe {
|
||||
let mem: *mut u8 = env.resolver().memory().data_ptr().offset(p as isize);
|
||||
let mem: *mut u8 = env.data().memory().data_ptr().offset(p as isize);
|
||||
let s = String::from_raw_parts(mem, len as usize, len as usize);
|
||||
println!("{}", s);
|
||||
forget(s);
|
||||
}
|
||||
}
|
||||
|
||||
fn _error(env: &WebAssemblyEnv, message: u32, message_len: u32, file: u32, file_len: u32, line: u32, position: u32) {
|
||||
unsafe {
|
||||
let mem: *mut u8 = env.resolver().memory().data_ptr().offset(message as isize);
|
||||
let mem: *mut u8 = env.data().memory().data_ptr().offset(message as isize);
|
||||
let message = String::from_raw_parts(mem, message_len as usize, message_len as usize);
|
||||
let mem: *mut u8 = env.resolver().memory().data_ptr().offset(file as isize);
|
||||
let mem: *mut u8 = env.data().memory().data_ptr().offset(file as isize);
|
||||
let file = String::from_raw_parts(mem, file_len as usize, file_len as usize);
|
||||
println!("Error: {} in file {}, line: {}:{}", message, file, line, position);
|
||||
forget(message);
|
||||
forget(file);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +62,7 @@ fn move_library_get_move_by_hash(env: &WebAssemblyEnv, lib: ExternRef<MoveLibrar
|
|||
let lib = lib.value(env).unwrap();
|
||||
let m = lib.get_by_hash(hash);
|
||||
if let Some(v) = m {
|
||||
ExternRef::new(env, v)
|
||||
ExternRef::new(env.data().as_ref(), v)
|
||||
} else {
|
||||
ExternRef::null()
|
||||
}
|
||||
|
@ -67,7 +70,7 @@ fn move_library_get_move_by_hash(env: &WebAssemblyEnv, lib: ExternRef<MoveLibrar
|
|||
|
||||
fn move_data_get_name(env: &WebAssemblyEnv, move_data: ExternRef<MoveData>) -> ExternRef<StringKey> {
|
||||
let move_data = move_data.value(env).unwrap();
|
||||
ExternRef::new(env, move_data.name())
|
||||
ExternRef::new(env.data().as_ref(), move_data.name())
|
||||
}
|
||||
|
||||
fn move_data_get_base_power(env: &WebAssemblyEnv, move_data: ExternRef<MoveData>) -> u8 {
|
||||
|
@ -80,12 +83,15 @@ fn const_string_get_hash(env: &WebAssemblyEnv, string_key: ExternRef<StringKey>)
|
|||
|
||||
fn const_string_get_str(env: &WebAssemblyEnv, string_key: ExternRef<StringKey>) -> u32 {
|
||||
let string_key = string_key.value(env).unwrap().str();
|
||||
let s: CString = CString::new(string_key.as_bytes()).unwrap();
|
||||
let wasm_string_ptr = env
|
||||
.resolver()
|
||||
.allocate_mem(string_key.len() as u32, align_of::<CString>() as u32);
|
||||
let mut wasm_string = unsafe { CString::from_raw(wasm_string_ptr.0 as *mut c_char) };
|
||||
s.clone_into(&mut wasm_string);
|
||||
.data()
|
||||
.allocate_mem((string_key.len() + 1) as u32, align_of::<CString>() as u32);
|
||||
let mut wasm_string: Vec<u8> =
|
||||
unsafe { Vec::from_raw_parts(wasm_string_ptr.0, string_key.len() + 1, string_key.len() + 1) };
|
||||
wasm_string.resize(string_key.len() + 1, 0);
|
||||
string_key.as_bytes().clone_into(&mut wasm_string);
|
||||
wasm_string.insert(string_key.len(), 0 as u8);
|
||||
forget(wasm_string);
|
||||
wasm_string_ptr.1
|
||||
}
|
||||
|
||||
|
@ -93,9 +99,9 @@ fn battle_library_get_data_library(
|
|||
env: &WebAssemblyEnv,
|
||||
dynamic_lib: ExternRef<DynamicLibrary>,
|
||||
) -> ExternRef<StaticData> {
|
||||
ExternRef::new(env, dynamic_lib.value(env).unwrap().static_data())
|
||||
ExternRef::new(env.data().as_ref(), dynamic_lib.value(env).unwrap().static_data())
|
||||
}
|
||||
|
||||
fn data_library_get_move_library(env: &WebAssemblyEnv, data_library: ExternRef<StaticData>) -> ExternRef<MoveLibrary> {
|
||||
ExternRef::new(env, data_library.value(env).unwrap().moves())
|
||||
ExternRef::new(env.data().as_ref(), data_library.value(env).unwrap().moves())
|
||||
}
|
||||
|
|
|
@ -3,17 +3,19 @@ use std::marker::PhantomData;
|
|||
use unique_type_id::UniqueTypeId;
|
||||
use wasmer::FromToNativeWasmType;
|
||||
|
||||
use crate::script_implementations::wasm::script_resolver::{WebAssemblyEnv, WebAssemblyScriptResolver};
|
||||
use crate::script_implementations::wasm::script_resolver::{
|
||||
WebAssemblyEnv, WebAssemblyEnvironmentData, WebAssemblyScriptResolver,
|
||||
};
|
||||
|
||||
pub(crate) struct ExternRef<T: UniqueTypeId<u64>> {
|
||||
pub(crate) struct ExternRef<T: UniqueTypeId<u64> + ?Sized> {
|
||||
index: u32,
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: UniqueTypeId<u64>> ExternRef<T> {
|
||||
pub fn new(env: &WebAssemblyEnv, value: &T) -> Self {
|
||||
pub fn new(env: &WebAssemblyEnvironmentData, value: &T) -> Self {
|
||||
Self {
|
||||
index: env.resolver().get_extern_ref_index(value),
|
||||
index: env.get_extern_ref_index(value),
|
||||
_phantom: Default::default(),
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +39,7 @@ impl<T: UniqueTypeId<u64>> ExternRef<T> {
|
|||
/// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the
|
||||
/// value when it was passed before. If these types do not match, this will panic.
|
||||
pub fn value<'a, 'b>(&'a self, env: &'b WebAssemblyEnv) -> Option<&'b T> {
|
||||
let ptr = env.resolver().get_extern_ref_value(self.index) as *const T;
|
||||
let ptr = env.data().get_extern_ref_value(self.index) as *const T;
|
||||
unsafe { ptr.as_ref() }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
use std::any::Any;
|
||||
use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize};
|
||||
use std::sync::Weak;
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use wasmer::NativeFunc;
|
||||
|
||||
use crate::dynamic_data::Script;
|
||||
use crate::script_implementations::wasm::script_resolver::WebAssemblyScriptResolver;
|
||||
use crate::dynamic_data::{DynamicLibrary, Script};
|
||||
use crate::script_implementations::wasm::extern_ref::ExternRef;
|
||||
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnvironmentData;
|
||||
use crate::script_implementations::wasm::WebAssemblyScriptCapabilities;
|
||||
use crate::static_data::EffectParameter;
|
||||
use crate::StringKey;
|
||||
|
||||
/// A WebAssemblyScript is there to implement the Script trait within WebAssemblyScript.
|
||||
|
@ -25,8 +29,8 @@ pub struct WebAssemblyScript {
|
|||
self_ptr: u32,
|
||||
/// Capabilities define which functions we actually implement.
|
||||
capabilities: AtomicPtr<HashSet<WebAssemblyScriptCapabilities>>,
|
||||
/// A reference back to our resolver.
|
||||
resolver: AtomicPtr<WebAssemblyScriptResolver>,
|
||||
/// The global runtime environment data.
|
||||
environment: Weak<WebAssemblyEnvironmentData>,
|
||||
}
|
||||
|
||||
impl WebAssemblyScript {
|
||||
|
@ -35,7 +39,7 @@ impl WebAssemblyScript {
|
|||
owner_ptr: *mut u8,
|
||||
self_ptr: u32,
|
||||
capabilities: *mut HashSet<WebAssemblyScriptCapabilities>,
|
||||
resolver: *mut WebAssemblyScriptResolver,
|
||||
environment: Weak<WebAssemblyEnvironmentData>,
|
||||
name: StringKey,
|
||||
) -> Self {
|
||||
Self {
|
||||
|
@ -45,7 +49,7 @@ impl WebAssemblyScript {
|
|||
owner_ptr: AtomicPtr::new(owner_ptr),
|
||||
self_ptr,
|
||||
capabilities: AtomicPtr::new(capabilities),
|
||||
resolver: AtomicPtr::new(resolver),
|
||||
environment,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +67,16 @@ impl Script for WebAssemblyScript {
|
|||
&self.suppressed_count
|
||||
}
|
||||
|
||||
fn on_initialize(&self, library: &DynamicLibrary, _pars: &[EffectParameter]) {
|
||||
let env = self.environment.upgrade().unwrap();
|
||||
let exported = env.exported_functions();
|
||||
if let Some(f) = exported.get(&"script_on_initialize".into()) {
|
||||
let func: NativeFunc<(u32, ExternRef<DynamicLibrary>, u32), ()> = f.native().unwrap();
|
||||
func.call(self.self_ptr, ExternRef::new(env.as_ref(), library), 0)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use std::fmt::{Debug, Formatter};
|
||||
use std::ops::DerefMut;
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use parking_lot::lock_api::{MappedRwLockReadGuard, RwLockReadGuard};
|
||||
use parking_lot::{RawRwLock, RwLock};
|
||||
use unique_type_id::{TypeId, UniqueTypeId};
|
||||
use unique_type_id::UniqueTypeId;
|
||||
use wasmer::{
|
||||
Cranelift, Exports, Extern, Features, Function, ImportObject, Instance, Memory, Module, NativeFunc, Store,
|
||||
Universal, Value, WasmerEnv,
|
||||
|
@ -28,8 +27,6 @@ pub struct WebAssemblyScriptResolver {
|
|||
/// Our currently loaded WASM instances. Empty until finalize() is called, after which the loaded modules get turned
|
||||
/// into actual instances.
|
||||
instances: Vec<Instance>,
|
||||
/// This is a map of all the functions that WASM gives us.
|
||||
exported_functions: HashMap<StringKey, Function>,
|
||||
|
||||
/// This is the WASM function to load a script.
|
||||
load_script_fn: Option<NativeFunc<(u8, ExternRef<StringKey>), u32>>,
|
||||
|
@ -64,7 +61,6 @@ impl WebAssemblyScriptResolver {
|
|||
store,
|
||||
modules: Default::default(),
|
||||
instances: Default::default(),
|
||||
exported_functions: Default::default(),
|
||||
load_script_fn: None,
|
||||
script_capabilities: Default::default(),
|
||||
environment_data: Arc::new(Default::default()),
|
||||
|
@ -84,22 +80,21 @@ impl WebAssemblyScriptResolver {
|
|||
let mut imports = ImportObject::new();
|
||||
let mut exports = Exports::new();
|
||||
|
||||
let env = WebAssemblyEnv {
|
||||
resolver: self.environment_data.clone(),
|
||||
};
|
||||
let env = WebAssemblyEnv::new(Arc::downgrade(&self.environment_data));
|
||||
register_webassembly_funcs(&mut exports, &self.store, env);
|
||||
imports.register("env", exports);
|
||||
|
||||
for module in &self.modules {
|
||||
let instance = Instance::new(module, &imports).unwrap();
|
||||
let exports = &instance.exports;
|
||||
let mut exported_functions = self.environment_data.exported_functions.write();
|
||||
for export in exports.iter() {
|
||||
match export.1 {
|
||||
Extern::Function(f) => {
|
||||
self.exported_functions.insert(export.0.as_str().into(), f.clone());
|
||||
exported_functions.insert(export.0.as_str().into(), f.clone());
|
||||
}
|
||||
Extern::Memory(m) => {
|
||||
self.environment_data.memory.write().insert(m.clone());
|
||||
let _ = self.environment_data.memory.write().insert(m.clone());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -107,11 +102,12 @@ impl WebAssemblyScriptResolver {
|
|||
if let Some(m) = &self.environment_data.memory.read().as_ref() {
|
||||
m.grow(32).unwrap();
|
||||
}
|
||||
if let Some(f) = self.exported_functions.get(&"load_script".into()) {
|
||||
if let Some(f) = exported_functions.get(&"load_script".into()) {
|
||||
self.load_script_fn = Some(f.native().unwrap())
|
||||
}
|
||||
if let Some(f) = self.exported_functions.get(&"allocate_mem".into()) {
|
||||
self.environment_data
|
||||
if let Some(f) = exported_functions.get(&"allocate_mem".into()) {
|
||||
let _ = self
|
||||
.environment_data
|
||||
.allocate_mem_fn
|
||||
.write()
|
||||
.insert(f.native().unwrap());
|
||||
|
@ -151,7 +147,12 @@ impl ScriptResolver for WebAssemblyScriptResolver {
|
|||
if !self.script_capabilities.read().contains_key(&key) {
|
||||
let mut capabilities = HashSet::new();
|
||||
unsafe {
|
||||
if let Some(get_cap) = self.exported_functions.get(&"get_script_capabilities".into()) {
|
||||
if let Some(get_cap) = self
|
||||
.environment_data
|
||||
.exported_functions
|
||||
.read()
|
||||
.get(&"get_script_capabilities".into())
|
||||
{
|
||||
let res = get_cap.call(&[Value::I32(script as i32)]).unwrap();
|
||||
let ptr = (self.environment_data.memory.read().as_ref().unwrap().data_ptr()
|
||||
as *const WebAssemblyScriptCapabilities)
|
||||
|
@ -173,7 +174,7 @@ impl ScriptResolver for WebAssemblyScriptResolver {
|
|||
script,
|
||||
capabilities as *const HashSet<WebAssemblyScriptCapabilities>
|
||||
as *mut HashSet<WebAssemblyScriptCapabilities>,
|
||||
self as *const WebAssemblyScriptResolver as *mut WebAssemblyScriptResolver,
|
||||
Arc::downgrade(&self.environment_data),
|
||||
script_key.clone(),
|
||||
))))
|
||||
}
|
||||
|
@ -200,30 +201,44 @@ pub struct WebAssemblyEnvironmentData {
|
|||
extern_ref_pointers: RwLock<Vec<*const u8>>,
|
||||
/// To make sure we send the same identifier to WASM when we send the same piece of data multiple times, we have a
|
||||
/// backwards lookup on extern_ref_pointers. This allows us to get the index for a given piece of data.
|
||||
extern_ref_pointers_lookup: RwLock<HashMap<*const u8, u32>>,
|
||||
extern_ref_pointers_lookup: RwLock<HashMap<ExternRefLookupKey, u32>>,
|
||||
/// As an added security measure on our extern refs, we keep track of the types of the extern ref data we've sent.
|
||||
/// This prevents illegal arbitrary memory operations, where we expect type X, but the actual type is Y, which would
|
||||
/// allow for modifying memory we might not want to. If we get a type mismatch, we will panic, preventing this.
|
||||
extern_ref_type_lookup: RwLock<HashMap<*const u8, TypeId<u64>>>,
|
||||
extern_ref_type_lookup: RwLock<HashSet<ExternRefLookupKey>>,
|
||||
|
||||
/// The memory inside of the WASM container.
|
||||
memory: RwLock<Option<Memory>>,
|
||||
|
||||
/// This is a map of all the functions that WASM gives us.
|
||||
exported_functions: RwLock<HashMap<StringKey, Function>>,
|
||||
|
||||
/// This is the WASM function to allocate memory inside the WASM container.
|
||||
allocate_mem_fn: RwLock<Option<NativeFunc<(u32, u32), u32>>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
struct ExternRefLookupKey {
|
||||
pub ptr: *const u8,
|
||||
pub t: u64,
|
||||
}
|
||||
|
||||
impl WebAssemblyEnvironmentData {
|
||||
/// This returns the memory of the WASM container.
|
||||
pub fn memory(&self) -> MappedRwLockReadGuard<'_, RawRwLock, Memory> {
|
||||
RwLockReadGuard::map(self.memory.read(), |a| a.as_ref().unwrap())
|
||||
}
|
||||
|
||||
/// This returns the functions exported from WASM.
|
||||
pub fn exported_functions(&self) -> RwLockReadGuard<'_, RawRwLock, HashMap<StringKey, Function>> {
|
||||
self.exported_functions.read()
|
||||
}
|
||||
|
||||
/// Allocates memory inside the WASM container with a given size and alignment. This memory is
|
||||
/// owned by WASM, and is how we can pass memory references that the host allocated to WASM.
|
||||
/// The return is a tuple containing both the actual pointer to the memory (usable by the host),
|
||||
/// and the WASM offset to the memory (usable by the client).
|
||||
pub fn allocate_mem(&self, size: u32, align: u32) -> (*const u8, u32) {
|
||||
pub fn allocate_mem(&self, size: u32, align: u32) -> (*mut u8, u32) {
|
||||
let wasm_ptr = self.allocate_mem_fn.read().as_ref().unwrap().call(size, align).unwrap();
|
||||
unsafe {
|
||||
(
|
||||
|
@ -246,7 +261,11 @@ impl WebAssemblyEnvironmentData {
|
|||
/// of this code.
|
||||
pub fn get_extern_ref_index<T: UniqueTypeId<u64>>(&self, value: &T) -> u32 {
|
||||
let ptr = value as *const T as *const u8;
|
||||
if let Some(v) = self.extern_ref_pointers_lookup.read().get(&ptr) {
|
||||
if let Some(v) = self
|
||||
.extern_ref_pointers_lookup
|
||||
.read()
|
||||
.get(&ExternRefLookupKey { ptr, t: T::id().0 })
|
||||
{
|
||||
return *v as u32;
|
||||
}
|
||||
let index = {
|
||||
|
@ -254,8 +273,12 @@ impl WebAssemblyEnvironmentData {
|
|||
extern_ref_guard.push(ptr);
|
||||
extern_ref_guard.len() as u32
|
||||
};
|
||||
self.extern_ref_pointers_lookup.write().insert(ptr, index);
|
||||
self.extern_ref_type_lookup.write().insert(ptr, T::id());
|
||||
self.extern_ref_pointers_lookup
|
||||
.write()
|
||||
.insert(ExternRefLookupKey { ptr, t: T::id().0 }, index);
|
||||
self.extern_ref_type_lookup
|
||||
.write()
|
||||
.insert(ExternRefLookupKey { ptr, t: T::id().0 });
|
||||
index
|
||||
}
|
||||
|
||||
|
@ -264,8 +287,15 @@ impl WebAssemblyEnvironmentData {
|
|||
pub fn get_extern_ref_value<T: UniqueTypeId<u64>>(&self, index: u32) -> &T {
|
||||
let read_guard = self.extern_ref_pointers.read();
|
||||
let ptr = read_guard.get((index - 1) as usize).unwrap();
|
||||
let expected_type_id = &self.extern_ref_type_lookup.read()[ptr];
|
||||
if expected_type_id.0 != T::id().0 {
|
||||
if self
|
||||
.extern_ref_type_lookup
|
||||
.read()
|
||||
.get(&ExternRefLookupKey {
|
||||
ptr: *ptr,
|
||||
t: T::id().0,
|
||||
})
|
||||
.is_none()
|
||||
{
|
||||
panic!(
|
||||
"Extern ref was accessed with wrong type. Requested type {}, but this was not the type the extern ref was stored with.",
|
||||
std::any::type_name::<T>()
|
||||
|
@ -280,13 +310,18 @@ impl WebAssemblyEnvironmentData {
|
|||
#[derive(Clone)]
|
||||
pub(crate) struct WebAssemblyEnv {
|
||||
/// A pointer to the WebAssemblyScriptResolver belonging to the current script environment.
|
||||
pub resolver: Arc<WebAssemblyEnvironmentData>,
|
||||
data: Weak<WebAssemblyEnvironmentData>,
|
||||
}
|
||||
|
||||
impl WebAssemblyEnv {
|
||||
/// Get the WebAssemblyScriptResolver belonging to the current context.
|
||||
pub fn resolver(&self) -> &Arc<WebAssemblyEnvironmentData> {
|
||||
&self.resolver
|
||||
/// Instantiates a new Environment with the requested data.
|
||||
pub fn new(data: Weak<WebAssemblyEnvironmentData>) -> Self {
|
||||
Self { data }
|
||||
}
|
||||
|
||||
/// Get the actual data belonging to the current context.
|
||||
pub fn data(&self) -> Arc<WebAssemblyEnvironmentData> {
|
||||
self.data.upgrade().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,4 +329,8 @@ unsafe impl Sync for WebAssemblyEnv {}
|
|||
|
||||
unsafe impl Send for WebAssemblyEnv {}
|
||||
|
||||
unsafe impl Sync for WebAssemblyEnvironmentData {}
|
||||
|
||||
unsafe impl Send for WebAssemblyEnvironmentData {}
|
||||
|
||||
impl WasmerEnv for WebAssemblyEnv {}
|
||||
|
|
Binary file not shown.
|
@ -56,5 +56,5 @@ fn validate_script() {
|
|||
.load_script(0 as *const u8, ScriptCategory::Move, &"test".into())
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
script.on_initialize(&[]);
|
||||
script.on_initialize(&lib, &[]);
|
||||
}
|
||||
|
|
15
types.toml
15
types.toml
|
@ -1,15 +0,0 @@
|
|||
MoveLibrary = 0
|
||||
MoveData = 1
|
||||
StringKey = 2
|
||||
DynamicLibrary = 3
|
||||
StaticData = 4
|
||||
DynamicLibrary = 0
|
||||
MoveLibrary = 1
|
||||
StaticData = 2
|
||||
MoveData = 3
|
||||
StringKey = 4
|
||||
DynamicLibrary = 0
|
||||
MoveLibrary = 1
|
||||
StaticData = 2
|
||||
MoveData = 3
|
||||
StringKey = 4
|
Loading…
Reference in New Issue