Merge "Fix infinite loop when calling SetStatus after OOM."
diff --git a/runtime/gc/accounting/card_table.cc b/runtime/gc/accounting/card_table.cc
index a95c003..ceb42e5 100644
--- a/runtime/gc/accounting/card_table.cc
+++ b/runtime/gc/accounting/card_table.cc
@@ -83,8 +83,6 @@
CardTable::CardTable(MemMap* mem_map, byte* biased_begin, size_t offset)
: mem_map_(mem_map), biased_begin_(biased_begin), offset_(offset) {
- byte* __attribute__((unused)) begin = mem_map_->Begin() + offset_;
- byte* __attribute__((unused)) end = mem_map_->End();
}
void CardTable::ClearSpaceCards(space::ContinuousSpace* space) {
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index 419af30..7d3fd2d 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -63,6 +63,7 @@
// If we have a thread local allocation we don't need to update bytes allocated.
if (allocator == kAllocatorTypeTLAB && byte_count <= self->TlabSize()) {
obj = self->AllocTlab(byte_count);
+ DCHECK(obj != nullptr) << "AllocTlab can't fail";
obj->SetClass(klass);
if (kUseBakerOrBrooksReadBarrier) {
if (kUseBrooksReadBarrier) {
@@ -71,7 +72,8 @@
obj->AssertReadBarrierPointer();
}
bytes_allocated = byte_count;
- pre_fence_visitor(obj, bytes_allocated);
+ usable_size = bytes_allocated;
+ pre_fence_visitor(obj, usable_size);
QuasiAtomic::ThreadFenceForConstructor();
} else {
obj = TryToAllocate<kInstrumented, false>(self, allocator, byte_count, &bytes_allocated,
@@ -111,13 +113,13 @@
WriteBarrierField(obj, mirror::Object::ClassOffset(), klass);
}
pre_fence_visitor(obj, usable_size);
- if (kIsDebugBuild && Runtime::Current()->IsStarted()) {
- CHECK_LE(obj->SizeOf(), usable_size);
- }
new_num_bytes_allocated =
static_cast<size_t>(num_bytes_allocated_.FetchAndAddSequentiallyConsistent(bytes_allocated))
+ bytes_allocated;
}
+ if (kIsDebugBuild && Runtime::Current()->IsStarted()) {
+ CHECK_LE(obj->SizeOf(), usable_size);
+ }
// TODO: Deprecate.
if (kInstrumented) {
if (Runtime::Current()->HasStatsEnabled()) {
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 371e984..be05fb8 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -88,18 +88,22 @@
Handle<mirror::ArtMethod> old_throw_method(hs.NewHandle(old_throw_location.GetMethod()));
uint32_t old_throw_dex_pc = old_throw_location.GetDexPc();
bool is_exception_reported = self->IsExceptionReportedToInstrumentation();
- // clear exception to call FindSystemClass
- self->ClearException();
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- Class* eiie_class = class_linker->FindSystemClass(self,
- "Ljava/lang/ExceptionInInitializerError;");
- CHECK(!self->IsExceptionPending());
-
- // Only verification errors, not initialization problems, should set a verify error.
- // This is to ensure that ThrowEarlierClassFailure will throw NoClassDefFoundError in that case.
- Class* exception_class = old_exception->GetClass();
- if (!eiie_class->IsAssignableFrom(exception_class)) {
- SetVerifyErrorClass(exception_class);
+ Class* eiie_class;
+ // Do't attempt to use FindClass if we have an OOM error since this can try to do more
+ // allocations and may cause infinite loops.
+ if (old_exception.Get() == nullptr ||
+ old_exception->GetClass()->GetDescriptor() != "Ljava/lang/OutOfMemoryError;") {
+ // Clear exception to call FindSystemClass.
+ self->ClearException();
+ eiie_class = Runtime::Current()->GetClassLinker()->FindSystemClass(
+ self, "Ljava/lang/ExceptionInInitializerError;");
+ CHECK(!self->IsExceptionPending());
+ // Only verification errors, not initialization problems, should set a verify error.
+ // This is to ensure that ThrowEarlierClassFailure will throw NoClassDefFoundError in that case.
+ Class* exception_class = old_exception->GetClass();
+ if (!eiie_class->IsAssignableFrom(exception_class)) {
+ SetVerifyErrorClass(exception_class);
+ }
}
// Restore exception.