mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-12 22:05:33 +00:00
Metering for LLVM.
This commit is contained in:
parent
fd8675324c
commit
b834b4ff36
@ -24,6 +24,7 @@ use wasmer_runtime_core::{
|
||||
CacheGen, RunnableModule,
|
||||
},
|
||||
cache::Error as CacheError,
|
||||
codegen::BkptInfo,
|
||||
module::ModuleInfo,
|
||||
structures::TypedIndex,
|
||||
typed_func::{Wasm, WasmTrapInfo},
|
||||
@ -190,6 +191,8 @@ fn get_callbacks() -> Callbacks {
|
||||
|
||||
fn_name!("vm.exception.trap") => throw_trap as _,
|
||||
|
||||
fn_name!("vm.breakpoint") => vm_breakpoint as _,
|
||||
|
||||
_ => ptr::null(),
|
||||
}
|
||||
}
|
||||
@ -209,6 +212,19 @@ fn get_callbacks() -> Callbacks {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn vm_breakpoint(_ctx: &mut vm::Ctx, breakpoints: *const Vec<Box<Fn(BkptInfo) + Send + Sync + 'static>>, index: u32) -> i32 {
|
||||
unsafe extern "C" fn do_throw() -> ! {
|
||||
let ptr: *mut i32 = ::std::ptr::null_mut();
|
||||
*ptr = 42;
|
||||
::std::process::abort();
|
||||
}
|
||||
let breakpoints: &Vec<_> = &*breakpoints;
|
||||
breakpoints[index as usize](BkptInfo {
|
||||
throw: do_throw,
|
||||
});
|
||||
0
|
||||
}
|
||||
|
||||
pub enum Buffer {
|
||||
LlvmMemory(MemoryBuffer),
|
||||
Memory(Memory),
|
||||
@ -231,10 +247,11 @@ pub struct LLVMBackend {
|
||||
module: *mut LLVMModule,
|
||||
#[allow(dead_code)]
|
||||
buffer: Arc<Buffer>,
|
||||
breakpoints: Box<Vec<Box<Fn(BkptInfo) + Send + Sync + 'static>>>,
|
||||
}
|
||||
|
||||
impl LLVMBackend {
|
||||
pub fn new(module: Module, _intrinsics: Intrinsics) -> (Self, LLVMCache) {
|
||||
pub fn new(module: Module, _intrinsics: Intrinsics, breakpoints: Box<Vec<Box<Fn(BkptInfo) + Send + Sync + 'static>>>) -> (Self, LLVMCache) {
|
||||
Target::initialize_x86(&InitializationConfig {
|
||||
asm_parser: true,
|
||||
asm_printer: true,
|
||||
@ -289,12 +306,13 @@ impl LLVMBackend {
|
||||
Self {
|
||||
module,
|
||||
buffer: Arc::clone(&buffer),
|
||||
breakpoints,
|
||||
},
|
||||
LLVMCache { buffer },
|
||||
)
|
||||
}
|
||||
|
||||
pub unsafe fn from_buffer(memory: Memory) -> Result<(Self, LLVMCache), String> {
|
||||
pub unsafe fn from_buffer(memory: Memory, breakpoints: Box<Vec<Box<Fn(BkptInfo) + Send + Sync + 'static>>>) -> Result<(Self, LLVMCache), String> {
|
||||
let callbacks = get_callbacks();
|
||||
let mut module: *mut LLVMModule = ptr::null_mut();
|
||||
|
||||
@ -318,6 +336,7 @@ impl LLVMBackend {
|
||||
Self {
|
||||
module,
|
||||
buffer: Arc::clone(&buffer),
|
||||
breakpoints,
|
||||
},
|
||||
LLVMCache { buffer },
|
||||
))
|
||||
|
@ -398,6 +398,7 @@ pub struct LLVMFunctionCodeGenerator {
|
||||
num_params: usize,
|
||||
ctx: Option<CtxType<'static>>,
|
||||
unreachable_depth: usize,
|
||||
breakpoints: Option<Box<Vec<Box<Fn(BkptInfo) + Send + Sync + 'static>>>>,
|
||||
}
|
||||
|
||||
impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
|
||||
@ -470,13 +471,12 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
|
||||
}
|
||||
|
||||
fn feed_event(&mut self, event: Event, module_info: &ModuleInfo) -> Result<(), CodegenError> {
|
||||
let op = match event {
|
||||
Event::Wasm(x) => x,
|
||||
Event::WasmOwned(ref x) => x,
|
||||
Event::Internal(_x) => {
|
||||
match event {
|
||||
Event::Internal(InternalEvent::FunctionBegin(_)) | Event::Internal(InternalEvent::FunctionEnd) => {
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let mut state = &mut self.state;
|
||||
let builder = self.builder.as_ref().unwrap();
|
||||
@ -489,6 +489,13 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
|
||||
let mut ctx = self.ctx.as_mut().unwrap();
|
||||
|
||||
if !state.reachable {
|
||||
let op = match event {
|
||||
Event::Wasm(x) => x,
|
||||
Event::WasmOwned(ref x) => x,
|
||||
Event::Internal(_x) => {
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
match *op {
|
||||
Operator::Block { ty: _ } | Operator::Loop { ty: _ } | Operator::If { ty: _ } => {
|
||||
self.unreachable_depth += 1;
|
||||
@ -511,6 +518,44 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
let op = match event {
|
||||
Event::Wasm(x) => x,
|
||||
Event::WasmOwned(ref x) => x,
|
||||
Event::Internal(x) => {
|
||||
match x {
|
||||
InternalEvent::Breakpoint(handler) => {
|
||||
let mut breakpoints = self.breakpoints.as_mut().unwrap();
|
||||
breakpoints.push(handler);
|
||||
let ptr: *mut Vec<_> = &mut **breakpoints;
|
||||
let ptr_const = intrinsics
|
||||
.i64_ty
|
||||
.const_int(ptr as usize as u64, false)
|
||||
.as_basic_value_enum();
|
||||
builder.build_call(
|
||||
intrinsics.breakpoint,
|
||||
&[ctx.basic(), ptr_const, intrinsics
|
||||
.i32_ty
|
||||
.const_int((breakpoints.len() - 1) as u64, false)
|
||||
.as_basic_value_enum()],
|
||||
&state.var_name(),
|
||||
);
|
||||
},
|
||||
InternalEvent::GetInternal(index) => {
|
||||
let ptr = ctx.internal_pointer(index as usize, intrinsics);
|
||||
let value = builder.build_load(ptr, "internal_value");
|
||||
state.push1(value);
|
||||
}
|
||||
InternalEvent::SetInternal(index) => {
|
||||
let value = state.pop1()?;
|
||||
let ptr = ctx.internal_pointer(index as usize, intrinsics);
|
||||
builder.build_store(ptr, value);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
match *op {
|
||||
/***************************
|
||||
* Control Flow instructions.
|
||||
@ -2508,16 +2553,18 @@ impl ModuleCodeGenerator<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
|
||||
|
||||
fn next_function(&mut self) -> Result<&mut LLVMFunctionCodeGenerator, CodegenError> {
|
||||
// Creates a new function and returns the function-scope code generator for it.
|
||||
let (context, builder, intrinsics) = match self.functions.last_mut() {
|
||||
let (context, builder, intrinsics, breakpoints) = match self.functions.last_mut() {
|
||||
Some(x) => (
|
||||
x.context.take().unwrap(),
|
||||
x.builder.take().unwrap(),
|
||||
x.intrinsics.take().unwrap(),
|
||||
x.breakpoints.take().unwrap(),
|
||||
),
|
||||
None => (
|
||||
self.context.take().unwrap(),
|
||||
self.builder.take().unwrap(),
|
||||
self.intrinsics.take().unwrap(),
|
||||
Box::new(Vec::new()),
|
||||
),
|
||||
};
|
||||
|
||||
@ -2576,6 +2623,7 @@ impl ModuleCodeGenerator<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
|
||||
num_params,
|
||||
ctx: None,
|
||||
unreachable_depth: 0,
|
||||
breakpoints: Some(breakpoints),
|
||||
};
|
||||
self.functions.push(code);
|
||||
Ok(self.functions.last_mut().unwrap())
|
||||
@ -2585,16 +2633,18 @@ impl ModuleCodeGenerator<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
|
||||
mut self,
|
||||
module_info: &ModuleInfo,
|
||||
) -> Result<(LLVMBackend, Box<dyn CacheGen>), CodegenError> {
|
||||
let (context, builder, intrinsics) = match self.functions.last_mut() {
|
||||
let (context, builder, intrinsics, breakpoints) = match self.functions.last_mut() {
|
||||
Some(x) => (
|
||||
x.context.take().unwrap(),
|
||||
x.builder.take().unwrap(),
|
||||
x.intrinsics.take().unwrap(),
|
||||
x.breakpoints.take().unwrap(),
|
||||
),
|
||||
None => (
|
||||
self.context.take().unwrap(),
|
||||
self.builder.take().unwrap(),
|
||||
self.intrinsics.take().unwrap(),
|
||||
Box::new(Vec::new()),
|
||||
),
|
||||
};
|
||||
self.context = Some(context);
|
||||
@ -2625,7 +2675,7 @@ impl ModuleCodeGenerator<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
|
||||
|
||||
// self.module.print_to_stderr();
|
||||
|
||||
let (backend, cache_gen) = LLVMBackend::new(self.module, self.intrinsics.take().unwrap());
|
||||
let (backend, cache_gen) = LLVMBackend::new(self.module, self.intrinsics.take().unwrap(), breakpoints);
|
||||
Ok((backend, Box::new(cache_gen)))
|
||||
}
|
||||
|
||||
@ -2657,7 +2707,9 @@ impl ModuleCodeGenerator<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn from_cache(artifact: Artifact, _: Token) -> Result<ModuleInner, CacheError> {
|
||||
unsafe fn from_cache(_artifact: Artifact, _: Token) -> Result<ModuleInner, CacheError> {
|
||||
Err(CacheError::Unknown("caching is broken for LLVM backend".into()))
|
||||
/*
|
||||
let (info, _, memory) = artifact.consume();
|
||||
let (backend, cache_gen) =
|
||||
LLVMBackend::from_buffer(memory).map_err(CacheError::DeserializeError)?;
|
||||
@ -2667,6 +2719,6 @@ impl ModuleCodeGenerator<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
|
||||
cache_gen: Box::new(cache_gen),
|
||||
|
||||
info,
|
||||
})
|
||||
})*/
|
||||
}
|
||||
}
|
||||
|
@ -113,6 +113,8 @@ pub struct Intrinsics {
|
||||
pub memory_size_static_import: FunctionValue,
|
||||
pub memory_size_shared_import: FunctionValue,
|
||||
|
||||
pub breakpoint: FunctionValue,
|
||||
|
||||
pub throw_trap: FunctionValue,
|
||||
|
||||
pub ctx_ptr_ty: PointerType,
|
||||
@ -163,7 +165,7 @@ impl Intrinsics {
|
||||
let stack_lower_bound_ty = i8_ty;
|
||||
let memory_base_ty = i8_ty;
|
||||
let memory_bound_ty = void_ty;
|
||||
let internals_ty = void_ty;
|
||||
let internals_ty = i64_ty;
|
||||
let local_function_ty = i8_ptr_ty;
|
||||
|
||||
let anyfunc_ty = context.struct_type(
|
||||
@ -250,6 +252,8 @@ impl Intrinsics {
|
||||
|
||||
let ret_i1_take_i1_i1 = i1_ty.fn_type(&[i1_ty_basic, i1_ty_basic], false);
|
||||
|
||||
let ret_i32_take_ctx_i64_i32 = i32_ty.fn_type(&[ctx_ptr_ty.as_basic_type_enum(), i64_ty_basic, i32_ty_basic], false);
|
||||
|
||||
Self {
|
||||
ctlz_i32: module.add_function("llvm.ctlz.i32", ret_i32_take_i32_i1, None),
|
||||
ctlz_i64: module.add_function("llvm.ctlz.i64", ret_i64_take_i64_i1, None),
|
||||
@ -382,6 +386,11 @@ impl Intrinsics {
|
||||
ret_i32_take_ctx_i32,
|
||||
None,
|
||||
),
|
||||
breakpoint: module.add_function(
|
||||
"vm.breakpoint",
|
||||
ret_i32_take_ctx_i64_i32,
|
||||
None,
|
||||
),
|
||||
throw_trap: module.add_function(
|
||||
"vm.exception.trap",
|
||||
void_ty.fn_type(&[i32_ty_basic], false),
|
||||
@ -432,6 +441,7 @@ pub struct CtxType<'a> {
|
||||
cached_tables: HashMap<TableIndex, TableCache>,
|
||||
cached_sigindices: HashMap<SigIndex, IntValue>,
|
||||
cached_globals: HashMap<GlobalIndex, GlobalCache>,
|
||||
cached_internals: HashMap<usize, PointerValue>,
|
||||
cached_imported_functions: HashMap<ImportedFuncIndex, ImportedFuncCache>,
|
||||
|
||||
_phantom: PhantomData<&'a FunctionValue>,
|
||||
@ -457,6 +467,7 @@ impl<'a> CtxType<'a> {
|
||||
cached_tables: HashMap::new(),
|
||||
cached_sigindices: HashMap::new(),
|
||||
cached_globals: HashMap::new(),
|
||||
cached_internals: HashMap::new(),
|
||||
cached_imported_functions: HashMap::new(),
|
||||
|
||||
_phantom: PhantomData,
|
||||
@ -680,6 +691,33 @@ impl<'a> CtxType<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn internal_pointer(&mut self, index: usize, intrinsics: &Intrinsics) -> PointerValue {
|
||||
let (cached_internals, ctx_ptr_value, _info, cache_builder) = (
|
||||
&mut self.cached_internals,
|
||||
self.ctx_ptr_value,
|
||||
self.info,
|
||||
&self.cache_builder,
|
||||
);
|
||||
*cached_internals.entry(index).or_insert_with(|| {
|
||||
let array_ptr_ptr = unsafe {
|
||||
cache_builder.build_struct_gep(
|
||||
ctx_ptr_value,
|
||||
offset_to_index(Ctx::offset_internals()),
|
||||
"internals_array_ptr_ptr",
|
||||
)
|
||||
};
|
||||
let array_ptr = cache_builder.build_load(array_ptr_ptr, "internals_array_ptr").into_pointer_value();
|
||||
let const_index = intrinsics.i32_ty.const_int(index as u64, false);
|
||||
unsafe {
|
||||
cache_builder.build_in_bounds_gep(
|
||||
array_ptr,
|
||||
&[const_index],
|
||||
"element_ptr",
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn global_cache(&mut self, index: GlobalIndex, intrinsics: &Intrinsics) -> GlobalCache {
|
||||
let (cached_globals, ctx_ptr_value, info, cache_builder) = (
|
||||
&mut self.cached_globals,
|
||||
|
@ -2,7 +2,7 @@
|
||||
#![cfg_attr(nightly, feature(unwind_attributes))]
|
||||
|
||||
mod backend;
|
||||
mod code;
|
||||
pub mod code;
|
||||
mod intrinsics;
|
||||
mod platform;
|
||||
mod read_info;
|
||||
|
@ -16,15 +16,10 @@ tar = "0.4"
|
||||
wasmparser = "0.30.0"
|
||||
zstd = "0.4"
|
||||
|
||||
<<<<<<< HEAD
|
||||
[target.'cfg(unix)'.dependencies.zbox]
|
||||
git = "https://github.com/zboxfs/zbox"
|
||||
=======
|
||||
# [target.'cfg(unix)'.dependencies.zbox]
|
||||
# git = "https://github.com/wasmerio/zbox"
|
||||
# branch = "bundle-libsodium"
|
||||
# features = ["libsodium-bundled"]
|
||||
>>>>>>> origin/master
|
||||
|
||||
[dev-dependencies]
|
||||
tempdir = "0.3"
|
||||
|
@ -16,8 +16,9 @@ use structopt::StructOpt;
|
||||
use wasmer::*;
|
||||
use wasmer_clif_backend::CraneliftCompiler;
|
||||
#[cfg(feature = "backend:llvm")]
|
||||
use wasmer_llvm_backend::LLVMCompiler;
|
||||
#[cfg(feature = "backend:singlepass")]
|
||||
use wasmer_llvm_backend::{
|
||||
code::LLVMModuleCodeGenerator,
|
||||
};
|
||||
use wasmer_middleware_common::metering::Metering;
|
||||
use wasmer_runtime::{
|
||||
cache::{Cache as BaseCache, FileSystemCache, WasmHash, WASMER_VERSION_HASH},
|
||||
@ -336,7 +337,16 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
Backend::Singlepass => return Err("The singlepass backend is not enabled".to_string()),
|
||||
Backend::Cranelift => Box::new(CraneliftCompiler::new()),
|
||||
#[cfg(feature = "backend:llvm")]
|
||||
Backend::LLVM => Box::new(LLVMCompiler::new()),
|
||||
Backend::LLVM => {
|
||||
let c: StreamingCompiler<LLVMModuleCodeGenerator, _, _, _, _> = StreamingCompiler::new(|| {
|
||||
let mut chain = MiddlewareChain::new();
|
||||
if let Some(limit) = options.instruction_limit {
|
||||
chain.push(Metering::new(limit));
|
||||
}
|
||||
chain
|
||||
});
|
||||
Box::new(c)
|
||||
},
|
||||
#[cfg(not(feature = "backend:llvm"))]
|
||||
Backend::LLVM => return Err("the llvm backend is not enabled".to_string()),
|
||||
};
|
||||
@ -527,11 +537,11 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
.map(|arg| arg.as_str())
|
||||
.map(|x| Value::I32(x.parse().unwrap()))
|
||||
.collect();
|
||||
instance
|
||||
println!("{:?}", instance
|
||||
.dyn_func("main")
|
||||
.map_err(|e| format!("{:?}", e))?
|
||||
.call(&args)
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
.map_err(|e| format!("{:?}", e))?);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user