Yzena
/
Yc
2
1
Fork 0
Browse Source

Redo stackpools to make malloc fast

This uses extra space to tradeoff on performance, in number of
instructions.

Signed-off-by: Gavin Howard <gavin@yzena.com>
afl_persistent_mode
Gavin Howard 2 months ago
parent
commit
39bd3156a2
Signed by: gavin
GPG Key ID: C08038BDF280D33E
  1. 7
      include/yc/gaml.h
  2. 18
      include/yc/io.h
  3. 23
      include/yc/mappool.h
  4. 5
      include/yc/opt.h
  5. 2
      include/yc/setpool.h
  6. 36
      include/yc/stackpool.h
  7. 3
      src/concurrency/strucon.c
  8. 4
      src/concurrency/threadset.c
  9. 5
      src/gaml/gaml.c
  10. 5
      src/gaml/parse.c
  11. 4
      src/io/file.c
  12. 4
      src/io/io.c
  13. 3
      src/io/io.h
  14. 25
      src/io/path.c
  15. 36
      src/pool/mappool.c
  16. 31
      src/pool/mappool.h
  17. 12
      src/pool/setpool.c
  18. 17
      src/pool/setpool.h
  19. 606
      src/pool/stackpool.c
  20. 109
      src/pool/stackpool.h
  21. 28
      src/rig/build.c
  22. 10
      src/rig/db.c
  23. 7
      src/rig/main.c
  24. 5
      src/rig/rig.c
  25. 5
      src/str/str.c
  26. 4
      src/sys/proc.c
  27. 1
      src/util/CMakeLists.txt
  28. 4
      src/util/opt.c
  29. 101
      src/util/types.c
  30. 155
      src/util/types.h
  31. 10
      src/yao/lex.c
  32. 7
      src/yao/parse.c
  33. 12
      src/yao/program.c
  34. 2
      src/yao/yao.c
  35. 9
      src/yao/yao.h
  36. 3
      src/yvm/yvm.c
  37. 10
      tests/pool/mappool_all.c

7
include/yc/gaml.h

