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); }
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; }
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); }
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 }