89 lines · 3.8 KB · C
RawDownload
//// Dis VM// File: vm_memory.h// Author: arr// #ifndef _DISVM_SRC_INCLUDE_VM_MEMORY_H_#define _DISVM_SRC_INCLUDE_VM_MEMORY_H_ #include <cstdint>#include <cassert>#include <limits>#include <mutex>#include <memory>#include <bitset>#include <functional>#include "runtime.h" namespace disvm{    namespace runtime    {        // Allocate memory from the VM heap that is initialize to 0.        // [SPEC] All memory in this implementation of the Dis VM spec        // will be 0 initialized.        void *alloc_memory(std::size_t amount_in_bytes);         template<typename T>        T *alloc_memory(std::size_t amount_in_bytes = sizeof(T))        {            return reinterpret_cast<T *>(alloc_memory(amount_in_bytes));        }         // Free memory on the VM heap        void free_memory(void *memory);         // Initialize supplied memory based on the type descriptor        void init_memory(const type_descriptor_t &type_desc, void *data);         // Destroy supplied memory based on the type descriptor        void destroy_memory(const type_descriptor_t &type_desc, void *data);         // Increment the ref count of all pointers in the supplied memory allocation        void inc_ref_count_in_memory(const type_descriptor_t &type_desc, void *data);         // Decrement the ref count of all pointers in the supplied memory allocation        void dec_ref_count_in_memory(const type_descriptor_t &type_desc, void *data);         // Decrement the ref count and if 0 free the allocation        void dec_ref_count_and_free(vm_alloc_t *alloc);         // Function to enumerate pointer fields in an object. The function is defined        // as a template to permit raw function pointers or lambdas. The signature        // of the callback must be 'void(pointer_t *)' and is supplied a pointer to the        // non-null pointer field. The offset of the field is relative to the supplied        // 'data' pointer.        template<typename CB>        void enum_pointer_fields(const type_descriptor_t &type_desc, void *data, CB callback)        {            assert(data != nullptr);             auto memory = reinterpret_cast<word_t *>(data);            for (auto i = word_t{ 0 }; i < type_desc.map_in_bytes; ++i, memory += 8)            {                const auto words8 = type_desc.pointer_map[i];                assert(sizeof(words8) == 1);                if (words8 == 0)                    continue;                 const auto flags = std::bitset<sizeof(words8) * 8>{ words8 };                 // Enumerating the flags in reverse order so memory access is sequential.                if (flags[7] && (memory[0] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t *>(memory));                if (flags[6] && (memory[1] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t *>(memory) + 1);                if (flags[5] && (memory[2] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t *>(memory) + 2);                if (flags[4] && (memory[3] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t *>(memory) + 3);                if (flags[3] && (memory[4] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t *>(memory) + 4);                if (flags[2] && (memory[5] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t *>(memory) + 5);                if (flags[1] && (memory[6] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t *>(memory) + 6);                if (flags[0] && (memory[7] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t *>(memory) + 7);            }        }         // Check if a specific pointer-sized offset in a type represents a pointer        bool is_offset_pointer(const type_descriptor_t &type_desc, std::size_t offset);    }} #endif // _DISVM_SRC_INCLUDE_VM_MEMORY_H_