示例#1
0
uAutoReleasePool::~uAutoReleasePool()
{
    uThreadData* thread = uGetThreadData();
    uAutoReleaseFrame& frame = thread->AutoReleaseStack[thread->AutoReleaseStack.Length() - 1];

    // Note: Rewritten because that uAutoReleaseObject() might be called from uReleaseObject() inside this loop.
    // TODO: It may be faster if uAutoReleaseObject() were able to handle this, i.e. not adding anything to pool while flushing it.
    for (int i = frame.StartIndex; i < (int)thread->AutoReleasePool.Length(); i++)
    {
        uObject* obj = thread->AutoReleasePool[i];

#ifdef U_DEBUG_MEM
        frame.AllocCount++;
        frame.AllocSize += obj->__obj_alloc_size;
#endif
        uReleaseObject(obj);
    }

#if U_DEBUG_MEM >= 1
    Xli::Error->WriteFormat("ARC FRAME: Alloc'd %d objects (%d bytes), Free'd %d objects (%d bytes)\n", frame.AllocCount, frame.AllocSize, frame.FreeCount, frame.FreeSize);
#endif

    thread->AutoReleasePool.Resize(frame.StartIndex);
    thread->AutoReleaseStack.RemoveLast();
}
示例#2
0
void uAutoReleaseObject(uObject* obj)
{
    uThreadData* thread = uGetThreadData();

    if (thread->AutoReleaseStack.Length() == 0)
        uFatalError(XLI_FUNCTION);

    if (obj)
    {
        thread->AutoReleasePool.Add(obj);

#ifdef U_DEBUG_MEM
        int releaseCount = 0;

        for (int i = 0; i < thread->AutoReleasePool.Length(); i++)
            if (thread->AutoReleasePool[i] == obj)
                releaseCount++;

        int retainCount = obj->__obj_retains - releaseCount;

        if (retainCount < 0)
            Xli::Error->WriteFormat("*** BAD RELEASE: '%s', object id: %d (%d retains) ***\n", obj->__obj_type->TypeName, obj->__obj_id, retainCount);
#endif
    }
}
示例#3
0
uStackFrame::uStackFrame(const char* type, const char* function)
{
    uThreadData* thread = uGetThreadData();
    uCallStackFrame& frame = thread->CallStack[thread->CallStack.Add()];
    frame.Type = type;
    frame.Function = function;
}
示例#4
0
void uAutoRelease(uObject* object)
{
    if (object)
    {
        uThreadData* thread = uGetThreadData();
        thread->AutoReleaseList.Add(object);
        U_ASSERT(thread->AutoReleasePtr >= thread->AutoReleaseStack);
#ifdef DEBUG_ARC
        int releaseCount = 0;
        for (size_t i = 0; i < thread->AutoReleaseList.Length(); i++)
            if (thread->AutoReleaseList[i] == object)
                releaseCount++;

        int retainCount = object->__retains - releaseCount;
        if (retainCount < 0)
        {
            Xli::Error->WriteFormat("*** BAD AUTORELEASE: %s #%d (%d bytes, %d retains) ***%s\n", object->__type->FullName, object->__id, object->__size, retainCount, uGetCaller().Ptr());
            U_FATAL();
        }
#endif
#if DEBUG_ARC >= 4
        Xli::Error->WriteFormat("autorelease %s #%d (%d bytes, %d retains)%s\n", object->__type->FullName, object->__id, object->__size, object->__retains, uGetCaller().Ptr());
#endif
    }
}
示例#5
0
uType* uSwapThreadType(uType* type)
{
    uThreadData* thread = uGetThreadData();
    uType* result = thread->CurrentType;
    thread->CurrentType = type;
    return result;
}
示例#6
0
uStackFrame::uStackFrame(const char* type, const char* function)
{
    uThreadData* thread = uGetThreadData();
    uCallStackFrame* frame = ++thread->CallStackPtr;
    U_ASSERT(frame < thread->CallStackEnd);
    frame->Type = type;
    frame->Function = function;
}
示例#7
0
uAutoReleasePool::uAutoReleasePool()
{
    uThreadData* thread = uGetThreadData();
    uAutoReleaseFrame& frame = thread->AutoReleaseStack[thread->AutoReleaseStack.Add()];
    frame.StartIndex = thread->AutoReleasePool.Length();

#ifdef U_DEBUG_MEM
    frame.AllocCount = 0;
    frame.AllocSize = 0;
    frame.FreeCount = 0;
    frame.FreeSize = 0;
#endif
}
示例#8
0
uAutoReleasePool::uAutoReleasePool()
{
    uThreadData* thread = uGetThreadData();
    uAutoReleaseFrame* frame = ++thread->AutoReleasePtr;
    U_ASSERT(frame < thread->AutoReleaseEnd);
    frame->StartIndex = thread->AutoReleaseList.Length();

#ifdef DEBUG_ARC
    frame->AllocCount = 0;
    frame->AllocSize = 0;
    frame->FreeCount = 0;
    frame->FreeSize = 0;
#endif
}
示例#9
0
static Xli::String uGetCaller()
{
    uThreadData* thread = uGetThreadData();

    if (thread->CallStackPtr < thread->CallStack)
        return "";

    Xli::StringBuilder sb;
    uCallStackFrame* frame = thread->CallStackPtr;
    sb += " -- at ";
    sb += frame->Type;
    sb += '.';
    sb += frame->Function;
    return sb.ToString();
}
示例#10
0
uString* uGetStackTrace()
{
    Xli::StringBuilder sb;
    uThreadData* thread = uGetThreadData();

    for (int i = thread->CallStack.Length() - 1; i >= 0; i--)
    {
        if (sb.GetLength() > 0)
            sb += '\n';

        uCallStackFrame& frame = thread->CallStack[i];
        sb += "   at ";
        sb += frame.Type;
        sb += '.';
        sb += frame.Function;
    }

    return uStringFromXliString(sb.ToString());
}
示例#11
0
uString* uGetStackTrace()
{
    Xli::StringBuilder sb;
    uThreadData* thread = uGetThreadData();

    for (uCallStackFrame* frame = thread->CallStackPtr;
         frame >= thread->CallStack;
         frame--)
    {
        if (sb.GetLength() > 0)
            sb += '\n';

        sb += "   at ";
        sb += frame->Type;
        sb += '.';
        sb += frame->Function;
    }

    return uStringFromXliString(sb.ToString());
}
示例#12
0
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--;
}
示例#13
0
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
        }
    }
}
示例#14
0
uStackFrame::~uStackFrame()
{
    uGetThreadData()->CallStack.RemoveLast();
}
示例#15
0
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
        }
    }
}
示例#16
0
uStackFrame::~uStackFrame()
{
    uGetThreadData()->CallStackPtr--;
}