Fix accidental IMT and root marking regression
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
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 84da475..3ce646f 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1264,12 +1264,18 @@
// 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_) {
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 7c92b18..042c33f 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -2083,7 +2083,7 @@
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();
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 91a0e8a..1c9c412 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -590,7 +590,8 @@
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 {
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index fbde494..59d0259 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -1630,7 +1630,12 @@
}
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 {
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 482640b..f0b7bfd 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -806,7 +806,7 @@
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);
diff --git a/runtime/runtime.h b/runtime/runtime.h
index f6f9725..e569333 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -98,6 +98,9 @@
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 {