File indexing completed on 2026-09-18 09:32:11
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef UPB_MEM_INTERNAL_ARENA_H_
0009 #define UPB_MEM_INTERNAL_ARENA_H_
0010
0011 #include <stddef.h>
0012 #include <stdint.h>
0013 #include <string.h>
0014
0015 #include "upb/port/sanitizers.h"
0016
0017
0018 #include "upb/port/def.inc"
0019
0020
0021
0022
0023
0024
0025 #define UPB_ARENA_SIZE_HACK (10 + (UPB_XSAN_STRUCT_SIZE * 2))
0026
0027
0028
0029 struct upb_Arena {
0030 char* UPB_ONLYBITS(ptr);
0031 const UPB_NODEREF char* UPB_ONLYBITS(end);
0032 UPB_XSAN_MEMBER
0033 };
0034
0035
0036
0037 #ifdef __cplusplus
0038 extern "C" {
0039 #endif
0040
0041 void UPB_PRIVATE(_upb_Arena_SwapIn)(struct upb_Arena* des,
0042 const struct upb_Arena* src);
0043 void UPB_PRIVATE(_upb_Arena_SwapOut)(struct upb_Arena* des,
0044 const struct upb_Arena* src);
0045
0046 UPB_INLINE size_t UPB_PRIVATE(_upb_ArenaHas)(const struct upb_Arena* a) {
0047 return (size_t)(a->UPB_ONLYBITS(end) - a->UPB_ONLYBITS(ptr));
0048 }
0049
0050 UPB_INLINE size_t UPB_PRIVATE(_upb_Arena_AllocSpan)(size_t size) {
0051 return UPB_ALIGN_MALLOC(size) + UPB_PRIVATE(kUpb_Asan_GuardSize);
0052 }
0053
0054 UPB_INLINE bool UPB_PRIVATE(_upb_Arena_WasLastAllocFromCurrentBlock)(
0055 const struct upb_Arena* a, void* ptr, size_t size) {
0056 return UPB_PRIVATE(upb_Xsan_PtrEq)(
0057 (char*)ptr + UPB_PRIVATE(_upb_Arena_AllocSpan)(size),
0058 a->UPB_ONLYBITS(ptr));
0059 }
0060
0061 UPB_INLINE bool UPB_PRIVATE(_upb_Arena_IsAligned)(const void* ptr) {
0062 return (uintptr_t)ptr % UPB_MALLOC_ALIGN == 0;
0063 }
0064
0065 UPB_API_INLINE void* upb_Arena_Malloc(struct upb_Arena* a, size_t size) {
0066 UPB_PRIVATE(upb_Xsan_AccessReadWrite)(UPB_XSAN(a));
0067
0068 size_t span = UPB_PRIVATE(_upb_Arena_AllocSpan)(size);
0069
0070 if (UPB_UNLIKELY(UPB_PRIVATE(_upb_ArenaHas)(a) < span)) {
0071 void* UPB_PRIVATE(_upb_Arena_SlowMalloc)(struct upb_Arena * a, size_t size);
0072 return UPB_PRIVATE(_upb_Arena_SlowMalloc)(a, span);
0073 }
0074
0075
0076 void* ret = a->UPB_ONLYBITS(ptr);
0077 a->UPB_ONLYBITS(ptr) += span;
0078 UPB_ASSERT(UPB_PRIVATE(_upb_Arena_IsAligned)(ret));
0079 UPB_ASSERT(UPB_PRIVATE(_upb_Arena_IsAligned)(a->UPB_ONLYBITS(ptr)));
0080
0081 return UPB_PRIVATE(upb_Xsan_NewUnpoisonedRegion)(UPB_XSAN(a), ret, size);
0082 }
0083
0084 UPB_API_INLINE void upb_Arena_ShrinkLast(struct upb_Arena* a, void* ptr,
0085 size_t oldsize, size_t size) {
0086 UPB_ASSERT(ptr);
0087 UPB_ASSERT(size <= oldsize);
0088
0089 UPB_PRIVATE(upb_Xsan_AccessReadWrite)(UPB_XSAN(a));
0090 UPB_PRIVATE(upb_Xsan_ResizeUnpoisonedRegion)(ptr, oldsize, size);
0091
0092 if (UPB_PRIVATE(_upb_Arena_WasLastAllocFromCurrentBlock)(a, ptr, oldsize)) {
0093
0094 a->UPB_ONLYBITS(ptr) -= UPB_ALIGN_MALLOC(oldsize) - UPB_ALIGN_MALLOC(size);
0095 } else {
0096
0097
0098 #ifndef NDEBUG
0099 bool _upb_Arena_WasLastAlloc(struct upb_Arena * a, void* ptr,
0100 size_t oldsize);
0101 UPB_ASSERT(_upb_Arena_WasLastAlloc(a, ptr, oldsize));
0102 #endif
0103 }
0104 }
0105
0106 UPB_API_INLINE bool upb_Arena_TryExtend(struct upb_Arena* a, void* ptr,
0107 size_t oldsize, size_t size) {
0108 UPB_ASSERT(ptr);
0109 UPB_ASSERT(size > oldsize);
0110
0111 UPB_PRIVATE(upb_Xsan_AccessReadWrite)(UPB_XSAN(a));
0112 size_t extend = UPB_ALIGN_MALLOC(size) - UPB_ALIGN_MALLOC(oldsize);
0113
0114 if (UPB_PRIVATE(_upb_Arena_WasLastAllocFromCurrentBlock)(a, ptr, oldsize) &&
0115 UPB_PRIVATE(_upb_ArenaHas)(a) >= extend) {
0116 a->UPB_ONLYBITS(ptr) += extend;
0117 UPB_PRIVATE(upb_Xsan_ResizeUnpoisonedRegion)(ptr, oldsize, size);
0118 return true;
0119 }
0120
0121 return false;
0122 }
0123
0124 UPB_API_INLINE void* upb_Arena_Realloc(struct upb_Arena* a, void* ptr,
0125 size_t oldsize, size_t size) {
0126 UPB_PRIVATE(upb_Xsan_AccessReadWrite)(UPB_XSAN(a));
0127
0128 void* ret;
0129
0130 if (ptr && (size <= oldsize || upb_Arena_TryExtend(a, ptr, oldsize, size))) {
0131
0132 if (size <= oldsize &&
0133 UPB_PRIVATE(_upb_Arena_WasLastAllocFromCurrentBlock)(a, ptr, oldsize)) {
0134 upb_Arena_ShrinkLast(a, ptr, oldsize, size);
0135 }
0136 ret = ptr;
0137 } else {
0138
0139 ret = upb_Arena_Malloc(a, size);
0140 if (ret && oldsize > 0) {
0141 memcpy(ret, ptr, UPB_MIN(oldsize, size));
0142 }
0143 }
0144
0145
0146
0147 UPB_PRIVATE(upb_Xsan_PoisonRegion)(ptr, oldsize);
0148 return UPB_PRIVATE(upb_Xsan_NewUnpoisonedRegion)(UPB_XSAN(a), ret, size);
0149 }
0150
0151 #ifdef __cplusplus
0152 }
0153 #endif
0154
0155 #include "upb/port/undef.inc"
0156
0157 #endif