allocation_record.h revision 1ed11b9ad5512cf464cb1686640df53201fa5297
18c2ff641294715864013737fdec57cdfd410270cMan Cao/*
28c2ff641294715864013737fdec57cdfd410270cMan Cao * Copyright (C) 2015 The Android Open Source Project
38c2ff641294715864013737fdec57cdfd410270cMan Cao *
48c2ff641294715864013737fdec57cdfd410270cMan Cao * Licensed under the Apache License, Version 2.0 (the "License");
58c2ff641294715864013737fdec57cdfd410270cMan Cao * you may not use this file except in compliance with the License.
68c2ff641294715864013737fdec57cdfd410270cMan Cao * You may obtain a copy of the License at
78c2ff641294715864013737fdec57cdfd410270cMan Cao *
88c2ff641294715864013737fdec57cdfd410270cMan Cao *      http://www.apache.org/licenses/LICENSE-2.0
98c2ff641294715864013737fdec57cdfd410270cMan Cao *
108c2ff641294715864013737fdec57cdfd410270cMan Cao * Unless required by applicable law or agreed to in writing, software
118c2ff641294715864013737fdec57cdfd410270cMan Cao * distributed under the License is distributed on an "AS IS" BASIS,
128c2ff641294715864013737fdec57cdfd410270cMan Cao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138c2ff641294715864013737fdec57cdfd410270cMan Cao * See the License for the specific language governing permissions and
148c2ff641294715864013737fdec57cdfd410270cMan Cao * limitations under the License.
158c2ff641294715864013737fdec57cdfd410270cMan Cao */
168c2ff641294715864013737fdec57cdfd410270cMan Cao
178c2ff641294715864013737fdec57cdfd410270cMan Cao#ifndef ART_RUNTIME_GC_ALLOCATION_RECORD_H_
188c2ff641294715864013737fdec57cdfd410270cMan Cao#define ART_RUNTIME_GC_ALLOCATION_RECORD_H_
198c2ff641294715864013737fdec57cdfd410270cMan Cao
208c2ff641294715864013737fdec57cdfd410270cMan Cao#include <list>
218c2ff641294715864013737fdec57cdfd410270cMan Cao
228c2ff641294715864013737fdec57cdfd410270cMan Cao#include "base/mutex.h"
238c2ff641294715864013737fdec57cdfd410270cMan Cao#include "object_callbacks.h"
248c2ff641294715864013737fdec57cdfd410270cMan Cao#include "gc_root.h"
258c2ff641294715864013737fdec57cdfd410270cMan Cao
268c2ff641294715864013737fdec57cdfd410270cMan Caonamespace art {
278c2ff641294715864013737fdec57cdfd410270cMan Cao
288c2ff641294715864013737fdec57cdfd410270cMan Caoclass ArtMethod;
298c2ff641294715864013737fdec57cdfd410270cMan Caoclass Thread;
308c2ff641294715864013737fdec57cdfd410270cMan Cao
318c2ff641294715864013737fdec57cdfd410270cMan Caonamespace mirror {
328c2ff641294715864013737fdec57cdfd410270cMan Cao  class Class;
338c2ff641294715864013737fdec57cdfd410270cMan Cao  class Object;
348c2ff641294715864013737fdec57cdfd410270cMan Cao}
358c2ff641294715864013737fdec57cdfd410270cMan Cao
368c2ff641294715864013737fdec57cdfd410270cMan Caonamespace gc {
378c2ff641294715864013737fdec57cdfd410270cMan Cao
388c2ff641294715864013737fdec57cdfd410270cMan Caoclass AllocRecordStackTraceElement {
398c2ff641294715864013737fdec57cdfd410270cMan Cao public:
408c2ff641294715864013737fdec57cdfd410270cMan Cao  AllocRecordStackTraceElement() : method_(nullptr), dex_pc_(0) {}
418c2ff641294715864013737fdec57cdfd410270cMan Cao
428c2ff641294715864013737fdec57cdfd410270cMan Cao  int32_t ComputeLineNumber() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
438c2ff641294715864013737fdec57cdfd410270cMan Cao
448c2ff641294715864013737fdec57cdfd410270cMan Cao  ArtMethod* GetMethod() const {
458c2ff641294715864013737fdec57cdfd410270cMan Cao    return method_;
468c2ff641294715864013737fdec57cdfd410270cMan Cao  }
478c2ff641294715864013737fdec57cdfd410270cMan Cao
488c2ff641294715864013737fdec57cdfd410270cMan Cao  void SetMethod(ArtMethod* m) {
498c2ff641294715864013737fdec57cdfd410270cMan Cao    method_ = m;
508c2ff641294715864013737fdec57cdfd410270cMan Cao  }
518c2ff641294715864013737fdec57cdfd410270cMan Cao
528c2ff641294715864013737fdec57cdfd410270cMan Cao  uint32_t GetDexPc() const {
538c2ff641294715864013737fdec57cdfd410270cMan Cao    return dex_pc_;
548c2ff641294715864013737fdec57cdfd410270cMan Cao  }
558c2ff641294715864013737fdec57cdfd410270cMan Cao
568c2ff641294715864013737fdec57cdfd410270cMan Cao  void SetDexPc(uint32_t pc) {
578c2ff641294715864013737fdec57cdfd410270cMan Cao    dex_pc_ = pc;
588c2ff641294715864013737fdec57cdfd410270cMan Cao  }
598c2ff641294715864013737fdec57cdfd410270cMan Cao
608c2ff641294715864013737fdec57cdfd410270cMan Cao  bool operator==(const AllocRecordStackTraceElement& other) const {
618c2ff641294715864013737fdec57cdfd410270cMan Cao    if (this == &other) return true;
628c2ff641294715864013737fdec57cdfd410270cMan Cao    return method_ == other.method_ && dex_pc_ == other.dex_pc_;
638c2ff641294715864013737fdec57cdfd410270cMan Cao  }
648c2ff641294715864013737fdec57cdfd410270cMan Cao
658c2ff641294715864013737fdec57cdfd410270cMan Cao private:
668c2ff641294715864013737fdec57cdfd410270cMan Cao  ArtMethod* method_;
678c2ff641294715864013737fdec57cdfd410270cMan Cao  uint32_t dex_pc_;
688c2ff641294715864013737fdec57cdfd410270cMan Cao};
698c2ff641294715864013737fdec57cdfd410270cMan Cao
708c2ff641294715864013737fdec57cdfd410270cMan Caoclass AllocRecordStackTrace {
718c2ff641294715864013737fdec57cdfd410270cMan Cao public:
728c2ff641294715864013737fdec57cdfd410270cMan Cao  static constexpr size_t kHashMultiplier = 17;
738c2ff641294715864013737fdec57cdfd410270cMan Cao
741ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  explicit AllocRecordStackTrace(size_t max_depth)
751ed11b9ad5512cf464cb1686640df53201fa5297Man Cao      : tid_(0), depth_(0), stack_(new AllocRecordStackTraceElement[max_depth]) {}
761ed11b9ad5512cf464cb1686640df53201fa5297Man Cao
771ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  AllocRecordStackTrace(const AllocRecordStackTrace& r)
781ed11b9ad5512cf464cb1686640df53201fa5297Man Cao      : tid_(r.tid_), depth_(r.depth_), stack_(new AllocRecordStackTraceElement[r.depth_]) {
791ed11b9ad5512cf464cb1686640df53201fa5297Man Cao    for (size_t i = 0; i < depth_; ++i) {
801ed11b9ad5512cf464cb1686640df53201fa5297Man Cao      stack_[i] = r.stack_[i];
811ed11b9ad5512cf464cb1686640df53201fa5297Man Cao    }
821ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  }
838c2ff641294715864013737fdec57cdfd410270cMan Cao
848c2ff641294715864013737fdec57cdfd410270cMan Cao  ~AllocRecordStackTrace() {
858c2ff641294715864013737fdec57cdfd410270cMan Cao    delete[] stack_;
868c2ff641294715864013737fdec57cdfd410270cMan Cao  }
878c2ff641294715864013737fdec57cdfd410270cMan Cao
888c2ff641294715864013737fdec57cdfd410270cMan Cao  pid_t GetTid() const {
898c2ff641294715864013737fdec57cdfd410270cMan Cao    return tid_;
908c2ff641294715864013737fdec57cdfd410270cMan Cao  }
918c2ff641294715864013737fdec57cdfd410270cMan Cao
921ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  void SetTid(pid_t t) {
931ed11b9ad5512cf464cb1686640df53201fa5297Man Cao    tid_ = t;
941ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  }
951ed11b9ad5512cf464cb1686640df53201fa5297Man Cao
968c2ff641294715864013737fdec57cdfd410270cMan Cao  size_t GetDepth() const {
978c2ff641294715864013737fdec57cdfd410270cMan Cao    return depth_;
988c2ff641294715864013737fdec57cdfd410270cMan Cao  }
998c2ff641294715864013737fdec57cdfd410270cMan Cao
1008c2ff641294715864013737fdec57cdfd410270cMan Cao  void SetDepth(size_t depth) {
1018c2ff641294715864013737fdec57cdfd410270cMan Cao    depth_ = depth;
1028c2ff641294715864013737fdec57cdfd410270cMan Cao  }
1038c2ff641294715864013737fdec57cdfd410270cMan Cao
1048c2ff641294715864013737fdec57cdfd410270cMan Cao  const AllocRecordStackTraceElement& GetStackElement(size_t index) const {
1058c2ff641294715864013737fdec57cdfd410270cMan Cao    DCHECK_LT(index, depth_);
1068c2ff641294715864013737fdec57cdfd410270cMan Cao    return stack_[index];
1078c2ff641294715864013737fdec57cdfd410270cMan Cao  }
1088c2ff641294715864013737fdec57cdfd410270cMan Cao
1098c2ff641294715864013737fdec57cdfd410270cMan Cao  void SetStackElementAt(size_t index, ArtMethod* m, uint32_t dex_pc) {
1108c2ff641294715864013737fdec57cdfd410270cMan Cao    stack_[index].SetMethod(m);
1118c2ff641294715864013737fdec57cdfd410270cMan Cao    stack_[index].SetDexPc(dex_pc);
1128c2ff641294715864013737fdec57cdfd410270cMan Cao  }
1138c2ff641294715864013737fdec57cdfd410270cMan Cao
1148c2ff641294715864013737fdec57cdfd410270cMan Cao  bool operator==(const AllocRecordStackTrace& other) const {
1158c2ff641294715864013737fdec57cdfd410270cMan Cao    if (this == &other) return true;
1161ed11b9ad5512cf464cb1686640df53201fa5297Man Cao    if (tid_ != other.tid_) return false;
1178c2ff641294715864013737fdec57cdfd410270cMan Cao    if (depth_ != other.depth_) return false;
1188c2ff641294715864013737fdec57cdfd410270cMan Cao    for (size_t i = 0; i < depth_; ++i) {
1198c2ff641294715864013737fdec57cdfd410270cMan Cao      if (!(stack_[i] == other.stack_[i])) return false;
1208c2ff641294715864013737fdec57cdfd410270cMan Cao    }
1218c2ff641294715864013737fdec57cdfd410270cMan Cao    return true;
1228c2ff641294715864013737fdec57cdfd410270cMan Cao  }
1238c2ff641294715864013737fdec57cdfd410270cMan Cao
1248c2ff641294715864013737fdec57cdfd410270cMan Cao private:
1251ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  pid_t tid_;
1268c2ff641294715864013737fdec57cdfd410270cMan Cao  size_t depth_;
1278c2ff641294715864013737fdec57cdfd410270cMan Cao  AllocRecordStackTraceElement* const stack_;
1288c2ff641294715864013737fdec57cdfd410270cMan Cao};
1298c2ff641294715864013737fdec57cdfd410270cMan Cao
1308c2ff641294715864013737fdec57cdfd410270cMan Caostruct HashAllocRecordTypes {
1318c2ff641294715864013737fdec57cdfd410270cMan Cao  size_t operator()(const AllocRecordStackTraceElement& r) const {
1328c2ff641294715864013737fdec57cdfd410270cMan Cao    return std::hash<void*>()(reinterpret_cast<void*>(r.GetMethod())) *
1338c2ff641294715864013737fdec57cdfd410270cMan Cao        AllocRecordStackTrace::kHashMultiplier + std::hash<uint32_t>()(r.GetDexPc());
1348c2ff641294715864013737fdec57cdfd410270cMan Cao  }
1358c2ff641294715864013737fdec57cdfd410270cMan Cao
1368c2ff641294715864013737fdec57cdfd410270cMan Cao  size_t operator()(const AllocRecordStackTrace& r) const {
1378c2ff641294715864013737fdec57cdfd410270cMan Cao    size_t depth = r.GetDepth();
1388c2ff641294715864013737fdec57cdfd410270cMan Cao    size_t result = r.GetTid() * AllocRecordStackTrace::kHashMultiplier + depth;
1398c2ff641294715864013737fdec57cdfd410270cMan Cao    for (size_t i = 0; i < depth; ++i) {
1408c2ff641294715864013737fdec57cdfd410270cMan Cao      result = result * AllocRecordStackTrace::kHashMultiplier + (*this)(r.GetStackElement(i));
1418c2ff641294715864013737fdec57cdfd410270cMan Cao    }
1428c2ff641294715864013737fdec57cdfd410270cMan Cao    return result;
1438c2ff641294715864013737fdec57cdfd410270cMan Cao  }
1448c2ff641294715864013737fdec57cdfd410270cMan Cao};
1458c2ff641294715864013737fdec57cdfd410270cMan Cao
1468c2ff641294715864013737fdec57cdfd410270cMan Caotemplate <typename T> struct HashAllocRecordTypesPtr {
1478c2ff641294715864013737fdec57cdfd410270cMan Cao  size_t operator()(const T* r) const {
1488c2ff641294715864013737fdec57cdfd410270cMan Cao    if (r == nullptr) return 0;
1498c2ff641294715864013737fdec57cdfd410270cMan Cao    return HashAllocRecordTypes()(*r);
1508c2ff641294715864013737fdec57cdfd410270cMan Cao  }
1518c2ff641294715864013737fdec57cdfd410270cMan Cao};
1528c2ff641294715864013737fdec57cdfd410270cMan Cao
1538c2ff641294715864013737fdec57cdfd410270cMan Caotemplate <typename T> struct EqAllocRecordTypesPtr {
1548c2ff641294715864013737fdec57cdfd410270cMan Cao  bool operator()(const T* r1, const T* r2) const {
1558c2ff641294715864013737fdec57cdfd410270cMan Cao    if (r1 == r2) return true;
1568c2ff641294715864013737fdec57cdfd410270cMan Cao    if (r1 == nullptr || r2 == nullptr) return false;
1578c2ff641294715864013737fdec57cdfd410270cMan Cao    return *r1 == *r2;
1588c2ff641294715864013737fdec57cdfd410270cMan Cao  }
1598c2ff641294715864013737fdec57cdfd410270cMan Cao};
1608c2ff641294715864013737fdec57cdfd410270cMan Cao
1618c2ff641294715864013737fdec57cdfd410270cMan Caoclass AllocRecord {
1628c2ff641294715864013737fdec57cdfd410270cMan Cao public:
1638c2ff641294715864013737fdec57cdfd410270cMan Cao  // All instances of AllocRecord should be managed by an instance of AllocRecordObjectMap.
1648c2ff641294715864013737fdec57cdfd410270cMan Cao  AllocRecord(size_t count, AllocRecordStackTrace* trace)
1658c2ff641294715864013737fdec57cdfd410270cMan Cao      : byte_count_(count), trace_(trace) {}
1668c2ff641294715864013737fdec57cdfd410270cMan Cao
1678c2ff641294715864013737fdec57cdfd410270cMan Cao  ~AllocRecord() {
1688c2ff641294715864013737fdec57cdfd410270cMan Cao    delete trace_;
1698c2ff641294715864013737fdec57cdfd410270cMan Cao  }
1708c2ff641294715864013737fdec57cdfd410270cMan Cao
1718c2ff641294715864013737fdec57cdfd410270cMan Cao  size_t GetDepth() const {
1728c2ff641294715864013737fdec57cdfd410270cMan Cao    return trace_->GetDepth();
1738c2ff641294715864013737fdec57cdfd410270cMan Cao  }
1748c2ff641294715864013737fdec57cdfd410270cMan Cao
1758c2ff641294715864013737fdec57cdfd410270cMan Cao  const AllocRecordStackTrace* GetStackTrace() const {
1768c2ff641294715864013737fdec57cdfd410270cMan Cao    return trace_;
1778c2ff641294715864013737fdec57cdfd410270cMan Cao  }
1788c2ff641294715864013737fdec57cdfd410270cMan Cao
1798c2ff641294715864013737fdec57cdfd410270cMan Cao  size_t ByteCount() const {
1808c2ff641294715864013737fdec57cdfd410270cMan Cao    return byte_count_;
1818c2ff641294715864013737fdec57cdfd410270cMan Cao  }
1828c2ff641294715864013737fdec57cdfd410270cMan Cao
1838c2ff641294715864013737fdec57cdfd410270cMan Cao  pid_t GetTid() const {
1848c2ff641294715864013737fdec57cdfd410270cMan Cao    return trace_->GetTid();
1858c2ff641294715864013737fdec57cdfd410270cMan Cao  }
1868c2ff641294715864013737fdec57cdfd410270cMan Cao
1878c2ff641294715864013737fdec57cdfd410270cMan Cao  const AllocRecordStackTraceElement& StackElement(size_t index) const {
1888c2ff641294715864013737fdec57cdfd410270cMan Cao    return trace_->GetStackElement(index);
1898c2ff641294715864013737fdec57cdfd410270cMan Cao  }
1908c2ff641294715864013737fdec57cdfd410270cMan Cao
1918c2ff641294715864013737fdec57cdfd410270cMan Cao private:
1928c2ff641294715864013737fdec57cdfd410270cMan Cao  const size_t byte_count_;
1938c2ff641294715864013737fdec57cdfd410270cMan Cao  // TODO: Currently trace_ is like a std::unique_ptr,
1948c2ff641294715864013737fdec57cdfd410270cMan Cao  // but in future with deduplication it could be a std::shared_ptr.
1958c2ff641294715864013737fdec57cdfd410270cMan Cao  const AllocRecordStackTrace* const trace_;
1968c2ff641294715864013737fdec57cdfd410270cMan Cao};
1978c2ff641294715864013737fdec57cdfd410270cMan Cao
1988c2ff641294715864013737fdec57cdfd410270cMan Caoclass AllocRecordObjectMap {
1998c2ff641294715864013737fdec57cdfd410270cMan Cao public:
2008c2ff641294715864013737fdec57cdfd410270cMan Cao  // Since the entries contain weak roots, they need a read barrier. Do not directly access
2018c2ff641294715864013737fdec57cdfd410270cMan Cao  // the mirror::Object pointers in it. Use functions that contain read barriers.
2028c2ff641294715864013737fdec57cdfd410270cMan Cao  // No need for "const AllocRecord*" in the list, because all fields of AllocRecord are const.
2038c2ff641294715864013737fdec57cdfd410270cMan Cao  typedef std::list<std::pair<GcRoot<mirror::Object>, AllocRecord*>> EntryList;
2048c2ff641294715864013737fdec57cdfd410270cMan Cao
2058c2ff641294715864013737fdec57cdfd410270cMan Cao  // "static" because it is part of double-checked locking. It needs to check a bool first,
2068c2ff641294715864013737fdec57cdfd410270cMan Cao  // in order to make sure the AllocRecordObjectMap object is not null.
2078c2ff641294715864013737fdec57cdfd410270cMan Cao  static void RecordAllocation(Thread* self, mirror::Object* obj, size_t byte_count)
2088c2ff641294715864013737fdec57cdfd410270cMan Cao      LOCKS_EXCLUDED(Locks::alloc_tracker_lock_)
2098c2ff641294715864013737fdec57cdfd410270cMan Cao      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
2108c2ff641294715864013737fdec57cdfd410270cMan Cao
2118c2ff641294715864013737fdec57cdfd410270cMan Cao  static void SetAllocTrackingEnabled(bool enabled) LOCKS_EXCLUDED(Locks::alloc_tracker_lock_);
2128c2ff641294715864013737fdec57cdfd410270cMan Cao
2138c2ff641294715864013737fdec57cdfd410270cMan Cao  AllocRecordObjectMap() EXCLUSIVE_LOCKS_REQUIRED(Locks::alloc_tracker_lock_)
2148c2ff641294715864013737fdec57cdfd410270cMan Cao      : alloc_record_max_(kDefaultNumAllocRecords),
2151ed11b9ad5512cf464cb1686640df53201fa5297Man Cao        recent_record_max_(kDefaultNumRecentRecords),
2168c2ff641294715864013737fdec57cdfd410270cMan Cao        max_stack_depth_(kDefaultAllocStackDepth),
2171ed11b9ad5512cf464cb1686640df53201fa5297Man Cao        scratch_trace_(kMaxSupportedStackDepth),
2188c2ff641294715864013737fdec57cdfd410270cMan Cao        alloc_ddm_thread_id_(0) {}
2198c2ff641294715864013737fdec57cdfd410270cMan Cao
2208c2ff641294715864013737fdec57cdfd410270cMan Cao  ~AllocRecordObjectMap();
2218c2ff641294715864013737fdec57cdfd410270cMan Cao
2228c2ff641294715864013737fdec57cdfd410270cMan Cao  void Put(mirror::Object* obj, AllocRecord* record)
2238c2ff641294715864013737fdec57cdfd410270cMan Cao      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
2248c2ff641294715864013737fdec57cdfd410270cMan Cao      EXCLUSIVE_LOCKS_REQUIRED(Locks::alloc_tracker_lock_) {
2251ed11b9ad5512cf464cb1686640df53201fa5297Man Cao    if (entries_.size() == alloc_record_max_) {
2261ed11b9ad5512cf464cb1686640df53201fa5297Man Cao      delete entries_.front().second;
2271ed11b9ad5512cf464cb1686640df53201fa5297Man Cao      entries_.pop_front();
2281ed11b9ad5512cf464cb1686640df53201fa5297Man Cao    }
2298c2ff641294715864013737fdec57cdfd410270cMan Cao    entries_.emplace_back(GcRoot<mirror::Object>(obj), record);
2308c2ff641294715864013737fdec57cdfd410270cMan Cao  }
2318c2ff641294715864013737fdec57cdfd410270cMan Cao
2328c2ff641294715864013737fdec57cdfd410270cMan Cao  size_t Size() const SHARED_LOCKS_REQUIRED(Locks::alloc_tracker_lock_) {
2338c2ff641294715864013737fdec57cdfd410270cMan Cao    return entries_.size();
2348c2ff641294715864013737fdec57cdfd410270cMan Cao  }
2358c2ff641294715864013737fdec57cdfd410270cMan Cao
2361ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  size_t GetRecentAllocationSize() const SHARED_LOCKS_REQUIRED(Locks::alloc_tracker_lock_) {
2371ed11b9ad5512cf464cb1686640df53201fa5297Man Cao    CHECK_LE(recent_record_max_, alloc_record_max_);
2381ed11b9ad5512cf464cb1686640df53201fa5297Man Cao    size_t sz = entries_.size();
2391ed11b9ad5512cf464cb1686640df53201fa5297Man Cao    return std::min(recent_record_max_, sz);
2401ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  }
2411ed11b9ad5512cf464cb1686640df53201fa5297Man Cao
2421ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  void VisitRoots(RootVisitor* visitor)
2438c2ff641294715864013737fdec57cdfd410270cMan Cao      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
2448c2ff641294715864013737fdec57cdfd410270cMan Cao      EXCLUSIVE_LOCKS_REQUIRED(Locks::alloc_tracker_lock_);
2458c2ff641294715864013737fdec57cdfd410270cMan Cao
2461ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  void SweepAllocationRecords(IsMarkedCallback* callback, void* arg)
2478c2ff641294715864013737fdec57cdfd410270cMan Cao      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
2481ed11b9ad5512cf464cb1686640df53201fa5297Man Cao      EXCLUSIVE_LOCKS_REQUIRED(Locks::alloc_tracker_lock_);
2498c2ff641294715864013737fdec57cdfd410270cMan Cao
2508c2ff641294715864013737fdec57cdfd410270cMan Cao  // TODO: Is there a better way to hide the entries_'s type?
2518c2ff641294715864013737fdec57cdfd410270cMan Cao  EntryList::iterator Begin()
2528c2ff641294715864013737fdec57cdfd410270cMan Cao      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
2538c2ff641294715864013737fdec57cdfd410270cMan Cao      EXCLUSIVE_LOCKS_REQUIRED(Locks::alloc_tracker_lock_) {
2548c2ff641294715864013737fdec57cdfd410270cMan Cao    return entries_.begin();
2558c2ff641294715864013737fdec57cdfd410270cMan Cao  }
2568c2ff641294715864013737fdec57cdfd410270cMan Cao
2578c2ff641294715864013737fdec57cdfd410270cMan Cao  EntryList::iterator End()
2588c2ff641294715864013737fdec57cdfd410270cMan Cao      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
2598c2ff641294715864013737fdec57cdfd410270cMan Cao      EXCLUSIVE_LOCKS_REQUIRED(Locks::alloc_tracker_lock_) {
2608c2ff641294715864013737fdec57cdfd410270cMan Cao    return entries_.end();
2618c2ff641294715864013737fdec57cdfd410270cMan Cao  }
2628c2ff641294715864013737fdec57cdfd410270cMan Cao
2638c2ff641294715864013737fdec57cdfd410270cMan Cao  EntryList::reverse_iterator RBegin()
2648c2ff641294715864013737fdec57cdfd410270cMan Cao      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
2658c2ff641294715864013737fdec57cdfd410270cMan Cao      EXCLUSIVE_LOCKS_REQUIRED(Locks::alloc_tracker_lock_) {
2668c2ff641294715864013737fdec57cdfd410270cMan Cao    return entries_.rbegin();
2678c2ff641294715864013737fdec57cdfd410270cMan Cao  }
2688c2ff641294715864013737fdec57cdfd410270cMan Cao
2698c2ff641294715864013737fdec57cdfd410270cMan Cao  EntryList::reverse_iterator REnd()
2708c2ff641294715864013737fdec57cdfd410270cMan Cao      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
2718c2ff641294715864013737fdec57cdfd410270cMan Cao      EXCLUSIVE_LOCKS_REQUIRED(Locks::alloc_tracker_lock_) {
2728c2ff641294715864013737fdec57cdfd410270cMan Cao    return entries_.rend();
2738c2ff641294715864013737fdec57cdfd410270cMan Cao  }
2748c2ff641294715864013737fdec57cdfd410270cMan Cao
2758c2ff641294715864013737fdec57cdfd410270cMan Cao private:
2768c2ff641294715864013737fdec57cdfd410270cMan Cao  static constexpr size_t kDefaultNumAllocRecords = 512 * 1024;
2771ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  static constexpr size_t kDefaultNumRecentRecords = 64 * 1024 - 1;
2781ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  static constexpr size_t kDefaultAllocStackDepth = 16;
2791ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  static constexpr size_t kMaxSupportedStackDepth = 128;
2808c2ff641294715864013737fdec57cdfd410270cMan Cao  size_t alloc_record_max_ GUARDED_BY(Locks::alloc_tracker_lock_);
2811ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  size_t recent_record_max_ GUARDED_BY(Locks::alloc_tracker_lock_);
2828c2ff641294715864013737fdec57cdfd410270cMan Cao  size_t max_stack_depth_ GUARDED_BY(Locks::alloc_tracker_lock_);
2831ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  AllocRecordStackTrace scratch_trace_ GUARDED_BY(Locks::alloc_tracker_lock_);
2848c2ff641294715864013737fdec57cdfd410270cMan Cao  pid_t alloc_ddm_thread_id_ GUARDED_BY(Locks::alloc_tracker_lock_);
2858c2ff641294715864013737fdec57cdfd410270cMan Cao  EntryList entries_ GUARDED_BY(Locks::alloc_tracker_lock_);
2868c2ff641294715864013737fdec57cdfd410270cMan Cao
2878c2ff641294715864013737fdec57cdfd410270cMan Cao  void SetProperties() EXCLUSIVE_LOCKS_REQUIRED(Locks::alloc_tracker_lock_);
2888c2ff641294715864013737fdec57cdfd410270cMan Cao};
2898c2ff641294715864013737fdec57cdfd410270cMan Cao
2908c2ff641294715864013737fdec57cdfd410270cMan Cao}  // namespace gc
2918c2ff641294715864013737fdec57cdfd410270cMan Cao}  // namespace art
2928c2ff641294715864013737fdec57cdfd410270cMan Cao#endif  // ART_RUNTIME_GC_ALLOCATION_RECORD_H_
293