xref: /aosp_15_r20/external/cronet/base/memory/stack_allocated.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2023 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_MEMORY_STACK_ALLOCATED_H_
6 #define BASE_MEMORY_STACK_ALLOCATED_H_
7 
8 #include <stddef.h>
9 
10 #if defined(__clang__)
11 #define STACK_ALLOCATED_IGNORE(reason) \
12   __attribute__((annotate("stack_allocated_ignore")))
13 #else  // !defined(__clang__)
14 #define STACK_ALLOCATED_IGNORE(reason)
15 #endif  // !defined(__clang__)
16 
17 // If a class or one of its ancestor classes is annotated with STACK_ALLOCATED()
18 // in its class definition, then instances of the class may not be allocated on
19 // the heap or as a member variable of a non-stack-allocated class.
20 #define STACK_ALLOCATED()                                         \
21  public:                                                          \
22   using IsStackAllocatedTypeMarker [[maybe_unused]] = int;        \
23                                                                   \
24  private:                                                         \
25   void* operator new(size_t) = delete;                            \
26   void* operator new(size_t, ::base::NotNullTag, void*) = delete; \
27   void* operator new(size_t, void*) = delete
28 
29 namespace base {
30 
31 // NotNullTag was originally added to WebKit here:
32 //     https://trac.webkit.org/changeset/103243/webkit
33 // ...with the stated goal of improving the performance of the placement new
34 // operator and potentially enabling the -fomit-frame-pointer compiler flag.
35 //
36 // TODO(szager): The placement new operator which uses this tag is currently
37 // defined in third_party/blink/renderer/platform/wtf/allocator/allocator.h,
38 // in the global namespace. It should probably move to /base.
39 //
40 // It's unknown at the time of writing whether it still provides any benefit
41 // (or if it ever did). It is used by placing the kNotNull tag before the
42 // address of the object when calling placement new.
43 //
44 // If the kNotNull tag is specified to placement new for a null pointer,
45 // Undefined Behaviour can result.
46 //
47 // Example:
48 //
49 // union { int i; } u;
50 //
51 // // Typically placement new looks like this.
52 // new (&u.i) int(3);
53 // // But we can promise `&u.i` is not null like this.
54 // new (base::NotNullTag::kNotNull, &u.i) int(3);
55 enum class NotNullTag { kNotNull };
56 
57 }  // namespace base
58 
59 #endif  // BASE_MEMORY_STACK_ALLOCATED_H_
60