@ -148,12 +148,11 @@ y_gaml_create(void);
/**
* Creates an empty y_Gaml object using the stack allocator. This must be freed
* with @a y_stackallocator_free().
* @param dtor The destructor index for y_Gaml objects.
* @return An empty y_Gaml object, or NULL on error.
* with @a y_stackpool_free().
* @return An empty y_Gaml object, or NULL on error.
*/
y_Gaml
y_gaml_screate(y_Dtor dtor);
y_gaml_screate(void);
/**
* Reads the GAML file at @a path into the @a y_Gaml object. If the @a y_Gaml

18
include/yc/io.h

@ -466,14 +466,13 @@ y_fs_path_init_cstr(y_Path* path, const char* s) y_allnonnull;
* assumed to be UTF-8. Uses the stack allocator for the thread.
* @param path The path to initialize and set.
* @param s The string to turn into a path.
* @param dtor The index of the path destructor.
* @return An error code, if any.
* @pre @a path must not be NULL.
* @pre @a s must not be NULL.
* @pre @a s must be UTF-8.
*/
y_Status
y_fs_path_sinit_cstr(y_Path* path, const char* s, y_Dtor dtor) y_allnonnull;
y_fs_path_sinit_cstr(y_Path* path, const char* s) y_allnonnull;
/**
* Initializes @a path with the y_Path that matches the string. The string is
@ -493,14 +492,13 @@ y_fs_path_init_str(y_Path* path, y_str s) y_allnonnull;
* assumed to be UTF-8. Uses the stack allocator for the thread.
* @param path The path to initialize and set.
* @param s The string to turn into a path.
* @param dtor The index of the path destructor.
* @return An error code, if any.
* @pre @a path must not be NULL.
* @pre @a s's string must not be NULL.
* @pre @a s's string must be UTF-8.
*/
y_Status
y_fs_path_sinit_str(y_Path* path, y_str s, y_Dtor dtor) y_allnonnull;
y_fs_path_sinit_str(y_Path* path, y_str s) y_allnonnull;
/**
* Initializes @a path with the y_Path that matches the string. The string is
@ -520,15 +518,13 @@ y_fs_path_init_string(y_Path* path, const y_String s) y_allnonnull;
* assumed to be UTF-8. Uses the stack allocator for the thread.
* @param path The path to initialize and set.
* @param s The string to turn into a path.
* @param dtor The index of the path destructor.
* @return An error code, if any.
* @pre @a path must not be NULL.
* @pre @a s must not be NULL.
* @pre @a s must be UTF-8.
*/
y_Status
y_fs_path_sinit_string(y_Path* path, const y_String s,
y_Dtor dtor) y_allnonnull;
y_fs_path_sinit_string(y_Path* path, const y_String s) y_allnonnull;
/**
* Removes the item at @a path.
@ -765,15 +761,13 @@ y_fs_path_concat(y_Path* res, y_Path path, y_Path name) y_allnonnull;
* @param res The path to initialize and set.
* @param path The beginning part of the path.
* @param name The file name.
* @param dtor The destructor index.
* @return An error code, if any.
* @pre @a res must not be NULL.
* @pre @a path must not be NULL.
* @pre @a name must not be NULL.
*/
y_Status
y_fs_path_sconcat(y_Path* res, y_Path path, y_Path name,
y_Dtor dtor) y_allnonnull;
y_fs_path_sconcat(y_Path* res, y_Path path, y_Path name) y_allnonnull;
/**
* Frees @a path.
@ -1609,14 +1603,12 @@ y_fs_filebytes_read(y_FileBytes* bytes, y_Path path, bool binary) y_allnonnull;
* @param bytes The byte array to initialize.
* @param path The path to the file.
* @param binary true if the file is a binary file, false otherwise.
* @param dtor The destructor for the stack allocator.
* @return An error code, if any.
* @pre @a file must not be NULL.
* @pre @a path must be valid.
*/
y_Status
y_fs_filebytes_sread(y_FileBytes* bytes, y_Path path, bool binary,
y_Dtor dtor) y_allnonnull;
y_fs_filebytes_sread(y_FileBytes* bytes, y_Path path, bool binary) y_allnonnull;
/**
* @}

23
include/yc/mappool.h

@ -101,29 +101,24 @@ typedef struct y_mappool* y_MapPool;
* @param hash The hash function for the pool's keys.
* @param eq The equality function for the pool's keys.
* @param kdtor The key destructor, or NULL if unnecessary.
* @param dtors A list of destructors to use with indices.
* @return A newly-created y_MapPool, or NULL on error.
* @pre @a ksize must be greater than zero.
* @pre If @a cmp is NULL, @a ksize must be sizeof(uint64_t).
* @pre If @a hash is NULL, @a ksize must be sizeof(uint64_t).
* @pre @a dtors must not be NULL.
* @pre @a load must be between (0, 1].
*/
y_MapPool
y_mappool_create(float load, size_t ksize, y_Hasher hash, y_Equal eq,
y_Destructor kdtor, const y_Destructor* dtors) y_noretalias;
y_Destructor kdtor) y_noretalias;
/**
* Creates a y_MapPool using strings as keys.
* @param load The load of the pool.
* @param dtors A list of destructors to use with indices.
* @return A newly-created y_MapPool, or NULL on error.
* @pre @a dtors must not be NULL.
* @pre @a load must be between (0, 1].
* @param load The load of the pool.
* @return A newly-created y_MapPool, or NULL on error.
* @pre @a load must be between (0, 1].
*/
y_MapPool
y_mappool_createStringKeyMap(float load,
const y_Destructor* dtors) y_noretalias;
y_mappool_createStringKeyMap(float load) y_noretalias;
/**
* Returns the number of allocations in @a p.
@ -254,7 +249,7 @@ y_mappool_getStringKey(const y_MapPool p,
*/
void*
y_mappool_malloc(y_MapPool p, const void* key, size_t size,
y_Dtor dtor) y_inline y_paramsnonnull(1, 2);
y_Destructor dtor) y_inline y_paramsnonnull(1, 2);
/**
* Allocates space in the pool for the key and returns a pointer to the space,
@ -277,7 +272,7 @@ y_mappool_malloc(y_MapPool p, const void* key, size_t size,
*/
void*
y_mappool_mallocStringKey(y_MapPool p, const char* key, size_t size,
y_Dtor dtor) y_inline y_paramsnonnull(1, 2);
y_Destructor dtor) y_inline y_paramsnonnull(1, 2);
/**
* Allocates space in @a p for @a key and returns a pointer to the space, or
@ -302,7 +297,7 @@ y_mappool_mallocStringKey(y_MapPool p, const char* key, size_t size,
*/
void*
y_mappool_calloc(y_MapPool p, const void* key, size_t size,
y_Dtor dtor) y_inline y_paramsnonnull(1, 2);
y_Destructor dtor) y_inline y_paramsnonnull(1, 2);
/**
* Allocates space in @a p for @a key and returns a pointer to the space, or
@ -327,7 +322,7 @@ y_mappool_calloc(y_MapPool p, const void* key, size_t size,
*/
void*
y_mappool_callocStringKey(y_MapPool p, const char* key, size_t size,
y_Dtor dtor) y_inline y_paramsnonnull(1, 2);
y_Destructor dtor) y_inline y_paramsnonnull(1, 2);
/**
* Frees the pool and all of its stuff.

5
include/yc/opt.h

@ -131,11 +131,10 @@ typedef struct
/**
* Creates and initializes the parser state.
* @param dtor The destructor index for the parser.
* @return The newly-created option parser, or NULL on error.
* @return The newly-created option parser, or NULL on error.
*/
y_Opt
y_opt_screate(y_Dtor dtor);
y_opt_screate(void);
/**
* Puts a new argv into the parser state. This is for parsing more than one

2
include/yc/setpool.h

@ -108,7 +108,7 @@ typedef struct y_setpool* y_SetPool;
*/
void*
y_setpool_alloc(y_SetPool p, const void* data, size_t size,
y_Dtor dtor) y_allnonnull;
y_Destructor dtor) y_paramsnonnull(1, 2);
#if YC_ENABLE_ALLOC_ACCOUNTING

36
include/yc/stackpool.h

