diff options
| -rw-r--r-- | src/heap.cc | 34 | ||||
| -rw-r--r-- | src/jni_internal.cc | 5 | ||||
| -rw-r--r-- | src/object.cc | 5 | ||||
| -rw-r--r-- | src/thread.cc | 30 | ||||
| -rw-r--r-- | src/thread.h | 5 |
5 files changed, 43 insertions, 36 deletions
diff --git a/src/heap.cc b/src/heap.cc index eae772f2c4..65bc4c02ed 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -150,18 +150,22 @@ void Heap::Destroy() { live_bitmap_ = NULL; } -Object* Heap::AllocObject(Class* klass, size_t num_bytes) { - ScopedHeapLock lock; - DCHECK(klass == NULL - || klass->GetDescriptor() == NULL - || (klass->IsClassClass() && num_bytes >= sizeof(Class)) - || (klass->IsVariableSize() || klass->GetObjectSize() == num_bytes)); - DCHECK(num_bytes >= sizeof(Object)); - Object* obj = AllocateLocked(num_bytes); - if (obj != NULL) { - obj->SetClass(klass); +Object* Heap::AllocObject(Class* klass, size_t byte_count) { + { + ScopedHeapLock lock; + DCHECK(klass == NULL || klass->GetDescriptor() == NULL || + (klass->IsClassClass() && byte_count >= sizeof(Class)) || + (klass->IsVariableSize() || klass->GetObjectSize() == byte_count)); + DCHECK_GE(byte_count, sizeof(Object)); + Object* obj = AllocateLocked(byte_count); + if (obj != NULL) { + obj->SetClass(klass); + return obj; + } } - return obj; + + Thread::Current()->ThrowOutOfMemoryError(klass, byte_count); + return NULL; } bool Heap::IsHeapAddress(const Object* obj) { @@ -340,21 +344,21 @@ Object* Heap::AllocateLocked(Space* space, size_t size) { ++Runtime::Current()->GetStats()->gc_for_alloc_count; ++Thread::Current()->GetStats()->gc_for_alloc_count; } - LOG(INFO) << "GC_FOR_ALLOC: TODO: test"; + LOG(INFO) << "GC_FOR_ALLOC: AllocWithoutGrowth: TODO: test"; CollectGarbageInternal(); ptr = space->AllocWithoutGrowth(size); if (ptr != NULL) { return ptr; } - UNIMPLEMENTED(FATAL) << "No AllocWithGrowth, use larger -Xms -Xmx"; + LOG(INFO) << "GC_FOR_ALLOC: AllocWithGrowth: TODO: test"; // Even that didn't work; this is an exceptional state. // Try harder, growing the heap if necessary. ptr = space->AllocWithGrowth(size); if (ptr != NULL) { //size_t new_footprint = dvmHeapSourceGetIdealFootprint(); size_t new_footprint = space->GetMaxAllowedFootprint(); - // TODO: may want to grow a little bit more so that the amount of + // OLD-TODO: may want to grow a little bit more so that the amount of // free space is equal to the old free space + the // utilization slop for the new allocation. LOG(INFO) << "Grow heap (frag case) to " << new_footprint / MB @@ -368,7 +372,7 @@ Object* Heap::AllocateLocked(Space* space, size_t size) { // spec requires that all SoftReferences have been collected and // cleared before throwing an OOME. - // TODO: wait for the finalizers from the previous GC to finish + // OLD-TODO: wait for the finalizers from the previous GC to finish LOG(INFO) << "Forcing collection of SoftReferences for " << size << "-byte allocation"; CollectGarbageInternal(); diff --git a/src/jni_internal.cc b/src/jni_internal.cc index bc1de521aa..f9d536b250 100644 --- a/src/jni_internal.cc +++ b/src/jni_internal.cc @@ -1803,10 +1803,7 @@ class JNI { String* s = Decode<String*>(ts, java_string); size_t byte_count = s->GetUtfLength(); char* bytes = new char[byte_count + 1]; - if (bytes == NULL) { - ts.Self()->ThrowOutOfMemoryError(); - return NULL; - } + CHECK(bytes != NULL); // bionic aborts anyway. const uint16_t* chars = s->GetCharArray()->GetData() + s->GetOffset(); ConvertUtf16ToModifiedUtf8(bytes, chars, s->GetLength()); bytes[byte_count] = '\0'; diff --git a/src/object.cc b/src/object.cc index 342599e174..1f64faa3f7 100644 --- a/src/object.cc +++ b/src/object.cc @@ -1239,11 +1239,6 @@ Array* Array::Alloc(Class* array_class, int32_t component_count, size_t componen DCHECK(array->IsArrayInstance()); array->SetLength(component_count); } - - // TODO: throw OutOfMemoryError. (here or in Heap::AllocObject?) - CHECK(array != NULL) << PrettyClass(array_class) - << " component_count=" << component_count - << " component_size=" << component_size; return array; } diff --git a/src/thread.cc b/src/thread.cc index a481aa6856..16b8b67a41 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -696,7 +696,8 @@ Thread::Thread() exception_(NULL), suspend_count_(0), class_loader_override_(NULL), - long_jump_context_(NULL) { + long_jump_context_(NULL), + throwing_OOME_(false) { CHECK((sizeof(Thread) % 4) == 0) << sizeof(Thread); } @@ -967,14 +968,14 @@ void Thread::WalkStack(StackVisitor* visitor) const { while (frame.GetSP() != 0) { for ( ; frame.GetMethod() != 0; frame.Next()) { - DCHECK(frame.GetMethod()->IsWithinCode(pc)); - visitor->VisitFrame(frame, pc); - pc = frame.GetReturnPC(); // Move the PC back 2 bytes as a call will frequently terminate the // decoding of a particular instruction and we want to make sure we // get the Dex PC of the instruction with the call and not the // instruction following. - pc -= 2; + if (pc > 0) { pc -= 2; } + DCHECK(frame.GetMethod()->IsWithinCode(pc)); + visitor->VisitFrame(frame, pc); + pc = frame.GetReturnPC(); } if (record == NULL) { break; @@ -992,14 +993,14 @@ void Thread::WalkStackUntilUpCall(StackVisitor* visitor, bool include_upcall) co if (frame.GetSP() != 0) { for ( ; frame.GetMethod() != 0; frame.Next()) { - DCHECK(frame.GetMethod()->IsWithinCode(pc)); - visitor->VisitFrame(frame, pc); - pc = frame.GetReturnPC(); // Move the PC back 2 bytes as a call will frequently terminate the // decoding of a particular instruction and we want to make sure we // get the Dex PC of the instruction with the call and not the // instruction following. - pc -= 2; + if (pc > 0) { pc -= 2; } + DCHECK(frame.GetMethod()->IsWithinCode(pc)); + visitor->VisitFrame(frame, pc); + pc = frame.GetReturnPC(); } if (include_upcall) { visitor->VisitFrame(frame, pc); @@ -1110,8 +1111,15 @@ void Thread::ThrowNewException(const char* exception_class_descriptor, const cha env->DeleteLocalRef(exception_class); } -void Thread::ThrowOutOfMemoryError() { - UNIMPLEMENTED(FATAL); +void Thread::ThrowOutOfMemoryError(Class* c, size_t byte_count) { + if (!throwing_OOME_) { + throwing_OOME_ = true; + ThrowNewException("Ljava/lang/OutOfMemoryError;", NULL); + LOG(ERROR) << "Failed to allocate a " << PrettyDescriptor(c->GetDescriptor()) << " (" << byte_count << " bytes)"; + } else { + UNIMPLEMENTED(FATAL) << "throw one i prepared earlier..."; + } + throwing_OOME_ = false; } class CatchBlockStackVisitor : public Thread::StackVisitor { diff --git a/src/thread.h b/src/thread.h index 7bd6855cad..c898a76650 100644 --- a/src/thread.h +++ b/src/thread.h @@ -285,7 +285,7 @@ class PACKED Thread { void ThrowNewExceptionV(const char* exception_class_descriptor, const char* fmt, va_list ap); // This exception is special, because we need to pre-allocate an instance. - void ThrowOutOfMemoryError(); + void ThrowOutOfMemoryError(Class* c, size_t byte_count); Frame FindExceptionHandler(void* throw_pc, void** handler_pc); @@ -573,6 +573,9 @@ class PACKED Thread { // Thread local, lazily allocated, long jump context. Used to deliver exceptions. Context* long_jump_context_; + // A boolean telling us whether we're recursively throwing OOME. + uint32_t throwing_OOME_; + // TLS key used to retrieve the VM thread object. static pthread_key_t pthread_key_self_; |