This commit is contained in:
bQUARKz 2026-02-18 16:19:49 +00:00
parent 3d4d1dc45d
commit 650f1e0716
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
3 changed files with 104 additions and 51 deletions

View File

@ -3,6 +3,8 @@ pub mod local_addressing;
pub mod verifier;
mod virtual_machine;
pub mod vm_init_error;
pub mod object;
pub use prometeu_hal::{HostContext, HostReturn, NativeInterface, SyscallId};
pub use virtual_machine::{BudgetReport, LogicalFrameEndingReason, VirtualMachine};
pub use object::{object_flags, ObjectHeader, ObjectKind};

View File

@ -0,0 +1,102 @@
//! Canonical heap object header and kind tags.
//!
//! This module defines the minimal common header that prefixes every
//! heap-allocated object managed by the VM. The purpose of the header is to:
//! - allow the garbage collector (GC) to identify and classify objects,
//! - carry the object "kind" (type tag),
//! - optionally carry size/length metadata for variable-sized payloads.
//!
//! Scope of this file:
//! - No GC/traversal logic is implemented here.
//! - No allocation strategies are defined here.
//! - Only the data layout and documentation are provided.
//!
//! Layout and semantics
//! --------------------
//! The header has a fixed layout and uses `repr(C)` to keep a stable field order.
//!
//! Fields:
//! - `flags` (u8): bit flags used by the runtime/GC. Bit 0 is the GC "mark" bit.
//! Remaining bits are reserved for future use (e.g., color, pinning, etc.).
//! - `kind` (ObjectKind): object kind tag (stored as `u8`). It describes how the
//! object should be interpreted by higher layers (array, string, closure, ...).
//! - `payload_len` (u32): optional, object-specific length field. For fixed-size
//! objects this MAY be zero. For variable-size objects it typically stores the
//! element count (arrays) or byte length (strings). Exact interpretation is
//! defined by each object kind; the GC treats it as an opaque metadata field.
//!
//! Notes:
//! - The GC only relies on `flags` (mark bit) and `kind` to traverse/trace.
//! Actual traversal logic will be implemented elsewhere in future PRs.
//! - The header is intentionally compact (8 bytes on most targets) to minimize
//! per-object overhead.
//!
//! Safety & invariants:
//! - Every heap object MUST begin with an `ObjectHeader`.
//! - `kind` must contain a valid `ObjectKind` tag for the object's payload.
//! - `payload_len` must be consistent with the chosen `kind` (if applicable).
/// Object kind tags for heap objects.
///
/// This `repr(u8)` enum is stable across FFI boundaries and persisted images.
/// Do not reorder variants; append new ones at the end.
#[repr(u8)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum ObjectKind {
/// Reserved/unknown kind. Should not appear in valid allocations.
Unknown = 0,
/// UTF-8 string. `payload_len` is the number of bytes.
String = 1,
/// Homogeneous array of VM values/handles. `payload_len` is element count.
Array = 2,
/// Compiled closure/function value. Fixed-size payload (implementation-defined).
Closure = 3,
/// Byte buffer / blob. `payload_len` is the number of bytes.
Bytes = 4,
/// User-defined/native host object. Payload shape is host-defined.
UserData = 5,
// Future kinds must be appended here to keep tag numbers stable.
}
/// Bit flags stored in `ObjectHeader.flags`.
pub mod object_flags {
/// GC mark bit (used during tracing). 1 = marked, 0 = not marked.
pub const MARKED: u8 = 0b0000_0001;
// Reserved bits for future use:
// pub const PINNED: u8 = 0b0000_0010; // example: prevent movement/collection
}
/// Common header that prefixes every heap-allocated object.
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct ObjectHeader {
/// Runtime/GC flags. See `object_flags` for meanings.
pub flags: u8,
/// Object kind tag (compact `u8`). See `ObjectKind`.
pub kind: ObjectKind,
/// Optional length metadata for variable-sized payloads.
/// For fixed-size objects this may be zero.
pub payload_len: u32,
}
impl ObjectHeader {
/// Create a new header with given `kind` and `payload_len`, flags cleared.
pub const fn new(kind: ObjectKind, payload_len: u32) -> Self {
Self { flags: 0, kind, payload_len }
}
/// Returns true if the GC mark bit is set.
pub fn is_marked(&self) -> bool { (self.flags & object_flags::MARKED) != 0 }
/// Sets or clears the GC mark bit. Note: actual GC logic lives elsewhere.
pub fn set_marked(&mut self, value: bool) {
if value { self.flags |= object_flags::MARKED; } else { self.flags &= !object_flags::MARKED; }
}
}

View File

@ -1,54 +1,3 @@
## PR-3.2 — Define Heap Object Header and Object Kind Tags
### Briefing
All heap objects must share a common header so the GC can traverse them. This PR introduces the canonical object header and object kind tagging.
### Target
* Define a unified object header.
* Introduce object kind tags for future types (array, string, closure, etc.).
### Work items
* Define `ObjectHeader` containing:
* Mark bit or flag.
* Object kind/tag.
* Size or length field if required.
* Define an `ObjectKind` enum.
* Ensure header layout is clearly documented in comments.
* Do not implement traversal or GC logic yet.
### Acceptance checklist
* [ ] `ObjectHeader` and `ObjectKind` are defined.
* [ ] Code compiles without GC logic.
* [ ] Comments explain header semantics in English.
* [ ] `cargo test` passes.
### Tests
* None required.
### Junie instructions
**You MAY:**
* Introduce header structs and enums.
* Add comments explaining layout.
**You MUST NOT:**
* Implement object traversal logic.
* Add allocation strategies or pools.
**If unclear:**
* Ask before choosing header fields.
---
# PR-3.3 — Implement Basic Heap Allocator (No GC Yet)
### Briefing