mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-24 06:14:01 +08:00
runtime: size a cloned map's direct index for its own keys
new Map(m) and new Set(s) copied the source's direct-index size, which follows the source's peak. The copy now covers its largest live key, and keys that are sparse for their count hash instead.
This commit is contained in:
@@ -1248,9 +1248,14 @@ ScrMap *scr_map_clone(const ScrMap *source, bool keys_only) {
|
||||
out->entries = malloc(count * sizeof(ScrMapEntry));
|
||||
if (!out->entries) scr_map_oom();
|
||||
out->ecap = count;
|
||||
size_t top = 0;
|
||||
for (size_t i = 0; i < source->nentries; i++) {
|
||||
const ScrMapEntry *entry = &source->entries[i];
|
||||
if (!entry->hash) continue;
|
||||
if (source->ndense) {
|
||||
size_t k = (size_t)scr_map_slot_to_f64(entry->key);
|
||||
if (k > top) top = k;
|
||||
}
|
||||
ScrMapEntry *copy = &out->entries[out->nentries++];
|
||||
*copy = *entry;
|
||||
if (out->key_kind == SCR_MAP_KEY_STR) scr_str_retain(scr_map_slot_to_ptr(copy->key));
|
||||
@@ -1259,9 +1264,10 @@ ScrMap *scr_map_clone(const ScrMap *source, bool keys_only) {
|
||||
else if (out->val_kind == SCR_MAP_VAL_REF) out->val_retain(scr_map_slot_to_ptr(copy->val));
|
||||
}
|
||||
out->nlive = count;
|
||||
if (source->ndense) {
|
||||
/* Same keys, so the same table size; entry indices are compacted. */
|
||||
scr_map_dense_alloc(out, source->ndense);
|
||||
/* Size the copy's direct index for its own keys, not for the source's
|
||||
* peak; keys that are sparse for their count hash instead. */
|
||||
if (source->ndense && top / 2 < scr_map_dense_limit(count)) {
|
||||
scr_map_dense_alloc(out, scr_map_dense_size(top));
|
||||
scr_map_fill_dense(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -372,6 +372,22 @@ static void delete_shrinks(void) {
|
||||
assert(scr_map_size(map) == 20 && map->ndense && map->ndense <= 64);
|
||||
for (size_t i = 0; i < 40; i++) assert(scr_map_has_f64(map, (double)i) == (i < 20));
|
||||
scr_map_release(map);
|
||||
|
||||
/* A copy indexes its own keys, not the source's peak (here a quarter of
|
||||
* the entries survive, too many to compact the source yet). */
|
||||
map = scr_map_new(SCR_MAP_KEY_F64, SCR_MAP_VAL_F64, NULL, NULL, NULL);
|
||||
for (size_t i = 0; i < 4096; i++) scr_map_set_f64_f64(map, (double)i, (double)i);
|
||||
for (size_t i = 1024; i < 4096; i++) assert(scr_map_delete_f64(map, (double)i));
|
||||
assert(map->ndense == 4096 && scr_map_iter_count(map) == 4096);
|
||||
ScrMap *copy = scr_map_clone(map, false);
|
||||
assert(copy->ndense == 1024 && scr_map_size(copy) == 1024);
|
||||
double out;
|
||||
for (size_t i = 0; i < 1100; i++) {
|
||||
assert(scr_map_get_f64_f64(copy, (double)i, &out) == (i < 1024));
|
||||
if (i < 1024) assert(out == (double)i);
|
||||
}
|
||||
scr_map_release(copy);
|
||||
scr_map_release(map);
|
||||
}
|
||||
|
||||
/* Grow-and-drain cycles against the ordered model: the map repeatedly
|
||||
|
||||
Reference in New Issue
Block a user