Delete large objects in space destructor. Also some cleanup.
Change-Id: I4c4e90149841a156b7a3236201b37683e14890fb
class VerifyRootVisitor : public SingleRootVisitor {
public:
- explicit VerifyRootVisitor(MarkSweep* collector) : collector_(collector) { }
-
void VisitRoot(mirror::Object* root, const RootInfo& info) OVERRIDE
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
- collector_->VerifyRoot(root, info);
- }
-
- private:
- MarkSweep* const collector_;
-};
-
-void MarkSweep::VerifyRoot(const Object* root, const RootInfo& root_info) {
- // See if the root is on any space bitmap.
- if (heap_->GetLiveBitmap()->GetContinuousSpaceBitmap(root) == nullptr) {
- space::LargeObjectSpace* large_object_space = GetHeap()->GetLargeObjectsSpace();
- if (large_object_space != nullptr && !large_object_space->Contains(root)) {
- LOG(ERROR) << "Found invalid root: " << root << " " << root_info;
+ // See if the root is on any space bitmap.
+ auto* heap = Runtime::Current()->GetHeap();
+ if (heap->GetLiveBitmap()->GetContinuousSpaceBitmap(root) == nullptr) {
+ space::LargeObjectSpace* large_object_space = heap->GetLargeObjectsSpace();
+ if (large_object_space != nullptr && !large_object_space->Contains(root)) {
+ LOG(ERROR) << "Found invalid root: " << root << " " << info;
+ }
}
}
-}
+};
void MarkSweep::VerifyRoots() {
- VerifyRootVisitor visitor(this);
+ VerifyRootVisitor visitor;
Runtime::Current()->GetThreadList()->VisitRoots(&visitor);
}
// whether or not we care about pauses.
size_t GetThreadCount(bool paused) const;
- void VerifyRoot(const mirror::Object* root, const RootInfo& root_info)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_);
-
// Push a single reference on a mark stack.
void PushOnMarkStack(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
explicit ValgrindLargeObjectMapSpace(const std::string& name) : LargeObjectMapSpace(name) {
}
+ ~ValgrindLargeObjectMapSpace() OVERRIDE {
+ // Keep valgrind happy if there is any large objects such as dex cache arrays which aren't
+ // freed since they are held live by the class linker.
+ MutexLock mu(Thread::Current(), lock_);
+ for (auto& m : mem_maps_) {
+ delete m.second;
+ }
+ }
+
virtual mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated,
size_t* usable_size, size_t* bytes_tl_bulk_allocated)
OVERRIDE {
ALWAYS_INLINE GcRoot(MirrorType* ref = nullptr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
+ // Root visitors take pointers to root_ and place the min CompressedReference** arrays. We use a
+ // CompressedReference<mirror::Object> here since it violates strict aliasing requirements to
+ // cast CompressedReference<MirrorType>* to CompressedReference<mirror::Object>*.
mutable mirror::CompressedReference<mirror::Object> root_;
template <size_t kBufferSize> friend class BufferedRootVisitor;
void IndirectReferenceTable::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) {
BufferedRootVisitor<kDefaultBufferedRootCount> root_visitor(visitor, root_info);
for (auto ref : *this) {
- root_visitor.VisitRootIfNonNull(*ref);
+ if (!ref->IsNull()) {
+ root_visitor.VisitRoot(*ref);
+ DCHECK(!ref->IsNull());
+ }
}
}
visitor, RootInfo(kRootNativeStack, thread_id));
for (HandleScope* cur = tlsPtr_.top_handle_scope; cur; cur = cur->GetLink()) {
for (size_t j = 0, count = cur->NumberOfReferences(); j < count; ++j) {
+ // GetReference returns a pointer to the stack reference within the handle scope. If this
+ // needs to be updated, it will be done by the root visitor.
buffered_visitor.VisitRootIfNonNull(cur->GetHandle(j).GetReference());
}
}
ReleaseLongJumpContext(context);
for (instrumentation::InstrumentationStackFrame& frame : *GetInstrumentationStack()) {
visitor->VisitRootIfNonNull(&frame.this_object_, RootInfo(kRootVMInternal, thread_id));
+ DCHECK(frame.method_ != nullptr);
visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&frame.method_),
RootInfo(kRootVMInternal, thread_id));
}