@@ -67,7 +67,11 @@ TEST_F(ContextTest, Callsite) {
67
67
__llvm_ctx_profile_expected_callee[0 ] = &FakeCalleeAddress;
68
68
__llvm_ctx_profile_callsite[0 ] = &Ctx->subContexts ()[2 ];
69
69
// This is what the callee does
70
- auto *Subctx = __llvm_ctx_profile_get_context (&FakeCalleeAddress, 2 , 3 , 1 );
70
+ FunctionData FData = {0 };
71
+ auto *Subctx =
72
+ __llvm_ctx_profile_get_context (&FData, &FakeCalleeAddress, 2 , 3 , 1 );
73
+ // This should not have required creating a flat context.
74
+ EXPECT_EQ (FData.FlatCtx , nullptr );
71
75
// We expect the subcontext to be appropriately placed and dimensioned
72
76
EXPECT_EQ (Ctx->subContexts ()[2 ], Subctx);
73
77
EXPECT_EQ (Subctx->counters_size (), 3U );
@@ -81,15 +85,38 @@ TEST_F(ContextTest, Callsite) {
81
85
__llvm_ctx_profile_release_context (&Root);
82
86
}
83
87
84
- TEST_F (ContextTest, ScratchNoCollection ) {
88
+ TEST_F (ContextTest, ScratchNoCollectionProfilingNotStarted ) {
85
89
EXPECT_EQ (__llvm_ctx_profile_current_context_root, nullptr );
86
90
int FakeCalleeAddress = 0 ;
87
91
// this would be the very first function executing this. the TLS is empty,
88
92
// too.
89
- auto *Ctx = __llvm_ctx_profile_get_context (&FakeCalleeAddress, 2 , 3 , 1 );
93
+ FunctionData FData = {0 };
94
+ auto *Ctx =
95
+ __llvm_ctx_profile_get_context (&FData, &FakeCalleeAddress, 2 , 3 , 1 );
90
96
// We never entered a context (_start_context was never called) - so the
91
- // returned context must be scratch .
97
+ // returned context must be a tagged pointer .
92
98
EXPECT_TRUE (isScratch (Ctx));
99
+ // Because we never entered a context, we should have allocated a flat context
100
+ EXPECT_EQ (FData.FlatCtx , nullptr );
101
+ }
102
+
103
+ TEST_F (ContextTest, ScratchNoCollectionProfilingStarted) {
104
+ EXPECT_EQ (__llvm_ctx_profile_current_context_root, nullptr );
105
+ int FakeCalleeAddress = 0 ;
106
+ // Start collection, so the function gets a flat profile instead of scratch.
107
+ __llvm_ctx_profile_start_collection ();
108
+ // this would be the very first function executing this. the TLS is empty,
109
+ // too.
110
+ FunctionData FData = {0 };
111
+ auto *Ctx =
112
+ __llvm_ctx_profile_get_context (&FData, &FakeCalleeAddress, 2 , 3 , 1 );
113
+ // We never entered a context (_start_context was never called) - so the
114
+ // returned context must be a tagged pointer.
115
+ EXPECT_TRUE (isScratch (Ctx));
116
+ // Because we never entered a context, we should have allocated a flat context
117
+ EXPECT_NE (FData.FlatCtx , nullptr );
118
+ EXPECT_EQ (reinterpret_cast <uintptr_t >(FData.FlatCtx ) + 1 ,
119
+ reinterpret_cast <uintptr_t >(Ctx));
93
120
}
94
121
95
122
TEST_F (ContextTest, ScratchDuringCollection) {
@@ -98,32 +125,38 @@ TEST_F(ContextTest, ScratchDuringCollection) {
98
125
int OtherFakeCalleeAddress = 0 ;
99
126
__llvm_ctx_profile_expected_callee[0 ] = &FakeCalleeAddress;
100
127
__llvm_ctx_profile_callsite[0 ] = &Ctx->subContexts ()[2 ];
101
- auto *Subctx =
102
- __llvm_ctx_profile_get_context (&OtherFakeCalleeAddress, 2 , 3 , 1 );
128
+ FunctionData FData[3 ] = {0 };
129
+ auto *Subctx = __llvm_ctx_profile_get_context (
130
+ &FData[0 ], &OtherFakeCalleeAddress, 2 , 3 , 1 );
103
131
// We expected a different callee - so return scratch. It mimics what happens
104
132
// in the case of a signal handler - in this case, OtherFakeCalleeAddress is
105
133
// the signal handler.
106
134
EXPECT_TRUE (isScratch (Subctx));
135
+ // We shouldn't have tried to return a flat context because we're under a
136
+ // root.
137
+ EXPECT_EQ (FData[0 ].FlatCtx , nullptr );
107
138
EXPECT_EQ (__llvm_ctx_profile_expected_callee[0 ], nullptr );
108
139
EXPECT_EQ (__llvm_ctx_profile_callsite[0 ], nullptr );
109
140
110
141
int ThirdFakeCalleeAddress = 0 ;
111
142
__llvm_ctx_profile_expected_callee[1 ] = &ThirdFakeCalleeAddress;
112
143
__llvm_ctx_profile_callsite[1 ] = &Subctx->subContexts ()[0 ];
113
144
114
- auto *Subctx2 =
115
- __llvm_ctx_profile_get_context ( &ThirdFakeCalleeAddress, 3 , 0 , 0 );
145
+ auto *Subctx2 = __llvm_ctx_profile_get_context (
146
+ &FData[ 1 ], &ThirdFakeCalleeAddress, 3 , 0 , 0 );
116
147
// We again expect scratch because the '0' position is where the runtime
117
148
// looks, so it doesn't matter the '1' position is populated correctly.
118
149
EXPECT_TRUE (isScratch (Subctx2));
150
+ EXPECT_EQ (FData[1 ].FlatCtx , nullptr );
119
151
120
152
__llvm_ctx_profile_expected_callee[0 ] = &ThirdFakeCalleeAddress;
121
153
__llvm_ctx_profile_callsite[0 ] = &Subctx->subContexts ()[0 ];
122
- auto *Subctx3 =
123
- __llvm_ctx_profile_get_context ( &ThirdFakeCalleeAddress, 3 , 0 , 0 );
154
+ auto *Subctx3 = __llvm_ctx_profile_get_context (
155
+ &FData[ 2 ], &ThirdFakeCalleeAddress, 3 , 0 , 0 );
124
156
// We expect scratch here, too, because the value placed in
125
157
// __llvm_ctx_profile_callsite is scratch
126
158
EXPECT_TRUE (isScratch (Subctx3));
159
+ EXPECT_EQ (FData[2 ].FlatCtx , nullptr );
127
160
128
161
__llvm_ctx_profile_release_context (&Root);
129
162
}
@@ -136,9 +169,11 @@ TEST_F(ContextTest, NeedMoreMemory) {
136
169
const auto *CurrentMem = Root.CurrentMem ;
137
170
__llvm_ctx_profile_expected_callee[0 ] = &FakeCalleeAddress;
138
171
__llvm_ctx_profile_callsite[0 ] = &Ctx->subContexts ()[2 ];
172
+ FunctionData FData = {0 };
139
173
// Allocate a massive subcontext to force new arena allocation
140
174
auto *Subctx =
141
- __llvm_ctx_profile_get_context (&FakeCalleeAddress, 3 , 1 << 20 , 1 );
175
+ __llvm_ctx_profile_get_context (&FData, &FakeCalleeAddress, 3 , 1 << 20 , 1 );
176
+ EXPECT_EQ (FData.FlatCtx , nullptr );
142
177
EXPECT_EQ (Ctx->subContexts ()[2 ], Subctx);
143
178
EXPECT_NE (CurrentMem, Root.CurrentMem );
144
179
EXPECT_NE (Root.CurrentMem , nullptr );
@@ -175,7 +210,9 @@ TEST_F(ContextTest, Dump) {
175
210
int FakeCalleeAddress = 0 ;
176
211
__llvm_ctx_profile_expected_callee[0 ] = &FakeCalleeAddress;
177
212
__llvm_ctx_profile_callsite[0 ] = &Ctx->subContexts ()[2 ];
178
- auto *Subctx = __llvm_ctx_profile_get_context (&FakeCalleeAddress, 2 , 3 , 1 );
213
+ FunctionData FData = {0 };
214
+ auto *Subctx =
215
+ __llvm_ctx_profile_get_context (&FData, &FakeCalleeAddress, 2 , 3 , 1 );
179
216
(void )Subctx;
180
217
__llvm_ctx_profile_release_context (&Root);
181
218
@@ -186,6 +223,9 @@ TEST_F(ContextTest, Dump) {
186
223
187
224
int EnteredSectionCount = 0 ;
188
225
int ExitedSectionCount = 0 ;
226
+ int EnteredFlatCount = 0 ;
227
+ int ExitedFlatCount = 0 ;
228
+ int FlatsWritten = 0 ;
189
229
190
230
bool State = false ;
191
231
@@ -217,6 +257,16 @@ TEST_F(ContextTest, Dump) {
217
257
EXPECT_EQ (EnteredSectionCount, 1 );
218
258
++ExitedSectionCount;
219
259
}
260
+ void startFlatSection () override { ++EnteredFlatCount; }
261
+ void writeFlat (GUID Guid, const uint64_t *Buffer,
262
+ size_t BufferSize) override {
263
+ ++FlatsWritten;
264
+ EXPECT_EQ (BufferSize, 3 );
265
+ EXPECT_EQ (Buffer[0 ], 15U );
266
+ EXPECT_EQ (Buffer[1 ], 0U );
267
+ EXPECT_EQ (Buffer[2 ], 0U );
268
+ }
269
+ void endFlatSection () override { ++ExitedFlatCount; }
220
270
};
221
271
222
272
TestProfileWriter W (&Root, 1 );
@@ -226,10 +276,17 @@ TEST_F(ContextTest, Dump) {
226
276
227
277
// this resets all counters but not the internal structure.
228
278
__llvm_ctx_profile_start_collection ();
279
+ auto *Flat =
280
+ __llvm_ctx_profile_get_context (&FData, &FakeCalleeAddress, 2 , 3 , 1 );
281
+ EXPECT_NE (FData.FlatCtx , nullptr );
282
+ FData.FlatCtx ->counters ()[0 ] = 15U ;
229
283
TestProfileWriter W2 (&Root, 0 );
230
284
EXPECT_FALSE (W2.State );
231
285
__llvm_ctx_profile_fetch (W2);
232
286
EXPECT_TRUE (W2.State );
233
287
EXPECT_EQ (W2.EnteredSectionCount , 1 );
234
288
EXPECT_EQ (W2.ExitedSectionCount , 1 );
289
+ EXPECT_EQ (W2.EnteredFlatCount , 1 );
290
+ EXPECT_EQ (W2.FlatsWritten , 1 );
291
+ EXPECT_EQ (W2.ExitedFlatCount , 1 );
235
292
}
0 commit comments