WPILibC++ 2027.0.0-alpha-3
Loading...
Searching...
No Matches
arena.h
Go to the documentation of this file.
1// Protocol Buffers - Google's data interchange format
2// Copyright 2023 Google LLC. All rights reserved.
3//
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file or at
6// https://developers.google.com/open-source/licenses/bsd
7
8#ifndef UPB_MEM_INTERNAL_ARENA_H_
9#define UPB_MEM_INTERNAL_ARENA_H_
10
11#include <stddef.h>
12#include <stdint.h>
13#include <string.h>
14
15#include "upb/port/sanitizers.h"
16
17// Must be last.
18#include "upb/port/def.inc"
19
20// This is QUITE an ugly hack, which specifies the number of pointers needed
21// to equal (or exceed) the storage required for one upb_Arena.
22//
23// We need this because the decoder inlines a upb_Arena for performance but
24// the full struct is not visible outside of arena.c. Yes, I know, it's awful.
25#define UPB_ARENA_SIZE_HACK (10 + (UPB_XSAN_STRUCT_SIZE * 2))
26
27// LINT.IfChange(upb_Arena)
28
29struct upb_Arena {
31 const UPB_NODEREF char* UPB_ONLYBITS(end);
33};
34
35// LINT.ThenChange(//depot/google3/third_party/upb/bits/typescript/arena.ts:upb_Arena)
36
37#ifdef __cplusplus
38extern "C" {
39#endif
40
42 const struct upb_Arena* src);
44 const struct upb_Arena* src);
45
47 return (size_t)(a->UPB_ONLYBITS(end) - a->UPB_ONLYBITS(ptr));
48}
49
51 return UPB_ALIGN_MALLOC(size) + UPB_PRIVATE(kUpb_Asan_GuardSize);
52}
53
55 const struct upb_Arena* a, void* ptr, size_t size) {
57 (char*)ptr + UPB_PRIVATE(_upb_Arena_AllocSpan)(size),
58 a->UPB_ONLYBITS(ptr));
59}
60
62 return (uintptr_t)ptr % UPB_MALLOC_ALIGN == 0;
63}
64
65UPB_API_INLINE void* upb_Arena_Malloc(struct upb_Arena* a, size_t size) {
67
68 size_t span = UPB_PRIVATE(_upb_Arena_AllocSpan)(size);
69
70 if (UPB_UNLIKELY(UPB_PRIVATE(_upb_ArenaHas)(a) < span)) {
71 void* UPB_PRIVATE(_upb_Arena_SlowMalloc)(struct upb_Arena * a, size_t size);
72 return UPB_PRIVATE(_upb_Arena_SlowMalloc)(a, span);
73 }
74
75 // We have enough space to do a fast malloc.
76 void* ret = a->UPB_ONLYBITS(ptr);
77 a->UPB_ONLYBITS(ptr) += span;
80
82}
83
85 size_t oldsize, size_t size) {
87 UPB_ASSERT(size <= oldsize);
88
91
93 // We can reclaim some memory.
94 a->UPB_ONLYBITS(ptr) -= UPB_ALIGN_MALLOC(oldsize) - UPB_ALIGN_MALLOC(size);
95 } else {
96 // We can't reclaim any memory, but we need to verify that `ptr` really
97 // does represent the most recent allocation.
98#ifndef NDEBUG
99 bool _upb_Arena_WasLastAlloc(struct upb_Arena * a, void* ptr,
100 size_t oldsize);
101 UPB_ASSERT(_upb_Arena_WasLastAlloc(a, ptr, oldsize));
102#endif
103 }
104}
105
107 size_t oldsize, size_t size) {
109 UPB_ASSERT(size > oldsize);
110
112 size_t extend = UPB_ALIGN_MALLOC(size) - UPB_ALIGN_MALLOC(oldsize);
113
115 UPB_PRIVATE(_upb_ArenaHas)(a) >= extend) {
116 a->UPB_ONLYBITS(ptr) += extend;
118 return true;
119 }
120
121 return false;
122}
123
125 size_t oldsize, size_t size) {
127
128 void* ret;
129
130 if (ptr && (size <= oldsize || upb_Arena_TryExtend(a, ptr, oldsize, size))) {
131 // We can extend or shrink in place.
132 if (size <= oldsize &&
134 upb_Arena_ShrinkLast(a, ptr, oldsize, size);
135 }
136 ret = ptr;
137 } else {
138 // We need to copy into a new allocation.
139 ret = upb_Arena_Malloc(a, size);
140 if (ret && oldsize > 0) {
141 memcpy(ret, ptr, UPB_MIN(oldsize, size));
142 }
143 }
144
145 // We want to invalidate pointers to the old region if hwasan is enabled, so
146 // we poison and unpoison even if ptr == ret.
149}
150
151#ifdef __cplusplus
152} /* extern "C" */
153#endif
154
155#include "upb/port/undef.inc"
156
157#endif /* UPB_MEM_INTERNAL_ARENA_H_ */
UPB_API_INLINE void upb_Arena_ShrinkLast(upb_Arena *a, void *ptr, size_t oldsize, size_t size)
Definition arena.h:84
UPB_API_INLINE void * upb_Arena_Realloc(upb_Arena *a, void *ptr, size_t oldsize, size_t size)
Definition arena.h:124
UPB_API_INLINE bool upb_Arena_TryExtend(upb_Arena *a, void *ptr, size_t oldsize, size_t size)
Definition arena.h:106
UPB_API_INLINE void * upb_Arena_Malloc(struct upb_Arena *a, size_t size)
Definition arena.h:65
#define UPB_UNLIKELY(x)
Definition def.inc:265
#define UPB_API_INLINE
Definition def.inc:163
#define UPB_XSAN_MEMBER
Definition def.inc:200
#define UPB_ASSERT(expr)
Definition def.inc:329
#define UPB_PRIVATE(x)
Definition def.inc:393
#define UPB_ALIGN_MALLOC(size)
Definition def.inc:207
#define UPB_MALLOC_ALIGN
Definition def.inc:184
#define UPB_NODEREF
Definition def.inc:297
#define UPB_INLINE
Definition def.inc:144
#define UPB_XSAN(st)
Definition def.inc:201
#define UPB_MIN(x, y)
Definition def.inc:301
auto ptr(T p) -> const void *
Converts p to const void* for pointer formatting.
Definition format.h:3963
void UPB_PRIVATE _upb_Arena_SwapOut(struct upb_Arena *des, const struct upb_Arena *src)
UPB_INLINE size_t UPB_PRIVATE _upb_ArenaHas(const struct upb_Arena *a)
Definition arena.h:46
UPB_INLINE size_t UPB_PRIVATE _upb_Arena_AllocSpan(size_t size)
Definition arena.h:50
UPB_INLINE bool UPB_PRIVATE _upb_Arena_WasLastAllocFromCurrentBlock(const struct upb_Arena *a, void *ptr, size_t size)
Definition arena.h:54
void UPB_PRIVATE _upb_Arena_SwapIn(struct upb_Arena *des, const struct upb_Arena *src)
UPB_INLINE bool UPB_PRIVATE _upb_Arena_IsAligned(const void *ptr)
Definition arena.h:61
UPB_INLINE void UPB_PRIVATE upb_Xsan_PoisonRegion(const void *addr, size_t size)
Definition sanitizers.h:68
UPB_INLINE bool UPB_PRIVATE upb_Xsan_PtrEq(const void *a, const void *b)
Definition sanitizers.h:135
UPB_INLINE void *UPB_PRIVATE upb_Xsan_NewUnpoisonedRegion(upb_Xsan *xsan, void *addr, size_t size)
Definition sanitizers.h:112
UPB_INLINE void *UPB_PRIVATE upb_Xsan_ResizeUnpoisonedRegion(void *tagged_addr, size_t old_size, size_t new_size)
Definition sanitizers.h:125
UPB_INLINE void UPB_PRIVATE upb_Xsan_AccessReadWrite(upb_Xsan *xsan)
Definition sanitizers.h:155
Definition arena.h:29
char * UPB_ONLYBITS(ptr)
const UPB_NODEREF char * UPB_ONLYBITS(end)