1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_LIBARTBASE_BASE_DEBUG_STACK_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_LIBARTBASE_BASE_DEBUG_STACK_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h> 21*795d594fSAndroid Build Coastguard Worker #include <android-base/macros.h> 22*795d594fSAndroid Build Coastguard Worker 23*795d594fSAndroid Build Coastguard Worker #include "globals.h" 24*795d594fSAndroid Build Coastguard Worker 25*795d594fSAndroid Build Coastguard Worker namespace art { 26*795d594fSAndroid Build Coastguard Worker 27*795d594fSAndroid Build Coastguard Worker // Helper classes for reference counting to enforce construction/destruction order and 28*795d594fSAndroid Build Coastguard Worker // usage of the top element of a stack in debug mode with no overhead in release mode. 29*795d594fSAndroid Build Coastguard Worker 30*795d594fSAndroid Build Coastguard Worker // Reference counter. No references allowed in destructor or in explicitly called CheckNoRefs(). 31*795d594fSAndroid Build Coastguard Worker template <bool kIsDebug> 32*795d594fSAndroid Build Coastguard Worker class DebugStackRefCounterImpl; 33*795d594fSAndroid Build Coastguard Worker // Reference. Allows an explicit check that it's the top reference. 34*795d594fSAndroid Build Coastguard Worker template <bool kIsDebug> 35*795d594fSAndroid Build Coastguard Worker class DebugStackReferenceImpl; 36*795d594fSAndroid Build Coastguard Worker // Indirect top reference. Checks that the reference is the top reference when used. 37*795d594fSAndroid Build Coastguard Worker template <bool kIsDebug> 38*795d594fSAndroid Build Coastguard Worker class DebugStackIndirectTopRefImpl; 39*795d594fSAndroid Build Coastguard Worker 40*795d594fSAndroid Build Coastguard Worker using DebugStackRefCounter = DebugStackRefCounterImpl<kIsDebugBuild>; 41*795d594fSAndroid Build Coastguard Worker using DebugStackReference = DebugStackReferenceImpl<kIsDebugBuild>; 42*795d594fSAndroid Build Coastguard Worker using DebugStackIndirectTopRef = DebugStackIndirectTopRefImpl<kIsDebugBuild>; 43*795d594fSAndroid Build Coastguard Worker 44*795d594fSAndroid Build Coastguard Worker // Non-debug mode specializations. This should be optimized away. 45*795d594fSAndroid Build Coastguard Worker 46*795d594fSAndroid Build Coastguard Worker template <> 47*795d594fSAndroid Build Coastguard Worker class DebugStackRefCounterImpl<false> { 48*795d594fSAndroid Build Coastguard Worker public: IncrementRefCount()49*795d594fSAndroid Build Coastguard Worker size_t IncrementRefCount() { return 0u; } DecrementRefCount()50*795d594fSAndroid Build Coastguard Worker void DecrementRefCount() { } GetRefCount()51*795d594fSAndroid Build Coastguard Worker size_t GetRefCount() const { return 0u; } CheckNoRefs()52*795d594fSAndroid Build Coastguard Worker void CheckNoRefs() const { } 53*795d594fSAndroid Build Coastguard Worker }; 54*795d594fSAndroid Build Coastguard Worker 55*795d594fSAndroid Build Coastguard Worker template <> 56*795d594fSAndroid Build Coastguard Worker class DebugStackReferenceImpl<false> { 57*795d594fSAndroid Build Coastguard Worker public: DebugStackReferenceImpl(DebugStackRefCounterImpl<false> * counter)58*795d594fSAndroid Build Coastguard Worker explicit DebugStackReferenceImpl([[maybe_unused]] DebugStackRefCounterImpl<false>* counter) {} 59*795d594fSAndroid Build Coastguard Worker DebugStackReferenceImpl(const DebugStackReferenceImpl& other) = default; 60*795d594fSAndroid Build Coastguard Worker DebugStackReferenceImpl& operator=(const DebugStackReferenceImpl& other) = default; CheckTop()61*795d594fSAndroid Build Coastguard Worker void CheckTop() { } 62*795d594fSAndroid Build Coastguard Worker }; 63*795d594fSAndroid Build Coastguard Worker 64*795d594fSAndroid Build Coastguard Worker template <> 65*795d594fSAndroid Build Coastguard Worker class DebugStackIndirectTopRefImpl<false> { 66*795d594fSAndroid Build Coastguard Worker public: DebugStackIndirectTopRefImpl(DebugStackReferenceImpl<false> * ref)67*795d594fSAndroid Build Coastguard Worker explicit DebugStackIndirectTopRefImpl([[maybe_unused]] DebugStackReferenceImpl<false>* ref) {} 68*795d594fSAndroid Build Coastguard Worker DebugStackIndirectTopRefImpl(const DebugStackIndirectTopRefImpl& other) = default; 69*795d594fSAndroid Build Coastguard Worker DebugStackIndirectTopRefImpl& operator=(const DebugStackIndirectTopRefImpl& other) = default; CheckTop()70*795d594fSAndroid Build Coastguard Worker void CheckTop() { } 71*795d594fSAndroid Build Coastguard Worker }; 72*795d594fSAndroid Build Coastguard Worker 73*795d594fSAndroid Build Coastguard Worker // Debug mode versions. 74*795d594fSAndroid Build Coastguard Worker 75*795d594fSAndroid Build Coastguard Worker template <bool kIsDebug> 76*795d594fSAndroid Build Coastguard Worker class DebugStackRefCounterImpl { 77*795d594fSAndroid Build Coastguard Worker public: DebugStackRefCounterImpl()78*795d594fSAndroid Build Coastguard Worker DebugStackRefCounterImpl() : ref_count_(0u) { } ~DebugStackRefCounterImpl()79*795d594fSAndroid Build Coastguard Worker ~DebugStackRefCounterImpl() { CheckNoRefs(); } IncrementRefCount()80*795d594fSAndroid Build Coastguard Worker size_t IncrementRefCount() { return ++ref_count_; } DecrementRefCount()81*795d594fSAndroid Build Coastguard Worker void DecrementRefCount() { --ref_count_; } GetRefCount()82*795d594fSAndroid Build Coastguard Worker size_t GetRefCount() const { return ref_count_; } CheckNoRefs()83*795d594fSAndroid Build Coastguard Worker void CheckNoRefs() const { CHECK_EQ(ref_count_, 0u); } 84*795d594fSAndroid Build Coastguard Worker 85*795d594fSAndroid Build Coastguard Worker private: 86*795d594fSAndroid Build Coastguard Worker size_t ref_count_; 87*795d594fSAndroid Build Coastguard Worker }; 88*795d594fSAndroid Build Coastguard Worker 89*795d594fSAndroid Build Coastguard Worker template <bool kIsDebug> 90*795d594fSAndroid Build Coastguard Worker class DebugStackReferenceImpl { 91*795d594fSAndroid Build Coastguard Worker public: DebugStackReferenceImpl(DebugStackRefCounterImpl<kIsDebug> * counter)92*795d594fSAndroid Build Coastguard Worker explicit DebugStackReferenceImpl(DebugStackRefCounterImpl<kIsDebug>* counter) 93*795d594fSAndroid Build Coastguard Worker : counter_(counter), ref_count_(counter->IncrementRefCount()) { 94*795d594fSAndroid Build Coastguard Worker } DebugStackReferenceImpl(const DebugStackReferenceImpl & other)95*795d594fSAndroid Build Coastguard Worker DebugStackReferenceImpl(const DebugStackReferenceImpl& other) 96*795d594fSAndroid Build Coastguard Worker : counter_(other.counter_), ref_count_(counter_->IncrementRefCount()) { 97*795d594fSAndroid Build Coastguard Worker } DebugStackReferenceImpl(DebugStackReferenceImpl && other)98*795d594fSAndroid Build Coastguard Worker DebugStackReferenceImpl(DebugStackReferenceImpl&& other) noexcept 99*795d594fSAndroid Build Coastguard Worker : counter_(other.counter_), ref_count_(other.ref_count_) { 100*795d594fSAndroid Build Coastguard Worker other.counter_ = nullptr; 101*795d594fSAndroid Build Coastguard Worker } 102*795d594fSAndroid Build Coastguard Worker DebugStackReferenceImpl& operator=(const DebugStackReferenceImpl& other) { 103*795d594fSAndroid Build Coastguard Worker CHECK(counter_ == other.counter_); 104*795d594fSAndroid Build Coastguard Worker return *this; 105*795d594fSAndroid Build Coastguard Worker } ~DebugStackReferenceImpl()106*795d594fSAndroid Build Coastguard Worker ~DebugStackReferenceImpl() { 107*795d594fSAndroid Build Coastguard Worker if (counter_ != nullptr) { 108*795d594fSAndroid Build Coastguard Worker counter_->DecrementRefCount(); 109*795d594fSAndroid Build Coastguard Worker } 110*795d594fSAndroid Build Coastguard Worker } CheckTop()111*795d594fSAndroid Build Coastguard Worker void CheckTop() { CHECK_EQ(counter_->GetRefCount(), ref_count_); } 112*795d594fSAndroid Build Coastguard Worker 113*795d594fSAndroid Build Coastguard Worker private: 114*795d594fSAndroid Build Coastguard Worker DebugStackRefCounterImpl<true>* counter_; 115*795d594fSAndroid Build Coastguard Worker size_t ref_count_; 116*795d594fSAndroid Build Coastguard Worker }; 117*795d594fSAndroid Build Coastguard Worker 118*795d594fSAndroid Build Coastguard Worker template <bool kIsDebug> 119*795d594fSAndroid Build Coastguard Worker class DebugStackIndirectTopRefImpl { 120*795d594fSAndroid Build Coastguard Worker public: DebugStackIndirectTopRefImpl(DebugStackReferenceImpl<kIsDebug> * ref)121*795d594fSAndroid Build Coastguard Worker explicit DebugStackIndirectTopRefImpl(DebugStackReferenceImpl<kIsDebug>* ref) 122*795d594fSAndroid Build Coastguard Worker : ref_(ref) { 123*795d594fSAndroid Build Coastguard Worker CheckTop(); 124*795d594fSAndroid Build Coastguard Worker } DebugStackIndirectTopRefImpl(const DebugStackIndirectTopRefImpl & other)125*795d594fSAndroid Build Coastguard Worker DebugStackIndirectTopRefImpl(const DebugStackIndirectTopRefImpl& other) 126*795d594fSAndroid Build Coastguard Worker : ref_(other.ref_) { 127*795d594fSAndroid Build Coastguard Worker CheckTop(); 128*795d594fSAndroid Build Coastguard Worker } 129*795d594fSAndroid Build Coastguard Worker DebugStackIndirectTopRefImpl& operator=(const DebugStackIndirectTopRefImpl& other) { 130*795d594fSAndroid Build Coastguard Worker CHECK(ref_ == other.ref_); 131*795d594fSAndroid Build Coastguard Worker CheckTop(); 132*795d594fSAndroid Build Coastguard Worker return *this; 133*795d594fSAndroid Build Coastguard Worker } ~DebugStackIndirectTopRefImpl()134*795d594fSAndroid Build Coastguard Worker ~DebugStackIndirectTopRefImpl() { 135*795d594fSAndroid Build Coastguard Worker CheckTop(); 136*795d594fSAndroid Build Coastguard Worker } CheckTop()137*795d594fSAndroid Build Coastguard Worker void CheckTop() { 138*795d594fSAndroid Build Coastguard Worker ref_->CheckTop(); 139*795d594fSAndroid Build Coastguard Worker } 140*795d594fSAndroid Build Coastguard Worker 141*795d594fSAndroid Build Coastguard Worker private: 142*795d594fSAndroid Build Coastguard Worker DebugStackReferenceImpl<kIsDebug>* ref_; 143*795d594fSAndroid Build Coastguard Worker }; 144*795d594fSAndroid Build Coastguard Worker 145*795d594fSAndroid Build Coastguard Worker } // namespace art 146*795d594fSAndroid Build Coastguard Worker 147*795d594fSAndroid Build Coastguard Worker #endif // ART_LIBARTBASE_BASE_DEBUG_STACK_H_ 148