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 } }
uType* uType::GetBase(uType* def) { for (uType* type = this; type; type = type->Base) if (type->Definition == def) return type; U_FATAL(); }
void uWeakStateIntercept::SetCallback(uWeakObject* weak, uWeakStateIntercept::Callback cb) { if (!weak || !cb || weak->ZombieState != uWeakObject::Healthy) U_FATAL(); weak->ZombieState = uWeakObject::Infected; weak->ZombieStateIntercept = cb; }
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); }
void uType::Build() { switch (State) { default: return; case uTypeStateBuilding: U_FATAL(); case uTypeStateUninitialized: State = uTypeStateBuilding; uBuildParameterization(this); uBuildMemory(this); //#if #(REFLECTION:Defined) uBuildReflection(this); //#endif uVerifyBuild(this); State = uTypeStateBuilt; break; } }
void uCopy(uType* type, const void* src, void* dst, uint8_t flags) { U_ASSERT(type && dst && ( U_IS_OBJECT(type) && flags & uCopyFlagsValue || src )); if (U_IS_OBJECT(type)) { switch (flags) { case 0: *(uObject**)dst = *(uObject**)src; break; case uCopyFlagsValue: *(uObject**)dst = (uObject*)src; break; case uCopyFlagsStrong: *(uStrong<uObject*>*)dst = *(uObject**)src; break; case uCopyFlagsStrongValue: *(uStrong<uObject*>*)dst = (uObject*)src; break; default: U_FATAL(); } U_ASSERT(!*(uObject**)dst || uIs(*(uObject**)dst, type)); } else if (type->Flags & uTypeFlagsRetainStruct) { uAutoReleaseStruct(type, dst); memcpy(dst, src, type->ValueSize); uRetainStruct(type, dst); } else INLINE_MEMCPY(dst, src, type->ValueSize); }
void uReverseBytes(uint8_t* ptr, size_t size) { uint8_t tmp; switch (size) { case 2: tmp = ptr[0]; ptr[0] = ptr[1]; ptr[1] = tmp; break; case 4: tmp = ptr[0]; ptr[0] = ptr[3]; ptr[3] = tmp; tmp = ptr[1]; ptr[1] = ptr[2]; ptr[2] = tmp; break; case 8: tmp = ptr[0]; ptr[0] = ptr[7]; ptr[7] = tmp; tmp = ptr[1]; ptr[1] = ptr[6]; ptr[6] = tmp; tmp = ptr[2]; ptr[2] = ptr[5]; ptr[5] = tmp; tmp = ptr[3]; ptr[3] = ptr[4]; ptr[4] = tmp; break; default: U_FATAL(); } }
static int64_t uLoadEnum(uEnumType* type, void* value) { // See if value is unsigned (Uno.Byte|Uno.U*) uChar fifth = type->Base->FullName[4]; bool isUnsigned = fifth == 'B' || fifth == 'U'; switch (type->ValueSize) { case 1: return isUnsigned ? (int64_t)*(uint8_t*)value : (int64_t)*(int8_t*)value; case 2: return isUnsigned ? (int64_t)*(uint16_t*)value : (int64_t)*(int16_t*)value; case 4: return isUnsigned ? (int64_t)*(uint32_t*)value : (int64_t)*(int32_t*)value; case 8: return isUnsigned ? (int64_t)*(uint64_t*)value : *(int64_t*)value; default: U_FATAL(); } }
const void* uType::InterfacePtr(const uObject* object) { uType* type = object->__type; do { intptr_t left = 0, right = (intptr_t)type->InterfaceCount - 1; while (left <= right) { intptr_t mid = (left + right) >> 1; ptrdiff_t diff = (uint8_t*)this - (uint8_t*)type->Interfaces[mid].Type; if (diff > 0) left = mid + 1; else if (diff < 0) right = mid - 1; else return (const uint8_t*)type + type->Interfaces[mid].Offset; } } while ((type = type->Base)); U_FATAL(); }
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 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 } } }
static void uDumpObjectAndStrongRefs(FILE* fp, uObject* object) { uType* type = object->GetType(); uDumpObject(fp, object, type->FullName); switch (type->Type) { case uTypeTypeClass: do uDumpAllStrongRefs(fp, object, object, type); while ((type = type->Base)); break; case uTypeTypeEnum: break; case uTypeTypeStruct: { uint8_t* address = (uint8_t*)object + sizeof(uObject); uDumpAllStrongRefs(fp, object, address, type); break; } case uTypeTypeDelegate: { uDelegate* delegate = (uDelegate*)object; uDumpStrongRef(fp, object, delegate->_object); uDumpStrongRef(fp, object, delegate->_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 (int i = 0; i < array->Length(); ++i) { uObject* target = ((uObject**)array->Ptr())[i]; uDumpStrongRef(fp, object, target); } break; case uTypeTypeEnum: break; case uTypeTypeStruct: for (int i = 0; i < array->Length(); ++i) { uint8_t* address = (uint8_t*)array->Ptr() + i * elmType->ValueSize; uDumpAllStrongRefs(fp, object, address, elmType); } break; default: U_FATAL(); } break; } default: U_FATAL(); } }