stone pool renamed to constant pool - more appropriate
This commit is contained in:
157
source/runtime.c
157
source/runtime.c
@@ -134,53 +134,53 @@ void JS_DeleteGCRef (JSContext *ctx, JSGCRef *ref) {
|
||||
}
|
||||
}
|
||||
|
||||
void *st_alloc (JSContext *ctx, size_t bytes, size_t align) {
|
||||
void *ct_alloc (JSContext *ctx, size_t bytes, size_t align) {
|
||||
/* Align the request */
|
||||
bytes = (bytes + align - 1) & ~(align - 1);
|
||||
|
||||
/* Check if we have space in the stone arena */
|
||||
if (ctx->stone_base && ctx->stone_free + bytes <= ctx->stone_end) {
|
||||
void *ptr = ctx->stone_free;
|
||||
ctx->stone_free += bytes;
|
||||
/* Check if we have space in the constant text pool */
|
||||
if (ctx->ct_base && ctx->ct_free + bytes <= ctx->ct_end) {
|
||||
void *ptr = ctx->ct_free;
|
||||
ctx->ct_free += bytes;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* No stone arena or not enough space - allocate a page */
|
||||
size_t page_size = sizeof (StonePage) + bytes;
|
||||
StonePage *page = malloc (page_size);
|
||||
/* No pool space - allocate a page */
|
||||
size_t page_size = sizeof (CTPage) + bytes;
|
||||
CTPage *page = malloc (page_size);
|
||||
if (!page) return NULL;
|
||||
|
||||
page->next = ctx->st_pages;
|
||||
page->next = ctx->ct_pages;
|
||||
page->size = bytes;
|
||||
ctx->st_pages = page;
|
||||
ctx->ct_pages = page;
|
||||
|
||||
return page->data;
|
||||
}
|
||||
|
||||
/* Free all stone arena pages */
|
||||
void st_free_all (JSContext *ctx) {
|
||||
StonePage *page = ctx->st_pages;
|
||||
/* Free all constant text pool pages */
|
||||
void ct_free_all (JSContext *ctx) {
|
||||
CTPage *page = ctx->ct_pages;
|
||||
while (page) {
|
||||
StonePage *next = page->next;
|
||||
CTPage *next = page->next;
|
||||
free (page);
|
||||
page = next;
|
||||
}
|
||||
ctx->st_pages = NULL;
|
||||
ctx->ct_pages = NULL;
|
||||
}
|
||||
|
||||
int st_text_resize (JSContext *ctx) {
|
||||
uint32_t new_size, new_resize;
|
||||
int ct_resize (JSContext *ctx) {
|
||||
uint32_t new_size, new_threshold;
|
||||
uint32_t *new_hash;
|
||||
JSText **new_array;
|
||||
|
||||
if (ctx->st_text_size == 0) {
|
||||
if (ctx->ct_size == 0) {
|
||||
/* Initial allocation */
|
||||
new_size = ST_TEXT_INITIAL_SIZE;
|
||||
new_size = CT_INITIAL_SIZE;
|
||||
} else {
|
||||
/* Double the size */
|
||||
new_size = ctx->st_text_size * 2;
|
||||
new_size = ctx->ct_size * 2;
|
||||
}
|
||||
new_resize = new_size * 3 / 4; /* 75% load factor */
|
||||
new_threshold = new_size * 3 / 4; /* 75% load factor */
|
||||
|
||||
/* Allocate new hash table (use runtime malloc, not bump allocator) */
|
||||
new_hash = js_malloc_rt (new_size * sizeof (uint32_t));
|
||||
@@ -196,10 +196,10 @@ int st_text_resize (JSContext *ctx) {
|
||||
memset (new_array, 0, (new_size + 1) * sizeof (JSText *));
|
||||
|
||||
/* Rehash existing entries */
|
||||
if (ctx->st_text_count > 0) {
|
||||
if (ctx->ct_count > 0) {
|
||||
uint32_t mask = new_size - 1;
|
||||
for (uint32_t id = 1; id <= ctx->st_text_count; id++) {
|
||||
JSText *text = ctx->st_text_array[id];
|
||||
for (uint32_t id = 1; id <= ctx->ct_count; id++) {
|
||||
JSText *text = ctx->ct_array[id];
|
||||
new_array[id] = text;
|
||||
|
||||
/* Compute hash and find slot */
|
||||
@@ -212,13 +212,13 @@ int st_text_resize (JSContext *ctx) {
|
||||
}
|
||||
|
||||
/* Free old tables */
|
||||
if (ctx->st_text_hash) js_free_rt (ctx->st_text_hash);
|
||||
if (ctx->st_text_array) js_free_rt (ctx->st_text_array);
|
||||
if (ctx->ct_hash) js_free_rt (ctx->ct_hash);
|
||||
if (ctx->ct_array) js_free_rt (ctx->ct_array);
|
||||
|
||||
ctx->st_text_hash = new_hash;
|
||||
ctx->st_text_array = new_array;
|
||||
ctx->st_text_size = new_size;
|
||||
ctx->st_text_resize = new_resize;
|
||||
ctx->ct_hash = new_hash;
|
||||
ctx->ct_array = new_array;
|
||||
ctx->ct_size = new_size;
|
||||
ctx->ct_resize_threshold = new_threshold;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -251,12 +251,12 @@ JSValue intern_text_to_value (JSContext *ctx, const uint32_t *utf32, uint32_t le
|
||||
uint64_t hash = fash64_hash_words (packed, word_count, len);
|
||||
|
||||
/* Look up in hash table */
|
||||
uint32_t mask = ctx->st_text_size - 1;
|
||||
uint32_t mask = ctx->ct_size - 1;
|
||||
uint32_t slot = hash & mask;
|
||||
|
||||
while (ctx->st_text_hash[slot] != 0) {
|
||||
uint32_t id = ctx->st_text_hash[slot];
|
||||
JSText *existing = ctx->st_text_array[id];
|
||||
while (ctx->ct_hash[slot] != 0) {
|
||||
uint32_t id = ctx->ct_hash[slot];
|
||||
JSText *existing = ctx->ct_array[id];
|
||||
if (text_equal (existing, packed, len)) {
|
||||
/* Found existing entry */
|
||||
return JS_MKPTR (existing);
|
||||
@@ -265,18 +265,18 @@ JSValue intern_text_to_value (JSContext *ctx, const uint32_t *utf32, uint32_t le
|
||||
}
|
||||
|
||||
/* Not found - create new entry */
|
||||
if (ctx->st_text_count >= ctx->st_text_resize) {
|
||||
if (st_text_resize (ctx) < 0) return JS_NULL; /* OOM */
|
||||
if (ctx->ct_count >= ctx->ct_resize_threshold) {
|
||||
if (ct_resize (ctx) < 0) return JS_NULL; /* OOM */
|
||||
/* Recompute slot after resize */
|
||||
mask = ctx->st_text_size - 1;
|
||||
mask = ctx->ct_size - 1;
|
||||
slot = hash & mask;
|
||||
while (ctx->st_text_hash[slot] != 0)
|
||||
while (ctx->ct_hash[slot] != 0)
|
||||
slot = (slot + 1) & mask;
|
||||
}
|
||||
|
||||
/* Allocate JSText in stone arena */
|
||||
/* Allocate JSText in constant text pool */
|
||||
size_t text_size = sizeof (JSText) + word_count * sizeof (uint64_t);
|
||||
JSText *text = st_alloc (ctx, text_size, 8);
|
||||
JSText *text = ct_alloc (ctx, text_size, 8);
|
||||
if (!text) return JS_NULL; /* OOM */
|
||||
|
||||
/* Initialize the text */
|
||||
@@ -285,9 +285,9 @@ JSValue intern_text_to_value (JSContext *ctx, const uint32_t *utf32, uint32_t le
|
||||
memcpy (text->packed, packed, word_count * sizeof (uint64_t));
|
||||
|
||||
/* Add to intern table */
|
||||
uint32_t new_id = ++ctx->st_text_count;
|
||||
ctx->st_text_hash[slot] = new_id;
|
||||
ctx->st_text_array[new_id] = text;
|
||||
uint32_t new_id = ++ctx->ct_count;
|
||||
ctx->ct_hash[slot] = new_id;
|
||||
ctx->ct_array[new_id] = text;
|
||||
|
||||
return JS_MKPTR (text);
|
||||
}
|
||||
@@ -875,22 +875,11 @@ PPretext *ppretext_append_int (PPretext *p, int n) {
|
||||
}
|
||||
|
||||
/* Convert a JSValue string to a property key.
|
||||
For immediates, returns the value as-is (can be used directly as keys).
|
||||
For heap strings, returns interned version. */
|
||||
Returns the value as-is for immediates and heap texts.
|
||||
No allocation — cannot trigger GC. */
|
||||
JSValue js_key_from_string (JSContext *ctx, JSValue val) {
|
||||
if (MIST_IsImmediateASCII (val)) {
|
||||
return val; /* Immediates can be used directly as keys */
|
||||
}
|
||||
if (JS_IsText (val)) {
|
||||
JSText *p = JS_VALUE_GET_TEXT (val);
|
||||
int64_t len = JSText_len (p); /* Use JSText_len which checks header for stoned text */
|
||||
/* Extract UTF-32 characters and intern */
|
||||
uint32_t *utf32_buf = alloca (len * sizeof (uint32_t));
|
||||
for (int64_t i = 0; i < len; i++) {
|
||||
utf32_buf[i] = string_get (p, i);
|
||||
}
|
||||
return intern_text_to_value (ctx, utf32_buf, len);
|
||||
}
|
||||
if (MIST_IsImmediateASCII (val)) return val;
|
||||
if (JS_IsText (val)) return val;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
@@ -1019,7 +1008,7 @@ JSValue gc_copy_value (JSContext *ctx, JSValue v, uint8_t *from_base, uint8_t *f
|
||||
|
||||
for (;;) {
|
||||
void *ptr = JS_VALUE_GET_PTR (v);
|
||||
if (is_stone_ptr (ctx, ptr)) return v;
|
||||
if (is_ct_ptr (ctx, ptr)) return v;
|
||||
|
||||
if (!ptr_in_range (ptr, from_base, from_end)) return v;
|
||||
|
||||
@@ -1198,7 +1187,7 @@ int ctx_gc (JSContext *ctx, int allow_grow, size_t alloc_size) {
|
||||
void *gptr = JS_VALUE_GET_PTR(ctx->global_obj);
|
||||
printf(" ptr=%p in_from=%d is_stone=%d\n", gptr,
|
||||
((uint8_t*)gptr >= from_base && (uint8_t*)gptr < from_end),
|
||||
is_stone_ptr(ctx, gptr));
|
||||
is_ct_ptr(ctx, gptr));
|
||||
fflush(stdout);
|
||||
}
|
||||
#endif
|
||||
@@ -1414,14 +1403,14 @@ JSContext *JS_NewContextRawWithHeapSize (JSRuntime *rt, size_t heap_size) {
|
||||
/* Initialize per-context execution state (moved from JSRuntime) */
|
||||
ctx->current_exception = JS_NULL;
|
||||
|
||||
/* Initialize stone text intern table */
|
||||
ctx->st_pages = NULL;
|
||||
ctx->st_text_array = NULL;
|
||||
ctx->st_text_hash = NULL;
|
||||
ctx->st_text_count = 0;
|
||||
ctx->st_text_size = 0;
|
||||
ctx->st_text_resize = 0;
|
||||
if (st_text_resize (ctx) < 0) {
|
||||
/* Initialize constant text intern table */
|
||||
ctx->ct_pages = NULL;
|
||||
ctx->ct_array = NULL;
|
||||
ctx->ct_hash = NULL;
|
||||
ctx->ct_count = 0;
|
||||
ctx->ct_size = 0;
|
||||
ctx->ct_resize_threshold = 0;
|
||||
if (ct_resize (ctx) < 0) {
|
||||
js_free_rt (ctx->class_array);
|
||||
js_free_rt (ctx->class_proto);
|
||||
js_free_rt (ctx);
|
||||
@@ -1433,8 +1422,8 @@ JSContext *JS_NewContextRawWithHeapSize (JSRuntime *rt, size_t heap_size) {
|
||||
ctx->next_block_size = ctx->current_block_size;
|
||||
ctx->heap_base = heap_block_alloc (rt, ctx->current_block_size);
|
||||
if (!ctx->heap_base) {
|
||||
js_free_rt (ctx->st_text_hash);
|
||||
js_free_rt (ctx->st_text_array);
|
||||
js_free_rt (ctx->ct_hash);
|
||||
js_free_rt (ctx->ct_array);
|
||||
js_free_rt (ctx->class_array);
|
||||
js_free_rt (ctx->class_proto);
|
||||
js_free_rt (ctx);
|
||||
@@ -1501,10 +1490,10 @@ void JS_FreeContext (JSContext *ctx) {
|
||||
js_free_rt (ctx->class_array);
|
||||
js_free_rt (ctx->class_proto);
|
||||
|
||||
/* Free stone arena and intern table */
|
||||
st_free_all (ctx);
|
||||
js_free_rt (ctx->st_text_hash);
|
||||
js_free_rt (ctx->st_text_array);
|
||||
/* Free constant text pool and intern table */
|
||||
ct_free_all (ctx);
|
||||
js_free_rt (ctx->ct_hash);
|
||||
js_free_rt (ctx->ct_array);
|
||||
|
||||
/* Free heap block */
|
||||
if (ctx->heap_base) {
|
||||
@@ -2734,10 +2723,10 @@ JSValue JS_GetPropertyValue (JSContext *ctx, JSValue this_obj, JSValue prop) {
|
||||
if (JS_IsArray (this_obj)) {
|
||||
return JS_NULL;
|
||||
}
|
||||
/* Create an interned key from the string */
|
||||
/* Use text directly as key */
|
||||
JSValue key = js_key_from_string (ctx, prop);
|
||||
ret = JS_GetProperty (ctx, this_obj, key);
|
||||
/* key is interned or immediate, no need to free */
|
||||
/* key is the original text or immediate */
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2919,7 +2908,7 @@ JSValue JS_GetPropertyKey (JSContext *ctx, JSValue this_obj, JSValue key) {
|
||||
return rec_get (ctx, rec, key);
|
||||
}
|
||||
|
||||
/* For string keys, create an interned key and use JS_GetProperty */
|
||||
/* For string keys, use text directly as key */
|
||||
if (JS_IsText (key)) {
|
||||
JSValue prop_key = js_key_from_string (ctx, key);
|
||||
return JS_GetProperty (ctx, this_obj, prop_key);
|
||||
@@ -2946,7 +2935,7 @@ int JS_SetPropertyKey (JSContext *ctx, JSValue this_obj, JSValue key, JSValue va
|
||||
return rec_set_own (ctx, rec, key, val);
|
||||
}
|
||||
|
||||
/* For string keys, create an interned key */
|
||||
/* For string keys, use text directly as key */
|
||||
if (JS_IsText (key)) {
|
||||
JSValue prop_key = js_key_from_string (ctx, key);
|
||||
return JS_SetPropertyInternal (ctx, this_obj, prop_key, val);
|
||||
@@ -2956,8 +2945,8 @@ int JS_SetPropertyKey (JSContext *ctx, JSValue this_obj, JSValue key, JSValue va
|
||||
return JS_SetPropertyInternal (ctx, this_obj, key, val);
|
||||
}
|
||||
|
||||
/* GC-SAFE for record keys (no allocations).
|
||||
String keys call js_key_from_string then JS_HasProperty which re-chases. */
|
||||
/* GC-SAFE: no allocations.
|
||||
String keys pass through js_key_from_string (no interning). */
|
||||
int JS_HasPropertyKey (JSContext *ctx, JSValue obj, JSValue key) {
|
||||
if (JS_IsRecord (key)) {
|
||||
if (!JS_IsRecord (obj)) return FALSE;
|
||||
@@ -2970,7 +2959,7 @@ int JS_HasPropertyKey (JSContext *ctx, JSValue obj, JSValue key) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* For string keys, create an interned key */
|
||||
/* For string keys, use text directly as key */
|
||||
if (JS_IsText (key)) {
|
||||
JSValue prop_key = js_key_from_string (ctx, key);
|
||||
return JS_HasProperty (ctx, obj, prop_key);
|
||||
@@ -2998,7 +2987,7 @@ int JS_DeletePropertyKey (JSContext *ctx, JSValue obj, JSValue key) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* For string keys, create an interned key */
|
||||
/* For string keys, use text directly as key */
|
||||
if (JS_IsText (key)) {
|
||||
JSValue prop_key = js_key_from_string (ctx, key);
|
||||
return JS_DeleteProperty (ctx, obj, prop_key);
|
||||
@@ -8281,7 +8270,7 @@ static JSValue js_cell_array_sort (JSContext *ctx, JSValue this_val, int argc, J
|
||||
} else if (JS_VALUE_GET_TAG (argv[1]) == JS_TAG_STRING
|
||||
|| JS_VALUE_GET_TAG (argv[1]) == JS_TAG_STRING_IMM) {
|
||||
JSValue prop_key = js_key_from_string (ctx, argv[1]);
|
||||
/* Re-read items[i] after allocation (js_key_from_string can trigger GC) */
|
||||
/* Re-read items[i] (js_key_from_string no longer allocates, but re-read is harmless) */
|
||||
arr = JS_VALUE_GET_ARRAY (arr_ref.val);
|
||||
items[i] = arr->values[i];
|
||||
key = JS_GetProperty (ctx, items[i], prop_key);
|
||||
@@ -8564,7 +8553,7 @@ static JSValue js_cell_object (JSContext *ctx, JSValue this_val, int argc, JSVal
|
||||
if (i >= (int)keys->len) break;
|
||||
JSValue key = keys->values[i];
|
||||
if (JS_IsText (key)) {
|
||||
/* Use JSValue key directly - create interned key */
|
||||
/* Use text directly as key */
|
||||
JSValue prop_key = js_key_from_string (ctx, key);
|
||||
JSValue val;
|
||||
if (argc < 2 || JS_IsNull (func_ref.val)) {
|
||||
|
||||
Reference in New Issue
Block a user