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(core-processor): make dlmalloc a program library #2941

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
998 changes: 934 additions & 64 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ members = [
"gcli",
"gclient",
"gcore",
"gwasm",
# "gwasm/[!.cargo|!src]*",
"gwasm/processor",
"gmeta",
"gsdk",
"gsdk/codegen",
Expand Down Expand Up @@ -196,6 +199,8 @@ gstd = { path = "gstd" }
gsys = { path = "gsys" }
gtest = { path = "gtest" }
gmeta = { path = "gmeta" }
gwasm = { path = "gwasm" }
gwasm-processor = { path = "gwasm/processor" }
gear-authorship = { path = "node/authorship" }
gear-backend-codegen = { path = "core-backend/codegen" }
gear-backend-common = { path = "core-backend/common" }
Expand Down Expand Up @@ -449,6 +454,7 @@ scale-value = "^0.10" # gsdk
heck = "0.4.1" # gsdk-api-gen
etc = "0.1.16" # gcli
scale-decode = "0.7.0" # gsdk
rustc-demangle = "0.1.23" # gwasm/builder

[profile.release]
panic = "unwind"
Expand Down
1 change: 1 addition & 0 deletions core-backend/sandbox/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ codec.workspace = true
[features]
default = ["std"]
std = ["gear-sandbox/std", "gear-wasm-instrument/std", "log/std"]
experimental-features = ["gear-sandbox/experimental-features"]
1 change: 1 addition & 0 deletions examples/ping/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ gstd.workspace = true
gear-wasm-builder.workspace = true

[features]
gwasm = ["gstd/gwasm"]
debug = ["gstd/debug"]
default = ["std"]
std = []
2 changes: 2 additions & 0 deletions galloc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ license.workspace = true
[dependencies]
# add "checks" feature to enable hard checks in allocator
dlmalloc = { workspace = true, features = ["global"] }
gwasm = { workspace = true, optional = true }

[features]
debug = ["dlmalloc/debug"]
gwasm = ["dep:gwasm"]
6 changes: 5 additions & 1 deletion galloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@
#![doc(html_logo_url = "https://docs.gear.rs/logo.svg")]

// until https://github.com/alexcrichton/dlmalloc-rs/pull/26 is merged
#[cfg(not(windows))]
#[cfg(not(any(windows, feature = "gwasm")))]
#[global_allocator]
pub static ALLOC: dlmalloc::GlobalDlmalloc = dlmalloc::GlobalDlmalloc;

#[cfg(all(not(windows), feature = "gwasm"))]
#[global_allocator]
pub static ALLOC: gwasm::Allocator = gwasm::Allocator;

pub mod prelude;
1 change: 0 additions & 1 deletion gcore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ static_assertions.workspace = true

[dev-dependencies]
hex-literal.workspace = true
galloc.workspace = true

[features]
codec = ["dep:codec", "gear-core-errors/codec"]
Expand Down
2 changes: 0 additions & 2 deletions gcore/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@
//! ```
//! #![no_std]
//!
//! extern crate galloc;
//!
//! use gcore::msg;
//!
//! #[no_mangle]
Expand Down
1 change: 1 addition & 0 deletions gstd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ static_assertions.workspace = true
default = ["panic-handler"]
panic-handler = []
debug = ["galloc/debug", "gcore/debug"]
gwasm = ["galloc/gwasm"]
6 changes: 6 additions & 0 deletions gwasm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "gwasm"
version = "0.0.0"
edition = "2021"
description = "Gear WASM libraries"

2 changes: 2 additions & 0 deletions gwasm/lib/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
target = "wasm32-unknown-unknown"
1 change: 1 addition & 0 deletions gwasm/lib/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target
25 changes: 25 additions & 0 deletions gwasm/lib/Cargo.lock

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

7 changes: 7 additions & 0 deletions gwasm/lib/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[workspace]
members = [
"dlmalloc"
]

[workspace.dependencies]
dlmalloc = "0.2.4"
10 changes: 10 additions & 0 deletions gwasm/lib/dlmalloc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "gwasm-dlmalloc"
version = "0.0.1"
edition = "2021"

[lib]
crate-type = [ "cdylib" ]

[dependencies]
dlmalloc.workspace = true
44 changes: 44 additions & 0 deletions gwasm/lib/dlmalloc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//! Dummy library for exporting dlmalloc-rs as wasm module.
#![no_std]
// #![feature(wasm_import_memory)]
// #![wasm_import_memory]

use dlmalloc::Dlmalloc;

static mut DLMALLOC: Dlmalloc = Dlmalloc::new();

/// Allocate memory as described by the given `layout`.
#[no_mangle]
pub unsafe extern "C" fn alloc(size: usize, align: usize) -> *mut u8 {
DLMALLOC.malloc(size, align)
}

/// Deallocate the block of memory at the given `ptr` pointer with the given `layout`.
#[no_mangle]
pub unsafe extern "C" fn dealloc(ptr: *mut u8, size: usize, align: usize) {
DLMALLOC.free(ptr, size, align)
}

/// Behaves like `alloc`, but also ensures that the contents
/// are set to zero before being returned.
#[no_mangle]
pub unsafe extern "C" fn alloc_zeroed(size: usize, align: usize) -> *mut u8 {
DLMALLOC.calloc(size, align)
}

/// Shrink or grow a block of memory to the given `new_size` in bytes.
/// The block is described by the given `ptr` pointer and `layout`.
#[no_mangle]
pub unsafe extern "C" fn realloc(
ptr: *mut u8,
size: usize,
align: usize,
new_size: usize,
) -> *mut u8 {
DLMALLOC.realloc(ptr, size, align, new_size)
}

#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! {
loop {}
}
17 changes: 17 additions & 0 deletions gwasm/processor/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "gwasm-processor"
version = "0.1.0"
edition = "2021"

