static struct ao_lisp_cons *save_cons[2];
static char *save_string[2];
-static ao_poly save_poly[2];
+static ao_poly save_poly[3];
static const struct ao_lisp_root ao_lisp_root[] = {
{
},
{
.type = &ao_lisp_string_type,
- .addr = (void **) &save_string[0]
+ .addr = (void **) &save_string[0],
},
{
.type = &ao_lisp_string_type,
- .addr = (void **) &save_string[1]
+ .addr = (void **) &save_string[1],
},
{
.type = NULL,
.type = NULL,
.addr = (void **) &save_poly[1]
},
+ {
+ .type = NULL,
+ .addr = (void **) &save_poly[2]
+ },
{
.type = &ao_lisp_atom_type,
.addr = (void **) &ao_lisp_atoms
return ((uint8_t *) addr) - ao_lisp_pool;
}
-/*
- * Convert back and forth between 'poly's used
- * as short addresses in the pool and addresses.
- * These are used in the chunk code.
- */
-static inline ao_poly pool_poly(void *addr) {
-#if DBG_MEM
- if (!AO_LISP_IS_POOL(addr))
- ao_lisp_abort();
-#endif
- return ((uint8_t *) addr) - AO_LISP_POOL_BASE;
-}
-
-static inline void *pool_ref(ao_poly p) {
- return AO_LISP_POOL_BASE + p;
-}
-
static inline void mark(uint8_t *tag, int offset) {
int byte = offset >> 5;
int bit = (offset >> 2) & 7;
static void
note_chunk(uint16_t addr, uint16_t size)
{
- int i;
+ int l, r;
- if (addr < chunk_low || chunk_high < addr)
+ if (addr < chunk_low || chunk_high <= addr)
return;
- for (i = 0; i < chunk_busy; i++) {
- if (ao_lisp_chunk[i].size && ao_lisp_chunk[i].old_addr == addr) {
-#if DBG_MEM
- if (ao_lisp_chunk[i].size != size)
- ao_lisp_abort();
-#endif
- return;
- }
- if (ao_lisp_chunk[i].old_addr > addr) {
- int end = min(AO_LISP_NCHUNK, chunk_busy + 1);
- memmove(&ao_lisp_chunk[i+1],
- &ao_lisp_chunk[i],
- (end - (i+1)) * sizeof (struct ao_lisp_chunk));
- break;
- }
- }
- if (i < AO_LISP_NCHUNK) {
- ao_lisp_chunk[i].old_addr = addr;
- ao_lisp_chunk[i].size = size;
- if (chunk_busy < AO_LISP_NCHUNK)
- chunk_busy++;
+ /* Binary search for the location */
+ l = 0;
+ r = chunk_busy - 1;
+ while (l <= r) {
+ int m = (l + r) >> 1;
+ if (ao_lisp_chunk[m].old_addr < addr)
+ l = m + 1;
else
- chunk_high = ao_lisp_chunk[AO_LISP_NCHUNK-1].old_addr +
- ao_lisp_chunk[AO_LISP_NCHUNK-1].size;
+ r = m - 1;
}
+ /*
+ * The correct location is always in 'l', with r = l-1 being
+ * the entry before the right one
+ */
+
+#if DBG_MEM
+ /* Off the right side */
+ if (l >= AO_LISP_NCHUNK)
+ ao_lisp_abort();
+
+ /* Off the left side */
+ if (l == 0 && chunk_busy && addr > ao_lisp_chunk[0].old_addr)
+ ao_lisp_abort();
+#endif
+
+ /* Shuffle existing entries right */
+ int end = min(AO_LISP_NCHUNK, chunk_busy + 1);
+
+ memmove(&ao_lisp_chunk[l+1],
+ &ao_lisp_chunk[l],
+ (end - (l+1)) * sizeof (struct ao_lisp_chunk));
+
+ /* Add new entry */
+ ao_lisp_chunk[l].old_addr = addr;
+ ao_lisp_chunk[l].size = size;
+
+ /* Increment the number of elements up to the size of the array */
+ if (chunk_busy < AO_LISP_NCHUNK)
+ chunk_busy++;
+
+ /* Set the top address if the array is full */
+ if (chunk_busy == AO_LISP_NCHUNK)
+ chunk_high = ao_lisp_chunk[AO_LISP_NCHUNK-1].old_addr +
+ ao_lisp_chunk[AO_LISP_NCHUNK-1].size;
}
static void
[AO_LISP_BUILTIN] = &ao_lisp_builtin_type,
[AO_LISP_FRAME] = &ao_lisp_frame_type,
[AO_LISP_LAMBDA] = &ao_lisp_lambda_type,
+ [AO_LISP_STACK] = &ao_lisp_stack_type,
};
static int
return cons;
}
+void
+ao_lisp_poly_stash(int id, ao_poly poly)
+{
+ save_poly[id] = poly;
+}
+
+ao_poly
+ao_lisp_poly_fetch(int id)
+{
+ ao_poly poly = save_poly[id];
+ save_poly[id] = AO_LISP_NIL;
+ return poly;
+}
+
void
ao_lisp_string_stash(int id, char *string)
{
save_string[id] = NULL;
return string;
}
-void
-ao_lisp_poly_stash(int id, ao_poly poly)
-{
- save_poly[id] = poly;
-}
-ao_poly
-ao_lisp_poly_fetch(int id)
-{
- ao_poly poly = save_poly[id];
- save_poly[id] = AO_LISP_NIL;
- return poly;
-}