@@ -67,7 +67,11 @@ TEST_F(ContextTest, Callsite) {
6767 __llvm_ctx_profile_expected_callee[0 ] = &FakeCalleeAddress;
6868 __llvm_ctx_profile_callsite[0 ] = &Ctx->subContexts ()[2 ];
6969 // 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 );
7175 // We expect the subcontext to be appropriately placed and dimensioned
7276 EXPECT_EQ (Ctx->subContexts ()[2 ], Subctx);
7377 EXPECT_EQ (Subctx->counters_size (), 3U );
@@ -81,15 +85,38 @@ TEST_F(ContextTest, Callsite) {
8185 __llvm_ctx_profile_release_context (&Root);
8286}
8387
84- TEST_F (ContextTest, ScratchNoCollection ) {
88+ TEST_F (ContextTest, ScratchNoCollectionProfilingNotStarted ) {
8589 EXPECT_EQ (__llvm_ctx_profile_current_context_root, nullptr );
8690 int FakeCalleeAddress = 0 ;
8791 // this would be the very first function executing this. the TLS is empty,
8892 // 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 );
9096 // 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 .
9298 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));
93120}
94121
95122TEST_F (ContextTest, ScratchDuringCollection) {
@@ -98,32 +125,38 @@ TEST_F(ContextTest, ScratchDuringCollection) {
98125 int OtherFakeCalleeAddress = 0 ;
99126 __llvm_ctx_profile_expected_callee[0 ] = &FakeCalleeAddress;
100127 __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 );
103131 // We expected a different callee - so return scratch. It mimics what happens
104132 // in the case of a signal handler - in this case, OtherFakeCalleeAddress is
105133 // the signal handler.
106134 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 );
107138 EXPECT_EQ (__llvm_ctx_profile_expected_callee[0 ], nullptr );
108139 EXPECT_EQ (__llvm_ctx_profile_callsite[0 ], nullptr );
109140
110141 int ThirdFakeCalleeAddress = 0 ;
111142 __llvm_ctx_profile_expected_callee[1 ] = &ThirdFakeCalleeAddress;
112143 __llvm_ctx_profile_callsite[1 ] = &Subctx->subContexts ()[0 ];
113144
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 );
116147 // We again expect scratch because the '0' position is where the runtime
117148 // looks, so it doesn't matter the '1' position is populated correctly.
118149 EXPECT_TRUE (isScratch (Subctx2));
150+ EXPECT_EQ (FData[1 ].FlatCtx , nullptr );
119151
120152 __llvm_ctx_profile_expected_callee[0 ] = &ThirdFakeCalleeAddress;
121153 __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 );
124156 // We expect scratch here, too, because the value placed in
125157 // __llvm_ctx_profile_callsite is scratch
126158 EXPECT_TRUE (isScratch (Subctx3));
159+ EXPECT_EQ (FData[2 ].FlatCtx , nullptr );
127160
128161 __llvm_ctx_profile_release_context (&Root);
129162}
@@ -136,9 +169,11 @@ TEST_F(ContextTest, NeedMoreMemory) {
136169 const auto *CurrentMem = Root.CurrentMem ;
137170 __llvm_ctx_profile_expected_callee[0 ] = &FakeCalleeAddress;
138171 __llvm_ctx_profile_callsite[0 ] = &Ctx->subContexts ()[2 ];
172+ FunctionData FData = {0 };
139173 // Allocate a massive subcontext to force new arena allocation
140174 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 );
142177 EXPECT_EQ (Ctx->subContexts ()[2 ], Subctx);
143178 EXPECT_NE (CurrentMem, Root.CurrentMem );
144179 EXPECT_NE (Root.CurrentMem , nullptr );
@@ -175,7 +210,9 @@ TEST_F(ContextTest, Dump) {
175210 int FakeCalleeAddress = 0 ;
176211 __llvm_ctx_profile_expected_callee[0 ] = &FakeCalleeAddress;
177212 __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 );
179216 (void )Subctx;
180217 __llvm_ctx_profile_release_context (&Root);
181218
@@ -186,6 +223,9 @@ TEST_F(ContextTest, Dump) {
186223
187224 int EnteredSectionCount = 0 ;
188225 int ExitedSectionCount = 0 ;
226+ int EnteredFlatCount = 0 ;
227+ int ExitedFlatCount = 0 ;
228+ int FlatsWritten = 0 ;
189229
190230 bool State = false ;
191231
@@ -217,6 +257,16 @@ TEST_F(ContextTest, Dump) {
217257 EXPECT_EQ (EnteredSectionCount, 1 );
218258 ++ExitedSectionCount;
219259 }
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; }
220270 };
221271
222272 TestProfileWriter W (&Root, 1 );
@@ -226,10 +276,17 @@ TEST_F(ContextTest, Dump) {
226276
227277 // this resets all counters but not the internal structure.
228278 __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 ;
229283 TestProfileWriter W2 (&Root, 0 );
230284 EXPECT_FALSE (W2.State );
231285 __llvm_ctx_profile_fetch (W2);
232286 EXPECT_TRUE (W2.State );
233287 EXPECT_EQ (W2.EnteredSectionCount , 1 );
234288 EXPECT_EQ (W2.ExitedSectionCount , 1 );
289+ EXPECT_EQ (W2.EnteredFlatCount , 1 );
290+ EXPECT_EQ (W2.FlatsWritten , 1 );
291+ EXPECT_EQ (W2.ExitedFlatCount , 1 );
235292}
0 commit comments