mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
gpgscm: Use a compact vector representation.
* tests/gpgscm/scheme-private.h (struct cell): Add a compact vector representation. * tests/gpgscm/scheme.c (vector_length): Use new representation. (vector_size): New macro. (get_vector_object): Use the new representation. (fill_vector): Likewise. (vector_elem): Likewise. (set_vector_elem): Likewise. (mark): Likewise. (gc): Likewise. Be careful not to confuse immediate values for type flags. (finalize_cell): Vectors now require finalization. -- Previously, vectors were represented using consecutive cons cells, wasting one word per cell for the type information. Fix that by using a flat array. Previously, a vector of size N required 1 + (n + 1) / 2 cells. Now it uses 1 + (n - 1 + 2) / 3 cells. Signed-off-by: Justus Winter <justus@g10code.com>
This commit is contained in:
parent
e343984fc5
commit
49e2ae65e8
@ -55,6 +55,10 @@ struct cell {
|
|||||||
struct cell *_car;
|
struct cell *_car;
|
||||||
struct cell *_cdr;
|
struct cell *_cdr;
|
||||||
} _cons;
|
} _cons;
|
||||||
|
struct {
|
||||||
|
size_t _length;
|
||||||
|
pointer _elements[0];
|
||||||
|
} _vector;
|
||||||
struct {
|
struct {
|
||||||
char *_data;
|
char *_data;
|
||||||
const foreign_object_vtable *_vtable;
|
const foreign_object_vtable *_vtable;
|
||||||
|
@ -226,7 +226,11 @@ INTERFACE INLINE int is_string(pointer p) { return (type(p)==T_STRING); }
|
|||||||
|
|
||||||
INTERFACE static int is_list(scheme *sc, pointer p);
|
INTERFACE static int is_list(scheme *sc, pointer p);
|
||||||
INTERFACE INLINE int is_vector(pointer p) { return (type(p)==T_VECTOR); }
|
INTERFACE INLINE int is_vector(pointer p) { return (type(p)==T_VECTOR); }
|
||||||
#define vector_length(v) ivalue_unchecked(v)
|
/* Given a vector, return it's length. */
|
||||||
|
#define vector_length(v) (v)->_object._vector._length
|
||||||
|
/* Given a vector length, compute the amount of cells required to
|
||||||
|
* represent it. */
|
||||||
|
#define vector_size(len) (1 + ((len) - 1 + 2) / 3)
|
||||||
INTERFACE static void fill_vector(pointer vec, pointer obj);
|
INTERFACE static void fill_vector(pointer vec, pointer obj);
|
||||||
INTERFACE static pointer vector_elem(pointer vec, int ielem);
|
INTERFACE static pointer vector_elem(pointer vec, int ielem);
|
||||||
INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a);
|
INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a);
|
||||||
@ -1035,12 +1039,11 @@ static pointer get_cell(scheme *sc, pointer a, pointer b)
|
|||||||
|
|
||||||
static pointer get_vector_object(scheme *sc, int len, pointer init)
|
static pointer get_vector_object(scheme *sc, int len, pointer init)
|
||||||
{
|
{
|
||||||
pointer cells = get_consecutive_cells(sc,len/2+len%2+1);
|
pointer cells = get_consecutive_cells(sc, vector_size(len));
|
||||||
if(sc->no_memory) { return sc->sink; }
|
if(sc->no_memory) { return sc->sink; }
|
||||||
/* Record it as a vector so that gc understands it. */
|
/* Record it as a vector so that gc understands it. */
|
||||||
typeflag(cells) = (T_VECTOR | T_ATOM);
|
typeflag(cells) = (T_VECTOR | T_ATOM | T_FINALIZE);
|
||||||
vector_length(cells) = len;
|
vector_length(cells) = len;
|
||||||
set_num_integer(cells);
|
|
||||||
fill_vector(cells,init);
|
fill_vector(cells,init);
|
||||||
if (gc_enabled (sc))
|
if (gc_enabled (sc))
|
||||||
push_recent_alloc(sc, cells, sc->NIL);
|
push_recent_alloc(sc, cells, sc->NIL);
|
||||||
@ -1340,32 +1343,24 @@ INTERFACE static pointer mk_vector(scheme *sc, int len)
|
|||||||
{ return get_vector_object(sc,len,sc->NIL); }
|
{ return get_vector_object(sc,len,sc->NIL); }
|
||||||
|
|
||||||
INTERFACE static void fill_vector(pointer vec, pointer obj) {
|
INTERFACE static void fill_vector(pointer vec, pointer obj) {
|
||||||
int i;
|
size_t i;
|
||||||
int n = vector_length(vec) / 2 + vector_length(vec) % 2;
|
assert (is_vector (vec));
|
||||||
for(i=0; i < n; i++) {
|
for(i = 0; i < vector_length(vec); i++) {
|
||||||
typeflag(vec+1+i) = T_PAIR;
|
vec->_object._vector._elements[i] = set_immediate(obj);
|
||||||
setimmutable(vec+1+i);
|
|
||||||
car(vec+1+i)=obj;
|
|
||||||
cdr(vec+1+i)=obj;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERFACE static pointer vector_elem(pointer vec, int ielem) {
|
INTERFACE static pointer vector_elem(pointer vec, int ielem) {
|
||||||
int n=ielem/2;
|
assert (is_vector (vec));
|
||||||
if(ielem%2==0) {
|
assert (ielem < vector_length(vec));
|
||||||
return car(vec+1+n);
|
return clr_immediate(vec->_object._vector._elements[ielem]);
|
||||||
} else {
|
|
||||||
return cdr(vec+1+n);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a) {
|
INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a) {
|
||||||
int n=ielem/2;
|
assert (is_vector (vec));
|
||||||
if(ielem%2==0) {
|
assert (ielem < vector_length(vec));
|
||||||
return car(vec+1+n)=a;
|
vec->_object._vector._elements[ielem] = set_immediate(a);
|
||||||
} else {
|
return a;
|
||||||
return cdr(vec+1+n)=a;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get new symbol */
|
/* get new symbol */
|
||||||
@ -1563,10 +1558,8 @@ static void mark(pointer a) {
|
|||||||
E2: setmark(p);
|
E2: setmark(p);
|
||||||
if(is_vector(p)) {
|
if(is_vector(p)) {
|
||||||
int i;
|
int i;
|
||||||
int n = vector_length(p) / 2 + vector_length(p) % 2;
|
for (i = 0; i < vector_length(p); i++) {
|
||||||
for(i=0; i < n; i++) {
|
mark(clr_immediate(p->_object._vector._elements[i]));
|
||||||
/* Vector cells will be treated like ordinary cells */
|
|
||||||
mark(p+1+i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if SHOW_ERROR_LINE
|
#if SHOW_ERROR_LINE
|
||||||
@ -1672,6 +1665,8 @@ static void gc(scheme *sc, pointer a, pointer b) {
|
|||||||
for (i = sc->last_cell_seg; i >= 0; i--) {
|
for (i = sc->last_cell_seg; i >= 0; i--) {
|
||||||
p = sc->cell_seg[i] + CELL_SEGSIZE;
|
p = sc->cell_seg[i] + CELL_SEGSIZE;
|
||||||
while (--p >= sc->cell_seg[i]) {
|
while (--p >= sc->cell_seg[i]) {
|
||||||
|
if (typeflag(p) & IMMEDIATE_TAG)
|
||||||
|
continue;
|
||||||
if (is_mark(p)) {
|
if (is_mark(p)) {
|
||||||
clrmark(p);
|
clrmark(p);
|
||||||
} else {
|
} else {
|
||||||
@ -1708,6 +1703,16 @@ static void finalize_cell(scheme *sc, pointer a) {
|
|||||||
sc->free(a->_object._port);
|
sc->free(a->_object._port);
|
||||||
} else if(is_foreign_object(a)) {
|
} else if(is_foreign_object(a)) {
|
||||||
a->_object._foreign_object._vtable->finalize(sc, a->_object._foreign_object._data);
|
a->_object._foreign_object._vtable->finalize(sc, a->_object._foreign_object._data);
|
||||||
|
} else if (is_vector(a)) {
|
||||||
|
int i;
|
||||||
|
for (i = vector_size(vector_length(a)) - 1; i > 0; i--) {
|
||||||
|
pointer p = a + i;
|
||||||
|
typeflag(p) = 0;
|
||||||
|
car(p) = sc->NIL;
|
||||||
|
cdr(p) = sc->free_cell;
|
||||||
|
sc->free_cell = p;
|
||||||
|
sc->fcells += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user