@ -87,24 +87,24 @@ extern "C" {
* @{
*/
/**
* @def YC_ENABLE_ALLOC_ACCOUNTING
* A define that is non-zero when allocators should include accounting code.
*/
#ifdef YC_DEBUG
#ifndef YC_ENABLE_ALLOC_ACCOUNTING
#define YC_ENABLE_ALLOC_ACCOUNTING (1)
#endif // YC_ENABLE_ALLOC_ACCOUNTING
#endif // YC_DEBUG
#else // YC_DEBUG
/**
* @def y_STACKPOOL_MAX_DTORS
* The maximum number of dtors allowed, including the none destructor.
*/
#define y_STACKPOOL_MAX_DTORS (UINT16_MAX - 3)
#ifndef YC_ENABLE_ALLOC_ACCOUNTING
#define YC_ENABLE_ALLOC_ACCOUNTING (0)
#endif // YC_ENABLE_ALLOC_ACCOUNTING
/**
* A typedef for a destructor index.
*/
typedef uint16_t y_Dtor;
#endif // YC_DEBUG
/**
* The public type for the stack pool.
@ -168,30 +168,30 @@ y_stackpool_jmp(y_StackPool p, bool jmp) y_allnonnull;
* destructor at the @a dtor index to the allocation.
* @param p The stack pool.
* @param size The size to allocate.
* @param dtor The index of the destructor in the stack pool's destructor list
* to attach to the allocation.
* @param dtor The destructor to attach to the allocation. Can be NULL for no
* destructor.
* @return A pointer to the allocation.
* @pre @a p must not be NULL.
* @pre @a size must be greater than 0.
* @pre @a dtor must be a valid index to the destructor array.
*/
void*
y_stackpool_malloc(y_StackPool p, size_t size, y_Dtor dtor) y_allnonnull;
y_stackpool_malloc(y_StackPool p, size_t size, y_Destructor dtor)
y_paramsnonnull(1);
/**
* Allocates and zeroes at least @a size bytes in the stack pool and attaches
* the destructor at the @a dtor index to the allocation.
* @param p The stack pool.
* @param size The size to allocate.
* @param dtor The index of the destructor in the stack pool's destructor list
* to attach to the allocation.
* @param dtor The destructor to attach to the allocation. Can be NULL for no
* destructor.
* @return A pointer to the allocation.
* @pre @a p must not be NULL.
* @pre @a size must be greater than 0.
* @pre @a dtor must be a valid index to the destructor array.
*/
void*
y_stackpool_calloc(y_StackPool p, size_t size, y_Dtor dtor) y_allnonnull;
y_stackpool_calloc(y_StackPool p, size_t size, y_Destructor dtor)
y_paramsnonnull(1);
#if YC_ENABLE_ALLOC_ACCOUNTING

3
src/concurrency/strucon.c

@ -71,7 +71,6 @@
#include "../container/list.h"
#include "../io/io.h"
#include "../pool/stackpool.h"
#include "../util/types.h"
#include <setjmp.h>
@ -395,7 +394,7 @@ y_strucon_thread_init(y_threaddata** data, y_ThreadID parent,
if (init_pool)
{
s = y_stackpool_init(&dptr->pool, y_exec_dtors, alignof(max_align_t));
s = y_stackpool_init(&dptr->pool);
if (y_err(s != y_STATUS_SUCCESS)) goto alloc_err;
}

4
src/concurrency/threadset.c

@ -65,8 +65,6 @@
#include "threadset.h"
#include "../util/types.h"
static void
y_threadset_child_destroy(void* child)
{
@ -101,7 +99,7 @@ y_threadset_screate(void)
s = y_stackpool_enterScope(p);
if (y_err(s != y_STATUS_SUCCESS)) return NULL;
ts = y_stackpool_malloc(p, sizeof(y_threadset), y_EXECDTOR_THREADSET);
ts = y_stackpool_malloc(p, sizeof(y_threadset), y_threadset_destroy);
if (y_err(ts == NULL)) return NULL;
s = y_threadset_init(ts);

5
src/gaml/gaml.c

@ -74,7 +74,6 @@
#include "../container/imap.h"
#include "../str/string.h"
#include "../util/types.h"
#include "../yao/yao.h"
#include <assert.h>
@ -175,11 +174,11 @@ y_gaml_create(void)
}
y_Gaml
y_gaml_screate(y_Dtor dtor)
y_gaml_screate(void)
{
y_StackPool p = y_strucon_stackpool();
y_Gaml g = y_stackpool_malloc(p, sizeof(y_gaml), dtor);
y_Gaml g = y_stackpool_malloc(p, sizeof(y_gaml), y_gaml_destroy);
if (y_err(g == NULL)) return NULL;

5
src/gaml/parse.c

@ -64,7 +64,6 @@
#include "../yc.h"
#include "../concurrency/strucon.h"
#include "../util/types.h"
#include "../yao/yao.h"
static void
@ -399,7 +398,7 @@ y_gaml_parse_initVars(yao_Parse* p)
y_Status s;
void* ptr = yao_lex_alloc(&p->l, "gaml", "data", sizeof(y_GamlParseData),
y_EXECDTOR_GAML_PARSE_DATA);
y_gaml_parse_data_destroy);
if (y_err(ptr == NULL)) return y_strucon_status();
y_GamlParseData* data = (y_GamlParseData*) ptr;
@ -407,7 +406,7 @@ y_gaml_parse_initVars(yao_Parse* p)
data->nl_ws = true;
data->need_key = true;
s = y_setpool_init(&data->strs, 0.96f, y_exec_dtors, 1);
s = y_setpool_init(&data->strs, 0.96f);
data->inited = (s == y_STATUS_SUCCESS);
return s;

4
src/io/file.c

@ -1108,7 +1108,7 @@ y_file_read_err:
}
y_Status
y_fs_filebytes_sread(y_FileBytes* file, y_Path path, bool binary, y_Dtor dtor)
y_fs_filebytes_sread(y_FileBytes* file, y_Path path, bool binary)
{
y_File fp;
y_Status s = y_STATUS_SUCCESS;
@ -1137,7 +1137,7 @@ y_fs_filebytes_sread(y_FileBytes* file, y_Path path, bool binary, y_Dtor dtor)
y_StackPool p = y_strucon_stackpool();
file->len = alloc;
file->a = y_stackpool_malloc(p, alloc, dtor);
file->a = y_stackpool_malloc(p, alloc, NULL);
if (y_err(file->a == NULL))
{

4
src/io/io.c

@ -66,8 +66,6 @@
#include "../yc.h"
#include "../util/types.h"
static y_file y_stdin_file;
y_File y_stdin = &y_stdin_file;
@ -117,7 +115,7 @@ y_io_buf_sinit_size(y_iobuf* b, size_t size, y_stackpool* pool)
{
y_io_buf_initHelper(b, size);
b->buf = y_stackpool_malloc(pool, b->cap, y_EXECDTOR_NONE);
b->buf = y_stackpool_malloc(pool, b->cap, NULL);
if (y_err(b->buf == NULL)) return y_strucon_status();
return y_STATUS_SUCCESS;

3
src/io/io.h

@ -897,12 +897,11 @@ y_fs_path_init(y_Path* path, size_t len) y_allnonnull;
* allocator.
* @param path The path to initialize and set.
* @param len The amount of space to reserve for the path.
* @param dtor The index of the path destructor.
* @return An error code, if any.
* @pre @a path must not be NULL.
*/
y_Status
y_fs_path_sinit(y_Path* path, size_t len, y_Dtor dtor) y_allnonnull;
y_fs_path_sinit(y_Path* path, size_t len) y_allnonnull;
/**
* Opens the parent directory of the item at @a path. @a dir must be closed with

25
src/io/path.c

@ -100,7 +100,6 @@
#include "../yc.h"
#include "../pool/stackpool.h"
#include "../util/types.h"
#include <sys/stat.h>
@ -143,11 +142,11 @@ y_fs_path_init(y_Path* path, size_t len)
}
y_Status
y_fs_path_sinit(y_Path* path, size_t len, y_Dtor dtor)
y_fs_path_sinit(y_Path* path, size_t len)
{
y_StackPool p = y_strucon_stackpool();
path->a = y_stackpool_malloc(p, y_PATH_LEN(len), dtor);
path->a = y_stackpool_malloc(p, y_PATH_LEN(len), NULL);
if (path->a == NULL) return y_strucon_status();
#ifdef YC_DEBUG
@ -189,13 +188,13 @@ y_fs_path_init_cstr(y_Path* path, const char* s)
}
y_Status
y_fs_path_sinit_cstr(y_Path* path, const char* s, y_Dtor dtor)
y_fs_path_sinit_cstr(y_Path* path, const char* s)
{
size_t len = strlen(s) + 1;
y_StackPool p = y_strucon_stackpool();
path->a = y_stackpool_malloc(p, y_PATH_LEN(len), dtor);
path->a = y_stackpool_malloc(p, y_PATH_LEN(len), NULL);
if (y_err(path->a == NULL)) return y_strucon_status();
@ -245,11 +244,11 @@ y_fs_path_init_str(y_Path* path, y_str s)
}
y_Status
y_fs_path_sinit_str(y_Path* path, y_str s, y_Dtor dtor)
y_fs_path_sinit_str(y_Path* path, y_str s)
{
y_StackPool p = y_strucon_stackpool();
path->a = y_stackpool_malloc(p, y_PATH_LEN(s.len), dtor);
path->a = y_stackpool_malloc(p, y_PATH_LEN(s.len), NULL);
if (y_err(path->a == NULL)) return y_strucon_status();
@ -299,11 +298,11 @@ y_fs_path_init_string(y_Path* path, const y_String s)
}
y_Status
y_fs_path_sinit_string(y_Path* path, const y_String s, y_Dtor dtor)
y_fs_path_sinit_string(y_Path* path, const y_String s)
{
y_StackPool p = y_strucon_stackpool();
path->a = y_stackpool_malloc(p, y_PATH_LEN(s->len), dtor);
path->a = y_stackpool_malloc(p, y_PATH_LEN(s->len), NULL);
if (y_err(path->a == NULL)) return y_strucon_status();
@ -474,7 +473,7 @@ y_fs_path_realpath(y_Path* realpath, y_Path path)
y_Status
y_fs_path_srealpath(y_Path* realpath, y_Path path)
{
y_Status s = y_fs_path_sinit(realpath, y_PATH_ALLOC, y_EXECDTOR_NONE);
y_Status s = y_fs_path_sinit(realpath, y_PATH_ALLOC);
if (y_err(s != y_STATUS_SUCCESS)) return s;
y_Error e = y_fs_os_realpath(realpath, path);
@ -529,9 +528,9 @@ y_fs_path_concat(y_Path* res, y_Path path, y_Path name)
}
y_Status
y_fs_path_sconcat(y_Path* res, y_Path path, y_Path name, y_Dtor dtor)
y_fs_path_sconcat(y_Path* res, y_Path path, y_Path name)
{
y_Status s = y_fs_path_sinit(res, path.len + name.len + 1, dtor);
y_Status s = y_fs_path_sinit(res, path.len + name.len + 1);
if (y_err(s != y_STATUS_SUCCESS)) return s;
@ -654,7 +653,7 @@ y_fs_path_copyTreeHelper(const y_Path dest, const y_Path src)
continue;
}
s = y_fs_path_sconcat(&dest_path, dest, base, y_EXECDTOR_NONE);
s = y_fs_path_sconcat(&dest_path, dest, base);
if (y_err(s != y_STATUS_SUCCESS))
{
y_fs_path_destroy(&base);

36
src/pool/mappool.c

@ -95,7 +95,7 @@
* @a y_mappool_createStringKey().
*/
y_allnonnull static void*
y_mappool_alloc(y_mappool* p, const void* key, size_t size, y_Dtor dtor,
y_mappool_alloc(y_mappool* p, const void* key, size_t size, y_Destructor dtor,
bool zero)
{
unsigned char* ptr;
@ -141,7 +141,7 @@ y_mappool_alloc(y_mappool* p, const void* key, size_t size, y_Dtor dtor,
*/
y_allnonnull static void*
y_mappool_allocStringKey(y_mappool* p, const char* key, size_t size,
y_Dtor dtor, bool zero)
y_Destructor dtor, bool zero)
{
unsigned char* ptr;
@ -170,9 +170,9 @@ y_mappool_allocStringKey(y_mappool* p, const char* key, size_t size,
y_Status
y_mappool_init(y_mappool* p, float load, size_t ksize, y_Hasher hash,
y_Equal eq, y_Destructor kdtor, const y_Destructor* dtors)
y_Equal eq, y_Destructor kdtor)
{
y_Status s = y_stackpool_init(&p->pool, dtors, alignof(max_align_t));
y_Status s = y_stackpool_init(&p->pool);
if (y_err(s != y_STATUS_SUCCESS)) return s;
s = y_map_init(&p->map, load, ksize, sizeof(y_mappool_ref), hash, eq, kdtor,
@ -186,15 +186,15 @@ y_mappool_init(y_mappool* p, float load, size_t ksize, y_Hasher hash,
}
y_Status
y_mappool_initStringKeyMap(y_mappool* p, float load, const y_Destructor* dtors)
y_mappool_initStringKeyMap(y_mappool* p, float load)
{
return y_mappool_init(p, load, sizeof(y_str), y_str_hash, y_str_eq,
y_str_free, dtors);
y_str_free);
}
y_MapPool
y_mappool_create(float load, size_t ksize, y_Hasher hash, y_Equal eq,
y_Destructor kdtor, const y_Destructor* dtors)
y_Destructor kdtor)
{
yc_assert(ksize, YC_ASSERT_KSIZE_ZERO);
@ -207,7 +207,7 @@ y_mappool_create(float load, size_t ksize, y_Hasher hash, y_Equal eq,
y_mappool* p = (y_mappool*) y_calloc(1, size);
if (y_err(p == NULL)) return NULL;
y_Status s = y_mappool_init(p, load, ksize, hash, eq, kdtor, dtors);
y_Status s = y_mappool_init(p, load, ksize, hash, eq, kdtor);
if (y_err(s != y_STATUS_SUCCESS))
{
y_free(p);
@ -218,7 +218,7 @@ y_mappool_create(float load, size_t ksize, y_Hasher hash, y_Equal eq,
}
y_MapPool
y_mappool_createStringKeyMap(float load, const y_Destructor* dtors)
y_mappool_createStringKeyMap(float load)
{
yc_assert(load <= 1.0f && load > 0.0f, YC_ASSERT_MAP_LOAD_RANGE);
@ -229,7 +229,7 @@ y_mappool_createStringKeyMap(float load, const y_Destructor* dtors)
if (y_err(p == NULL)) return NULL;
y_Status s = y_mappool_init(p, load, sizeof(y_str), y_str_hash, y_str_eq,
y_str_free, dtors);
y_str_free);
if (y_err(s != y_STATUS_SUCCESS))
{
y_free(p);
@ -329,7 +329,7 @@ y_mappool_getStringKey(const y_MapPool p, const char* key)
}
void*
y_mappool_malloc(y_MapPool p, const void* key, size_t size, y_Dtor dtor)
y_mappool_malloc(y_MapPool p, const void* key, size_t size, y_Destructor dtor)
{
yc_assert(p, YC_ASSERT_POOL_NULL);
yc_assert(key, YC_ASSERT_KEY_NULL);
@ -340,7 +340,7 @@ y_mappool_malloc(y_MapPool p, const void* key, size_t size, y_Dtor dtor)
y_mappool_ref* refptr;
size = y_MAPPOOL_ROUND_UP(size, p->pool.align);
size = y_MAPPOOL_ROUND_UP(size);
if (size >= UINT32_MAX)
{
@ -364,7 +364,7 @@ y_mappool_malloc(y_MapPool p, const void* key, size_t size, y_Dtor dtor)
void*
y_mappool_mallocStringKey(y_MapPool p, const char* key, size_t size,
y_Dtor dtor)
y_Destructor dtor)
{
yc_assert(p, YC_ASSERT_POOL_NULL);
yc_assert(key, YC_ASSERT_KEY_NULL);
@ -375,7 +375,7 @@ y_mappool_mallocStringKey(y_MapPool p, const char* key, size_t size,
y_mappool_ref* refptr;
size = y_MAPPOOL_ROUND_UP(size, p->pool.align);
size = y_MAPPOOL_ROUND_UP(size);
if (size >= UINT32_MAX)
{
@ -398,7 +398,7 @@ y_mappool_mallocStringKey(y_MapPool p, const char* key, size_t size,
}
void*
y_mappool_calloc(y_MapPool p, const void* key, size_t size, y_Dtor dtor)
y_mappool_calloc(y_MapPool p, const void* key, size_t size, y_Destructor dtor)
{
yc_assert(p, YC_ASSERT_POOL_NULL);
yc_assert(key, YC_ASSERT_KEY_NULL);
@ -409,7 +409,7 @@ y_mappool_calloc(y_MapPool p, const void* key, size_t size, y_Dtor dtor)
y_mappool_ref* refptr;
size = y_MAPPOOL_ROUND_UP(size, p->pool.align);
size = y_MAPPOOL_ROUND_UP(size);
if (size >= UINT32_MAX)
{
@ -433,7 +433,7 @@ y_mappool_calloc(y_MapPool p, const void* key, size_t size, y_Dtor dtor)
void*
y_mappool_callocStringKey(y_MapPool p, const char* key, size_t size,
y_Dtor dtor)
y_Destructor dtor)
{
yc_assert(p, YC_ASSERT_POOL_NULL);
yc_assert(key, YC_ASSERT_KEY_NULL);
@ -444,7 +444,7 @@ y_mappool_callocStringKey(y_MapPool p, const char* key, size_t size,
y_mappool_ref* refptr;
size = y_MAPPOOL_ROUND_UP(size, p->pool.align);
size = y_MAPPOOL_ROUND_UP(size);
if (size >= UINT32_MAX)
{

31
src/pool/mappool.h

@ -89,12 +89,11 @@ extern "C" {
/**
* @def y_MAPPOOL_ROUND_UP
* Rounds a size up to the next multiple of the max_align_t size.
* Rounds a size up to the next multiple of the max_align_t alignment.
* @param s The input size.
* @param a The alignment.
* @return The size rounded up to the next multiple of the size of pointers.
* @return The size rounded up to the next multiple of the max alignment.
*/
#define y_MAPPOOL_ROUND_UP(s, a) y_STACKPOOL_ROUND_UP(s, a)
#define y_MAPPOOL_ROUND_UP(s) y_STACKPOOL_ROUND_UP(s)
/**
* @def y_MAPPOOL_VEC_INITIAL_CAP
@ -153,7 +152,6 @@ typedef struct y_mappool_ref
* @param hash The hash function that will be used for the map.
* @param eq The equality function that will be used to compare keys.
* @param kdtor The destructor function for the key type, if necessary.
* @param dtors The array of destructors to use for element destructors.
* @return @a y_STATUS_SUCCESS on success, an error code otherwise.
* @pre @a p must not be NULL.
* @pre Key size must be greater than zero.
@ -166,24 +164,21 @@ typedef struct y_mappool_ref
*/
y_Status
y_mappool_init(y_mappool* p, float load, size_t ksize, y_Hasher hash,
y_Equal eq, y_Destructor kdtor, const y_Destructor* dtors)
y_paramsnonnull(1, 7);
y_Equal eq, y_Destructor kdtor) y_paramsnonnull(1);
/**
* Initializes a y_MapPool using string keys.
* @param p The mappool to initialize.
* @param load The max load factor for the map.
* @param dtors The array of destructors to use for element destructors.
* @return @a y_STATUS_SUCCESS on success, an error code otherwise.
* @pre @a p must not be NULL.
* @pre @a load must be between (0, 1].
* @pre There must be enough space after @a m for 3 * ksize and 3 *
* esize. This is to use for swapping keys and values for Robin
* Hood hashing.
* @param p The mappool to initialize.
* @param load The max load factor for the map.
* @return @a y_STATUS_SUCCESS on success, an error code otherwise.
* @pre @a p must not be NULL.
* @pre @a load must be between (0, 1].
* @pre There must be enough space after @a m for 3 * ksize and 3 *
* esize. This is to use for swapping keys and values for Robin
* Hood hashing.
*/
y_Status
y_mappool_initStringKeyMap(y_mappool* p, float load,
const y_Destructor* dtors) y_allnonnull;
y_mappool_initStringKeyMap(y_mappool* p, float load) y_allnonnull;
/**
* Frees the data for a mappool.

12
src/pool/setpool.c

@ -388,14 +388,13 @@ err:
}
y_Status
y_setpool_init(y_setpool* p, const float load, const y_Destructor* dtors,
unsigned char align)
y_setpool_init(y_setpool* p, const float load)
{
yc_assert(p, YC_ASSERT_POOL_NULL);
yc_assert(load <= 1.0f && load > 0.0f, YC_ASSERT_MAP_LOAD_RANGE);
y_Status s = y_stackpool_init(&p->pool, dtors, 1U << align);
y_Status s = y_stackpool_init(&p->pool);
if (y_err(s != y_STATUS_SUCCESS)) return s;
y_setpoolkey_mut** keys = y_calloc(y_SETPOOL_INITIAL_ARRAY_ALLOC,
@ -415,6 +414,7 @@ y_setpool_init(y_setpool* p, const float load, const y_Destructor* dtors,
p->max = (size_t) (load * (float) y_SETPOOL_INITIAL_CAP);
p->load = load;
p->len = 0;
p->growing = false;
return y_STATUS_SUCCESS;
@ -694,7 +694,7 @@ y_setpool_insertHelper(y_setpool* p, y_setpoolkey* key)
// This directly uses the allocs length because it needs to work in the
// absence of accounting, and a setpool does not use scopes or jumps anyway.
if (p->pool.allocs.len > p->max)
if (p->len > p->max)
{
s = y_setpool_grow(p);
if (y_err(s != y_STATUS_SUCCESS)) return s;
@ -714,7 +714,7 @@ y_setpool_insertHelper(y_setpool* p, y_setpoolkey* key)
}
void*
y_setpool_alloc(y_SetPool p, const void* data, size_t size, y_Dtor dtor)
y_setpool_alloc(y_SetPool p, const void* data, size_t size, y_Destructor dtor)
{
y_Status s;
@ -756,6 +756,8 @@ y_setpool_alloc(y_SetPool p, const void* data, size_t size, y_Dtor dtor)
return NULL;
}
p->len += 1;
#if YC_DEBUG_CODE
y_setpool_print(p);
#endif // YC_DEBUG_CODE

17
src/pool/setpool.h

@ -249,6 +249,9 @@ typedef struct y_setpool
/// The capacity.
size_t cap;
/// The number of allocations.
size_t len;
/// The max number of elements the setpool can hold without growing.
size_t max;
@ -265,17 +268,13 @@ typedef struct y_setpool
/**
* Initializes a setpool.
* @param p The setpool to initialize.
* @param load The load of the internal map.
* @param dtors The array of destructors to use with dtor indices.
* @param align The power of 2 to use for alignment for allocations.
* @return An error code, if any.
* @pre @a p must not be NULL.
* @pre @a dtors must not be NULL.
* @param p The setpool to initialize.
* @param load The load of the internal map.
* @return An error code, if any.
* @pre @a p must not be NULL.
*/
y_Status
y_setpool_init(y_setpool* p, const float load, const y_Destructor* dtors,
unsigned char align) y_allnonnull;
y_setpool_init(y_setpool* p, const float load) y_allnonnull;
/**
* This is the procedure that prepares for the insertion.

606
src/pool/stackpool.c

@ -61,7 +61,6 @@
#include <yc/assert.h>
#include <yc/strucon.h>
#include <yc/svector.h>
#include <yc/sys.h>
#include "stackpool.h"
@ -70,24 +69,182 @@
#include <stdalign.h>
// TODO: Investigate the idea of having a NULL dtors array in a stackpool for
// situations where no destructor is ever needed for allocations. One example is
// the strings one in YaoProgram. With a NULL dtors, use a different struct type
// to store info about an allocation that does not have a dtor field.
// TODO: Change the destructor list to always include Yc's. However, users'
// destructors should be included; they should just be adjusted to always be
// higher.
// TODO: Make sure cur_mmap and cur_ptr are always set.
static y_ulong pagesize;
static y_ulong mmapsize;
static void
y_stackpool_freeHelper(y_stackpool* p, bool destruct) y_allnonnull;
static y_Status
y_stackpage_init(y_StackPage* p, size_t esize, y_Destructor dtor)
{
y_stackpage* new;
y_assert(esize < pagesize - sizeof(y_stackpage),
"Must be able to fit item into page");
new = y_alloc_os_mmap(pagesize);
if (y_err(new == NULL)) return y_strucon_status();
new->prev = new;
new->next = NULL;
new->dtor = dtor;
new->used = sizeof(y_stackpage);
new->esize = (uint32_t) esize;
*p = new;
return y_STATUS_SUCCESS;
}
static y_Status
y_stackpage_addPage(y_StackPage* p)
{
y_stackpage* new;
y_stackpage* page = *p;
new = y_alloc_os_mmap(pagesize);
if (y_err(new == NULL)) return y_strucon_status();
new->prev = page;
new->next = NULL;
new->dtor = page->dtor;
new->used = sizeof(y_stackpage);
new->esize = page->esize;
page->next = new;
*p = new;
return y_STATUS_SUCCESS;
}
static y_inline y_Status
y_stackpage_push(y_StackPage* p, void* data)
{
y_Status s;
y_StackPage page = *p;
size_t n = page->esize;
y_assert(n <= pagesize - sizeof(y_stackpage),
"Cannot push data that is bigger than a page");
if (y_unlikely(page->used + n > pagesize))
{
s = y_stackpage_addPage(p);
if (y_err(s != y_STATUS_SUCCESS)) return s;
page = *p;
}
unsigned char* ptr = ((unsigned char*) page) + page->used;
memcpy(ptr, data, n);
page->used += n;
return y_STATUS_SUCCESS;
}
static y_inline bool
y_stackpage_hasItem(y_StackPage p)
{
return (p != p->next || p->used > sizeof(y_stackpage));
}
static y_inline bool
y_stackpage_hasOneItem(y_StackPage p)
{
return (p == p->next && p->used == p->esize + sizeof(y_stackpage));
}
static y_inline void*
y_stackpage_last(y_StackPage p)
{
y_assert(n <= p->used - sizeof(y_stackpage),
"Wrong size for the last item");
return ((unsigned char*) p) + (p->used - p->esize);
}
static void
y_stackpage_pop(y_StackPage* p)
{
y_StackPage page = *p;
y_assert(page->esize <= page->used - sizeof(y_stackpage),
"Wrong size for popping or trying to pop item that doesn't exist");
page->used -= page->esize;
if (page->dtor != NULL)
{
page->dtor(page + page->used);
}
if (y_unlikely(page->used == sizeof(y_stackpage)))
{
y_assert(page->prev != page, "Trying to pop item that doesn't exist");
*p = page->prev;
}
}
static void
y_stackpage_gc(y_StackPage p)
{
if (p->dtor != NULL)
{
y_Destructor dtor = p->dtor;
while (p != NULL)
{
y_stackpage* temp = p->next;
size_t n = sizeof(y_stackpage);
unsigned char* ptr = (unsigned char*) (void*) p;
while (n + p->esize <= p->used)
{
dtor(ptr + n);
n += p->esize;
}
y_alloc_os_munmap(p, pagesize);
p = temp;
}
}
else
{
while (p != NULL)
{
y_stackpage* temp = p->next;
y_alloc_os_munmap(p, pagesize);
p = temp;
}
}
}
static void
y_stackpage_destroy(void* page)
{
y_StackPage* p = (y_StackPage*) page;
y_StackPage p2 = *p;
y_assert(p2->prev == p2, "Must call destroy on the first page");
y_stackpage_gc(p2);
}
y_Status
y_stackmmap_mmap(y_stackmmap* m)
{
m->ptr = y_alloc_os_mmap(y_STACKMMAP_SIZE);
y_assert(mmapsize != 0, "mmapsize not set");
m->ptr = y_alloc_os_mmap(mmapsize);
if (y_err(m->ptr == NULL)) return y_strucon_status();
return y_STATUS_SUCCESS;
@ -96,19 +253,24 @@ y_stackmmap_mmap(y_stackmmap* m)
void
y_stackmmap_munmap(y_stackmmap* m)
{
y_alloc_os_munmap(m->ptr, y_STACKMMAP_SIZE);
y_assert(mmapsize != 0, "mmapsize not set");
y_alloc_os_munmap(m->ptr, mmapsize);
}
static y_Status
y_stackmmap_init(y_stackmmap* m)
{
yc_assert(m != NULL, YC_ASSERT_NULL);
y_assert(mmapsize != 0, "mmapsize not set");
m->used = 0;
return y_stackmmap_mmap(m);
}
static void
y_stackmmap_free(void* stackmmap)
y_stackmmap_destroy(void* stackmmap)
{
yc_assert(stackmmap != NULL, YC_ASSERT_NULL);
y_stackmmap* m = (y_stackmmap*) stackmmap;
@ -116,7 +278,7 @@ y_stackmmap_free(void* stackmmap)
}
static void
y_stackmalloc_free(void* stackmalloc)
y_stackmalloc_destroy(void* stackmalloc)
{
yc_assert(stackmalloc != NULL, YC_ASSERT_NULL);
y_stackmalloc* m = (y_stackmalloc*) stackmalloc;
@ -124,69 +286,133 @@ y_stackmalloc_free(void* stackmalloc)
y_free(m->ptr);
}
static void
y_stackpool_scope_destroy(void* ptr)
{
unsigned char* p = (unsigned char*) ptr;
y_UNUSED(p);
#ifdef YC_DEBUG
for (size_t i = 0; i < sizeof(max_align_t); ++i)
{
if (p[i] != y_STACKMMAP_SCOPE)
{
panic("Invalid scope");
}
}
#endif // YC_DEBUG
}
static void
y_stackpool_jmp_destroy(void* ptr)
{
unsigned char* p = (unsigned char*) ptr;
y_UNUSED(p);
#ifdef YC_DEBUG
for (size_t i = 0; i < sizeof(max_align_t); ++i)
{
if (p[i] != y_STACKMMAP_JMP)
{
panic("Invalid jmp");
}
}
#endif // YC_DEBUG
}
static y_noreturn void
y_stackpool_jmp2_destroy(void* ptr)
{
sigjmp_buf* p = (sigjmp_buf*) ptr;
sigjmp_buf buf;
memcpy(&buf, p, sizeof(sigjmp_buf));
siglongjmp(buf, 1);
}
y_Status
y_stackpool_init(y_stackpool* p, const y_Destructor* dtors, uint32_t align)
y_stackpool_init(y_stackpool* p)
{
y_Status s;
yc_assert(p != NULL, YC_ASSERT_NULL);
y_assert(align == 1 || !(align & (align - 1)),
"alignment must be a power of 2");
p->dtors = dtors;
p->mmap_idx = 0;
#if YC_ENABLE_ALLOC_ACCOUNTING
p->nbytes = 0;
p->nallocs = 0;
p->nscopes = 0;
p->njmps = 0;
#endif // YC_ENABLE_ALLOC_ACCOUNTING
p->align = align;
if (pagesize == 0)
{
y_ulong pagesize2 = y_sys_pagesize();
pagesize = y_sys_pagesize();
if (pagesize > y_STACKMMAP_MAX_PAGESIZE)
{
pagesize = y_STACKMMAP_MAX_PAGESIZE;
}
if (pagesize2 < y_STACKMMAP_MAX_PAGESIZE)
if (pagesize < y_STACKMMAP_SIZE)
{
pagesize = pagesize2;
mmapsize = y_STACKMMAP_SIZE;
}
else
{
pagesize = y_STACKMMAP_DEF_PAGESIZE;
mmapsize = pagesize;
}
}
s = y_svec_init(&p->mmaps, sizeof(y_stackmmap), y_stackmmap_free, NULL);
s = y_stackpage_init(&p->cur_alloc_page, sizeof(y_stackalloc), NULL);
if (y_err(s != y_STATUS_SUCCESS)) return s;
s = y_stackpage_init(&p->cur_malloc_page, sizeof(y_stackmalloc),
y_stackmalloc_destroy);
if (y_err(s != y_STATUS_SUCCESS)) goto malloc_page_init_err;
s = y_stackpage_init(&p->cur_mmap_page, sizeof(y_stackmmap),
y_stackmmap_destroy);
if (y_err(s != y_STATUS_SUCCESS)) goto mmap_page_init_err;
y_stackmmap mm;
s = y_stackmmap_init(&mm);
if (y_err(s != y_STATUS_SUCCESS)) goto mmap_init_err;
s = y_svec_push(&p->mmaps, &mm);
s = y_stackpage_push(&p->cur_mmap_page, &mm);
if (y_err(s != y_STATUS_SUCCESS)) goto mmap_push_err;
s = y_svec_init(&p->allocs, sizeof(y_stackalloc), NULL, NULL);
if (y_err(s != y_STATUS_SUCCESS)) goto mmap_init_err;
unsigned char* ptr;
s = y_svec_init(&p->mallocs, sizeof(y_stackmalloc), y_stackmalloc_free,
NULL);
if (y_err(s != y_STATUS_SUCCESS))
{
y_svec_destroy(&p->allocs);
goto mmap_init_err;
}
p->mmap_idx = sizeof(y_stackpage);
ptr = ((unsigned char*) p->cur_mmap_page) + p->mmap_idx;
p->cur_mmap = (y_stackmmap*) (void*) ptr;
p->cur_ptr = p->cur_mmap->ptr;
p->first_mmap = p->cur_mmap;
return s;
mmap_push_err:
y_stackmmap_free(&mm);
y_stackmmap_destroy(&mm);
mmap_init_err:
y_svec_destroy(&p->mmaps);
y_stackpage_destroy(&p->cur_mmap_page);
mmap_page_init_err:
y_stackpage_destroy(&p->cur_malloc_page);
malloc_page_init_err:
y_stackpage_destroy(&p->cur_alloc_page);