webkit  2cdf99a9e3038c7e01b3c37e8ad903ecbe5eecf1
https://github.com/WebKit/webkit
arena.h
Go to the documentation of this file.
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 #ifndef GOOGLE_PROTOBUF_ARENA_H__
32 #define GOOGLE_PROTOBUF_ARENA_H__
33 
34 #include <limits>
35 #ifdef max
36 #undef max // Visual Studio defines this macro
37 #endif
38 #if __cplusplus >= 201103L
40 #endif
41 #if defined(_MSC_VER) && !_HAS_EXCEPTIONS
42 // Work around bugs in MSVC <typeinfo> header when _HAS_EXCEPTIONS=0.
43 #include <exception>
44 #include <typeinfo>
45 namespace std {
46 using type_info = ::type_info;
47 }
48 #else
49 #include <typeinfo>
50 #endif
51 
58 
59 
60 namespace google {
61 namespace protobuf {
62 
63 class Arena; // defined below
64 class Message; // message.h
65 
66 namespace internal {
67 class ArenaString; // arenastring.h
68 class LazyField; // lazy_field.h
69 
70 template<typename Type>
71 class GenericTypeHandler; // repeated_field.h
72 
73 // Templated cleanup methods.
74 template<typename T> void arena_destruct_object(void* object) {
75  reinterpret_cast<T*>(object)->~T();
76 }
77 template<typename T> void arena_delete_object(void* object) {
78  delete reinterpret_cast<T*>(object);
79 }
80 inline void arena_free(void* object, size_t /* size */) {
81  free(object);
82 }
83 
84 } // namespace internal
85 
86 // ArenaOptions provides optional additional parameters to arena construction
87 // that control its block-allocation behavior.
88 struct ArenaOptions {
89  // This defines the size of the first block requested from the system malloc.
90  // Subsequent block sizes will increase in a geometric series up to a maximum.
92 
93  // This defines the maximum block size requested from system malloc (unless an
94  // individual arena allocation request occurs with a size larger than this
95  // maximum). Requested block sizes increase up to this value, then remain
96  // here.
98 
99  // An initial block of memory for the arena to use, or NULL for none. If
100  // provided, the block must live at least as long as the arena itself. The
101  // creator of the Arena retains ownership of the block after the Arena is
102  // destroyed.
104 
105  // The size of the initial block, if provided.
107 
108  // A function pointer to an alloc method that returns memory blocks of size
109  // requested. By default, it contains a ptr to the malloc function.
110  //
111  // NOTE: block_alloc and dealloc functions are expected to behave like
112  // malloc and free, including Asan poisoning.
113  void* (*block_alloc)(size_t);
114  // A function pointer to a dealloc method that takes ownership of the blocks
115  // from the arena. By default, it contains a ptr to a wrapper function that
116  // calls free.
117  void (*block_dealloc)(void*, size_t);
118 
119  // Hooks for adding external functionality such as user-specific metrics
120  // collection, specific debugging abilities, etc.
121  // Init hook may return a pointer to a cookie to be stored in the arena.
122  // reset and destruction hooks will then be called with the same cookie
123  // pointer. This allows us to save an external object per arena instance and
124  // use it on the other hooks (Note: It is just as legal for init to return
125  // NULL and not use the cookie feature).
126  // on_arena_reset and on_arena_destruction also receive the space used in
127  // the arena just before the reset.
128  void* (*on_arena_init)(Arena* arena);
129  void (*on_arena_reset)(Arena* arena, void* cookie, uint64 space_used);
130  void (*on_arena_destruction)(Arena* arena, void* cookie, uint64 space_used);
131 
132  // type_info is promised to be static - its lifetime extends to
133  // match program's lifetime (It is given by typeid operator).
134  // Note: typeid(void) will be passed as allocated_type every time we
135  // intentionally want to avoid monitoring an allocation. (i.e. internal
136  // allocations for managing the arena)
137  void (*on_arena_allocation)(const std::type_info* allocated_type,
138  uint64 alloc_size, void* cookie);
139 
141  : start_block_size(kDefaultStartBlockSize),
142  max_block_size(kDefaultMaxBlockSize),
143  initial_block(NULL),
144  initial_block_size(0),
145  block_alloc(&malloc),
146  block_dealloc(&internal::arena_free),
147  on_arena_init(NULL),
148  on_arena_reset(NULL),
149  on_arena_destruction(NULL),
150  on_arena_allocation(NULL) {}
151 
152  private:
153  // Constants define default starting block size and max block size for
154  // arena allocator behavior -- see descriptions above.
155  static const size_t kDefaultStartBlockSize = 256;
156  static const size_t kDefaultMaxBlockSize = 8192;
157 };
158 
159 // Support for non-RTTI environments. (The metrics hooks API uses type
160 // information.)
161 #ifndef GOOGLE_PROTOBUF_NO_RTTI
162 #define RTTI_TYPE_ID(type) (&typeid(type))
163 #else
164 #define RTTI_TYPE_ID(type) (NULL)
165 #endif
166 
167 // Arena allocator. Arena allocation replaces ordinary (heap-based) allocation
168 // with new/delete, and improves performance by aggregating allocations into
169 // larger blocks and freeing allocations all at once. Protocol messages are
170 // allocated on an arena by using Arena::CreateMessage<T>(Arena*), below, and
171 // are automatically freed when the arena is destroyed.
172 //
173 // This is a thread-safe implementation: multiple threads may allocate from the
174 // arena concurrently. Destruction is not thread-safe and the destructing
175 // thread must synchronize with users of the arena first.
176 //
177 // An arena provides two allocation interfaces: CreateMessage<T>, which works
178 // for arena-enabled proto2 message types as well as other types that satisfy
179 // the appropriate protocol (described below), and Create<T>, which works for
180 // any arbitrary type T. CreateMessage<T> is better when the type T supports it,
181 // because this interface (i) passes the arena pointer to the created object so
182 // that its sub-objects and internal allocations can use the arena too, and (ii)
183 // elides the object's destructor call when possible. Create<T> does not place
184 // any special requirements on the type T, and will invoke the object's
185 // destructor when the arena is destroyed.
186 //
187 // The arena message allocation protocol, required by CreateMessage<T>, is as
188 // follows:
189 //
190 // - The type T must have (at least) two constructors: a constructor with no
191 // arguments, called when a T is allocated on the heap; and a constructor with
192 // a google::protobuf::Arena* argument, called when a T is allocated on an arena. If the
193 // second constructor is called with a NULL arena pointer, it must be
194 // equivalent to invoking the first (no-argument) constructor.
195 //
196 // - The type T must have a particular type trait: a nested type
197 // |InternalArenaConstructable_|. This is usually a typedef to |void|. If no
198 // such type trait exists, then the instantiation CreateMessage<T> will fail
199 // to compile.
200 //
201 // - The type T *may* have the type trait |DestructorSkippable_|. If this type
202 // trait is present in the type, then its destructor will not be called if and
203 // only if it was passed a non-NULL arena pointer. If this type trait is not
204 // present on the type, then its destructor is always called when the
205 // containing arena is destroyed.
206 //
207 // - One- and two-user-argument forms of CreateMessage<T>() also exist that
208 // forward these constructor arguments to T's constructor: for example,
209 // CreateMessage<T>(Arena*, arg1, arg2) forwards to a constructor T(Arena*,
210 // arg1, arg2).
211 //
212 // This protocol is implemented by all arena-enabled proto2 message classes as
213 // well as RepeatedPtrField.
214 
215 #if __cplusplus >= 201103L
216 class LIBPROTOBUF_EXPORT Arena final {
217 #else
219 #endif
220  public:
221  // Arena constructor taking custom options. See ArenaOptions below for
222  // descriptions of the options available.
223  explicit Arena(const ArenaOptions& options) : options_(options) {
224  Init();
225  }
226 
227  // Default constructor with sensible default options, tuned for average
228  // use-cases.
229  Arena() {
230  Init();
231  }
232 
233  // Destructor deletes all owned heap allocated objects, and destructs objects
234  // that have non-trivial destructors, except for proto2 message objects whose
235  // destructors can be skipped. Also, frees all blocks except the initial block
236  // if it was passed in.
237  ~Arena();
238 
239  // API to create proto2 message objects on the arena. If the arena passed in
240  // is NULL, then a heap allocated object is returned. Type T must be a message
241  // defined in a .proto file with cc_enable_arenas set to true, otherwise a
242  // compilation error will occur.
243  //
244  // RepeatedField and RepeatedPtrField may also be instantiated directly on an
245  // arena with this method.
246  //
247  // This function also accepts any type T that satisfies the arena message
248  // allocation protocol, documented above.
249  template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
251  if (arena == NULL) {
252  return new T;
253  } else {
254  return arena->CreateMessageInternal<T>(static_cast<T*>(0));
255  }
256  }
257 
258  // One-argument form of CreateMessage. This is useful for constructing objects
259  // that implement the arena message construction protocol described above but
260  // take additional constructor arguments.
261  template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
262  static T* CreateMessage(::google::protobuf::Arena* arena, const Arg& arg) {
263  if (arena == NULL) {
264  return new T(NULL, arg);
265  } else {
266  return arena->CreateMessageInternal<T>(static_cast<T*>(0),
267  arg);
268  }
269  }
270 
271  // Two-argument form of CreateMessage. This is useful for constructing objects
272  // that implement the arena message construction protocol described above but
273  // take additional constructor arguments.
274  template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
276  const Arg1& arg1,
277  const Arg2& arg2) {
278  if (arena == NULL) {
279  return new T(NULL, arg1, arg2);
280  } else {
281  return arena->CreateMessageInternal<T>(static_cast<T*>(0),
282  arg1, arg2);
283  }
284  }
285 
286  // API to create any objects on the arena. Note that only the object will
287  // be created on the arena; the underlying ptrs (in case of a proto2 message)
288  // will be still heap allocated. Proto messages should usually be allocated
289  // with CreateMessage<T>() instead.
290  //
291  // Note that even if T satisfies the arena message construction protocol
292  // (InternalArenaConstructable_ trait and optional DestructorSkippable_
293  // trait), as described above, this function does not follow the protocol;
294  // instead, it treats T as a black-box type, just as if it did not have these
295  // traits. Specifically, T's constructor arguments will always be only those
296  // passed to Create<T>() -- no additional arena pointer is implicitly added.
297  // Furthermore, the destructor will always be called at arena destruction time
298  // (unless the destructor is trivial). Hence, from T's point of view, it is as
299  // if the object were allocated on the heap (except that the underlying memory
300  // is obtained from the arena).
301  template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
302  static T* Create(::google::protobuf::Arena* arena) {
303  if (arena == NULL) {
304  return new T();
305  } else {
307  }
308  }
309 
310  // Version of the above with one constructor argument for the created object.
311  template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
312  static T* Create(::google::protobuf::Arena* arena, const Arg& arg) {
313  if (arena == NULL) {
314  return new T(arg);
315  } else {
317  arg);
318  }
319  }
320 
321  // Version of the above with two constructor arguments for the created object.
322  template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
323  static T* Create(::google::protobuf::Arena* arena, const Arg1& arg1, const Arg2& arg2) {
324  if (arena == NULL) {
325  return new T(arg1, arg2);
326  } else {
328  arg1, arg2);
329  }
330  }
331 
332  // Version of the above with three constructor arguments for the created
333  // object.
334  template <typename T, typename Arg1, typename Arg2, typename Arg3>
336  const Arg1& arg1, const Arg2& arg2,
337  const Arg3& arg3) {
338  if (arena == NULL) {
339  return new T(arg1, arg2, arg3);
340  } else {
342  arg1, arg2, arg3);
343  }
344  }
345 
346  // Version of the above with four constructor arguments for the created
347  // object.
348  template <typename T, typename Arg1, typename Arg2, typename Arg3,
349  typename Arg4>
351  const Arg1& arg1, const Arg2& arg2,
352  const Arg3& arg3, const Arg4& arg4) {
353  if (arena == NULL) {
354  return new T(arg1, arg2, arg3, arg4);
355  } else {
357  arg1, arg2, arg3, arg4);
358  }
359  }
360 
361  // Version of the above with five constructor arguments for the created
362  // object.
363  template <typename T, typename Arg1, typename Arg2, typename Arg3,
364  typename Arg4, typename Arg5>
366  const Arg1& arg1, const Arg2& arg2,
367  const Arg3& arg3, const Arg4& arg4,
368  const Arg5& arg5) {
369  if (arena == NULL) {
370  return new T(arg1, arg2, arg3, arg4, arg5);
371  } else {
373  arg1, arg2, arg3, arg4, arg5);
374  }
375  }
376 
377  // Version of the above with six constructor arguments for the created
378  // object.
379  template <typename T, typename Arg1, typename Arg2, typename Arg3,
380  typename Arg4, typename Arg5, typename Arg6>
382  const Arg1& arg1, const Arg2& arg2,
383  const Arg3& arg3, const Arg4& arg4,
384  const Arg5& arg5, const Arg6& arg6) {
385  if (arena == NULL) {
386  return new T(arg1, arg2, arg3, arg4, arg5, arg6);
387  } else {
389  arg1, arg2, arg3, arg4, arg5, arg6);
390  }
391  }
392 
393  // Version of the above with seven constructor arguments for the created
394  // object.
395  template <typename T, typename Arg1, typename Arg2, typename Arg3,
396  typename Arg4, typename Arg5, typename Arg6, typename Arg7>
398  const Arg1& arg1, const Arg2& arg2,
399  const Arg3& arg3, const Arg4& arg4,
400  const Arg5& arg5, const Arg6& arg6,
401  const Arg7& arg7) {
402  if (arena == NULL) {
403  return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
404  } else {
406  arg1, arg2, arg3, arg4, arg5, arg6, arg7);
407  }
408  }
409 
410  // Version of the above with eight constructor arguments for the created
411  // object.
412  template <typename T, typename Arg1, typename Arg2, typename Arg3,
413  typename Arg4, typename Arg5, typename Arg6, typename Arg7,
414  typename Arg8>
416  const Arg1& arg1, const Arg2& arg2,
417  const Arg3& arg3, const Arg4& arg4,
418  const Arg5& arg5, const Arg6& arg6,
419  const Arg7& arg7, const Arg8& arg8) {
420  if (arena == NULL) {
421  return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
422  } else {
423  return arena->CreateInternal<T>(
425  arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
426  }
427  }
428 
429  // Create an array of object type T on the arena *without* invoking the
430  // constructor of T. If `arena` is null, then the return value should be freed
431  // with `delete[] x;` (or `::operator delete[](x);`).
432  // To ensure safe uses, this function checks at compile time
433  // (when compiled as C++11) that T is trivially default-constructible and
434  // trivially destructible.
435  template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
436  static T* CreateArray(::google::protobuf::Arena* arena, size_t num_elements) {
437  GOOGLE_CHECK_LE(num_elements,
438  std::numeric_limits<size_t>::max() / sizeof(T))
439  << "Requested size is too large to fit into size_t.";
440  if (arena == NULL) {
441  return static_cast<T*>(::operator new[](num_elements * sizeof(T)));
442  } else {
443  return arena->CreateInternalRawArray<T>(num_elements);
444  }
445  }
446 
447  // Returns the total space used by the arena, which is the sums of the sizes
448  // of the underlying blocks. The total space used may not include the new
449  // blocks that are allocated by this arena from other threads concurrently
450  // with the call to this method.
451  GOOGLE_ATTRIBUTE_NOINLINE uint64 SpaceAllocated() const;
452  // As above, but does not include any free space in underlying blocks.
453  GOOGLE_ATTRIBUTE_NOINLINE uint64 SpaceUsed() const;
454 
455  // Combines SpaceAllocated and SpaceUsed. Returns a pair of
456  // <space_allocated, space_used>.
457  GOOGLE_ATTRIBUTE_NOINLINE pair<uint64, uint64> SpaceAllocatedAndUsed() const;
458 
459  // Frees all storage allocated by this arena after calling destructors
460  // registered with OwnDestructor() and freeing objects registered with Own().
461  // Any objects allocated on this arena are unusable after this call. It also
462  // returns the total space used by the arena which is the sums of the sizes
463  // of the allocated blocks. This method is not thread-safe.
465 
466  // Adds |object| to a list of heap-allocated objects to be freed with |delete|
467  // when the arena is destroyed or reset.
468  template <typename T> GOOGLE_ATTRIBUTE_NOINLINE
469  void Own(T* object) {
471  }
472 
473  // Adds |object| to a list of objects whose destructors will be manually
474  // called when the arena is destroyed or reset. This differs from Own() in
475  // that it does not free the underlying memory with |delete|; hence, it is
476  // normally only used for objects that are placement-newed into
477  // arena-allocated memory.
478  template <typename T> GOOGLE_ATTRIBUTE_NOINLINE
479  void OwnDestructor(T* object) {
480  if (object != NULL) {
481  AddListNode(object, &internal::arena_destruct_object<T>);
482  }
483  }
484 
485  // Adds a custom member function on an object to the list of destructors that
486  // will be manually called when the arena is destroyed or reset. This differs
487  // from OwnDestructor() in that any member function may be specified, not only
488  // the class destructor.
490  void (*destruct)(void*)) {
491  AddListNode(object, destruct);
492  }
493 
494  // Retrieves the arena associated with |value| if |value| is an arena-capable
495  // message, or NULL otherwise. This differs from value->GetArena() in that the
496  // latter is a virtual call, while this method is a templated call that
497  // resolves at compile-time.
498  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
499  static ::google::protobuf::Arena* GetArena(const T* value) {
500  return GetArenaInternal(value, static_cast<T*>(0));
501  }
502 
503  private:
504  struct InternalIsArenaConstructableHelper {
505  template<typename U>
506  static char ArenaConstructable(
507  const typename U::InternalArenaConstructable_*);
508  template<typename U>
509  static double ArenaConstructable(...);
510  };
511 
512  public:
513  // Helper typetrait that indicates support for arenas in a type T at compile
514  // time. This is public only to allow construction of higher-level templated
515  // utilities. is_arena_constructable<T>::value is true if the message type T
516  // has arena support enabled, and false otherwise.
517  //
518  // This is inside Arena because only Arena has the friend relationships
519  // necessary to see the underlying generated code traits.
520  template <typename T>
523  bool, sizeof(InternalIsArenaConstructableHelper::ArenaConstructable<
524  const T>(static_cast<const T*>(0))) == sizeof(char)> {
525  };
526 
527  private:
528  // Blocks are variable length malloc-ed objects. The following structure
529  // describes the common header for all blocks.
530  struct Block {
531  void* owner; // &ThreadCache of thread that owns this block, or
532  // &this->owner if not yet owned by a thread.
533  Block* next; // Next block in arena (may have different owner)
534  // ((char*) &block) + pos is next available byte. It is always
535  // aligned at a multiple of 8 bytes.
536  size_t pos;
537  size_t size; // total size of the block.
538  GOOGLE_ATTRIBUTE_ALWAYS_INLINE size_t avail() const { return size - pos; }
539  // data follows
540  };
541 
542  template<typename Type> friend class ::google::protobuf::internal::GenericTypeHandler;
543  friend class MockArena; // For unit-testing.
544  friend class internal::ArenaString; // For AllocateAligned.
545  friend class internal::LazyField; // For CreateMaybeMessage.
546 
547  struct ThreadCache {
548  // The ThreadCache is considered valid as long as this matches the
549  // lifecycle_id of the arena being used.
550  int64 last_lifecycle_id_seen;
551  Block* last_block_used_;
552  };
553 
554  static const size_t kHeaderSize = sizeof(Block);
555  static google::protobuf::internal::SequenceNumber lifecycle_id_generator_;
556 #if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
557  // Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread
558  // local storage class we implemented.
559  // iOS also does not support the GOOGLE_THREAD_LOCAL keyword.
560  static ThreadCache& thread_cache();
561 #elif defined(PROTOBUF_USE_DLLS)
562  // Thread local variables cannot be exposed through DLL interface but we can
563  // wrap them in static functions.
564  static ThreadCache& thread_cache();
565 #else
566  static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
567  static ThreadCache& thread_cache() { return thread_cache_; }
568 #endif
569 
570  // SFINAE for skipping addition to delete list for a message type when created
571  // with CreateMessage. This is mainly to skip proto2/proto1 message objects
572  // with cc_enable_arenas=true from being part of the delete list. Also, note,
573  // compiler will optimize out the branch in CreateInternal<T>.
574  template<typename T>
575  static inline bool SkipDeleteList(typename T::DestructorSkippable_*) {
576  return true;
577  }
578 
579  // For message objects that don't have the DestructorSkippable_ trait, we
580  // always add to the delete list.
581  template<typename T>
582  static inline bool SkipDeleteList(...) {
584  }
585 
586  private:
587  struct InternalIsDestructorSkippableHelper {
588  template<typename U>
589  static char DestructorSkippable(
590  const typename U::DestructorSkippable_*);
591  template<typename U>
592  static double DestructorSkippable(...);
593  };
594 
595  public:
596  // Helper typetrait that indicates whether the desctructor of type T should be
597  // called when arena is destroyed at compile time. This is only to allow
598  // construction of higher-level templated utilities.
599  // is_destructor_skippable<T>::value is true if the destructor of the message
600  // type T should not be called when arena is destroyed or false otherwise.
601  // This is inside Arena because only Arena has the friend relationships
602  // necessary to see the underlying generated code traits.
603  template<typename T>
606  bool,
607  sizeof(InternalIsDestructorSkippableHelper::DestructorSkippable<
608  const T>(static_cast<const T*>(0))) == sizeof(char) ||
609  google::protobuf::internal::has_trivial_destructor<T>::value> {};
610 
611  // CreateMessage<T> requires that T supports arenas, but this private method
612  // works whether or not T supports arenas. These are not exposed to user code
613  // as it can cause confusing API usages, and end up having double free in
614  // user code. These are used only internally from LazyField and Repeated
615  // fields, since they are designed to work in all mode combinations.
616  template<typename Msg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
617  static Msg* CreateMaybeMessage(
618  Arena* arena, typename Msg::InternalArenaConstructable_*) {
619  return CreateMessage<Msg>(arena);
620  }
621 
622  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
623  static T* CreateMaybeMessage(Arena* arena, ...) {
624  return Create<T>(arena);
625  }
626 
627  // Just allocate the required size for the given type assuming the
628  // type has a trivial constructor.
629  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
630  T* CreateInternalRawArray(size_t num_elements) {
631  GOOGLE_CHECK_LE(num_elements,
632  std::numeric_limits<size_t>::max() / sizeof(T))
633  << "Requested size is too large to fit into size_t.";
634  return static_cast<T*>(
635  AllocateAligned(RTTI_TYPE_ID(T), sizeof(T) * num_elements));
636  }
637 
638  template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
639  T* CreateInternal(bool skip_explicit_ownership) {
640  T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T();
641  if (!skip_explicit_ownership) {
642  AddListNode(t, &internal::arena_destruct_object<T>);
643  }
644  return t;
645  }
646 
647  template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
648  T* CreateInternal(bool skip_explicit_ownership, const Arg& arg) {
649  T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg);
650  if (!skip_explicit_ownership) {
651  AddListNode(t, &internal::arena_destruct_object<T>);
652  }
653  return t;
654  }
655 
656  template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
658  bool skip_explicit_ownership, const Arg1& arg1, const Arg2& arg2) {
659  T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg1, arg2);
660  if (!skip_explicit_ownership) {
661  AddListNode(t, &internal::arena_destruct_object<T>);
662  }
663  return t;
664  }
665 
666  template <typename T, typename Arg1, typename Arg2, typename Arg3>
667  GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
668  const Arg1& arg1,
669  const Arg2& arg2,
670  const Arg3& arg3) {
671  T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
672  T(arg1, arg2, arg3);
673  if (!skip_explicit_ownership) {
674  AddListNode(t, &internal::arena_destruct_object<T>);
675  }
676  return t;
677  }
678 
679  template <typename T, typename Arg1, typename Arg2, typename Arg3,
680  typename Arg4>
681  GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
682  const Arg1& arg1,
683  const Arg2& arg2,
684  const Arg3& arg3,
685  const Arg4& arg4) {
686  T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
687  T(arg1, arg2, arg3, arg4);
688  if (!skip_explicit_ownership) {
689  AddListNode(t, &internal::arena_destruct_object<T>);
690  }
691  return t;
692  }
693 
694  template <typename T, typename Arg1, typename Arg2, typename Arg3,
695  typename Arg4, typename Arg5>
696  GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
697  const Arg1& arg1,
698  const Arg2& arg2,
699  const Arg3& arg3,
700  const Arg4& arg4,
701  const Arg5& arg5) {
702  T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
703  T(arg1, arg2, arg3, arg4, arg5);
704  if (!skip_explicit_ownership) {
705  AddListNode(t, &internal::arena_destruct_object<T>);
706  }
707  return t;
708  }
709 
710  template <typename T, typename Arg1, typename Arg2, typename Arg3,
711  typename Arg4, typename Arg5, typename Arg6>
712  GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
713  const Arg1& arg1,
714  const Arg2& arg2,
715  const Arg3& arg3,
716  const Arg4& arg4,
717  const Arg5& arg5,
718  const Arg6& arg6) {
719  T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
720  T(arg1, arg2, arg3, arg4, arg5, arg6);
721  if (!skip_explicit_ownership) {
722  AddListNode(t, &internal::arena_destruct_object<T>);
723  }
724  return t;
725  }
726 
727  template <typename T, typename Arg1, typename Arg2, typename Arg3,
728  typename Arg4, typename Arg5, typename Arg6, typename Arg7>
729  GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
730  const Arg1& arg1,
731  const Arg2& arg2,
732  const Arg3& arg3,
733  const Arg4& arg4,
734  const Arg5& arg5,
735  const Arg6& arg6,
736  const Arg7& arg7) {
737  T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
738  T(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
739  if (!skip_explicit_ownership) {
740  AddListNode(t, &internal::arena_destruct_object<T>);
741  }
742  return t;
743  }
744 
745  template <typename T, typename Arg1, typename Arg2, typename Arg3,
746  typename Arg4, typename Arg5, typename Arg6, typename Arg7,
747  typename Arg8>
748  GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
749  const Arg1& arg1,
750  const Arg2& arg2,
751  const Arg3& arg3,
752  const Arg4& arg4,
753  const Arg5& arg5,
754  const Arg6& arg6,
755  const Arg7& arg7,
756  const Arg8& arg8) {
757  T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
758  T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
759  if (!skip_explicit_ownership) {
760  AddListNode(t, &internal::arena_destruct_object<T>);
761  }
762  return t;
763  }
764 
765  template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
766  T* CreateMessageInternal(typename T::InternalArenaConstructable_*) {
767  return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
768  this);
769  }
770 
771  template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
772  T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
773  const Arg& arg) {
774  return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
775  this, arg);
776  }
777 
778  template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
779  T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
780  const Arg1& arg1, const Arg2& arg2) {
781  return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
782  this, arg1, arg2);
783  }
784 
785  // CreateInArenaStorage is used to implement map field. Without it,
786  // google::protobuf::Map need to call generated message's protected arena constructor,
787  // which needs to declare google::protobuf::Map as friend of generated message.
788  template <typename T>
789  static void CreateInArenaStorage(T* ptr, Arena* arena) {
790  CreateInArenaStorageInternal(ptr, arena,
792  RegisterDestructorInternal(ptr, arena,
794  }
795 
796  template <typename T>
799  new (ptr) T(arena);
800  }
801  template <typename T>
804  new (ptr) T;
805  }
806 
807  template <typename T>
809  T* ptr, Arena* arena, google::protobuf::internal::true_type) {}
810  template <typename T>
813  arena->OwnDestructor(ptr);
814  }
815 
816  // These implement Own(), which registers an object for deletion (destructor
817  // call and operator delete()). The second parameter has type 'true_type' if T
818  // is a subtype of ::google::protobuf::Message and 'false_type' otherwise. Collapsing
819  // all template instantiations to one for generic Message reduces code size,
820  // using the virtual destructor instead.
821  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
823  if (object != NULL) {
824  AddListNode(object, &internal::arena_delete_object< ::google::protobuf::Message >);
825  }
826  }
827  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
829  if (object != NULL) {
830  AddListNode(object, &internal::arena_delete_object<T>);
831  }
832  }
833 
834  // Implementation for GetArena(). Only message objects with
835  // InternalArenaConstructable_ tags can be associated with an arena, and such
836  // objects must implement a GetArenaNoVirtual() method.
837  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
838  static ::google::protobuf::Arena* GetArenaInternal(
839  const T* value, typename T::InternalArenaConstructable_*) {
840  return value->GetArenaNoVirtual();
841  }
842 
843  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
844  static ::google::protobuf::Arena* GetArenaInternal(const T* value, ...) {
845  return NULL;
846  }
847 
848  // Allocate and also optionally call on_arena_allocation callback with the
849  // allocated type info when the hooks are in place in ArenaOptions and
850  // the cookie is not null.
851  void* AllocateAligned(const std::type_info* allocated, size_t n);
852 
853  // Allocate an internal allocation, avoiding optional typed monitoring.
855  return AllocateAligned(NULL, n);
856  }
857 
858  void Init();
859 
860  // Free all blocks and return the total space used which is the sums of sizes
861  // of the all the allocated blocks.
862  uint64 FreeBlocks();
863 
864  // Add object pointer and cleanup function pointer to the list.
865  // TODO(rohananil, cfallin): We could pass in a sub-arena into this method
866  // to avoid polluting blocks of this arena with list nodes. This would help in
867  // mixed mode (where many protobufs have cc_enable_arenas=false), and is an
868  // alternative to a chunked linked-list, but with extra overhead of *next.
869  void AddListNode(void* elem, void (*cleanup)(void*));
870  // Delete or Destruct all objects owned by the arena.
871  void CleanupList();
872  uint64 ResetInternal();
873 
874  inline void SetThreadCacheBlock(Block* block) {
875  thread_cache().last_block_used_ = block;
876  thread_cache().last_lifecycle_id_seen = lifecycle_id_;
877  }
878 
879  int64 lifecycle_id_; // Unique for each arena. Changes on Reset().
880 
881  google::protobuf::internal::AtomicWord blocks_; // Head of linked list of all allocated blocks
882  google::protobuf::internal::AtomicWord hint_; // Fast thread-local block access
883 
884  // Node contains the ptr of the object to be cleaned up and the associated
885  // cleanup function ptr.
886  struct Node {
887  void* elem; // Pointer to the object to be cleaned up.
888  void (*cleanup)(void*); // Function pointer to the destructor or deleter.
889  Node* next; // Next node in the list.
890  };
891 
892  google::protobuf::internal::AtomicWord cleanup_list_; // Head of a linked list of nodes containing object
893  // ptrs and cleanup methods.
894 
895  bool owns_first_block_; // Indicates that arena owns the first block
897 
898  void AddBlock(Block* b);
899  // Access must be synchronized, either by blocks_lock_ or by being called from
900  // Init()/Reset().
901  void AddBlockInternal(Block* b);
902  void* SlowAlloc(size_t n);
903  Block* FindBlock(void* me);
904  Block* NewBlock(void* me, Block* my_last_block, size_t n,
905  size_t start_block_size, size_t max_block_size);
906  static void* AllocFromBlock(Block* b, size_t n);
907  template <typename Key, typename T>
908  friend class Map;
909 
910  // The arena may save a cookie it receives from the external on_init hook
911  // and then use it when calling the on_reset and on_destruction hooks.
913 
915 
917 };
918 
919 // Defined above for supporting environments without RTTI.
920 #undef RTTI_TYPE_ID
921 
922 } // namespace protobuf
923 
924 } // namespace google
925 #endif // GOOGLE_PROTOBUF_ARENA_H__
static void CreateInArenaStorageInternal(T *ptr, Arena *arena, google::protobuf::internal::true_type)
Definition: arena.h:797
void Reset()
Definition: metrics_default.cc:285
#define size
Definition: float-mm.c:27
Definition: mutex.h:48
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateMessageInternal(typename T::InternalArenaConstructable_ *)
Definition: arena.h:766
bool owns_first_block_
Definition: arena.h:895
size_t initial_block_size
Definition: arena.h:106
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateInternal(bool skip_explicit_ownership, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
Definition: arena.h:681
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateInternal(bool skip_explicit_ownership, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5, const Arg6 &arg6, const Arg7 &arg7)
Definition: arena.h:729
#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName)
Definition: macros.h:40
Arena()
Definition: arena.h:229
options
Definition: CodeGeneratorReplayInputs.py:1046
#define GOOGLE_THREAD_LOCAL
Definition: port.h:292
static void RegisterDestructorInternal(T *ptr, Arena *arena, google::protobuf::internal::true_type)
Definition: arena.h:808
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateInternal(bool skip_explicit_ownership, const Arg1 &arg1, const Arg2 &arg2)
Definition: arena.h:657
bool t
Definition: UpdateContents.py:37
Definition: videoengine_unittest.h:62
Definition: map.h:57
Definition: type_traits.h:111
static GOOGLE_ATTRIBUTE_ALWAYS_INLINE Msg * CreateMaybeMessage(Arena *arena, typename Msg::InternalArenaConstructable_ *)
Definition: arena.h:617
#define GOOGLE_ATTRIBUTE_NOINLINE
Definition: port.h:189
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateInternal(bool skip_explicit_ownership, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
Definition: arena.h:667
JavaScriptCore arg3
Definition: jsc-trace-profiler-events.d:41
#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE
Definition: port.h:175
Message
Definition: peerconnection_unittest.cc:105
Definition: arena.h:886
std::integral_constant< std::size_t, V > size_t
Definition: Brigand.h:447
GOOGLE_ATTRIBUTE_ALWAYS_INLINE ::google::protobuf::Arena * GetArena(const T *value)
Definition: arena.h:499
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateInternal(bool skip_explicit_ownership, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
Definition: arena.h:696
int64 lifecycle_id_
Definition: arena.h:879
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateInternal(bool skip_explicit_ownership, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5, const Arg6 &arg6)
Definition: arena.h:712
size_t start_block_size
Definition: arena.h:91
void
Definition: AVFoundationCFSoftLinking.h:81
EGLStreamKHR EGLint n
Definition: eglext.h:984
static GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * Create(::google::protobuf::Arena *arena, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5, const Arg6 &arg6, const Arg7 &arg7)
Definition: arena.h:397
Definition: template_util.h:77
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateInternal(bool skip_explicit_ownership)
Definition: arena.h:639
TestSubObjConstructor T
Definition: TestTypedefs.idl:84
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateInternalRawArray(size_t num_elements)
Definition: arena.h:630
Definition: interfaces.idl:172
EGLAttrib * value
Definition: eglext.h:120
void * elem
Definition: arena.h:887
void arena_free(void *object, size_t)
Definition: arena.h:80
static GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateMessage(::google::protobuf::Arena *arena, const Arg1 &arg1, const Arg2 &arg2)
Definition: arena.h:275
#define RTTI_TYPE_ID(type)
Definition: arena.h:162
GOOGLE_ATTRIBUTE_NOINLINE void OwnDestructor(T *object)
Definition: arena.h:479
static void CreateInArenaStorageInternal(T *ptr, Arena *arena, google::protobuf::internal::false_type)
Definition: arena.h:802
static void CreateInArenaStorage(T *ptr, Arena *arena)
Definition: arena.h:789
static GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * Create(::google::protobuf::Arena *arena, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
Definition: arena.h:365
GOOGLE_ATTRIBUTE_NOINLINE void OwnCustomDestructor(void *object, void(*destruct)(void *))
Definition: arena.h:489
ArenaOptions()
Definition: arena.h:140
static GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * Create(::google::protobuf::Arena *arena, const Arg1 &arg1, const Arg2 &arg2)
Definition: arena.h:323
static void RegisterDestructorInternal(T *ptr, Arena *arena, google::protobuf::internal::false_type)
Definition: arena.h:811
intptr_t AtomicWord
Definition: atomicops.h:92
Definition: ApplePayLineItem.idl:30
Definition: __init__.py:1
uint64_t uint64
Definition: port.h:136
GOOGLE_ATTRIBUTE_ALWAYS_INLINE void * AllocateAligned(size_t n)
Definition: arena.h:854
google::protobuf::internal::AtomicWord cleanup_list_
Definition: arena.h:892
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateMessageInternal(typename T::InternalArenaConstructable_ *, const Arg &arg)
Definition: arena.h:772
void arena_delete_object(void *object)
Definition: arena.h:77
Definition: xmlparse.c:217
#define malloc
Definition: mbmalloc.h:49
static GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateMessage(::google::protobuf::Arena *arena)
Definition: arena.h:250
GOOGLE_ATTRIBUTE_ALWAYS_INLINE ::google::protobuf::Arena * GetArenaInternal(const T *value,...)
Definition: arena.h:844
Definition: arena.h:218
static GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * Create(::google::protobuf::Arena *arena, const Arg &arg)
Definition: arena.h:312
static GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * Create(::google::protobuf::Arena *arena, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5, const Arg6 &arg6)
Definition: arena.h:381
Node * next
Definition: arena.h:889
void * hooks_cookie_
Definition: arena.h:912
static GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateMessage(::google::protobuf::Arena *arena, const Arg &arg)
Definition: arena.h:262
Mutex blocks_lock_
Definition: arena.h:896
GOOGLE_ATTRIBUTE_NOINLINE void Own(T *object)
Definition: arena.h:469
Definition: document.h:393
Definition: atomic_sequence_num.h:39
void Init(int s, int n)
Definition: towers.c:162
#define GOOGLE_CHECK_LE(A, B)
Definition: logging.h:157
double max
Definition: DeviceProximityEvent.idl:32
void SetThreadCacheBlock(Block *block)
Definition: arena.h:874
static GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateMaybeMessage(Arena *arena,...)
Definition: arena.h:623
static GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * Create(::google::protobuf::Arena *arena, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5, const Arg6 &arg6, const Arg7 &arg7, const Arg8 &arg8)
Definition: arena.h:415
ArenaOptions options_
Definition: arena.h:914
int64_t int64
Definition: port.h:131
GOOGLE_ATTRIBUTE_ALWAYS_INLINE ::google::protobuf::Arena * GetArenaInternal(const T *value, typename T::InternalArenaConstructable_ *)
Definition: arena.h:838
#define NULL
Definition: common_types.h:41
static GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateArray(::google::protobuf::Arena *arena, size_t num_elements)
Definition: arena.h:436
EGLenum EGLObjectKHR object
Definition: eglext.h:121
JavaScriptCore arg4
Definition: jsc-trace-profiler-events.d:41
#define LIBPROTOBUF_EXPORT
Definition: port.h:97
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateMessageInternal(typename T::InternalArenaConstructable_ *, const Arg1 &arg1, const Arg2 &arg2)
Definition: arena.h:779
GLboolean GLboolean GLboolean b
Definition: gl2ext.h:306
Definition: gflags_completions.h:115
static GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * Create(::google::protobuf::Arena *arena)
Definition: arena.h:302
void arena_destruct_object(void *object)
Definition: arena.h:74
GOOGLE_ATTRIBUTE_ALWAYS_INLINE void OwnInternal(T *object, google::protobuf::internal::false_type)
Definition: arena.h:828
Definition: arena.h:88
GOOGLE_ATTRIBUTE_ALWAYS_INLINE void OwnInternal(T *object, google::protobuf::internal::true_type)
Definition: arena.h:822
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateInternal(bool skip_explicit_ownership, const Arg &arg)
Definition: arena.h:648
static GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * Create(::google::protobuf::Arena *arena, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
Definition: arena.h:350
#define free
Definition: mbmalloc.h:50
size_t max_block_size
Definition: arena.h:97
google::protobuf::internal::AtomicWord hint_
Definition: arena.h:882
google::protobuf::internal::AtomicWord blocks_
Definition: arena.h:881
static GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * Create(::google::protobuf::Arena *arena, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
Definition: arena.h:335
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T * CreateInternal(bool skip_explicit_ownership, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5, const Arg6 &arg6, const Arg7 &arg7, const Arg8 &arg8)
Definition: arena.h:748
char * initial_block
Definition: arena.h:103
Arena(const ArenaOptions &options)
Definition: arena.h:223
#define T(a)
Definition: row_common.cc:1964