diff --git a/README.md b/README.md index 323c0a4..334c1ad 100644 --- a/README.md +++ b/README.md @@ -36,12 +36,12 @@ advantages, including: * Clean codebase that is easy to read and contribute to * Support for arbitrary size integers and floats (can be set at compile time) * Allows building into a static or shared library, supports `-fvisibility=hidden` +* Custom allocator support (control over how heap memory is allocated) There are some features that are a work in progress and will come later: * More helpful debug information (proper line infos at both parse and run time) * A degree of thread safety (see below) -* Custom allocator support (control over how heap memory is allocated) * Coroutines The API is currently very unstable, as is the actual codebase. Therefore you diff --git a/src/cs_vm.cc b/src/cs_vm.cc index 4707567..fa43a54 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -135,6 +135,30 @@ cs_stack_state cs_error::save_stack(cs_state &cs) { return cs_stack_state(cs, ret, total > dalias->get_value()); } +struct bcode_hdr { + cs_shared_state *cs; /* needed to construct the allocator */ + std::size_t asize; /* alloc size of the bytecode block */ + std::uint32_t init; /* CS_CODE_START + refcount */ +}; + +/* returned address is the 'init' member of the header */ +static inline std::uint32_t *bcode_alloc(cs_state &cs, std::size_t sz) { + auto a = cs_allocator{cs}; + std::size_t hdrs = sizeof(bcode_hdr) / sizeof(std::uint32_t); + auto p = a.allocate(sz + hdrs - 1); + bcode_hdr *hdr = reinterpret_cast(p); + hdr->cs = cs_get_sstate(cs); + hdr->asize = sz + hdrs - 1; + return p + hdrs - 1; +} + +/* bc's address must be the 'init' member of the header */ +static inline void bcode_free(uint32_t *bc) { + auto *rp = bc + 1 - (sizeof(bcode_hdr) / sizeof(std::uint32_t)); + bcode_hdr *hdr = reinterpret_cast(rp); + cs_allocator{hdr->cs}.deallocate(rp, hdr->asize); +} + static inline void bcode_incr(uint32_t *bc) { *bc += 0x100; } @@ -142,7 +166,7 @@ static inline void bcode_incr(uint32_t *bc) { static inline void bcode_decr(uint32_t *bc) { *bc -= 0x100; if (std::int32_t(*bc) < 0x100) { - delete[] bc; + bcode_free(bc); } } @@ -223,7 +247,7 @@ cs_bcode *cs_alias_impl::compile_code(cs_state &cs) { gs.code.reserve(64); gs.gen_main(get_value().get_str()); /* i wish i could steal the memory somehow */ - uint32_t *code = new uint32_t[gs.code.size()]; + uint32_t *code = bcode_alloc(cs, gs.code.size()); memcpy(code, gs.code.data(), gs.code.size() * sizeof(uint32_t)); bcode_incr(code); p_acode = reinterpret_cast(code); @@ -238,7 +262,7 @@ static inline uint32_t *forcecode(cs_state &cs, cs_value &v) { gs.code.reserve(64); gs.gen_main(v.get_str()); gs.done(); - uint32_t *cbuf = new uint32_t[gs.code.size()]; + uint32_t *cbuf = bcode_alloc(cs, gs.code.size()); memcpy(cbuf, gs.code.data(), gs.code.size() * sizeof(uint32_t)); v.set_code(reinterpret_cast(cbuf + 1)); code = reinterpret_cast(v.get_code()); @@ -884,7 +908,7 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { break; } gs.done(); - uint32_t *cbuf = new uint32_t[gs.code.size()]; + uint32_t *cbuf = bcode_alloc(gs.cs, gs.code.size()); memcpy(cbuf, gs.code.data(), gs.code.size() * sizeof(uint32_t)); arg.set_code( reinterpret_cast(cbuf + 1) @@ -901,7 +925,7 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { gs.code.reserve(64); gs.gen_main(s); gs.done(); - uint32_t *cbuf = new uint32_t[gs.code.size()]; + uint32_t *cbuf = bcode_alloc(gs.cs, gs.code.size()); memcpy( cbuf, gs.code.data(), gs.code.size() * sizeof(uint32_t) @@ -1559,7 +1583,7 @@ static void cs_run( gs.code.reserve(64); gs.gen_main(code, CS_VAL_ANY); gs.done(); - uint32_t *cbuf = new uint32_t[gs.code.size()]; + uint32_t *cbuf = bcode_alloc(gs.cs, gs.code.size()); memcpy(cbuf, gs.code.data(), gs.code.size() * sizeof(uint32_t)); bcode_incr(cbuf); runcode(cs, cbuf + 1, ret);