|
@@ -7,9 +7,13 @@
|
|
#define t_map _MNAME(_map)
|
|
#define t_map _MNAME(_map)
|
|
#define t_entry _MNAME(_entry)
|
|
#define t_entry _MNAME(_entry)
|
|
#define t_value _MNAME(_value)
|
|
#define t_value _MNAME(_value)
|
|
|
|
+#define _MLIMIT 128
|
|
|
|
+#define _MINDEX(m,ckey) ((m)->maxentries < _MLIMIT ? (int)((char*)(m)->cells)[ckey] : ((int*)(m)->cells)[ckey])
|
|
|
|
+#define _MNEXT(m,ckey) ((m)->maxentries < _MLIMIT ? (int)((char*)(m)->nexts)[ckey] : ((int*)(m)->nexts)[ckey])
|
|
|
|
|
|
typedef struct {
|
|
typedef struct {
|
|
- int *cells;
|
|
|
|
|
|
+ void *cells;
|
|
|
|
+ void *nexts;
|
|
t_entry *entries;
|
|
t_entry *entries;
|
|
t_value *values;
|
|
t_value *values;
|
|
hl_free_list lfree;
|
|
hl_free_list lfree;
|
|
@@ -27,14 +31,15 @@ HL_PRIM t_map *_MNAME(alloc)() {
|
|
static vdynamic **_MNAME(find)( t_map *m, t_key key ) {
|
|
static vdynamic **_MNAME(find)( t_map *m, t_key key ) {
|
|
int c, ckey;
|
|
int c, ckey;
|
|
unsigned int hash;
|
|
unsigned int hash;
|
|
- if( !m->entries ) return NULL;
|
|
|
|
|
|
+
|
|
|
|
+ if( !m->values ) return NULL;
|
|
hash = _MNAME(hash)(key);
|
|
hash = _MNAME(hash)(key);
|
|
ckey = hash % ((unsigned)m->ncells);
|
|
ckey = hash % ((unsigned)m->ncells);
|
|
- c = m->cells[ckey];
|
|
|
|
|
|
+ c = _MINDEX(m,ckey);
|
|
while( c >= 0 ) {
|
|
while( c >= 0 ) {
|
|
if( _MMATCH(c) )
|
|
if( _MMATCH(c) )
|
|
return &m->values[c].value;
|
|
return &m->values[c].value;
|
|
- c = m->entries[c].next;
|
|
|
|
|
|
+ c = _MNEXT(m,c);
|
|
}
|
|
}
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
@@ -44,15 +49,15 @@ static void _MNAME(resize)( t_map *m );
|
|
static void _MNAME(set_impl)( t_map *m, t_key key, vdynamic *value ) {
|
|
static void _MNAME(set_impl)( t_map *m, t_key key, vdynamic *value ) {
|
|
int c, ckey = 0;
|
|
int c, ckey = 0;
|
|
unsigned int hash = _MNAME(hash)(key);
|
|
unsigned int hash = _MNAME(hash)(key);
|
|
- if( m->entries ) {
|
|
|
|
|
|
+ if( m->values ) {
|
|
ckey = hash % ((unsigned)m->ncells);
|
|
ckey = hash % ((unsigned)m->ncells);
|
|
- c = m->cells[ckey];
|
|
|
|
|
|
+ c = _MINDEX(m,ckey);
|
|
while( c >= 0 ) {
|
|
while( c >= 0 ) {
|
|
if( _MMATCH(c) ) {
|
|
if( _MMATCH(c) ) {
|
|
m->values[c].value = value;
|
|
m->values[c].value = value;
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- c = m->entries[c].next;
|
|
|
|
|
|
+ c = _MNEXT(m,c);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
c = hl_freelist_get(&m->lfree);
|
|
c = hl_freelist_get(&m->lfree);
|
|
@@ -62,8 +67,13 @@ static void _MNAME(set_impl)( t_map *m, t_key key, vdynamic *value ) {
|
|
c = hl_freelist_get(&m->lfree);
|
|
c = hl_freelist_get(&m->lfree);
|
|
}
|
|
}
|
|
_MSET(c);
|
|
_MSET(c);
|
|
- m->entries[c].next = m->cells[ckey];
|
|
|
|
- m->cells[ckey] = c;
|
|
|
|
|
|
+ if( m->maxentries < _MLIMIT ) {
|
|
|
|
+ ((char*)m->nexts)[c] = ((char*)m->cells)[ckey];
|
|
|
|
+ ((char*)m->cells)[ckey] = (char)c;
|
|
|
|
+ } else {
|
|
|
|
+ ((int*)m->nexts)[c] = ((int*)m->cells)[ckey];
|
|
|
|
+ ((int*)m->cells)[ckey] = c;
|
|
|
|
+ }
|
|
m->values[c].value = value;
|
|
m->values[c].value = value;
|
|
m->nentries++;
|
|
m->nentries++;
|
|
}
|
|
}
|
|
@@ -82,35 +92,40 @@ static void _MNAME(resize)( t_map *m ) {
|
|
while( H_PRIMES[i] < ncells ) i++;
|
|
while( H_PRIMES[i] < ncells ) i++;
|
|
ncells = H_PRIMES[i];
|
|
ncells = H_PRIMES[i];
|
|
|
|
|
|
|
|
+ int ksize = nentries < _MLIMIT ? 1 : sizeof(int);
|
|
m->entries = (t_entry*)hl_gc_alloc_noptr(nentries * sizeof(t_entry));
|
|
m->entries = (t_entry*)hl_gc_alloc_noptr(nentries * sizeof(t_entry));
|
|
m->values = (t_value*)hl_gc_alloc_raw(nentries * sizeof(t_value));
|
|
m->values = (t_value*)hl_gc_alloc_raw(nentries * sizeof(t_value));
|
|
m->maxentries = nentries;
|
|
m->maxentries = nentries;
|
|
|
|
|
|
- if( old.ncells == ncells ) {
|
|
|
|
|
|
+ if( old.ncells == ncells && (nentries < _MLIMIT || old.maxentries >= _MLIMIT) ) {
|
|
// simply expand
|
|
// simply expand
|
|
|
|
+ m->nexts = hl_gc_alloc_noptr(nentries * ksize);
|
|
memcpy(m->entries,old.entries,old.maxentries * sizeof(t_entry));
|
|
memcpy(m->entries,old.entries,old.maxentries * sizeof(t_entry));
|
|
memcpy(m->values,old.values,old.maxentries * sizeof(t_value));
|
|
memcpy(m->values,old.values,old.maxentries * sizeof(t_value));
|
|
|
|
+ memcpy(m->nexts,old.nexts,old.maxentries * ksize);
|
|
memset(m->values + old.maxentries, 0, (nentries - old.maxentries) * sizeof(t_value));
|
|
memset(m->values + old.maxentries, 0, (nentries - old.maxentries) * sizeof(t_value));
|
|
hl_freelist_add_range(&m->lfree,old.maxentries,m->maxentries - old.maxentries);
|
|
hl_freelist_add_range(&m->lfree,old.maxentries,m->maxentries - old.maxentries);
|
|
} else {
|
|
} else {
|
|
// expand and remap
|
|
// expand and remap
|
|
- m->cells = (int*)hl_gc_alloc_noptr(ncells * sizeof(int));
|
|
|
|
|
|
+ m->cells = hl_gc_alloc_noptr((ncells + nentries) * ksize);
|
|
|
|
+ m->nexts = (char*)m->cells + ncells * ksize;
|
|
m->ncells = ncells;
|
|
m->ncells = ncells;
|
|
m->nentries = 0;
|
|
m->nentries = 0;
|
|
- memset(m->cells,0xFF,ncells * sizeof(int));
|
|
|
|
|
|
+ memset(m->cells,0xFF,ncells * ksize);
|
|
memset(m->values, 0, nentries * sizeof(t_value));
|
|
memset(m->values, 0, nentries * sizeof(t_value));
|
|
hl_freelist_init(&m->lfree);
|
|
hl_freelist_init(&m->lfree);
|
|
hl_freelist_add_range(&m->lfree,0,m->maxentries);
|
|
hl_freelist_add_range(&m->lfree,0,m->maxentries);
|
|
-
|
|
|
|
- hl_add_root(&old); // prevent old.cells pointer aliasing
|
|
|
|
- for(i=0;i<old.ncells;i++) {
|
|
|
|
- int c = old.cells[i];
|
|
|
|
- while( c >= 0 ) {
|
|
|
|
- _MNAME(set_impl)(m,_MKEY((&old),c),old.values[c].value);
|
|
|
|
- c = old.entries[c].next;
|
|
|
|
|
|
+ if( old.ncells ) {
|
|
|
|
+ hl_add_root(&old); // prevent old.cells pointer aliasing
|
|
|
|
+ for(i=0;i<old.ncells;i++) {
|
|
|
|
+ int c = old.maxentries < _MLIMIT ? ((char*)old.cells)[i] : ((int*)old.cells)[i];
|
|
|
|
+ while( c >= 0 ) {
|
|
|
|
+ _MNAME(set_impl)(m,_MKEY((&old),c),old.values[c].value);
|
|
|
|
+ c = _MNEXT(&old,c);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+ hl_remove_root(&old);
|
|
}
|
|
}
|
|
- hl_remove_root(&old);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -135,21 +150,28 @@ HL_PRIM bool _MNAME(remove)( t_map *m, t_key key ) {
|
|
key = _MNAME(filter)(key);
|
|
key = _MNAME(filter)(key);
|
|
hash = _MNAME(hash)(key);
|
|
hash = _MNAME(hash)(key);
|
|
ckey = hash % ((unsigned)m->ncells);
|
|
ckey = hash % ((unsigned)m->ncells);
|
|
- c = m->cells[ckey];
|
|
|
|
|
|
+ c = _MINDEX(m,ckey);
|
|
while( c >= 0 ) {
|
|
while( c >= 0 ) {
|
|
if( _MMATCH(c) ) {
|
|
if( _MMATCH(c) ) {
|
|
hl_freelist_add(&m->lfree,c);
|
|
hl_freelist_add(&m->lfree,c);
|
|
m->nentries--;
|
|
m->nentries--;
|
|
_MERASE(c);
|
|
_MERASE(c);
|
|
m->values[c].value = NULL;
|
|
m->values[c].value = NULL;
|
|
- if( prev >= 0 )
|
|
|
|
- m->entries[prev].next = m->entries[c].next;
|
|
|
|
- else
|
|
|
|
- m->cells[ckey] = m->entries[c].next;
|
|
|
|
|
|
+ if( m->maxentries < _MLIMIT ) {
|
|
|
|
+ if( prev >= 0 )
|
|
|
|
+ ((char*)m->nexts)[prev] = ((char*)m->nexts)[c];
|
|
|
|
+ else
|
|
|
|
+ ((char*)m->cells)[ckey] = ((char*)m->nexts)[c];
|
|
|
|
+ } else {
|
|
|
|
+ if( prev >= 0 )
|
|
|
|
+ ((int*)m->nexts)[prev] = ((int*)m->nexts)[c];
|
|
|
|
+ else
|
|
|
|
+ ((int*)m->cells)[ckey] = ((int*)m->nexts)[c];
|
|
|
|
+ }
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
prev = c;
|
|
prev = c;
|
|
- c = m->entries[c].next;
|
|
|
|
|
|
+ c = _MNEXT(m,c);
|
|
}
|
|
}
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
@@ -160,10 +182,10 @@ HL_PRIM varray* _MNAME(keys)( t_map *m ) {
|
|
int p = 0;
|
|
int p = 0;
|
|
int i;
|
|
int i;
|
|
for(i=0;i<m->ncells;i++) {
|
|
for(i=0;i<m->ncells;i++) {
|
|
- int c = m->cells[i];
|
|
|
|
|
|
+ int c = _MINDEX(m,i);
|
|
while( c >= 0 ) {
|
|
while( c >= 0 ) {
|
|
keys[p++] = _MKEY(m,c);
|
|
keys[p++] = _MKEY(m,c);
|
|
- c = m->entries[c].next;
|
|
|
|
|
|
+ c = _MNEXT(m,c);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return a;
|
|
return a;
|
|
@@ -175,10 +197,10 @@ HL_PRIM varray* _MNAME(values)( t_map *m ) {
|
|
int p = 0;
|
|
int p = 0;
|
|
int i;
|
|
int i;
|
|
for(i=0;i<m->ncells;i++) {
|
|
for(i=0;i<m->ncells;i++) {
|
|
- int c = m->cells[i];
|
|
|
|
|
|
+ int c = _MINDEX(m,i);
|
|
while( c >= 0 ) {
|
|
while( c >= 0 ) {
|
|
values[p++] = m->values[c].value;
|
|
values[p++] = m->values[c].value;
|
|
- c = m->entries[c].next;
|
|
|
|
|
|
+ c = _MNEXT(m,c);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return a;
|
|
return a;
|
|
@@ -202,4 +224,5 @@ HL_PRIM int _MNAME(size)( t_map *m ) {
|
|
#undef _MSET
|
|
#undef _MSET
|
|
#undef _MERASE
|
|
#undef _MERASE
|
|
#undef _MOLD_KEY
|
|
#undef _MOLD_KEY
|
|
-
|
|
|
|
|
|
+#undef _MINDEX
|
|
|
|
+#undef _MNEXT
|