• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <random>
17 
18 #include "gtest/gtest.h"
19 #include "runtime/include/managed_thread.h"
20 #include "runtime/mark_word.cpp"
21 
22 namespace panda {
23 
24 class MarkWordTest : public testing::Test {
25 public:
MarkWordTest()26     MarkWordTest() {}
27 
28 protected:
SetUp()29     void SetUp() override
30     {
31         // Logger::InitializeStdLogging(Logger::Level::DEBUG, Logger::Component::ALL);
32     }
33 
TearDown()34     void TearDown() override
35     {
36         // Logger::Destroy();
37     }
38 
39     enum MarkWordFieldsMaxValues : MarkWord::markWordSize {
40         MAX_THREAD_ID = (1UL << MarkWord::MarkWordRepresentation::LIGHT_LOCK_THREADID_SIZE) - 1UL,
41         MAX_LOCK_COUNT = (1UL << MarkWord::MarkWordRepresentation::LIGHT_LOCK_LOCK_COUNT_SIZE) - 1UL,
42         MAX_MONITOR_ID = (1UL << MarkWord::MarkWordRepresentation::MONITOR_POINTER_SIZE) - 1UL,
43         MAX_HASH = (1UL << MarkWord::MarkWordRepresentation::HASH_SIZE) - 1UL,
44         MAX_FORWARDING_ADDRESS = std::numeric_limits<MarkWord::markWordSize>::max() &
45                                  MarkWord::MarkWordRepresentation::FORWARDING_ADDRESS_MASK_IN_PLACE,
46     };
47 
48     class RandomTestValuesGetter {
49     public:
50         using MarkWordDistribution = std::uniform_int_distribution<MarkWord::markWordSize>;
51 
RandomTestValuesGetter()52         RandomTestValuesGetter()
53         {
54 #ifdef PANDA_NIGHTLY_TEST_ON
55             seed_ = std::random_device()();
56 #else
57             seed_ = 0xC0E67D50;
58 #endif
59             gen_ = std::mt19937(seed_);
60 
61             threadIdRange_ = MarkWordDistribution(0, MAX_THREAD_ID);
62             lockCountRange_ = MarkWordDistribution(0, MAX_LOCK_COUNT);
63             monitorIdRange_ = MarkWordDistribution(0, MAX_MONITOR_ID);
64             hashRange_ = MarkWordDistribution(0, MAX_HASH);
65             forwardingAddressRange_ = MarkWordDistribution(0, MAX_FORWARDING_ADDRESS);
66         }
67 
GetThreadId()68         ManagedThread::ThreadId GetThreadId()
69         {
70             return threadIdRange_(gen_);
71         }
72 
GetLockCount()73         uint32_t GetLockCount()
74         {
75             return lockCountRange_(gen_);
76         }
77 
GetMonitorId()78         Monitor::MonitorId GetMonitorId()
79         {
80             return monitorIdRange_(gen_);
81         }
82 
GetHash()83         uint32_t GetHash()
84         {
85             return hashRange_(gen_);
86         }
87 
GetForwardingAddress()88         MarkWord::markWordSize GetForwardingAddress()
89         {
90             return forwardingAddressRange_(gen_) & MarkWord::MarkWordRepresentation::FORWARDING_ADDRESS_MASK_IN_PLACE;
91         }
92 
GetSeed()93         uint32_t GetSeed()
94         {
95             return seed_;
96         }
97 
98     private:
99         uint32_t seed_;
100         std::mt19937 gen_;
101         MarkWordDistribution threadIdRange_;
102         MarkWordDistribution lockCountRange_;
103         MarkWordDistribution monitorIdRange_;
104         MarkWordDistribution hashRange_;
105         MarkWordDistribution forwardingAddressRange_;
106     };
107 
108     class MaxTestValuesGetter {
109     public:
GetThreadId() const110         ManagedThread::ThreadId GetThreadId() const
111         {
112             return MAX_THREAD_ID;
113         }
114 
GetLockCount() const115         uint32_t GetLockCount() const
116         {
117             return MAX_LOCK_COUNT;
118         }
119 
GetMonitorId() const120         Monitor::MonitorId GetMonitorId() const
121         {
122             return static_cast<Monitor::MonitorId>(MAX_MONITOR_ID);
123         }
124 
GetHash() const125         uint32_t GetHash() const
126         {
127             return static_cast<uint32_t>(MAX_HASH);
128         }
129 
GetForwardingAddress() const130         MarkWord::markWordSize GetForwardingAddress() const
131         {
132             return MAX_FORWARDING_ADDRESS;
133         }
134 
GetSeed() const135         uint32_t GetSeed() const
136         {
137             // We don't have a seed for this case
138             return 0;
139         }
140     };
141 
142     template <class Getter>
143     class MarkWordWrapper {
144     public:
MarkWordWrapper(bool isMarkedForGC=false,bool isReadBarrierSet=false)145         MarkWordWrapper(bool isMarkedForGC = false, bool isReadBarrierSet = false)
146         {
147             if (isMarkedForGC) {
148                 mw_ = mw_.SetMarkedForGC();
149             }
150             if (isReadBarrierSet) {
151                 mw_ = mw_.SetReadBarrier();
152             }
153         };
154 
CheckUnlocked(bool isMarkedForGC=false,bool isReadBarrierSet=false)155         void CheckUnlocked(bool isMarkedForGC = false, bool isReadBarrierSet = false)
156         {
157             ASSERT_EQ(mw_.GetState(), MarkWord::ObjectState::STATE_UNLOCKED) << " seed = " << paramGetter_.GetSeed();
158             ASSERT_EQ(mw_.IsMarkedForGC(), isMarkedForGC) << " seed = " << paramGetter_.GetSeed();
159             ASSERT_EQ(mw_.IsReadBarrierSet(), isReadBarrierSet) << " seed = " << paramGetter_.GetSeed();
160         }
161 
CheckLightweightLock(const ManagedThread::ThreadId tId,const uint32_t lockCount,bool isMarkedForGC,bool isReadBarrierSet=false)162         void CheckLightweightLock(const ManagedThread::ThreadId tId, const uint32_t lockCount, bool isMarkedForGC,
163                                   bool isReadBarrierSet = false)
164         {
165             ASSERT_EQ(mw_.GetState(), MarkWord::ObjectState::STATE_LIGHT_LOCKED)
166                 << " seed = " << paramGetter_.GetSeed();
167             ASSERT_EQ(mw_.GetThreadId(), tId) << " seed = " << paramGetter_.GetSeed();
168             ASSERT_EQ(mw_.GetLockCount(), lockCount) << " seed = " << paramGetter_.GetSeed();
169             ASSERT_EQ(mw_.IsMarkedForGC(), isMarkedForGC) << " seed = " << paramGetter_.GetSeed();
170             ASSERT_EQ(mw_.IsReadBarrierSet(), isReadBarrierSet) << " seed = " << paramGetter_.GetSeed();
171         }
172 
CheckHeavyweightLock(const Monitor::MonitorId mId,bool isMarkedForGC,bool isReadBarrierSet=false)173         void CheckHeavyweightLock(const Monitor::MonitorId mId, bool isMarkedForGC, bool isReadBarrierSet = false)
174         {
175             ASSERT_EQ(mw_.GetState(), MarkWord::ObjectState::STATE_HEAVY_LOCKED)
176                 << " seed = " << paramGetter_.GetSeed();
177             ASSERT_EQ(mw_.GetMonitorId(), mId) << " seed = " << paramGetter_.GetSeed();
178             ASSERT_EQ(mw_.IsMarkedForGC(), isMarkedForGC) << " seed = " << paramGetter_.GetSeed();
179             ASSERT_EQ(mw_.IsReadBarrierSet(), isReadBarrierSet) << " seed = " << paramGetter_.GetSeed();
180         }
181 
CheckHashed(uint32_t hash,bool isMarkedForGC,bool isReadBarrierSet=false)182         void CheckHashed(uint32_t hash, bool isMarkedForGC, bool isReadBarrierSet = false)
183         {
184             if (mw_.CONFIG_IS_HASH_IN_OBJ_HEADER) {
185                 ASSERT_EQ(mw_.GetState(), MarkWord::ObjectState::STATE_HASHED) << " seed = " << paramGetter_.GetSeed();
186                 ASSERT_EQ(mw_.GetHash(), hash) << " seed = " << paramGetter_.GetSeed();
187                 ASSERT_EQ(mw_.IsMarkedForGC(), isMarkedForGC) << " seed = " << paramGetter_.GetSeed();
188                 ASSERT_EQ(mw_.IsReadBarrierSet(), isReadBarrierSet) << " seed = " << paramGetter_.GetSeed();
189             }
190         }
191 
CheckGC(MarkWord::markWordSize forwardingAddress)192         void CheckGC(MarkWord::markWordSize forwardingAddress)
193         {
194             ASSERT_EQ(mw_.GetState(), MarkWord::ObjectState::STATE_GC) << " seed = " << paramGetter_.GetSeed();
195             ASSERT_EQ(mw_.GetForwardingAddress(), forwardingAddress) << " seed = " << paramGetter_.GetSeed();
196         }
197 
DecodeLightLock(ManagedThread::ThreadId tId,uint32_t lCount)198         void DecodeLightLock(ManagedThread::ThreadId tId, uint32_t lCount)
199         {
200             mw_ = mw_.DecodeFromLightLock(tId, lCount);
201         }
202 
DecodeHeavyLock(Monitor::MonitorId mId)203         void DecodeHeavyLock(Monitor::MonitorId mId)
204         {
205             mw_ = mw_.DecodeFromMonitor(mId);
206         }
207 
DecodeHash(uint32_t hash)208         void DecodeHash(uint32_t hash)
209         {
210             mw_ = mw_.DecodeFromHash(hash);
211         }
212 
DecodeForwardingAddress(MarkWord::markWordSize fAddress)213         void DecodeForwardingAddress(MarkWord::markWordSize fAddress)
214         {
215             mw_ = mw_.DecodeFromForwardingAddress(fAddress);
216         }
217 
DecodeAndCheckLightLock(bool isMarkedForGC=false,bool isReadBarrierSet=false)218         void DecodeAndCheckLightLock(bool isMarkedForGC = false, bool isReadBarrierSet = false)
219         {
220             auto tId = paramGetter_.GetThreadId();
221             auto lCount = paramGetter_.GetLockCount();
222             DecodeLightLock(tId, lCount);
223             CheckLightweightLock(tId, lCount, isMarkedForGC, isReadBarrierSet);
224         }
225 
DecodeAndCheckHeavyLock(bool isMarkedForGC=false,bool isReadBarrierSet=false)226         void DecodeAndCheckHeavyLock(bool isMarkedForGC = false, bool isReadBarrierSet = false)
227         {
228             auto mId = paramGetter_.GetMonitorId();
229             DecodeHeavyLock(mId);
230             CheckHeavyweightLock(mId, isMarkedForGC, isReadBarrierSet);
231         }
232 
DecodeAndCheckHashed(bool isMarkedForGC=false,bool isReadBarrierSet=false)233         void DecodeAndCheckHashed(bool isMarkedForGC = false, bool isReadBarrierSet = false)
234         {
235             auto hash = paramGetter_.GetHash();
236             DecodeHash(hash);
237             CheckHashed(hash, isMarkedForGC, isReadBarrierSet);
238         }
239 
DecodeAndCheckGC()240         void DecodeAndCheckGC()
241         {
242             auto fAddress = paramGetter_.GetForwardingAddress();
243             DecodeForwardingAddress(fAddress);
244             CheckGC(fAddress);
245         }
246 
SetMarkedForGC()247         void SetMarkedForGC()
248         {
249             mw_ = mw_.SetMarkedForGC();
250         }
251 
SetReadBarrier()252         void SetReadBarrier()
253         {
254             mw_ = mw_.SetReadBarrier();
255         }
256 
257     private:
258         MarkWord mw_;
259         Getter paramGetter_;
260     };
261 
262     template <class Getter>
263     void CheckMakeHashed(bool isMarkedForGC, bool isReadBarrierSet);
264 
265     template <class Getter>
266     void CheckMakeLightweightLock(bool isMarkedForGC, bool isReadBarrierSet);
267 
268     template <class Getter>
269     void CheckMakeHeavyweightLock(bool isMarkedForGC, bool isReadBarrierSet);
270 
271     template <class Getter>
272     void CheckMakeGC();
273 
274     template <class Getter>
275     void CheckMarkingWithGC();
276 
277     template <class Getter>
278     void CheckReadBarrierSet();
279 };
280 
281 template <class Getter>
CheckMakeHashed(bool isMarkedForGC,bool isReadBarrierSet)282 void MarkWordTest::CheckMakeHashed(bool isMarkedForGC, bool isReadBarrierSet)
283 {
284     // nothing, gc = markedForGC, rb = readBarrierSet, state = unlocked
285     MarkWordWrapper<Getter> wrapper(isMarkedForGC, isReadBarrierSet);
286 
287     // check new hash
288     wrapper.DecodeAndCheckHashed(isMarkedForGC, isReadBarrierSet);
289     wrapper.DecodeAndCheckHashed(isMarkedForGC, isReadBarrierSet);
290 
291     // check after lightweight lock
292     wrapper.DecodeAndCheckLightLock(isMarkedForGC, isReadBarrierSet);
293     wrapper.DecodeAndCheckHashed(isMarkedForGC, isReadBarrierSet);
294 
295     // check after heavyweight lock
296     wrapper.DecodeAndCheckHeavyLock(isMarkedForGC, isReadBarrierSet);
297     wrapper.DecodeAndCheckHashed(isMarkedForGC, isReadBarrierSet);
298 }
299 
TEST_F(MarkWordTest,CreateHashedWithRandValues)300 TEST_F(MarkWordTest, CreateHashedWithRandValues)
301 {
302     CheckMakeHashed<RandomTestValuesGetter>(false, false);
303     CheckMakeHashed<RandomTestValuesGetter>(false, true);
304     CheckMakeHashed<RandomTestValuesGetter>(true, false);
305     CheckMakeHashed<RandomTestValuesGetter>(true, true);
306 }
307 
TEST_F(MarkWordTest,CreateHashedWithMaxValues)308 TEST_F(MarkWordTest, CreateHashedWithMaxValues)
309 {
310     CheckMakeHashed<MaxTestValuesGetter>(false, false);
311     CheckMakeHashed<MaxTestValuesGetter>(false, true);
312     CheckMakeHashed<MaxTestValuesGetter>(true, false);
313     CheckMakeHashed<MaxTestValuesGetter>(true, true);
314 }
315 
316 template <class Getter>
CheckMakeLightweightLock(bool isMarkedForGC,bool isReadBarrierSet)317 void MarkWordTest::CheckMakeLightweightLock(bool isMarkedForGC, bool isReadBarrierSet)
318 {
319     // nothing, gc = markedForGC, rb = readBarrierSet, state = unlocked
320     MarkWordWrapper<Getter> wrapper(isMarkedForGC, isReadBarrierSet);
321 
322     // check new lightweight lock
323     wrapper.DecodeAndCheckLightLock(isMarkedForGC, isReadBarrierSet);
324     wrapper.DecodeAndCheckLightLock(isMarkedForGC, isReadBarrierSet);
325 
326     // check after hash
327     wrapper.DecodeAndCheckHashed(isMarkedForGC, isReadBarrierSet);
328     wrapper.DecodeAndCheckLightLock(isMarkedForGC, isReadBarrierSet);
329 
330     // check after heavyweight lock
331     wrapper.DecodeAndCheckHeavyLock(isMarkedForGC, isReadBarrierSet);
332     wrapper.DecodeAndCheckLightLock(isMarkedForGC, isReadBarrierSet);
333 }
334 
TEST_F(MarkWordTest,CreateLightweightLockWithRandValues)335 TEST_F(MarkWordTest, CreateLightweightLockWithRandValues)
336 {
337     CheckMakeLightweightLock<RandomTestValuesGetter>(false, false);
338     CheckMakeLightweightLock<RandomTestValuesGetter>(false, true);
339     CheckMakeLightweightLock<RandomTestValuesGetter>(true, false);
340     CheckMakeLightweightLock<RandomTestValuesGetter>(true, true);
341 }
342 
TEST_F(MarkWordTest,CreateLightweightLockWithMaxValues)343 TEST_F(MarkWordTest, CreateLightweightLockWithMaxValues)
344 {
345     CheckMakeLightweightLock<MaxTestValuesGetter>(false, false);
346     CheckMakeLightweightLock<MaxTestValuesGetter>(false, true);
347     CheckMakeLightweightLock<MaxTestValuesGetter>(true, false);
348     CheckMakeLightweightLock<MaxTestValuesGetter>(true, true);
349 }
350 
351 template <class Getter>
CheckMakeHeavyweightLock(bool isMarkedForGC,bool isReadBarrierSet)352 void MarkWordTest::CheckMakeHeavyweightLock(bool isMarkedForGC, bool isReadBarrierSet)
353 {
354     // nothing, gc = markedForGC, rb = readBarrierSet, state = unlocked
355     MarkWordWrapper<Getter> wrapper(isMarkedForGC, isReadBarrierSet);
356 
357     // check new heavyweight lock
358     wrapper.DecodeAndCheckHeavyLock(isMarkedForGC, isReadBarrierSet);
359     wrapper.DecodeAndCheckHeavyLock(isMarkedForGC, isReadBarrierSet);
360 
361     // check after hash
362     wrapper.DecodeAndCheckHashed(isMarkedForGC, isReadBarrierSet);
363     wrapper.DecodeAndCheckHeavyLock(isMarkedForGC, isReadBarrierSet);
364 
365     // check after lightweight lock
366     wrapper.DecodeAndCheckLightLock(isMarkedForGC, isReadBarrierSet);
367     wrapper.DecodeAndCheckHeavyLock(isMarkedForGC, isReadBarrierSet);
368 }
369 
TEST_F(MarkWordTest,CreateHeavyweightLockWithRandValues)370 TEST_F(MarkWordTest, CreateHeavyweightLockWithRandValues)
371 {
372     CheckMakeHeavyweightLock<RandomTestValuesGetter>(false, false);
373     CheckMakeHeavyweightLock<RandomTestValuesGetter>(false, true);
374     CheckMakeHeavyweightLock<RandomTestValuesGetter>(true, false);
375     CheckMakeHeavyweightLock<RandomTestValuesGetter>(true, true);
376 }
377 
TEST_F(MarkWordTest,CreateHeavyweightLockWithMaxValues)378 TEST_F(MarkWordTest, CreateHeavyweightLockWithMaxValues)
379 {
380     CheckMakeHeavyweightLock<MaxTestValuesGetter>(false, false);
381     CheckMakeHeavyweightLock<MaxTestValuesGetter>(false, true);
382     CheckMakeHeavyweightLock<MaxTestValuesGetter>(true, false);
383     CheckMakeHeavyweightLock<MaxTestValuesGetter>(true, true);
384 }
385 
386 template <class Getter>
CheckMakeGC()387 void MarkWordTest::CheckMakeGC()
388 {
389     // check new gc
390     {
391         MarkWordWrapper<Getter> wrapper;
392         wrapper.DecodeAndCheckGC();
393         wrapper.DecodeAndCheckGC();
394     }
395 
396     // check after hash
397     {
398         MarkWordWrapper<Getter> wrapper;
399         wrapper.DecodeAndCheckHashed();
400         wrapper.DecodeAndCheckGC();
401     }
402 
403     // check after lightweight lock
404     {
405         MarkWordWrapper<Getter> wrapper;
406         wrapper.DecodeAndCheckLightLock();
407         wrapper.DecodeAndCheckGC();
408     }
409 
410     // check after heavyweight lock
411     {
412         MarkWordWrapper<Getter> wrapper;
413         wrapper.DecodeAndCheckHeavyLock();
414         wrapper.DecodeAndCheckGC();
415     }
416 }
417 
TEST_F(MarkWordTest,CreateGCWithRandomValues)418 TEST_F(MarkWordTest, CreateGCWithRandomValues)
419 {
420     CheckMakeGC<RandomTestValuesGetter>();
421 }
422 
TEST_F(MarkWordTest,CreateGCWithMaxValues)423 TEST_F(MarkWordTest, CreateGCWithMaxValues)
424 {
425     CheckMakeGC<MaxTestValuesGetter>();
426 }
427 
428 template <class Getter>
CheckMarkingWithGC()429 void MarkWordTest::CheckMarkingWithGC()
430 {
431     Getter paramGetter;
432 
433     // with unlocked
434     {
435         MarkWordWrapper<Getter> wrapper;
436 
437         wrapper.SetMarkedForGC();
438         wrapper.CheckUnlocked(true);
439     }
440 
441     // with lightweight locked
442     {
443         MarkWordWrapper<Getter> wrapper;
444         auto tId = paramGetter.GetThreadId();
445         auto lCount = paramGetter.GetLockCount();
446         wrapper.DecodeLightLock(tId, lCount);
447 
448         wrapper.SetMarkedForGC();
449         wrapper.CheckLightweightLock(tId, lCount, true);
450     }
451 
452     // with heavyweight locked
453     {
454         MarkWordWrapper<Getter> wrapper;
455         auto mId = paramGetter.GetMonitorId();
456         wrapper.DecodeHeavyLock(mId);
457 
458         wrapper.SetMarkedForGC();
459         wrapper.CheckHeavyweightLock(mId, true);
460     }
461 
462     // with hashed
463     {
464         MarkWordWrapper<Getter> wrapper;
465         auto hash = paramGetter.GetHash();
466         wrapper.DecodeHash(hash);
467 
468         wrapper.SetMarkedForGC();
469         wrapper.CheckHashed(hash, true);
470     }
471 }
472 
TEST_F(MarkWordTest,MarkWithGCWithRandValues)473 TEST_F(MarkWordTest, MarkWithGCWithRandValues)
474 {
475     CheckMarkingWithGC<RandomTestValuesGetter>();
476 }
477 
TEST_F(MarkWordTest,MarkWithGCWithMaxValues)478 TEST_F(MarkWordTest, MarkWithGCWithMaxValues)
479 {
480     CheckMarkingWithGC<MaxTestValuesGetter>();
481 }
482 
483 template <class Getter>
CheckReadBarrierSet()484 void MarkWordTest::CheckReadBarrierSet()
485 {
486     Getter paramGetter;
487 
488     // with unlocked
489     {
490         MarkWordWrapper<Getter> wrapper;
491 
492         wrapper.SetReadBarrier();
493         wrapper.CheckUnlocked(false, true);
494     }
495 
496     // with lightweight locked
497     {
498         MarkWordWrapper<Getter> wrapper;
499         auto tId = paramGetter.GetThreadId();
500         auto lCount = paramGetter.GetLockCount();
501         wrapper.DecodeLightLock(tId, lCount);
502 
503         wrapper.SetReadBarrier();
504         wrapper.CheckLightweightLock(tId, lCount, false, true);
505     }
506 
507     // with heavyweight locked
508     {
509         MarkWordWrapper<Getter> wrapper;
510         auto mId = paramGetter.GetMonitorId();
511         wrapper.DecodeHeavyLock(mId);
512 
513         wrapper.SetReadBarrier();
514         wrapper.CheckHeavyweightLock(mId, false, true);
515     }
516 
517     // with hashed
518     {
519         MarkWordWrapper<Getter> wrapper;
520         auto hash = paramGetter.GetHash();
521         wrapper.DecodeHash(hash);
522 
523         wrapper.SetReadBarrier();
524         wrapper.CheckHashed(hash, false, true);
525     }
526 }
527 
TEST_F(MarkWordTest,ReadBarrierSetWithRandValues)528 TEST_F(MarkWordTest, ReadBarrierSetWithRandValues)
529 {
530     CheckReadBarrierSet<RandomTestValuesGetter>();
531 }
532 
TEST_F(MarkWordTest,ReadBarrierSetWithMaxValues)533 TEST_F(MarkWordTest, ReadBarrierSetWithMaxValues)
534 {
535     CheckReadBarrierSet<MaxTestValuesGetter>();
536 }
537 
538 }  //  namespace panda
539