[dependencies]
wasm-compose = "0.4.0"

[dev-dependencies]
anyhow.workspace = true
gear-wasm-builder.workspace = true
wasmer = { version = "4.1.0", features = ["singlepass"]}
wasmtime = "11.0.1"

[build-dependencies]
anyhow.workspace = true
gear-wasm-builder.workspace = true
120 changes: 120 additions & 0 deletions gwasm/processor/benches/module-linking.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
//! Benches for wasm module-linking.
#![feature(test)]

extern crate test;

use anyhow::Result;
use gear_wasm_builder::optimize;
use std::{path::PathBuf, process::Command};
use test::bench::Bencher;

const DEMO_MEMOP_RELATIVE_PATH: &str = "memop";
const DEMO_MEMOP_WASM_RELATIVE_PATH: &str =
"memop/target/wasm32-unknown-unknown/release/memop.wasm";

/// Build demo memop with different features.
fn build_demo(gwasm: bool) -> Result<Vec<u8>> {
let demo = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join(DEMO_MEMOP_RELATIVE_PATH)
.canonicalize()?;
let mut args = vec!["build", "--release", "--no-default-features"];

if gwasm {
args.push("--features");
args.push("gwasm");
}

Command::new("cargo")
.env("RUSTFLAGS", "-C link-arg=--import-memory")
.args(&args)
.current_dir(demo)
.status()?;

optimize::optimize_wasm(
DEMO_MEMOP_WASM_RELATIVE_PATH.into(),
DEMO_MEMOP_WASM_RELATIVE_PATH.into(),
"z",
false,
)?;
std::fs::read(DEMO_MEMOP_WASM_RELATIVE_PATH).map_err(Into::into)
}

// #[bench]
// fn bench_galloc_memop(b: &mut Bencher) -> Result<()> {
// let wasm = build_demo(false)?;
// b.iter(|| execute(&wasm).expect("Failed to execute"));
//
// Ok(())
// }

mod wasmtime {
use crate::{build_demo, Bencher, Result};

fn execute(wasm: &[u8]) -> Result<()> {
use ::wasmtime::{Engine, Linker, Memory, MemoryType, Module, Store};

let engine = Engine::default();
let mut linker = Linker::<()>::new(&engine);
let mut store = Store::new(&engine, ());

// TODO: calculate this memory.
let memory = Memory::new(&mut store, MemoryType::new(0xffff, None))?;
linker.define(&mut store, "env", "memory", memory)?;

let memop = Module::from_binary(&engine, wasm)?;
let dlmalloc = Module::from_binary(&engine, &gwasm_processor::DLMALLOC)?;

let dlmalloc = linker.instantiate(&mut store, &dlmalloc)?;
linker.instance(&mut store, "gwasm-dlmalloc", dlmalloc)?;

let memop = linker.instantiate(&mut store, &memop)?;
let run = memop.get_typed_func::<(), i64>(&mut store, "memop")?;
let res = run.call(&mut store, ())?;

assert_eq!(res, 1);

Ok(())
}

#[bench]
fn bench_gwasm_memop(b: &mut Bencher) -> Result<()> {
let wasm = build_demo(true)?;
b.iter(|| execute(&wasm).expect("Failed to execute"));

Ok(())
}
}

mod wasmer {
use crate::{build_demo, Bencher, Result};

fn execute(wasm: &[u8]) -> Result<()> {
use ::wasmer::{Imports, Instance, Memory, MemoryType, Module, Store, Value};

let mut store = Store::default();
let dlmalloc = Module::new(&store.engine(), &gwasm_processor::DLMALLOC)?;
let memop = Module::new(&store.engine(), &wasm)?;

let memory = Memory::new(&mut store, MemoryType::new(0xffff, None, false))?;
let mut imports = Imports::new();
imports.define("env", "memory", memory);

let dlmalloc = Instance::new(&mut store, &dlmalloc, &Default::default())?;
imports.register_namespace("gwasm-dlmalloc", dlmalloc.exports);

let memop = Instance::new(&mut store, &memop, &imports)?;
let res = memop.exports.get_function("memop")?.call(&mut store, &[])?;

assert_eq!(res[0], Value::I64(1));

Ok(())
}

#[bench]
fn bench_gwasm_memop(b: &mut Bencher) -> Result<()> {
let wasm = build_demo(true)?;
b.iter(|| execute(&wasm).expect("Failed to execute"));

Ok(())
}
}
Loading