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