From 7b05f25b980e9589c7e0f9a5c9754f3442e01a33 Mon Sep 17 00:00:00 2001 From: Protobuf Team Bot Date: Wed, 22 Jun 2022 09:18:12 -0700 Subject: [PATCH] split out the alloc code from the arena code PiperOrigin-RevId: 456531002 --- BUILD | 3 ++ upb/alloc.c | 47 +++++++++++++++++++++++ upb/alloc.h | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ upb/arena.c | 23 +----------- upb/arena.h | 63 ++----------------------------- upb/port_def.inc | 5 ++- 6 files changed, 157 insertions(+), 82 deletions(-) create mode 100644 upb/alloc.c create mode 100644 upb/alloc.h diff --git a/BUILD b/BUILD index 95701d1d2f..00bd8fd5fb 100644 --- a/BUILD +++ b/BUILD @@ -102,6 +102,7 @@ cc_library( cc_library( name = "upb", srcs = [ + "upb/alloc.c", "upb/arena.c", "upb/decode.c", "upb/encode.c", @@ -115,6 +116,7 @@ cc_library( "upb/upb.c", ], hdrs = [ + "upb/alloc.h", "upb/arena.h", "upb/decode.h", "upb/encode.h", @@ -707,6 +709,7 @@ sh_test( cc_library( name = "table", hdrs = [ + "upb/alloc.h", "upb/arena.h", "upb/internal/table.h", "upb/status.h", diff --git a/upb/alloc.c b/upb/alloc.c new file mode 100644 index 0000000000..6e242cd6c4 --- /dev/null +++ b/upb/alloc.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2009-2021, Google LLC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Google LLC nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "upb/alloc.h" + +#include + +// Must be last. +#include "upb/port_def.inc" + +static void* upb_global_allocfunc(upb_alloc* alloc, void* ptr, size_t oldsize, + size_t size) { + UPB_UNUSED(alloc); + UPB_UNUSED(oldsize); + if (size == 0) { + free(ptr); + return NULL; + } else { + return realloc(ptr, size); + } +} + +upb_alloc upb_alloc_global = {&upb_global_allocfunc}; diff --git a/upb/alloc.h b/upb/alloc.h new file mode 100644 index 0000000000..add70b8799 --- /dev/null +++ b/upb/alloc.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2009-2021, Google LLC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Google LLC nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UPB_ALLOC_H_ +#define UPB_ALLOC_H_ + +#include "upb/port_def.inc" + +#ifdef __cplusplus +extern "C" { +#endif + +struct upb_alloc; +typedef struct upb_alloc upb_alloc; + +/* A combined `malloc()`/`free()` function. + * If `size` is 0 then the function acts like `free()`, otherwise it acts like + * `realloc()`. Only `oldsize` bytes from a previous allocation are + * preserved. */ +typedef void* upb_alloc_func(upb_alloc* alloc, void* ptr, size_t oldsize, + size_t size); + +/* A upb_alloc is a possibly-stateful allocator object. + * + * It could either be an arena allocator (which doesn't require individual + * `free()` calls) or a regular `malloc()` (which does). The client must + * therefore free memory unless it knows that the allocator is an arena + * allocator. */ +struct upb_alloc { + upb_alloc_func* func; +}; + +UPB_INLINE void* upb_malloc(upb_alloc* alloc, size_t size) { + UPB_ASSERT(alloc); + return alloc->func(alloc, NULL, 0, size); +} + +UPB_INLINE void* upb_realloc(upb_alloc* alloc, void* ptr, size_t oldsize, + size_t size) { + UPB_ASSERT(alloc); + return alloc->func(alloc, ptr, oldsize, size); +} + +UPB_INLINE void upb_free(upb_alloc* alloc, void* ptr) { + UPB_ASSERT(alloc); + alloc->func(alloc, ptr, 0, 0); +} + +/* The global allocator used by upb. Uses the standard malloc()/free(). */ + +extern upb_alloc upb_alloc_global; + +/* Functions that hard-code the global malloc. + * + * We still get benefit because we can put custom logic into our global + * allocator, like injecting out-of-memory faults in debug/testing builds. */ + +UPB_INLINE void* upb_gmalloc(size_t size) { + return upb_malloc(&upb_alloc_global, size); +} + +UPB_INLINE void* upb_grealloc(void* ptr, size_t oldsize, size_t size) { + return upb_realloc(&upb_alloc_global, ptr, oldsize, size); +} + +UPB_INLINE void upb_gfree(void* ptr) { upb_free(&upb_alloc_global, ptr); } + +#include "upb/port_undef.inc" + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* UPB_ALLOC_H_ */ diff --git a/upb/arena.c b/upb/arena.c index 3c872698cd..6cee9cfcb2 100644 --- a/upb/arena.c +++ b/upb/arena.c @@ -27,27 +27,12 @@ #include "upb/arena.h" -#include - +#include "upb/alloc.h" #include "upb/internal/upb.h" // Must be last. #include "upb/port_def.inc" -/* upb_alloc ******************************************************************/ - -static void* upb_global_allocfunc(upb_alloc* alloc, void* ptr, size_t oldsize, - size_t size) { - UPB_UNUSED(alloc); - UPB_UNUSED(oldsize); - if (size == 0) { - free(ptr); - return NULL; - } else { - return realloc(ptr, size); - } -} - static uint32_t* upb_cleanup_pointer(uintptr_t cleanup_metadata) { return (uint32_t*)(cleanup_metadata & ~0x1); } @@ -61,10 +46,6 @@ static uintptr_t upb_cleanup_metadata(uint32_t* cleanup, return (uintptr_t)cleanup | has_initial_block; } -upb_alloc upb_alloc_global = {&upb_global_allocfunc}; - -/* upb_Arena ******************************************************************/ - struct mem_block { struct mem_block* next; uint32_t size; @@ -135,7 +116,7 @@ static void* upb_Arena_doalloc(upb_alloc* alloc, void* ptr, size_t oldsize, /* Public Arena API ***********************************************************/ -upb_Arena* arena_initslow(void* mem, size_t n, upb_alloc* alloc) { +static upb_Arena* arena_initslow(void* mem, size_t n, upb_alloc* alloc) { const size_t first_block_overhead = sizeof(upb_Arena) + memblock_reserve; upb_Arena* a; diff --git a/upb/arena.h b/upb/arena.h index 0c4fd1b83c..81a673bd9a 100644 --- a/upb/arena.h +++ b/upb/arena.h @@ -28,75 +28,18 @@ #ifndef UPB_ARENA_H_ #define UPB_ARENA_H_ -#include #include -#include #include +#include "upb/alloc.h" + +// Must be last. #include "upb/port_def.inc" #ifdef __cplusplus extern "C" { #endif -/** upb_alloc *****************************************************************/ - -/* A upb_alloc is a possibly-stateful allocator object. - * - * It could either be an arena allocator (which doesn't require individual - * free() calls) or a regular malloc() (which does). The client must therefore - * free memory unless it knows that the allocator is an arena allocator. */ - -struct upb_alloc; -typedef struct upb_alloc upb_alloc; - -/* A malloc()/free() function. - * If "size" is 0 then the function acts like free(), otherwise it acts like - * realloc(). Only "oldsize" bytes from a previous allocation are preserved. */ -typedef void* upb_alloc_func(upb_alloc* alloc, void* ptr, size_t oldsize, - size_t size); - -struct upb_alloc { - upb_alloc_func* func; -}; - -UPB_INLINE void* upb_malloc(upb_alloc* alloc, size_t size) { - UPB_ASSERT(alloc); - return alloc->func(alloc, NULL, 0, size); -} - -UPB_INLINE void* upb_realloc(upb_alloc* alloc, void* ptr, size_t oldsize, - size_t size) { - UPB_ASSERT(alloc); - return alloc->func(alloc, ptr, oldsize, size); -} - -UPB_INLINE void upb_free(upb_alloc* alloc, void* ptr) { - assert(alloc); - alloc->func(alloc, ptr, 0, 0); -} - -/* The global allocator used by upb. Uses the standard malloc()/free(). */ - -extern upb_alloc upb_alloc_global; - -/* Functions that hard-code the global malloc. - * - * We still get benefit because we can put custom logic into our global - * allocator, like injecting out-of-memory faults in debug/testing builds. */ - -UPB_INLINE void* upb_gmalloc(size_t size) { - return upb_malloc(&upb_alloc_global, size); -} - -UPB_INLINE void* upb_grealloc(void* ptr, size_t oldsize, size_t size) { - return upb_realloc(&upb_alloc_global, ptr, oldsize, size); -} - -UPB_INLINE void upb_gfree(void* ptr) { upb_free(&upb_alloc_global, ptr); } - -/* upb_Arena ******************************************************************/ - /* upb_Arena is a specific allocator implementation that uses arena allocation. * The user provides an allocator that will be used to allocate the underlying * arena blocks. Arenas by nature do not require the individual allocations diff --git a/upb/port_def.inc b/upb/port_def.inc index 92e4bf2477..849a7659d8 100644 --- a/upb/port_def.inc +++ b/upb/port_def.inc @@ -54,8 +54,11 @@ #error upb requires C99 or C++11 or MSVC >= 2015. #endif -#include +#include +#include +#include #include +#include #if UINTPTR_MAX == 0xffffffff #define UPB_SIZE(size32, size64) size32