HANDLES(GC_9, "get_ephemeron_tombstone", ves_icall_System_GC_get_ephemeron_tombstone, MonoObject, 0, ())
HANDLES(GC_8, "register_ephemeron_array", ves_icall_System_GC_register_ephemeron_array, void, 1, (MonoObject))
+ICALL_TYPE(STREAM, "System.IO.Stream", STREAM_1)
+HANDLES(STREAM_1, "HasOverriddenBeginEndRead", ves_icall_System_IO_Stream_HasOverriddenBeginEndRead, MonoBoolean, 1, (MonoObject))
+HANDLES(STREAM_2, "HasOverriddenBeginEndWrite", ves_icall_System_IO_Stream_HasOverriddenBeginEndWrite, MonoBoolean, 1, (MonoObject))
+
ICALL_TYPE(MATH, "System.Math", MATH_19)
NOHANDLES(ICALL(MATH_19, "Abs(double)", ves_icall_System_Math_Abs_double))
NOHANDLES(ICALL(MATH_20, "Abs(single)", ves_icall_System_Math_Abs_single))
return mono_method_get_object_handle (MONO_HANDLE_DOMAIN (ref_method), result, NULL, error);
}
+#ifdef ENABLE_NETCORE
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (stream, "System.IO", "Stream")
+static int io_stream_begin_read_slot = -1;
+static int io_stream_begin_write_slot = -1;
+static int io_stream_end_read_slot = -1;
+static int io_stream_end_write_slot = -1;
+static gboolean io_stream_slots_set = FALSE;
+
+static void
+init_io_stream_slots (void)
+{
+ MonoClass* klass = mono_class_try_get_stream_class ();
+ mono_class_setup_vtable (klass);
+ MonoMethod **klass_methods = m_class_get_methods (klass);
+ if (!klass_methods) {
+ mono_class_setup_methods (klass);
+ klass_methods = m_class_get_methods (klass);
+ }
+ int method_count = mono_class_get_method_count (klass);
+ int methods_found = 0;
+ for (int i = 0; i < method_count; i++) {
+ // find slots for Begin(End)Read and Begin(End)Write
+ MonoMethod* m = klass->methods [i];
+ if (m->slot == -1)
+ continue;
+
+ if (!strcmp (m->name, "BeginRead")) {
+ methods_found++;
+ io_stream_begin_read_slot = m->slot;
+ } else if (!strcmp (m->name, "BeginWrite")) {
+ methods_found++;
+ io_stream_begin_write_slot = m->slot;
+ } else if (!strcmp (m->name, "EndRead")) {
+ methods_found++;
+ io_stream_end_read_slot = m->slot;
+ } else if (!strcmp (m->name, "EndWrite")) {
+ methods_found++;
+ io_stream_end_write_slot = m->slot;
+ }
+ }
+ g_assert (methods_found <= 4); // some of them can be linked out
+ io_stream_slots_set = TRUE;
+}
+
+MonoBoolean
+ves_icall_System_IO_Stream_HasOverriddenBeginEndRead (MonoObjectHandle stream, MonoError *error)
+{
+ MonoClass* curr_klass = MONO_HANDLE_GET_CLASS (stream);
+ MonoClass* base_klass = mono_class_try_get_stream_class ();
+
+ if (!io_stream_slots_set)
+ init_io_stream_slots ();
+
+ // slots can still be -1 and it means Linker removed the methods from the base class (Stream)
+ // in this case we can safely assume the methods are not overridden
+ // otherwise - check vtable
+ gboolean begin_read_is_overriden = io_stream_begin_read_slot != -1 && curr_klass->vtable [io_stream_begin_read_slot]->klass != base_klass;
+ gboolean end_read_is_overriden = io_stream_end_read_slot != -1 && curr_klass->vtable [io_stream_end_read_slot]->klass != base_klass;
+
+ // return true if BeginRead or EndRead were overriden
+ return begin_read_is_overriden || end_read_is_overriden;
+}
+
+MonoBoolean
+ves_icall_System_IO_Stream_HasOverriddenBeginEndWrite (MonoObjectHandle stream, MonoError *error)
+{
+ MonoClass* curr_klass = MONO_HANDLE_GETVAL (stream, vtable)->klass;
+ MonoClass* base_klass = mono_class_try_get_stream_class ();
+
+ if (!io_stream_slots_set)
+ init_io_stream_slots ();
+
+ gboolean begin_write_is_overriden = curr_klass->vtable [io_stream_begin_write_slot]->klass != base_klass;
+ gboolean end_write_is_overriden = curr_klass->vtable [io_stream_end_write_slot]->klass != base_klass;
+
+ // return true if BeginWrite or EndWrite were overriden
+ return begin_write_is_overriden || end_write_is_overriden;
+}
+#endif
+
MonoBoolean
ves_icall_RuntimeMethodInfo_get_IsGenericMethod (MonoReflectionMethodHandle ref_method, MonoError *erro)
{