overengineered piece of shit, but compiles fine

This commit is contained in:
2026-06-14 18:15:44 -06:00
parent 5f4c2abec8
commit 869ce0c7bf
5 changed files with 309 additions and 218 deletions
+7 -7
View File
@@ -26,7 +26,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u8 readU8(u64 ip) = 0; virtual u8 readU8(u64 ip) const = 0;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -34,7 +34,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u16 readU16(u64 ip) = 0; virtual u16 readU16(u64 ip) const = 0;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -42,7 +42,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u32 readU32(u64 ip) = 0; virtual u32 readU32(u64 ip) const = 0;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -50,20 +50,20 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u64 readU64(u64 ip) = 0; virtual u64 readU64(u64 ip) const = 0;
/** /**
* Reads a range of data, and * Reads a range of data, and
* outputs it. * outputs it.
*/ */
virtual void readRange(u64 ip, u8* out, u64 length) = 0; virtual void readRange(u64 ip, u8* out, u64 length) const = 0;
virtual void loadRegister(u64 ip, u8 size_code, register_t* r) = 0; virtual void loadRegister(u64 ip, u8 size_code, register_t* r) const = 0;
/** /**
* Current size of the instructions. * Current size of the instructions.
*/ */
virtual u64 size() = 0; virtual u64 size() const = 0;
public: // Static Utils // public: // Static Utils //
+266 -165
View File
@@ -5,181 +5,69 @@
namespace spider { namespace spider {
InstrReelDyn::InstrReelDyn(u64 length) : _size(length) { InstrReelDyn::InstrReelDyn(u64 length) : _size(length) {
// Safe int ceil division if (_size == 0) return;
growTo((length >> 8) + ((length & 255) != 0));
// 1. Allocate and fill the buffer with zeroed blocks
grow(_size);
_buffer.assign(_size, 0);
// 2. Pad the physical vector to match block alignment
if (_buffer.size() % _blocksize != 0) {
u64 padding = _blocksize - (_buffer.size() % _blocksize);
_buffer.insert(_buffer.end(), padding, 0);
} }
//InstrReelDyn::InstrReelDyn(const u8* data, u64 length) {} // 3. Manifest the initial blank part in our orchestration
_pieces.push_back({ 0, _size });
}
InstrReelDyn::InstrReelDyn(const u8* data, u64 length) : _size(0) {
if (length == 0) return;
grow(length);
write(0, data, length);
}
InstrReelDyn::InstrReelDyn(const InstrReelDyn& copy) InstrReelDyn::InstrReelDyn(const InstrReelDyn& copy)
: _blocks(copy._blocks), _size(copy._size) { : _buffer(copy._buffer),
} _pieces(copy._pieces),
_size(copy._size) {}
// No-throw Move Constructor
InstrReelDyn::InstrReelDyn(InstrReelDyn&& move) noexcept InstrReelDyn::InstrReelDyn(InstrReelDyn&& move) noexcept
: _blocks(std::move(move._blocks)), _size(std::move(move._size)) { : _buffer(std::move(move._buffer)),
_pieces(std::move(move._pieces)),
_size(move._size) {
move._size = 0;
} }
// Explicit Destructor execution
InstrReelDyn::~InstrReelDyn() { InstrReelDyn::~InstrReelDyn() {
// .. // _pieces.clear();
_buffer.clear();
} }
// Deep Copy Assignment Operator
InstrReelDyn& InstrReelDyn::operator=(const InstrReelDyn& copy) { InstrReelDyn& InstrReelDyn::operator=(const InstrReelDyn& copy) {
_blocks = copy._blocks; if (this != &copy) {
_buffer = copy._buffer;
_pieces = copy._pieces;
_size = copy._size; _size = copy._size;
}
return *this; return *this;
} }
// No-throw Move Assignment Operator
InstrReelDyn& InstrReelDyn::operator=(InstrReelDyn&& move) noexcept { InstrReelDyn& InstrReelDyn::operator=(InstrReelDyn&& move) noexcept {
_blocks = std::move(move._blocks); if (this != &move) {
_size = std::move(move._size); _buffer = std::move(move._buffer);
_pieces = std::move(move._pieces);
_size = move._size;
move._size = 0;
}
return *this; return *this;
} }
void InstrReelDyn::growTo(u64 ip) { void InstrReelDyn::loadRegister(u64 ip, u8 size_code, register_t* r) const {
u64 b_index = (ip >> 8) + 1;
while (_blocks.size() < b_index) {
_blocks.emplace_back();
}
if (ip >= _size) _size = ip + 1;
}
std::pair<u64, u8> InstrReelDyn::indexOf(u64 ip) {
return { ip >> 8, ip & 0xFF }; // { ip / 256, ip % 256 };
}
bool InstrReelDyn::continous(u64 ip0, u64 ip1, u64* b_index, u16* s_index) {
auto i = indexOf(ip0);
*b_index = i.first;
*s_index = i.second;
return i.first == (ip1 >> 8);
}
// Particular Cases
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
u8 InstrReelDyn::readU8(u64 ip) {
if (ip + 1 > _size) return 0;
auto i = indexOf(ip);
return _blocks[i.first].data[i.second];
}
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
u16 InstrReelDyn::readU16(u64 ip) {
if (ip + 2 > _size) return 0;
u16 dat;
u64 b_index;
u16 s_index;
if (continous(ip, ip + 1, &b_index, &s_index)) {
spider::loadLE(&dat, &_blocks[b_index].data[s_index]);
return dat;
}
dat = 0;
for (isize i = 0; i < sizeof(dat); i++) {
auto& b = _blocks[(b_index + s_index) >> 8];
dat |= u16(b.data[s_index++ & 0xFF] << (i * 8));
}
return dat;
}
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
u32 InstrReelDyn::readU32(u64 ip) {
if (ip + 4 > _size) return 0;
u32 dat;
u64 b_index;
u16 s_index;
if (continous(ip, ip + 3, &b_index, &s_index)) {
spider::loadLE(&dat, &_blocks[b_index].data[s_index]);
return dat;
}
dat = 0;
for (isize i = 0; i < sizeof(dat); i++) {
auto& b = _blocks[(b_index + s_index) >> 8];
dat |= u32(b.data[s_index++ & 0xFF]) << (i * 8);
}
return dat;
}
/**
* Obtains a byte of data at
* the specific location.
* Reindexing may occur, continous access
* may incurr in less penalties.
*/
u64 InstrReelDyn::readU64(u64 ip) {
if (ip + 8 > _size) return 0;
u64 dat;
u64 b_index;
u16 s_index;
if (continous(ip, ip + 7, &b_index, &s_index)) {
spider::loadLE(&dat, &_blocks[b_index].data[s_index]);
return dat;
}
dat = 0;
for (isize i = 0; i < sizeof(dat); i++) {
auto& b = _blocks[(b_index + s_index) >> 8];
dat |= u64(b.data[s_index++ & 0xFF]) << (i * 8);
}
return dat;
}
/**
* Reads a range of data, and
* outputs it.
*/
void InstrReelDyn::readRange(u64 ip, u8* out, u64 length) {
if (ip + length > _size) {
std::memset(out, 0, length);
return;
}
u64 b_index;
u16 s_index;
if (continous(ip, ip + length, &b_index, &s_index)) {
std::memcpy(out, &_blocks[b_index].data[s_index], length);
return;
}
u64 bytes_read = 0;
while (bytes_read < length) {
u64 remaining_in_block = 256 - s_index;
u64 chunk_size = std::min(remaining_in_block, length - bytes_read);
// Perform bulk copy for the current segment
std::memcpy(out + bytes_read, &_blocks[b_index].data[s_index], chunk_size);
// Advance pointers
bytes_read += chunk_size;
b_index++;
s_index = 0; // reset
}
}
void InstrReelDyn::loadRegister(u64 ip, u8 size_code, register_t* r) {
u8 bytes[8]; u8 bytes[8];
readRange(ip, bytes, 1 << size_code); readRange(ip, bytes, 1 << size_code);
spider::loadRegister[size_code](r, bytes, 8); spider::loadRegister[size_code](r, bytes, 8);
@@ -188,22 +76,235 @@ namespace spider {
/** /**
* Current size of the instructions. * Current size of the instructions.
*/ */
u64 InstrReelDyn::size() { u64 InstrReelDyn::size() const {
return _size; return _size;
} }
// Reading, Prepared //
u8 InstrReelDyn::readU8(u64 ip) const {
u8 dat;
u8 arr[sizeof(dat)];
readRange(ip, arr, sizeof(arr));
spider::loadPartialLE(&dat, arr, sizeof(arr));
return dat;
}
u16 InstrReelDyn::readU16(u64 ip) const {
u16 dat;
u8 arr[sizeof(dat)];
readRange(ip, arr, sizeof(arr));
spider::loadPartialLE(&dat, arr, sizeof(arr));
return dat;
}
u32 InstrReelDyn::readU32(u64 ip) const {
u32 dat;
u8 arr[sizeof(dat)];
readRange(ip, arr, sizeof(arr));
spider::loadPartialLE(&dat, arr, sizeof(arr));
return dat;
}
u64 InstrReelDyn::readU64(u64 ip) const {
u64 dat;
u8 arr[sizeof(dat)];
readRange(ip, arr, sizeof(arr));
spider::loadPartialLE(&dat, arr, sizeof(arr));
return dat;
}
// Mutation // // Mutation //
// TODO! void InstrReelDyn::readRange(u64 ip, u8* dat, const u64 len) const {
// 1. Boundary Guard
if (len == 0 || ip + len > _size || dat == nullptr) return;
//void InstrReelDyn::writeU8(u64 ip, u8 dat) {} u64 bytes_copied = 0;
//void InstrReelDyn::writeU16(u64 ip, u16 dat) {} u64 current_ip = 0;
//void InstrReelDyn::writeU32(u64 ip, u32 dat) {}
//void InstrReelDyn::writeU64(u64 ip, u64 dat) {}
/** for (const auto& p : _pieces) {
* Appends instruction at the end. u64 piece_start = current_ip;
*/ u64 piece_end = current_ip + p.length;
//void InstrReelDyn::append(u16 bc) {}
// 2. Determine if the requested read window overlaps with this piece
if (ip + bytes_copied < piece_end && (ip + len) > piece_start) {
// Calculate where inside this specific piece our read window begins
u64 read_start_logical = std::max(ip + bytes_copied, piece_start);
u64 local_offset_within_piece = read_start_logical - piece_start;
// Calculate how many remaining bytes can be extracted from this piece
u64 available_in_piece = p.length - local_offset_within_piece;
u64 bytes_to_copy = std::min(len - bytes_copied, available_in_piece);
// 3. Perform safe unaligned copy from our master buffer to the user's destination
const u8* src_ptr = _buffer.data() + p.offset + local_offset_within_piece;
std::memcpy(dat + bytes_copied, src_ptr, bytes_to_copy);
bytes_copied += bytes_to_copy;
// 4. Optimization: Break early if we've completely satisfied the read request
if (bytes_copied == len) {
break;
}
}
current_ip += p.length;
}
}
void InstrReelDyn::write(u64 ip, const u8* dat, const u64 len) {
if (len == 0) return;
// If writing inside existing data, we OVERWRITE by removing the old section first.
// If ip >= _size, it naturally appends, so remove does nothing.
if (ip < _size) {
u64 bytes_to_overwrite = std::min(len, _size - ip);
remove(ip, bytes_to_overwrite);
}
// 1. Capture the exact physical offset BEFORE inserting data or padding
grow(len);
u64 write_offset = _buffer.size();
_buffer.insert(_buffer.end(), dat, dat + len);
// Apply padding immediately so _buffer.size() is always clean for the next run
if (_buffer.size() % _blocksize != 0) {
u64 padding = _blocksize - (_buffer.size() % _blocksize);
_buffer.insert(_buffer.end(), padding, 0);
}
// 2. Orchestrate Pieces (This is strictly an Insertion now because Old Data was removed)
if (_pieces.empty() || ip >= _size) {
_pieces.push_back({ write_offset, len });
_size += len;
return;
}
u64 current_ip = 0;
for (auto it = _pieces.begin(); it != _pieces.end(); ++it) {
if (current_ip + it->length >= ip) {
u64 local_offset = ip - current_ip;
if (local_offset == 0) {
_pieces.insert(it, { write_offset, len });
} else {
// Split the piece cleanly
piece left = { it->offset, local_offset };
piece right = { it->offset + local_offset, it->length - local_offset };
*it = left; // Update existing piece to be the 'left' side
auto next_it = std::next(it);
next_it = _pieces.insert(next_it, { write_offset, len });
_pieces.insert(std::next(next_it), right);
}
break; // Essential: stop processing once the piece is handled!
}
current_ip += it->length;
}
_size += len;
}
void InstrReelDyn::remove(u64 ip, const u64 len) {
if (len == 0 || ip + len > _size) return;
u64 current_ip = 0;
u64 bytes_to_remove = len;
for (auto it = _pieces.begin(); it != _pieces.end() && bytes_to_remove > 0;) {
u64 piece_start = current_ip;
u64 piece_end = current_ip + it->length;
if (ip < piece_end && (ip + bytes_to_remove) > piece_start) {
u64 overlap_start = std::max(ip, piece_start);
u64 overlap_end = std::min(ip + bytes_to_remove, piece_end);
u64 overlap_len = overlap_end - overlap_start;
u64 local_offset = overlap_start - piece_start;
if (local_offset == 0 && overlap_len == it->length) {
it = _pieces.erase(it); // Returns next valid iterator safely
} else if (local_offset == 0) {
it->offset += overlap_len;
it->length -= overlap_len;
++it;
} else if (local_offset + overlap_len == it->length) {
it->length -= overlap_len;
++it;
} else {
// Slice a hole out of the middle
piece right = { it->offset + local_offset + overlap_len, it->length - (local_offset + overlap_len) };
it->length = local_offset;
_pieces.insert(std::next(it), right);
break;
}
bytes_to_remove -= overlap_len;
} else {
current_ip += it->length;
++it;
}
}
_size -= len;
}
void InstrReelDyn::defragment() {
// 1. Edge Case: If the buffer is completely empty, reset states cleanly
if (_size == 0) {
_pieces.clear();
_buffer.clear();
_size = 0;
return;
}
// 2. Optimization: If there is only 1 piece and it's already aligned at physical offset 0,
// then the buffer is already perfectly defragmented. Skip the work entirely.
if (_pieces.size() == 1 && _pieces.front().offset == 0) {
return;
}
// 3. Allocate a fresh, temporary vector aligned perfectly to your 256-byte blocks
std::vector<u8> clean_buffer;
// We use the same rounding formula to ensure clean_buffer matches block boundaries
u64 blocks_needed = (_size + _blocksize - 1) / _blocksize;
clean_buffer.reserve(blocks_needed * _blocksize);
// 4. Linearly stream only the ACTIVE byte chunks into our clean buffer
for (const auto& p : _pieces) {
const u8* src_ptr = _buffer.data() + p.offset;
clean_buffer.insert(clean_buffer.end(), src_ptr, src_ptr + p.length);
}
// 5. Enforce trailing block alignment padding
if (clean_buffer.size() % _blocksize != 0) {
u64 padding = _blocksize - (clean_buffer.size() % _blocksize);
clean_buffer.insert(clean_buffer.end(), padding, 0);
}
// 6. Fast O(1) swap to point your class to the new optimized buffer
_buffer = std::move(clean_buffer);
// 7. Reset piece orchestration to a single monolithic piece mapping 1:1
_pieces.clear();
_pieces.push_back({ 0, _size });
}
void InstrReelDyn::grow(u64 len) {
u64 current_capacity = _buffer.capacity();
// Account for requested bytes PLUS up to a block's worth of trailing alignment padding
u64 minimum_needed = _buffer.size() + len + (_blocksize - 1);
if (minimum_needed > current_capacity) {
// Grow exponentially (1.5x). If empty, seed it with 1 full block minimum.
u64 raw_growth = (current_capacity == 0) ? _blocksize : current_capacity + (current_capacity / 2);
u64 target_capacity = std::max(minimum_needed, raw_growth);
// Round the final target UP to the nearest 256-byte block
u64 blocks = (target_capacity + _blocksize - 1) / _blocksize;
_buffer.reserve(blocks * _blocksize);
}
}
} }
+20 -28
View File
@@ -2,6 +2,8 @@
#include <spider/runtime/reel/InstrReel.hpp> #include <spider/runtime/reel/InstrReel.hpp>
#include <list>
namespace spider { namespace spider {
/** /**
@@ -10,13 +12,14 @@ namespace spider {
class InstrReelDyn : public InstrReel { class InstrReelDyn : public InstrReel {
private: private:
struct ReelBlock { struct piece {
u8 data[256] = {}; u64 offset;
u64 length;
}; };
private: static constexpr u64 _blocksize = 256;
std::vector<u8> _buffer;
deque<ReelBlock> _blocks; std::list<piece> _pieces;
u64 _size; u64 _size;
public: public:
@@ -37,14 +40,6 @@ namespace spider {
InstrReelDyn& operator=(InstrReelDyn&& move) noexcept; InstrReelDyn& operator=(InstrReelDyn&& move) noexcept;
private:
std::pair<u64, u8> indexOf(u64 ip);
bool continous(u64 ip0, u64 ip1, u64* b_index, u16* s_index);
void growTo(u64 ip);
public: public:
/** /**
@@ -53,7 +48,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u8 readU8(u64 ip) override; virtual u8 readU8(u64 ip) const override;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -61,7 +56,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u16 readU16(u64 ip) override; virtual u16 readU16(u64 ip) const override;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -69,7 +64,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u32 readU32(u64 ip) override; virtual u32 readU32(u64 ip) const override;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -77,35 +72,32 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u64 readU64(u64 ip) override; virtual u64 readU64(u64 ip) const override;
/** /**
* Reads a range of data, and * Reads a range of data, and
* outputs it. * outputs it.
*/ */
virtual void readRange(u64 ip, u8* out, u64 length) override; virtual void readRange(u64 ip, u8* out, u64 length) const override;
virtual void loadRegister(u64 ip, u8 size_code, register_t* r) override; virtual void loadRegister(u64 ip, u8 size_code, register_t* r) const override;
/** /**
* Current size of the instructions. * Current size of the instructions.
*/ */
virtual u64 size() override; virtual u64 size() const override;
public: public:
void writeU8(u64 ip, u8 dat); void write(u64 ip, const u8* dat, const u64 len);
void writeU16(u64 ip, u16 dat); void remove(u64 ip, const u64 len);
void writeU32(u64 ip, u32 dat); void defragment();
void writeU64(u64 ip, u64 dat); private:
/** void grow(u64 len);
* Appends instruction at the end.
*/
void append(u16 bc);
}; };
+7 -9
View File
@@ -42,44 +42,42 @@ namespace spider {
delete[] _mem; delete[] _mem;
} }
// General Case(s) //
// Instruction abstraction // // Instruction abstraction //
u8 InstrReelFixed::readU8(u64 ip) { u8 InstrReelFixed::readU8(u64 ip) const {
u8 dat; u8 dat;
spider::loadPartialLE(&dat, _mem + ip, _size); spider::loadPartialLE(&dat, _mem + ip, _size);
return dat; return dat;
} }
u16 InstrReelFixed::readU16(u64 ip) { u16 InstrReelFixed::readU16(u64 ip) const {
u16 dat; u16 dat;
spider::loadPartialLE(&dat, _mem + ip, _size); spider::loadPartialLE(&dat, _mem + ip, _size);
return dat; return dat;
} }
u32 InstrReelFixed::readU32(u64 ip) { u32 InstrReelFixed::readU32(u64 ip) const {
u32 dat; u32 dat;
spider::loadPartialLE(&dat, _mem + ip, _size); spider::loadPartialLE(&dat, _mem + ip, _size);
return dat; return dat;
} }
u64 InstrReelFixed::readU64(u64 ip) { u64 InstrReelFixed::readU64(u64 ip) const {
u64 dat; u64 dat;
spider::loadPartialLE(&dat, _mem + ip, _size); spider::loadPartialLE(&dat, _mem + ip, _size);
return dat; return dat;
} }
void InstrReelFixed::readRange(u64 ip, u8* out, u64 length) { void InstrReelFixed::readRange(u64 ip, u8* out, u64 length) const {
spider::loadPartialBytes(_mem, isize(ip), _size, out, length); spider::loadPartialBytes(_mem, isize(ip), _size, out, length);
} }
void InstrReelFixed::loadRegister(u64 ip, u8 size_code, register_t* r) { void InstrReelFixed::loadRegister(u64 ip, u8 size_code, register_t* r) const {
ip = std::min(ip, _size); ip = std::min(ip, _size);
spider::loadRegister[size_code](r, _mem + ip, _size - ip); spider::loadRegister[size_code](r, _mem + ip, _size - ip);
} }
u64 InstrReelFixed::size() { u64 InstrReelFixed::size() const {
return _size; return _size;
} }
+7 -7
View File
@@ -38,7 +38,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u8 readU8(u64 ip) override; virtual u8 readU8(u64 ip) const override;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -46,7 +46,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u16 readU16(u64 ip) override; virtual u16 readU16(u64 ip) const override;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -54,7 +54,7 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u32 readU32(u64 ip) override; virtual u32 readU32(u64 ip) const override;
/** /**
* Obtains a byte of data at * Obtains a byte of data at
@@ -62,20 +62,20 @@ namespace spider {
* Reindexing may occur, continous access * Reindexing may occur, continous access
* may incurr in less penalties. * may incurr in less penalties.
*/ */
virtual u64 readU64(u64 ip) override; virtual u64 readU64(u64 ip) const override;
/** /**
* Reads a range of data, and * Reads a range of data, and
* outputs it. * outputs it.
*/ */
virtual void readRange(u64 ip, u8* out, u64 length) override; virtual void readRange(u64 ip, u8* out, u64 length) const override;
virtual void loadRegister(u64 ip, u8 size_code, register_t* r) override; virtual void loadRegister(u64 ip, u8 size_code, register_t* r) const override;
/** /**
* Current size of the instructions. * Current size of the instructions.
*/ */
virtual u64 size() override; virtual u64 size() const override;
public: public: