예제 #1
0
uObject* uDelegate::Invoke(uArray* array)
{
    uDelegateType* type = (uDelegateType*)GetType();
    size_t count = type->ParameterCount;
    uType** params = type->ParameterTypes;
    void** args = NULL;

    if (array)
    {
        if (!U_IS_OBJECT(((uArrayType*)array->GetType())->ElementType))
            U_THROW_ICE();
        if (count != array->Length())
            U_THROW_IOORE();

        uObject** objects = (uObject**)array->Ptr();
        void** ptr = args = count > 0
            ? (void**)U_ALLOCA(count * sizeof(void*))
            : NULL;

        for (size_t i = 0; i < count; i++)
        {
            uType* param = *params++;
            uObject* object = *objects++;

            switch (param->Type)
            {
            case uTypeTypeEnum:
            case uTypeTypeStruct:
                *ptr++ = (uint8_t*)object + sizeof(uObject);
                break;
            case uTypeTypeByRef:
                *ptr++ = U_IS_VALUE(((uByRefType*)param)->ValueType)
                        ? (uint8_t*)object + sizeof(uObject)
                        : (void*)&object;
                break;
            case uTypeTypeClass:
            case uTypeTypeDelegate:
            case uTypeTypeInterface:
            case uTypeTypeArray:
                *ptr++ = object;
                break;
            default:
                U_FATAL();
            }
        }
    }

    uType* returnType = type->ReturnType;
    void* retval = !U_IS_VOID(returnType)
        ? U_ALLOCA(returnType->ValueSize)
        : NULL;

    Invoke(retval, args, count);
    return uBoxPtr(returnType, retval, NULL, true);
}
예제 #2
0
uDelegate* uDelegate::New(uType* type, const void* func, uObject* object, uType* generic)
{
    U_ASSERT(func);
    uDelegate* delegate = (uDelegate*)uNew(type, sizeof(uDelegate));
    delegate->_func = func;
    delegate->_generic = generic;
    delegate->_object = object;
    delegate->_this = object && U_IS_VALUE(object->GetType())
                    ? (uint8_t*)object + sizeof(uObject)
                    : (void*)object;
    return delegate;
}
예제 #3
0
uObject* uFunction::Invoke(uObject* object, uArray* args)
{
    size_t count = ParameterTypes->Length();
    void* retval = !U_IS_VOID(ReturnType)
        ? U_ALLOCA(ReturnType->ValueSize)
        : NULL;

    if (!(Flags & uFunctionFlagsStatic))
        count++;
    if (Generic)
        count++;
    if (retval)
        count++;

    void** stack;
    void** ptr = stack = count > 0
            ? (void**)U_ALLOCA(count * sizeof(void*))
            : NULL;

    if (!(Flags & uFunctionFlagsStatic))
        *ptr++ = !(Flags & uFunctionFlagsVirtual) && U_IS_VALUE(DeclaringType)
            ? (uint8_t*)uPtr(object) + sizeof(uObject)
            : (void*)uPtr(object);
    if (Generic)
        *ptr++ = Generic;

    if (args)
    {
        if (args->Length() != ParameterTypes->Length())
            U_THROW_IOORE();
        if (U_IS_VALUE(((uArrayType*)args->GetType())->ElementType))
            U_THROW_ICE();

        uType** params = (uType**)ParameterTypes->Ptr();
        uObject** objects = (uObject**)args->Ptr();

        for (int i = 0; i < args->Length(); i++)
        {
            uType*& param = *params++;
            uObject*& arg = *objects++;

            switch (param->Type)
            {
            case uTypeTypeEnum:
            case uTypeTypeStruct:
                *ptr++ = (uint8_t*)arg + sizeof(uObject);
                break;
            case uTypeTypeByRef:
                *ptr++ = U_IS_VALUE(((uByRefType*)param)->ValueType)
                        ? (uint8_t*)arg + sizeof(uObject)
                        : (void*)&arg;
                break;
            case uTypeTypeClass:
            case uTypeTypeDelegate:
            case uTypeTypeInterface:
            case uTypeTypeArray:
                *ptr++ = arg;
                break;
            default:
                U_FATAL();
            }
        }
    }
    else if (ParameterTypes->Length() != 0)
        U_THROW_IOORE();

    if (retval)
        *ptr++ = retval;

    U_ASSERT(DeclaringType);
    DeclaringType->Init();
    uInvoke(Flags & uFunctionFlagsVirtual
            ? *(void**)((uint8_t*)object->GetType() + _offset)
            : _func,
        stack,
        count);
    return uBoxPtr(ReturnType, retval, NULL, true);
}
예제 #4
0
void uBuildMemory(uType* type)
{
    U_ASSERT(type);
    if (!type->IsClosed())
        return;

    size_t strongCount = 0,
           weakCount = 0,
           objOffset = U_IS_OBJECT(type)
               ? sizeof(uObject)
               : 0,
           typeOffset = 0;

    if (type->Base)
        type->Base->Build();

    for (size_t i = 0; i < type->FieldCount; i++)
    {
        uFieldInfo& f = type->Fields[i];
        U_ASSERT(f.Type);

        if (f.Type != type && !U_IS_OBJECT(f.Type))
            f.Type->Build();

        if ((f.Flags & uFieldFlagsStatic) == 0)
        {
            if ((f.Flags & uFieldFlagsConstrained) == 0)
                objOffset = f.Offset + f.Type->ValueSize;

            if (U_IS_VALUE(f.Type))
            {
                strongCount += f.Type->Refs.StrongCount;
                weakCount += f.Type->Refs.WeakCount;
            }
            else if ((f.Flags & uFieldFlagsWeak) != 0)
                weakCount++;
            else
                strongCount++;
        }
        else if ((f.Flags & uFieldFlagsConstrained) != 0)
        {
            uAlignField(typeOffset, f.Type);
            f.Offset = typeOffset;
            typeOffset += f.Type->ValueSize;
        }
    }

    size_t size = typeOffset + (strongCount + weakCount) * sizeof(uRefInfo<size_t>);
    uint8_t* ptr = (uint8_t*)malloc(size); // Leak
    memset(ptr, 0, size);

    type->Refs.Strong = (uRefInfo<size_t>*)ptr;
    ptr += strongCount * sizeof(uRefInfo<size_t>);

    type->Refs.Weak = (uRefInfo<size_t>*)ptr;
    ptr += weakCount * sizeof(uRefInfo<size_t>);

    for (size_t i = 0; i < type->FieldCount; i++)
    {
#ifdef DEBUG_ARC
#define DEBUG_NAME ((Xli::String)type->FullName + "[" + (int)i + "]").CopyPtr(), // Leak
#else
#define DEBUG_NAME
#endif
        uFieldInfo& f = type->Fields[i];

        if ((f.Flags & uFieldFlagsStatic) == 0)
        {
            if ((f.Flags & uFieldFlagsConstrained) != 0)
            {
                uAlignField(objOffset, f.Type);
                f.Flags &= ~uFieldFlagsConstrained;
                f.Offset = objOffset;
                objOffset += f.Type->ValueSize;
            }

            if (U_IS_VALUE(f.Type))
            {
                f.Flags &= ~uFieldFlagsWeak;

                for (size_t j = 0; j < f.Type->Refs.StrongCount; j++)
                    type->Refs.Strong[type->Refs.StrongCount++] = f.Type->Refs.Strong[j] + f.Offset;
                for (size_t j = 0; j < f.Type->Refs.WeakCount; j++)
                    type->Refs.Weak[type->Refs.WeakCount++] = f.Type->Refs.Weak[j] + f.Offset;
            }
            else if ((f.Flags & uFieldFlagsWeak) != 0)
            {
                uRefInfo<size_t> ref = {DEBUG_NAME f.Offset};
                type->Refs.Weak[type->Refs.WeakCount++] = ref;
            }
            else
            {
                uRefInfo<size_t> ref = {DEBUG_NAME f.Offset};
                type->Refs.Strong[type->Refs.StrongCount++] = ref;
            }
        }
        else
        {
            if ((f.Flags & uFieldFlagsConstrained) != 0)
            {
                f.Flags &= ~uFieldFlagsConstrained;
                f.Offset += (uintptr_t)ptr;
            }

            if ((f.Flags & uFieldFlagsWeak) != 0)
            {
                uRefInfo<uWeakObject**> ref = {DEBUG_NAME (uWeakObject**)f.Offset};
                _WeakRefs->Add(ref);
            }
            else if (U_IS_OBJECT(f.Type))
            {
                uRefInfo<uObject**> ref = {DEBUG_NAME (uObject**)f.Offset};
                _StrongRefs->Add(ref);
            }
        }
#undef DEBUG_NAME
    }

    if (U_IS_VALUE(type))
    {
        if (objOffset != 0)
        {
            uAlignField(objOffset, type);
            U_ASSERT(type->ValueSize == objOffset || type->ValueSize == 0);
            type->ValueSize = objOffset;
        }

        type->ObjectSize = sizeof(uObject) + type->ValueSize;
    }
    else
    {
        if (type->Base && type->Base->ObjectSize > objOffset)
            objOffset = type->Base->ObjectSize;

        if (objOffset > type->ObjectSize)
            type->ObjectSize = objOffset;
    }

#ifdef DEBUG_UNSAFE
    uint8_t* layout = (uint8_t*)U_ALLOCA(type->ObjectSize);
    memset(layout, 0, type->ObjectSize);

    for (size_t i = 0; i < type->FieldCount; i++)
    {
        uFieldInfo& f = type->Fields[i];
        if ((f.Flags & uFieldFlagsStatic) == 0)
        {
            for (size_t j = 0; j < f.Type->ValueSize; j++)
            {
                U_ASSERT(f.Offset + j < type->ObjectSize);
                layout[f.Offset + j]++;
            }
        }
    }

    // Verify that no fields are overlapping
    for (size_t i = 0; i < type->ObjectSize; i++)
        U_ASSERT(layout[i] < 2);
#endif
}