Restructure VMContext to eliminate a level of indirection.

This commit is contained in:
Dan Gohman
2019-01-03 11:02:37 -08:00
parent ff6776fe10
commit 3270369a69
10 changed files with 774 additions and 621 deletions

View File

@@ -2,7 +2,7 @@ use cast;
use cranelift_codegen::cursor::FuncCursor;
use cranelift_codegen::ir;
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::{
AbiParam, ArgumentPurpose, ExtFuncData, FuncRef, Function, InstBuilder, Signature,
@@ -60,6 +60,8 @@ pub struct FuncEnvironment<'module_environment> {
vmctx: Option<ir::GlobalValue>,
/// 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>,
/// 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,
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(|| {
let pointer_type = self.pointer_type();
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,
offset: Offset32::new(i32::from(self.offsets.vmctx_imported_functions())),
offset: Imm64::new(self.offsets.vmctx_imported_functions()),
global_type: pointer_type,
readonly: true,
});
self.imported_functions_base = Some(new_base);
new_base
@@ -156,11 +157,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
self.imported_tables_base.unwrap_or_else(|| {
let pointer_type = self.pointer_type();
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,
offset: Offset32::new(i32::from(self.offsets.vmctx_imported_tables())),
offset: Imm64::new(self.offsets.vmctx_imported_tables()),
global_type: pointer_type,
readonly: true,
});
self.imported_tables_base = Some(new_base);
new_base
@@ -171,11 +171,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
self.imported_memories_base.unwrap_or_else(|| {
let pointer_type = self.pointer_type();
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,
offset: Offset32::new(i32::from(self.offsets.vmctx_imported_memories())),
offset: Imm64::new(self.offsets.vmctx_imported_memories()),
global_type: pointer_type,
readonly: true,
});
self.imported_memories_base = Some(new_base);
new_base
@@ -186,11 +185,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
self.imported_globals_base.unwrap_or_else(|| {
let pointer_type = self.pointer_type();
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,
offset: Offset32::new(i32::from(self.offsets.vmctx_imported_globals())),
offset: Imm64::new(self.offsets.vmctx_imported_globals()),
global_type: pointer_type,
readonly: true,
});
self.imported_globals_base = Some(new_base);
new_base
@@ -201,11 +199,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
self.tables_base.unwrap_or_else(|| {
let pointer_type = self.pointer_type();
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,
offset: Offset32::new(i32::from(self.offsets.vmctx_tables())),
offset: Imm64::new(self.offsets.vmctx_tables()),
global_type: pointer_type,
readonly: true,
});
self.tables_base = Some(new_base);
new_base
@@ -216,11 +213,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
self.memories_base.unwrap_or_else(|| {
let pointer_type = self.pointer_type();
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,
offset: Offset32::new(i32::from(self.offsets.vmctx_memories())),
offset: Imm64::new(self.offsets.vmctx_memories()),
global_type: pointer_type,
readonly: true,
});
self.memories_base = Some(new_base);
new_base
@@ -231,11 +227,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
self.globals_base.unwrap_or_else(|| {
let pointer_type = self.pointer_type();
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,
offset: Offset32::new(i32::from(self.offsets.vmctx_globals())),
offset: Imm64::new(self.offsets.vmctx_globals()),
global_type: pointer_type,
readonly: true,
});
self.globals_base = Some(new_base);
new_base
@@ -246,11 +241,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
self.signature_ids_base.unwrap_or_else(|| {
let pointer_type = self.pointer_type();
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,
offset: Offset32::new(i32::from(self.offsets.vmctx_signature_ids())),
offset: Imm64::new(self.offsets.vmctx_signature_ids()),
global_type: pointer_type,
readonly: true,
});
self.signature_ids_base = Some(new_base);
new_base

View File

@@ -2,21 +2,50 @@
//! module.
use cranelift_codegen::ir;
use cranelift_entity::EntityRef;
use cranelift_wasm::{
DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, GlobalIndex, MemoryIndex,
TableIndex,
SignatureIndex, TableIndex,
};
use module::Module;
/// This class computes offsets to fields within `VMContext` and other
/// related structs that JIT code accesses directly.
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 {
/// Return a new `VMOffsets` instance, for a given pointer size.
pub fn new(pointer_size: u8) -> Self {
Self { pointer_size }
pub fn new(pointer_size: u8, module: &Module) -> Self {
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`.
impl VMOffsets {
/// The offset of the `signature_ids` field.
pub fn vmctx_signature_ids(&self) -> u8 {
0 * self.pointer_size
pub fn vmctx_signature_ids(&self) -> i64 {
0
}
/// The offset of the `tables` field.
#[allow(clippy::erasing_op)]
pub fn vmctx_imported_functions(&self) -> u8 {
1 * self.pointer_size
pub fn vmctx_imported_functions(&self) -> i64 {
self.vmctx_signature_ids()
+ self.num_signature_ids as i64 * i64::from(self.size_of_vmshared_signature_index())
}
/// The offset of the `tables` field.
#[allow(clippy::identity_op)]
pub fn vmctx_imported_tables(&self) -> u8 {
2 * self.pointer_size
pub fn vmctx_imported_tables(&self) -> i64 {
self.vmctx_imported_functions()
+ self.num_imported_functions as i64 * i64::from(self.size_of_vmfunction_import())
}
/// The offset of the `memories` field.
pub fn vmctx_imported_memories(&self) -> u8 {
3 * self.pointer_size
pub fn vmctx_imported_memories(&self) -> i64 {
self.vmctx_imported_tables()
+ self.num_imported_tables as i64 * i64::from(self.size_of_vmtable_import())
}
/// The offset of the `globals` field.
pub fn vmctx_imported_globals(&self) -> u8 {
4 * self.pointer_size
pub fn vmctx_imported_globals(&self) -> i64 {
self.vmctx_imported_memories()
+ self.num_imported_memories as i64 * i64::from(self.size_of_vmmemory_import())
}
/// The offset of the `tables` field.
pub fn vmctx_tables(&self) -> u8 {
5 * self.pointer_size
pub fn vmctx_tables(&self) -> i64 {
self.vmctx_imported_globals()
+ self.num_imported_globals as i64 * i64::from(self.size_of_vmglobal_import())
}
/// The offset of the `memories` field.
pub fn vmctx_memories(&self) -> u8 {
6 * self.pointer_size
pub fn vmctx_memories(&self) -> i64 {
self.vmctx_tables()
+ self.num_defined_tables as i64 * i64::from(self.size_of_vmtable_definition())
}
/// The offset of the `globals` field.
pub fn vmctx_globals(&self) -> u8 {
7 * self.pointer_size
pub fn vmctx_globals(&self) -> i64 {
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)]
pub fn size_of_vmctx(&self) -> u8 {
8 * self.pointer_size
pub fn size_of_vmctx(&self) -> i64 {
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`.
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(
index
.as_u32()
@@ -267,7 +317,8 @@ impl VMOffsets {
}
/// 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(
index
.as_u32()
@@ -277,19 +328,9 @@ impl VMOffsets {
.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`.
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(
index
.as_u32()
@@ -299,8 +340,33 @@ impl VMOffsets {
.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`.
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(
index
.as_u32()
@@ -310,12 +376,14 @@ impl VMOffsets {
.unwrap()
}
/// Return the offset from the `imported_globals` pointer to `VMGlobalImport` index `index`.
fn index_vmglobal_import(&self, index: GlobalIndex) -> i32 {
/// Return the offset from the `globals` pointer to the `VMGlobalDefinition`
/// index `index`.
pub fn index_vmglobal_definition(&self, index: DefinedGlobalIndex) -> i32 {
assert!((index.index() as u64) < self.num_defined_globals);
cast::i32(
index
.as_u32()
.checked_mul(u32::from(self.size_of_vmglobal_import()))
.checked_mul(u32::from(self.size_of_vmglobal_definition()))
.unwrap(),
)
.unwrap()
@@ -400,16 +468,4 @@ impl VMOffsets {
.checked_add(i32::from(self.vmglobal_import_from()))
.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()
}
}