114 lines · 2.7 KB · C++
RawDownload
//// Dis VM// File: list.cpp// Author: arr// #include <runtime.h>#include <exceptions.h>#include <vm_memory.h>#include <debug.h> using disvm::debug::component_trace_t;using disvm::debug::log_level_t; using disvm::runtime::intrinsic_type_desc;using disvm::runtime::pointer_t;using disvm::runtime::type_descriptor_t;using disvm::runtime::vm_alloc_t;using disvm::runtime::vm_list_t;using disvm::runtime::word_t; std::shared_ptr<const type_descriptor_t> vm_list_t::type_desc(){    return intrinsic_type_desc::type<vm_list_t>();} vm_list_t::vm_list_t(std::shared_ptr<const type_descriptor_t> td, vm_list_t *tail)    : vm_alloc_t(vm_list_t::type_desc())    , _is_alloc{ sizeof(_mem) < td->size_in_bytes }    , _mem{}    , _tail{ nullptr }{    _element_type = std::move(td);    assert(_element_type != nullptr);    set_tail(tail);     // If the default list element storage is not enough, allocate more memory.    // [SPEC] Element memory is already initialized to zero based on the alloc_memory contract    if (_is_alloc)        _mem.alloc = static_cast<pointer_t>(alloc_memory(_element_type->size_in_bytes));     if (disvm::debug::is_component_tracing_enabled<component_trace_t::memory>())        disvm::debug::log_msg(component_trace_t::memory, log_level_t::debug, "init: vm list");} vm_list_t::~vm_list_t(){    // Destroy and free the list element, if default element size was surpassed.    if (_is_alloc)    {        destroy_memory(*_element_type, _mem.alloc);        free_memory(_mem.alloc);    }    else    {        destroy_memory(*_element_type, &_mem.local);    }     debug::assign_debug_pointer(&_mem.alloc);     // Remove tail    dec_ref_count_and_free(_tail);    debug::assign_debug_pointer(&_tail);     if (disvm::debug::is_component_tracing_enabled<component_trace_t::memory>())        disvm::debug::log_msg(component_trace_t::memory, log_level_t::debug, "destroy: vm list");} std::shared_ptr<const type_descriptor_t> vm_list_t::get_element_type() const{    return _element_type;} word_t vm_list_t::get_length() const{    auto len = word_t{ 1 };    auto list = _tail;    while (list != nullptr)    {        len++;        list = list->get_tail();    }     return len;} vm_list_t *vm_list_t::get_tail() const{    return _tail;} void vm_list_t::set_tail(vm_list_t *new_tail){    if (new_tail != nullptr)    {        if (!new_tail->get_element_type()->is_equal(_element_type.get()))            throw type_violation{};         new_tail->add_ref();    }     auto prev_tail = _tail;    _tail = new_tail;     dec_ref_count_and_free(prev_tail);} pointer_t vm_list_t::value() const{    if (_is_alloc)        return _mem.alloc;    else        return reinterpret_cast<pointer_t>(&_mem.local);}