From 253f4f1fdf3f050319e653e378f79661a211e2d3 Mon Sep 17 00:00:00 2001 From: Brett Laptop Date: Sun, 4 Aug 2024 22:07:41 -0400 Subject: [PATCH] silly little mutation now uses direct stack moving. --- CMakeLists.txt | 2 +- include/blt/gp/stack.h | 110 ++++++++++++++++++++++++++++++++++++++--- lib/blt | 2 +- src/transformers.cpp | 12 +++-- 4 files changed, 112 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d41bab4..3142371 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.0.114) +project(blt-gp VERSION 0.0.115) include(CTest) diff --git a/include/blt/gp/stack.h b/include/blt/gp/stack.h index 667691c..4db12c1 100644 --- a/include/blt/gp/stack.h +++ b/include/blt/gp/stack.h @@ -82,6 +82,102 @@ namespace blt::gp } }; + void insert(stack_allocator stack) + { + if (stack.empty()) + return; + // take a copy of the pointer to this stack's blocks + auto old_head = stack.head; + // stack is now empty, we have the last reference to it. + stack.head = nullptr; + // we don't have any nodes to search through or re-point, we can just assign the head + if (head == nullptr) + { + head = old_head; + return; + } + + // find the beginning of the stack + auto begin = old_head; + while (begin->metadata.prev != nullptr) + begin = begin->metadata.prev; + + // move along blocks with free space, attempt to insert bytes from one stack to another + auto insert = head; + while (insert->metadata.next != nullptr && begin != nullptr) + { + if (begin->used_bytes_in_block() <= insert->remaining_bytes_in_block()) + { + std::memcpy(insert->metadata.offset, begin->buffer, begin->used_bytes_in_block()); + insert->metadata.offset += begin->used_bytes_in_block(); + auto old_begin = begin; + begin = begin->metadata.next; + free_block(old_begin); + } + head = insert; + insert = insert->metadata.next; + } + if (begin == nullptr) + return; + while (insert->metadata.next != nullptr) + insert = insert->metadata.next; + // if here is space left we can move the pointers around + insert->metadata.next = begin; + begin->metadata.prev = insert; + // find where the head is now and set the head to this new point. + auto new_head = begin; + while (new_head->metadata.next != nullptr) + new_head = new_head->metadata.next; + head = new_head; + } + + /** + * Bytes must be the number of bytes to move, all types must have alignment accounted for + */ + void copy_from(const stack_allocator& stack, blt::size_t bytes) + { + if (stack.empty()) + { + BLT_WARN("This stack is empty, we will copy no bytes from it!"); + return; + } + auto start_block = stack.head; + auto bytes_left = static_cast(bytes); + blt::u8* start_point = nullptr; + while (bytes_left > 0) + { + if (start_block == nullptr) + { + BLT_WARN("This stack doesn't contain enough space to copy %ld bytes!", bytes); + BLT_WARN_STREAM << "State: " << size() << "\n"; + BLT_ABORT("Stack doesn't contain enough data for this copy operation!"); + } + if (start_block->used_bytes_in_block() < bytes_left) + { + bytes_left -= start_block->used_bytes_in_block(); + start_block = start_block->metadata.prev; + } else if (start_block->used_bytes_in_block() == bytes_left) + { + start_point = start_block->buffer; + break; + } else + { + start_point = start_block->metadata.offset - bytes_left; + break; + } + } + // we can copy the bytes directly, no special allocation + if (head->remaining_bytes_in_block() >= bytes_left) + { + std::memcpy(head->metadata.offset, start_point, bytes_left); + head->metadata.offset += bytes_left; + start_block = start_block->metadata.next; + } + while (start_block != nullptr) + { + + } + } /** * Pushes an instance of an object on to the stack @@ -337,7 +433,7 @@ namespace blt::gp { auto ptr = blk; blk = blk->metadata.next; - std::free(ptr); + free_block(ptr); } } free_chain(head); @@ -496,11 +592,16 @@ namespace blt::gp { block* ptr = current; current = current->metadata.prev; - std::free(ptr); + free_block(ptr); //get_allocator().deallocate(ptr); } } + static void free_block(block* ptr) + { + std::free(ptr); + } + inline bool move_back() { auto old = head; @@ -511,11 +612,6 @@ namespace blt::gp return false; } return true; - //free_chain(old); - // required to prevent silly memory :3 -// if (head != nullptr) -// head->metadata.next = nullptr; -// std::free(old); } private: diff --git a/lib/blt b/lib/blt index befd5e0..79ad108 160000 --- a/lib/blt +++ b/lib/blt @@ -1 +1 @@ -Subproject commit befd5e0ca1135c467f194d1d0e5691d301f93a34 +Subproject commit 79ad108fab60159461d4c78ffb97b910d446cc11 diff --git a/src/transformers.cpp b/src/transformers.cpp index e926523..fe03bc4 100644 --- a/src/transformers.cpp +++ b/src/transformers.cpp @@ -195,7 +195,7 @@ namespace blt::gp auto& new_vals_r = new_tree.get_values(); stack_allocator stack_after; - stack_allocator new_vals_flip; // this is annoying. + //stack_allocator new_vals_flip; // this is annoying. transfer_backward(vals_r, stack_after, ops_r.end() - 1, end_itr - 1); for (auto it = end_itr - 1; it != begin_itr - 1; it--) { @@ -203,8 +203,7 @@ namespace blt::gp vals_r.pop_bytes(static_cast(stack_allocator::aligned_size(it->type_size))); } - transfer_backward(new_vals_r, new_vals_flip, new_ops_r.end() - 1, new_ops_r.begin() - 1); - transfer_forward(new_vals_flip, vals_r, new_ops_r.begin(), new_ops_r.end()); + vals_r.insert(std::move(new_vals_r)); transfer_forward(stack_after, vals_r, end_itr, ops_r.end()); auto before = begin_itr - 1; @@ -225,7 +224,9 @@ namespace blt::gp if (bytes_expected != bytes_size) { - BLT_WARN("Child tree bytes %ld vs expected %ld", bytes_size, bytes_expected); + BLT_WARN_STREAM << "Stack state: " << vals_r.size() << "\n"; + BLT_WARN("Child tree bytes %ld vs expected %ld, difference: %ld", bytes_size, bytes_expected, + static_cast(bytes_expected) - static_cast(bytes_size)); BLT_ABORT("Amount of bytes in stack doesn't match the number of bytes expected for the operations"); } auto copy = c; @@ -236,7 +237,8 @@ namespace blt::gp } catch (...) { std::cout << "This occurred at point " << begin_point << " ending at (old) " << end_point << "\n"; - std::cout << "our root type is " << ops_r[begin_point].id << " with size " << stack_allocator::aligned_size(ops_r[begin_point].type_size) << "\n"; + std::cout << "our root type is " << ops_r[begin_point].id << " with size " << stack_allocator::aligned_size(ops_r[begin_point].type_size) + << "\n"; std::cout << "now Named: " << (program.get_name(ops_r[begin_point].id) ? *program.get_name(ops_r[begin_point].id) : "Unnamed") << "\n"; std::cout << "Was named: " << (program.get_name(begin_operator_id) ? *program.get_name(begin_operator_id) : "Unnamed") << "\n"; std::cout << "Parent:" << std::endl;