Showing the changes to src/include (2 of 10 files). Show all
Unified · Split
| @@ -98,7 +98,14 @@ namespace disvm · 97 unmodified lines | |||
| 98 | 98 | ||
| 99 | static vm_alloc_t *allocate(std::shared_ptr<const type_descriptor_t> td); | 99 | static vm_alloc_t *allocate(std::shared_ptr<const type_descriptor_t> td); |
| 100 | static vm_alloc_t *copy(const vm_alloc_t &other); | 100 | static vm_alloc_t *copy(const vm_alloc_t &other); |
| 101 | static vm_alloc_t *from_allocation(pointer_t allocation); | 101 | |
| 102 | static vm_alloc_t *from_allocation(pointer_t allocation) | ||
| 103 | { | ||
| 104 | if (allocation == nullptr) | ||
| 105 | return nullptr; | ||
| 106 | |||
| 107 | return reinterpret_cast<vm_alloc_t *>(reinterpret_cast<uint8_t *>(allocation) - sizeof(vm_alloc_t)); | ||
| 108 | } | ||
| 102 | 109 | ||
| 103 | template <typename T> | 110 | template <typename T> |
| 104 | static T *from_allocation(pointer_t allocation) | 111 | static T *from_allocation(pointer_t allocation) |
| @@ -125,7 +132,12 @@ namespace disvm · 20 unmodified lines | |||
| 125 | pointer_t gc_reserved; | 132 | pointer_t gc_reserved; |
| 126 | 133 | ||
| 127 | public: | 134 | public: |
| 128 | pointer_t get_allocation() const; | 135 | pointer_t get_allocation() const |
| 136 | { | ||
| 137 | // Remove const on the this pointer so the offset can be computed. | ||
| 138 | auto non_const_this = const_cast<vm_alloc_t *>(this); | ||
| 139 | return reinterpret_cast<pointer_t>(reinterpret_cast<uint8_t *>(non_const_this) + sizeof(vm_alloc_t)); | ||
| 140 | } | ||
| 129 | 141 | ||
| 130 | template <typename T> | 142 | template <typename T> |
| 131 | T *get_allocation() const | 143 | T *get_allocation() const |
| @@ -638,7 +650,7 @@ namespace disvm · 506 unmodified lines | |||
| 638 | class vm_frame_t final | 650 | class vm_frame_t final |
| 639 | { | 651 | { |
| 640 | public: | 652 | public: |
| 641 | vm_frame_t(std::shared_ptr<const type_descriptor_t> &frame_type); | 653 | vm_frame_t(std::shared_ptr<const type_descriptor_t> frame_type); |
| 642 | ~vm_frame_t(); | 654 | ~vm_frame_t(); |
| 643 | 655 | ||
| 644 | std::shared_ptr<const type_descriptor_t> frame_type; | 656 | std::shared_ptr<const type_descriptor_t> frame_type; |
| @@ -49,23 +49,37 @@ namespace disvm · 48 unmodified lines | |||
| 49 | // Decrement the ref count and if 0 free the allocation | 49 | // Decrement the ref count and if 0 free the allocation |
| 50 | void dec_ref_count_and_free(vm_alloc_t *alloc); | 50 | void dec_ref_count_and_free(vm_alloc_t *alloc); |
| 51 | 51 | ||
| 52 | // Callback for a pointer field supplying the pointer | 52 | // Function to enumerate pointer fields in an object. The function is defined |
| 53 | using pointer_field_callback_t = void(*)(pointer_t); | 53 | // as a template to permit raw function pointers or lambdas. The signature |
| 54 | 54 | // of the callback must be 'void(pointer_t *)' and is supplied a pointer to the | |
| 55 | // The callback will be called on all non-null pointer fields. | 55 | // non-null pointer field. The offset of the field is relative to the supplied |
| 56 | void enum_pointer_fields(const type_descriptor_t &type_desc, void *data, pointer_field_callback_t callback); | 56 | // 'data' pointer. |
| 57 | 57 | template<typename CB> | |
| 58 | // Callback for a pointer field supplying the pointer and a calling context | 58 | void enum_pointer_fields(const type_descriptor_t &type_desc, void *data, CB callback) |
| 59 | using pointer_field_callback_ext_t = void(*)(pointer_t, void *cxt); | 59 | { |
| 60 | 60 | assert(data != nullptr && callback != nullptr); | |
| 61 | // The callback will be called on all non-null pointer fields. | 61 | |
| 62 | void enum_pointer_fields(const type_descriptor_t &type_desc, void *data, pointer_field_callback_ext_t callback, void *cxt); | 62 | auto memory = reinterpret_cast<word_t *>(data); |
| 63 | 63 | for (auto i = word_t{ 0 }; i < type_desc.map_in_bytes; ++i, memory += 8) | |
| 64 | // Callback for a pointer field supplying the pointer and byte offset | 64 | { |
| 65 | using pointer_field_offset_callback_t = std::function<void(pointer_t, std::size_t)>; | 65 | const auto words8 = type_desc.pointer_map[i]; |
| 66 | 66 | assert(sizeof(words8) == 1); | |
| 67 | // The callback will be called on all non-null pointer fields. | 67 | if (words8 == 0) |
| 68 | void enum_pointer_fields_with_offset(const type_descriptor_t &type_desc, void *data, pointer_field_offset_callback_t callback); | 68 | continue; |
| 69 | |||
| 70 | const auto flags = std::bitset<sizeof(words8) * 8>{ words8 }; | ||
| 71 | |||
| 72 | // Enumerating the flags in reverse order so memory access is sequential. | ||
| 73 | if (flags[7] && (memory[0] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t *>(memory)); | ||
| 74 | if (flags[6] && (memory[1] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t *>(memory) + 1); | ||
| 75 | if (flags[5] && (memory[2] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t *>(memory) + 2); | ||
| 76 | if (flags[4] && (memory[3] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t *>(memory) + 3); | ||
| 77 | if (flags[3] && (memory[4] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t *>(memory) + 4); | ||
| 78 | if (flags[2] && (memory[5] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t *>(memory) + 5); | ||
| 79 | if (flags[1] && (memory[6] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t *>(memory) + 6); | ||
| 80 | if (flags[0] && (memory[7] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t *>(memory) + 7); | ||
| 81 | } | ||
| 82 | } | ||
| 69 | 83 | ||
| 70 | // Check if a specific pointer-sized offset in a type represents a pointer | 84 | // Check if a specific pointer-sized offset in a type represents a pointer |
| 71 | bool is_offset_pointer(const type_descriptor_t &type_desc, std::size_t offset); | 85 | bool is_offset_pointer(const type_descriptor_t &type_desc, std::size_t offset); |