This commit is contained in:
2025-12-04 07:35:31 -06:00
parent 39ac340e01
commit 6b8464aca4
7 changed files with 82 additions and 61 deletions

View File

@@ -584,7 +584,8 @@ function turn(msg)
send_messages()
}
actor_mod.register_actor(cell.id, turn, cell.args.main, config.system.ar_timer)
log.console(`is main ${cell.args.main}`)
actor_mod.register_actor(cell.id, turn, true, config.system.ar_timer)
if (config.system.actor_memory)
js.mem_limit(config.system.actor_memory)

View File

@@ -472,8 +472,8 @@ var open_dls = {}
var script_forms = []
script_forms['.cm'] = function(path, script, pkg) {
// injecting a custom use function that passes the module path
var fn = `(function setup_module($_){ var use = function(path) { return globalThis.use(path, '${pkg}'); }; ${script}})`
var pkg_arg = pkg ? `'${pkg}'` : 'null'
var fn = `(function setup_module($_){ var use = function(path) { return globalThis.use(path, ${pkg_arg}); }; ${script}})`
return fn
}
@@ -514,7 +514,6 @@ function get_rel_path(path, pkg) {
function resolve_mod_fn(path, pkg)
{
if (!fd.is_file(path)) throw new Error(`path ${path} is not a file`)
var rel_path = get_rel_path(path, pkg)
var build_dir = get_build_dir(pkg)
var cache_path = build_dir + '/' + rel_path + '.o'
@@ -529,11 +528,8 @@ function resolve_mod_fn(path, pkg)
var script_form = script_forms[ext]
if (!script_form) throw new Error(`No script form for extension ${ext}`)
// Only log if we are actually compiling (which might happen during runtime if not built)
// log.console(`building ${path}`)
var script = script_form(path, text(fd.slurp(path)), pkg)
var fn = js.compile("script", script)
var fn = js.compile(path, script)
ensure_dir(cache_path.substring(0, cache_path.lastIndexOf('/')))
fd.slurpwrite(cache_path, js.compile_blob(fn))
return js.eval_compile(fn)
@@ -592,7 +588,6 @@ function resolve_c_symbol(path, package_ctx)
open_dls[local_dl_name] = os.dylib_open(local_dl_name);
if (open_dls[local_dl_name]) {
log.console(`Found local symbol ${local}`)
var local_addr = os.dylib_symbol(open_dls[local_dl_name], local);
if (local_addr) return {symbol: local_addr, scope: SCOPE_LOCAL};
}
@@ -646,9 +641,8 @@ Shop.use = function(path, package_context) {
var min_scope = Math.min(c_resolve.scope, mod_resolve.scope)
if (min_scope == 999) {
throw new Error(`Module ${path} could not be found`)
}
if (min_scope == 999)
throw new Error(`Module ${path} could not be found in ${package_context}`)
var cache_key = `${text(min_scope)}::${path}`

View File

@@ -1,5 +1,4 @@
#include "cell.h"
#include "blob.h"
#include <string.h>
#include <stdlib.h>

View File

@@ -5,6 +5,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
// -----------------------------------------------------------------------------
// A simple blob structure that can be in two states:
@@ -15,16 +16,7 @@
// we store them in a dynamic byte array with a length and capacity in bits.
// -----------------------------------------------------------------------------
typedef struct blob {
uint8_t *data;
// The total number of bits currently in use (the "length" of the blob).
size_t length;
size_t capacity;
// 0 = antestone (mutable)
// 1 = stone (immutable)
int is_stone;
} blob;
typedef struct blob blob;
// Create a new blob with specified bit capacity
blob *blob_new(size_t capacity);
@@ -35,6 +27,10 @@ blob *blob_new_from_blob(const blob *src, size_t from, size_t to);
// Create a blob with length bits, filled with logical value or random function
blob *blob_new_with_fill(size_t length_bits, int logical_value);
// Accessors
size_t blob_length(const blob *b);
const uint8_t *blob_data(const blob *b);
// Destroy blob and free memory
void blob_destroy(blob *b);
@@ -49,6 +45,7 @@ int blob_write_int64(blob *b, int64_t i);
int blob_write_fit(blob *b, int64_t value, int len);
int blob_write_pad(blob *b, int block_size);
int blob_write_text(blob *b, const char *text);
int blob_write_bytes(blob *b, const void *data, size_t len_bytes);
// Read operations (only work on stone blobs)
int blob_read_bit(const blob *b, size_t pos, int *out_bit);
@@ -64,6 +61,20 @@ int kim_length_for_fit(int64_t value);
#ifdef BLOB_IMPLEMENTATION
struct blob {
uint8_t *data;
// The total number of bits currently in use (the "length" of the blob).
size_t length;
size_t capacity;
// 0 = antestone (mutable)
// 1 = stone (immutable)
int is_stone;
};
size_t blob_length(const blob *b) { return b ? b->length : 0; }
const uint8_t *blob_data(const blob *b) { return b ? b->data : NULL; }
// Helper to ensure capacity for writing
static int blob_ensure_capacity(blob *b, size_t new_bits) {
size_t need_bits = b->length + new_bits;
@@ -91,14 +102,14 @@ static int blob_ensure_capacity(blob *b, size_t new_bits) {
}
// A simple bit-level memcpy (may handle unaligned bits at both ends)
void bitcpy(unsigned char *dst, int dst_bit_offset,
unsigned char *src, int src_bit_offset, int bit_length)
void bitcpy(unsigned char *dst, size_t dst_bit_offset,
unsigned char *src, size_t src_bit_offset, size_t bit_length)
{
int dst_byte_offset = dst_bit_offset / 8;
int src_byte_offset = src_bit_offset / 8;
size_t dst_byte_offset = dst_bit_offset / 8;
size_t src_byte_offset = src_bit_offset / 8;
int dst_bit = dst_bit_offset % 8;
int src_bit = src_bit_offset % 8;
int remaining_bits = bit_length;
size_t remaining_bits = bit_length;
if (dst_bit != 0 || src_bit != 0)
{
@@ -112,8 +123,8 @@ void bitcpy(unsigned char *dst, int dst_bit_offset,
src_byte_offset += (remaining_bits <= 0) ? 0 : 1;
}
int whole_bytes = remaining_bits / 8;
for (int i = 0; i < whole_bytes; i++)
size_t whole_bytes = remaining_bits / 8;
for (size_t i = 0; i < whole_bytes; i++)
dst[dst_byte_offset + i] = src[src_byte_offset + i];
remaining_bits %= 8;
dst_byte_offset += whole_bytes;
@@ -129,26 +140,26 @@ void bitcpy(unsigned char *dst, int dst_bit_offset,
// Fast bit-copy for arbitrary bit ranges (inclusive) from src → dest
void copy_bits_fast(const void *src, void *dest,
int n, /* start bit in src (inclusive) */
int m, /* end bit in src (inclusive) */
int x) /* start bit in dest */
size_t n, /* start bit in src (inclusive) */
size_t m, /* end bit in src (inclusive) */
size_t x) /* start bit in dest */
{
const uint8_t *s = (const uint8_t*)src;
uint8_t *d = (uint8_t*)dest;
int total_bits = m - n + 1;
if (total_bits <= 0) return;
size_t total_bits = m - n + 1;
if (m < n) return;
int src_bit = n;
int dst_bit = x;
int src_byte = src_bit >> 3;
int dst_byte = dst_bit >> 3;
size_t src_bit = n;
size_t dst_bit = x;
size_t src_byte = src_bit >> 3;
size_t dst_byte = dst_bit >> 3;
int src_off = src_bit & 7;
int dst_off = dst_bit & 7;
// 1) Leading partial byte to align dest
if (dst_off != 0) {
int chunk = 8 - dst_off;
size_t chunk = 8 - dst_off;
if (chunk > total_bits) chunk = total_bits;
uint8_t dst_mask = (((1u << chunk) - 1u) << dst_off);
@@ -169,14 +180,14 @@ void copy_bits_fast(const void *src, void *dest,
// 2) Copy full bytes
if (total_bits >= 8) {
if (src_off == 0) {
int num_bytes = total_bits >> 3;
memcpy(&d[dst_byte], &s[src_byte], (size_t)num_bytes);
size_t num_bytes = total_bits >> 3;
memcpy(&d[dst_byte], &s[src_byte], num_bytes);
total_bits -= num_bytes << 3;
src_byte += num_bytes;
dst_byte += num_bytes;
} else {
int num_bytes = total_bits >> 3;
for (int i = 0; i < num_bytes; i++) {
size_t num_bytes = total_bits >> 3;
for (size_t i = 0; i < num_bytes; i++) {
uint16_t wb = (uint16_t)s[src_byte + i] |
((uint16_t)s[src_byte + i + 1] << 8);
d[dst_byte + i] = (uint8_t)((wb >> src_off) & 0xFFu);
@@ -199,11 +210,10 @@ void copy_bits_fast(const void *src, void *dest,
// Copy bits [from..to) from src buffer into the blob at its current length
// (i.e. 'to' is exclusive). Advance blob->length by (to - from). Return 0.
static int blob_copy_bits(blob *dest, const void *src, size_t from, size_t to) {
if (from >= to) return 0;
size_t bits = to - from;
if (blob_ensure_capacity(dest, bits) < 0) return -1;
int n = (int)from;
int m = (int)(to - 1);
copy_bits_fast(src, dest->data, n, m, (int)dest->length);
copy_bits_fast(src, dest->data, from, to - 1, dest->length);
dest->length += bits;
return 0;
}
@@ -211,6 +221,7 @@ static int blob_copy_bits(blob *dest, const void *src, size_t from, size_t to) {
blob *blob_new(size_t capacity) {
if (capacity < 0) capacity = 0;
blob *b = calloc(1, sizeof(blob));
printf("allocating blob %p size %zu\n", b, capacity);
if (!b) return NULL;
if (blob_ensure_capacity(b, capacity) < 0) {
free(b);
@@ -253,6 +264,7 @@ blob *blob_new_with_fill(size_t length_bits, int logical_value) {
void blob_destroy(blob *b) {
if (!b) return;
printf("destroying blob %p, data %p, length %zu, capacity %zu\n", b, b->data, b->length, b->capacity);
if (b->data) {
free(b->data);
b->data = NULL;
@@ -304,7 +316,7 @@ int blob_write_blob(blob *b, const blob *src) {
int blob_write_dec64(blob *b, double d) {
if (!b || b->is_stone) return -1;
if (blob_ensure_capacity(b, 64) < 0) return -1;
copy_bits_fast(&d, b->data, 0, 64 - 1, (int)b->length);
copy_bits_fast(&d, b->data, 0, 64 - 1, b->length);
b->length += 64;
return 0;
}
@@ -312,7 +324,7 @@ int blob_write_dec64(blob *b, double d) {
int blob_write_int64(blob *b, int64_t i) {
if (!b || b->is_stone) return -1;
if (blob_ensure_capacity(b, 64) < 0) return -1;
copy_bits_fast(&i, b->data, 0, 64 - 1, (int)b->length);
copy_bits_fast(&i, b->data, 0, 64 - 1, b->length);
b->length += 64;
return 0;
}
@@ -329,7 +341,7 @@ int blob_write_fit(blob *b, int64_t value, int len) {
}
if (blob_ensure_capacity(b, len) < 0) return -1;
copy_bits_fast(&value, b->data, 0, len - 1, (int)b->length);
copy_bits_fast(&value, b->data, 0, len - 1, b->length);
b->length += len;
return 0;
}
@@ -362,12 +374,22 @@ int blob_write_text(blob *b, const char *text) {
// 2) Write raw text bytes (len * 8 bits)
if (len > 0) {
copy_bits_fast(text, b->data, 0, (int)(len * 8 - 1), (int)b->length);
copy_bits_fast(text, b->data, 0, len * 8 - 1, b->length);
b->length += (len * 8);
}
return 0;
}
int blob_write_bytes(blob *b, const void *data, size_t len_bytes) {
if (!b || b->is_stone) return -1;
if (len_bytes == 0) return 0;
size_t bits = len_bytes * 8;
if (blob_ensure_capacity(b, bits) < 0) return -1;
copy_bits_fast(data, b->data, 0, bits - 1, b->length);
b->length += bits;
return 0;
}
int blob_read_bit(const blob *b, size_t pos, int *out_bit) {
if (!b || !b->is_stone || !out_bit) return -1;
if (pos >= b->length) return -1;
@@ -387,7 +409,7 @@ int blob_read_dec64(const blob *b, size_t from, double *out_value) {
if (!b || !b->is_stone || !out_value) return -1;
if (from + 64 > b->length) return -1;
if (from < 0) return -1;
copy_bits_fast(b->data, out_value, (int)from, (int)(from + 64 - 1), 0);
copy_bits_fast(b->data, out_value, from, from + 64 - 1, 0);
return 0;
}
@@ -395,7 +417,7 @@ int blob_read_int64(const blob *b, size_t from, int length, int64_t *out_value)
if (!b || !b->is_stone || !out_value) return -1;
if (length < 0 || length > 64) return -1;
if (from + (size_t)length > b->length) return -1;
copy_bits_fast(b->data, out_value, (int)from, (int)(from + length - 1), 0);
copy_bits_fast(b->data, out_value, from, from + length - 1, 0);
return 0;
}
@@ -405,7 +427,7 @@ int blob_read_fit(const blob *b, size_t from, int len, int64_t *out_value) {
if (from + (size_t)len > b->length) return -1;
*out_value = 0;
copy_bits_fast(b->data, out_value, (int)from, (int)(from + len - 1), 0);
copy_bits_fast(b->data, out_value, from, from + len - 1, 0);
// Sign extend if necessary (if the high bit is set and len < 64)
if (len < 64 && (*out_value & (1LL << (len - 1)))) {
@@ -424,7 +446,7 @@ int blob_read_text(const blob *b, size_t from, char **out_text, size_t *bits_rea
int64_t raw_len = 0;
// Read 64 bits of length
copy_bits_fast(b->data, &raw_len, (int)from, (int)(from + 64 - 1), 0);
copy_bits_fast(b->data, &raw_len, from, from + 64 - 1, 0);
if (raw_len < 0) return -1;
size_t len = (size_t)raw_len;
@@ -438,7 +460,7 @@ int blob_read_text(const blob *b, size_t from, char **out_text, size_t *bits_rea
if (!str) return -1;
// Copy exactly len*8 bits into str[0..len-1]
copy_bits_fast(b->data, str, (int)after_len, (int)(after_len + (len * 8) - 1), 0);
copy_bits_fast(b->data, str, after_len, after_len + (len * 8) - 1, 0);
str[len] = '\0';
*out_text = str;

View File

@@ -57,8 +57,7 @@ JSC_CCALL(os_mailbox_push,
}
// Copy data to blob
memcpy(msg_blob->data, data, size);
msg_blob->length = size * 8;
blob_write_bytes(msg_blob, data, size);
blob_make_stone(msg_blob); // Make it immutable
const char *err = send_message(id, msg_blob);

View File

@@ -11,6 +11,7 @@
void blob_free(JSRuntime *rt, blob *b)
{
if (b) {
printf("destroying blob %p blob data %p, length %zu\n", b, b->data, b->length);
blob_destroy(b);
}
}
@@ -122,6 +123,7 @@ static JSValue js_blob_constructor(JSContext *ctx, JSValueConst new_target,
}
JSValue ret = blob2js(ctx, bd);
printf("created blob %p blob data %p, length %zu\n", bd, bd->data, bd->length);
// Ensure the returned object's prototype is set correctly for instanceof
JSValue ctor_proto = JS_GetPropertyStr(ctx, new_target, "prototype");
if (!JS_IsException(ctor_proto)) {
@@ -321,6 +323,8 @@ static JSValue js_blob_read_blob(JSContext *ctx, JSValueConst this_val,
return JS_ThrowOutOfMemory(ctx);
}
printf("stoned copy blob %p blob data %p, length %" PRId64 "\n", new_bd, new_bd->data, new_bd->length);
return blob2js(ctx, new_bd);
}
@@ -525,6 +529,8 @@ JSValue js_new_blob_stoned_copy(JSContext *js, void *data, size_t bytes)
b->length = bytes * 8; // Set the actual length in bits
blob_make_stone(b);
printf("stoned copy blob %p blob data %p, length %" PRId64 "\n", b, b->data, b->length);
return blob2js(js, b);
}

View File

@@ -587,8 +587,8 @@ void actor_turn(cell_rt *actor)
if (l.type == LETTER_BLOB) {
// Create a JS blob from the C blob
size_t size = l.blob_data->length / 8; // Convert bits to bytes
JSValue arg = js_new_blob_stoned_copy(actor->context, l.blob_data->data, size);
size_t size = blob_length(l.blob_data) / 8; // Convert bits to bytes
JSValue arg = js_new_blob_stoned_copy(actor->context, (void*)blob_data(l.blob_data), size);
blob_destroy(l.blob_data);
result = JS_Call(actor->context, actor->message_handle, JS_NULL, 1, &arg);
uncaught_exception(actor->context, result);