Rtree: Remove the per-field accessors.
We instead split things into "edata" and "metadata".
This commit is contained in:
parent
26e9a3103d
commit
79ae7f9211
@ -132,8 +132,7 @@ emap_edata_lookup(tsdn_t *tsdn, emap_t *emap, const void *ptr) {
|
|||||||
rtree_ctx_t rtree_ctx_fallback;
|
rtree_ctx_t rtree_ctx_fallback;
|
||||||
rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
|
rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
|
||||||
|
|
||||||
return rtree_edata_read(tsdn, &emap->rtree, rtree_ctx, (uintptr_t)ptr,
|
return rtree_read(tsdn, &emap->rtree, rtree_ctx, (uintptr_t)ptr).edata;
|
||||||
true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fills in alloc_ctx with the info in the map. */
|
/* Fills in alloc_ctx with the info in the map. */
|
||||||
@ -143,8 +142,10 @@ emap_alloc_ctx_lookup(tsdn_t *tsdn, emap_t *emap, const void *ptr,
|
|||||||
rtree_ctx_t rtree_ctx_fallback;
|
rtree_ctx_t rtree_ctx_fallback;
|
||||||
rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
|
rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
|
||||||
|
|
||||||
rtree_szind_slab_read(tsdn, &emap->rtree, rtree_ctx, (uintptr_t)ptr,
|
rtree_metadata_t metadata = rtree_metadata_read(tsdn, &emap->rtree,
|
||||||
true, &alloc_ctx->szind, &alloc_ctx->slab);
|
rtree_ctx, (uintptr_t)ptr);
|
||||||
|
alloc_ctx->szind = metadata.szind;
|
||||||
|
alloc_ctx->slab = metadata.slab;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The pointer must be mapped. */
|
/* The pointer must be mapped. */
|
||||||
@ -154,9 +155,11 @@ emap_full_alloc_ctx_lookup(tsdn_t *tsdn, emap_t *emap, const void *ptr,
|
|||||||
rtree_ctx_t rtree_ctx_fallback;
|
rtree_ctx_t rtree_ctx_fallback;
|
||||||
rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
|
rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
|
||||||
|
|
||||||
rtree_edata_szind_slab_read(tsdn, &emap->rtree, rtree_ctx,
|
rtree_contents_t contents = rtree_read(tsdn, &emap->rtree, rtree_ctx,
|
||||||
(uintptr_t)ptr, true, &full_alloc_ctx->edata,
|
(uintptr_t)ptr);
|
||||||
&full_alloc_ctx->szind, &full_alloc_ctx->slab);
|
full_alloc_ctx->edata = contents.edata;
|
||||||
|
full_alloc_ctx->szind = contents.metadata.szind;
|
||||||
|
full_alloc_ctx->slab = contents.metadata.slab;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -170,24 +173,35 @@ emap_full_alloc_ctx_try_lookup(tsdn_t *tsdn, emap_t *emap, const void *ptr,
|
|||||||
rtree_ctx_t rtree_ctx_fallback;
|
rtree_ctx_t rtree_ctx_fallback;
|
||||||
rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
|
rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
|
||||||
|
|
||||||
return rtree_edata_szind_slab_read(tsdn, &emap->rtree, rtree_ctx,
|
rtree_contents_t contents;
|
||||||
(uintptr_t)ptr, false, &full_alloc_ctx->edata,
|
bool err = rtree_read_independent(tsdn, &emap->rtree, rtree_ctx,
|
||||||
&full_alloc_ctx->szind, &full_alloc_ctx->slab);
|
(uintptr_t)ptr, &contents);
|
||||||
|
if (err) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
full_alloc_ctx->edata = contents.edata;
|
||||||
|
full_alloc_ctx->szind = contents.metadata.szind;
|
||||||
|
full_alloc_ctx->slab = contents.metadata.slab;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fills in alloc_ctx, but only if it can be done easily (i.e. with a hit in the
|
* Returns true on error.
|
||||||
* L1 rtree cache.
|
|
||||||
*
|
|
||||||
* Returns whether or not alloc_ctx was filled in.
|
|
||||||
*/
|
*/
|
||||||
JEMALLOC_ALWAYS_INLINE bool
|
JEMALLOC_ALWAYS_INLINE bool
|
||||||
emap_alloc_ctx_try_lookup_fast(tsd_t *tsd, emap_t *emap, const void *ptr,
|
emap_alloc_ctx_try_lookup_fast(tsd_t *tsd, emap_t *emap, const void *ptr,
|
||||||
emap_alloc_ctx_t *alloc_ctx) {
|
emap_alloc_ctx_t *alloc_ctx) {
|
||||||
rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd);
|
rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd);
|
||||||
bool res = rtree_szind_slab_read_fast(tsd_tsdn(tsd), &emap->rtree,
|
|
||||||
rtree_ctx, (uintptr_t)ptr, &alloc_ctx->szind, &alloc_ctx->slab);
|
rtree_metadata_t metadata;
|
||||||
return res;
|
bool err = rtree_metadata_try_read_fast(tsd_tsdn(tsd), &emap->rtree,
|
||||||
|
rtree_ctx, (uintptr_t)ptr, &metadata);
|
||||||
|
if (err) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
alloc_ctx->szind = metadata.szind;
|
||||||
|
alloc_ctx->slab = metadata.slab;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* JEMALLOC_INTERNAL_EMAP_H */
|
#endif /* JEMALLOC_INTERNAL_EMAP_H */
|
||||||
|
@ -257,19 +257,29 @@ rtree_leaf_elm_write(tsdn_t *tsdn, rtree_t *rtree,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
/*
|
||||||
rtree_leaf_elm_szind_slab_update(tsdn_t *tsdn, rtree_t *rtree,
|
* Tries to look up the key in the L1 cache, returning it if there's a hit, or
|
||||||
rtree_leaf_elm_t *elm, szind_t szind, bool slab) {
|
* NULL if there's a miss.
|
||||||
assert(!slab || szind < SC_NBINS);
|
* Key is allowed to be NULL; returns NULL in this case.
|
||||||
rtree_contents_t contents = rtree_leaf_elm_read(
|
*/
|
||||||
tsdn, rtree, elm, /* dependent */ true);
|
JEMALLOC_ALWAYS_INLINE rtree_leaf_elm_t *
|
||||||
/*
|
rtree_leaf_elm_lookup_fast(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
|
||||||
* The caller implicitly assures that it is the only writer to the szind
|
uintptr_t key) {
|
||||||
* and slab fields, and that the edata field cannot currently change.
|
rtree_leaf_elm_t *elm;
|
||||||
*/
|
|
||||||
contents.metadata.slab = slab;
|
size_t slot = rtree_cache_direct_map(key);
|
||||||
contents.metadata.szind = szind;
|
uintptr_t leafkey = rtree_leafkey(key);
|
||||||
rtree_leaf_elm_write(tsdn, rtree, elm, contents);
|
assert(leafkey != RTREE_LEAFKEY_INVALID);
|
||||||
|
|
||||||
|
if (likely(rtree_ctx->cache[slot].leafkey == leafkey)) {
|
||||||
|
rtree_leaf_elm_t *leaf = rtree_ctx->cache[slot].leaf;
|
||||||
|
assert(leaf != NULL);
|
||||||
|
uintptr_t subkey = rtree_subkey(key, RTREE_HEIGHT-1);
|
||||||
|
elm = &leaf[subkey];
|
||||||
|
return elm;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JEMALLOC_ALWAYS_INLINE rtree_leaf_elm_t *
|
JEMALLOC_ALWAYS_INLINE rtree_leaf_elm_t *
|
||||||
@ -331,144 +341,79 @@ rtree_leaf_elm_lookup(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
|
|||||||
dependent, init_missing);
|
dependent, init_missing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns true on lookup failure.
|
||||||
|
*/
|
||||||
|
static inline bool
|
||||||
|
rtree_read_independent(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
|
||||||
|
uintptr_t key, rtree_contents_t *r_contents) {
|
||||||
|
rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup(tsdn, rtree, rtree_ctx,
|
||||||
|
key, /* dependent */ false, /* init_missing */ false);
|
||||||
|
if (elm == NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*r_contents = rtree_leaf_elm_read(tsdn, rtree, elm,
|
||||||
|
/* dependent */ false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline rtree_contents_t
|
||||||
|
rtree_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
|
||||||
|
uintptr_t key) {
|
||||||
|
rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup(tsdn, rtree, rtree_ctx,
|
||||||
|
key, /* dependent */ true, /* init_missing */ false);
|
||||||
|
assert(elm != NULL);
|
||||||
|
return rtree_leaf_elm_read(tsdn, rtree, elm, /* dependent */ true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline rtree_metadata_t
|
||||||
|
rtree_metadata_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
|
||||||
|
uintptr_t key) {
|
||||||
|
rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup(tsdn, rtree, rtree_ctx,
|
||||||
|
key, /* dependent */ true, /* init_missing */ false);
|
||||||
|
assert(elm != NULL);
|
||||||
|
return rtree_leaf_elm_read(tsdn, rtree, elm,
|
||||||
|
/* dependent */ true).metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns true on error.
|
||||||
|
*/
|
||||||
|
static inline bool
|
||||||
|
rtree_metadata_try_read_fast(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
|
||||||
|
uintptr_t key, rtree_metadata_t *r_rtree_metadata) {
|
||||||
|
rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup_fast(tsdn, rtree, rtree_ctx,
|
||||||
|
key);
|
||||||
|
if (elm == NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*r_rtree_metadata = rtree_leaf_elm_read(tsdn, rtree, elm,
|
||||||
|
/* dependent */ true).metadata;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
rtree_write(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, uintptr_t key,
|
rtree_write(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, uintptr_t key,
|
||||||
edata_t *edata, szind_t szind, bool slab) {
|
rtree_contents_t contents) {
|
||||||
rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup(tsdn, rtree, rtree_ctx,
|
rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup(tsdn, rtree, rtree_ctx,
|
||||||
key, false, true);
|
key, /* dependent */ false, /* init_missing */ true);
|
||||||
if (elm == NULL) {
|
if (elm == NULL) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtree_contents_t contents;
|
|
||||||
contents.edata = edata;
|
|
||||||
contents.metadata.szind = szind;
|
|
||||||
contents.metadata.slab = slab;
|
|
||||||
rtree_leaf_elm_write(tsdn, rtree, elm, contents);
|
rtree_leaf_elm_write(tsdn, rtree, elm, contents);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
JEMALLOC_ALWAYS_INLINE rtree_leaf_elm_t *
|
|
||||||
rtree_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, uintptr_t key,
|
|
||||||
bool dependent) {
|
|
||||||
rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup(tsdn, rtree, rtree_ctx,
|
|
||||||
key, dependent, false);
|
|
||||||
if (!dependent && elm == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
assert(elm != NULL);
|
|
||||||
return elm;
|
|
||||||
}
|
|
||||||
|
|
||||||
JEMALLOC_ALWAYS_INLINE edata_t *
|
|
||||||
rtree_edata_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
|
|
||||||
uintptr_t key, bool dependent) {
|
|
||||||
rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key,
|
|
||||||
dependent);
|
|
||||||
if (!dependent && elm == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return rtree_leaf_elm_read(tsdn, rtree, elm, dependent).edata;
|
|
||||||
}
|
|
||||||
|
|
||||||
JEMALLOC_ALWAYS_INLINE szind_t
|
|
||||||
rtree_szind_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
|
|
||||||
uintptr_t key, bool dependent) {
|
|
||||||
rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key,
|
|
||||||
dependent);
|
|
||||||
if (!dependent && elm == NULL) {
|
|
||||||
return SC_NSIZES;
|
|
||||||
}
|
|
||||||
return rtree_leaf_elm_read(tsdn, rtree, elm, dependent).metadata.szind;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rtree_slab_read() is intentionally omitted because slab is always read in
|
|
||||||
* conjunction with szind, which makes rtree_szind_slab_read() a better choice.
|
|
||||||
*/
|
|
||||||
|
|
||||||
JEMALLOC_ALWAYS_INLINE bool
|
|
||||||
rtree_edata_szind_slab_read(tsdn_t *tsdn, rtree_t *rtree,
|
|
||||||
rtree_ctx_t *rtree_ctx, uintptr_t key, bool dependent, edata_t **r_edata,
|
|
||||||
szind_t *r_szind, bool *r_slab) {
|
|
||||||
rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key,
|
|
||||||
dependent);
|
|
||||||
if (!dependent && elm == NULL) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
rtree_contents_t contents = rtree_leaf_elm_read(tsdn, rtree, elm,
|
|
||||||
dependent);
|
|
||||||
*r_edata = contents.edata;
|
|
||||||
*r_szind = contents.metadata.szind;
|
|
||||||
*r_slab = contents.metadata.slab;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try to read szind_slab from the L1 cache. Returns true on a hit,
|
|
||||||
* and fills in r_szind and r_slab. Otherwise returns false.
|
|
||||||
*
|
|
||||||
* Key is allowed to be NULL in order to save an extra branch on the
|
|
||||||
* fastpath. returns false in this case.
|
|
||||||
*/
|
|
||||||
JEMALLOC_ALWAYS_INLINE bool
|
|
||||||
rtree_szind_slab_read_fast(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
|
|
||||||
uintptr_t key, szind_t *r_szind, bool *r_slab) {
|
|
||||||
rtree_leaf_elm_t *elm;
|
|
||||||
|
|
||||||
size_t slot = rtree_cache_direct_map(key);
|
|
||||||
uintptr_t leafkey = rtree_leafkey(key);
|
|
||||||
assert(leafkey != RTREE_LEAFKEY_INVALID);
|
|
||||||
|
|
||||||
if (likely(rtree_ctx->cache[slot].leafkey == leafkey)) {
|
|
||||||
rtree_leaf_elm_t *leaf = rtree_ctx->cache[slot].leaf;
|
|
||||||
assert(leaf != NULL);
|
|
||||||
uintptr_t subkey = rtree_subkey(key, RTREE_HEIGHT-1);
|
|
||||||
elm = &leaf[subkey];
|
|
||||||
|
|
||||||
rtree_contents_t contents = rtree_leaf_elm_read(tsdn, rtree,
|
|
||||||
elm, /* dependent */ true);
|
|
||||||
*r_szind = contents.metadata.szind;
|
|
||||||
*r_slab = contents.metadata.slab;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JEMALLOC_ALWAYS_INLINE bool
|
|
||||||
rtree_szind_slab_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
|
|
||||||
uintptr_t key, bool dependent, szind_t *r_szind, bool *r_slab) {
|
|
||||||
rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key,
|
|
||||||
dependent);
|
|
||||||
if (!dependent && elm == NULL) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
rtree_contents_t contents = rtree_leaf_elm_read(tsdn, rtree, elm,
|
|
||||||
/* dependent */ true);
|
|
||||||
*r_szind = contents.metadata.szind;
|
|
||||||
*r_slab = contents.metadata.slab;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
rtree_szind_slab_update(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
|
|
||||||
uintptr_t key, szind_t szind, bool slab) {
|
|
||||||
assert(!slab || szind < SC_NBINS);
|
|
||||||
|
|
||||||
rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key, true);
|
|
||||||
rtree_leaf_elm_szind_slab_update(tsdn, rtree, elm, szind, slab);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
rtree_clear(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
|
rtree_clear(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
|
||||||
uintptr_t key) {
|
uintptr_t key) {
|
||||||
rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key, true);
|
rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup(tsdn, rtree, rtree_ctx,
|
||||||
|
key, /* dependent */ true, /* init_missing */ false);
|
||||||
|
assert(elm != NULL);
|
||||||
assert(rtree_leaf_elm_read(tsdn, rtree, elm,
|
assert(rtree_leaf_elm_read(tsdn, rtree, elm,
|
||||||
/* dependent */ false).edata != NULL);
|
/* dependent */ true).edata != NULL);
|
||||||
rtree_contents_t contents;
|
rtree_contents_t contents;
|
||||||
contents.edata = NULL;
|
contents.edata = NULL;
|
||||||
contents.metadata.szind = SC_NSIZES;
|
contents.metadata.szind = SC_NSIZES;
|
||||||
|
31
src/emap.c
31
src/emap.c
@ -171,9 +171,13 @@ emap_register_interior(tsdn_t *tsdn, emap_t *emap, edata_t *edata,
|
|||||||
|
|
||||||
/* Register interior. */
|
/* Register interior. */
|
||||||
for (size_t i = 1; i < (edata_size_get(edata) >> LG_PAGE) - 1; i++) {
|
for (size_t i = 1; i < (edata_size_get(edata) >> LG_PAGE) - 1; i++) {
|
||||||
|
rtree_contents_t contents;
|
||||||
|
contents.edata = edata;
|
||||||
|
contents.metadata.szind = szind;
|
||||||
|
contents.metadata.slab = true;
|
||||||
rtree_write(tsdn, &emap->rtree, rtree_ctx,
|
rtree_write(tsdn, &emap->rtree, rtree_ctx,
|
||||||
(uintptr_t)edata_base_get(edata) + (uintptr_t)(i <<
|
(uintptr_t)edata_base_get(edata) + (uintptr_t)(i <<
|
||||||
LG_PAGE), edata, szind, true);
|
LG_PAGE), contents);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,13 +204,18 @@ emap_deregister_interior(tsdn_t *tsdn, emap_t *emap, edata_t *edata) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void emap_remap(tsdn_t *tsdn, emap_t *emap, edata_t *edata, szind_t szind,
|
void
|
||||||
|
emap_remap(tsdn_t *tsdn, emap_t *emap, edata_t *edata, szind_t szind,
|
||||||
bool slab) {
|
bool slab) {
|
||||||
EMAP_DECLARE_RTREE_CTX;
|
EMAP_DECLARE_RTREE_CTX;
|
||||||
|
|
||||||
if (szind != SC_NSIZES) {
|
if (szind != SC_NSIZES) {
|
||||||
rtree_szind_slab_update(tsdn, &emap->rtree, rtree_ctx,
|
rtree_contents_t contents;
|
||||||
(uintptr_t)edata_addr_get(edata), szind, slab);
|
contents.edata = edata;
|
||||||
|
contents.metadata.szind = szind;
|
||||||
|
contents.metadata.slab = slab;
|
||||||
|
rtree_write(tsdn, &emap->rtree, rtree_ctx,
|
||||||
|
(uintptr_t)edata_addr_get(edata), contents);
|
||||||
/*
|
/*
|
||||||
* Recall that this is called only for active->inactive and
|
* Recall that this is called only for active->inactive and
|
||||||
* inactive->active transitions (since only active extents have
|
* inactive->active transitions (since only active extents have
|
||||||
@ -220,12 +229,12 @@ void emap_remap(tsdn_t *tsdn, emap_t *emap, edata_t *edata, szind_t szind,
|
|||||||
* call is coming in those cases, though.
|
* call is coming in those cases, though.
|
||||||
*/
|
*/
|
||||||
if (slab && edata_size_get(edata) > PAGE) {
|
if (slab && edata_size_get(edata) > PAGE) {
|
||||||
rtree_szind_slab_update(tsdn,
|
uintptr_t key = (uintptr_t)edata_past_get(edata)
|
||||||
&emap->rtree, rtree_ctx,
|
- (uintptr_t)PAGE;
|
||||||
(uintptr_t)edata_past_get(edata) - (uintptr_t)PAGE,
|
rtree_write(tsdn, &emap->rtree, rtree_ctx, key,
|
||||||
szind, slab);
|
contents);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -311,6 +320,6 @@ void
|
|||||||
emap_do_assert_mapped(tsdn_t *tsdn, emap_t *emap, edata_t *edata) {
|
emap_do_assert_mapped(tsdn_t *tsdn, emap_t *emap, edata_t *edata) {
|
||||||
EMAP_DECLARE_RTREE_CTX;
|
EMAP_DECLARE_RTREE_CTX;
|
||||||
|
|
||||||
assert(rtree_edata_read(tsdn, &emap->rtree, rtree_ctx,
|
assert(rtree_read(tsdn, &emap->rtree, rtree_ctx,
|
||||||
(uintptr_t)edata_base_get(edata), true) == edata);
|
(uintptr_t)edata_base_get(edata)).edata == edata);
|
||||||
}
|
}
|
||||||
|
@ -2782,11 +2782,11 @@ bool free_fastpath(void *ptr, size_t size, bool size_hint) {
|
|||||||
if (unlikely(tsd == NULL || !tsd_fast(tsd))) {
|
if (unlikely(tsd == NULL || !tsd_fast(tsd))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool res = emap_alloc_ctx_try_lookup_fast(tsd,
|
bool err = emap_alloc_ctx_try_lookup_fast(tsd,
|
||||||
&arena_emap_global, ptr, &alloc_ctx);
|
&arena_emap_global, ptr, &alloc_ctx);
|
||||||
|
|
||||||
/* Note: profiled objects will have alloc_ctx.slab set */
|
/* Note: profiled objects will have alloc_ctx.slab set */
|
||||||
if (unlikely(!res || !alloc_ctx.slab)) {
|
if (unlikely(err || !alloc_ctx.slab)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
assert(alloc_ctx.szind != SC_NSIZES);
|
assert(alloc_ctx.szind != SC_NSIZES);
|
||||||
|
@ -20,8 +20,9 @@ TEST_BEGIN(test_rtree_read_empty) {
|
|||||||
rtree_ctx_data_init(&rtree_ctx);
|
rtree_ctx_data_init(&rtree_ctx);
|
||||||
expect_false(rtree_new(rtree, base, false),
|
expect_false(rtree_new(rtree, base, false),
|
||||||
"Unexpected rtree_new() failure");
|
"Unexpected rtree_new() failure");
|
||||||
expect_ptr_null(rtree_edata_read(tsdn, rtree, &rtree_ctx, PAGE,
|
rtree_contents_t contents;
|
||||||
false), "rtree_edata_read() should return NULL for empty tree");
|
expect_true(rtree_read_independent(tsdn, rtree, &rtree_ctx, PAGE,
|
||||||
|
&contents), "rtree_read_independent() should fail on empty rtree.");
|
||||||
|
|
||||||
base_delete(tsdn, base);
|
base_delete(tsdn, base);
|
||||||
}
|
}
|
||||||
@ -50,21 +51,33 @@ TEST_BEGIN(test_rtree_extrema) {
|
|||||||
expect_false(rtree_new(rtree, base, false),
|
expect_false(rtree_new(rtree, base, false),
|
||||||
"Unexpected rtree_new() failure");
|
"Unexpected rtree_new() failure");
|
||||||
|
|
||||||
expect_false(rtree_write(tsdn, rtree, &rtree_ctx, PAGE, &edata_a,
|
rtree_contents_t contents_a;
|
||||||
edata_szind_get(&edata_a), edata_slab_get(&edata_a)),
|
contents_a.edata = &edata_a;
|
||||||
|
contents_a.metadata.szind = edata_szind_get(&edata_a);
|
||||||
|
contents_a.metadata.slab = edata_slab_get(&edata_a);
|
||||||
|
expect_false(rtree_write(tsdn, rtree, &rtree_ctx, PAGE, contents_a),
|
||||||
"Unexpected rtree_write() failure");
|
"Unexpected rtree_write() failure");
|
||||||
rtree_szind_slab_update(tsdn, rtree, &rtree_ctx, PAGE,
|
expect_false(rtree_write(tsdn, rtree, &rtree_ctx, PAGE, contents_a),
|
||||||
edata_szind_get(&edata_a), edata_slab_get(&edata_a));
|
"Unexpected rtree_write() failure");
|
||||||
expect_ptr_eq(rtree_edata_read(tsdn, rtree, &rtree_ctx, PAGE, true),
|
rtree_contents_t read_contents_a = rtree_read(tsdn, rtree, &rtree_ctx,
|
||||||
&edata_a,
|
PAGE);
|
||||||
"rtree_edata_read() should return previously set value");
|
expect_true(contents_a.edata == read_contents_a.edata
|
||||||
|
&& contents_a.metadata.szind == read_contents_a.metadata.szind
|
||||||
|
&& contents_a.metadata.slab == read_contents_a.metadata.slab,
|
||||||
|
"rtree_read() should return previously set value");
|
||||||
|
|
||||||
|
rtree_contents_t contents_b;
|
||||||
|
contents_b.edata = &edata_b;
|
||||||
|
contents_b.metadata.szind = edata_szind_get_maybe_invalid(&edata_b);
|
||||||
|
contents_b.metadata.slab = edata_slab_get(&edata_b);
|
||||||
expect_false(rtree_write(tsdn, rtree, &rtree_ctx, ~((uintptr_t)0),
|
expect_false(rtree_write(tsdn, rtree, &rtree_ctx, ~((uintptr_t)0),
|
||||||
&edata_b, edata_szind_get_maybe_invalid(&edata_b),
|
contents_b), "Unexpected rtree_write() failure");
|
||||||
edata_slab_get(&edata_b)), "Unexpected rtree_write() failure");
|
rtree_contents_t read_contents_b = rtree_read(tsdn, rtree, &rtree_ctx,
|
||||||
expect_ptr_eq(rtree_edata_read(tsdn, rtree, &rtree_ctx,
|
~((uintptr_t)0));
|
||||||
~((uintptr_t)0), true), &edata_b,
|
assert_true(contents_b.edata == read_contents_b.edata
|
||||||
"rtree_edata_read() should return previously set value");
|
&& contents_b.metadata.szind == read_contents_b.metadata.szind
|
||||||
|
&& contents_b.metadata.slab == read_contents_b.metadata.slab,
|
||||||
|
"rtree_read() should return previously set value");
|
||||||
|
|
||||||
base_delete(tsdn, base);
|
base_delete(tsdn, base);
|
||||||
}
|
}
|
||||||
@ -89,19 +102,23 @@ TEST_BEGIN(test_rtree_bits) {
|
|||||||
"Unexpected rtree_new() failure");
|
"Unexpected rtree_new() failure");
|
||||||
|
|
||||||
for (unsigned i = 0; i < sizeof(keys)/sizeof(uintptr_t); i++) {
|
for (unsigned i = 0; i < sizeof(keys)/sizeof(uintptr_t); i++) {
|
||||||
|
rtree_contents_t contents;
|
||||||
|
contents.edata = &edata;
|
||||||
|
contents.metadata.szind = SC_NSIZES;
|
||||||
|
contents.metadata.slab = false;
|
||||||
|
|
||||||
expect_false(rtree_write(tsdn, rtree, &rtree_ctx, keys[i],
|
expect_false(rtree_write(tsdn, rtree, &rtree_ctx, keys[i],
|
||||||
&edata, SC_NSIZES, false),
|
contents), "Unexpected rtree_write() failure");
|
||||||
"Unexpected rtree_write() failure");
|
|
||||||
for (unsigned j = 0; j < sizeof(keys)/sizeof(uintptr_t); j++) {
|
for (unsigned j = 0; j < sizeof(keys)/sizeof(uintptr_t); j++) {
|
||||||
expect_ptr_eq(rtree_edata_read(tsdn, rtree, &rtree_ctx,
|
expect_ptr_eq(rtree_read(tsdn, rtree, &rtree_ctx,
|
||||||
keys[j], true), &edata,
|
keys[j]).edata, &edata,
|
||||||
"rtree_edata_read() should return previously set "
|
"rtree_edata_read() should return previously set "
|
||||||
"value and ignore insignificant key bits; i=%u, "
|
"value and ignore insignificant key bits; i=%u, "
|
||||||
"j=%u, set key=%#"FMTxPTR", get key=%#"FMTxPTR, i,
|
"j=%u, set key=%#"FMTxPTR", get key=%#"FMTxPTR, i,
|
||||||
j, keys[i], keys[j]);
|
j, keys[i], keys[j]);
|
||||||
}
|
}
|
||||||
expect_ptr_null(rtree_edata_read(tsdn, rtree, &rtree_ctx,
|
expect_ptr_null(rtree_read(tsdn, rtree, &rtree_ctx,
|
||||||
(((uintptr_t)2) << LG_PAGE), false),
|
(((uintptr_t)2) << LG_PAGE)).edata,
|
||||||
"Only leftmost rtree leaf should be set; i=%u", i);
|
"Only leftmost rtree leaf should be set; i=%u", i);
|
||||||
rtree_clear(tsdn, rtree, &rtree_ctx, keys[i]);
|
rtree_clear(tsdn, rtree, &rtree_ctx, keys[i]);
|
||||||
}
|
}
|
||||||
@ -142,26 +159,26 @@ TEST_BEGIN(test_rtree_random) {
|
|||||||
contents.metadata.szind = SC_NSIZES;
|
contents.metadata.szind = SC_NSIZES;
|
||||||
contents.metadata.slab = false;
|
contents.metadata.slab = false;
|
||||||
rtree_leaf_elm_write(tsdn, rtree, elm, contents);
|
rtree_leaf_elm_write(tsdn, rtree, elm, contents);
|
||||||
expect_ptr_eq(rtree_edata_read(tsdn, rtree, &rtree_ctx,
|
expect_ptr_eq(rtree_read(tsdn, rtree, &rtree_ctx,
|
||||||
keys[i], true), &edata,
|
keys[i]).edata, &edata,
|
||||||
"rtree_edata_read() should return previously set value");
|
"rtree_edata_read() should return previously set value");
|
||||||
}
|
}
|
||||||
for (unsigned i = 0; i < NSET; i++) {
|
for (unsigned i = 0; i < NSET; i++) {
|
||||||
expect_ptr_eq(rtree_edata_read(tsdn, rtree, &rtree_ctx,
|
expect_ptr_eq(rtree_read(tsdn, rtree, &rtree_ctx,
|
||||||
keys[i], true), &edata,
|
keys[i]).edata, &edata,
|
||||||
"rtree_edata_read() should return previously set value, "
|
"rtree_edata_read() should return previously set value, "
|
||||||
"i=%u", i);
|
"i=%u", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < NSET; i++) {
|
for (unsigned i = 0; i < NSET; i++) {
|
||||||
rtree_clear(tsdn, rtree, &rtree_ctx, keys[i]);
|
rtree_clear(tsdn, rtree, &rtree_ctx, keys[i]);
|
||||||
expect_ptr_null(rtree_edata_read(tsdn, rtree, &rtree_ctx,
|
expect_ptr_null(rtree_read(tsdn, rtree, &rtree_ctx,
|
||||||
keys[i], true),
|
keys[i]).edata,
|
||||||
"rtree_edata_read() should return previously set value");
|
"rtree_edata_read() should return previously set value");
|
||||||
}
|
}
|
||||||
for (unsigned i = 0; i < NSET; i++) {
|
for (unsigned i = 0; i < NSET; i++) {
|
||||||
expect_ptr_null(rtree_edata_read(tsdn, rtree, &rtree_ctx,
|
expect_ptr_null(rtree_read(tsdn, rtree, &rtree_ctx,
|
||||||
keys[i], true),
|
keys[i]).edata,
|
||||||
"rtree_edata_read() should return previously set value");
|
"rtree_edata_read() should return previously set value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user