diff --git a/crates/console/prometeu-vm/src/lib.rs b/crates/console/prometeu-vm/src/lib.rs index fa4fb06f..ecc5539a 100644 --- a/crates/console/prometeu-vm/src/lib.rs +++ b/crates/console/prometeu-vm/src/lib.rs @@ -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}; diff --git a/crates/console/prometeu-vm/src/object.rs b/crates/console/prometeu-vm/src/object.rs new file mode 100644 index 00000000..3f8bf563 --- /dev/null +++ b/crates/console/prometeu-vm/src/object.rs @@ -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; } + } +} diff --git a/files/TODOs.md b/files/TODOs.md index 54856320..056b3646 100644 --- a/files/TODOs.md +++ b/files/TODOs.md @@ -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