Restructure VMContext to eliminate a level of indirection.
This commit is contained in:
@@ -2,7 +2,7 @@ use cast;
|
|||||||
use cranelift_codegen::cursor::FuncCursor;
|
use cranelift_codegen::cursor::FuncCursor;
|
||||||
use cranelift_codegen::ir;
|
use cranelift_codegen::ir;
|
||||||
use cranelift_codegen::ir::condcodes::*;
|
use cranelift_codegen::ir::condcodes::*;
|
||||||
use cranelift_codegen::ir::immediates::{Offset32, Uimm64};
|
use cranelift_codegen::ir::immediates::{Imm64, Offset32, Uimm64};
|
||||||
use cranelift_codegen::ir::types::*;
|
use cranelift_codegen::ir::types::*;
|
||||||
use cranelift_codegen::ir::{
|
use cranelift_codegen::ir::{
|
||||||
AbiParam, ArgumentPurpose, ExtFuncData, FuncRef, Function, InstBuilder, Signature,
|
AbiParam, ArgumentPurpose, ExtFuncData, FuncRef, Function, InstBuilder, Signature,
|
||||||
@@ -60,6 +60,8 @@ pub struct FuncEnvironment<'module_environment> {
|
|||||||
vmctx: Option<ir::GlobalValue>,
|
vmctx: Option<ir::GlobalValue>,
|
||||||
|
|
||||||
/// The Cranelift global holding the base address of the signature IDs vector.
|
/// The Cranelift global holding the base address of the signature IDs vector.
|
||||||
|
/// TODO: Now that the bases are just offsets from vmctx rather than loads, we
|
||||||
|
/// can eliminate these base variables.
|
||||||
signature_ids_base: Option<ir::GlobalValue>,
|
signature_ids_base: Option<ir::GlobalValue>,
|
||||||
|
|
||||||
/// The Cranelift global holding the base address of the imported functions table.
|
/// The Cranelift global holding the base address of the imported functions table.
|
||||||
@@ -121,7 +123,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
|||||||
imported_memory32_size_extfunc: None,
|
imported_memory32_size_extfunc: None,
|
||||||
memory_grow_extfunc: None,
|
memory_grow_extfunc: None,
|
||||||
imported_memory_grow_extfunc: None,
|
imported_memory_grow_extfunc: None,
|
||||||
offsets: VMOffsets::new(target_config.pointer_bytes()),
|
offsets: VMOffsets::new(target_config.pointer_bytes(), module),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,11 +143,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
|||||||
self.imported_functions_base.unwrap_or_else(|| {
|
self.imported_functions_base.unwrap_or_else(|| {
|
||||||
let pointer_type = self.pointer_type();
|
let pointer_type = self.pointer_type();
|
||||||
let vmctx = self.vmctx(func);
|
let vmctx = self.vmctx(func);
|
||||||
let new_base = func.create_global_value(ir::GlobalValueData::Load {
|
let new_base = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
base: vmctx,
|
base: vmctx,
|
||||||
offset: Offset32::new(i32::from(self.offsets.vmctx_imported_functions())),
|
offset: Imm64::new(self.offsets.vmctx_imported_functions()),
|
||||||
global_type: pointer_type,
|
global_type: pointer_type,
|
||||||
readonly: true,
|
|
||||||
});
|
});
|
||||||
self.imported_functions_base = Some(new_base);
|
self.imported_functions_base = Some(new_base);
|
||||||
new_base
|
new_base
|
||||||
@@ -156,11 +157,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
|||||||
self.imported_tables_base.unwrap_or_else(|| {
|
self.imported_tables_base.unwrap_or_else(|| {
|
||||||
let pointer_type = self.pointer_type();
|
let pointer_type = self.pointer_type();
|
||||||
let vmctx = self.vmctx(func);
|
let vmctx = self.vmctx(func);
|
||||||
let new_base = func.create_global_value(ir::GlobalValueData::Load {
|
let new_base = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
base: vmctx,
|
base: vmctx,
|
||||||
offset: Offset32::new(i32::from(self.offsets.vmctx_imported_tables())),
|
offset: Imm64::new(self.offsets.vmctx_imported_tables()),
|
||||||
global_type: pointer_type,
|
global_type: pointer_type,
|
||||||
readonly: true,
|
|
||||||
});
|
});
|
||||||
self.imported_tables_base = Some(new_base);
|
self.imported_tables_base = Some(new_base);
|
||||||
new_base
|
new_base
|
||||||
@@ -171,11 +171,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
|||||||
self.imported_memories_base.unwrap_or_else(|| {
|
self.imported_memories_base.unwrap_or_else(|| {
|
||||||
let pointer_type = self.pointer_type();
|
let pointer_type = self.pointer_type();
|
||||||
let vmctx = self.vmctx(func);
|
let vmctx = self.vmctx(func);
|
||||||
let new_base = func.create_global_value(ir::GlobalValueData::Load {
|
let new_base = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
base: vmctx,
|
base: vmctx,
|
||||||
offset: Offset32::new(i32::from(self.offsets.vmctx_imported_memories())),
|
offset: Imm64::new(self.offsets.vmctx_imported_memories()),
|
||||||
global_type: pointer_type,
|
global_type: pointer_type,
|
||||||
readonly: true,
|
|
||||||
});
|
});
|
||||||
self.imported_memories_base = Some(new_base);
|
self.imported_memories_base = Some(new_base);
|
||||||
new_base
|
new_base
|
||||||
@@ -186,11 +185,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
|||||||
self.imported_globals_base.unwrap_or_else(|| {
|
self.imported_globals_base.unwrap_or_else(|| {
|
||||||
let pointer_type = self.pointer_type();
|
let pointer_type = self.pointer_type();
|
||||||
let vmctx = self.vmctx(func);
|
let vmctx = self.vmctx(func);
|
||||||
let new_base = func.create_global_value(ir::GlobalValueData::Load {
|
let new_base = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
base: vmctx,
|
base: vmctx,
|
||||||
offset: Offset32::new(i32::from(self.offsets.vmctx_imported_globals())),
|
offset: Imm64::new(self.offsets.vmctx_imported_globals()),
|
||||||
global_type: pointer_type,
|
global_type: pointer_type,
|
||||||
readonly: true,
|
|
||||||
});
|
});
|
||||||
self.imported_globals_base = Some(new_base);
|
self.imported_globals_base = Some(new_base);
|
||||||
new_base
|
new_base
|
||||||
@@ -201,11 +199,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
|||||||
self.tables_base.unwrap_or_else(|| {
|
self.tables_base.unwrap_or_else(|| {
|
||||||
let pointer_type = self.pointer_type();
|
let pointer_type = self.pointer_type();
|
||||||
let vmctx = self.vmctx(func);
|
let vmctx = self.vmctx(func);
|
||||||
let new_base = func.create_global_value(ir::GlobalValueData::Load {
|
let new_base = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
base: vmctx,
|
base: vmctx,
|
||||||
offset: Offset32::new(i32::from(self.offsets.vmctx_tables())),
|
offset: Imm64::new(self.offsets.vmctx_tables()),
|
||||||
global_type: pointer_type,
|
global_type: pointer_type,
|
||||||
readonly: true,
|
|
||||||
});
|
});
|
||||||
self.tables_base = Some(new_base);
|
self.tables_base = Some(new_base);
|
||||||
new_base
|
new_base
|
||||||
@@ -216,11 +213,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
|||||||
self.memories_base.unwrap_or_else(|| {
|
self.memories_base.unwrap_or_else(|| {
|
||||||
let pointer_type = self.pointer_type();
|
let pointer_type = self.pointer_type();
|
||||||
let vmctx = self.vmctx(func);
|
let vmctx = self.vmctx(func);
|
||||||
let new_base = func.create_global_value(ir::GlobalValueData::Load {
|
let new_base = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
base: vmctx,
|
base: vmctx,
|
||||||
offset: Offset32::new(i32::from(self.offsets.vmctx_memories())),
|
offset: Imm64::new(self.offsets.vmctx_memories()),
|
||||||
global_type: pointer_type,
|
global_type: pointer_type,
|
||||||
readonly: true,
|
|
||||||
});
|
});
|
||||||
self.memories_base = Some(new_base);
|
self.memories_base = Some(new_base);
|
||||||
new_base
|
new_base
|
||||||
@@ -231,11 +227,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
|||||||
self.globals_base.unwrap_or_else(|| {
|
self.globals_base.unwrap_or_else(|| {
|
||||||
let pointer_type = self.pointer_type();
|
let pointer_type = self.pointer_type();
|
||||||
let vmctx = self.vmctx(func);
|
let vmctx = self.vmctx(func);
|
||||||
let new_base = func.create_global_value(ir::GlobalValueData::Load {
|
let new_base = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
base: vmctx,
|
base: vmctx,
|
||||||
offset: Offset32::new(i32::from(self.offsets.vmctx_globals())),
|
offset: Imm64::new(self.offsets.vmctx_globals()),
|
||||||
global_type: pointer_type,
|
global_type: pointer_type,
|
||||||
readonly: true,
|
|
||||||
});
|
});
|
||||||
self.globals_base = Some(new_base);
|
self.globals_base = Some(new_base);
|
||||||
new_base
|
new_base
|
||||||
@@ -246,11 +241,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
|||||||
self.signature_ids_base.unwrap_or_else(|| {
|
self.signature_ids_base.unwrap_or_else(|| {
|
||||||
let pointer_type = self.pointer_type();
|
let pointer_type = self.pointer_type();
|
||||||
let vmctx = self.vmctx(func);
|
let vmctx = self.vmctx(func);
|
||||||
let new_base = func.create_global_value(ir::GlobalValueData::Load {
|
let new_base = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
base: vmctx,
|
base: vmctx,
|
||||||
offset: Offset32::new(i32::from(self.offsets.vmctx_signature_ids())),
|
offset: Imm64::new(self.offsets.vmctx_signature_ids()),
|
||||||
global_type: pointer_type,
|
global_type: pointer_type,
|
||||||
readonly: true,
|
|
||||||
});
|
});
|
||||||
self.signature_ids_base = Some(new_base);
|
self.signature_ids_base = Some(new_base);
|
||||||
new_base
|
new_base
|
||||||
|
|||||||
@@ -2,21 +2,50 @@
|
|||||||
//! module.
|
//! module.
|
||||||
|
|
||||||
use cranelift_codegen::ir;
|
use cranelift_codegen::ir;
|
||||||
|
use cranelift_entity::EntityRef;
|
||||||
use cranelift_wasm::{
|
use cranelift_wasm::{
|
||||||
DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, GlobalIndex, MemoryIndex,
|
DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, GlobalIndex, MemoryIndex,
|
||||||
TableIndex,
|
SignatureIndex, TableIndex,
|
||||||
};
|
};
|
||||||
|
use module::Module;
|
||||||
|
|
||||||
/// This class computes offsets to fields within `VMContext` and other
|
/// This class computes offsets to fields within `VMContext` and other
|
||||||
/// related structs that JIT code accesses directly.
|
/// related structs that JIT code accesses directly.
|
||||||
pub struct VMOffsets {
|
pub struct VMOffsets {
|
||||||
pointer_size: u8,
|
/// The size in bytes of a pointer on the target.
|
||||||
|
pub pointer_size: u8,
|
||||||
|
/// The number of signature declarations in the module.
|
||||||
|
pub num_signature_ids: u64,
|
||||||
|
/// The number of imported functions in the module.
|
||||||
|
pub num_imported_functions: u64,
|
||||||
|
/// The number of imported tables in the module.
|
||||||
|
pub num_imported_tables: u64,
|
||||||
|
/// The number of imported memories in the module.
|
||||||
|
pub num_imported_memories: u64,
|
||||||
|
/// The number of imported globals in the module.
|
||||||
|
pub num_imported_globals: u64,
|
||||||
|
/// The number of defined tables in the module.
|
||||||
|
pub num_defined_tables: u64,
|
||||||
|
/// The number of defined memories in the module.
|
||||||
|
pub num_defined_memories: u64,
|
||||||
|
/// The number of defined globals in the module.
|
||||||
|
pub num_defined_globals: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VMOffsets {
|
impl VMOffsets {
|
||||||
/// Return a new `VMOffsets` instance, for a given pointer size.
|
/// Return a new `VMOffsets` instance, for a given pointer size.
|
||||||
pub fn new(pointer_size: u8) -> Self {
|
pub fn new(pointer_size: u8, module: &Module) -> Self {
|
||||||
Self { pointer_size }
|
Self {
|
||||||
|
pointer_size,
|
||||||
|
num_signature_ids: module.signatures.len() as u64,
|
||||||
|
num_imported_functions: module.imported_funcs.len() as u64,
|
||||||
|
num_imported_tables: module.imported_tables.len() as u64,
|
||||||
|
num_imported_memories: module.imported_memories.len() as u64,
|
||||||
|
num_imported_globals: module.imported_globals.len() as u64,
|
||||||
|
num_defined_tables: module.table_plans.len() as u64,
|
||||||
|
num_defined_memories: module.memory_plans.len() as u64,
|
||||||
|
num_defined_globals: module.globals.len() as u64,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,55 +237,76 @@ impl VMOffsets {
|
|||||||
/// Offsets for `VMContext`.
|
/// Offsets for `VMContext`.
|
||||||
impl VMOffsets {
|
impl VMOffsets {
|
||||||
/// The offset of the `signature_ids` field.
|
/// The offset of the `signature_ids` field.
|
||||||
pub fn vmctx_signature_ids(&self) -> u8 {
|
pub fn vmctx_signature_ids(&self) -> i64 {
|
||||||
0 * self.pointer_size
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The offset of the `tables` field.
|
/// The offset of the `tables` field.
|
||||||
#[allow(clippy::erasing_op)]
|
#[allow(clippy::erasing_op)]
|
||||||
pub fn vmctx_imported_functions(&self) -> u8 {
|
pub fn vmctx_imported_functions(&self) -> i64 {
|
||||||
1 * self.pointer_size
|
self.vmctx_signature_ids()
|
||||||
|
+ self.num_signature_ids as i64 * i64::from(self.size_of_vmshared_signature_index())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The offset of the `tables` field.
|
/// The offset of the `tables` field.
|
||||||
#[allow(clippy::identity_op)]
|
#[allow(clippy::identity_op)]
|
||||||
pub fn vmctx_imported_tables(&self) -> u8 {
|
pub fn vmctx_imported_tables(&self) -> i64 {
|
||||||
2 * self.pointer_size
|
self.vmctx_imported_functions()
|
||||||
|
+ self.num_imported_functions as i64 * i64::from(self.size_of_vmfunction_import())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The offset of the `memories` field.
|
/// The offset of the `memories` field.
|
||||||
pub fn vmctx_imported_memories(&self) -> u8 {
|
pub fn vmctx_imported_memories(&self) -> i64 {
|
||||||
3 * self.pointer_size
|
self.vmctx_imported_tables()
|
||||||
|
+ self.num_imported_tables as i64 * i64::from(self.size_of_vmtable_import())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The offset of the `globals` field.
|
/// The offset of the `globals` field.
|
||||||
pub fn vmctx_imported_globals(&self) -> u8 {
|
pub fn vmctx_imported_globals(&self) -> i64 {
|
||||||
4 * self.pointer_size
|
self.vmctx_imported_memories()
|
||||||
|
+ self.num_imported_memories as i64 * i64::from(self.size_of_vmmemory_import())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The offset of the `tables` field.
|
/// The offset of the `tables` field.
|
||||||
pub fn vmctx_tables(&self) -> u8 {
|
pub fn vmctx_tables(&self) -> i64 {
|
||||||
5 * self.pointer_size
|
self.vmctx_imported_globals()
|
||||||
|
+ self.num_imported_globals as i64 * i64::from(self.size_of_vmglobal_import())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The offset of the `memories` field.
|
/// The offset of the `memories` field.
|
||||||
pub fn vmctx_memories(&self) -> u8 {
|
pub fn vmctx_memories(&self) -> i64 {
|
||||||
6 * self.pointer_size
|
self.vmctx_tables()
|
||||||
|
+ self.num_defined_tables as i64 * i64::from(self.size_of_vmtable_definition())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The offset of the `globals` field.
|
/// The offset of the `globals` field.
|
||||||
pub fn vmctx_globals(&self) -> u8 {
|
pub fn vmctx_globals(&self) -> i64 {
|
||||||
7 * self.pointer_size
|
self.vmctx_memories()
|
||||||
|
+ self.num_defined_memories as i64 * i64::from(self.size_of_vmmemory_definition())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the size of `VMContext`.
|
/// Return the size of the `VMContext` allocation.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn size_of_vmctx(&self) -> u8 {
|
pub fn size_of_vmctx(&self) -> i64 {
|
||||||
8 * self.pointer_size
|
self.vmctx_globals()
|
||||||
|
+ self.num_defined_globals as i64 * i64::from(self.size_of_vmglobal_definition())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the offset from the `signature_ids` pointer to `VMSharedSignatureId` index `index`.
|
||||||
|
pub fn index_vmshared_signature_id(&self, index: SignatureIndex) -> i32 {
|
||||||
|
assert!((index.index() as u64) < self.num_signature_ids);
|
||||||
|
cast::i32(
|
||||||
|
index
|
||||||
|
.as_u32()
|
||||||
|
.checked_mul(u32::from(self.size_of_vmshared_signature_index()))
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the offset from the `imported_functions` pointer to `VMFunctionImport` index `index`.
|
/// Return the offset from the `imported_functions` pointer to `VMFunctionImport` index `index`.
|
||||||
fn index_vmfunction_import(&self, index: FuncIndex) -> i32 {
|
pub fn index_vmfunction_import(&self, index: FuncIndex) -> i32 {
|
||||||
|
assert!((index.index() as u64) < self.num_imported_functions);
|
||||||
cast::i32(
|
cast::i32(
|
||||||
index
|
index
|
||||||
.as_u32()
|
.as_u32()
|
||||||
@@ -267,7 +317,8 @@ impl VMOffsets {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the offset from the `imported_tables` pointer to `VMTableImport` index `index`.
|
/// Return the offset from the `imported_tables` pointer to `VMTableImport` index `index`.
|
||||||
fn index_vmtable_import(&self, index: TableIndex) -> i32 {
|
pub fn index_vmtable_import(&self, index: TableIndex) -> i32 {
|
||||||
|
assert!((index.index() as u64) < self.num_imported_tables);
|
||||||
cast::i32(
|
cast::i32(
|
||||||
index
|
index
|
||||||
.as_u32()
|
.as_u32()
|
||||||
@@ -277,19 +328,9 @@ impl VMOffsets {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the offset from the `tables` pointer to `VMTableDefinition` index `index`.
|
|
||||||
fn index_vmtable_definition(&self, index: DefinedTableIndex) -> i32 {
|
|
||||||
cast::i32(
|
|
||||||
index
|
|
||||||
.as_u32()
|
|
||||||
.checked_mul(u32::from(self.size_of_vmtable_definition()))
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the offset from the `imported_memories` pointer to `VMMemoryImport` index `index`.
|
/// Return the offset from the `imported_memories` pointer to `VMMemoryImport` index `index`.
|
||||||
fn index_vmmemory_import(&self, index: MemoryIndex) -> i32 {
|
pub fn index_vmmemory_import(&self, index: MemoryIndex) -> i32 {
|
||||||
|
assert!((index.index() as u64) < self.num_imported_memories);
|
||||||
cast::i32(
|
cast::i32(
|
||||||
index
|
index
|
||||||
.as_u32()
|
.as_u32()
|
||||||
@@ -299,8 +340,33 @@ impl VMOffsets {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the offset from the `imported_globals` pointer to `VMGlobalImport` index `index`.
|
||||||
|
pub fn index_vmglobal_import(&self, index: GlobalIndex) -> i32 {
|
||||||
|
assert!((index.index() as u64) < self.num_imported_globals);
|
||||||
|
cast::i32(
|
||||||
|
index
|
||||||
|
.as_u32()
|
||||||
|
.checked_mul(u32::from(self.size_of_vmglobal_import()))
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the offset from the `tables` pointer to `VMTableDefinition` index `index`.
|
||||||
|
pub fn index_vmtable_definition(&self, index: DefinedTableIndex) -> i32 {
|
||||||
|
assert!((index.index() as u64) < self.num_defined_tables);
|
||||||
|
cast::i32(
|
||||||
|
index
|
||||||
|
.as_u32()
|
||||||
|
.checked_mul(u32::from(self.size_of_vmtable_definition()))
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the offset from the `memories` pointer to `VMMemoryDefinition` index `index`.
|
/// Return the offset from the `memories` pointer to `VMMemoryDefinition` index `index`.
|
||||||
fn index_vmmemory_definition(&self, index: DefinedMemoryIndex) -> i32 {
|
pub fn index_vmmemory_definition(&self, index: DefinedMemoryIndex) -> i32 {
|
||||||
|
assert!((index.index() as u64) < self.num_defined_memories);
|
||||||
cast::i32(
|
cast::i32(
|
||||||
index
|
index
|
||||||
.as_u32()
|
.as_u32()
|
||||||
@@ -310,12 +376,14 @@ impl VMOffsets {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the offset from the `imported_globals` pointer to `VMGlobalImport` index `index`.
|
/// Return the offset from the `globals` pointer to the `VMGlobalDefinition`
|
||||||
fn index_vmglobal_import(&self, index: GlobalIndex) -> i32 {
|
/// index `index`.
|
||||||
|
pub fn index_vmglobal_definition(&self, index: DefinedGlobalIndex) -> i32 {
|
||||||
|
assert!((index.index() as u64) < self.num_defined_globals);
|
||||||
cast::i32(
|
cast::i32(
|
||||||
index
|
index
|
||||||
.as_u32()
|
.as_u32()
|
||||||
.checked_mul(u32::from(self.size_of_vmglobal_import()))
|
.checked_mul(u32::from(self.size_of_vmglobal_definition()))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -400,16 +468,4 @@ impl VMOffsets {
|
|||||||
.checked_add(i32::from(self.vmglobal_import_from()))
|
.checked_add(i32::from(self.vmglobal_import_from()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the offset from the `globals` pointer to the `VMGlobalDefinition`
|
|
||||||
/// index `index`.
|
|
||||||
pub fn index_vmglobal_definition(&self, index: DefinedGlobalIndex) -> i32 {
|
|
||||||
cast::i32(
|
|
||||||
index
|
|
||||||
.as_u32()
|
|
||||||
.checked_mul(u32::from(self.size_of_vmglobal_definition()))
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ impl CompiledModule {
|
|||||||
/// Note that if only one instance of this module is needed, it may be more
|
/// Note that if only one instance of this module is needed, it may be more
|
||||||
/// efficient to call the top-level `instantiate`, since that avoids copying
|
/// efficient to call the top-level `instantiate`, since that avoids copying
|
||||||
/// the data initializers.
|
/// the data initializers.
|
||||||
pub fn instantiate(&mut self) -> Result<Box<Instance>, InstantiationError> {
|
pub fn instantiate(&mut self) -> Result<Instance, InstantiationError> {
|
||||||
let data_initializers = self
|
let data_initializers = self
|
||||||
.data_initializers
|
.data_initializers
|
||||||
.iter()
|
.iter()
|
||||||
@@ -205,7 +205,7 @@ pub fn instantiate(
|
|||||||
compiler: &mut Compiler,
|
compiler: &mut Compiler,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
resolver: &mut Resolver,
|
resolver: &mut Resolver,
|
||||||
) -> Result<Box<Instance>, SetupError> {
|
) -> Result<Instance, SetupError> {
|
||||||
let raw = RawCompiledModule::new(compiler, data, resolver)?;
|
let raw = RawCompiledModule::new(compiler, data, resolver)?;
|
||||||
|
|
||||||
Instance::new(
|
Instance::new(
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ use action::{ActionError, ActionOutcome, RuntimeValue};
|
|||||||
use compiler::Compiler;
|
use compiler::Compiler;
|
||||||
use cranelift_entity::PrimaryMap;
|
use cranelift_entity::PrimaryMap;
|
||||||
use resolver::Resolver;
|
use resolver::Resolver;
|
||||||
use std::boxed::Box;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::string::String;
|
use std::string::String;
|
||||||
use wasmtime_runtime::{Export, Instance};
|
use wasmtime_runtime::{Export, Instance};
|
||||||
@@ -26,7 +25,7 @@ pub struct Namespace {
|
|||||||
names: HashMap<String, InstanceIndex>,
|
names: HashMap<String, InstanceIndex>,
|
||||||
|
|
||||||
/// The instances, available by index.
|
/// The instances, available by index.
|
||||||
instances: PrimaryMap<InstanceIndex, Box<Instance>>,
|
instances: PrimaryMap<InstanceIndex, Instance>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Namespace {
|
impl Namespace {
|
||||||
@@ -40,11 +39,7 @@ impl Namespace {
|
|||||||
|
|
||||||
/// Install a new `Instance` in this `Namespace`, optionally with the
|
/// Install a new `Instance` in this `Namespace`, optionally with the
|
||||||
/// given name, and return its index.
|
/// given name, and return its index.
|
||||||
pub fn instance(
|
pub fn instance(&mut self, instance_name: Option<&str>, instance: Instance) -> InstanceIndex {
|
||||||
&mut self,
|
|
||||||
instance_name: Option<&str>,
|
|
||||||
instance: Box<Instance>,
|
|
||||||
) -> InstanceIndex {
|
|
||||||
let index = self.instances.push(instance);
|
let index = self.instances.push(instance);
|
||||||
if let Some(instance_name) = instance_name {
|
if let Some(instance_name) = instance_name {
|
||||||
self.names.insert(instance_name.into(), index);
|
self.names.insert(instance_name.into(), index);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -94,10 +94,10 @@ pub unsafe extern "C" fn wasmtime_memory32_grow(
|
|||||||
memory_index: u32,
|
memory_index: u32,
|
||||||
vmctx: *mut VMContext,
|
vmctx: *mut VMContext,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
let instance = (&mut *vmctx).instance();
|
let instance_contents = (&mut *vmctx).instance_contents();
|
||||||
let memory_index = DefinedMemoryIndex::from_u32(memory_index);
|
let memory_index = DefinedMemoryIndex::from_u32(memory_index);
|
||||||
|
|
||||||
instance
|
instance_contents
|
||||||
.memory_grow(memory_index, delta)
|
.memory_grow(memory_index, delta)
|
||||||
.unwrap_or(u32::max_value())
|
.unwrap_or(u32::max_value())
|
||||||
}
|
}
|
||||||
@@ -109,30 +109,21 @@ pub unsafe extern "C" fn wasmtime_imported_memory32_grow(
|
|||||||
memory_index: u32,
|
memory_index: u32,
|
||||||
vmctx: *mut VMContext,
|
vmctx: *mut VMContext,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
let instance = (&mut *vmctx).instance();
|
let instance_contents = (&mut *vmctx).instance_contents();
|
||||||
assert!(
|
|
||||||
(memory_index as usize) < instance.num_imported_memories(),
|
|
||||||
"imported memory index for memory.grow out of bounds"
|
|
||||||
);
|
|
||||||
|
|
||||||
let memory_index = MemoryIndex::from_u32(memory_index);
|
let memory_index = MemoryIndex::from_u32(memory_index);
|
||||||
let import = instance.vmctx().imported_memory(memory_index);
|
|
||||||
let foreign_instance = (&mut *import.vmctx).instance();
|
|
||||||
let foreign_memory = &mut *import.from;
|
|
||||||
let foreign_index = foreign_instance.vmctx().memory_index(foreign_memory);
|
|
||||||
|
|
||||||
foreign_instance
|
instance_contents
|
||||||
.memory_grow(foreign_index, delta)
|
.imported_memory_grow(memory_index, delta)
|
||||||
.unwrap_or(u32::max_value())
|
.unwrap_or(u32::max_value())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation of memory.size for locally-defined 32-bit memories.
|
/// Implementation of memory.size for locally-defined 32-bit memories.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasmtime_memory32_size(memory_index: u32, vmctx: *mut VMContext) -> u32 {
|
pub unsafe extern "C" fn wasmtime_memory32_size(memory_index: u32, vmctx: *mut VMContext) -> u32 {
|
||||||
let instance = (&mut *vmctx).instance();
|
let instance_contents = (&mut *vmctx).instance_contents();
|
||||||
let memory_index = DefinedMemoryIndex::from_u32(memory_index);
|
let memory_index = DefinedMemoryIndex::from_u32(memory_index);
|
||||||
|
|
||||||
instance.memory_size(memory_index)
|
instance_contents.memory_size(memory_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation of memory.size for imported 32-bit memories.
|
/// Implementation of memory.size for imported 32-bit memories.
|
||||||
@@ -141,17 +132,8 @@ pub unsafe extern "C" fn wasmtime_imported_memory32_size(
|
|||||||
memory_index: u32,
|
memory_index: u32,
|
||||||
vmctx: *mut VMContext,
|
vmctx: *mut VMContext,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
let instance = (&mut *vmctx).instance();
|
let instance_contents = (&mut *vmctx).instance_contents();
|
||||||
assert!(
|
|
||||||
(memory_index as usize) < instance.num_imported_memories(),
|
|
||||||
"imported memory index for memory.grow out of bounds"
|
|
||||||
);
|
|
||||||
|
|
||||||
let memory_index = MemoryIndex::from_u32(memory_index);
|
let memory_index = MemoryIndex::from_u32(memory_index);
|
||||||
let import = instance.vmctx().imported_memory(memory_index);
|
|
||||||
let foreign_instance = (&mut *import.vmctx).instance();
|
|
||||||
let foreign_memory = &mut *import.from;
|
|
||||||
let foreign_index = foreign_instance.vmctx().memory_index(foreign_memory);
|
|
||||||
|
|
||||||
foreign_instance.memory_size(foreign_index)
|
instance_contents.imported_memory_size(memory_index)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,9 +94,9 @@ pub extern "C" fn wasmtime_init_finish(vmctx: &mut VMContext) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let instance = unsafe { vmctx.instance() };
|
let instance_contents = unsafe { vmctx.instance_contents() };
|
||||||
let have_signal_handlers = TRAP_CONTEXT.with(|cx| cx.borrow().haveSignalHandlers);
|
let have_signal_handlers = TRAP_CONTEXT.with(|cx| cx.borrow().haveSignalHandlers);
|
||||||
if !have_signal_handlers && instance.needs_signal_handlers() {
|
if !have_signal_handlers && instance_contents.needs_signal_handlers() {
|
||||||
panic!("failed to install signal handlers");
|
panic!("failed to install signal handlers");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,8 @@
|
|||||||
//! This file declares `VMContext` and several related structs which contain
|
//! This file declares `VMContext` and several related structs which contain
|
||||||
//! fields that compiled wasm code accesses directly.
|
//! fields that compiled wasm code accesses directly.
|
||||||
|
|
||||||
use cranelift_entity::EntityRef;
|
use instance::InstanceContents;
|
||||||
use cranelift_wasm::{
|
use std::{ptr, u32};
|
||||||
DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, GlobalIndex, MemoryIndex,
|
|
||||||
TableIndex,
|
|
||||||
};
|
|
||||||
use instance::Instance;
|
|
||||||
use std::{mem, ptr, u32};
|
|
||||||
|
|
||||||
/// An imported function.
|
/// An imported function.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
@@ -24,11 +19,12 @@ pub struct VMFunctionImport {
|
|||||||
mod test_vmfunction_import {
|
mod test_vmfunction_import {
|
||||||
use super::VMFunctionImport;
|
use super::VMFunctionImport;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use wasmtime_environ::VMOffsets;
|
use wasmtime_environ::{Module, VMOffsets};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_vmfunction_import_offsets() {
|
fn check_vmfunction_import_offsets() {
|
||||||
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
|
let module = Module::new();
|
||||||
|
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
size_of::<VMFunctionImport>(),
|
size_of::<VMFunctionImport>(),
|
||||||
usize::from(offsets.size_of_vmfunction_import())
|
usize::from(offsets.size_of_vmfunction_import())
|
||||||
@@ -78,11 +74,12 @@ pub struct VMTableImport {
|
|||||||
mod test_vmtable_import {
|
mod test_vmtable_import {
|
||||||
use super::VMTableImport;
|
use super::VMTableImport;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use wasmtime_environ::VMOffsets;
|
use wasmtime_environ::{Module, VMOffsets};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_vmtable_import_offsets() {
|
fn check_vmtable_import_offsets() {
|
||||||
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
|
let module = Module::new();
|
||||||
|
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
size_of::<VMTableImport>(),
|
size_of::<VMTableImport>(),
|
||||||
usize::from(offsets.size_of_vmtable_import())
|
usize::from(offsets.size_of_vmtable_import())
|
||||||
@@ -114,11 +111,12 @@ pub struct VMMemoryImport {
|
|||||||
mod test_vmmemory_import {
|
mod test_vmmemory_import {
|
||||||
use super::VMMemoryImport;
|
use super::VMMemoryImport;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use wasmtime_environ::VMOffsets;
|
use wasmtime_environ::{Module, VMOffsets};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_vmmemory_import_offsets() {
|
fn check_vmmemory_import_offsets() {
|
||||||
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
|
let module = Module::new();
|
||||||
|
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
size_of::<VMMemoryImport>(),
|
size_of::<VMMemoryImport>(),
|
||||||
usize::from(offsets.size_of_vmmemory_import())
|
usize::from(offsets.size_of_vmmemory_import())
|
||||||
@@ -147,11 +145,12 @@ pub struct VMGlobalImport {
|
|||||||
mod test_vmglobal_import {
|
mod test_vmglobal_import {
|
||||||
use super::VMGlobalImport;
|
use super::VMGlobalImport;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use wasmtime_environ::VMOffsets;
|
use wasmtime_environ::{Module, VMOffsets};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_vmglobal_import_offsets() {
|
fn check_vmglobal_import_offsets() {
|
||||||
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
|
let module = Module::new();
|
||||||
|
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
size_of::<VMGlobalImport>(),
|
size_of::<VMGlobalImport>(),
|
||||||
usize::from(offsets.size_of_vmglobal_import())
|
usize::from(offsets.size_of_vmglobal_import())
|
||||||
@@ -180,11 +179,12 @@ pub struct VMMemoryDefinition {
|
|||||||
mod test_vmmemory_definition {
|
mod test_vmmemory_definition {
|
||||||
use super::VMMemoryDefinition;
|
use super::VMMemoryDefinition;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use wasmtime_environ::VMOffsets;
|
use wasmtime_environ::{Module, VMOffsets};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_vmmemory_definition_offsets() {
|
fn check_vmmemory_definition_offsets() {
|
||||||
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
|
let module = Module::new();
|
||||||
|
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
size_of::<VMMemoryDefinition>(),
|
size_of::<VMMemoryDefinition>(),
|
||||||
usize::from(offsets.size_of_vmmemory_definition())
|
usize::from(offsets.size_of_vmmemory_definition())
|
||||||
@@ -222,11 +222,12 @@ pub struct VMTableDefinition {
|
|||||||
mod test_vmtable_definition {
|
mod test_vmtable_definition {
|
||||||
use super::VMTableDefinition;
|
use super::VMTableDefinition;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use wasmtime_environ::VMOffsets;
|
use wasmtime_environ::{Module, VMOffsets};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_vmtable_definition_offsets() {
|
fn check_vmtable_definition_offsets() {
|
||||||
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
|
let module = Module::new();
|
||||||
|
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
size_of::<VMTableDefinition>(),
|
size_of::<VMTableDefinition>(),
|
||||||
usize::from(offsets.size_of_vmtable_definition())
|
usize::from(offsets.size_of_vmtable_definition())
|
||||||
@@ -257,7 +258,7 @@ pub struct VMGlobalDefinition {
|
|||||||
mod test_vmglobal_definition {
|
mod test_vmglobal_definition {
|
||||||
use super::VMGlobalDefinition;
|
use super::VMGlobalDefinition;
|
||||||
use std::mem::{align_of, size_of};
|
use std::mem::{align_of, size_of};
|
||||||
use wasmtime_environ::VMOffsets;
|
use wasmtime_environ::{Module, VMOffsets};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_vmglobal_definition_alignment() {
|
fn check_vmglobal_definition_alignment() {
|
||||||
@@ -269,7 +270,8 @@ mod test_vmglobal_definition {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_vmglobal_definition_offsets() {
|
fn check_vmglobal_definition_offsets() {
|
||||||
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
|
let module = Module::new();
|
||||||
|
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
size_of::<VMGlobalDefinition>(),
|
size_of::<VMGlobalDefinition>(),
|
||||||
usize::from(offsets.size_of_vmglobal_definition())
|
usize::from(offsets.size_of_vmglobal_definition())
|
||||||
@@ -390,11 +392,12 @@ pub struct VMSharedSignatureIndex(u32);
|
|||||||
mod test_vmshared_signature_index {
|
mod test_vmshared_signature_index {
|
||||||
use super::VMSharedSignatureIndex;
|
use super::VMSharedSignatureIndex;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use wasmtime_environ::VMOffsets;
|
use wasmtime_environ::{Module, VMOffsets};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_vmshared_signature_index() {
|
fn check_vmshared_signature_index() {
|
||||||
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
|
let module = Module::new();
|
||||||
|
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
size_of::<VMSharedSignatureIndex>(),
|
size_of::<VMSharedSignatureIndex>(),
|
||||||
usize::from(offsets.size_of_vmshared_signature_index())
|
usize::from(offsets.size_of_vmshared_signature_index())
|
||||||
@@ -425,11 +428,12 @@ pub struct VMCallerCheckedAnyfunc {
|
|||||||
mod test_vmcaller_checked_anyfunc {
|
mod test_vmcaller_checked_anyfunc {
|
||||||
use super::VMCallerCheckedAnyfunc;
|
use super::VMCallerCheckedAnyfunc;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use wasmtime_environ::VMOffsets;
|
use wasmtime_environ::{Module, VMOffsets};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_vmcaller_checked_anyfunc_offsets() {
|
fn check_vmcaller_checked_anyfunc_offsets() {
|
||||||
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
|
let module = Module::new();
|
||||||
|
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
size_of::<VMCallerCheckedAnyfunc>(),
|
size_of::<VMCallerCheckedAnyfunc>(),
|
||||||
usize::from(offsets.size_of_vmcaller_checked_anyfunc())
|
usize::from(offsets.size_of_vmcaller_checked_anyfunc())
|
||||||
@@ -460,186 +464,23 @@ impl Default for VMCallerCheckedAnyfunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The VM "context", which is pointed to by the `vmctx` arg in Cranelift.
|
/// The VM "context", which is pointed to by the `vmctx` arg in Cranelift.
|
||||||
/// This has pointers to the globals, memories, tables, and other runtime
|
/// This has information about globals, memories, tables, and other runtime
|
||||||
/// state associated with the current instance.
|
/// state associated with the current instance.
|
||||||
///
|
///
|
||||||
/// TODO: The number of memories, globals, tables, and signature IDs does
|
/// The struct here is empty, as the sizes of these fields are dynamic, and
|
||||||
/// not change dynamically, and pointer arrays are not indexed dynamically,
|
/// we can't describe them in Rust's type system. Sufficient memory is
|
||||||
/// so these fields could all be contiguously allocated.
|
/// allocated at runtime.
|
||||||
|
///
|
||||||
|
/// TODO: We could move the globals into the `vmctx` allocation too.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct VMContext {
|
pub struct VMContext {}
|
||||||
/// Signature identifiers for signature-checking indirect calls.
|
|
||||||
signature_ids: *mut VMSharedSignatureIndex,
|
|
||||||
|
|
||||||
/// A pointer to an array of `*const VMFunctionBody` instances, indexed by `FuncIndex`.
|
|
||||||
imported_functions: *const VMFunctionImport,
|
|
||||||
|
|
||||||
/// A pointer to an array of `VMTableImport` instances, indexed by `TableIndex`.
|
|
||||||
imported_tables: *const VMTableImport,
|
|
||||||
|
|
||||||
/// A pointer to an array of `VMMemoryImport` instances, indexed by `MemoryIndex`.
|
|
||||||
imported_memories: *const VMMemoryImport,
|
|
||||||
|
|
||||||
/// A pointer to an array of `VMGlobalImport` instances, indexed by `GlobalIndex`.
|
|
||||||
imported_globals: *const VMGlobalImport,
|
|
||||||
|
|
||||||
/// A pointer to an array of locally-defined `VMTableDefinition` instances,
|
|
||||||
/// indexed by `DefinedTableIndex`.
|
|
||||||
tables: *mut VMTableDefinition,
|
|
||||||
|
|
||||||
/// A pointer to an array of locally-defined `VMMemoryDefinition` instances,
|
|
||||||
/// indexed by `DefinedMemoryIndex`.
|
|
||||||
memories: *mut VMMemoryDefinition,
|
|
||||||
|
|
||||||
/// A pointer to an array of locally-defined `VMGlobalDefinition` instances,
|
|
||||||
/// indexed by `DefinedGlobalIndex`.
|
|
||||||
globals: *mut VMGlobalDefinition,
|
|
||||||
// If more elements are added here, remember to add offset_of tests below!
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::VMContext;
|
|
||||||
use std::mem::size_of;
|
|
||||||
use wasmtime_environ::VMOffsets;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn check_vmctx_offsets() {
|
|
||||||
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
|
|
||||||
assert_eq!(size_of::<VMContext>(), usize::from(offsets.size_of_vmctx()));
|
|
||||||
assert_eq!(
|
|
||||||
offset_of!(VMContext, signature_ids),
|
|
||||||
usize::from(offsets.vmctx_signature_ids())
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
offset_of!(VMContext, imported_functions),
|
|
||||||
usize::from(offsets.vmctx_imported_functions())
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
offset_of!(VMContext, imported_tables),
|
|
||||||
usize::from(offsets.vmctx_imported_tables())
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
offset_of!(VMContext, imported_memories),
|
|
||||||
usize::from(offsets.vmctx_imported_memories())
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
offset_of!(VMContext, imported_globals),
|
|
||||||
usize::from(offsets.vmctx_imported_globals())
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
offset_of!(VMContext, tables),
|
|
||||||
usize::from(offsets.vmctx_tables())
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
offset_of!(VMContext, memories),
|
|
||||||
usize::from(offsets.vmctx_memories())
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
offset_of!(VMContext, globals),
|
|
||||||
usize::from(offsets.vmctx_globals())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VMContext {
|
impl VMContext {
|
||||||
/// Create a new `VMContext` instance.
|
|
||||||
pub fn new(
|
|
||||||
imported_functions: *const VMFunctionImport,
|
|
||||||
imported_tables: *const VMTableImport,
|
|
||||||
imported_memories: *const VMMemoryImport,
|
|
||||||
imported_globals: *const VMGlobalImport,
|
|
||||||
tables: *mut VMTableDefinition,
|
|
||||||
memories: *mut VMMemoryDefinition,
|
|
||||||
globals: *mut VMGlobalDefinition,
|
|
||||||
signature_ids: *mut VMSharedSignatureIndex,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
imported_functions,
|
|
||||||
imported_tables,
|
|
||||||
imported_memories,
|
|
||||||
imported_globals,
|
|
||||||
tables,
|
|
||||||
memories,
|
|
||||||
globals,
|
|
||||||
signature_ids,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a reference to imported function `index`.
|
|
||||||
pub unsafe fn imported_function(&self, index: FuncIndex) -> &VMFunctionImport {
|
|
||||||
&*self.imported_functions.add(index.index())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a reference to imported table `index`.
|
|
||||||
pub unsafe fn imported_table(&self, index: TableIndex) -> &VMTableImport {
|
|
||||||
&*self.imported_tables.add(index.index())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a reference to imported memory `index`.
|
|
||||||
pub unsafe fn imported_memory(&self, index: MemoryIndex) -> &VMMemoryImport {
|
|
||||||
&*self.imported_memories.add(index.index())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a reference to imported global `index`.
|
|
||||||
pub unsafe fn imported_global(&self, index: GlobalIndex) -> &VMGlobalImport {
|
|
||||||
&*self.imported_globals.add(index.index())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a reference to locally-defined table `index`.
|
|
||||||
pub unsafe fn table(&self, index: DefinedTableIndex) -> &VMTableDefinition {
|
|
||||||
&*self.tables.add(index.index())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a mutable reference to locally-defined table `index`.
|
|
||||||
pub unsafe fn table_mut(&mut self, index: DefinedTableIndex) -> &mut VMTableDefinition {
|
|
||||||
&mut *self.tables.add(index.index())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a reference to locally-defined linear memory `index`.
|
|
||||||
pub unsafe fn memory(&self, index: DefinedMemoryIndex) -> &VMMemoryDefinition {
|
|
||||||
&*self.memories.add(index.index())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a mutable reference to locally-defined linear memory `index`.
|
|
||||||
pub unsafe fn memory_mut(&mut self, index: DefinedMemoryIndex) -> &mut VMMemoryDefinition {
|
|
||||||
&mut *self.memories.add(index.index())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a reference to locally-defined global variable `index`.
|
|
||||||
pub unsafe fn global(&self, index: DefinedGlobalIndex) -> &VMGlobalDefinition {
|
|
||||||
&*self.globals.add(index.index())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a mutable reference to locally-defined global variable `index`.
|
|
||||||
pub unsafe fn global_mut(&mut self, index: DefinedGlobalIndex) -> &mut VMGlobalDefinition {
|
|
||||||
&mut *self.globals.add(index.index())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a mutable reference to the associated `Instance`.
|
/// Return a mutable reference to the associated `Instance`.
|
||||||
#[allow(clippy::cast_ptr_alignment)]
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
pub unsafe fn instance(&mut self) -> &mut Instance {
|
pub(crate) unsafe fn instance_contents(&mut self) -> &mut InstanceContents {
|
||||||
&mut *((self as *mut Self as *mut u8).offset(-Instance::vmctx_offset()) as *mut Instance)
|
&mut *((self as *mut Self as *mut u8).offset(-InstanceContents::vmctx_offset())
|
||||||
}
|
as *mut InstanceContents)
|
||||||
|
|
||||||
/// Return the table index for the given `VMTableDefinition`.
|
|
||||||
pub fn table_index(&self, table: &mut VMTableDefinition) -> DefinedTableIndex {
|
|
||||||
// TODO: Use `offset_from` once it stablizes.
|
|
||||||
let begin = self.tables;
|
|
||||||
let end: *mut VMTableDefinition = table;
|
|
||||||
DefinedTableIndex::new(
|
|
||||||
(end as usize - begin as usize) / mem::size_of::<VMTableDefinition>(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the memory index for the given `VMMemoryDefinition`.
|
|
||||||
pub fn memory_index(&self, memory: &mut VMMemoryDefinition) -> DefinedMemoryIndex {
|
|
||||||
// TODO: Use `offset_from` once it stablizes.
|
|
||||||
let begin = self.memories;
|
|
||||||
let end: *mut VMMemoryDefinition = memory;
|
|
||||||
DefinedMemoryIndex::new(
|
|
||||||
(end as usize - begin as usize) / mem::size_of::<VMMemoryDefinition>(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ extern "C" fn spectest_print_f64_f64(x: f64, y: f64) {
|
|||||||
|
|
||||||
/// Return an instance implementing the "spectest" interface used in the
|
/// Return an instance implementing the "spectest" interface used in the
|
||||||
/// spec testsuite.
|
/// spec testsuite.
|
||||||
pub fn instantiate_spectest() -> Result<Box<Instance>, InstantiationError> {
|
pub fn instantiate_spectest() -> Result<Instance, InstantiationError> {
|
||||||
let call_conv = isa::CallConv::triple_default(&HOST);
|
let call_conv = isa::CallConv::triple_default(&HOST);
|
||||||
let pointer_type = types::Type::triple_pointer_type(&HOST);
|
let pointer_type = types::Type::triple_pointer_type(&HOST);
|
||||||
let mut module = Module::new();
|
let mut module = Module::new();
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ impl WastContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn instantiate(&mut self, module: ModuleBinary) -> Result<Box<Instance>, SetupError> {
|
fn instantiate(&mut self, module: ModuleBinary) -> Result<Instance, SetupError> {
|
||||||
let data = module.into_vec();
|
let data = module.into_vec();
|
||||||
|
|
||||||
self.validate(&data).map_err(SetupError::Validate)?;
|
self.validate(&data).map_err(SetupError::Validate)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user