diff --git a/Cargo.toml b/Cargo.toml index dae7b7b..b51aafa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ members = [ "ontio-std", "ontio-codegen", + "ontio-bump-alloc", "examples", "examples/token", "examples/token-zero-copy", diff --git a/examples/oep8token/Cargo.toml b/examples/oep8token/Cargo.toml index b9d9e90..94cc416 100644 --- a/examples/oep8token/Cargo.toml +++ b/examples/oep8token/Cargo.toml @@ -4,8 +4,13 @@ version = "0.1.0" authors = ["lucas7788 "] edition = "2018" +[lib] +crate-type = ["cdylib"] +path = "src/lib.rs" + [dependencies] ontio-std = {path="../../ontio-std"} [features] +default = ["ontio-std/bump-alloc"] mock = ["ontio-std/mock"] diff --git a/examples/token/Cargo.toml b/examples/token/Cargo.toml index 325ae62..23a5db5 100644 --- a/examples/token/Cargo.toml +++ b/examples/token/Cargo.toml @@ -9,5 +9,5 @@ crate-type = ["cdylib"] path = "src/lib.rs" [dependencies] -ontio-std = {path="../../ontio-std"} +ontio-std = {path="../../ontio-std", features=["bump-alloc"]} diff --git a/examples/token/src/lib.rs b/examples/token/src/lib.rs index d29365f..6cf1efc 100644 --- a/examples/token/src/lib.rs +++ b/examples/token/src/lib.rs @@ -22,8 +22,8 @@ fn balance_of(owner: &Addr) -> U256 { fn transfer(from: &Addr, to: &Addr, amount: U256) -> bool { assert!(runtime::check_witness(from)); - let mut frmbal = balance_of(from); - let mut tobal = balance_of(to); + let frmbal = balance_of(from); + let tobal = balance_of(to); if amount == 0.into() || frmbal < amount { return false; } diff --git a/ontio-bump-alloc/Cargo.toml b/ontio-bump-alloc/Cargo.toml new file mode 100644 index 0000000..6d50d11 --- /dev/null +++ b/ontio-bump-alloc/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "ontio-bump-alloc" +version = "0.1.0" +authors = ["laizy "] +edition = "2018" + +[dependencies] +cfg-if = { version = "0.1", default-features = false } diff --git a/ontio-bump-alloc/src/lib.rs b/ontio-bump-alloc/src/lib.rs new file mode 100644 index 0000000..f20ea05 --- /dev/null +++ b/ontio-bump-alloc/src/lib.rs @@ -0,0 +1,84 @@ +#![no_std] +use cfg_if::cfg_if; +use core::alloc::{GlobalAlloc, Layout}; +use core::cell::RefCell; +use core::ptr; + +const PAGE_SIZE: usize = 65536; + +struct Inner { + pos: *mut u8, + size: usize, +} + +pub struct BumpAlloc { + inner: RefCell, +} + +//contract execution is single thread +unsafe impl Sync for BumpAlloc {} + +impl BumpAlloc { + pub const fn new() -> BumpAlloc { + BumpAlloc { inner: RefCell::new(Inner { pos: ptr::null_mut(), size: 0 }) } + } +} + +fn align_to(size: usize, align: usize) -> usize { + (size + align - 1) & !(align - 1) +} + +unsafe impl GlobalAlloc for BumpAlloc { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + let mut inner = self.inner.borrow_mut(); + + let need_bytes = align_to(layout.size(), layout.align()); + let pos = align_to(inner.pos as usize, layout.align()); + if pos + need_bytes > inner.size { + let need_page = (pos + need_bytes - inner.size + PAGE_SIZE - 1) / PAGE_SIZE; + match alloc_pages(need_page) { + Some(p) => { + if inner.pos == ptr::null_mut() { + inner.pos = p; + } + inner.size = (p as usize) + need_page * PAGE_SIZE; + } + None => return ptr::null_mut(), + } + } + + let pos = align_to(inner.pos as usize, layout.align()); + inner.pos = (pos + need_bytes) as *mut u8; + + pos as *mut u8 + } + + unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} +} + +cfg_if! { +if #[cfg(target_arch = "wasm32")] { + mod alloc_impl { + use core::arch::wasm32; + use super::PAGE_SIZE; + + pub(crate) unsafe fn alloc_pages(num_page: usize) -> Option<*mut u8> { + let ptr = wasm32::memory_grow(0, num_page); + if ptr != usize::max_value() { + let ptr = (ptr * PAGE_SIZE) as *mut u8; + Some(ptr) + } else { + None + } + } + } + use alloc_impl::alloc_pages; +} else { + mod imp_noop { + pub(crate) unsafe fn alloc_pages(_num_page: usize) -> Option<*mut u8> { + None + } + } + use imp_noop::alloc_pages; +} +} diff --git a/ontio-std/Cargo.toml b/ontio-std/Cargo.toml index 66794e8..25340e4 100644 --- a/ontio-std/Cargo.toml +++ b/ontio-std/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" [dependencies] wee_alloc = "0.4" +ontio-bump-alloc = {path = "../ontio-bump-alloc", optional = true} bigint = { version = "4.4", default-features = false } fixed-hash = { version = "0.3", default-features = false } cfg-if = { version = "0.1", default-features = false } @@ -18,4 +19,5 @@ rand = "0.6" [features] std = [] +bump-alloc = ["ontio-bump-alloc"] mock = ["std", "fixed-hash/default"] diff --git a/ontio-std/src/lib.rs b/ontio-std/src/lib.rs index 22be6fb..2558566 100644 --- a/ontio-std/src/lib.rs +++ b/ontio-std/src/lib.rs @@ -11,11 +11,20 @@ //#![feature(trace_macros)] cfg_if::cfg_if! { - if #[cfg(not(feature = "std"))] { + if #[cfg(all(not(feature = "std"), feature = "bump-alloc"))] { + use ontio_bump_alloc::BumpAlloc; + #[global_allocator] + static ALLOC: BumpAlloc = BumpAlloc::new(); + } else if #[cfg(not(feature = "std"))] { extern crate wee_alloc; // Use `wee_alloc` as the global allocator. #[global_allocator] static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; + } +} + +cfg_if::cfg_if! { + if #[cfg(not(feature = "std"))] { /// Overrides the default panic_fmt #[no_mangle] #[panic_handler]