typedef enum {
/* array or string */
MONO_VT_FLAG_ARRAY_OR_STRING = (1 << 0),
- MONO_VT_FLAG_HAS_REFERENCES = (1 << 1)
+ MONO_VT_FLAG_HAS_REFERENCES = (1 << 1),
+ MONO_VT_FLAG_ARRAY_IS_PRIMITIVE = (1 << 2),
} MonoVTableFlags;
/* the interface_offsets array is stored in memory before this struct */
ICALL_TYPE(BUFFER, "System.Buffer", BUFFER_0)
NOHANDLES(ICALL(BUFFER_0, "BulkMoveWithWriteBarrier", ves_icall_System_Runtime_RuntimeImports_RhBulkMoveWithWriteBarrier))
-HANDLES(BUFFER_1, "IsPrimitiveTypeArray", ves_icall_System_Buffer_IsPrimitiveTypeArray, MonoBoolean, 1, (MonoArray))
NOHANDLES(ICALL(BUFFER_2, "__Memmove", ves_icall_System_Runtime_RuntimeImports_Memmove))
NOHANDLES(ICALL(BUFFER_3, "__ZeroMemory", ves_icall_System_Runtime_RuntimeImports_ZeroMemory))
}
}
-#ifdef ENABLE_NETCORE
-MonoBoolean
-ves_icall_System_Buffer_IsPrimitiveTypeArray (MonoArrayHandle array, MonoError* error)
-{
- MonoClass * const klass = m_class_get_element_class (MONO_HANDLE_GETVAL (array, obj.vtable)->klass);
- return m_class_is_primitive (klass);
-}
-#endif
-
gint32
ves_icall_System_Buffer_ByteLengthInternal (MonoArrayHandle array, MonoError* error)
{
guint32 vtable_size, class_size;
gpointer iter;
gpointer *interface_offsets;
+ gboolean is_primitive_type_array = FALSE;
gboolean use_interpreter = callbacks.is_interpreter_enabled ();
mono_loader_lock (); /*FIXME mono_class_init_internal acquires it*/
/* Array types require that their element type be valid*/
if (m_class_get_byval_arg (klass)->type == MONO_TYPE_ARRAY || m_class_get_byval_arg (klass)->type == MONO_TYPE_SZARRAY) {
MonoClass *element_class = m_class_get_element_class (klass);
+ is_primitive_type_array = m_class_is_primitive (element_class);
if (!m_class_is_inited (element_class))
mono_class_init_internal (element_class);
if (m_class_has_references (klass))
vt->flags |= MONO_VT_FLAG_HAS_REFERENCES;
+ if (is_primitive_type_array)
+ vt->flags |= MONO_VT_FLAG_ARRAY_IS_PRIMITIVE;
+
MONO_PROFILER_RAISE (vtable_loading, (vt));
mono_class_compute_gc_descriptor (klass);
ip++;
MINT_IN_BREAK;
}
+ MINT_IN_CASE(MINT_ARRAY_IS_PRIMITIVE) {
+ MonoObject* const o = sp [-1].data.o;
+ NULL_CHECK (o);
+ sp [-1].data.i = m_class_is_primitive (m_class_get_element_class (mono_object_class (o)));
+ ip++;
+ MINT_IN_BREAK;
+ }
MINT_IN_CASE(MINT_LDELEMA1) {
/* No bounds, one direction */
MonoArray *ao = (MonoArray*)sp [-2].data.o;
OPDEF(MINT_STRLEN, "strlen", 1, Pop1, Push1, MintOpNoArgs)
OPDEF(MINT_ARRAY_RANK, "array_rank", 1, Pop1, Push1, MintOpNoArgs)
OPDEF(MINT_ARRAY_ELEMENT_SIZE, "array_element_size", 1, Pop1, Push1, MintOpNoArgs)
+OPDEF(MINT_ARRAY_IS_PRIMITIVE, "array_is_primitive", 1, Pop1, Push1, MintOpNoArgs)
/* Calls */
OPDEF(MINT_CALL, "call", 3, VarPop, Push1, MintOpMethodToken)
*op = MINT_LDLEN;
} else if (!strcmp (tm, "GetElementSize")) {
*op = MINT_ARRAY_ELEMENT_SIZE;
+ } else if (!strcmp (tm, "IsPrimitive")) {
+ *op = MINT_ARRAY_IS_PRIMITIVE;
} else if (!strcmp (tm, "Address")) {
MonoClass *check_class = readonly ? NULL : m_class_get_element_class (target_method->klass);
interp_emit_ldelema (td, target_method->klass, check_class);
EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, class_reg, vt_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADI4_MEMBASE, sizes_reg, class_reg, m_class_offsetof_sizes ());
return ins;
+ } else if (!strcmp (cmethod->name, "IsPrimitive")) {
+ 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_ARRAY_IS_PRIMITIVE);
+ 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;
}
#ifndef MONO_BIG_ARRAYS
using Internal.Runtime.CompilerServices;
using System.Collections;
using System.Collections.Generic;
+using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Mono;
return 0;
}
+ [Intrinsic]
+ public bool IsPrimitive ()
+ {
+ ThrowHelper.ThrowNotSupportedException ();
+ return false;
+ }
+
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static bool CanChangePrimitive (Type srcType, Type dstType, bool reliable);
{
partial class Buffer
{
- [MethodImpl (MethodImplOptions.InternalCall)]
- static extern bool IsPrimitiveTypeArray (Array array);
+ static bool IsPrimitiveTypeArray (Array array) => array.IsPrimitive ();
internal static unsafe void Memcpy (byte* dest, byte* src, int len) => Memmove (dest, src, (nuint) len);