Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(c-api) Introduce the middleware (specifically metering) C API #2103

Merged
merged 37 commits into from
Mar 5, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
197d0f7
Initial commit of C API for metering and middleware.
nlewycky Feb 9, 2021
d660943
feat(c-api) Simplify `&Box<T>` to `&T`.
Hywan Mar 1, 2021
2bc502b
fix(c-api) Move the middleware API into the `unstable` module.
Hywan Mar 1, 2021
fd5a9b5
chore(c-api) Update headers.
Hywan Mar 1, 2021
cbbdfda
temp
Hywan Mar 1, 2021
0f43391
Merge branch 'master' into feature/metering-c-api
Hywan Mar 1, 2021
db4286d
fix(c-api) Fix merge conflict.
Hywan Mar 1, 2021
8b30ae9
feat(c-api) Add `_delete` and rename `_value` to `wasmer_metering_poi…
Hywan Mar 1, 2021
cb02694
test(c-api) Add tests for the `wasmer_metering_*` API.
Hywan Mar 1, 2021
3b0572f
feat(makefile) Test the C API with the `middlewares` feature.
Hywan Mar 1, 2021
e67fd6a
feat(c-api) Update headers + add the `MIDDLEWARES_FEATURE_AS_C_DEFINE…
Hywan Mar 1, 2021
8f1a4f3
feat(c-api) Add `wasmer_metering_delete`.
Hywan Mar 1, 2021
fb973b2
fix(c-api) `wasmer_module_middleware_t` is an opaque type.
Hywan Mar 2, 2021
31669b8
feat(c-api) Rename `wasmer_module_middleware_t` to `wasmer_middleware…
Hywan Mar 2, 2021
798dd88
feat(c-api) Simplify a compilation condition.
Hywan Mar 2, 2021
e014807
doc(middlewares) Format.
Hywan Mar 2, 2021
19c0412
doc(c-api) Write more documentation and tests.
Hywan Mar 2, 2021
0c4e063
chore(c-api) Update headers.
Hywan Mar 2, 2021
902f58e
!tmp
Hywan Mar 2, 2021
487c964
feat(middleware) Relax `F` in `Metering<F>` by removing `Clone` and `…
Hywan Mar 4, 2021
7780423
feat(c-api) `wasmer_metering_t` contains a closure to the cost function.
Hywan Mar 4, 2021
e2c4f1e
feat(c-api) Rename `Operator` to `wasmer_parser_operator_t`.
Hywan Mar 4, 2021
0163b33
test(c-api) Update the test to use a custom user-defined cost function.
Hywan Mar 4, 2021
e7c78e7
test(c-api) Update tests for the metering API.
Hywan Mar 4, 2021
072066a
Merge branch 'master' into feature/metering-c-api
Hywan Mar 4, 2021
f0024c5
doc(c-api) Fix typos.
Hywan Mar 4, 2021
4f2ba72
feat(c-api) Simplify the metering API.
Hywan Mar 4, 2021
f233ca4
chore(api) The `compiler` feature enables `wasmer-compiler/translator`.
Hywan Mar 4, 2021
df0bdeb
fix(makefile) `build-capi` includes the `middlewares` feature.
Hywan Mar 4, 2021
2d20f44
fix(c-api) Remove useless `unsafe` marker.
Hywan Mar 4, 2021
4136536
Merge branch 'master' into feature/metering-c-api
Hywan Mar 4, 2021
96524b5
chore(c-api) Update headers.
Hywan Mar 4, 2021
8517547
fix(engine-native) Fix Cargo.lock and `Library::new` is unsafe.
Hywan Mar 4, 2021
1700c2d
feat(c-api) Return ~1 if metering are exhausted. Add `wasmer_metering…
Hywan Mar 4, 2021
06a00d9
doc(c-api) Update documentation for clarity.
Hywan Mar 4, 2021
d3f7b7e
chore(c-api) Change `operator` to `wasm_operator` (reserved keyword i…
Hywan Mar 4, 2021
21ea09f
chore(c-api) Fix merge conflicts.
Hywan Mar 5, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 13 additions & 13 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -170,55 +170,55 @@ build-capi: build-capi-cranelift

build-capi-singlepass:
cargo build --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features deprecated,wat,jit,native,object-file,singlepass,wasi $(capi_default_features)
--no-default-features --features deprecated,wat,jit,native,object-file,singlepass,wasi,middlewares $(capi_default_features)

build-capi-singlepass-jit:
cargo build --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features deprecated,wat,jit,singlepass,wasi $(capi_default_features)
--no-default-features --features deprecated,wat,jit,singlepass,wasi,middlewares $(capi_default_features)

build-capi-singlepass-native:
cargo build --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features deprecated,wat,native,singlepass,wasi $(capi_default_features)
--no-default-features --features deprecated,wat,native,singlepass,wasi,middlewares $(capi_default_features)

build-capi-singlepass-object-file:
cargo build --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features deprecated,wat,object-file,singlepass,wasi $(capi_default_features)
--no-default-features --features deprecated,wat,object-file,singlepass,wasi,middlewares $(capi_default_features)

build-capi-cranelift:
cargo build --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features deprecated,wat,jit,native,object-file,cranelift,wasi $(capi_default_features)
--no-default-features --features deprecated,wat,jit,native,object-file,cranelift,wasi,middlewares $(capi_default_features)

build-capi-cranelift-system-libffi:
cargo build --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features deprecated,wat,jit,native,object-file,cranelift,wasi,system-libffi $(capi_default_features)
--no-default-features --features deprecated,wat,jit,native,object-file,cranelift,wasi,middlewares,system-libffi $(capi_default_features)

build-capi-cranelift-jit:
cargo build --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features deprecated,wat,jit,cranelift,wasi $(capi_default_features)
--no-default-features --features deprecated,wat,jit,cranelift,wasi,middlewares $(capi_default_features)

build-capi-cranelift-native:
cargo build --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features deprecated,wat,native,cranelift,wasi $(capi_default_features)
--no-default-features --features deprecated,wat,native,cranelift,wasi,middlewares $(capi_default_features)

build-capi-cranelift-object-file:
cargo build --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features deprecated,wat,native,object-file,cranelift,wasi $(capi_default_features)
--no-default-features --features deprecated,wat,native,object-file,cranelift,wasi,middlewares $(capi_default_features)

build-capi-llvm:
cargo build --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features deprecated,wat,jit,native,object-file,llvm,wasi $(capi_default_features)
--no-default-features --features deprecated,wat,jit,native,object-file,llvm,wasi,middlewares $(capi_default_features)

build-capi-llvm-jit:
cargo build --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features deprecated,wat,jit,llvm,wasi $(capi_default_features)
--no-default-features --features deprecated,wat,jit,llvm,wasi,middlewares $(capi_default_features)

build-capi-llvm-native:
cargo build --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features deprecated,wat,native,llvm,wasi $(capi_default_features)
--no-default-features --features deprecated,wat,native,llvm,wasi,middlewares $(capi_default_features)

build-capi-llvm-object-file:
cargo build --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features deprecated,wat,object-file,llvm,wasi $(capi_default_features)
--no-default-features --features deprecated,wat,object-file,llvm,wasi,middlewares $(capi_default_features)

# Headless (we include the minimal to be able to run)

Expand Down
3 changes: 3 additions & 0 deletions lib/c-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ wasmer-engine = { version = "1.0.2", path = "../engine" }
wasmer-engine-jit = { version = "1.0.2", path = "../engine-jit", optional = true }
wasmer-engine-native = { version = "1.0.2", path = "../engine-native", optional = true }
wasmer-engine-object-file = { version = "1.0.2", path = "../engine-object-file", optional = true }
wasmer-middlewares = { version = "1.0.2", path = "../middlewares", optional = true }
wasmer-wasi = { version = "1.0.2", path = "../wasi", optional = true }
wasmer-types = { version = "1.0.2", path = "../wasmer-types" }
enumset = "1.0"
Expand All @@ -50,10 +51,12 @@ default = [
"cranelift",
"jit",
"wasi",
"middlewares",
]
wat = ["wasmer/wat"]
wasi = ["wasmer-wasi", "typetag", "serde"]
engine = []
middlewares = ["wasmer-middlewares"]
deprecated = ["libffi"]
jit = [
"wasmer-engine-jit",
Expand Down
3 changes: 3 additions & 0 deletions lib/c-api/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ fn exclude_items_from_wasm_c_api(builder: Builder) -> Builder {
.exclude_item("wasm_config_set_compiler")
.exclude_item("wasm_config_set_engine")
.exclude_item("wasm_config_set_target")
.exclude_item("wasm_config_push_middleware")
.exclude_item("wasm_cpu_features_add")
.exclude_item("wasm_cpu_features_delete")
.exclude_item("wasm_cpu_features_new")
Expand All @@ -494,6 +495,8 @@ fn exclude_items_from_wasm_c_api(builder: Builder) -> Builder {
.exclude_item("wasm_triple_t")
.exclude_item("wasmer_compiler_t")
.exclude_item("wasmer_engine_t")
.exclude_item("wasmer_metering_get_remaining_points")
.exclude_item("wasmer_metering_set_remaining_points")
.exclude_item("wat2wasm")
}

Expand Down
2 changes: 2 additions & 0 deletions lib/c-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,7 @@
#[cfg(feature = "deprecated")]
pub mod deprecated;
pub mod error;
#[cfg(feature = "middlewares")]
pub mod metering;
mod ordered_resolver;
pub mod wasm_c_api;
73 changes: 73 additions & 0 deletions lib/c-api/src/metering.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// C API for metering.

use super::wasm_c_api::instance::wasm_instance_t;
use std::sync::Arc;
use wasmer::wasmparser::Operator;
use wasmer_middlewares::{
metering::{get_remaining_points, set_remaining_points, MeteringPoints},
Metering,
};

/// Opaque type representing a MeteringPoints.
#[allow(non_camel_case_types)]
pub struct wasmer_metering_points_t {
pub(crate) inner: MeteringPoints,
}

#[no_mangle]
pub unsafe extern "C" fn wasmer_metering_points_value(
metering_points: &Box<wasmer_metering_points_t>,
exhausted: u64,
) -> u64 {
match metering_points.inner {
MeteringPoints::Remaining(value) => value,
MeteringPoints::Exhausted => exhausted,
}
}

#[no_mangle]
pub unsafe extern "C" fn wasmer_metering_points_is_exhausted(
metering_points: &Box<wasmer_metering_points_t>,
) -> bool {
matches!(metering_points.inner, MeteringPoints::Exhausted)
}

/// Opaque type representing a MeteringPoints.
#[allow(non_camel_case_types)]
pub struct wasmer_metering_t {
#[allow(dead_code)]
pub(crate) inner: Arc<Metering<fn(&Operator) -> u64>>,
}

#[no_mangle]
pub unsafe extern "C" fn wasmer_metering_new(initial_limit: u64) -> Box<wasmer_metering_t> {
let cost_function = |operator: &Operator| -> u64 {
match operator {
Operator::I32Const { .. }
| Operator::I64Const { .. }
| Operator::F32Const { .. }
| Operator::F64Const { .. } => 0,
_ => 1,
}
};
Box::new(wasmer_metering_t {
inner: Arc::new(Metering::new(initial_limit, cost_function)),
})
}

#[no_mangle]
pub unsafe extern "C" fn wasmer_metering_get_remaining_points(
instance: &wasm_instance_t,
) -> Box<wasmer_metering_points_t> {
Box::new(wasmer_metering_points_t {
inner: get_remaining_points(&instance.inner),
})
}

#[no_mangle]
pub unsafe extern "C" fn wasmer_metering_set_remaining_points(
instance: &wasm_instance_t,
new_limit: u64,
) {
set_remaining_points(&instance.inner, new_limit);
}
38 changes: 37 additions & 1 deletion lib/c-api/src/wasm_c_api/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@ use crate::error::{update_last_error, CApiError};
use cfg_if::cfg_if;
use std::sync::Arc;
use wasmer::Engine;
#[cfg(feature = "middlewares")]
use wasmer_compiler::ModuleMiddleware;
#[cfg(feature = "jit")]
use wasmer_engine_jit::JIT;
#[cfg(feature = "native")]
use wasmer_engine_native::Native;
#[cfg(feature = "object-file")]
use wasmer_engine_object_file::ObjectFile;

#[cfg(feature = "middlewares")]
#[cfg(not(feature = "compiler"))]
compile_error!("middlewares features requires compilers feature");

/// Kind of compilers that can be used by the engines.
///
/// This is a Wasmer-specific type with Wasmer-specific functions for
Expand Down Expand Up @@ -86,6 +92,16 @@ impl Default for wasmer_engine_t {
}
}

/// Opaque representing a middleware.
///
#[cfg(feature = "middlewares")]
#[derive(Debug)]
#[repr(C)]
Hywan marked this conversation as resolved.
Show resolved Hide resolved
#[allow(non_camel_case_types)]
pub struct wasmer_module_middleware_t {
pub(super) inner: Arc<dyn ModuleMiddleware>,
}

/// A configuration holds the compiler and the engine used by the store.
///
/// cbindgen:ignore
Expand All @@ -96,6 +112,8 @@ pub struct wasm_config_t {
#[cfg(feature = "compiler")]
compiler: wasmer_compiler_t,
pub(super) target: Option<Box<wasm_target_t>>,
#[cfg(feature = "middlewares")]
pub(super) middlewares: Vec<wasmer_module_middleware_t>,
}

/// Create a new default Wasmer configuration.
Expand Down Expand Up @@ -246,6 +264,16 @@ pub extern "C" fn wasm_config_set_engine(config: &mut wasm_config_t, engine: was
config.engine = engine;
}

// TODO: documentation
#[cfg(feature = "middlewares")]
#[no_mangle]
pub extern "C" fn wasm_config_push_middleware(
config: &mut wasm_config_t,
middleware: Box<wasmer_module_middleware_t>,
) {
config.middlewares.push(*middleware);
}

/// An engine is used by the store to drive the compilation and the
/// execution of a WebAssembly module.
///
Expand Down Expand Up @@ -311,7 +339,7 @@ cfg_if! {
/// cbindgen:ignore
#[no_mangle]
pub extern "C" fn wasm_engine_new() -> Box<wasm_engine_t> {
let mut compiler_config: Box<dyn CompilerConfig> = get_default_compiler_config();
let compiler_config: Box<dyn CompilerConfig> = get_default_compiler_config();
let engine: Arc<dyn Engine + Send + Sync> = Arc::new(Native::new(compiler_config).engine());
Box::new(wasm_engine_t { inner: engine })
}
Expand Down Expand Up @@ -448,6 +476,14 @@ pub extern "C" fn wasm_engine_new_with_config(
},
};

cfg_if! {
if #[cfg(feature = "middlewares")] {
for middleware in config.middlewares {
compiler_config.push_middleware(middleware.inner);
}
}
}

let inner: Arc<dyn Engine + Send + Sync> = match config.engine {
wasmer_engine_t::JIT => {
cfg_if! {
Expand Down
14 changes: 14 additions & 0 deletions lib/c-api/wasmer.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,13 @@ enum wasmer_value_tag
typedef uint32_t wasmer_value_tag;
#endif // __cplusplus

typedef struct Box_wasmer_metering_points_t Box_wasmer_metering_points_t;

/**
* Opaque type representing a MeteringPoints.
*/
typedef struct wasmer_metering_t wasmer_metering_t;

typedef struct {

} wasmer_module_t;
Expand Down Expand Up @@ -1296,6 +1303,13 @@ uint32_t wasmer_memory_length(const wasmer_memory_t *memory);
*/
wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits);

wasmer_metering_t *wasmer_metering_new(uint64_t initial_limit);

bool wasmer_metering_points_is_exhausted(const Box_wasmer_metering_points_t *metering_points);

uint64_t wasmer_metering_points_value(const Box_wasmer_metering_points_t *metering_points,
uint64_t exhausted);

/**
* Deserialize the given serialized module.
*
Expand Down
16 changes: 16 additions & 0 deletions lib/c-api/wasmer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,15 @@ enum class wasmer_value_tag : uint32_t {
WASM_F64,
};

template<typename T = void>
struct Box;

/// Opaque type representing a MeteringPoints.
struct wasmer_metering_points_t;

/// Opaque type representing a MeteringPoints.
struct wasmer_metering_t;

struct wasmer_module_t {

};
Expand Down Expand Up @@ -1060,6 +1069,13 @@ uint32_t wasmer_memory_length(const wasmer_memory_t *memory);
/// ```
wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits);

Box<wasmer_metering_t> wasmer_metering_new(uint64_t initial_limit);

bool wasmer_metering_points_is_exhausted(const Box<wasmer_metering_points_t> *metering_points);

uint64_t wasmer_metering_points_value(const Box<wasmer_metering_points_t> *metering_points,
uint64_t exhausted);

/// Deserialize the given serialized module.
///
/// Returns `wasmer_result_t::WASMER_OK` upon success.
Expand Down
Loading