1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-08 12:44:23 +01:00

gpgscm: Use a static pool of cells for small integers.

* tests/gpgscm/scheme-private.h (struct scheme): New fields for the
static integer cells.
* tests/gpgscm/scheme.c (_alloc_cellseg): New function.
(alloc_cellseg): Use the new function.
(MAX_SMALL_INTEGER): New macro.
(initialize_small_integers): New function.
(mk_small_integer): Likewise.
(mk_integer): Return a small integer if possible.
(_s_return): Do not free 'op' if it is a small integer.
(s_save): Use a small integer to box the opcode.
(scheme_init_custom_alloc): Initialize small integers.
(scheme_deinit): Free chunk of small integers.
* tests/gpgscm/scheme.h (USE_SMALL_INTEGERS): New macro.

Signed-off-by: Justus Winter <justus@g10code.com>
This commit is contained in:
Justus Winter 2016-11-16 11:29:34 +01:00
parent 893a3f7fb4
commit 66834eb838
3 changed files with 108 additions and 19 deletions

@ -119,6 +119,12 @@ pointer SHARP_HOOK; /* *sharp-hook* */
pointer COMPILE_HOOK; /* *compile-hook* */
#endif
#if USE_SMALL_INTEGERS
/* A fixed allocation of small integers. */
void *integer_alloc;
pointer integer_cells;
#endif
pointer free_cell; /* pointer to top of free cells */
long fcells; /* # of free cells */
size_t inhibit_gc; /* nesting of gc_disable */

