diff options
author | Justus Winter <justus@g10code.com> | 2017-01-30 15:51:19 +0100 |
---|---|---|
committer | Justus Winter <justus@g10code.com> | 2017-01-30 18:21:24 +0100 |
commit | 49e2ae65e892f93be7f87cfaae3392b50a99e4b1 (patch) | |
tree | 3f6fdefe15b86ce7893ad95d8c6aae7c64ba9bfb /tests/gpgscm/scheme.c | |
parent | gpgscm: Provide framework for immediate values. (diff) | |
download | gnupg2-49e2ae65e892f93be7f87cfaae3392b50a99e4b1.tar.xz gnupg2-49e2ae65e892f93be7f87cfaae3392b50a99e4b1.zip |
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>
Diffstat (limited to 'tests/gpgscm/scheme.c')
-rw-r--r-- | tests/gpgscm/scheme.c | 59 |
1 files changed, 32 insertions, 27 deletions
diff --git a/tests/gpgscm/scheme.c b/tests/gpgscm/scheme.c index 32d8032f0..86df85101 100644 --- a/tests/gpgscm/scheme.c +++ b/tests/gpgscm/scheme.c @@ -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 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 pointer vector_elem(pointer vec, int ielem); 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) { - 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; } /* 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; - set_num_integer(cells); fill_vector(cells,init); if (gc_enabled (sc)) 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); } INTERFACE static void fill_vector(pointer vec, pointer obj) { - int i; - int n = vector_length(vec) / 2 + vector_length(vec) % 2; - for(i=0; i < n; i++) { - typeflag(vec+1+i) = T_PAIR; - setimmutable(vec+1+i); - car(vec+1+i)=obj; - cdr(vec+1+i)=obj; + size_t i; + assert (is_vector (vec)); + for(i = 0; i < vector_length(vec); i++) { + vec->_object._vector._elements[i] = set_immediate(obj); } } INTERFACE static pointer vector_elem(pointer vec, int ielem) { - int n=ielem/2; - if(ielem%2==0) { - return car(vec+1+n); - } else { - return cdr(vec+1+n); - } + assert (is_vector (vec)); + assert (ielem < vector_length(vec)); + return clr_immediate(vec->_object._vector._elements[ielem]); } INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a) { - int n=ielem/2; - if(ielem%2==0) { - return car(vec+1+n)=a; - } else { - return cdr(vec+1+n)=a; - } + assert (is_vector (vec)); + assert (ielem < vector_length(vec)); + vec->_object._vector._elements[ielem] = set_immediate(a); + return a; } /* get new symbol */ @@ -1563,10 +1558,8 @@ static void mark(pointer a) { E2: setmark(p); if(is_vector(p)) { int i; - int n = vector_length(p) / 2 + vector_length(p) % 2; - for(i=0; i < n; i++) { - /* Vector cells will be treated like ordinary cells */ - mark(p+1+i); + for (i = 0; i < vector_length(p); i++) { + mark(clr_immediate(p->_object._vector._elements[i])); } } #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--) { p = sc->cell_seg[i] + CELL_SEGSIZE; while (--p >= sc->cell_seg[i]) { + if (typeflag(p) & IMMEDIATE_TAG) + continue; if (is_mark(p)) { clrmark(p); } else { @@ -1708,6 +1703,16 @@ static void finalize_cell(scheme *sc, pointer a) { sc->free(a->_object._port); } else if(is_foreign_object(a)) { 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; + } } } |