Was always using the conflict trampoline. Also included fix for
regression in GC time caused by extra roots. Most of the regression
was IMT.
Fixed bug in DumpGcPerformanceInfo where we would get SIGABRT due to
detached thread.
EvaluateAndApplyChanges:
From ~2500 -> ~1980
GC time: 8.2s -> 7.2s due to 1s less of MarkConcurrentRoots
Bug:
19264997
Change-Id: I4333e80a8268c2ed1284f87f25b9f113d4f2c7e0
// marked concurrently and we don't hold the classlinker_classes_lock_ when we do the copy.
for (GcRoot<mirror::Class>& root : class_table_) {
buffered_visitor.VisitRoot(root);
- root.Read()->VisitNativeRoots(buffered_visitor, image_pointer_size_);
+ if ((flags & kVisitRootFlagNonMoving) == 0) {
+ // Don't bother visiting ArtField and ArtMethod if kVisitRootFlagNonMoving is set since
+ // these roots are all reachable from the class or dex cache.
+ root.Read()->VisitNativeRoots(buffered_visitor, image_pointer_size_);
+ }
}
// PreZygote classes can't move so we won't need to update fields' declaring classes.
for (GcRoot<mirror::Class>& root : pre_zygote_class_table_) {
buffered_visitor.VisitRoot(root);
- root.Read()->VisitNativeRoots(buffered_visitor, image_pointer_size_);
+ if ((flags & kVisitRootFlagNonMoving) == 0) {
+ root.Read()->VisitNativeRoots(buffered_visitor, image_pointer_size_);
+ }
}
} else if ((flags & kVisitRootFlagNewRoots) != 0) {
for (auto& root : new_class_roots_) {
return GetTwoWordFailureValue(); // Failure.
}
} else {
- DCHECK(interface_method == Runtime::Current()->GetResolutionMethod());
+ DCHECK_EQ(interface_method, Runtime::Current()->GetResolutionMethod());
if (kIsDebugBuild) {
uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp);
const DexFile::CodeItem* code = caller_method->GetCodeItem();
void MarkSweep::MarkConcurrentRoots(VisitRootFlags flags) {
TimingLogger::ScopedTiming t(__FUNCTION__, GetTimings());
// Visit all runtime roots and clear dirty flags.
- Runtime::Current()->VisitConcurrentRoots(this, flags);
+ Runtime::Current()->VisitConcurrentRoots(
+ this, static_cast<VisitRootFlags>(flags | kVisitRootFlagNonMoving));
}
class ScanObjectVisitor {
}
uint64_t Heap::GetObjectsAllocatedEver() const {
- return GetObjectsFreedEver() + GetObjectsAllocated();
+ uint64_t total = GetObjectsFreedEver();
+ // If we are detached, we can't use GetObjectsAllocated since we can't change thread states.
+ if (Thread::Current() != nullptr) {
+ total += GetObjectsAllocated();
+ }
+ return total;
}
uint64_t Heap::GetBytesAllocatedEver() const {
for (size_t i = 0; i < kImtSize; i++) {
auto method = methods[i];
DCHECK(method != nullptr);
- SetEmbeddedImTableEntry(i, Runtime::Current()->GetImtConflictMethod(), pointer_size);
+ SetEmbeddedImTableEntry(i, method, pointer_size);
}
PointerArray* table = GetVTableDuringLinking();
CHECK(table != nullptr) << PrettyClass(this);
kVisitRootFlagStartLoggingNewRoots = 0x4,
kVisitRootFlagStopLoggingNewRoots = 0x8,
kVisitRootFlagClearRootLog = 0x10,
+ // Non moving means we can have optimizations where we don't visit some roots if they are
+ // definitely reachable from another location. E.g. ArtMethod and ArtField roots.
+ kVisitRootFlagNonMoving = 0x20,
};
class Runtime {