* Address feedback
* fix build error
* Fix has_reference usage in object.c
* Fix fallback impl
* Rename to ArrayHasReferences
* Rename to ObjectHasReferences
* Rollback to ArrayHasReferences
* Rename to ObjectHasReference
* remove redundant is_array variable
* ObjectHasReferences can accept any object
* undo changes in Program.cs
* undo changes in Program.cs
Commit migrated from https://github.com/mono/mono/commit/
cf8495e2f73a56770d5a9d876ab865485b4f353b
typedef enum {
/* array or string */
- MONO_VT_FLAG_ARRAY_OR_STRING = (1 << 0)
+ MONO_VT_FLAG_ARRAY_OR_STRING = (1 << 0),
+ MONO_VT_FLAG_HAS_REFERENCES = (1 << 1)
} MonoVTableFlags;
/* the interface_offsets array is stored in memory before this struct */
ICALL_TYPE(ARRAY, "System.Array", ARRAY_0)
HANDLES(ARRAY_0, "CanChangePrimitive", ves_icall_System_Array_CanChangePrimitive, MonoBoolean, 3, (MonoReflectionType, MonoReflectionType, MonoBoolean))
-HANDLES(ARRAY_1, "ClearInternal", ves_icall_System_Array_ClearInternal, void, 3, (MonoArray, int, int))
HANDLES(ARRAY_4, "FastCopy", ves_icall_System_Array_FastCopy, MonoBoolean, 5, (MonoArray, int, MonoArray, int, int))
NOHANDLES(ICALL(ARRAY_5, "GetGenericValue_icall", ves_icall_System_Array_GetGenericValue_icall))
HANDLES(ARRAY_6, "GetLength", ves_icall_System_Array_GetLength, gint32, 2, (MonoArray, gint32))
vt->domain = domain;
if ((vt->rank > 0) || klass == mono_get_string_class ())
vt->flags |= MONO_VT_FLAG_ARRAY_OR_STRING;
+
+ if (m_class_has_references (klass))
+ vt->flags |= MONO_VT_FLAG_HAS_REFERENCES;
MONO_PROFILER_RAISE (vtable_loading, (vt));
EMIT_NEW_UNALU (cfg, ins, OP_ICGT, dreg, -1);
ins->type = STACK_I4;
return ins;
+ } else if (!strcmp (cmethod->name, "ObjectHasReferences")) {
+ int dreg = alloc_ireg (cfg);
+ MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOAD_MEMBASE, dreg, args [0]->dreg, MONO_STRUCT_OFFSET (MonoObject, vtable));
+ MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU1_MEMBASE, dreg, dreg, MONO_STRUCT_OFFSET (MonoVTable, flags));
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, dreg, dreg, MONO_VT_FLAG_HAS_REFERENCES);
+ EMIT_NEW_BIALU_IMM (cfg, ins, OP_COMPARE_IMM, -1, dreg, 0);
+ EMIT_NEW_UNALU (cfg, ins, OP_ICGT, dreg, -1);
+ ins->type = STACK_I4;
+ return ins;
} else
return NULL;
} else if (cmethod->klass == mono_defaults.monitor_class) {
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using Mono;
+#if BIT64
+using nuint = System.UInt64;
+#else
+using nuint = System.UInt32;
+#endif
namespace System
{
}
}
- public static void Clear (Array array, int index, int length)
+ public static unsafe void Clear (Array array, int index, int length)
{
if (array == null)
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
- if (length < 0)
- ThrowHelper.ThrowIndexOutOfRangeException();
+ ThrowHelper.ThrowArgumentNullException (ExceptionArgument.array);
- int low = array!.GetLowerBound (0);
- if (index < low)
- ThrowHelper.ThrowIndexOutOfRangeException();
+ int lowerBound = array.GetLowerBound (0);
+ int elementSize = array.GetElementSize ();
+ nuint numComponents = (nuint) Unsafe.As<RawData> (array).Count;
- index = index - low;
+ int offset = index - lowerBound;
- // re-ordered to avoid possible integer overflow
- if (index > array.Length - length)
- ThrowHelper.ThrowIndexOutOfRangeException();
+ if (index < lowerBound || offset < 0 || length < 0 || (uint) (offset + length) > numComponents)
+ ThrowHelper.ThrowIndexOutOfRangeException ();
+
+ ref byte ptr = ref Unsafe.AddByteOffset (ref array.GetRawSzArrayData(), (uint) offset * (nuint) elementSize);
+ nuint byteLength = (uint) length * (nuint) elementSize;
- ClearInternal (array, index, length);
+ if (RuntimeHelpers.ObjectHasReferences (array))
+ SpanHelpers.ClearWithReferences (ref Unsafe.As<byte, IntPtr> (ref ptr), byteLength / (uint)sizeof (IntPtr));
+ else
+ SpanHelpers.ClearWithoutReferences (ref ptr, byteLength);
}
public static void ConstrainedCopy (Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
- extern static void ClearInternal (Array a, int index, int count);
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static bool CanChangePrimitive (Type srcType, Type dstType, bool reliable);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
[MethodImplAttribute (MethodImplOptions.InternalCall)]
public extern int GetLength (int dimension);
+ [Intrinsic] // when dimension is `0` constant
[MethodImplAttribute (MethodImplOptions.InternalCall)]
public extern int GetLowerBound (int dimension);
}
[Intrinsic]
- internal static unsafe bool ObjectHasComponentSize (object obj)
+ internal static bool ObjectHasComponentSize (object obj)
{
throw new NotImplementedException ();
}
+ [Intrinsic]
+ internal static bool ObjectHasReferences (object obj)
+ {
+ return RuntimeTypeHandle.HasReferences (obj.GetType () as RuntimeType);
+ }
+
static object GetUninitializedObjectInternal (Type type)
{
return GetUninitializedObjectInternal (new RuntimeTypeHandle ((RuntimeType)type).Value);