diff --git a/scripts/engine.cm b/scripts/engine.cm index b0ea5312..4df444de 100644 --- a/scripts/engine.cm +++ b/scripts/engine.cm @@ -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) diff --git a/scripts/shop.cm b/scripts/shop.cm index e9fa1570..e2587e4c 100644 --- a/scripts/shop.cm +++ b/scripts/shop.cm @@ -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,18 +528,15 @@ 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) } function resolve_locator(path, ext, ctx) -{ +{ var local_path if (ctx) local_path = `.cell/modules/${ctx}/${path}${ext}` @@ -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}` diff --git a/scripts/text.c b/scripts/text.c index 33040cc2..6ecff687 100644 --- a/scripts/text.c +++ b/scripts/text.c @@ -1,5 +1,4 @@ #include "cell.h" -#include "blob.h" #include #include diff --git a/source/blob.h b/source/blob.h index 91d760de..964e5e32 100644 --- a/source/blob.h +++ b/source/blob.h @@ -5,6 +5,7 @@ #include #include #include +#include // ----------------------------------------------------------------------------- // 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; diff --git a/source/qjs_actor.c b/source/qjs_actor.c index 3d48ad25..0ddfa96f 100644 --- a/source/qjs_actor.c +++ b/source/qjs_actor.c @@ -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); diff --git a/source/qjs_blob.c b/source/qjs_blob.c index 2213f310..f8535527 100644 --- a/source/qjs_blob.c +++ b/source/qjs_blob.c @@ -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)) { @@ -320,6 +322,8 @@ static JSValue js_blob_read_blob(JSContext *ctx, JSValueConst this_val, if (!new_bd) { 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); } @@ -524,6 +528,8 @@ JSValue js_new_blob_stoned_copy(JSContext *js, void *data, size_t bytes) memcpy(b->data, data, 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); } diff --git a/source/scheduler_threaded.c b/source/scheduler_threaded.c index 778ab556..586a5ec9 100644 --- a/source/scheduler_threaded.c +++ b/source/scheduler_threaded.c @@ -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);