Struct wasmtime_runtime::VMGlobalDefinition
source · #[repr(C, align(16))]pub struct VMGlobalDefinition { /* private fields */ }
Expand description
The storage for a WebAssembly global defined within the instance.
TODO: Pack the globals more densely, rather than using the same size for every type.
Implementations§
source§impl VMGlobalDefinition
impl VMGlobalDefinition
sourcepub fn new() -> Self
pub fn new() -> Self
Construct a VMGlobalDefinition
.
Examples found in repository?
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
unsafe fn initialize_vmctx_globals(&mut self, module: &Module) {
let num_imports = module.num_imported_globals;
for (index, global) in module.globals.iter().skip(num_imports) {
let def_index = module.defined_global_index(index).unwrap();
let to = self.global_ptr(def_index);
// Initialize the global before writing to it
ptr::write(to, VMGlobalDefinition::new());
match global.initializer {
GlobalInit::I32Const(x) => *(*to).as_i32_mut() = x,
GlobalInit::I64Const(x) => *(*to).as_i64_mut() = x,
GlobalInit::F32Const(x) => *(*to).as_f32_bits_mut() = x,
GlobalInit::F64Const(x) => *(*to).as_f64_bits_mut() = x,
GlobalInit::V128Const(x) => *(*to).as_u128_mut() = x,
GlobalInit::GetGlobal(x) => {
let from = if let Some(def_x) = module.defined_global_index(x) {
self.global(def_x)
} else {
&*self.imported_global(x).from
};
// Globals of type `externref` need to manage the reference
// count as values move between globals, everything else is just
// copy-able bits.
match global.wasm_ty {
WasmType::ExternRef => {
*(*to).as_externref_mut() = from.as_externref().clone()
}
_ => ptr::copy_nonoverlapping(from, to, 1),
}
}
GlobalInit::RefFunc(f) => {
*(*to).as_anyfunc_mut() = self.get_caller_checked_anyfunc(f).unwrap()
as *const VMCallerCheckedAnyfunc;
}
GlobalInit::RefNullConst => match global.wasm_ty {
// `VMGlobalDefinition::new()` already zeroed out the bits
WasmType::FuncRef => {}
WasmType::ExternRef => {}
ty => panic!("unsupported reference type for global: {:?}", ty),
},
GlobalInit::Import => panic!("locally-defined global initialized as import"),
}
}
}
sourcepub unsafe fn as_i32_mut(&mut self) -> &mut i32
pub unsafe fn as_i32_mut(&mut self) -> &mut i32
Return a mutable reference to the value as an i32.
Examples found in repository?
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
unsafe fn initialize_vmctx_globals(&mut self, module: &Module) {
let num_imports = module.num_imported_globals;
for (index, global) in module.globals.iter().skip(num_imports) {
let def_index = module.defined_global_index(index).unwrap();
let to = self.global_ptr(def_index);
// Initialize the global before writing to it
ptr::write(to, VMGlobalDefinition::new());
match global.initializer {
GlobalInit::I32Const(x) => *(*to).as_i32_mut() = x,
GlobalInit::I64Const(x) => *(*to).as_i64_mut() = x,
GlobalInit::F32Const(x) => *(*to).as_f32_bits_mut() = x,
GlobalInit::F64Const(x) => *(*to).as_f64_bits_mut() = x,
GlobalInit::V128Const(x) => *(*to).as_u128_mut() = x,
GlobalInit::GetGlobal(x) => {
let from = if let Some(def_x) = module.defined_global_index(x) {
self.global(def_x)
} else {
&*self.imported_global(x).from
};
// Globals of type `externref` need to manage the reference
// count as values move between globals, everything else is just
// copy-able bits.
match global.wasm_ty {
WasmType::ExternRef => {
*(*to).as_externref_mut() = from.as_externref().clone()
}
_ => ptr::copy_nonoverlapping(from, to, 1),
}
}
GlobalInit::RefFunc(f) => {
*(*to).as_anyfunc_mut() = self.get_caller_checked_anyfunc(f).unwrap()
as *const VMCallerCheckedAnyfunc;
}
GlobalInit::RefNullConst => match global.wasm_ty {
// `VMGlobalDefinition::new()` already zeroed out the bits
WasmType::FuncRef => {}
WasmType::ExternRef => {}
ty => panic!("unsupported reference type for global: {:?}", ty),
},
GlobalInit::Import => panic!("locally-defined global initialized as import"),
}
}
}
sourcepub unsafe fn as_u32(&self) -> &u32
pub unsafe fn as_u32(&self) -> &u32
Return a reference to the value as a u32.
Examples found in repository?
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
fn get_table_init_start(init: &TableInitializer, instance: &Instance) -> Result<u32> {
match init.base {
Some(base) => {
let val = unsafe {
if let Some(def_index) = instance.module().defined_global_index(base) {
*instance.global(def_index).as_u32()
} else {
*(*instance.imported_global(base).from).as_u32()
}
};
init.offset
.checked_add(val)
.ok_or_else(|| anyhow!("element segment global base overflows"))
}
None => Ok(init.offset),
}
}
fn check_table_init_bounds(instance: &mut Instance, module: &Module) -> Result<()> {
match &module.table_initialization {
TableInitialization::FuncTable { segments, .. }
| TableInitialization::Segments { segments } => {
for segment in segments {
let table = unsafe { &*instance.get_table(segment.table_index) };
let start = get_table_init_start(segment, instance)?;
let start = usize::try_from(start).unwrap();
let end = start.checked_add(segment.elements.len());
match end {
Some(end) if end <= table.size() as usize => {
// Initializer is in bounds
}
_ => {
bail!("table out of bounds: elements segment does not fit")
}
}
}
}
}
Ok(())
}
fn initialize_tables(instance: &mut Instance, module: &Module) -> Result<()> {
// Note: if the module's table initializer state is in
// FuncTable mode, we will lazily initialize tables based on
// any statically-precomputed image of FuncIndexes, but there
// may still be "leftover segments" that could not be
// incorporated. So we have a unified handler here that
// iterates over all segments (Segments mode) or leftover
// segments (FuncTable mode) to initialize.
match &module.table_initialization {
TableInitialization::FuncTable { segments, .. }
| TableInitialization::Segments { segments } => {
for segment in segments {
instance.table_init_segment(
segment.table_index,
&segment.elements,
get_table_init_start(segment, instance)?,
0,
segment.elements.len() as u32,
)?;
}
}
}
Ok(())
}
fn get_memory_init_start(init: &MemoryInitializer, instance: &Instance) -> Result<u64> {
match init.base {
Some(base) => {
let mem64 = instance.module().memory_plans[init.memory_index]
.memory
.memory64;
let val = unsafe {
let global = if let Some(def_index) = instance.module().defined_global_index(base) {
instance.global(def_index)
} else {
&*instance.imported_global(base).from
};
if mem64 {
*global.as_u64()
} else {
u64::from(*global.as_u32())
}
};
init.offset
.checked_add(val)
.ok_or_else(|| anyhow!("data segment global base overflows"))
}
None => Ok(init.offset),
}
}
fn check_memory_init_bounds(instance: &Instance, initializers: &[MemoryInitializer]) -> Result<()> {
for init in initializers {
let memory = instance.get_memory(init.memory_index);
let start = get_memory_init_start(init, instance)?;
let end = usize::try_from(start)
.ok()
.and_then(|start| start.checked_add(init.data.len()));
match end {
Some(end) if end <= memory.current_length() => {
// Initializer is in bounds
}
_ => {
bail!("memory out of bounds: data segment does not fit")
}
}
}
Ok(())
}
fn initialize_memories(instance: &mut Instance, module: &Module) -> Result<()> {
let memory_size_in_pages =
&|memory| (instance.get_memory(memory).current_length() as u64) / u64::from(WASM_PAGE_SIZE);
// Loads the `global` value and returns it as a `u64`, but sign-extends
// 32-bit globals which can be used as the base for 32-bit memories.
let get_global_as_u64 = &|global| unsafe {
let def = if let Some(def_index) = instance.module().defined_global_index(global) {
instance.global(def_index)
} else {
&*instance.imported_global(global).from
};
if module.globals[global].wasm_ty == WasmType::I64 {
*def.as_u64()
} else {
u64::from(*def.as_u32())
}
};
// Delegates to the `init_memory` method which is sort of a duplicate of
// `instance.memory_init_segment` but is used at compile-time in other
// contexts so is shared here to have only one method of memory
// initialization.
//
// This call to `init_memory` notably implements all the bells and whistles
// so errors only happen if an out-of-bounds segment is found, in which case
// a trap is returned.
let ok = module.memory_initialization.init_memory(
InitMemory::Runtime {
memory_size_in_pages,
get_global_as_u64,
},
&mut |memory_index, init| {
// If this initializer applies to a defined memory but that memory
// doesn't need initialization, due to something like copy-on-write
// pre-initializing it via mmap magic, then this initializer can be
// skipped entirely.
if let Some(memory_index) = module.defined_memory_index(memory_index) {
if !instance.memories[memory_index].needs_init() {
return true;
}
}
let memory = instance.get_memory(memory_index);
unsafe {
let src = instance.wasm_data(init.data.clone());
let dst = memory.base.add(usize::try_from(init.offset).unwrap());
// FIXME audit whether this is safe in the presence of shared
// memory
// (https://github.com/bytecodealliance/wasmtime/issues/4203).
ptr::copy_nonoverlapping(src.as_ptr(), dst, src.len())
}
true
},
);
if !ok {
return Err(Trap::MemoryOutOfBounds.into());
}
Ok(())
}
sourcepub unsafe fn as_u32_mut(&mut self) -> &mut u32
pub unsafe fn as_u32_mut(&mut self) -> &mut u32
Return a mutable reference to the value as an u32.
sourcepub unsafe fn as_i64_mut(&mut self) -> &mut i64
pub unsafe fn as_i64_mut(&mut self) -> &mut i64
Return a mutable reference to the value as an i64.
Examples found in repository?
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
unsafe fn initialize_vmctx_globals(&mut self, module: &Module) {
let num_imports = module.num_imported_globals;
for (index, global) in module.globals.iter().skip(num_imports) {
let def_index = module.defined_global_index(index).unwrap();
let to = self.global_ptr(def_index);
// Initialize the global before writing to it
ptr::write(to, VMGlobalDefinition::new());
match global.initializer {
GlobalInit::I32Const(x) => *(*to).as_i32_mut() = x,
GlobalInit::I64Const(x) => *(*to).as_i64_mut() = x,
GlobalInit::F32Const(x) => *(*to).as_f32_bits_mut() = x,
GlobalInit::F64Const(x) => *(*to).as_f64_bits_mut() = x,
GlobalInit::V128Const(x) => *(*to).as_u128_mut() = x,
GlobalInit::GetGlobal(x) => {
let from = if let Some(def_x) = module.defined_global_index(x) {
self.global(def_x)
} else {
&*self.imported_global(x).from
};
// Globals of type `externref` need to manage the reference
// count as values move between globals, everything else is just
// copy-able bits.
match global.wasm_ty {
WasmType::ExternRef => {
*(*to).as_externref_mut() = from.as_externref().clone()
}
_ => ptr::copy_nonoverlapping(from, to, 1),
}
}
GlobalInit::RefFunc(f) => {
*(*to).as_anyfunc_mut() = self.get_caller_checked_anyfunc(f).unwrap()
as *const VMCallerCheckedAnyfunc;
}
GlobalInit::RefNullConst => match global.wasm_ty {
// `VMGlobalDefinition::new()` already zeroed out the bits
WasmType::FuncRef => {}
WasmType::ExternRef => {}
ty => panic!("unsupported reference type for global: {:?}", ty),
},
GlobalInit::Import => panic!("locally-defined global initialized as import"),
}
}
}
sourcepub unsafe fn as_u64(&self) -> &u64
pub unsafe fn as_u64(&self) -> &u64
Return a reference to the value as an u64.
Examples found in repository?
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
fn get_memory_init_start(init: &MemoryInitializer, instance: &Instance) -> Result<u64> {
match init.base {
Some(base) => {
let mem64 = instance.module().memory_plans[init.memory_index]
.memory
.memory64;
let val = unsafe {
let global = if let Some(def_index) = instance.module().defined_global_index(base) {
instance.global(def_index)
} else {
&*instance.imported_global(base).from
};
if mem64 {
*global.as_u64()
} else {
u64::from(*global.as_u32())
}
};
init.offset
.checked_add(val)
.ok_or_else(|| anyhow!("data segment global base overflows"))
}
None => Ok(init.offset),
}
}
fn check_memory_init_bounds(instance: &Instance, initializers: &[MemoryInitializer]) -> Result<()> {
for init in initializers {
let memory = instance.get_memory(init.memory_index);
let start = get_memory_init_start(init, instance)?;
let end = usize::try_from(start)
.ok()
.and_then(|start| start.checked_add(init.data.len()));
match end {
Some(end) if end <= memory.current_length() => {
// Initializer is in bounds
}
_ => {
bail!("memory out of bounds: data segment does not fit")
}
}
}
Ok(())
}
fn initialize_memories(instance: &mut Instance, module: &Module) -> Result<()> {
let memory_size_in_pages =
&|memory| (instance.get_memory(memory).current_length() as u64) / u64::from(WASM_PAGE_SIZE);
// Loads the `global` value and returns it as a `u64`, but sign-extends
// 32-bit globals which can be used as the base for 32-bit memories.
let get_global_as_u64 = &|global| unsafe {
let def = if let Some(def_index) = instance.module().defined_global_index(global) {
instance.global(def_index)
} else {
&*instance.imported_global(global).from
};
if module.globals[global].wasm_ty == WasmType::I64 {
*def.as_u64()
} else {
u64::from(*def.as_u32())
}
};
// Delegates to the `init_memory` method which is sort of a duplicate of
// `instance.memory_init_segment` but is used at compile-time in other
// contexts so is shared here to have only one method of memory
// initialization.
//
// This call to `init_memory` notably implements all the bells and whistles
// so errors only happen if an out-of-bounds segment is found, in which case
// a trap is returned.
let ok = module.memory_initialization.init_memory(
InitMemory::Runtime {
memory_size_in_pages,
get_global_as_u64,
},
&mut |memory_index, init| {
// If this initializer applies to a defined memory but that memory
// doesn't need initialization, due to something like copy-on-write
// pre-initializing it via mmap magic, then this initializer can be
// skipped entirely.
if let Some(memory_index) = module.defined_memory_index(memory_index) {
if !instance.memories[memory_index].needs_init() {
return true;
}
}
let memory = instance.get_memory(memory_index);
unsafe {
let src = instance.wasm_data(init.data.clone());
let dst = memory.base.add(usize::try_from(init.offset).unwrap());
// FIXME audit whether this is safe in the presence of shared
// memory
// (https://github.com/bytecodealliance/wasmtime/issues/4203).
ptr::copy_nonoverlapping(src.as_ptr(), dst, src.len())
}
true
},
);
if !ok {
return Err(Trap::MemoryOutOfBounds.into());
}
Ok(())
}
sourcepub unsafe fn as_u64_mut(&mut self) -> &mut u64
pub unsafe fn as_u64_mut(&mut self) -> &mut u64
Return a mutable reference to the value as an u64.
sourcepub unsafe fn as_f32_mut(&mut self) -> &mut f32
pub unsafe fn as_f32_mut(&mut self) -> &mut f32
Return a mutable reference to the value as an f32.
sourcepub unsafe fn as_f32_bits(&self) -> &u32
pub unsafe fn as_f32_bits(&self) -> &u32
Return a reference to the value as f32 bits.
sourcepub unsafe fn as_f32_bits_mut(&mut self) -> &mut u32
pub unsafe fn as_f32_bits_mut(&mut self) -> &mut u32
Return a mutable reference to the value as f32 bits.
Examples found in repository?
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
unsafe fn initialize_vmctx_globals(&mut self, module: &Module) {
let num_imports = module.num_imported_globals;
for (index, global) in module.globals.iter().skip(num_imports) {
let def_index = module.defined_global_index(index).unwrap();
let to = self.global_ptr(def_index);
// Initialize the global before writing to it
ptr::write(to, VMGlobalDefinition::new());
match global.initializer {
GlobalInit::I32Const(x) => *(*to).as_i32_mut() = x,
GlobalInit::I64Const(x) => *(*to).as_i64_mut() = x,
GlobalInit::F32Const(x) => *(*to).as_f32_bits_mut() = x,
GlobalInit::F64Const(x) => *(*to).as_f64_bits_mut() = x,
GlobalInit::V128Const(x) => *(*to).as_u128_mut() = x,
GlobalInit::GetGlobal(x) => {
let from = if let Some(def_x) = module.defined_global_index(x) {
self.global(def_x)
} else {
&*self.imported_global(x).from
};
// Globals of type `externref` need to manage the reference
// count as values move between globals, everything else is just
// copy-able bits.
match global.wasm_ty {
WasmType::ExternRef => {
*(*to).as_externref_mut() = from.as_externref().clone()
}
_ => ptr::copy_nonoverlapping(from, to, 1),
}
}
GlobalInit::RefFunc(f) => {
*(*to).as_anyfunc_mut() = self.get_caller_checked_anyfunc(f).unwrap()
as *const VMCallerCheckedAnyfunc;
}
GlobalInit::RefNullConst => match global.wasm_ty {
// `VMGlobalDefinition::new()` already zeroed out the bits
WasmType::FuncRef => {}
WasmType::ExternRef => {}
ty => panic!("unsupported reference type for global: {:?}", ty),
},
GlobalInit::Import => panic!("locally-defined global initialized as import"),
}
}
}
sourcepub unsafe fn as_f64_mut(&mut self) -> &mut f64
pub unsafe fn as_f64_mut(&mut self) -> &mut f64
Return a mutable reference to the value as an f64.
sourcepub unsafe fn as_f64_bits(&self) -> &u64
pub unsafe fn as_f64_bits(&self) -> &u64
Return a reference to the value as f64 bits.
sourcepub unsafe fn as_f64_bits_mut(&mut self) -> &mut u64
pub unsafe fn as_f64_bits_mut(&mut self) -> &mut u64
Return a mutable reference to the value as f64 bits.
Examples found in repository?
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
unsafe fn initialize_vmctx_globals(&mut self, module: &Module) {
let num_imports = module.num_imported_globals;
for (index, global) in module.globals.iter().skip(num_imports) {
let def_index = module.defined_global_index(index).unwrap();
let to = self.global_ptr(def_index);
// Initialize the global before writing to it
ptr::write(to, VMGlobalDefinition::new());
match global.initializer {
GlobalInit::I32Const(x) => *(*to).as_i32_mut() = x,
GlobalInit::I64Const(x) => *(*to).as_i64_mut() = x,
GlobalInit::F32Const(x) => *(*to).as_f32_bits_mut() = x,
GlobalInit::F64Const(x) => *(*to).as_f64_bits_mut() = x,
GlobalInit::V128Const(x) => *(*to).as_u128_mut() = x,
GlobalInit::GetGlobal(x) => {
let from = if let Some(def_x) = module.defined_global_index(x) {
self.global(def_x)
} else {
&*self.imported_global(x).from
};
// Globals of type `externref` need to manage the reference
// count as values move between globals, everything else is just
// copy-able bits.
match global.wasm_ty {
WasmType::ExternRef => {
*(*to).as_externref_mut() = from.as_externref().clone()
}
_ => ptr::copy_nonoverlapping(from, to, 1),
}
}
GlobalInit::RefFunc(f) => {
*(*to).as_anyfunc_mut() = self.get_caller_checked_anyfunc(f).unwrap()
as *const VMCallerCheckedAnyfunc;
}
GlobalInit::RefNullConst => match global.wasm_ty {
// `VMGlobalDefinition::new()` already zeroed out the bits
WasmType::FuncRef => {}
WasmType::ExternRef => {}
ty => panic!("unsupported reference type for global: {:?}", ty),
},
GlobalInit::Import => panic!("locally-defined global initialized as import"),
}
}
}
sourcepub unsafe fn as_u128_mut(&mut self) -> &mut u128
pub unsafe fn as_u128_mut(&mut self) -> &mut u128
Return a mutable reference to the value as an u128.
Examples found in repository?
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
unsafe fn initialize_vmctx_globals(&mut self, module: &Module) {
let num_imports = module.num_imported_globals;
for (index, global) in module.globals.iter().skip(num_imports) {
let def_index = module.defined_global_index(index).unwrap();
let to = self.global_ptr(def_index);
// Initialize the global before writing to it
ptr::write(to, VMGlobalDefinition::new());
match global.initializer {
GlobalInit::I32Const(x) => *(*to).as_i32_mut() = x,
GlobalInit::I64Const(x) => *(*to).as_i64_mut() = x,
GlobalInit::F32Const(x) => *(*to).as_f32_bits_mut() = x,
GlobalInit::F64Const(x) => *(*to).as_f64_bits_mut() = x,
GlobalInit::V128Const(x) => *(*to).as_u128_mut() = x,
GlobalInit::GetGlobal(x) => {
let from = if let Some(def_x) = module.defined_global_index(x) {
self.global(def_x)
} else {
&*self.imported_global(x).from
};
// Globals of type `externref` need to manage the reference
// count as values move between globals, everything else is just
// copy-able bits.
match global.wasm_ty {
WasmType::ExternRef => {
*(*to).as_externref_mut() = from.as_externref().clone()
}
_ => ptr::copy_nonoverlapping(from, to, 1),
}
}
GlobalInit::RefFunc(f) => {
*(*to).as_anyfunc_mut() = self.get_caller_checked_anyfunc(f).unwrap()
as *const VMCallerCheckedAnyfunc;
}
GlobalInit::RefNullConst => match global.wasm_ty {
// `VMGlobalDefinition::new()` already zeroed out the bits
WasmType::FuncRef => {}
WasmType::ExternRef => {}
ty => panic!("unsupported reference type for global: {:?}", ty),
},
GlobalInit::Import => panic!("locally-defined global initialized as import"),
}
}
}
sourcepub unsafe fn as_u128_bits(&self) -> &[u8; 16]
pub unsafe fn as_u128_bits(&self) -> &[u8; 16]
Return a reference to the value as u128 bits.
sourcepub unsafe fn as_u128_bits_mut(&mut self) -> &mut [u8; 16]
pub unsafe fn as_u128_bits_mut(&mut self) -> &mut [u8; 16]
Return a mutable reference to the value as u128 bits.
sourcepub unsafe fn as_externref(&self) -> &Option<VMExternRef>
pub unsafe fn as_externref(&self) -> &Option<VMExternRef>
Return a reference to the value as an externref.
Examples found in repository?
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
unsafe fn externref_global_get(vmctx: *mut VMContext, index: u32) -> *mut u8 {
let index = GlobalIndex::from_u32(index);
let instance = (*vmctx).instance();
let global = instance.defined_or_imported_global_ptr(index);
match (*global).as_externref().clone() {
None => ptr::null_mut(),
Some(externref) => {
let raw = externref.as_raw();
let (activations_table, module_info_lookup) =
(*instance.store()).externref_activations_table();
activations_table.insert_with_gc(externref, module_info_lookup);
raw
}
}
}
More examples
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
unsafe fn initialize_vmctx_globals(&mut self, module: &Module) {
let num_imports = module.num_imported_globals;
for (index, global) in module.globals.iter().skip(num_imports) {
let def_index = module.defined_global_index(index).unwrap();
let to = self.global_ptr(def_index);
// Initialize the global before writing to it
ptr::write(to, VMGlobalDefinition::new());
match global.initializer {
GlobalInit::I32Const(x) => *(*to).as_i32_mut() = x,
GlobalInit::I64Const(x) => *(*to).as_i64_mut() = x,
GlobalInit::F32Const(x) => *(*to).as_f32_bits_mut() = x,
GlobalInit::F64Const(x) => *(*to).as_f64_bits_mut() = x,
GlobalInit::V128Const(x) => *(*to).as_u128_mut() = x,
GlobalInit::GetGlobal(x) => {
let from = if let Some(def_x) = module.defined_global_index(x) {
self.global(def_x)
} else {
&*self.imported_global(x).from
};
// Globals of type `externref` need to manage the reference
// count as values move between globals, everything else is just
// copy-able bits.
match global.wasm_ty {
WasmType::ExternRef => {
*(*to).as_externref_mut() = from.as_externref().clone()
}
_ => ptr::copy_nonoverlapping(from, to, 1),
}
}
GlobalInit::RefFunc(f) => {
*(*to).as_anyfunc_mut() = self.get_caller_checked_anyfunc(f).unwrap()
as *const VMCallerCheckedAnyfunc;
}
GlobalInit::RefNullConst => match global.wasm_ty {
// `VMGlobalDefinition::new()` already zeroed out the bits
WasmType::FuncRef => {}
WasmType::ExternRef => {}
ty => panic!("unsupported reference type for global: {:?}", ty),
},
GlobalInit::Import => panic!("locally-defined global initialized as import"),
}
}
}
sourcepub unsafe fn as_externref_mut(&mut self) -> &mut Option<VMExternRef>
pub unsafe fn as_externref_mut(&mut self) -> &mut Option<VMExternRef>
Return a mutable reference to the value as an externref.
Examples found in repository?
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
unsafe fn externref_global_set(vmctx: *mut VMContext, index: u32, externref: *mut u8) {
let externref = if externref.is_null() {
None
} else {
Some(VMExternRef::clone_from_raw(externref))
};
let index = GlobalIndex::from_u32(index);
let instance = (*vmctx).instance();
let global = instance.defined_or_imported_global_ptr(index);
// Swap the new `externref` value into the global before we drop the old
// value. This protects against an `externref` with a `Drop` implementation
// that calls back into Wasm and touches this global again (we want to avoid
// it observing a halfway-deinitialized value).
let old = mem::replace((*global).as_externref_mut(), externref);
drop(old);
}
More examples
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054
unsafe fn initialize_vmctx_globals(&mut self, module: &Module) {
let num_imports = module.num_imported_globals;
for (index, global) in module.globals.iter().skip(num_imports) {
let def_index = module.defined_global_index(index).unwrap();
let to = self.global_ptr(def_index);
// Initialize the global before writing to it
ptr::write(to, VMGlobalDefinition::new());
match global.initializer {
GlobalInit::I32Const(x) => *(*to).as_i32_mut() = x,
GlobalInit::I64Const(x) => *(*to).as_i64_mut() = x,
GlobalInit::F32Const(x) => *(*to).as_f32_bits_mut() = x,
GlobalInit::F64Const(x) => *(*to).as_f64_bits_mut() = x,
GlobalInit::V128Const(x) => *(*to).as_u128_mut() = x,
GlobalInit::GetGlobal(x) => {
let from = if let Some(def_x) = module.defined_global_index(x) {
self.global(def_x)
} else {
&*self.imported_global(x).from
};
// Globals of type `externref` need to manage the reference
// count as values move between globals, everything else is just
// copy-able bits.
match global.wasm_ty {
WasmType::ExternRef => {
*(*to).as_externref_mut() = from.as_externref().clone()
}
_ => ptr::copy_nonoverlapping(from, to, 1),
}
}
GlobalInit::RefFunc(f) => {
*(*to).as_anyfunc_mut() = self.get_caller_checked_anyfunc(f).unwrap()
as *const VMCallerCheckedAnyfunc;
}
GlobalInit::RefNullConst => match global.wasm_ty {
// `VMGlobalDefinition::new()` already zeroed out the bits
WasmType::FuncRef => {}
WasmType::ExternRef => {}
ty => panic!("unsupported reference type for global: {:?}", ty),
},
GlobalInit::Import => panic!("locally-defined global initialized as import"),
}
}
}
}
impl Drop for Instance {
fn drop(&mut self) {
// Drop any defined globals
for (idx, global) in self.module().globals.iter() {
let idx = match self.module().defined_global_index(idx) {
Some(idx) => idx,
None => continue,
};
match global.wasm_ty {
// For now only externref globals need to get destroyed
WasmType::ExternRef => {}
_ => continue,
}
unsafe {
drop((*self.global_ptr(idx)).as_externref_mut().take());
}
}
}
sourcepub unsafe fn as_anyfunc(&self) -> *const VMCallerCheckedAnyfunc
pub unsafe fn as_anyfunc(&self) -> *const VMCallerCheckedAnyfunc
Return a reference to the value as an anyfunc.
sourcepub unsafe fn as_anyfunc_mut(&mut self) -> &mut *const VMCallerCheckedAnyfunc
pub unsafe fn as_anyfunc_mut(&mut self) -> &mut *const VMCallerCheckedAnyfunc
Return a mutable reference to the value as an anyfunc.
Examples found in repository?
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
unsafe fn initialize_vmctx_globals(&mut self, module: &Module) {
let num_imports = module.num_imported_globals;
for (index, global) in module.globals.iter().skip(num_imports) {
let def_index = module.defined_global_index(index).unwrap();
let to = self.global_ptr(def_index);
// Initialize the global before writing to it
ptr::write(to, VMGlobalDefinition::new());
match global.initializer {
GlobalInit::I32Const(x) => *(*to).as_i32_mut() = x,
GlobalInit::I64Const(x) => *(*to).as_i64_mut() = x,
GlobalInit::F32Const(x) => *(*to).as_f32_bits_mut() = x,
GlobalInit::F64Const(x) => *(*to).as_f64_bits_mut() = x,
GlobalInit::V128Const(x) => *(*to).as_u128_mut() = x,
GlobalInit::GetGlobal(x) => {
let from = if let Some(def_x) = module.defined_global_index(x) {
self.global(def_x)
} else {
&*self.imported_global(x).from
};
// Globals of type `externref` need to manage the reference
// count as values move between globals, everything else is just
// copy-able bits.
match global.wasm_ty {
WasmType::ExternRef => {
*(*to).as_externref_mut() = from.as_externref().clone()
}
_ => ptr::copy_nonoverlapping(from, to, 1),
}
}
GlobalInit::RefFunc(f) => {
*(*to).as_anyfunc_mut() = self.get_caller_checked_anyfunc(f).unwrap()
as *const VMCallerCheckedAnyfunc;
}
GlobalInit::RefNullConst => match global.wasm_ty {
// `VMGlobalDefinition::new()` already zeroed out the bits
WasmType::FuncRef => {}
WasmType::ExternRef => {}
ty => panic!("unsupported reference type for global: {:?}", ty),
},
GlobalInit::Import => panic!("locally-defined global initialized as import"),
}
}
}