Add janet_array_{get/set} for easier bounds checked access.

These functions also maintain barrier invariant(s). Also extend the
primtive collection optimization to tuples, for which it is much
simpler. For tuples, only maintain the invariant lazily. If on first
collection, all elements are primitive, we flag as such and never check
again.
This commit is contained in:
Calvin Rose
2026-09-05 11:26:40 -05:00
parent f1a9098875
commit 0ae8ab7b4a
3 changed files with 25 additions and 2 deletions
+13
View File
@@ -121,6 +121,19 @@ void janet_array_setcount(JanetArray *array, int32_t count) {
array->count = count;
}
/* Set an element in the array with assert bounds check. */
void janet_array_set(JanetArray *array, int32_t index, Janet x) {
janet_assert(index >= 0 && index < array->count, "bad array index");
array->data[index] = x;
array_elem_primcheck(array, x);
}
/* For symmetry with janet_array_set with assert bounds check. Direct indexing is prefered for perf. */
Janet janet_array_get(JanetArray *array, int32_t index) {
janet_assert(index >= 0 && index < array->count, "bad array index");
return array->data[index];
}
/* Push a value to the top of the array */
void janet_array_push(JanetArray *array, Janet x) {
if (array->count == INT32_MAX) {
+9 -2
View File
@@ -217,8 +217,15 @@ recur:
static void janet_mark_tuple(const Janet *tuple) {
if (janet_gc_reachable(janet_tuple_head(tuple)))
return;
janet_gc_mark(janet_tuple_head(tuple));
janet_mark_many(tuple, janet_tuple_length(tuple));
JanetTupleHead *head = janet_tuple_head(tuple);
janet_gc_mark((JanetGCObject *) head);
if (head->gc.flags & JANET_TUPLE_FLAG_PRIMITIVES) {
/* TODO - debug routine to check array for non-primitives. If we find any, assert */
return;
}
if (janet_mark_many(tuple, janet_tuple_length(tuple))) {
head->gc.flags |= JANET_TUPLE_FLAG_PRIMITIVES;
}
}
/* Helper to mark function environments */
+3
View File
@@ -1113,6 +1113,7 @@ struct JanetAbstractHead {
/* Mark an array as containing only primitive types. Hint for the garbage collector */
#define JANET_ARRAY_FLAG_PRIMITIVES ((int32_t)0x10000)
#define JANET_TUPLE_FLAG_PRIMITIVES ((int32_t)0x20000) /* Don't collide with JANET_TUPLE_FLAG_BRACKETCTOR */
/* Source mapping structure for a bytecode instruction */
struct JanetSourceMapping {
@@ -1781,6 +1782,8 @@ JANET_API void janet_array_setcount(JanetArray *array, int32_t count);
JANET_API void janet_array_push(JanetArray *array, Janet x);
JANET_API Janet janet_array_pop(JanetArray *array);
JANET_API Janet janet_array_peek(JanetArray *array);
JANET_API void janet_array_set(JanetArray *array, int32_t index, Janet x);
JANET_API Janet janet_array_get(JanetArray *array, int32_t index);
/* Buffer functions */
#define JANET_BUFFER_FLAG_NO_REALLOC 0x10000