public static void LoadElement(/*HEAP_PTR*/ byte *pThis_, uint index, byte *value) { tSystemArray *pArray = (tSystemArray *)pThis_; tMD_TypeDef * pArrayTypeDef; uint elemSize; byte * pElements; pArrayTypeDef = Heap.GetType(pThis_); elemSize = pArrayTypeDef->pArrayElementType->arrayElementSize; pElements = tSystemArray.GetElements(pArray); switch (elemSize) { case 1: *(byte *)value = ((byte *)pElements)[index]; break; case 2: *(ushort *)value = ((ushort *)pElements)[index]; break; case 4: *(uint *)value = ((uint *)pElements)[index]; break; default: Mem.memcpy(value, &pElements[index * elemSize], (SIZE_T)elemSize); break; } }
// Must return a boxed version of value-Type.types public static tAsyncCall *Internal_GetValue(tJITCallNative *pCallNative, byte *pThis_, byte *pParams, byte *pReturnValue) { tSystemArray *pArray = (tSystemArray *)pThis_; tMD_TypeDef * pArrayType; uint index, elementSize; tMD_TypeDef * pElementType; byte * pElement; index = (*((uint *)(pParams + 0))); pArrayType = Heap.GetType(pThis_); pElementType = pArrayType->pArrayElementType; elementSize = pElementType->arrayElementSize; pElement = tSystemArray.GetElements(pArray) + elementSize * index; if (pElementType->isValueType != 0) { // If it's a value-type, then box it /*HEAP_PTR*/ byte *boxedValue; if (pElementType->pGenericDefinition == Type.types[Type.TYPE_SYSTEM_NULLABLE]) { // Nullable type, so box specially if (*(uint *)pElement != 0) { // Nullable has value boxedValue = Heap.AllocType(pElementType->ppClassTypeArgs[0]); // Don't copy the .hasValue part Mem.memcpy(boxedValue, pElement + 4, elementSize - 4); } else { // Nullable does not have value boxedValue = null; } } else { boxedValue = Heap.AllocType(pElementType); Mem.memcpy(boxedValue, pElement, elementSize); } Sys.INTERNALCALL_RESULT_PTR(pReturnValue, boxedValue); } else { Sys.INTERNALCALL_RESULT_PTR(pReturnValue, *(byte **)pElement); } return(null); }
public static byte *LoadElementAddress(tJITCallNative *pCallNative, /*HEAP_PTR*/ byte *pThis_, uint index) { tSystemArray *pArray = (tSystemArray *)pThis_; tMD_TypeDef * pArrayTypeDef; byte * pElements; #if WIN32 && _DEBUG if (index >= pArray->length) { printf("SystemArray.LoadElementAddress() Bounds check failed\n"); __debugbreak(); } #endif pArrayTypeDef = Heap.GetType(pThis_); pElements = tSystemArray.GetElements(pArray); return(pElements + pArrayTypeDef->pArrayElementType->arrayElementSize * index); }
public static void StoreElement(/*HEAP_PTR*/ byte *pThis_, uint index, byte *value) { tSystemArray *pArray = (tSystemArray *)pThis_; tMD_TypeDef * pArrayTypeDef; uint elemSize; byte * pElements; #if WIN32 && _DEBUG // Do a bounds check if (index >= pArray->length) { printf("SystemArray.StoreElement() Bounds check failed. Array length: %d index: %d\n", pArray->length, index); __debugbreak(); } #endif pArrayTypeDef = Heap.GetType(pThis_); elemSize = pArrayTypeDef->pArrayElementType->arrayElementSize; pElements = tSystemArray.GetElements(pArray); switch (elemSize) { case 1: ((byte *)pElements)[index] = *(byte *)value; break; case 2: ((ushort *)pElements)[index] = *(ushort *)value; break; case 4: ((uint *)pElements)[index] = *(uint *)value; break; default: Mem.memcpy(&pElements[index * elemSize], value, (SIZE_T)elemSize); break; } }
// The elements //public byte elements[0]; public static byte *GetElements(tSystemArray *array) { return((byte *)array + 4); }
// Value-Type.types will be boxed public static tAsyncCall *Internal_SetValue(tJITCallNative *pCallNative, byte *pThis_, byte *pParams, byte *pReturnValue) { tSystemArray * pArray = (tSystemArray *)pThis_; tMD_TypeDef * pArrayType, pObjType; uint index, elementSize; /*HEAP_PTR*/ byte *obj; tMD_TypeDef * pElementType; byte * pElement; pArrayType = Heap.GetType(pThis_); obj = (*((byte **)(pParams + 0))); pObjType = Heap.GetType(obj); pElementType = pArrayType->pArrayElementType; // Check to see if the Type is ok to put in the array if (!(Type.IsAssignableFrom(pElementType, pObjType) != 0 || (pElementType->pGenericDefinition == Type.types[Type.TYPE_SYSTEM_NULLABLE] && pElementType->ppClassTypeArgs[0] == pObjType))) { // Can't be done Sys.INTERNALCALL_RESULT_U32(pReturnValue, 0); return(null); } index = (*((uint *)(pParams + Sys.S_PTR))); #if WIN32 && _DEBUG // Do a bounds-check if (index >= pArray->length) { printf("[Array] Internal_SetValue() Bounds-check failed\n"); __debugbreak(); } #endif elementSize = pElementType->arrayElementSize; pElement = tSystemArray.GetElements(pArray) + elementSize * index; if (pElementType->isValueType != 0) { if (pElementType->pGenericDefinition == Type.types[Type.TYPE_SYSTEM_NULLABLE]) { // Nullable type, so treat specially if (obj == null) { Mem.memset(pElement, 0, elementSize); } else { *(uint *)pElement = 1; Mem.memcpy(pElement + 4, obj, elementSize - 4); } } else { // Get the value out of the box Mem.memcpy(pElement, obj, elementSize); } } else { // This must be a reference type, so it must be 32-bits wide *(/*HEAP_PTR*/ byte **)pElement = obj; } Sys.INTERNALCALL_RESULT_U32(pReturnValue, 1); return(null); }