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#include "allocation_record.h"
188c2ff641294715864013737fdec57cdfd410270cMan Cao
198c2ff641294715864013737fdec57cdfd410270cMan Cao#include "art_method-inl.h"
20542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe#include "base/enums.h"
218c2ff641294715864013737fdec57cdfd410270cMan Cao#include "base/stl_util.h"
229d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier#include "obj_ptr-inl.h"
238c2ff641294715864013737fdec57cdfd410270cMan Cao#include "stack.h"
248c2ff641294715864013737fdec57cdfd410270cMan Cao
25bb661c0f0cb72d4bbfc2e251f6ded6949a713292Bilyan Borisov#ifdef ART_TARGET_ANDROID
268c2ff641294715864013737fdec57cdfd410270cMan Cao#include "cutils/properties.h"
278c2ff641294715864013737fdec57cdfd410270cMan Cao#endif
288c2ff641294715864013737fdec57cdfd410270cMan Cao
298c2ff641294715864013737fdec57cdfd410270cMan Caonamespace art {
308c2ff641294715864013737fdec57cdfd410270cMan Caonamespace gc {
318c2ff641294715864013737fdec57cdfd410270cMan Cao
328c2ff641294715864013737fdec57cdfd410270cMan Caoint32_t AllocRecordStackTraceElement::ComputeLineNumber() const {
338c2ff641294715864013737fdec57cdfd410270cMan Cao  DCHECK(method_ != nullptr);
348c2ff641294715864013737fdec57cdfd410270cMan Cao  return method_->GetLineNumFromDexPC(dex_pc_);
358c2ff641294715864013737fdec57cdfd410270cMan Cao}
368c2ff641294715864013737fdec57cdfd410270cMan Cao
3741656de4b6440bcd1bea5fb785f0710153b2bc68Man Caoconst char* AllocRecord::GetClassDescriptor(std::string* storage) const {
3841656de4b6440bcd1bea5fb785f0710153b2bc68Man Cao  // klass_ could contain null only if we implement class unloading.
39a7deef9260bd53dfd6b51ace02b4e6200078d5eaMathieu Chartier  return klass_.IsNull() ? "null" : klass_.Read()->GetDescriptor(storage);
4041656de4b6440bcd1bea5fb785f0710153b2bc68Man Cao}
4141656de4b6440bcd1bea5fb785f0710153b2bc68Man Cao
428c2ff641294715864013737fdec57cdfd410270cMan Caovoid AllocRecordObjectMap::SetProperties() {
43bb661c0f0cb72d4bbfc2e251f6ded6949a713292Bilyan Borisov#ifdef ART_TARGET_ANDROID
448c2ff641294715864013737fdec57cdfd410270cMan Cao  // Check whether there's a system property overriding the max number of records.
458c2ff641294715864013737fdec57cdfd410270cMan Cao  const char* propertyName = "dalvik.vm.allocTrackerMax";
468c2ff641294715864013737fdec57cdfd410270cMan Cao  char allocMaxString[PROPERTY_VALUE_MAX];
478c2ff641294715864013737fdec57cdfd410270cMan Cao  if (property_get(propertyName, allocMaxString, "") > 0) {
488c2ff641294715864013737fdec57cdfd410270cMan Cao    char* end;
498c2ff641294715864013737fdec57cdfd410270cMan Cao    size_t value = strtoul(allocMaxString, &end, 10);
508c2ff641294715864013737fdec57cdfd410270cMan Cao    if (*end != '\0') {
518c2ff641294715864013737fdec57cdfd410270cMan Cao      LOG(ERROR) << "Ignoring  " << propertyName << " '" << allocMaxString
528c2ff641294715864013737fdec57cdfd410270cMan Cao                 << "' --- invalid";
538c2ff641294715864013737fdec57cdfd410270cMan Cao    } else {
548c2ff641294715864013737fdec57cdfd410270cMan Cao      alloc_record_max_ = value;
551ed11b9ad5512cf464cb1686640df53201fa5297Man Cao      if (recent_record_max_ > value) {
561ed11b9ad5512cf464cb1686640df53201fa5297Man Cao        recent_record_max_ = value;
571ed11b9ad5512cf464cb1686640df53201fa5297Man Cao      }
581ed11b9ad5512cf464cb1686640df53201fa5297Man Cao    }
591ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  }
601ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  // Check whether there's a system property overriding the number of recent records.
611ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  propertyName = "dalvik.vm.recentAllocMax";
621ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  char recentAllocMaxString[PROPERTY_VALUE_MAX];
631ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  if (property_get(propertyName, recentAllocMaxString, "") > 0) {
641ed11b9ad5512cf464cb1686640df53201fa5297Man Cao    char* end;
651ed11b9ad5512cf464cb1686640df53201fa5297Man Cao    size_t value = strtoul(recentAllocMaxString, &end, 10);
661ed11b9ad5512cf464cb1686640df53201fa5297Man Cao    if (*end != '\0') {
671ed11b9ad5512cf464cb1686640df53201fa5297Man Cao      LOG(ERROR) << "Ignoring  " << propertyName << " '" << recentAllocMaxString
681ed11b9ad5512cf464cb1686640df53201fa5297Man Cao                 << "' --- invalid";
691ed11b9ad5512cf464cb1686640df53201fa5297Man Cao    } else if (value > alloc_record_max_) {
701ed11b9ad5512cf464cb1686640df53201fa5297Man Cao      LOG(ERROR) << "Ignoring  " << propertyName << " '" << recentAllocMaxString
711ed11b9ad5512cf464cb1686640df53201fa5297Man Cao                 << "' --- should be less than " << alloc_record_max_;
721ed11b9ad5512cf464cb1686640df53201fa5297Man Cao    } else {
731ed11b9ad5512cf464cb1686640df53201fa5297Man Cao      recent_record_max_ = value;
748c2ff641294715864013737fdec57cdfd410270cMan Cao    }
758c2ff641294715864013737fdec57cdfd410270cMan Cao  }
768c2ff641294715864013737fdec57cdfd410270cMan Cao  // Check whether there's a system property overriding the max depth of stack trace.
771ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  propertyName = "debug.allocTracker.stackDepth";
788c2ff641294715864013737fdec57cdfd410270cMan Cao  char stackDepthString[PROPERTY_VALUE_MAX];
798c2ff641294715864013737fdec57cdfd410270cMan Cao  if (property_get(propertyName, stackDepthString, "") > 0) {
808c2ff641294715864013737fdec57cdfd410270cMan Cao    char* end;
818c2ff641294715864013737fdec57cdfd410270cMan Cao    size_t value = strtoul(stackDepthString, &end, 10);
828c2ff641294715864013737fdec57cdfd410270cMan Cao    if (*end != '\0') {
838c2ff641294715864013737fdec57cdfd410270cMan Cao      LOG(ERROR) << "Ignoring  " << propertyName << " '" << stackDepthString
848c2ff641294715864013737fdec57cdfd410270cMan Cao                 << "' --- invalid";
851ed11b9ad5512cf464cb1686640df53201fa5297Man Cao    } else if (value > kMaxSupportedStackDepth) {
861ed11b9ad5512cf464cb1686640df53201fa5297Man Cao      LOG(WARNING) << propertyName << " '" << stackDepthString << "' too large, using "
871ed11b9ad5512cf464cb1686640df53201fa5297Man Cao                   << kMaxSupportedStackDepth;
881ed11b9ad5512cf464cb1686640df53201fa5297Man Cao      max_stack_depth_ = kMaxSupportedStackDepth;
898c2ff641294715864013737fdec57cdfd410270cMan Cao    } else {
908c2ff641294715864013737fdec57cdfd410270cMan Cao      max_stack_depth_ = value;
918c2ff641294715864013737fdec57cdfd410270cMan Cao    }
928c2ff641294715864013737fdec57cdfd410270cMan Cao  }
93bb661c0f0cb72d4bbfc2e251f6ded6949a713292Bilyan Borisov#endif  // ART_TARGET_ANDROID
948c2ff641294715864013737fdec57cdfd410270cMan Cao}
958c2ff641294715864013737fdec57cdfd410270cMan Cao
968c2ff641294715864013737fdec57cdfd410270cMan CaoAllocRecordObjectMap::~AllocRecordObjectMap() {
9714b0a5ddc0ae305e3ac152c34e4d6fdd0abb854cMathieu Chartier  Clear();
988c2ff641294715864013737fdec57cdfd410270cMan Cao}
998c2ff641294715864013737fdec57cdfd410270cMan Cao
1001ed11b9ad5512cf464cb1686640df53201fa5297Man Caovoid AllocRecordObjectMap::VisitRoots(RootVisitor* visitor) {
1011ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  CHECK_LE(recent_record_max_, alloc_record_max_);
1021ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  BufferedRootVisitor<kDefaultBufferedRootCount> buffered_visitor(visitor, RootInfo(kRootDebugger));
1031ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  size_t count = recent_record_max_;
10442c3c33df8b6eefc4ba532f1981282510f109928Man Cao  // Only visit the last recent_record_max_ number of allocation records in entries_ and mark the
10542c3c33df8b6eefc4ba532f1981282510f109928Man Cao  // klass_ fields as strong roots.
106a7deef9260bd53dfd6b51ace02b4e6200078d5eaMathieu Chartier  for (auto it = entries_.rbegin(), end = entries_.rend(); it != end; ++it) {
107458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier    AllocRecord& record = it->second;
108a7deef9260bd53dfd6b51ace02b4e6200078d5eaMathieu Chartier    if (count > 0) {
109458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier      buffered_visitor.VisitRootIfNonNull(record.GetClassGcRoot());
110a7deef9260bd53dfd6b51ace02b4e6200078d5eaMathieu Chartier      --count;
111a7deef9260bd53dfd6b51ace02b4e6200078d5eaMathieu Chartier    }
112a7deef9260bd53dfd6b51ace02b4e6200078d5eaMathieu Chartier    // Visit all of the stack frames to make sure no methods in the stack traces get unloaded by
113a7deef9260bd53dfd6b51ace02b4e6200078d5eaMathieu Chartier    // class unloading.
114458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier    for (size_t i = 0, depth = record.GetDepth(); i < depth; ++i) {
115458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier      const AllocRecordStackTraceElement& element = record.StackElement(i);
116a7deef9260bd53dfd6b51ace02b4e6200078d5eaMathieu Chartier      DCHECK(element.GetMethod() != nullptr);
117542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe      element.GetMethod()->VisitRoots(buffered_visitor, kRuntimePointerSize);
118a7deef9260bd53dfd6b51ace02b4e6200078d5eaMathieu Chartier    }
11942c3c33df8b6eefc4ba532f1981282510f109928Man Cao  }
12042c3c33df8b6eefc4ba532f1981282510f109928Man Cao}
12142c3c33df8b6eefc4ba532f1981282510f109928Man Cao
12297509954404d031594b2ecbda607314d169d512eMathieu Chartierstatic inline void SweepClassObject(AllocRecord* record, IsMarkedVisitor* visitor)
123bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_)
12490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    REQUIRES(Locks::alloc_tracker_lock_) {
12542c3c33df8b6eefc4ba532f1981282510f109928Man Cao  GcRoot<mirror::Class>& klass = record->GetClassGcRoot();
12642c3c33df8b6eefc4ba532f1981282510f109928Man Cao  // This does not need a read barrier because this is called by GC.
12742c3c33df8b6eefc4ba532f1981282510f109928Man Cao  mirror::Object* old_object = klass.Read<kWithoutReadBarrier>();
12897509954404d031594b2ecbda607314d169d512eMathieu Chartier  if (old_object != nullptr) {
12997509954404d031594b2ecbda607314d169d512eMathieu Chartier    // The class object can become null if we implement class unloading.
13097509954404d031594b2ecbda607314d169d512eMathieu Chartier    // In that case we might still want to keep the class name string (not implemented).
13197509954404d031594b2ecbda607314d169d512eMathieu Chartier    mirror::Object* new_object = visitor->IsMarked(old_object);
13297509954404d031594b2ecbda607314d169d512eMathieu Chartier    DCHECK(new_object != nullptr);
13397509954404d031594b2ecbda607314d169d512eMathieu Chartier    if (UNLIKELY(old_object != new_object)) {
13497509954404d031594b2ecbda607314d169d512eMathieu Chartier      klass = GcRoot<mirror::Class>(new_object->AsClass());
13597509954404d031594b2ecbda607314d169d512eMathieu Chartier    }
1361ed11b9ad5512cf464cb1686640df53201fa5297Man Cao  }
1371ed11b9ad5512cf464cb1686640df53201fa5297Man Cao}
1381ed11b9ad5512cf464cb1686640df53201fa5297Man Cao
13997509954404d031594b2ecbda607314d169d512eMathieu Chartiervoid AllocRecordObjectMap::SweepAllocationRecords(IsMarkedVisitor* visitor) {
1408c2ff641294715864013737fdec57cdfd410270cMan Cao  VLOG(heap) << "Start SweepAllocationRecords()";
14142c3c33df8b6eefc4ba532f1981282510f109928Man Cao  size_t count_deleted = 0, count_moved = 0, count = 0;
14242c3c33df8b6eefc4ba532f1981282510f109928Man Cao  // Only the first (size - recent_record_max_) number of records can be deleted.
143a7deef9260bd53dfd6b51ace02b4e6200078d5eaMathieu Chartier  const size_t delete_bound = std::max(entries_.size(), recent_record_max_) - recent_record_max_;
1448c2ff641294715864013737fdec57cdfd410270cMan Cao  for (auto it = entries_.begin(), end = entries_.end(); it != end;) {
14542c3c33df8b6eefc4ba532f1981282510f109928Man Cao    ++count;
1468c2ff641294715864013737fdec57cdfd410270cMan Cao    // This does not need a read barrier because this is called by GC.
1478c2ff641294715864013737fdec57cdfd410270cMan Cao    mirror::Object* old_object = it->first.Read<kWithoutReadBarrier>();
148458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier    AllocRecord& record = it->second;
14997509954404d031594b2ecbda607314d169d512eMathieu Chartier    mirror::Object* new_object = old_object == nullptr ? nullptr : visitor->IsMarked(old_object);
1508c2ff641294715864013737fdec57cdfd410270cMan Cao    if (new_object == nullptr) {
15142c3c33df8b6eefc4ba532f1981282510f109928Man Cao      if (count > delete_bound) {
15242c3c33df8b6eefc4ba532f1981282510f109928Man Cao        it->first = GcRoot<mirror::Object>(nullptr);
153458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier        SweepClassObject(&record, visitor);
15442c3c33df8b6eefc4ba532f1981282510f109928Man Cao        ++it;
15542c3c33df8b6eefc4ba532f1981282510f109928Man Cao      } else {
15642c3c33df8b6eefc4ba532f1981282510f109928Man Cao        it = entries_.erase(it);
15742c3c33df8b6eefc4ba532f1981282510f109928Man Cao        ++count_deleted;
15842c3c33df8b6eefc4ba532f1981282510f109928Man Cao      }
1598c2ff641294715864013737fdec57cdfd410270cMan Cao    } else {
1608c2ff641294715864013737fdec57cdfd410270cMan Cao      if (old_object != new_object) {
1618c2ff641294715864013737fdec57cdfd410270cMan Cao        it->first = GcRoot<mirror::Object>(new_object);
1628c2ff641294715864013737fdec57cdfd410270cMan Cao        ++count_moved;
1638c2ff641294715864013737fdec57cdfd410270cMan Cao      }
164458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier      SweepClassObject(&record, visitor);
1658c2ff641294715864013737fdec57cdfd410270cMan Cao      ++it;
1668c2ff641294715864013737fdec57cdfd410270cMan Cao    }
1678c2ff641294715864013737fdec57cdfd410270cMan Cao  }
1688c2ff641294715864013737fdec57cdfd410270cMan Cao  VLOG(heap) << "Deleted " << count_deleted << " allocation records";
1698c2ff641294715864013737fdec57cdfd410270cMan Cao  VLOG(heap) << "Updated " << count_moved << " allocation records";
1708c2ff641294715864013737fdec57cdfd410270cMan Cao}
1718c2ff641294715864013737fdec57cdfd410270cMan Cao
17242c3c33df8b6eefc4ba532f1981282510f109928Man Caovoid AllocRecordObjectMap::AllowNewAllocationRecords() {
173fdbd13c7af91a042eda753e436eeebf0e1937250Hiroshi Yamauchi  CHECK(!kUseReadBarrier);
17442c3c33df8b6eefc4ba532f1981282510f109928Man Cao  allow_new_record_ = true;
17542c3c33df8b6eefc4ba532f1981282510f109928Man Cao  new_record_condition_.Broadcast(Thread::Current());
17642c3c33df8b6eefc4ba532f1981282510f109928Man Cao}
17742c3c33df8b6eefc4ba532f1981282510f109928Man Cao
17842c3c33df8b6eefc4ba532f1981282510f109928Man Caovoid AllocRecordObjectMap::DisallowNewAllocationRecords() {
179fdbd13c7af91a042eda753e436eeebf0e1937250Hiroshi Yamauchi  CHECK(!kUseReadBarrier);
18042c3c33df8b6eefc4ba532f1981282510f109928Man Cao  allow_new_record_ = false;
18142c3c33df8b6eefc4ba532f1981282510f109928Man Cao}
18242c3c33df8b6eefc4ba532f1981282510f109928Man Cao
183fdbd13c7af91a042eda753e436eeebf0e1937250Hiroshi Yamauchivoid AllocRecordObjectMap::BroadcastForNewAllocationRecords() {
184fdbd13c7af91a042eda753e436eeebf0e1937250Hiroshi Yamauchi  new_record_condition_.Broadcast(Thread::Current());
185fdbd13c7af91a042eda753e436eeebf0e1937250Hiroshi Yamauchi}
186fdbd13c7af91a042eda753e436eeebf0e1937250Hiroshi Yamauchi
187458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartierclass AllocRecordStackVisitor : public StackVisitor {
188458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier public:
189458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  AllocRecordStackVisitor(Thread* thread, size_t max_depth, AllocRecordStackTrace* trace_out)
190bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe      REQUIRES_SHARED(Locks::mutator_lock_)
191c6df1e3cbfa7313007ee5fd4a5a6657a28627313Nicolas Geoffray      : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
192458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier        max_depth_(max_depth),
193458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier        trace_(trace_out) {}
1948c2ff641294715864013737fdec57cdfd410270cMan Cao
1958c2ff641294715864013737fdec57cdfd410270cMan Cao  // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
1968c2ff641294715864013737fdec57cdfd410270cMan Cao  // annotalysis.
1978c2ff641294715864013737fdec57cdfd410270cMan Cao  bool VisitFrame() OVERRIDE NO_THREAD_SAFETY_ANALYSIS {
198458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier    if (trace_->GetDepth() >= max_depth_) {
1998c2ff641294715864013737fdec57cdfd410270cMan Cao      return false;
2008c2ff641294715864013737fdec57cdfd410270cMan Cao    }
2018c2ff641294715864013737fdec57cdfd410270cMan Cao    ArtMethod* m = GetMethod();
20245bf250d61de433c18ded824348e87bd4ffd7678Mathieu Chartier    // m may be null if we have inlined methods of unresolved classes. b/27858645
20345bf250d61de433c18ded824348e87bd4ffd7678Mathieu Chartier    if (m != nullptr && !m->IsRuntimeMethod()) {
204542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe      m = m->GetInterfaceMethodIfProxy(kRuntimePointerSize);
205458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier      trace_->AddStackElement(AllocRecordStackTraceElement(m, GetDexPc()));
2068c2ff641294715864013737fdec57cdfd410270cMan Cao    }
2078c2ff641294715864013737fdec57cdfd410270cMan Cao    return true;
2088c2ff641294715864013737fdec57cdfd410270cMan Cao  }
2098c2ff641294715864013737fdec57cdfd410270cMan Cao
210458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier private:
211458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  const size_t max_depth_;
212458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  AllocRecordStackTrace* const trace_;
2138c2ff641294715864013737fdec57cdfd410270cMan Cao};
2148c2ff641294715864013737fdec57cdfd410270cMan Cao
2158c2ff641294715864013737fdec57cdfd410270cMan Caovoid AllocRecordObjectMap::SetAllocTrackingEnabled(bool enable) {
2168c2ff641294715864013737fdec57cdfd410270cMan Cao  Thread* self = Thread::Current();
2178c2ff641294715864013737fdec57cdfd410270cMan Cao  Heap* heap = Runtime::Current()->GetHeap();
2188c2ff641294715864013737fdec57cdfd410270cMan Cao  if (enable) {
2198c2ff641294715864013737fdec57cdfd410270cMan Cao    {
2208c2ff641294715864013737fdec57cdfd410270cMan Cao      MutexLock mu(self, *Locks::alloc_tracker_lock_);
2218c2ff641294715864013737fdec57cdfd410270cMan Cao      if (heap->IsAllocTrackingEnabled()) {
2228c2ff641294715864013737fdec57cdfd410270cMan Cao        return;  // Already enabled, bail.
2238c2ff641294715864013737fdec57cdfd410270cMan Cao      }
22414b0a5ddc0ae305e3ac152c34e4d6fdd0abb854cMathieu Chartier      AllocRecordObjectMap* records = heap->GetAllocationRecords();
22514b0a5ddc0ae305e3ac152c34e4d6fdd0abb854cMathieu Chartier      if (records == nullptr) {
22614b0a5ddc0ae305e3ac152c34e4d6fdd0abb854cMathieu Chartier        records = new AllocRecordObjectMap;
22714b0a5ddc0ae305e3ac152c34e4d6fdd0abb854cMathieu Chartier        heap->SetAllocationRecords(records);
22814b0a5ddc0ae305e3ac152c34e4d6fdd0abb854cMathieu Chartier      }
2298c2ff641294715864013737fdec57cdfd410270cMan Cao      CHECK(records != nullptr);
2308c2ff641294715864013737fdec57cdfd410270cMan Cao      records->SetProperties();
2318c2ff641294715864013737fdec57cdfd410270cMan Cao      std::string self_name;
2328c2ff641294715864013737fdec57cdfd410270cMan Cao      self->GetThreadName(self_name);
2338c2ff641294715864013737fdec57cdfd410270cMan Cao      if (self_name == "JDWP") {
2348c2ff641294715864013737fdec57cdfd410270cMan Cao        records->alloc_ddm_thread_id_ = self->GetTid();
2358c2ff641294715864013737fdec57cdfd410270cMan Cao      }
2368c2ff641294715864013737fdec57cdfd410270cMan Cao      size_t sz = sizeof(AllocRecordStackTraceElement) * records->max_stack_depth_ +
2378c2ff641294715864013737fdec57cdfd410270cMan Cao                  sizeof(AllocRecord) + sizeof(AllocRecordStackTrace);
2388c2ff641294715864013737fdec57cdfd410270cMan Cao      LOG(INFO) << "Enabling alloc tracker (" << records->alloc_record_max_ << " entries of "
2398c2ff641294715864013737fdec57cdfd410270cMan Cao                << records->max_stack_depth_ << " frames, taking up to "
2408c2ff641294715864013737fdec57cdfd410270cMan Cao                << PrettySize(sz * records->alloc_record_max_) << ")";
2418c2ff641294715864013737fdec57cdfd410270cMan Cao    }
2428c2ff641294715864013737fdec57cdfd410270cMan Cao    Runtime::Current()->GetInstrumentation()->InstrumentQuickAllocEntryPoints();
24316e51beb9a771ffe7be833173e3dd5f2dac63892Mathieu Chartier    {
24416e51beb9a771ffe7be833173e3dd5f2dac63892Mathieu Chartier      MutexLock mu(self, *Locks::alloc_tracker_lock_);
24516e51beb9a771ffe7be833173e3dd5f2dac63892Mathieu Chartier      heap->SetAllocTrackingEnabled(true);
24616e51beb9a771ffe7be833173e3dd5f2dac63892Mathieu Chartier    }
2478c2ff641294715864013737fdec57cdfd410270cMan Cao  } else {
2480b8b4a609120b90081d898dbf3c26f68fe80de96Mathieu Chartier    // Delete outside of the critical section to avoid possible lock violations like the runtime
2490b8b4a609120b90081d898dbf3c26f68fe80de96Mathieu Chartier    // shutdown lock.
2508c2ff641294715864013737fdec57cdfd410270cMan Cao    {
2518c2ff641294715864013737fdec57cdfd410270cMan Cao      MutexLock mu(self, *Locks::alloc_tracker_lock_);
2528c2ff641294715864013737fdec57cdfd410270cMan Cao      if (!heap->IsAllocTrackingEnabled()) {
2538c2ff641294715864013737fdec57cdfd410270cMan Cao        return;  // Already disabled, bail.
2548c2ff641294715864013737fdec57cdfd410270cMan Cao      }
2558c2ff641294715864013737fdec57cdfd410270cMan Cao      heap->SetAllocTrackingEnabled(false);
2568c2ff641294715864013737fdec57cdfd410270cMan Cao      LOG(INFO) << "Disabling alloc tracker";
25714b0a5ddc0ae305e3ac152c34e4d6fdd0abb854cMathieu Chartier      AllocRecordObjectMap* records = heap->GetAllocationRecords();
25814b0a5ddc0ae305e3ac152c34e4d6fdd0abb854cMathieu Chartier      records->Clear();
2598c2ff641294715864013737fdec57cdfd410270cMan Cao    }
2608c2ff641294715864013737fdec57cdfd410270cMan Cao    // If an allocation comes in before we uninstrument, we will safely drop it on the floor.
2618c2ff641294715864013737fdec57cdfd410270cMan Cao    Runtime::Current()->GetInstrumentation()->UninstrumentQuickAllocEntryPoints();
2628c2ff641294715864013737fdec57cdfd410270cMan Cao  }
2638c2ff641294715864013737fdec57cdfd410270cMan Cao}
2648c2ff641294715864013737fdec57cdfd410270cMan Cao
265458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartiervoid AllocRecordObjectMap::RecordAllocation(Thread* self,
2669d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier                                            ObjPtr<mirror::Object>* obj,
26742c3c33df8b6eefc4ba532f1981282510f109928Man Cao                                            size_t byte_count) {
268458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  // Get stack trace outside of lock in case there are allocations during the stack walk.
269458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  // b/27858645.
270458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  AllocRecordStackTrace trace;
271458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  AllocRecordStackVisitor visitor(self, max_stack_depth_, /*out*/ &trace);
272458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  {
273458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier    StackHandleScope<1> hs(self);
274458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier    auto obj_wrapper = hs.NewHandleWrapper(obj);
275458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier    visitor.WalkStack();
276458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  }
277458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier
2788c2ff641294715864013737fdec57cdfd410270cMan Cao  MutexLock mu(self, *Locks::alloc_tracker_lock_);
279458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  Heap* const heap = Runtime::Current()->GetHeap();
2808c2ff641294715864013737fdec57cdfd410270cMan Cao  if (!heap->IsAllocTrackingEnabled()) {
2818c2ff641294715864013737fdec57cdfd410270cMan Cao    // In the process of shutting down recording, bail.
2828c2ff641294715864013737fdec57cdfd410270cMan Cao    return;
2838c2ff641294715864013737fdec57cdfd410270cMan Cao  }
2848c2ff641294715864013737fdec57cdfd410270cMan Cao
285458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  // Do not record for DDM thread.
286458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  if (alloc_ddm_thread_id_ == self->GetTid()) {
2878c2ff641294715864013737fdec57cdfd410270cMan Cao    return;
2888c2ff641294715864013737fdec57cdfd410270cMan Cao  }
2898c2ff641294715864013737fdec57cdfd410270cMan Cao
29042c3c33df8b6eefc4ba532f1981282510f109928Man Cao  // Wait for GC's sweeping to complete and allow new records
291458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  while (UNLIKELY((!kUseReadBarrier && !allow_new_record_) ||
2920b71357fb52be9bb06d35396a3042b4381b01041Hiroshi Yamauchi                  (kUseReadBarrier && !self->GetWeakRefAccessEnabled()))) {
2933049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi    // Check and run the empty checkpoint before blocking so the empty checkpoint will work in the
2943049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi    // presence of threads blocking for weak ref access.
295a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi    self->CheckEmptyCheckpointFromWeakRefAccess(Locks::alloc_tracker_lock_);
296458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier    new_record_condition_.WaitHoldingLocks(self);
29742c3c33df8b6eefc4ba532f1981282510f109928Man Cao  }
29842c3c33df8b6eefc4ba532f1981282510f109928Man Cao
2996f0c6cdae6962532c4699df9dd5af6289b86d1c6Hiroshi Yamauchi  if (!heap->IsAllocTrackingEnabled()) {
3006f0c6cdae6962532c4699df9dd5af6289b86d1c6Hiroshi Yamauchi    // Return if the allocation tracking has been disabled while waiting for system weak access
3016f0c6cdae6962532c4699df9dd5af6289b86d1c6Hiroshi Yamauchi    // above.
3026f0c6cdae6962532c4699df9dd5af6289b86d1c6Hiroshi Yamauchi    return;
3036f0c6cdae6962532c4699df9dd5af6289b86d1c6Hiroshi Yamauchi  }
3046f0c6cdae6962532c4699df9dd5af6289b86d1c6Hiroshi Yamauchi
305458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  DCHECK_LE(Size(), alloc_record_max_);
3068c2ff641294715864013737fdec57cdfd410270cMan Cao
307458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  // Erase extra unfilled elements.
308458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  trace.SetTid(self->GetTid());
3098c2ff641294715864013737fdec57cdfd410270cMan Cao
310458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  // Add the record.
3119d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier  Put(obj->Ptr(), AllocRecord(byte_count, (*obj)->GetClass(), std::move(trace)));
312458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier  DCHECK_LE(Size(), alloc_record_max_);
3138c2ff641294715864013737fdec57cdfd410270cMan Cao}
3148c2ff641294715864013737fdec57cdfd410270cMan Cao
31514b0a5ddc0ae305e3ac152c34e4d6fdd0abb854cMathieu Chartiervoid AllocRecordObjectMap::Clear() {
31614b0a5ddc0ae305e3ac152c34e4d6fdd0abb854cMathieu Chartier  entries_.clear();
31714b0a5ddc0ae305e3ac152c34e4d6fdd0abb854cMathieu Chartier}
31814b0a5ddc0ae305e3ac152c34e4d6fdd0abb854cMathieu Chartier
319458b105a9cbab6156d72acf3b9372291dba9097aMathieu ChartierAllocRecordObjectMap::AllocRecordObjectMap()
320458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier    : new_record_condition_("New allocation record condition", *Locks::alloc_tracker_lock_) {}
321458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier
3228c2ff641294715864013737fdec57cdfd410270cMan Cao}  // namespace gc
3238c2ff641294715864013737fdec57cdfd410270cMan Cao}  // namespace art
324