183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko/* 283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * Copyright (C) 2014 The Android Open Source Project 383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * 483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * Licensed under the Apache License, Version 2.0 (the "License"); 583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * you may not use this file except in compliance with the License. 683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * You may obtain a copy of the License at 783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * 883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * http://www.apache.org/licenses/LICENSE-2.0 983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * 1083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * Unless required by applicable law or agreed to in writing, software 1183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * distributed under the License is distributed on an "AS IS" BASIS, 1283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * See the License for the specific language governing permissions and 1483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * limitations under the License. 1583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko */ 1683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 1783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko#ifndef ART_COMPILER_UTILS_DEBUG_STACK_H_ 1883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko#define ART_COMPILER_UTILS_DEBUG_STACK_H_ 1983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 2083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko#include "base/logging.h" 2183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko#include "base/macros.h" 2283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko#include "globals.h" 2383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 2483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markonamespace art { 2583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 2683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko// Helper classes for reference counting to enforce construction/destruction order and 2783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko// usage of the top element of a stack in debug mode with no overhead in release mode. 2883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 2983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko// Reference counter. No references allowed in destructor or in explicitly called CheckNoRefs(). 3083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markotemplate <bool kIsDebug> 3183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markoclass DebugStackRefCounterImpl; 3283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko// Reference. Allows an explicit check that it's the top reference. 3383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markotemplate <bool kIsDebug> 3483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markoclass DebugStackReferenceImpl; 3583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko// Indirect top reference. Checks that the reference is the top reference when used. 3683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markotemplate <bool kIsDebug> 3783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markoclass DebugStackIndirectTopRefImpl; 3883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 3983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markotypedef DebugStackRefCounterImpl<kIsDebugBuild> DebugStackRefCounter; 4083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markotypedef DebugStackReferenceImpl<kIsDebugBuild> DebugStackReference; 4183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markotypedef DebugStackIndirectTopRefImpl<kIsDebugBuild> DebugStackIndirectTopRef; 4283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 4383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko// Non-debug mode specializations. This should be optimized away. 4483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 4583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markotemplate <> 4683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markoclass DebugStackRefCounterImpl<false> { 4783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko public: 4883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko size_t IncrementRefCount() { return 0u; } 4983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko void DecrementRefCount() { } 5083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko size_t GetRefCount() const { return 0u; } 5183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko void CheckNoRefs() const { } 5283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko}; 5383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 5483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markotemplate <> 5583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markoclass DebugStackReferenceImpl<false> { 5683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko public: 5783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko explicit DebugStackReferenceImpl(DebugStackRefCounterImpl<false>* counter) { UNUSED(counter); } 5883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko DebugStackReferenceImpl(const DebugStackReferenceImpl& other) = default; 5983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko DebugStackReferenceImpl& operator=(const DebugStackReferenceImpl& other) = default; 6083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko void CheckTop() { } 6183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko}; 6283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 6383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markotemplate <> 6483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markoclass DebugStackIndirectTopRefImpl<false> { 6583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko public: 6683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko explicit DebugStackIndirectTopRefImpl(DebugStackReferenceImpl<false>* ref) { UNUSED(ref); } 6783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko DebugStackIndirectTopRefImpl(const DebugStackIndirectTopRefImpl& other) = default; 6883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko DebugStackIndirectTopRefImpl& operator=(const DebugStackIndirectTopRefImpl& other) = default; 6983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko void CheckTop() { } 7083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko}; 7183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 7283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko// Debug mode versions. 7383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 7483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markotemplate <bool kIsDebug> 7583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markoclass DebugStackRefCounterImpl { 7683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko public: 7783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko DebugStackRefCounterImpl() : ref_count_(0u) { } 7883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko ~DebugStackRefCounterImpl() { CheckNoRefs(); } 7983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko size_t IncrementRefCount() { return ++ref_count_; } 8083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko void DecrementRefCount() { --ref_count_; } 8183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko size_t GetRefCount() const { return ref_count_; } 8283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko void CheckNoRefs() const { CHECK_EQ(ref_count_, 0u); } 8383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 8483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko private: 8583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko size_t ref_count_; 8683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko}; 8783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 8883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markotemplate <bool kIsDebug> 8983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markoclass DebugStackReferenceImpl { 9083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko public: 9183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko explicit DebugStackReferenceImpl(DebugStackRefCounterImpl<kIsDebug>* counter) 9283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko : counter_(counter), ref_count_(counter->IncrementRefCount()) { 9383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko } 9483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko DebugStackReferenceImpl(const DebugStackReferenceImpl& other) 9583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko : counter_(other.counter_), ref_count_(counter_->IncrementRefCount()) { 9683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko } 9783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko DebugStackReferenceImpl& operator=(const DebugStackReferenceImpl& other) { 9883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko CHECK(counter_ == other.counter_); 9983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko return *this; 10083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko } 10183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko ~DebugStackReferenceImpl() { counter_->DecrementRefCount(); } 10283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko void CheckTop() { CHECK_EQ(counter_->GetRefCount(), ref_count_); } 10383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 10483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko private: 10583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko DebugStackRefCounterImpl<true>* counter_; 10683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko size_t ref_count_; 10783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko}; 10883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 10983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markotemplate <bool kIsDebug> 11083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markoclass DebugStackIndirectTopRefImpl { 11183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko public: 11283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko explicit DebugStackIndirectTopRefImpl(DebugStackReferenceImpl<kIsDebug>* ref) 11383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko : ref_(ref) { 11483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko CheckTop(); 11583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko } 11683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko DebugStackIndirectTopRefImpl(const DebugStackIndirectTopRefImpl& other) 11783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko : ref_(other.ref_) { 11883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko CheckTop(); 11983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko } 12083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko DebugStackIndirectTopRefImpl& operator=(const DebugStackIndirectTopRefImpl& other) { 12169f08baaa4b70ce32a258f3da43cf12f2a034696Vladimir Marko CHECK(ref_ == other.ref_); 12283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko CheckTop(); 12383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko return *this; 12483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko } 12583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko ~DebugStackIndirectTopRefImpl() { 12683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko CheckTop(); 12783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko } 12883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko void CheckTop() { 12983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko ref_->CheckTop(); 13083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko } 13183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 13283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko private: 13383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko DebugStackReferenceImpl<kIsDebug>* ref_; 13483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko}; 13583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 13683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko} // namespace art 13783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 13883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko#endif // ART_COMPILER_UTILS_DEBUG_STACK_H_ 139