void uReleaseStruct(uType* type, void* address) { #if DEBUG_ARC >= 4 Xli::Error->WriteFormat("release %s [struct] (%d bytes)%s\n", type->FullName, type->ValueSize, uGetCaller().Ptr()); #endif for (size_t i = 0; i < type->Refs.StrongCount; i++) { uObject*& ptr = *(uObject**)((uint8_t*)address + type->Refs.Strong[i].Value); uRelease(ptr); ptr = NULL; } for (size_t i = 0; i < type->Refs.WeakCount; i++) uStoreWeak((uWeakObject**)((uint8_t*)address + type->Refs.Weak[i].Value), NULL); }
uAutoReleasePool::~uAutoReleasePool() { uThreadData* thread = uGetThreadData(); uAutoReleaseFrame* frame = thread->AutoReleasePtr; U_ASSERT(thread->AutoReleasePtr >= thread->AutoReleaseStack); for (size_t i = frame->StartIndex; i < thread->AutoReleaseList.Length(); i++) { uObject* object = thread->AutoReleaseList[i]; #ifdef DEBUG_ARC frame->AllocCount++; frame->AllocSize += object->__size; #endif uRelease(object); } #if DEBUG_ARC >= 1 Xli::Error->WriteFormat("--- Alloc'd %d objects (%d bytes), Free'd %d objects (%d bytes) ---\n", frame->AllocCount, frame->AllocSize, frame->FreeCount, frame->FreeSize); #endif thread->AutoReleaseList.Resize(frame->StartIndex); thread->AutoReleasePtr--; }
void uRelease(uObject* object) { if (object) { if (Xli::AtomicDecrement(&object->__retains) == 0) { if (!uTryClearWeak(object)) return; #ifdef DEBUG_ARC uThreadData* thread = uGetThreadData(); if (thread->AutoReleasePtr >= thread->AutoReleaseStack) { uAutoReleaseFrame* frame = thread->AutoReleasePtr; if (frame->AllocCount > 0) { frame->FreeCount++; frame->FreeSize += object->__size; } } #endif uType* type = object->__type; switch (type->Type) { case uTypeTypeClass: { uType* baseType = type; do { if (baseType->fp_Finalize) { try { (*baseType->fp_Finalize)(object); } catch (...) { Xli::Error->WriteFormat("Runtime Error: Unhandled exception in finalizer for %s\n", baseType->FullName); } } } while ((baseType = baseType->Base)); uReleaseStruct(type, object); break; } case uTypeTypeStruct: // This must be a boxed value, so append size of object header uReleaseStruct(type, (uint8_t*)object + sizeof(uObject)); break; case uTypeTypeDelegate: uRelease(((uDelegate*)object)->_object); uRelease(((uDelegate*)object)->_prev); break; case uTypeTypeArray: { uArray* array = (uArray*)object; uArrayType* arrayType = (uArrayType*)type; uType* elmType = arrayType->ElementType; switch (elmType->Type) { case uTypeTypeClass: case uTypeTypeInterface: case uTypeTypeDelegate: case uTypeTypeArray: for (uObject** objAddr = (uObject**)array->_ptr; array->_length--; objAddr++) uRelease(*objAddr); break; case uTypeTypeStruct: for (uint8_t* address = (uint8_t*)array->_ptr; array->_length--; address += elmType->ValueSize) uReleaseStruct(elmType, address); break; default: break; } break; } default: break; } #if DEBUG_ARC >= 2 Xli::Error->WriteFormat("free %s #%d (%d bytes)%s\n", object->__type->FullName, object->__id, object->__size, uGetCaller().Ptr()); #endif #ifdef DEBUG_DUMPS uEnterCritical(); _HeapObjects->Remove(object); uExitCritical(); #endif U_ASSERT(object->__type != ::g::Uno::Type_typeof()); U_FREE_OBJECT(object); return; } if (object->__retains < 0) { #if DEBUG_ARC >= 4 Xli::Error->WriteFormat("*** BAD OBJECT: %s #%d (%d retains) ***%s\n", object->__type->FullName, object->__id, object->__retains, uGetCaller().Ptr()); #else Xli::Error->WriteFormat("*** BAD OBJECT: 0x%llx ***\n", (uintptr_t)object); #endif U_FATAL(); } else { #if DEBUG_ARC >= 3 Xli::Error->WriteFormat("release %s #%d (%d bytes, %d retains)%s\n", object->__type->FullName, object->__id, object->__size, object->__retains, uGetCaller().Ptr()); #endif } } }
//~ void __JavaUnoObject_Finalizer(JNIEnv *env , jclass clazz, jlong ptr) { uAutoReleasePool pool; uRelease((::g::Uno::Compiler::ExportTargetInterop::Foreign::Android::JavaUnoObject*)ptr); }