1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::vmcontext::VMGlobalDefinition;
use std::cell::UnsafeCell;
use std::ptr::NonNull;
use std::sync::Mutex;
use thiserror::Error;
use wasmer_types::{GlobalType, Mutability, Type, Value};
#[derive(Debug)]
pub struct Global {
ty: GlobalType,
vm_global_definition: Box<UnsafeCell<VMGlobalDefinition>>,
lock: Mutex<()>,
}
unsafe impl Send for Global {}
unsafe impl Sync for Global {}
#[derive(Error, Debug, Clone, PartialEq, Hash)]
pub enum GlobalError {
#[error("Attempted to set an immutable global")]
ImmutableGlobalCannotBeSet,
#[error("Attempted to operate on a global of type {expected} as a global of type {found}")]
IncorrectType {
expected: Type,
found: Type,
},
}
impl Global {
pub fn new(global_type: GlobalType) -> Self {
Self {
ty: global_type,
vm_global_definition: Box::new(UnsafeCell::new(VMGlobalDefinition::new())),
lock: Mutex::new(()),
}
}
pub fn ty(&self) -> &GlobalType {
&self.ty
}
pub fn vmglobal(&self) -> NonNull<VMGlobalDefinition> {
let ptr = self.vm_global_definition.as_ref() as *const UnsafeCell<VMGlobalDefinition>
as *const VMGlobalDefinition as *mut VMGlobalDefinition;
unsafe { NonNull::new_unchecked(ptr) }
}
pub fn get<T>(&self) -> Value<T> {
let _global_guard = self.lock.lock().unwrap();
unsafe {
let definition = &*self.vm_global_definition.get();
match self.ty().ty {
Type::I32 => Value::I32(*definition.as_i32()),
Type::I64 => Value::I64(*definition.as_i64()),
Type::F32 => Value::F32(*definition.as_f32()),
Type::F64 => Value::F64(*definition.as_f64()),
Type::V128 => Value::V128(*definition.as_u128()),
_ => unimplemented!("Global::get for {:?}", self.ty),
}
}
}
pub unsafe fn set<T>(&self, val: Value<T>) -> Result<(), GlobalError> {
let _global_guard = self.lock.lock().unwrap();
if self.ty().mutability != Mutability::Var {
return Err(GlobalError::ImmutableGlobalCannotBeSet);
}
if val.ty() != self.ty().ty {
return Err(GlobalError::IncorrectType {
expected: self.ty.ty,
found: val.ty(),
});
}
self.set_unchecked(val)
}
pub unsafe fn set_unchecked<T>(&self, val: Value<T>) -> Result<(), GlobalError> {
let definition = &mut *self.vm_global_definition.get();
match val {
Value::I32(i) => *definition.as_i32_mut() = i,
Value::I64(i) => *definition.as_i64_mut() = i,
Value::F32(f) => *definition.as_f32_mut() = f,
Value::F64(f) => *definition.as_f64_mut() = f,
Value::V128(x) => *definition.as_u128_bits_mut() = x.to_ne_bytes(),
_ => unimplemented!("Global::set for {:?}", val.ty()),
}
Ok(())
}
}