Andrew Top | a953d4e | 2016-11-22 22:38:45 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2016 Google Inc. All Rights Reserved. |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #ifndef NB_MEMORY_SCOPE_H_ |
| 18 | #define NB_MEMORY_SCOPE_H_ |
| 19 | |
Andrew Top | a953d4e | 2016-11-22 22:38:45 -0800 | [diff] [blame] | 20 | /////////////////////////////////////////////////////////////////////////////// |
| 21 | // Macros to define the memory scope objects. These are objects that are used |
| 22 | // to annotate sections of the code base as belonging to a particular memory |
| 23 | // scope. Note that this is an annotation and does not memory allocation. |
| 24 | /////////////////////////////////////////////////////////////////////////////// |
| 25 | |
| 26 | // Macro to track the memory scope inside a function or block of code. The |
| 27 | // memory scope is in effect until the end of the code block. |
| 28 | // Example: |
| 29 | // void Foo() { |
| 30 | // TRACK_MEMORY_SCOPE("FooMemoryScope"); |
| 31 | // // pops the memory scope at the end. |
| 32 | // } |
| 33 | |
| 34 | #if !defined(__cplusplus) |
| 35 | // Disallow macro use for non-C++ builds. |
| 36 | #define TRACK_MEMORY_SCOPE(STR) error_forbidden_in_non_c_plus_plus_code |
| 37 | #define TRACK_MEMORY_SCOPE_DYNAMIC(STR) error_forbidden_in_non_c_plus_plus_code |
| 38 | #elif defined(STARBOARD_ALLOWS_MEMORY_TRACKING) |
| 39 | #define TRACK_MEMORY_SCOPE(STR) TRACK_MEMORY_STATIC_CACHED(STR) |
| 40 | #define TRACK_MEMORY_SCOPE_DYNAMIC(STR) TRACK_MEMORY_STATIC_NOT_CACHED(STR) |
| 41 | #else |
| 42 | // No-op when starboard does not allow memory tracking. |
| 43 | #define TRACK_MEMORY_SCOPE(STR) |
| 44 | #define TRACK_MEMORY_SCOPE_DYNAMIC(STR) |
| 45 | #endif |
| 46 | |
| 47 | // Preprocessor needs double expansion in order to __FILE__, __LINE__ and |
| 48 | // __FUNCTION__ properly. |
| 49 | #define TRACK_MEMORY_STATIC_CACHED(STR) \ |
| 50 | TRACK_MEMORY_STATIC_CACHED_IMPL_2(STR, __FILE__, __LINE__, __FUNCTION__) |
| 51 | |
| 52 | #define TRACK_MEMORY_STATIC_NOT_CACHED(STR) \ |
| 53 | TRACK_MEMORY_STATIC_NOT_CACHED_IMPL_2(STR, __FILE__, __LINE__, __FUNCTION__) |
| 54 | |
| 55 | // Only enable TRACK_MEMORY_STATIC_CACHED_IMPL_2 if starboard allows memory |
| 56 | // tracking. |
| 57 | #define TRACK_MEMORY_STATIC_CACHED_IMPL_2(Str, FileStr, LineNum, FuncStr) \ |
| 58 | static NbMemoryScopeInfo memory_scope_handle_##LineNum = \ |
Andrew Top | a8b9985 | 2016-11-29 21:41:27 -0800 | [diff] [blame] | 59 | { NULL, Str, FileStr, LineNum, FuncStr, true }; \ |
Andrew Top | a953d4e | 2016-11-22 22:38:45 -0800 | [diff] [blame] | 60 | NbPushMemoryScope(&memory_scope_handle_##LineNum); \ |
David Ghandehari | 00be30f | 2017-04-27 21:30:48 -0700 | [diff] [blame] | 61 | NbPopMemoryScopeOnScopeEnd pop_on_scope_end_##LineNum; \ |
| 62 | (void)pop_on_scope_end_##LineNum; |
Andrew Top | a953d4e | 2016-11-22 22:38:45 -0800 | [diff] [blame] | 63 | |
| 64 | #define TRACK_MEMORY_STATIC_NOT_CACHED_IMPL_2(Str, FileStr, LineNum, FuncStr) \ |
| 65 | NbMemoryScopeInfo memory_scope_handle_##LineNum = { \ |
Andrew Top | a8b9985 | 2016-11-29 21:41:27 -0800 | [diff] [blame] | 66 | NULL, Str, FileStr, LineNum, FuncStr, false}; \ |
Andrew Top | a953d4e | 2016-11-22 22:38:45 -0800 | [diff] [blame] | 67 | NbPushMemoryScope(&memory_scope_handle_##LineNum); \ |
David Ghandehari | 00be30f | 2017-04-27 21:30:48 -0700 | [diff] [blame] | 68 | NbPopMemoryScopeOnScopeEnd pop_on_scope_end_##LineNum; \ |
| 69 | (void)pop_on_scope_end_##LineNum; |
Andrew Top | a953d4e | 2016-11-22 22:38:45 -0800 | [diff] [blame] | 70 | |
| 71 | #ifdef __cplusplus |
| 72 | extern "C" { |
| 73 | #endif |
| 74 | |
| 75 | struct NbMemoryScopeReporter; |
| 76 | struct NbMemoryScopeInfo; |
| 77 | |
| 78 | // Sets the memory reporter. Returns true on success, false something |
| 79 | // goes wrong. |
| 80 | bool NbSetMemoryScopeReporter(NbMemoryScopeReporter* reporter); |
| 81 | |
| 82 | // Note that we pass by pointer because the memory scope contains a |
| 83 | // variable allowing the result to be cached. |
| 84 | void NbPushMemoryScope(NbMemoryScopeInfo* memory_scope); |
| 85 | void NbPopMemoryScope(); |
| 86 | |
| 87 | /////////////////////////////////////////////////////////////////////////////// |
| 88 | // Implementation |
| 89 | /////////////////////////////////////////////////////////////////////////////// |
| 90 | // Interface for handling memory scopes. |
| 91 | typedef void (*NbReportPushMemoryScopeCallback)(void* context, |
| 92 | NbMemoryScopeInfo* info); |
| 93 | typedef void (*NbReportPopMemoryScopeCallback)(void* context); |
| 94 | |
| 95 | struct NbMemoryScopeReporter { |
| 96 | // Callback to report pushing of memory scope. |
| 97 | NbReportPushMemoryScopeCallback push_memory_scope_cb; |
| 98 | |
| 99 | // Callback to report poping of the memory scope. |
| 100 | NbReportPopMemoryScopeCallback pop_memory_scope_cb; |
| 101 | |
| 102 | // Optional, is passed to the callbacks as first argument. |
| 103 | void* context; |
| 104 | }; |
| 105 | |
| 106 | // This MemoryScope must remain a POD data type so that it can be statically |
| 107 | // initialized. |
| 108 | struct NbMemoryScopeInfo { |
| 109 | // cached_handle_ allows a cached result of the the fields represented in |
| 110 | // this struct to be generated and the handle be placed into this field. |
| 111 | // See also allows_caching_. |
Andrew Top | a8b9985 | 2016-11-29 21:41:27 -0800 | [diff] [blame] | 112 | void* cached_handle_; |
Andrew Top | a953d4e | 2016-11-22 22:38:45 -0800 | [diff] [blame] | 113 | |
| 114 | // Represents the name of the memory scope. I.E. "Javascript" or "Gfx". |
| 115 | const char* memory_scope_name_; |
| 116 | |
| 117 | // Represents the file name that this memory scope was created at. |
| 118 | const char* file_name_; |
| 119 | |
| 120 | // Represents the line number that this memory scope was created at. |
| 121 | int line_number_; |
| 122 | |
| 123 | // Represents the function name that this memory scope was created at. |
| 124 | const char* function_name_; |
| 125 | |
| 126 | // When true, if cached_handle_ is 0 then an object may be created that |
| 127 | // represents the fields of this object. The handle that represents this |
| 128 | // cached object is then placed in cached_hanlde_. |
Andrew Top | 2ea2238 | 2016-12-08 09:47:36 -0800 | [diff] [blame] | 129 | bool allows_caching_; |
Andrew Top | a953d4e | 2016-11-22 22:38:45 -0800 | [diff] [blame] | 130 | }; |
| 131 | |
| 132 | // NbPopMemoryScopeOnScopeEnd is only allowed for C++ builds. |
| 133 | #ifdef __cplusplus |
| 134 | // A helper that pops the memory scope at the end of the current code block. |
| 135 | struct NbPopMemoryScopeOnScopeEnd { |
| 136 | ~NbPopMemoryScopeOnScopeEnd() { NbPopMemoryScope(); } |
| 137 | }; |
| 138 | #endif |
| 139 | |
| 140 | |
| 141 | #ifdef __cplusplus |
| 142 | } // extern "C" |
| 143 | #endif |
| 144 | |
| 145 | #endif // NB_MEMORY_SCOPE_H_ |