create mem/ subdir for all arena code

PiperOrigin-RevId: 485884460
pull/13171/head
Eric Salo 2 years ago committed by Joshua Haberman
parent 5ba0d84c88
commit f409c9985b
  1. 51
      BUILD
  2. 69
      upb/alloc.h
  3. 139
      upb/arena.h
  4. 2
      upb/decode.h
  5. 2
      upb/internal/decode.h
  6. 2
      upb/io/chunked_input_stream.h
  7. 2
      upb/io/chunked_output_stream.h
  8. 2
      upb/io/string.h
  9. 2
      upb/mem/alloc.c
  10. 98
      upb/mem/alloc.h
  11. 2
      upb/mem/arena.c
  12. 168
      upb/mem/arena.h
  13. 9
      upb/mem/arena_internal.h
  14. 2
      upb/mini_table/common.c
  15. 2
      upb/mini_table/decode.c
  16. 2
      upb/mini_table/encode.c
  17. 2
      upb/msg.h
  18. 2
      upb/upb.h

51
BUILD

@ -109,8 +109,6 @@ cc_library(
cc_library( cc_library(
name = "upb", name = "upb",
srcs = [ srcs = [
"upb/alloc.c",
"upb/arena.c",
"upb/array.c", "upb/array.c",
"upb/decode.c", "upb/decode.c",
"upb/encode.c", "upb/encode.c",
@ -130,6 +128,8 @@ cc_library(
"upb/decode.h", "upb/decode.h",
"upb/encode.h", "upb/encode.h",
"upb/extension_registry.h", "upb/extension_registry.h",
"upb/mem/alloc.h",
"upb/mem/arena.h",
"upb/message_value.h", "upb/message_value.h",
"upb/msg.h", "upb/msg.h",
"upb/status.h", "upb/status.h",
@ -140,12 +140,12 @@ cc_library(
copts = UPB_DEFAULT_COPTS, copts = UPB_DEFAULT_COPTS,
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
":arena_internal",
":array_internal", ":array_internal",
":decode_internal", ":decode_internal",
":encode_internal", ":encode_internal",
":extension_registry", ":extension_registry",
":fastdecode", ":fastdecode",
":mem",
":port", ":port",
":table_internal", ":table_internal",
":unicode_internal", ":unicode_internal",
@ -287,10 +287,10 @@ cc_library(
], ],
copts = UPB_DEFAULT_COPTS, copts = UPB_DEFAULT_COPTS,
deps = [ deps = [
":arena_internal",
":array_internal", ":array_internal",
":decode_internal", ":decode_internal",
":extension_registry", ":extension_registry",
":mem_internal",
":port", ":port",
":table_internal", ":table_internal",
], ],
@ -944,8 +944,6 @@ cc_library(
cc_library( cc_library(
name = "array_internal", name = "array_internal",
srcs = [ srcs = [
"upb/alloc.h",
"upb/arena.h",
"upb/array.h", "upb/array.h",
"upb/internal/array.c", "upb/internal/array.c",
"upb/message_value.h", "upb/message_value.h",
@ -958,24 +956,38 @@ cc_library(
copts = UPB_DEFAULT_COPTS, copts = UPB_DEFAULT_COPTS,
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
":mem",
":port", ":port",
], ],
) )
cc_library( cc_library(
name = "arena_internal", name = "mem",
srcs = [ srcs = [
"upb/alloc.h", "upb/mem/alloc.c",
"upb/arena.h", "upb/mem/arena.c",
"upb/mem/arena_internal.h",
],
hdrs = [
"upb/mem/alloc.h",
"upb/mem/arena.h",
], ],
hdrs = ["upb/internal/arena.h"],
aspect_hints = [":suppress_kotlin_interop"],
compatible_with = ["//buildenv/target:non_prod"],
copts = UPB_DEFAULT_COPTS, copts = UPB_DEFAULT_COPTS,
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [":port"], deps = [":port"],
) )
cc_library(
name = "mem_internal",
hdrs = ["upb/mem/arena_internal.h"],
copts = UPB_DEFAULT_COPTS,
visibility = ["//:__subpackages__"],
deps = [
":mem",
":port",
],
)
cc_library( cc_library(
name = "atoi_internal", name = "atoi_internal",
srcs = ["upb/internal/atoi.c"], srcs = ["upb/internal/atoi.c"],
@ -999,7 +1011,7 @@ cc_library(
copts = UPB_DEFAULT_COPTS, copts = UPB_DEFAULT_COPTS,
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
":arena_internal", ":mem_internal",
":port", ":port",
":table_internal", ":table_internal",
"//third_party/utf8_range", "//third_party/utf8_range",
@ -1022,9 +1034,9 @@ cc_library(
"upb/internal/table.c", "upb/internal/table.c",
], ],
hdrs = [ hdrs = [
"upb/alloc.h",
"upb/arena.h",
"upb/internal/table.h", "upb/internal/table.h",
"upb/mem/alloc.h",
"upb/mem/arena.h",
"upb/status.h", "upb/status.h",
"upb/string_view.h", "upb/string_view.h",
"upb/upb.h", "upb/upb.h",
@ -1058,7 +1070,6 @@ upb_amalgamation(
"upb.h", "upb.h",
], ],
libs = [ libs = [
":arena_internal",
":array_internal", ":array_internal",
":atoi_internal", ":atoi_internal",
":collections", ":collections",
@ -1067,6 +1078,8 @@ upb_amalgamation(
":encode_internal", ":encode_internal",
":extension_registry", ":extension_registry",
":fastdecode", ":fastdecode",
":mem",
":mem_internal",
":mini_table", ":mini_table",
":port", ":port",
":reflection", ":reflection",
@ -1091,7 +1104,6 @@ upb_amalgamation(
"php-upb.h", "php-upb.h",
], ],
libs = [ libs = [
":arena_internal",
":array_internal", ":array_internal",
":atoi_internal", ":atoi_internal",
":collections", ":collections",
@ -1102,6 +1114,8 @@ upb_amalgamation(
":extension_registry", ":extension_registry",
":fastdecode", ":fastdecode",
":json", ":json",
":mem",
":mem_internal",
":mini_table", ":mini_table",
":port", ":port",
":reflection", ":reflection",
@ -1130,7 +1144,6 @@ upb_amalgamation(
"ruby-upb.h", "ruby-upb.h",
], ],
libs = [ libs = [
":arena_internal",
":array_internal", ":array_internal",
":atoi_internal", ":atoi_internal",
":collections", ":collections",
@ -1140,6 +1153,8 @@ upb_amalgamation(
":extension_registry", ":extension_registry",
":fastdecode", ":fastdecode",
":json", ":json",
":mem",
":mem_internal",
":mini_table", ":mini_table",
":port", ":port",
":reflection", ":reflection",

@ -25,74 +25,11 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
// This header is deprecated, use upb/mem/alloc.h instead
#ifndef UPB_ALLOC_H_ #ifndef UPB_ALLOC_H_
#define UPB_ALLOC_H_ #define UPB_ALLOC_H_
// Must be last. #include "upb/mem/alloc.h"
#include "upb/port_def.inc"
#ifdef __cplusplus
extern "C" {
#endif
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); }
#ifdef __cplusplus
} /* extern "C" */
#endif
#include "upb/port_undef.inc"
#endif /* UPB_ALLOC_H_ */ #endif /* UPB_ALLOC_H_ */

@ -25,144 +25,11 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
// This header is deprecated, use upb/mem/arena.h instead
#ifndef UPB_ARENA_H_ #ifndef UPB_ARENA_H_
#define UPB_ARENA_H_ #define UPB_ARENA_H_
#include <string.h> #include "upb/mem/arena.h"
#include "upb/alloc.h"
// Must be last.
#include "upb/port_def.inc"
#ifdef __cplusplus
extern "C" {
#endif
/* 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
* to be freed. However the Arena does allow users to register cleanup
* functions that will run when the arena is destroyed.
*
* A upb_Arena is *not* thread-safe.
*
* You could write a thread-safe arena allocator that satisfies the
* upb_alloc interface, but it would not be as efficient for the
* single-threaded case. */
typedef void upb_CleanupFunc(void* ud);
typedef struct upb_Arena upb_Arena;
typedef struct {
/* We implement the allocator interface.
* This must be the first member of upb_Arena!
* TODO(haberman): remove once handlers are gone. */
upb_alloc alloc;
char *ptr, *end;
} _upb_ArenaHead;
/* Creates an arena from the given initial block (if any -- n may be 0).
* Additional blocks will be allocated from |alloc|. If |alloc| is NULL, this
* is a fixed-size arena and cannot grow. */
upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc);
void upb_Arena_Free(upb_Arena* a);
bool upb_Arena_AddCleanup(upb_Arena* a, void* ud, upb_CleanupFunc* func);
bool upb_Arena_Fuse(upb_Arena* a, upb_Arena* b);
void* _upb_Arena_SlowMalloc(upb_Arena* a, size_t size);
size_t upb_Arena_SpaceAllocated(upb_Arena* arena);
uint32_t upb_Arena_DebugRefCount(upb_Arena* arena);
UPB_INLINE upb_alloc* upb_Arena_Alloc(upb_Arena* a) { return (upb_alloc*)a; }
UPB_INLINE size_t _upb_ArenaHas(upb_Arena* a) {
_upb_ArenaHead* h = (_upb_ArenaHead*)a;
return (size_t)(h->end - h->ptr);
}
UPB_INLINE void* _upb_Arena_FastMalloc(upb_Arena* a, size_t size) {
_upb_ArenaHead* h = (_upb_ArenaHead*)a;
void* ret = h->ptr;
UPB_ASSERT(UPB_ALIGN_MALLOC((uintptr_t)ret) == (uintptr_t)ret);
UPB_ASSERT(UPB_ALIGN_MALLOC(size) == size);
UPB_UNPOISON_MEMORY_REGION(ret, size);
h->ptr += size;
#if UPB_ASAN
{
size_t guard_size = 32;
if (_upb_ArenaHas(a) >= guard_size) {
h->ptr += guard_size;
} else {
h->ptr = h->end;
}
}
#endif
return ret;
}
UPB_INLINE void* upb_Arena_Malloc(upb_Arena* a, size_t size) {
size = UPB_ALIGN_MALLOC(size);
if (UPB_UNLIKELY(_upb_ArenaHas(a) < size)) {
return _upb_Arena_SlowMalloc(a, size);
}
return _upb_Arena_FastMalloc(a, size);
}
// Shrinks the last alloc from arena.
// REQUIRES: (ptr, oldsize) was the last malloc/realloc from this arena.
// We could also add a upb_Arena_TryShrinkLast() which is simply a no-op if
// this was not the last alloc.
UPB_INLINE void upb_Arena_ShrinkLast(upb_Arena* a, void* ptr, size_t oldsize,
size_t size) {
_upb_ArenaHead* h = (_upb_ArenaHead*)a;
oldsize = UPB_ALIGN_MALLOC(oldsize);
size = UPB_ALIGN_MALLOC(size);
UPB_ASSERT((char*)ptr + oldsize == h->ptr); // Must be the last alloc.
UPB_ASSERT(size <= oldsize);
h->ptr = (char*)ptr + size;
}
UPB_INLINE void* upb_Arena_Realloc(upb_Arena* a, void* ptr, size_t oldsize,
size_t size) {
_upb_ArenaHead* h = (_upb_ArenaHead*)a;
oldsize = UPB_ALIGN_MALLOC(oldsize);
size = UPB_ALIGN_MALLOC(size);
bool is_most_recent_alloc = (uintptr_t)ptr + oldsize == (uintptr_t)h->ptr;
if (is_most_recent_alloc) {
ptrdiff_t diff = size - oldsize;
if ((ptrdiff_t)_upb_ArenaHas(a) >= diff) {
h->ptr += diff;
return ptr;
}
} else if (size <= oldsize) {
return ptr;
}
void* ret = upb_Arena_Malloc(a, size);
if (ret && oldsize > 0) {
memcpy(ret, ptr, UPB_MIN(oldsize, size));
}
return ret;
}
UPB_INLINE upb_Arena* upb_Arena_New(void) {
return upb_Arena_Init(NULL, 0, &upb_alloc_global);
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#include "upb/port_undef.inc"
#endif /* UPB_ARENA_H_ */ #endif /* UPB_ARENA_H_ */

@ -32,8 +32,8 @@
#ifndef UPB_DECODE_H_ #ifndef UPB_DECODE_H_
#define UPB_DECODE_H_ #define UPB_DECODE_H_
#include "upb/arena.h"
#include "upb/extension_registry.h" #include "upb/extension_registry.h"
#include "upb/mem/arena.h"
#include "upb/msg.h" #include "upb/msg.h"
// Must be last. // Must be last.

@ -34,7 +34,7 @@
#define UPB_INTERNAL_DECODE_H_ #define UPB_INTERNAL_DECODE_H_
#include "upb/decode.h" #include "upb/decode.h"
#include "upb/internal/arena.h" #include "upb/mem/arena_internal.h"
#include "upb/msg_internal.h" #include "upb/msg_internal.h"
#include "third_party/utf8_range/utf8_range.h" #include "third_party/utf8_range/utf8_range.h"

@ -28,8 +28,8 @@
#ifndef UPB_IO_CHUNKED_INPUT_STREAM_H_ #ifndef UPB_IO_CHUNKED_INPUT_STREAM_H_
#define UPB_IO_CHUNKED_INPUT_STREAM_H_ #define UPB_IO_CHUNKED_INPUT_STREAM_H_
#include "upb/arena.h"
#include "upb/io/zero_copy_input_stream.h" #include "upb/io/zero_copy_input_stream.h"
#include "upb/mem/arena.h"
// Must be last. // Must be last.
#include "upb/port_def.inc" #include "upb/port_def.inc"

@ -28,8 +28,8 @@
#ifndef UPB_IO_CHUNKED_OUTPUT_STREAM_H_ #ifndef UPB_IO_CHUNKED_OUTPUT_STREAM_H_
#define UPB_IO_CHUNKED_OUTPUT_STREAM_H_ #define UPB_IO_CHUNKED_OUTPUT_STREAM_H_
#include "upb/arena.h"
#include "upb/io/zero_copy_output_stream.h" #include "upb/io/zero_copy_output_stream.h"
#include "upb/mem/arena.h"
// Must be last. // Must be last.
#include "upb/port_def.inc" #include "upb/port_def.inc"

@ -36,7 +36,7 @@
#include <string.h> #include <string.h>
#include "upb/arena.h" #include "upb/mem/arena.h"
// Must be last. // Must be last.
#include "upb/port_def.inc" #include "upb/port_def.inc"

@ -25,7 +25,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "upb/alloc.h" #include "upb/mem/alloc.h"
#include <stdlib.h> #include <stdlib.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_MEM_ALLOC_H_
#define UPB_MEM_ALLOC_H_
// Must be last.
#include "upb/port_def.inc"
#ifdef __cplusplus
extern "C" {
#endif
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); }
#ifdef __cplusplus
} /* extern "C" */
#endif
#include "upb/port_undef.inc"
#endif /* UPB_MEM_ALLOC_H_ */

@ -25,7 +25,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "upb/internal/arena.h" #include "upb/mem/arena_internal.h"
// Must be last. // Must be last.
#include "upb/port_def.inc" #include "upb/port_def.inc"

@ -0,0 +1,168 @@
/*
* 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_MEM_ARENA_H_
#define UPB_MEM_ARENA_H_
#include <string.h>
#include "upb/mem/alloc.h"
// Must be last.
#include "upb/port_def.inc"
#ifdef __cplusplus
extern "C" {
#endif
/* 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
* to be freed. However the Arena does allow users to register cleanup
* functions that will run when the arena is destroyed.
*
* A upb_Arena is *not* thread-safe.
*
* You could write a thread-safe arena allocator that satisfies the
* upb_alloc interface, but it would not be as efficient for the
* single-threaded case. */
typedef void upb_CleanupFunc(void* ud);
typedef struct upb_Arena upb_Arena;
typedef struct {
/* We implement the allocator interface.
* This must be the first member of upb_Arena!
* TODO(haberman): remove once handlers are gone. */
upb_alloc alloc;
char *ptr, *end;
} _upb_ArenaHead;
/* Creates an arena from the given initial block (if any -- n may be 0).
* Additional blocks will be allocated from |alloc|. If |alloc| is NULL, this
* is a fixed-size arena and cannot grow. */
upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc);
void upb_Arena_Free(upb_Arena* a);
bool upb_Arena_AddCleanup(upb_Arena* a, void* ud, upb_CleanupFunc* func);
bool upb_Arena_Fuse(upb_Arena* a, upb_Arena* b);
void* _upb_Arena_SlowMalloc(upb_Arena* a, size_t size);
size_t upb_Arena_SpaceAllocated(upb_Arena* arena);
uint32_t upb_Arena_DebugRefCount(upb_Arena* arena);
UPB_INLINE upb_alloc* upb_Arena_Alloc(upb_Arena* a) { return (upb_alloc*)a; }
UPB_INLINE size_t _upb_ArenaHas(upb_Arena* a) {
_upb_ArenaHead* h = (_upb_ArenaHead*)a;
return (size_t)(h->end - h->ptr);
}
UPB_INLINE void* _upb_Arena_FastMalloc(upb_Arena* a, size_t size) {
_upb_ArenaHead* h = (_upb_ArenaHead*)a;
void* ret = h->ptr;
UPB_ASSERT(UPB_ALIGN_MALLOC((uintptr_t)ret) == (uintptr_t)ret);
UPB_ASSERT(UPB_ALIGN_MALLOC(size) == size);
UPB_UNPOISON_MEMORY_REGION(ret, size);
h->ptr += size;
#if UPB_ASAN
{
size_t guard_size = 32;
if (_upb_ArenaHas(a) >= guard_size) {
h->ptr += guard_size;
} else {
h->ptr = h->end;
}
}
#endif
return ret;
}
UPB_INLINE void* upb_Arena_Malloc(upb_Arena* a, size_t size) {
size = UPB_ALIGN_MALLOC(size);
if (UPB_UNLIKELY(_upb_ArenaHas(a) < size)) {
return _upb_Arena_SlowMalloc(a, size);
}
return _upb_Arena_FastMalloc(a, size);
}
// Shrinks the last alloc from arena.
// REQUIRES: (ptr, oldsize) was the last malloc/realloc from this arena.
// We could also add a upb_Arena_TryShrinkLast() which is simply a no-op if
// this was not the last alloc.
UPB_INLINE void upb_Arena_ShrinkLast(upb_Arena* a, void* ptr, size_t oldsize,
size_t size) {
_upb_ArenaHead* h = (_upb_ArenaHead*)a;
oldsize = UPB_ALIGN_MALLOC(oldsize);
size = UPB_ALIGN_MALLOC(size);
UPB_ASSERT((char*)ptr + oldsize == h->ptr); // Must be the last alloc.
UPB_ASSERT(size <= oldsize);
h->ptr = (char*)ptr + size;
}
UPB_INLINE void* upb_Arena_Realloc(upb_Arena* a, void* ptr, size_t oldsize,
size_t size) {
_upb_ArenaHead* h = (_upb_ArenaHead*)a;
oldsize = UPB_ALIGN_MALLOC(oldsize);
size = UPB_ALIGN_MALLOC(size);
bool is_most_recent_alloc = (uintptr_t)ptr + oldsize == (uintptr_t)h->ptr;
if (is_most_recent_alloc) {
ptrdiff_t diff = size - oldsize;
if ((ptrdiff_t)_upb_ArenaHas(a) >= diff) {
h->ptr += diff;
return ptr;
}
} else if (size <= oldsize) {
return ptr;
}
void* ret = upb_Arena_Malloc(a, size);
if (ret && oldsize > 0) {
memcpy(ret, ptr, UPB_MIN(oldsize, size));
}
return ret;
}
UPB_INLINE upb_Arena* upb_Arena_New(void) {
return upb_Arena_Init(NULL, 0, &upb_alloc_global);
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#include "upb/port_undef.inc"
#endif /* UPB_MEM_ARENA_H_ */

@ -25,10 +25,10 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef UPB_INTERNAL_ARENA_H_ #ifndef UPB_MEM_ARENA_INTERNAL_H_
#define UPB_INTERNAL_ARENA_H_ #define UPB_MEM_ARENA_INTERNAL_H_
#include "upb/arena.h" #include "upb/mem/arena.h"
// Must be last. // Must be last.
#include "upb/port_def.inc" #include "upb/port_def.inc"
@ -67,5 +67,4 @@ struct upb_Arena {
#include "upb/port_undef.inc" #include "upb/port_undef.inc"
#endif /* UPB_INTERNAL_ARENA_H_ */ #endif /* UPB_MEM_ARENA_INTERNAL_H_ */

@ -29,7 +29,7 @@
#include <inttypes.h> #include <inttypes.h>
#include "upb/arena.h" #include "upb/mem/arena.h"
#include "upb/mini_table/common_internal.h" #include "upb/mini_table/common_internal.h"
#include "upb/upb.h" #include "upb/upb.h"

@ -29,7 +29,7 @@
#include <inttypes.h> #include <inttypes.h>
#include "upb/arena.h" #include "upb/mem/arena.h"
#include "upb/mini_table/common.h" #include "upb/mini_table/common.h"
#include "upb/mini_table/common_internal.h" #include "upb/mini_table/common_internal.h"
#include "upb/upb.h" #include "upb/upb.h"

@ -29,7 +29,7 @@
#include <inttypes.h> #include <inttypes.h>
#include "upb/arena.h" #include "upb/mem/arena.h"
#include "upb/mini_table/common.h" #include "upb/mini_table/common.h"
#include "upb/mini_table/common_internal.h" #include "upb/mini_table/common_internal.h"
#include "upb/upb.h" #include "upb/upb.h"

@ -36,7 +36,7 @@
#ifndef UPB_MSG_H_ #ifndef UPB_MSG_H_
#define UPB_MSG_H_ #define UPB_MSG_H_
#include "upb/arena.h" #include "upb/mem/arena.h"
// Must be last. // Must be last.
#include "upb/port_def.inc" #include "upb/port_def.inc"

@ -40,7 +40,7 @@
#include <string.h> #include <string.h>
// TODO(b/232091617): Remove these and fix everything that breaks as a result. // TODO(b/232091617): Remove these and fix everything that breaks as a result.
#include "upb/arena.h" #include "upb/mem/arena.h"
#include "upb/status.h" #include "upb/status.h"
#include "upb/string_view.h" #include "upb/string_view.h"

Loading…
Cancel
Save