Merge "Send ThreadEnd after clearing ThreadGroup."
diff --git a/dex2oat/dex2oat_image_test.cc b/dex2oat/dex2oat_image_test.cc
index 7ddf1c1..1f644c1 100644
--- a/dex2oat/dex2oat_image_test.cc
+++ b/dex2oat/dex2oat_image_test.cc
@@ -311,7 +311,11 @@
{
ProfileCompilationInfo profile;
VisitLibcoreDexes([&profile](MethodReference ref) {
- EXPECT_TRUE(profile.AddMethodIndex(ProfileCompilationInfo::MethodHotness::kFlagHot, ref));
+ uint32_t flags = ProfileCompilationInfo::MethodHotness::kFlagHot |
+ ProfileCompilationInfo::MethodHotness::kFlagStartup;
+ EXPECT_TRUE(profile.AddMethodIndex(
+ static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags),
+ ref));
}, [&profile](TypeReference ref) {
EXPECT_TRUE(profile.AddClassForDex(ref));
}, kMethodFrequency, kTypeFrequency);
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index a80dbf6..dfbe31a 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -961,8 +961,8 @@
if (method_hotness.IsHot() &&
!method_hotness.IsStartup() && !method_hotness.IsPostStartup()) {
std::string name = method_reference.PrettyMethod();
- LOG(WARNING) << "Method " << name << " had a Hot method that wasn't marked "
- << "either start-up or post-startup. Possible corrupted profile?";
+ LOG(FATAL) << "Method " << name << " had a Hot method that wasn't marked "
+ << "either start-up or post-startup. Possible corrupted profile?";
// This is not fatal, so only warn.
}
}
diff --git a/runtime/interpreter/shadow_frame.h b/runtime/interpreter/shadow_frame.h
index 6903af2..80fdadb 100644
--- a/runtime/interpreter/shadow_frame.h
+++ b/runtime/interpreter/shadow_frame.h
@@ -188,9 +188,7 @@
const uint32_t* vreg_ptr = &vregs_[i];
ref = reinterpret_cast<const StackReference<mirror::Object>*>(vreg_ptr)->AsMirrorPtr();
}
- if (kUseReadBarrier) {
- ReadBarrier::AssertToSpaceInvariant(ref);
- }
+ ReadBarrier::MaybeAssertToSpaceInvariant(ref);
if (kVerifyFlags & kVerifyReads) {
VerifyObject(ref);
}
@@ -256,9 +254,7 @@
if (kVerifyFlags & kVerifyWrites) {
VerifyObject(val);
}
- if (kUseReadBarrier) {
- ReadBarrier::AssertToSpaceInvariant(val);
- }
+ ReadBarrier::MaybeAssertToSpaceInvariant(val);
uint32_t* vreg = &vregs_[i];
reinterpret_cast<StackReference<mirror::Object>*>(vreg)->Assign(val);
if (HasReferenceArray()) {
diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc
index 1ed7889..5601317 100644
--- a/runtime/jit/profile_compilation_info.cc
+++ b/runtime/jit/profile_compilation_info.cc
@@ -1704,7 +1704,10 @@
if (m < (number_of_methods / kFavorSplit)) {
method_idx %= kFavorFirstN;
}
- info.AddMethodIndex(MethodHotness::kFlagHot,
+ // Alternate between startup and post startup.
+ uint32_t flags = MethodHotness::kFlagHot;
+ flags |= ((m & 1) != 0) ? MethodHotness::kFlagPostStartup : MethodHotness::kFlagStartup;
+ info.AddMethodIndex(static_cast<MethodHotness::Flag>(flags),
profile_key,
/*method_idx*/ 0,
method_idx,
@@ -1761,8 +1764,13 @@
if (number_of_methods - i == methods_required_in_profile ||
std::rand() % (number_of_methods - i - methods_required_in_profile) == 0) {
uint32_t method_index = (method_start_index + i) % number_of_methods;
- info.AddMethodIndex(MethodHotness::kFlagHot, MethodReference(dex_file.get(),
- method_index));
+ // Alternate between startup and post startup.
+ uint32_t flags = MethodHotness::kFlagHot;
+ flags |= ((method_index & 1) != 0)
+ ? MethodHotness::kFlagPostStartup
+ : MethodHotness::kFlagStartup;
+ info.AddMethodIndex(static_cast<MethodHotness::Flag>(flags),
+ MethodReference(dex_file.get(), method_index));
methods_required_in_profile--;
}
}
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index b2f6c03..9a42c29 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -635,29 +635,35 @@
}
if (boot_image_tables != nullptr) {
- // Map boot image tables into the .bss. The reserved size must match size of the tables.
- size_t reserved_size = static_cast<size_t>(boot_image_tables_end - boot_image_tables);
- size_t tables_size = 0u;
- for (gc::space::ImageSpace* space : Runtime::Current()->GetHeap()->GetBootImageSpaces()) {
- tables_size += space->GetImageHeader().GetBootImageConstantTablesSize();
- DCHECK_ALIGNED(tables_size, kPageSize);
- }
- if (tables_size != reserved_size) {
- *error_msg = StringPrintf("In oat file '%s' found unexpected boot image table sizes, "
- " %zu bytes, should be %zu.",
- GetLocation().c_str(),
- reserved_size,
- tables_size);
- return false;
- }
- for (gc::space::ImageSpace* space : Runtime::Current()->GetHeap()->GetBootImageSpaces()) {
- uint32_t current_tables_size = space->GetImageHeader().GetBootImageConstantTablesSize();
- if (current_tables_size != 0u && !MapConstantTables(space, boot_image_tables)) {
+ Runtime* runtime = Runtime::Current();
+ if (UNLIKELY(runtime == nullptr)) {
+ // This must be oatdump without boot image. Make sure the .bss is inaccessible.
+ mprotect(const_cast<uint8_t*>(BssBegin()), BssSize(), PROT_NONE);
+ } else {
+ // Map boot image tables into the .bss. The reserved size must match size of the tables.
+ size_t reserved_size = static_cast<size_t>(boot_image_tables_end - boot_image_tables);
+ size_t tables_size = 0u;
+ for (gc::space::ImageSpace* space : runtime->GetHeap()->GetBootImageSpaces()) {
+ tables_size += space->GetImageHeader().GetBootImageConstantTablesSize();
+ DCHECK_ALIGNED(tables_size, kPageSize);
+ }
+ if (tables_size != reserved_size) {
+ *error_msg = StringPrintf("In oat file '%s' found unexpected boot image table sizes, "
+ " %zu bytes, should be %zu.",
+ GetLocation().c_str(),
+ reserved_size,
+ tables_size);
return false;
}
- boot_image_tables += current_tables_size;
+ for (gc::space::ImageSpace* space : Runtime::Current()->GetHeap()->GetBootImageSpaces()) {
+ uint32_t current_tables_size = space->GetImageHeader().GetBootImageConstantTablesSize();
+ if (current_tables_size != 0u && !MapConstantTables(space, boot_image_tables)) {
+ return false;
+ }
+ boot_image_tables += current_tables_size;
+ }
+ DCHECK(boot_image_tables == boot_image_tables_end);
}
- DCHECK(boot_image_tables == boot_image_tables_end);
}
return true;
}
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index d8b6237..f94923e 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -166,10 +166,9 @@
<< line_number << ")";
}
}
- if (clear_exception_) {
- // Exception was cleared as part of delivery.
- DCHECK(!self_->IsExceptionPending());
- } else {
+ // Exception was cleared as part of delivery.
+ DCHECK(!self_->IsExceptionPending());
+ if (!clear_exception_) {
// Put exception back in root set with clear throw location.
self_->SetException(exception_ref.Get());
}
diff --git a/runtime/quick_exception_handler.h b/runtime/quick_exception_handler.h
index 8090f9b..12b63c9 100644
--- a/runtime/quick_exception_handler.h
+++ b/runtime/quick_exception_handler.h
@@ -112,6 +112,10 @@
handler_dex_pc_ = dex_pc;
}
+ bool GetClearException() const {
+ return clear_exception_;
+ }
+
void SetClearException(bool clear_exception) {
clear_exception_ = clear_exception;
}
diff --git a/runtime/read_barrier.h b/runtime/read_barrier.h
index 45e78bc..00674b2 100644
--- a/runtime/read_barrier.h
+++ b/runtime/read_barrier.h
@@ -89,6 +89,14 @@
static void AssertToSpaceInvariant(GcRootSource* gc_root_source, mirror::Object* ref)
REQUIRES_SHARED(Locks::mutator_lock_);
+ // Without the holder object, and only with the read barrier configuration (no-op otherwise).
+ static void MaybeAssertToSpaceInvariant(mirror::Object* ref)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (kUseReadBarrier) {
+ AssertToSpaceInvariant(ref);
+ }
+ }
+
// ALWAYS_INLINE on this caused a performance regression b/26744236.
static mirror::Object* Mark(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 198edc7..524e73d 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -3080,6 +3080,8 @@
UNREACHABLE();
}
+ ReadBarrier::MaybeAssertToSpaceInvariant(exception.Ptr());
+
// This is a real exception: let the instrumentation know about it.
instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
if (instrumentation->HasExceptionThrownListeners() &&
@@ -3121,6 +3123,15 @@
QuickExceptionHandler exception_handler(this, false);
exception_handler.FindCatch(exception);
exception_handler.UpdateInstrumentationStack();
+ if (exception_handler.GetClearException()) {
+ // Exception was cleared as part of delivery.
+ DCHECK(!IsExceptionPending());
+ } else {
+ // Exception was put back with a throw location.
+ DCHECK(IsExceptionPending());
+ // Check the to-space invariant on the re-installed exception (if applicable).
+ ReadBarrier::MaybeAssertToSpaceInvariant(GetException());
+ }
exception_handler.DoLongJump();
}
diff --git a/test/638-checker-inline-caches/profile b/test/638-checker-inline-caches/profile
index 1ca6d7b..7756a16 100644
--- a/test/638-checker-inline-caches/profile
+++ b/test/638-checker-inline-caches/profile
@@ -1,6 +1,6 @@
-LMain;->inlineMonomorphicSubA(LSuper;)I+LSubA;
-LMain;->inlinePolymophicSubASubB(LSuper;)I+LSubA;,LSubB;
-LMain;->inlinePolymophicCrossDexSubASubC(LSuper;)I+LSubA;,LSubC;
-LMain;->inlineMegamorphic(LSuper;)I+LSubA;,LSubB;,LSubC;,LSubD;,LSubE;
-LMain;->inlineMissingTypes(LSuper;)I+missing_types
-LMain;->noInlineCache(LSuper;)I
+HSLMain;->inlineMonomorphicSubA(LSuper;)I+LSubA;
+HSLMain;->inlinePolymophicSubASubB(LSuper;)I+LSubA;,LSubB;
+HSLMain;->inlinePolymophicCrossDexSubASubC(LSuper;)I+LSubA;,LSubC;
+HSLMain;->inlineMegamorphic(LSuper;)I+LSubA;,LSubB;,LSubC;,LSubD;,LSubE;
+HSLMain;->inlineMissingTypes(LSuper;)I+missing_types
+HSLMain;->noInlineCache(LSuper;)I
diff --git a/test/643-checker-bogus-ic/profile b/test/643-checker-bogus-ic/profile
index cbf7796..540a935 100644
--- a/test/643-checker-bogus-ic/profile
+++ b/test/643-checker-bogus-ic/profile
@@ -1,2 +1,2 @@
-LMain;->inlineMonomorphic(LMain;)I+LUnrelated;
-LMain;->inlinePolymorphic(LMain;)I+LUnrelated;,LMain;
+SHLMain;->inlineMonomorphic(LMain;)I+LUnrelated;
+SHLMain;->inlinePolymorphic(LMain;)I+LUnrelated;,LMain;
diff --git a/test/648-inline-caches-unresolved/profile b/test/648-inline-caches-unresolved/profile
index 92c0a41..06bc8ad 100644
--- a/test/648-inline-caches-unresolved/profile
+++ b/test/648-inline-caches-unresolved/profile
@@ -1 +1 @@
-LMain;->inlineMonomorphicUnresolvedSuper(Ljava/lang/Object;)Ljava/lang/String;+LSubclass;
+SHLMain;->inlineMonomorphicUnresolvedSuper(Ljava/lang/Object;)Ljava/lang/String;+LSubclass;
diff --git a/test/661-oat-writer-layout/expected.txt b/test/661-oat-writer-layout/expected.txt
index db28e4f..b7ad70a 100644
--- a/test/661-oat-writer-layout/expected.txt
+++ b/test/661-oat-writer-layout/expected.txt
@@ -8,15 +8,6 @@
C::m_a$$$
C::m_b$$$
C::m_c$$$
-A::m_a$Hot$$
-A::m_b$Hot$$
-A::m_c$Hot$$
-B::m_a$Hot$$
-B::m_b$Hot$$
-B::m_c$Hot$$
-C::m_a$Hot$$
-C::m_b$Hot$$
-C::m_c$Hot$$
A::m_a$$Startup$
A::m_b$$Startup$
A::m_c$$Startup$
diff --git a/test/661-oat-writer-layout/profile b/test/661-oat-writer-layout/profile
index 5406484..cf307c2 100644
--- a/test/661-oat-writer-layout/profile
+++ b/test/661-oat-writer-layout/profile
@@ -1,60 +1,51 @@
-HLA;->m_a$Hot$$()V
SLA;->m_a$$Startup$()V
HSLA;->m_a$Hot$Startup$()V
PLA;->m_a$$$Poststartup()V
HPLA;->m_a$Hot$$Poststartup()V
SPLA;->m_a$$Startup$Poststartup()V
HSPLA;->m_a$Hot$Startup$Poststartup()V
-HLA;->m_b$Hot$$()V
SLA;->m_b$$Startup$()V
HSLA;->m_b$Hot$Startup$()V
PLA;->m_b$$$Poststartup()V
HPLA;->m_b$Hot$$Poststartup()V
SPLA;->m_b$$Startup$Poststartup()V
HSPLA;->m_b$Hot$Startup$Poststartup()V
-HLA;->m_c$Hot$$()V
SLA;->m_c$$Startup$()V
HSLA;->m_c$Hot$Startup$()V
PLA;->m_c$$$Poststartup()V
HPLA;->m_c$Hot$$Poststartup()V
SPLA;->m_c$$Startup$Poststartup()V
HSPLA;->m_c$Hot$Startup$Poststartup()V
-HLB;->m_a$Hot$$()V
SLB;->m_a$$Startup$()V
HSLB;->m_a$Hot$Startup$()V
PLB;->m_a$$$Poststartup()V
HPLB;->m_a$Hot$$Poststartup()V
SPLB;->m_a$$Startup$Poststartup()V
HSPLB;->m_a$Hot$Startup$Poststartup()V
-HLB;->m_b$Hot$$()V
SLB;->m_b$$Startup$()V
HSLB;->m_b$Hot$Startup$()V
PLB;->m_b$$$Poststartup()V
HPLB;->m_b$Hot$$Poststartup()V
SPLB;->m_b$$Startup$Poststartup()V
HSPLB;->m_b$Hot$Startup$Poststartup()V
-HLB;->m_c$Hot$$()V
SLB;->m_c$$Startup$()V
HSLB;->m_c$Hot$Startup$()V
PLB;->m_c$$$Poststartup()V
HPLB;->m_c$Hot$$Poststartup()V
SPLB;->m_c$$Startup$Poststartup()V
HSPLB;->m_c$Hot$Startup$Poststartup()V
-HLC;->m_a$Hot$$()V
SLC;->m_a$$Startup$()V
HSLC;->m_a$Hot$Startup$()V
PLC;->m_a$$$Poststartup()V
HPLC;->m_a$Hot$$Poststartup()V
SPLC;->m_a$$Startup$Poststartup()V
HSPLC;->m_a$Hot$Startup$Poststartup()V
-HLC;->m_b$Hot$$()V
SLC;->m_b$$Startup$()V
HSLC;->m_b$Hot$Startup$()V
PLC;->m_b$$$Poststartup()V
HPLC;->m_b$Hot$$Poststartup()V
SPLC;->m_b$$Startup$Poststartup()V
HSPLC;->m_b$Hot$Startup$Poststartup()V
-HLC;->m_c$Hot$$()V
SLC;->m_c$$Startup$()V
HSLC;->m_c$Hot$Startup$()V
PLC;->m_c$$$Poststartup()V
diff --git a/test/661-oat-writer-layout/src/Test.java b/test/661-oat-writer-layout/src/Test.java
index db67b48..f862e37 100644
--- a/test/661-oat-writer-layout/src/Test.java
+++ b/test/661-oat-writer-layout/src/Test.java
@@ -13,86 +13,78 @@
// limitations under the License.
import java.lang.reflect.Method;
+import java.util.ArrayList;
public class Test {
// Returns list of all methods in Generated.java
// This is to avoid having to introspect classes with extra code
// (for example, we ignore <init> methods).
public static Method[] getTestMethods() throws NoSuchMethodException, SecurityException {
- Method[] all_methods = new Method[72];
- all_methods[0] = A.class.getDeclaredMethod("m_a$$$");
- all_methods[1] = A.class.getDeclaredMethod("m_a$Hot$$");
- all_methods[2] = A.class.getDeclaredMethod("m_a$$Startup$");
- all_methods[3] = A.class.getDeclaredMethod("m_a$Hot$Startup$");
- all_methods[4] = A.class.getDeclaredMethod("m_a$$$Poststartup");
- all_methods[5] = A.class.getDeclaredMethod("m_a$Hot$$Poststartup");
- all_methods[6] = A.class.getDeclaredMethod("m_a$$Startup$Poststartup");
- all_methods[7] = A.class.getDeclaredMethod("m_a$Hot$Startup$Poststartup");
- all_methods[8] = A.class.getDeclaredMethod("m_b$$$");
- all_methods[9] = A.class.getDeclaredMethod("m_b$Hot$$");
- all_methods[10] = A.class.getDeclaredMethod("m_b$$Startup$");
- all_methods[11] = A.class.getDeclaredMethod("m_b$Hot$Startup$");
- all_methods[12] = A.class.getDeclaredMethod("m_b$$$Poststartup");
- all_methods[13] = A.class.getDeclaredMethod("m_b$Hot$$Poststartup");
- all_methods[14] = A.class.getDeclaredMethod("m_b$$Startup$Poststartup");
- all_methods[15] = A.class.getDeclaredMethod("m_b$Hot$Startup$Poststartup");
- all_methods[16] = A.class.getDeclaredMethod("m_c$$$");
- all_methods[17] = A.class.getDeclaredMethod("m_c$Hot$$");
- all_methods[18] = A.class.getDeclaredMethod("m_c$$Startup$");
- all_methods[19] = A.class.getDeclaredMethod("m_c$Hot$Startup$");
- all_methods[20] = A.class.getDeclaredMethod("m_c$$$Poststartup");
- all_methods[21] = A.class.getDeclaredMethod("m_c$Hot$$Poststartup");
- all_methods[22] = A.class.getDeclaredMethod("m_c$$Startup$Poststartup");
- all_methods[23] = A.class.getDeclaredMethod("m_c$Hot$Startup$Poststartup");
- all_methods[24] = B.class.getDeclaredMethod("m_a$$$");
- all_methods[25] = B.class.getDeclaredMethod("m_a$Hot$$");
- all_methods[26] = B.class.getDeclaredMethod("m_a$$Startup$");
- all_methods[27] = B.class.getDeclaredMethod("m_a$Hot$Startup$");
- all_methods[28] = B.class.getDeclaredMethod("m_a$$$Poststartup");
- all_methods[29] = B.class.getDeclaredMethod("m_a$Hot$$Poststartup");
- all_methods[30] = B.class.getDeclaredMethod("m_a$$Startup$Poststartup");
- all_methods[31] = B.class.getDeclaredMethod("m_a$Hot$Startup$Poststartup");
- all_methods[32] = B.class.getDeclaredMethod("m_b$$$");
- all_methods[33] = B.class.getDeclaredMethod("m_b$Hot$$");
- all_methods[34] = B.class.getDeclaredMethod("m_b$$Startup$");
- all_methods[35] = B.class.getDeclaredMethod("m_b$Hot$Startup$");
- all_methods[36] = B.class.getDeclaredMethod("m_b$$$Poststartup");
- all_methods[37] = B.class.getDeclaredMethod("m_b$Hot$$Poststartup");
- all_methods[38] = B.class.getDeclaredMethod("m_b$$Startup$Poststartup");
- all_methods[39] = B.class.getDeclaredMethod("m_b$Hot$Startup$Poststartup");
- all_methods[40] = B.class.getDeclaredMethod("m_c$$$");
- all_methods[41] = B.class.getDeclaredMethod("m_c$Hot$$");
- all_methods[42] = B.class.getDeclaredMethod("m_c$$Startup$");
- all_methods[43] = B.class.getDeclaredMethod("m_c$Hot$Startup$");
- all_methods[44] = B.class.getDeclaredMethod("m_c$$$Poststartup");
- all_methods[45] = B.class.getDeclaredMethod("m_c$Hot$$Poststartup");
- all_methods[46] = B.class.getDeclaredMethod("m_c$$Startup$Poststartup");
- all_methods[47] = B.class.getDeclaredMethod("m_c$Hot$Startup$Poststartup");
- all_methods[48] = C.class.getDeclaredMethod("m_a$$$");
- all_methods[49] = C.class.getDeclaredMethod("m_a$Hot$$");
- all_methods[50] = C.class.getDeclaredMethod("m_a$$Startup$");
- all_methods[51] = C.class.getDeclaredMethod("m_a$Hot$Startup$");
- all_methods[52] = C.class.getDeclaredMethod("m_a$$$Poststartup");
- all_methods[53] = C.class.getDeclaredMethod("m_a$Hot$$Poststartup");
- all_methods[54] = C.class.getDeclaredMethod("m_a$$Startup$Poststartup");
- all_methods[55] = C.class.getDeclaredMethod("m_a$Hot$Startup$Poststartup");
- all_methods[56] = C.class.getDeclaredMethod("m_b$$$");
- all_methods[57] = C.class.getDeclaredMethod("m_b$Hot$$");
- all_methods[58] = C.class.getDeclaredMethod("m_b$$Startup$");
- all_methods[59] = C.class.getDeclaredMethod("m_b$Hot$Startup$");
- all_methods[60] = C.class.getDeclaredMethod("m_b$$$Poststartup");
- all_methods[61] = C.class.getDeclaredMethod("m_b$Hot$$Poststartup");
- all_methods[62] = C.class.getDeclaredMethod("m_b$$Startup$Poststartup");
- all_methods[63] = C.class.getDeclaredMethod("m_b$Hot$Startup$Poststartup");
- all_methods[64] = C.class.getDeclaredMethod("m_c$$$");
- all_methods[65] = C.class.getDeclaredMethod("m_c$Hot$$");
- all_methods[66] = C.class.getDeclaredMethod("m_c$$Startup$");
- all_methods[67] = C.class.getDeclaredMethod("m_c$Hot$Startup$");
- all_methods[68] = C.class.getDeclaredMethod("m_c$$$Poststartup");
- all_methods[69] = C.class.getDeclaredMethod("m_c$Hot$$Poststartup");
- all_methods[70] = C.class.getDeclaredMethod("m_c$$Startup$Poststartup");
- all_methods[71] = C.class.getDeclaredMethod("m_c$Hot$Startup$Poststartup");
- return all_methods;
+ ArrayList<Method> all_methods = new ArrayList<Method>();
+ all_methods.add(A.class.getDeclaredMethod("m_a$$$"));
+ all_methods.add(A.class.getDeclaredMethod("m_a$$Startup$"));
+ all_methods.add(A.class.getDeclaredMethod("m_a$Hot$Startup$"));
+ all_methods.add(A.class.getDeclaredMethod("m_a$$$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_a$Hot$$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_a$$Startup$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_a$Hot$Startup$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_b$$$"));
+ all_methods.add(A.class.getDeclaredMethod("m_b$$Startup$"));
+ all_methods.add(A.class.getDeclaredMethod("m_b$Hot$Startup$"));
+ all_methods.add(A.class.getDeclaredMethod("m_b$$$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_b$Hot$$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_b$$Startup$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_b$Hot$Startup$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_c$$$"));
+ all_methods.add(A.class.getDeclaredMethod("m_c$$Startup$"));
+ all_methods.add(A.class.getDeclaredMethod("m_c$Hot$Startup$"));
+ all_methods.add(A.class.getDeclaredMethod("m_c$$$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_c$Hot$$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_c$$Startup$Poststartup"));
+ all_methods.add(A.class.getDeclaredMethod("m_c$Hot$Startup$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_a$$$"));
+ all_methods.add(B.class.getDeclaredMethod("m_a$$Startup$"));
+ all_methods.add(B.class.getDeclaredMethod("m_a$Hot$Startup$"));
+ all_methods.add(B.class.getDeclaredMethod("m_a$$$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_a$Hot$$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_a$$Startup$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_a$Hot$Startup$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_b$$$"));
+ all_methods.add(B.class.getDeclaredMethod("m_b$$Startup$"));
+ all_methods.add(B.class.getDeclaredMethod("m_b$Hot$Startup$"));
+ all_methods.add(B.class.getDeclaredMethod("m_b$$$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_b$Hot$$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_b$$Startup$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_b$Hot$Startup$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_c$$$"));
+ all_methods.add(B.class.getDeclaredMethod("m_c$$Startup$"));
+ all_methods.add(B.class.getDeclaredMethod("m_c$Hot$Startup$"));
+ all_methods.add(B.class.getDeclaredMethod("m_c$$$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_c$Hot$$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_c$$Startup$Poststartup"));
+ all_methods.add(B.class.getDeclaredMethod("m_c$Hot$Startup$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_a$$$"));
+ all_methods.add(C.class.getDeclaredMethod("m_a$$Startup$"));
+ all_methods.add(C.class.getDeclaredMethod("m_a$Hot$Startup$"));
+ all_methods.add(C.class.getDeclaredMethod("m_a$$$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_a$Hot$$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_a$$Startup$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_a$Hot$Startup$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_b$$$"));
+ all_methods.add(C.class.getDeclaredMethod("m_b$$Startup$"));
+ all_methods.add(C.class.getDeclaredMethod("m_b$Hot$Startup$"));
+ all_methods.add(C.class.getDeclaredMethod("m_b$$$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_b$Hot$$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_b$$Startup$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_b$Hot$Startup$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_c$$$"));
+ all_methods.add(C.class.getDeclaredMethod("m_c$$Startup$"));
+ all_methods.add(C.class.getDeclaredMethod("m_c$Hot$Startup$"));
+ all_methods.add(C.class.getDeclaredMethod("m_c$$$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_c$Hot$$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_c$$Startup$Poststartup"));
+ all_methods.add(C.class.getDeclaredMethod("m_c$Hot$Startup$Poststartup"));
+ return all_methods.toArray(new Method[all_methods.size()]);
}
}
diff --git a/test/707-checker-invalid-profile/profile b/test/707-checker-invalid-profile/profile
index 5979dd2..f142c40 100644
--- a/test/707-checker-invalid-profile/profile
+++ b/test/707-checker-invalid-profile/profile
@@ -1,4 +1,4 @@
-LMain;->attemptInlineMonomorphic(LMain;)I+invalid_class
-LMain;->attemptInlinePolymorphic(LMain;)I+LMain;,invalid_class
-LMain;->invalid_method
+SHLMain;->attemptInlineMonomorphic(LMain;)I+invalid_class
+SHLMain;->attemptInlinePolymorphic(LMain;)I+LMain;,invalid_class
+SHLMain;->invalid_method
invalid_class
\ No newline at end of file
diff --git a/tools/ahat/src/Main.java b/tools/ahat/src/Main.java
index 623a865..31c485d 100644
--- a/tools/ahat/src/Main.java
+++ b/tools/ahat/src/Main.java
@@ -18,6 +18,7 @@
import com.android.ahat.heapdump.AhatSnapshot;
import com.android.ahat.heapdump.Diff;
+import com.android.ahat.heapdump.HprofFormatException;
import com.android.ahat.heapdump.Parser;
import com.android.ahat.proguard.ProguardMap;
import com.sun.net.httpserver.HttpServer;
@@ -47,7 +48,7 @@
out.println("");
}
- public static void main(String[] args) throws Exception {
+ public static void main(String[] args) {
int port = 7100;
for (String arg : args) {
if (arg.equals("--help")) {
@@ -104,34 +105,40 @@
return;
}
- // Launch the server before parsing the hprof file so we get
- // BindExceptions quickly.
- InetAddress loopback = InetAddress.getLoopbackAddress();
- InetSocketAddress addr = new InetSocketAddress(loopback, port);
- HttpServer server = HttpServer.create(addr, 0);
+ try {
+ // Launch the server before parsing the hprof file so we get
+ // BindExceptions quickly.
+ InetAddress loopback = InetAddress.getLoopbackAddress();
+ InetSocketAddress addr = new InetSocketAddress(loopback, port);
+ System.out.println("Preparing " + addr + " ...");
+ HttpServer server = HttpServer.create(addr, 0);
- System.out.println("Processing hprof file...");
- AhatSnapshot ahat = Parser.parseHeapDump(hprof, map);
+ System.out.println("Processing '" + hprof + "' ...");
+ AhatSnapshot ahat = Parser.parseHeapDump(hprof, map);
- if (hprofbase != null) {
- System.out.println("Processing baseline hprof file...");
- AhatSnapshot base = Parser.parseHeapDump(hprofbase, mapbase);
+ if (hprofbase != null) {
+ System.out.println("Processing '" + hprofbase + "' ...");
+ AhatSnapshot base = Parser.parseHeapDump(hprofbase, mapbase);
- System.out.println("Diffing hprof files...");
- Diff.snapshots(ahat, base);
+ System.out.println("Diffing heap dumps ...");
+ Diff.snapshots(ahat, base);
+ }
+
+ server.createContext("/", new AhatHttpHandler(new OverviewHandler(ahat, hprof, hprofbase)));
+ server.createContext("/rooted", new AhatHttpHandler(new RootedHandler(ahat)));
+ server.createContext("/object", new AhatHttpHandler(new ObjectHandler(ahat)));
+ server.createContext("/objects", new AhatHttpHandler(new ObjectsHandler(ahat)));
+ server.createContext("/site", new AhatHttpHandler(new SiteHandler(ahat)));
+ server.createContext("/bitmap", new BitmapHandler(ahat));
+ server.createContext("/style.css", new StaticHandler("style.css", "text/css"));
+ server.setExecutor(Executors.newFixedThreadPool(1));
+ System.out.println("Server started on localhost:" + port);
+
+ server.start();
+ } catch (HprofFormatException|IOException e) {
+ System.err.println("Unable to launch ahat:");
+ e.printStackTrace();
}
-
- server.createContext("/", new AhatHttpHandler(new OverviewHandler(ahat, hprof, hprofbase)));
- server.createContext("/rooted", new AhatHttpHandler(new RootedHandler(ahat)));
- server.createContext("/object", new AhatHttpHandler(new ObjectHandler(ahat)));
- server.createContext("/objects", new AhatHttpHandler(new ObjectsHandler(ahat)));
- server.createContext("/site", new AhatHttpHandler(new SiteHandler(ahat)));
- server.createContext("/bitmap", new BitmapHandler(ahat));
- server.createContext("/style.css", new StaticHandler("style.css", "text/css"));
- server.setExecutor(Executors.newFixedThreadPool(1));
- System.out.println("Server started on localhost:" + port);
-
- server.start();
}
}
diff --git a/tools/ahat/src/heapdump/HprofFormatException.java b/tools/ahat/src/heapdump/HprofFormatException.java
index 55e8958..0e128cd 100644
--- a/tools/ahat/src/heapdump/HprofFormatException.java
+++ b/tools/ahat/src/heapdump/HprofFormatException.java
@@ -20,4 +20,8 @@
public HprofFormatException(String msg) {
super(msg);
}
+
+ public HprofFormatException(String msg, Exception cause) {
+ super(msg, cause);
+ }
}
diff --git a/tools/ahat/src/heapdump/Parser.java b/tools/ahat/src/heapdump/Parser.java
index 3d5f95f..756b7d2 100644
--- a/tools/ahat/src/heapdump/Parser.java
+++ b/tools/ahat/src/heapdump/Parser.java
@@ -19,6 +19,7 @@
import com.android.ahat.proguard.ProguardMap;
import java.io.File;
import java.io.IOException;
+import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
@@ -48,7 +49,11 @@
*/
public static AhatSnapshot parseHeapDump(File hprof, ProguardMap map)
throws IOException, HprofFormatException {
- return parseHeapDump(new HprofBuffer(hprof), map);
+ try {
+ return parseHeapDump(new HprofBuffer(hprof), map);
+ } catch (BufferUnderflowException e) {
+ throw new HprofFormatException("Unexpected end of file", e);
+ }
}
/**
@@ -56,11 +61,15 @@
*/
public static AhatSnapshot parseHeapDump(ByteBuffer hprof, ProguardMap map)
throws IOException, HprofFormatException {
- return parseHeapDump(new HprofBuffer(hprof), map);
+ try {
+ return parseHeapDump(new HprofBuffer(hprof), map);
+ } catch (BufferUnderflowException e) {
+ throw new HprofFormatException("Unexpected end of file", e);
+ }
}
private static AhatSnapshot parseHeapDump(HprofBuffer hprof, ProguardMap map)
- throws IOException, HprofFormatException {
+ throws IOException, HprofFormatException, BufferUnderflowException {
// Read, and mostly ignore, the hprof header info.
{
StringBuilder format = new StringBuilder();
@@ -409,6 +418,12 @@
break;
}
+ case 0x8a: { // ROOT FINALIZING (ANDROID)
+ long objectId = hprof.getId();
+ roots.add(new RootData(objectId, RootType.FINALIZING));
+ break;
+ }
+
case 0x8b: { // ROOT DEBUGGER (ANDROID)
long objectId = hprof.getId();
roots.add(new RootData(objectId, RootType.DEBUGGER));
diff --git a/tools/ahat/src/heapdump/RootType.java b/tools/ahat/src/heapdump/RootType.java
index 7165b83..af552ea 100644
--- a/tools/ahat/src/heapdump/RootType.java
+++ b/tools/ahat/src/heapdump/RootType.java
@@ -29,7 +29,8 @@
DEBUGGER (1 << 9),
VM_INTERNAL (1 << 10),
UNKNOWN (1 << 11),
- JNI_MONITOR (1 << 12);
+ JNI_MONITOR (1 << 12),
+ FINALIZING (1 << 13);
public final int mask;
diff --git a/tools/ahat/test-dump/L.hprof b/tools/ahat/test-dump/L.hprof
index cf82557..1acdf79 100644
--- a/tools/ahat/test-dump/L.hprof
+++ b/tools/ahat/test-dump/L.hprof
Binary files differ
diff --git a/tools/ahat/test-dump/README.txt b/tools/ahat/test-dump/README.txt
index 344271c..e7ea584 100644
--- a/tools/ahat/test-dump/README.txt
+++ b/tools/ahat/test-dump/README.txt
@@ -1,5 +1,7 @@
Main.java - A program used to generate a heap dump used for tests.
-L.hprof - A version of the test dump generated on Android L.
+L.hprof - A version of the test dump generated on Android L,
+ with one of the ROOT_DEBUGGER records manually changed to a
+ ROOT_FINALIZING record.
O.hprof - A version of the test dump generated on Android O.
RI.hprof - A version of the test dump generated on the reference implementation.