@ -598,34 +598,47 @@ static long binary_decode(const char *s) {
return x;
}
/* Allocate a new cell segment but do not make it available yet. */
static int
_alloc_cellseg(scheme *sc, size_t len, void **alloc, pointer *cells)
{
int adj = ADJ;
void *cp;
if (adj < sizeof(struct cell))
adj = sizeof(struct cell);
cp = sc->malloc(len * sizeof(struct cell) + adj);
if (cp == NULL)
return 1;
*alloc = cp;
/* adjust in TYPE_BITS-bit boundary */
if (((unsigned long) cp) % adj != 0)
cp = (void *) (adj * ((unsigned long) cp / adj + 1));
*cells = cp;
return 0;
}
/* allocate new cell segment */
static int alloc_cellseg(scheme *sc, int n) {
pointer newp;
pointer last;
pointer p;
void *cp;
long i;
int k;
int adj=ADJ;
if(adj<sizeof(struct cell)) {
adj=sizeof(struct cell);
}
for (k = 0; k < n; k++) {
if (sc->last_cell_seg >= CELL_NSEGMENT - 1)
return k;
cp = sc->malloc(CELL_SEGSIZE * sizeof(struct cell)+adj);
if (cp == 0)
return k;
i = ++sc->last_cell_seg ;
sc->alloc_seg[i] = cp;
/* adjust in TYPE_BITS-bit boundary */
if(((unsigned long)cp)%adj!=0) {
cp=(void *)(adj*((unsigned long)cp/adj+1));
}
i = ++sc->last_cell_seg;
if (_alloc_cellseg(sc, CELL_SEGSIZE, &sc->alloc_seg[i], &newp)) {
sc->last_cell_seg--;
return k;
}
/* insert new segment in address order */
newp=(pointer)cp;
sc->cell_seg[i] = newp;
while (i > 0 && sc->cell_seg[i - 1] > sc->cell_seg[i]) {
p = sc->cell_seg[i];
@ -1128,16 +1141,64 @@ INTERFACE pointer mk_character(scheme *sc, int c) {
return (x);
}
#if USE_SMALL_INTEGERS
/* s_save assumes that all opcodes can be expressed as a small
* integer. */
#define MAX_SMALL_INTEGER OP_MAXDEFINED
static int
initialize_small_integers(scheme *sc)
{
int i;
if (_alloc_cellseg(sc, MAX_SMALL_INTEGER, &sc->integer_alloc,
&sc->integer_cells))
return 1;
for (i = 0; i < MAX_SMALL_INTEGER; i++) {
pointer x = &sc->integer_cells[i];
typeflag(x) = T_NUMBER | T_ATOM | MARK;
ivalue_unchecked(x) = i;
set_num_integer(x);
}
return 0;
}
static INLINE pointer
mk_small_integer(scheme *sc, long n)
{
#define mk_small_integer_allocates 0
assert(0 <= n && n < MAX_SMALL_INTEGER);
return &sc->integer_cells[n];
}
#else
#define mk_small_integer_allocates 1
#define mk_small_integer mk_integer
#endif
/* get number atom (integer) */
INTERFACE pointer mk_integer(scheme *sc, long n) {
pointer x = get_cell(sc,sc->NIL, sc->NIL);
pointer x;
#if USE_SMALL_INTEGERS
if (0 <= n && n < MAX_SMALL_INTEGER)
return mk_small_integer(sc, n);
#endif
x = get_cell(sc,sc->NIL, sc->NIL);
typeflag(x) = (T_NUMBER | T_ATOM);
ivalue_unchecked(x)= n;
set_num_integer(x);
return (x);
}
INTERFACE pointer mk_real(scheme *sc, double n) {
pointer x = get_cell(sc,sc->NIL, sc->NIL);
@ -2645,7 +2706,9 @@ static pointer _s_return(scheme *sc, pointer a, int enable_gc) {
return sc->NIL;
free_cons(sc, dump, &op, &dump);
sc->op = ivalue(op);
#ifndef USE_SMALL_INTEGERS
free_cell(sc, op);
#endif
free_cons(sc, dump, &sc->args, &dump);
free_cons(sc, dump, &sc->envir, &dump);
free_cons(sc, dump, &sc->code, &sc->dump);
@ -2653,12 +2716,12 @@ static pointer _s_return(scheme *sc, pointer a, int enable_gc) {
}
static void s_save(scheme *sc, enum scheme_opcodes op, pointer args, pointer code) {
#define s_save_allocates 5
#define s_save_allocates (4 + mk_small_integer_allocates)
pointer dump;
gc_disable(sc, gc_reservations (s_save));
dump = cons(sc, sc->envir, cons(sc, (code), sc->dump));
dump = cons(sc, (args), dump);
sc->dump = cons(sc, mk_integer(sc, (long)(op)), dump);
sc->dump = cons(sc, mk_small_integer(sc, (long)(op)), dump);
gc_enable(sc);
}
@ -4907,6 +4970,14 @@ int scheme_init_custom_alloc(scheme *sc, func_alloc malloc, func_dealloc free) {
sc->T = &sc->_HASHT;
sc->F = &sc->_HASHF;
sc->EOF_OBJ=&sc->_EOF_OBJ;
#if USE_SMALL_INTEGERS
if (initialize_small_integers(sc)) {
sc->no_memory=1;
return 0;
}
#endif
sc->free_cell = &sc->_NIL;
sc->fcells = 0;
sc->inhibit_gc = GC_ENABLED;
@ -5052,6 +5123,10 @@ void scheme_deinit(scheme *sc) {
sc->gc_verbose=0;
gc(sc,sc->NIL,sc->NIL);
#if USE_SMALL_INTEGERS
sc->free(sc->integer_alloc);
#endif
for(i=0; i<=sc->last_cell_seg; i++) {
sc->free(sc->alloc_seg[i]);
}

@ -43,6 +43,7 @@ extern "C" {
# define USE_COMPILE_HOOK 0
# define USE_DL 0
# define USE_PLIST 0
# define USE_SMALL_INTEGERS 0
#endif
@ -95,6 +96,13 @@ extern "C" {
# define USE_THREADED_CODE 1
#endif
/* Use a static set of cells to represent small numbers. This set
* notably includes all opcodes, and hence saves a cell reservation
* during 's_save'. */
#ifndef USE_SMALL_INTEGERS
# define USE_SMALL_INTEGERS 1
#endif
#ifndef USE_STRCASECMP /* stricmp for Unix */
# define USE_STRCASECMP 0
#endif