summaryrefslogtreecommitdiff
path: root/gs/src/gsnogc.c
diff options
context:
space:
mode:
Diffstat (limited to 'gs/src/gsnogc.c')
-rw-r--r--gs/src/gsnogc.c98
1 files changed, 71 insertions, 27 deletions
diff --git a/gs/src/gsnogc.c b/gs/src/gsnogc.c
index 7ff6b4ddd..13028048e 100644
--- a/gs/src/gsnogc.c
+++ b/gs/src/gsnogc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1996, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -19,8 +19,8 @@
/* String freelist implementation and ersatz garbage collector */
#include "gx.h"
-#include "gsgc.h"
#include "gsmdebug.h"
+#include "gsnogc.h"
#include "gsstruct.h"
#include "gxalloc.h"
@@ -29,8 +29,26 @@
* in non-garbage-collected environments.
*/
-#define GET2(ptr) (((ptr)[0] << 8) + (ptr)[1])
-#define PUT2(ptr, val) ((ptr)[0] = (val) >> 8, (ptr)[1] = (byte)(val))
+/*
+ * Get and put unaligned 32-bit values. NOTE: these procedures must match
+ * the value of SFREE_NB defined in gxalloc.h.
+ */
+#define NB SFREE_NB
+#if NB == 4
+private uint
+get_uu32(const byte *ptr)
+{
+ return (ptr[0] << 24) + (ptr[1] << 16) + (ptr[2] << 8) + ptr[3];
+}
+private void
+put_uu32(byte *ptr, uint val)
+{
+ ptr[0] = val >> 24;
+ ptr[1] = (byte)(val >> 16);
+ ptr[2] = (byte)(val >> 8);
+ ptr[3] = (byte)val;
+}
+#endif /* otherwise, undefined procedures will give an error */
/* Allocate a string. */
/* Scan the current chunk's free list if the request is large enough. */
@@ -49,14 +67,14 @@ sf_alloc_string(gs_memory_t * mem, uint nbytes, client_name_t cname)
for (; offset != 0; prev = ptr, offset = next) {
ptr = base + offset;
- next = GET2(ptr + 2);
- if (GET2(ptr) != nbytes)
+ next = get_uu32(ptr + NB);
+ if (get_uu32(ptr) != nbytes)
continue;
/* Take this block. */
if (prev == 0)
imem->cc.sfree = next;
else
- PUT2(prev + 2, next);
+ put_uu32(prev + NB, next);
if_debug4('A', "[a%d:+>F]%s(%u) = 0x%lx\n", imem->space,
client_name_string(cname), nbytes, (ulong) ptr);
gs_alloc_fill(ptr, gs_alloc_fill_alloc, nbytes);
@@ -102,14 +120,14 @@ sf_free_string(gs_memory_t * mem, byte * str, uint size, client_name_t cname)
}
}
str_offset = str - csbase(cp);
- if (size >= 4) {
+ if (size >= 2 * NB) {
byte *prev;
uint next;
- PUT2(str, size);
+ put_uu32(str, size);
if (cp->sfree == 0 || str_offset < cp->sfree) {
/* Put the string at the head of the free list. */
- PUT2(str + 2, cp->sfree);
+ put_uu32(str + NB, cp->sfree);
cp->sfree = str_offset;
return;
}
@@ -117,22 +135,22 @@ sf_free_string(gs_memory_t * mem, byte * str, uint size, client_name_t cname)
prev = csbase(cp) + cp->sfree;
#ifdef DEBUG
if (gs_debug_c('?')) {
- if (prev < str + size && prev + GET2(prev) > str) {
+ if (prev < str + size && prev + get_uu32(prev) > str) {
lprintf4("freeing string 0x%lx(%u), overlaps 0x%lx(%u)!\n",
- (ulong) str, size, (ulong) prev, GET2(prev));
+ (ulong) str, size, (ulong) prev, get_uu32(prev));
return;
}
}
#endif
for (;;) {
- next = GET2(prev + 2);
+ next = get_uu32(prev + NB);
#ifdef DEBUG
if (gs_debug_c('?') && next != 0) {
byte *pnext = csbase(cp) + next;
- if (pnext < str + size && pnext + GET2(pnext) > str) {
+ if (pnext < str + size && pnext + get_uu32(pnext) > str) {
lprintf4("freeing string 0x%lx(%u), overlaps 0x%lx(%u)!\n",
- (ulong) str, size, (ulong) pnext, GET2(pnext));
+ (ulong) str, size, (ulong) pnext, get_uu32(pnext));
return;
}
}
@@ -141,15 +159,15 @@ sf_free_string(gs_memory_t * mem, byte * str, uint size, client_name_t cname)
break;
prev = csbase(cp) + next;
}
- PUT2(str + 2, next);
- PUT2(prev + 2, str_offset);
- gs_alloc_fill(str + 4, gs_alloc_fill_free, size - 4);
+ put_uu32(str + NB, next);
+ put_uu32(prev + NB, str_offset);
+ gs_alloc_fill(str + 2 * NB, gs_alloc_fill_free, size - 2 * NB);
} else {
/*
* Insert the string in the 1-byte free list(s). Note that
* if it straddles a 256-byte block, we need to do this twice.
*/
- ushort *pfree1 = &cp->sfree1[str_offset >> 8];
+ uint *pfree1 = &cp->sfree1[str_offset >> 8];
uint count = size;
byte *prev;
byte *ptr = str;
@@ -210,11 +228,11 @@ sf_merge_strings(chunk_t * cp)
for (;;) {
byte *ctop = cp->ctop;
uint top_offset = ctop - csbase(cp);
- ushort *pfree1;
+ uint *pfree1;
if (cp->sfree == top_offset) { /* Merge a large free block. */
- cp->sfree = GET2(ctop + 2);
- cp->ctop += GET2(ctop);
+ cp->sfree = get_uu32(ctop + NB);
+ cp->ctop += get_uu32(ctop);
continue;
}
if (!cp->sfree1)
@@ -235,12 +253,35 @@ sf_consolidate_free(gs_memory_t *mem)
gs_ref_memory_t *imem = (gs_ref_memory_t *)mem;
chunk_t *cp;
+ alloc_close_chunk(imem);
for (cp = imem->clast; cp != 0; cp = cp->cprev) {
byte *top = cp->ctop;
sf_merge_strings(cp);
imem->lost.strings -= cp->ctop - top;
+ if (cp->ctop == cp->climit && cp->smark_size != 0) {
+ /*
+ * No string space is being used. Since we are not using the
+ * 'string marking table' for GC, we can recover its space by
+ * deleting the smark area, setting smark_size = 0, and sliding
+ * up ctop and climit. We also need to recompute the size of
+ * the string freelist area (it will be larger, since the
+ * space potentially allocated to strings is larger).
+ */
+ cp->smark_size = 0;
+ cp->smark = 0;
+ /*
+ * Reserve enough space for the string freelist all the way to
+ * cend even though the climit will be moved to before the
+ * freelist area. This recovers most of the space.
+ */
+ cp->climit = cp->cend;
+ cp->climit -= STRING_FREELIST_SPACE(cp);
+ cp->ctop = cp->climit;
+ alloc_init_free_strings(cp);
+ }
}
+ alloc_open_chunk(imem);
/* Merge free objects, detecting entirely free chunks. */
ialloc_consolidate_free(imem);
@@ -251,18 +292,21 @@ sf_consolidate_free(gs_memory_t *mem)
* PostScript interpreter, but it is designed to be used in environments
* that don't need garbage collection and don't use save/restore. All it
* does is coalesce free blocks at the high end of the object area of each
- * chunk, and free strings at the low end of the string area, and then free
- * completely empty chunks.
+ * chunk, and free strings at the low end of the string area, and then if
+ * not 'controlled' memory, free completely empty chunks.
+ *
+ * Note that any string marking area will be added to the free space
+ * within the chunk if possible.
*/
void
-gs_reclaim(vm_spaces * pspaces, bool global)
+gs_nogc_reclaim(vm_spaces * pspaces, bool global)
{
int space;
gs_ref_memory_t *mem_prev = 0;
- for (space = 0; space < countof(pspaces->indexed); ++space) {
- gs_ref_memory_t *mem = pspaces->indexed[space];
+ for (space = 0; space < countof(pspaces->memories.indexed); ++space) {
+ gs_ref_memory_t *mem = pspaces->memories.indexed[space];
if (mem == 0 || mem == mem_prev)
continue;