summaryrefslogtreecommitdiff
path: root/src/lisp/ao_lisp_frame.c
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2016-11-15 20:18:59 -0800
committerKeith Packard <keithp@keithp.com>2017-02-20 11:16:51 -0800
commit881161fe1c5fb0e2b1220c30572eb2c45bedbafe (patch)
tree36070649f2e3d46de239f769cc67cc765f3b9c9a /src/lisp/ao_lisp_frame.c
parent994adc7a47cbf3cbf6041eca7430273f8018de08 (diff)
altos/lisp: re-use small frames
This saves a pile more use of the allocator by noting when frames have not been referenced from another frame and freeing them when they go out of scope. Frames with references are left to the allocator to deal with. Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'src/lisp/ao_lisp_frame.c')
-rw-r--r--src/lisp/ao_lisp_frame.c91
1 files changed, 61 insertions, 30 deletions
diff --git a/src/lisp/ao_lisp_frame.c b/src/lisp/ao_lisp_frame.c
index e23a6413..052d27d7 100644
--- a/src/lisp/ao_lisp_frame.c
+++ b/src/lisp/ao_lisp_frame.c
@@ -24,7 +24,7 @@ static int
frame_size(void *addr)
{
struct ao_lisp_frame *frame = addr;
- return frame_num_size(frame->num);
+ return frame_num_size(ao_lisp_frame_num(frame));
}
static void
@@ -37,7 +37,7 @@ frame_mark(void *addr)
MDBG_MOVE("frame mark %d\n", MDBG_OFFSET(frame));
if (!AO_LISP_IS_POOL(frame))
break;
- for (f = 0; f < frame->num; f++) {
+ for (f = 0; f < ao_lisp_frame_num(frame); f++) {
struct ao_lisp_val *v = &frame->vals[f];
ao_lisp_poly_mark(v->val, 0);
@@ -46,7 +46,7 @@ frame_mark(void *addr)
MDBG_OFFSET(ao_lisp_ref(v->atom)),
MDBG_OFFSET(ao_lisp_ref(v->val)), f);
}
- frame = ao_lisp_poly_frame(frame->next);
+ frame = ao_lisp_poly_frame(frame->prev);
MDBG_MOVE("frame next %d\n", MDBG_OFFSET(frame));
if (!frame)
break;
@@ -62,13 +62,13 @@ frame_move(void *addr)
int f;
for (;;) {
- struct ao_lisp_frame *next;
+ struct ao_lisp_frame *prev;
int ret;
MDBG_MOVE("frame move %d\n", MDBG_OFFSET(frame));
if (!AO_LISP_IS_POOL(frame))
break;
- for (f = 0; f < frame->num; f++) {
+ for (f = 0; f < ao_lisp_frame_num(frame); f++) {
struct ao_lisp_val *v = &frame->vals[f];
ao_lisp_poly_move(&v->atom, 0);
@@ -78,19 +78,19 @@ frame_move(void *addr)
MDBG_OFFSET(ao_lisp_ref(v->atom)),
MDBG_OFFSET(ao_lisp_ref(v->val)), f);
}
- next = ao_lisp_poly_frame(frame->next);
- if (!next)
+ prev = ao_lisp_poly_frame(frame->prev);
+ if (!prev)
break;
- ret = ao_lisp_move_memory(&ao_lisp_frame_type, (void **) &next);
- if (next != ao_lisp_poly_frame(frame->next)) {
- MDBG_MOVE("frame next moved from %d to %d\n",
- MDBG_OFFSET(ao_lisp_poly_frame(frame->next)),
- MDBG_OFFSET(next));
- frame->next = ao_lisp_frame_poly(next);
+ ret = ao_lisp_move_memory(&ao_lisp_frame_type, (void **) &prev);
+ if (prev != ao_lisp_poly_frame(frame->prev)) {
+ MDBG_MOVE("frame prev moved from %d to %d\n",
+ MDBG_OFFSET(ao_lisp_poly_frame(frame->prev)),
+ MDBG_OFFSET(prev));
+ frame->prev = ao_lisp_frame_poly(prev);
}
if (ret)
break;
- frame = next;
+ frame = prev;
}
}
@@ -109,15 +109,15 @@ ao_lisp_frame_print(ao_poly p)
printf ("{");
if (frame) {
- for (f = 0; f < frame->num; f++) {
+ for (f = 0; f < ao_lisp_frame_num(frame); f++) {
if (f != 0)
printf(", ");
ao_lisp_poly_print(frame->vals[f].atom);
printf(" = ");
ao_lisp_poly_print(frame->vals[f].val);
}
- if (frame->next)
- ao_lisp_poly_print(frame->next);
+ if (frame->prev)
+ ao_lisp_poly_print(frame->prev);
}
printf("}");
}
@@ -126,7 +126,7 @@ ao_poly *
ao_lisp_frame_ref(struct ao_lisp_frame *frame, ao_poly atom)
{
int f;
- for (f = 0; f < frame->num; f++)
+ for (f = 0; f < ao_lisp_frame_num(frame); f++)
if (frame->vals[f].atom == atom)
return &frame->vals[f].val;
return NULL;
@@ -143,7 +143,7 @@ ao_lisp_frame_set(struct ao_lisp_frame *frame, ao_poly atom, ao_poly val)
return 1;
}
}
- frame = ao_lisp_poly_frame(frame->next);
+ frame = ao_lisp_poly_frame(frame->prev);
}
return 0;
}
@@ -155,25 +155,55 @@ ao_lisp_frame_get(struct ao_lisp_frame *frame, ao_poly atom)
ao_poly *ref = ao_lisp_frame_ref(frame, atom);
if (ref)
return *ref;
- frame = ao_lisp_poly_frame(frame->next);
+ frame = ao_lisp_poly_frame(frame->prev);
}
return AO_LISP_NIL;
}
+struct ao_lisp_frame *ao_lisp_frame_free_list[AO_LISP_FRAME_FREE];
+
struct ao_lisp_frame *
ao_lisp_frame_new(int num)
{
- struct ao_lisp_frame *frame = ao_lisp_alloc(frame_num_size(num));
+ struct ao_lisp_frame *frame;
- if (!frame)
- return NULL;
+ if (num < AO_LISP_FRAME_FREE && (frame = ao_lisp_frame_free_list[num]))
+ ao_lisp_frame_free_list[num] = ao_lisp_poly_frame(frame->prev);
+ else {
+ frame = ao_lisp_alloc(frame_num_size(num));
+ if (!frame)
+ return NULL;
+ }
frame->type = AO_LISP_FRAME;
- frame->num = num;
- frame->next = AO_LISP_NIL;
+ frame->_num = num;
+ frame->prev = AO_LISP_NIL;
memset(frame->vals, '\0', num * sizeof (struct ao_lisp_val));
return frame;
}
+ao_poly
+ao_lisp_frame_mark(struct ao_lisp_frame *frame)
+{
+ if (!frame)
+ return AO_LISP_NIL;
+ if (frame->_num == 0xff)
+ ao_lisp_abort();
+ frame->_num |= AO_LISP_FRAME_MARK;
+ return ao_lisp_frame_poly(frame);
+}
+
+void
+ao_lisp_frame_free(struct ao_lisp_frame *frame)
+{
+ if (!ao_lisp_frame_marked(frame)) {
+ int num = ao_lisp_frame_num(frame);
+ if (num < AO_LISP_FRAME_FREE) {
+ frame->prev = ao_lisp_frame_poly(ao_lisp_frame_free_list[num]);
+ ao_lisp_frame_free_list[num] = frame;
+ }
+ }
+}
+
static struct ao_lisp_frame *
ao_lisp_frame_realloc(struct ao_lisp_frame **frame_ref, int new_num)
{
@@ -181,7 +211,7 @@ ao_lisp_frame_realloc(struct ao_lisp_frame **frame_ref, int new_num)
struct ao_lisp_frame *new;
int copy;
- if (new_num == frame->num)
+ if (new_num == ao_lisp_frame_num(frame))
return frame;
new = ao_lisp_frame_new(new_num);
if (!new)
@@ -192,10 +222,11 @@ ao_lisp_frame_realloc(struct ao_lisp_frame **frame_ref, int new_num)
*/
frame = *frame_ref;
copy = new_num;
- if (copy > frame->num)
- copy = frame->num;
+ if (copy > ao_lisp_frame_num(frame))
+ copy = ao_lisp_frame_num(frame);
memcpy(new->vals, frame->vals, copy * sizeof (struct ao_lisp_val));
- new->next = frame->next;
+ new->prev = frame->prev;
+ ao_lisp_frame_free(frame);
return new;
}
@@ -210,7 +241,7 @@ ao_lisp_frame_add(struct ao_lisp_frame **frame_ref, ao_poly atom, ao_poly val)
ao_lisp_poly_stash(0, atom);
ao_lisp_poly_stash(1, val);
if (frame) {
- f = frame->num;
+ f = ao_lisp_frame_num(frame);
frame = ao_lisp_frame_realloc(frame_ref, f + 1);
} else {
f = 0;