Skip to content

Commit

Permalink
Move allocation functions into javy lib (#461)
Browse files Browse the repository at this point in the history
* Move allocation functions into javy lib

* Update crates/javy/src/alloc.rs

Co-authored-by: Saúl Cabrera <saulecabrera@gmail.com>

* Add comment about cfg_attr usage

* teh -> the

---------

Co-authored-by: Saúl Cabrera <saulecabrera@gmail.com>
  • Loading branch information
jeffcharles and saulecabrera authored Sep 6, 2023
1 parent 234544f commit 5c0ac2d
Show file tree
Hide file tree
Showing 12 changed files with 83 additions and 105 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ wasmtime-wasi = "9.0"
wasi-common = "9.0"
anyhow = "1.0"
once_cell = "1.16"
javy = { path = "crates/javy", version = "2.0.1-alpha.1" }
javy = { path = "crates/javy", version = "2.1.0-alpha.1" }

[profile.release]
lto = true
Expand Down
2 changes: 1 addition & 1 deletion crates/apis/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "javy-apis"
version = "2.0.1-alpha.1"
version = "2.1.0-alpha.1"
authors.workspace = true
edition.workspace = true
license.workspace = true
Expand Down
5 changes: 4 additions & 1 deletion crates/cli/src/wasm_generator/static.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,21 @@ pub fn generate(js: &JS, exports: Vec<Export>) -> Result<Vec<u8>> {

let mut module = transform::module_config().parse(&wasm)?;

let (realloc, invoke, memory) = {
let (realloc, free, invoke, memory) = {
let mut exports = HashMap::new();
for export in module.exports.iter() {
exports.insert(export.name.as_str(), export);
}
(
*exports.get("canonical_abi_realloc").unwrap(),
*exports.get("canonical_abi_free").unwrap(),
*exports.get("javy.invoke").unwrap(),
*exports.get("memory").unwrap(),
)
};

let realloc_export = realloc.id();
let free_export = free.id();
let invoke_export = invoke.id();

if !exports.is_empty() {
Expand All @@ -75,6 +77,7 @@ pub fn generate(js: &JS, exports: Vec<Export>) -> Result<Vec<u8>> {

// We no longer need these exports so remove them.
module.exports.delete(realloc_export);
module.exports.delete(free_export);
module.exports.delete(invoke_export);

let wasm = module.emit_wasm();
Expand Down
2 changes: 1 addition & 1 deletion crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ crate-type = ["cdylib"]

[dependencies]
anyhow = { workspace = true }
javy = { workspace = true }
javy = { workspace = true, features = ["export_alloc_fns"] }
javy-apis = { path = "../apis", features = ["console", "text_encoding", "random", "stream_io"] }
once_cell = { workspace = true }

Expand Down
35 changes: 0 additions & 35 deletions crates/core/src/alloc.rs

This file was deleted.

37 changes: 0 additions & 37 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use once_cell::sync::OnceCell;
use std::slice;
use std::str;

mod alloc;
mod execution;
mod runtime;

Expand Down Expand Up @@ -83,39 +82,3 @@ pub unsafe extern "C" fn invoke(
execution::run_bytecode(runtime, bytecode);
execution::invoke_function(runtime, FUNCTION_MODULE_NAME, fn_name);
}

/// 1. Allocate memory of new_size with alignment.
/// 2. If original_ptr != 0
/// a. copy min(new_size, original_size) bytes from original_ptr to new memory
/// b. de-allocate original_ptr
/// 3. return new memory ptr
///
/// # Safety
///
/// * `original_ptr` must be 0 or a valid pointer
/// * if `original_ptr` is not 0, it must be valid for reads of `original_size`
/// bytes
/// * if `original_ptr` is not 0, it must be properly aligned
/// * if `original_size` is not 0, it must match the `new_size` value provided
/// in the original `canonical_abi_realloc` call that returned `original_ptr`
#[export_name = "canonical_abi_realloc"]
pub unsafe extern "C" fn canonical_abi_realloc(
original_ptr: *mut u8,
original_size: usize,
alignment: usize,
new_size: usize,
) -> *mut std::ffi::c_void {
alloc::canonical_abi_realloc(original_ptr, original_size, alignment, new_size)
}

/// Frees memory
///
/// # Safety
///
/// * `ptr` must denote a block of memory allocated by `canonical_abi_realloc`
/// * `size` and `alignment` must match the values provided in the original
/// `canonical_abi_realloc` call that returned `ptr`
#[export_name = "canonical_abi_free"]
pub unsafe extern "C" fn canonical_abi_free(ptr: *mut u8, size: usize, alignment: usize) {
alloc::canonical_abi_free(ptr, size, alignment)
}
26 changes: 0 additions & 26 deletions crates/core/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use std::slice;
use std::str;
use std::string::String;

mod alloc;
mod execution;
mod runtime;

Expand Down Expand Up @@ -37,31 +36,6 @@ fn main() {
execution::run_bytecode(&runtime, &bytecode);
}

// Removed in post_processing.
/// 1. Allocate memory of new_size with alignment.
/// 2. If original_ptr != 0
/// a. copy min(new_size, original_size) bytes from original_ptr to new memory
/// b. de-allocate original_ptr
/// 3. return new memory ptr
///
/// # Safety
///
/// * `original_ptr` must be 0 or a valid pointer
/// * if `original_ptr` is not 0, it must be valid for reads of `original_size`
/// bytes
/// * if `original_ptr` is not 0, it must be properly aligned
/// * if `original_size` is not 0, it must match the `new_size` value provided
/// in the original `canonical_abi_realloc` call that returned `original_ptr`
#[export_name = "canonical_abi_realloc"]
pub unsafe extern "C" fn canonical_abi_realloc(
original_ptr: *mut u8,
original_size: usize,
alignment: usize,
new_size: usize,
) -> *mut std::ffi::c_void {
alloc::canonical_abi_realloc(original_ptr, original_size, alignment, new_size)
}

// Removed in post-processing.
/// Evaluates QuickJS bytecode and invokes the exported JS function name.
///
Expand Down
6 changes: 6 additions & 0 deletions crates/javy/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Added

- `alloc` module containing implementations of a realloc function and a free function.
- An `export_alloc_fns` crate feature which when enabled, will export `canonical_abi_realloc` and `canonical_abi_free`
functions from your Wasm module.

## 2.0.0 - 2023-08-17

### Changed
Expand Down
3 changes: 2 additions & 1 deletion crates/javy/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "javy"
version = "2.0.1-alpha.1"
version = "2.1.0-alpha.1"
authors.workspace = true
edition.workspace = true
license.workspace = true
Expand All @@ -17,5 +17,6 @@ serde-transcode = { version = "1.1", optional = true }
rmp-serde = { version = "^1.1", optional = true }

[features]
export_alloc_fns = []
messagepack = ["rmp-serde", "serde-transcode"]
json = ["serde_json", "serde-transcode"]
65 changes: 65 additions & 0 deletions crates/javy/src/alloc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use std::alloc::{alloc, dealloc, Layout};
use std::ptr::copy_nonoverlapping;

// Unlike C's realloc, zero-length allocations need not have
// unique addresses, so a zero-length allocation may be passed
// in and also requested, but it's ok to return anything that's
// non-zero to indicate success.
const ZERO_SIZE_ALLOCATION_PTR: *mut u8 = 1 as _;

// For canonical_abi_realloc and canonical_abi_free, we want the functions to be available for use
// by other crates, whether or not the `export_alloc_fns` feature is enabled. When the
// `export_alloc_fns` feature is enabled, we also want to export the two functions from the Wasm
// module. To do that, we apply an `export_name` attribute when the `export_alloc_fns` feature is
// enabled. The `export_name` attribute is what causes the functions to be exported from the Wasm
// module as opposed to just exported for use by other crates.

/// 1. Allocate memory of new_size with alignment.
/// 2. If original_ptr != 0
/// a. copy min(new_size, original_size) bytes from original_ptr to new memory
/// b. de-allocate original_ptr
/// 3. Return new memory ptr.
///
/// # Safety
///
/// * `original_ptr` must be 0 or a valid pointer
/// * if `original_ptr` is not 0, it must be valid for reads of `original_size`
/// bytes
/// * if `original_ptr` is not 0, it must be properly aligned
/// * if `original_size` is not 0, it must match the `new_size` value provided
/// in the original `canonical_abi_realloc` call that returned `original_ptr`
#[cfg_attr(feature = "export_alloc_fns", export_name = "canonical_abi_realloc")]
pub unsafe extern "C" fn canonical_abi_realloc(
original_ptr: *mut u8,
original_size: usize,
alignment: usize,
new_size: usize,
) -> *mut std::ffi::c_void {
assert!(new_size >= original_size);

let new_mem = match new_size {
0 => ZERO_SIZE_ALLOCATION_PTR,
// this call to `alloc` is safe since `new_size` must be > 0
_ => alloc(Layout::from_size_align(new_size, alignment).unwrap()),
};

if !original_ptr.is_null() && original_size != 0 {
copy_nonoverlapping(original_ptr, new_mem, original_size);
canonical_abi_free(original_ptr, original_size, alignment);
}
new_mem as _
}

/// Frees memory
///
/// # Safety
///
/// * `ptr` must denote a block of memory allocated by `canonical_abi_realloc`
/// * `size` and `alignment` must match the values provided in the original
/// `canonical_abi_realloc` call that returned `ptr`
#[cfg_attr(feature = "export_alloc_fns", export_name = "canonical_abi_free")]
pub unsafe extern "C" fn canonical_abi_free(ptr: *mut u8, size: usize, alignment: usize) {
if size > 0 {
dealloc(ptr, Layout::from_size_align(size, alignment).unwrap())
};
}
1 change: 1 addition & 0 deletions crates/javy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub use config::Config;
pub use quickjs_wasm_rs as quickjs;
pub use runtime::Runtime;

pub mod alloc;
mod config;
mod runtime;

Expand Down

0 comments on commit 5c0ac2d

Please sign in to comment.