17
17
18
18
#include " llvm/ADT/DenseMap.h"
19
19
#include " RuntimeInvocationsTracking.h"
20
+ #include " swift/Basic/Lazy.h"
20
21
#include " swift/Runtime/HeapObject.h"
22
+ #include " swift/Runtime/Mutex.h"
21
23
22
24
// This file is compiled always, even if assertions are disabled and no runtime
23
25
// functions are being tracked. This is done to avoid recompiling Swift clients
@@ -48,12 +50,19 @@ static bool UpdateGlobalRuntimeFunctionCounters = false;
48
50
// / TODO: Add support for enabling/disabling counters on a per object basis?
49
51
50
52
// / Global set of counters tracking the total number of runtime invocations.
51
- static RuntimeFunctionCountersState RuntimeGlobalFunctionCountersState;
53
+ struct RuntimeFunctionCountersStateSentinel {
54
+ RuntimeFunctionCountersState State;
55
+ StaticReadWriteLock Lock;
56
+ };
57
+ static RuntimeFunctionCountersStateSentinel RuntimeGlobalFunctionCountersState;
52
58
53
59
// / The object state cache mapping objects to the collected state associated with
54
60
// / them.
55
- // / TODO: Do we need to make it thread-safe?
56
- static llvm::DenseMap<HeapObject *, RuntimeFunctionCountersState> RuntimeObjectStateCache;
61
+ struct RuntimeObjectCacheSentinel {
62
+ llvm::DenseMap<HeapObject *, RuntimeFunctionCountersState> Cache;
63
+ StaticReadWriteLock Lock;
64
+ };
65
+ static Lazy<RuntimeObjectCacheSentinel> RuntimeObjectStateCache;
57
66
58
67
static const char *RuntimeFunctionNames[] {
59
68
// / Define names of runtime functions.
@@ -95,79 +104,84 @@ static uint16_t RuntimeFunctionCountersOffsets[] = {
95
104
void SWIFT_RT_TRACK_INVOCATION_NAME (RT_FUNCTION)(HeapObject * object) { \
96
105
/* Update global counters. */ \
97
106
if (UpdateGlobalRuntimeFunctionCounters) { \
98
- RuntimeGlobalFunctionCountersState \
107
+ StaticScopedWriteLock lock (RuntimeGlobalFunctionCountersState.Lock ); \
108
+ RuntimeGlobalFunctionCountersState.State \
99
109
.SWIFT_RT_FUNCTION_INVOCATION_COUNTER_NAME (RT_FUNCTION)++; \
100
110
if (GlobalRuntimeFunctionCountersUpdateHandler) { \
101
- auto oldGlobalMode = setGlobalRuntimeFunctionCountersMode (0 ); \
102
- auto oldPerObjectMode = setPerObjectRuntimeFunctionCountersMode (0 ); \
111
+ auto oldGlobalMode = _swift_setGlobalRuntimeFunctionCountersMode (0 ); \
112
+ auto oldPerObjectMode = \
113
+ _swift_setPerObjectRuntimeFunctionCountersMode (0 ); \
103
114
GlobalRuntimeFunctionCountersUpdateHandler ( \
104
115
object, RT_FUNCTION_ID (RT_FUNCTION)); \
105
- setGlobalRuntimeFunctionCountersMode (oldGlobalMode); \
106
- setPerObjectRuntimeFunctionCountersMode (oldPerObjectMode); \
116
+ _swift_setGlobalRuntimeFunctionCountersMode (oldGlobalMode); \
117
+ _swift_setPerObjectRuntimeFunctionCountersMode (oldPerObjectMode); \
107
118
} \
108
119
} \
109
120
/* Update per object counters. */ \
110
121
if (UpdatePerObjectRuntimeFunctionCounters && object) { \
111
- RuntimeObjectStateCache[object] \
112
- .SWIFT_RT_FUNCTION_INVOCATION_COUNTER_NAME (RT_FUNCTION)++; \
113
- /* TODO: Remember the order/history of operations? */ \
122
+ auto &theSentinel = RuntimeObjectStateCache.get (); \
123
+ StaticScopedWriteLock lock (theSentinel.Lock ); \
124
+ theSentinel.Cache [object].SWIFT_RT_FUNCTION_INVOCATION_COUNTER_NAME ( \
125
+ RT_FUNCTION)++; \
126
+ /* TODO: Remember the order/history of operations? */ \
114
127
} \
115
128
}
116
129
#include " RuntimeInvocationsTracking.def"
117
130
118
131
// / Public APIs
119
132
120
133
// / Get the runtime object state associated with an object.
121
- SWIFT_RT_ENTRY_VISIBILITY
122
- void getObjectRuntimeFunctionCounters (HeapObject *object,
123
- RuntimeFunctionCountersState *result) {
124
- *result = RuntimeObjectStateCache[object];
134
+ void _swift_getObjectRuntimeFunctionCounters (
135
+ HeapObject *object, RuntimeFunctionCountersState *result) {
136
+ auto &theSentinel = RuntimeObjectStateCache.get ();
137
+ StaticScopedReadLock lock (theSentinel.Lock );
138
+ *result = theSentinel.Cache [object];
125
139
}
126
140
127
141
// / Set the runtime object state associated with an object from a provided
128
142
// / state.
129
- SWIFT_RT_ENTRY_VISIBILITY
130
- void setObjectRuntimeFunctionCounters (HeapObject *object,
131
- RuntimeFunctionCountersState *state) {
132
- RuntimeObjectStateCache[object] = *state;
143
+ void _swift_setObjectRuntimeFunctionCounters (
144
+ HeapObject *object, RuntimeFunctionCountersState *state) {
145
+ auto &theSentinel = RuntimeObjectStateCache.get ();
146
+ StaticScopedWriteLock lock (theSentinel.Lock );
147
+ theSentinel.Cache [object] = *state;
133
148
}
134
149
135
150
// / Get the global runtime state containing the total numbers of invocations for
136
151
// / each runtime function of interest.
137
- SWIFT_RT_ENTRY_VISIBILITY
138
- void getGlobalRuntimeFunctionCounters (RuntimeFunctionCountersState *result) {
139
- *result = RuntimeGlobalFunctionCountersState;
152
+ void _swift_getGlobalRuntimeFunctionCounters (
153
+ RuntimeFunctionCountersState *result) {
154
+ StaticScopedReadLock lock (RuntimeGlobalFunctionCountersState.Lock );
155
+ *result = RuntimeGlobalFunctionCountersState.State ;
140
156
}
141
157
142
158
// / Set the global runtime state of function pointers from a provided state.
143
- SWIFT_RT_ENTRY_VISIBILITY
144
- void setGlobalRuntimeFunctionCounters (RuntimeFunctionCountersState *state) {
145
- RuntimeGlobalFunctionCountersState = *state;
159
+ void _swift_setGlobalRuntimeFunctionCounters (
160
+ RuntimeFunctionCountersState *state) {
161
+ StaticScopedWriteLock lock (RuntimeGlobalFunctionCountersState.Lock );
162
+ RuntimeGlobalFunctionCountersState.State = *state;
146
163
}
147
164
148
165
// / Return the names of the runtime functions being tracked.
149
166
// / Their order is the same as the order of the counters in the
150
167
// / RuntimeObjectState structure. All these strings are null terminated.
151
- SWIFT_RT_ENTRY_VISIBILITY
152
- const char **getRuntimeFunctionNames () {
168
+ const char **_swift_getRuntimeFunctionNames () {
153
169
return RuntimeFunctionNames;
154
170
}
155
171
156
172
// / Return the offsets of the runtime function counters being tracked.
157
173
// / Their order is the same as the order of the counters in the
158
174
// / RuntimeObjectState structure.
159
- SWIFT_RT_ENTRY_VISIBILITY
160
- const uint16_t *getRuntimeFunctionCountersOffsets () {
175
+ const uint16_t *_swift_getRuntimeFunctionCountersOffsets () {
161
176
return RuntimeFunctionCountersOffsets;
162
177
}
163
178
164
179
// / Return the number of runtime functions being tracked.
165
- SWIFT_RT_ENTRY_VISIBILITY
166
- uint64_t getNumRuntimeFunctionCounters () {
180
+ uint64_t _swift_getNumRuntimeFunctionCounters () {
167
181
return ID_LastRuntimeFunctionName;
168
182
}
169
183
170
- static void dumpRuntimeCounters (RuntimeFunctionCountersState *State) {
184
+ static void _swift_dumpRuntimeCounters (RuntimeFunctionCountersState *State) {
171
185
uint32_t tmp;
172
186
// / Define how to dump the counter for a given runtime function.
173
187
#define FUNCTION_TO_TRACK (RT_FUNCTION ) \
@@ -179,28 +193,27 @@ static void dumpRuntimeCounters(RuntimeFunctionCountersState *State) {
179
193
}
180
194
181
195
// / Dump all per-object runtime function pointers.
182
- SWIFT_RT_ENTRY_VISIBILITY
183
- void dumpObjectsRuntimeFunctionPointers () {
184
- for (auto &Pair : RuntimeObjectStateCache) {
196
+ void _swift_dumpObjectsRuntimeFunctionPointers () {
197
+ auto &theSentinel = RuntimeObjectStateCache.get ();
198
+ StaticScopedReadLock lock (theSentinel.Lock );
199
+ for (auto &Pair : theSentinel.Cache ) {
185
200
printf (" \n\n Runtime counters for object at address %p:\n " , Pair.getFirst ());
186
- dumpRuntimeCounters (&Pair.getSecond ());
201
+ _swift_dumpRuntimeCounters (&Pair.getSecond ());
187
202
printf (" \n " );
188
203
}
189
204
}
190
205
191
206
// / Set mode for global runtime function counters.
192
207
// / Return the old value of this flag.
193
- SWIFT_RT_ENTRY_VISIBILITY
194
- int setGlobalRuntimeFunctionCountersMode (int mode) {
208
+ int _swift_setGlobalRuntimeFunctionCountersMode (int mode) {
195
209
int oldMode = UpdateGlobalRuntimeFunctionCounters;
196
210
UpdateGlobalRuntimeFunctionCounters = mode ? 1 : 0 ;
197
211
return oldMode;
198
212
}
199
213
200
214
// / Set mode for per object runtime function counters.
201
215
// / Return the old value of this flag.
202
- SWIFT_RT_ENTRY_VISIBILITY
203
- int setPerObjectRuntimeFunctionCountersMode (int mode) {
216
+ int _swift_setPerObjectRuntimeFunctionCountersMode (int mode) {
204
217
int oldMode = UpdatePerObjectRuntimeFunctionCounters;
205
218
UpdatePerObjectRuntimeFunctionCounters = mode ? 1 : 0 ;
206
219
return oldMode;
@@ -210,13 +223,12 @@ int setPerObjectRuntimeFunctionCountersMode(int mode) {
210
223
// / is being updated. The handler should take the object and may be
211
224
// / the name of the runtime function as parameters. And this handler
212
225
// / could e.g. check some conditions and stop the program under
213
- // / a debuggger if a certain condition is met, like a refcount has
226
+ // / a debugger if a certain condition is met, like a refcount has
214
227
// / reached a certain value.
215
228
// / We could allow for setting global handlers or even per-object
216
229
// / handlers.
217
- SWIFT_RT_ENTRY_VISIBILITY
218
230
RuntimeFunctionCountersUpdateHandler
219
- setGlobalRuntimeFunctionCountersUpdateHandler (
231
+ _swift_setGlobalRuntimeFunctionCountersUpdateHandler (
220
232
RuntimeFunctionCountersUpdateHandler handler) {
221
233
auto oldHandler = GlobalRuntimeFunctionCountersUpdateHandler;
222
234
GlobalRuntimeFunctionCountersUpdateHandler = handler;
0 commit comments