static uObject *uInitObject(uType *objType, void *allocObj, size_t allocSize) { uObject *object = (uObject *)allocObj; object->__obj_type = objType; object->__obj_retains = 1; #ifdef U_DEBUG_MEM object->__obj_alloc_size = allocSize; object->__obj_id = objType->ObjectCount++; #endif #if U_DEBUG_MEM >= 2 Xli::Error->WriteFormat("Alloc'd '%s' (%d bytes)\n", objType->TypeName, allocSize); #endif #ifdef U_DEBUG_MEM uEnterCritical(); (*uHeapObjects)[object] = true; uExitCritical(); #endif uAutoReleaseObject(object); return object; }
void uDumpAllStrongRefs(const char *path) { FILE *fp = fopen(path, "w"); if (!fp) return; fprintf(fp, "digraph object_dump {\n"); uEnterCritical(); for (int i = uHeapObjects->Begin(); i != uHeapObjects->End(); i = uHeapObjects->Next(i)) { uDumpObjectAndStrongRefs(fp, uHeapObjects->GetKey(i)); } uObject ***globalStrongRefs = uGetGlobalStrongRefs(); const char **globalStrongRefNames = uGetGlobalStrongNames(); for (int i = 0; globalStrongRefs[i] != NULL && globalStrongRefNames[i] != NULL; ++i) { uDumpGlobalRef(fp, globalStrongRefs[i], globalStrongRefNames[i]); } uExitCritical(); fprintf(fp, "}\n"); fclose(fp); }
static uObject* uInitObject(uType* type, void* ptr, size_t size) { U_ASSERT(type && type->IsClosed() && type->ObjectSize && type->ValueSize && !(type->Flags & uTypeFlagsAbstract)); if (type->State < uTypeStateInitializing && strcmp(type->FullName, "Uno.String") != 0 && strcmp(type->FullName, "Uno.Type") != 0) type->Init(); uObject* object = (uObject*)ptr; object->__type = type; object->__retains = 1; #ifdef DEBUG_ARC object->__size = size; object->__id = type->Definition->ObjectCount++; #endif #if DEBUG_ARC >= 2 Xli::Error->WriteFormat("alloc %s #%d (%d bytes)%s\n", type->FullName, object->__id, size, uGetCaller().Ptr()); #endif #ifdef DEBUG_DUMPS uEnterCritical(); (*_HeapObjects)[object] = true; uExitCritical(); #endif uAutoRelease(object); return object; }
void uDumpAllStrongRefs(const char* path) { FILE* fp = fopen(path, "w"); if (!fp) return; fprintf(fp, "digraph object_dump {\n"); uEnterCritical(); for (int i = _HeapObjects->Begin(); i != _HeapObjects->End(); i = _HeapObjects->Next(i)) uDumpObjectAndStrongRefs(fp, _HeapObjects->GetKey(i)); for (int i = 0; i < _StrongRefs->Length(); i++) uDumpGlobalRef(fp, (*_StrongRefs)[i].Value, (*_StrongRefs)[i].Name); uExitCritical(); fprintf(fp, "}\n"); fclose(fp); }
void uReleaseObject(uObject* obj) { if (obj) { if (Xli::AtomicDecrement(&obj->__obj_retains) == 0) { if (!uTryClearWeakObject(obj)) return; #ifdef U_DEBUG_MEM uThreadData* thread = uGetThreadData(); if (thread->AutoReleaseStack.Length() > 0 && thread->AutoReleaseStack.Last().AllocCount > 0) { thread->AutoReleaseStack.Last().FreeCount++; thread->AutoReleaseStack.Last().FreeSize += obj->__obj_alloc_size; } #endif uType* type = obj->__obj_type; switch (type->TypeType) { case uTypeTypeClass: do { if (type->__fp_Finalize) { try { (*type->__fp_Finalize)(obj); } catch (...) { Xli::Error->WriteFormat("Runtime Error: Unhandled exception in finalizer for '%s'\n", type->TypeName); } } uReleaseValue(type, obj); type = type->BaseType; } while (type); break; case uTypeTypeEnum: break; case uTypeTypeStruct: // Note: This must be a boxed value, so append size of object header uReleaseValue(type, (uByte*)obj + sizeof(uObject)); break; case uTypeTypeDelegate: uReleaseObject(((uDelegate*)obj)->_obj); uReleaseObject(((uDelegate*)obj)->_prev); break; case uTypeTypeArray: { uArray* array = (uArray*)obj; uArrayType* arrayType = (uArrayType*)type; uType* elmType = arrayType->ElementType; switch (elmType->TypeType) { case uTypeTypeClass: case uTypeTypeInterface: case uTypeTypeDelegate: case uTypeTypeArray: for (uObject** objAddr = (uObject**)array->_ptr; array->_len--; objAddr++) uReleaseObject(*objAddr); break; case uTypeTypeEnum: break; case uTypeTypeStruct: for (uByte* valueAddr = (uByte*)array->_ptr; array->_len--; valueAddr += elmType->ValueSize) uReleaseValue(elmType, valueAddr); break; default: uFatalError(XLI_FUNCTION); } } break; default: uFatalError(XLI_FUNCTION); } #if U_DEBUG_MEM >= 2 Xli::Error->WriteFormat("Freeing '%s' (%d bytes)\n", obj->__obj_type->TypeName, obj->__obj_alloc_size); #endif #ifdef U_DEBUG_MEM uEnterCritical(); uHeapObjects->Remove(obj); uExitCritical(); #endif U_FREE_OBJECT(obj); } else if ((*(uUInt*)&obj->__obj_retains) & 0xF0000000) { // Object must be corrupt if one of the four first bits are set uFatalError(XLI_FUNCTION); } else { #if U_DEBUG_MEM >= 3 Xli::Error->WriteFormat("Released '%s' (%d bytes) (%d retains)\n", obj->__obj_type->TypeName, obj->__obj_alloc_size, obj->__obj_retains); #endif } } }
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 } } }