diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 20d67ea3c1f2..125528a12431 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -43,5 +43,5 @@ Please paste the stack trace here if available.
```
diff --git a/README.md b/README.md
index bc195a5a8b8f..38ccfdb15dec 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,13 @@ standards for C# and the Common Language Runtime.
The Mono project is part of the [.NET Foundation](https://www.dotnetfoundation.org/)
-[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mono/mono?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+Join us on [Discord](https://aka.ms/dotnet-discord) in the `#monovm` channel:
+
+
+
+
+
+### Contents
1. [Compilation and Installation](#compilation-and-installation)
2. [Using Mono](#using-mono)
diff --git a/configure.ac b/configure.ac
index d783e536e82f..0a8c0ba63a17 100644
--- a/configure.ac
+++ b/configure.ac
@@ -890,7 +890,7 @@ AC_ARG_ENABLE(visibility-hidden,
WARN=''
if test x"$GCC" = xyes; then
WARN='-Wall -Wunused -Wmissing-declarations -Wpointer-arith -Wno-cast-qual -Wwrite-strings -Wno-switch -Wno-switch-enum -Wno-unused-value -Wno-attributes'
- CFLAGS="$CFLAGS -Wmissing-prototypes -Wstrict-prototypes -Wnested-externs -Wno-format-zero-length"
+ CFLAGS="$CFLAGS -Wmissing-prototypes -Wstrict-prototypes -Wnested-externs -Wno-format-zero-length -Wc++-compat"
# We require C99 with some GNU extensions, e.g. `linux` macro
CFLAGS="$CFLAGS -std=gnu99"
@@ -1420,7 +1420,7 @@ if test x$with_runtime_preset = xnetcore; then
mono_feature_disable_perfcounters='yes'
mono_feature_disable_attach='yes'
mono_feature_disable_cfgdir_config='yes'
- if test "x$enable_monodroid" = "x" -a "x$enable_monotouch" = "x"; then
+ if test "x$enable_monodroid" = "xno" -a "x$enable_monotouch" = "xno"; then
mono_feature_disable_dllmap='yes' # FIXME: the mobile products use this
fi
disable_mono_native=yes
diff --git a/external/corefx b/external/corefx
index b9e66087d6a9..7c24bb0756fd 160000
--- a/external/corefx
+++ b/external/corefx
@@ -1 +1 @@
-Subproject commit b9e66087d6a9d4eb3a30c80ead3b8402510dad3d
+Subproject commit 7c24bb0756fd39fbf09b8777f25c15d21d78eb46
diff --git a/mcs/class/I18N/CJK/GB18030Encoding.cs b/mcs/class/I18N/CJK/GB18030Encoding.cs
index f62121e81f04..6f21c2534756 100644
--- a/mcs/class/I18N/CJK/GB18030Encoding.cs
+++ b/mcs/class/I18N/CJK/GB18030Encoding.cs
@@ -430,10 +430,9 @@ public unsafe override int GetBytesImpl (char* chars, int charCount, byte* bytes
}
#else
- public override int GetByteCount(char[] chars, int index, int count, bool refresh)
+ public override int GetByteCount(char[] chars, int start, int count, bool refresh)
{
- int start = 0;
- int end = count;
+ int end = start + count;
int ret = 0;
while (start < end)
{
diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs
index f61919f0a386..db17abaeb8d6 100644
--- a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs
+++ b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs
@@ -471,6 +471,14 @@ public class Tests : TestsBase, ITest2
#pragma warning restore 0414
+ public string BreakInField
+ {
+ get {
+ Debugger.Break ();
+ return "Foo";
+ }
+ }
+
public class NestedClass {
}
diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs
index e717d1f676e2..e6ec1dd62967 100644
--- a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs
+++ b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs
@@ -1806,7 +1806,7 @@ public void TypeInfo () {
t = frame.Method.GetParameters ()[7].ParameterType;
var props = t.GetProperties ();
- Assert.AreEqual (3, props.Length);
+ Assert.AreEqual (4, props.Length);
foreach (PropertyInfoMirror prop in props) {
ParameterInfoMirror[] indexes = prop.GetIndexParameters ();
@@ -4953,6 +4953,23 @@ public void IfPropertyStepping () {
Assert.IsTrue ((e as StepEvent).Method.Name == "op_Equality" || (e as StepEvent).Method.Name == "if_property_stepping");
}
+ [Test]
+ public void DebuggerBreakInFieldDoesNotHang () {
+ vm.EnableEvents (EventType.UserBreak);
+ Event e = run_until ("o1");
+
+ StackFrame frame = e.Thread.GetFrames () [0];
+ object val = frame.GetThis ();
+ Assert.IsTrue (val is ObjectMirror);
+ Assert.AreEqual ("Tests", (val as ObjectMirror).Type.Name);
+ ObjectMirror o = (val as ObjectMirror);
+ TypeMirror t = o.Type;
+
+ MethodMirror m = t.GetProperty ("BreakInField").GetGetMethod();
+ Value v = o.InvokeMethod (e.Thread, m, null, InvokeOptions.DisableBreakpoints);
+ AssertValue ("Foo", v);
+ }
+
#if !MONODROID_TOOLS
void HandleEvents () {
diff --git a/mcs/class/System.Windows.Forms/System.Windows.Forms/GridEntry.cs b/mcs/class/System.Windows.Forms/System.Windows.Forms/GridEntry.cs
index 063b89f375c4..8cc5581c3751 100644
--- a/mcs/class/System.Windows.Forms/System.Windows.Forms/GridEntry.cs
+++ b/mcs/class/System.Windows.Forms/System.Windows.Forms/GridEntry.cs
@@ -466,8 +466,7 @@ public bool SetValue (object value, out string error)
if (this.IsReadOnly)
return false;
- if (value != Value) {
- SetValueCore(value, out error);
+ if (SetValueCore (value, out error)) {
InvalidateChildGridItemsCache ();
property_grid.OnPropertyValueChangedInternal (this, this.Value);
return true;
@@ -478,6 +477,40 @@ public bool SetValue (object value, out string error)
protected virtual bool SetValueCore (object value, out string error)
{
error = null;
+
+ TypeConverter converter = GetConverter ();
+ Type valueType = value != null ? value.GetType () : null;
+ // if the new value is not of the same type try to convert it
+ if (valueType != null && this.PropertyDescriptor.PropertyType != null &&
+ !this.PropertyDescriptor.PropertyType.IsAssignableFrom (valueType)) {
+ bool conversionError = false;
+ try {
+ if (converter != null &&
+ converter.CanConvertFrom ((ITypeDescriptorContext)this, valueType))
+ value = converter.ConvertFrom ((ITypeDescriptorContext)this,
+ CultureInfo.CurrentCulture, value);
+ } catch (Exception e) {
+ error = e.Message;
+ conversionError = true;
+ }
+ if (conversionError) {
+ string valueText = ConvertToString (value);
+ string errorShortDescription = null;
+ if (valueText != null) {
+ errorShortDescription = "Property value '" + valueText + "' of '" +
+ PropertyDescriptor.Name + "' is not convertible to type '" +
+ this.PropertyDescriptor.PropertyType.Name + "'";
+
+ } else {
+ errorShortDescription = "Property value of '" +
+ PropertyDescriptor.Name + "' is not convertible to type '" +
+ this.PropertyDescriptor.PropertyType.Name + "'";
+ }
+ error = errorShortDescription + Environment.NewLine + Environment.NewLine + error;
+ return false;
+ }
+ }
+
bool changed = false;
bool current_changed = false;
object[] propertyOwners = this.PropertyOwners;
@@ -516,7 +549,7 @@ protected virtual bool SetValueCore (object value, out string error)
if (IsValueType (this.ParentEntry))
current_changed = ParentEntry.SetValueCore (propertyOwners[i], out error);
else
- current_changed = Object.Equals (properties[i].GetValue (propertyOwners[i]), value);
+ current_changed = true;
}
}
if (current_changed)
diff --git a/mcs/class/corlib/System/TimeZoneInfo.Android.cs b/mcs/class/corlib/System/TimeZoneInfo.Android.cs
index fa9f73a4dc68..792a9fe2bc33 100644
--- a/mcs/class/corlib/System/TimeZoneInfo.Android.cs
+++ b/mcs/class/corlib/System/TimeZoneInfo.Android.cs
@@ -58,10 +58,16 @@ unsafe struct AndroidTzDataEntry {
* https://android.googlesource.com/platform/libcore/+/master/luni/src/main/java/libcore/util/ZoneInfoDB.java
*
* This is needed in order to read Android v4.3 tzdata files.
+ *
+ * Android 10+ moved the up-to-date tzdata location to a module updatable via the Google Play Store and the
+ * database location changed (https://source.android.com/devices/architecture/modular-system/runtime#time-zone-data-interactions)
+ * The older locations still exist (at least the `/system/usr/share/zoneinfo` one) but they won't be updated.
*/
sealed class AndroidTzData : IAndroidTimeZoneDB {
internal static readonly string[] Paths = new string[]{
+ GetApexTimeDataRoot () + "/etc/tz/tzdata", // Android 10+, TimeData module where the updates land
+ GetApexRuntimeRoot () + "/etc/tz/tzdata", // Android 10+, Fallback location if the above isn't found or corrupted
Environment.GetEnvironmentVariable ("ANDROID_DATA") + "/misc/zoneinfo/tzdata",
Environment.GetEnvironmentVariable ("ANDROID_ROOT") + "/usr/share/zoneinfo/tzdata",
};
@@ -98,6 +104,26 @@ public string ZoneTab {
get {return zoneTab;}
}
+ static string GetApexTimeDataRoot ()
+ {
+ string ret = Environment.GetEnvironmentVariable ("ANDROID_TZDATA_ROOT");
+ if (!String.IsNullOrEmpty (ret)) {
+ return ret;
+ }
+
+ return "/apex/com.android.tzdata";
+ }
+
+ static string GetApexRuntimeRoot ()
+ {
+ string ret = Environment.GetEnvironmentVariable ("ANDROID_RUNTIME_ROOT");
+ if (!String.IsNullOrEmpty (ret)) {
+ return ret;
+ }
+
+ return "/apex/com.android.runtime";
+ }
+
bool LoadData (string path)
{
if (!File.Exists (path))
diff --git a/mcs/class/corlib/Test/System.Reflection.Emit/EnumBuilderTest.cs b/mcs/class/corlib/Test/System.Reflection.Emit/EnumBuilderTest.cs
index 5432040c5235..6a322c6c5e98 100644
--- a/mcs/class/corlib/Test/System.Reflection.Emit/EnumBuilderTest.cs
+++ b/mcs/class/corlib/Test/System.Reflection.Emit/EnumBuilderTest.cs
@@ -316,6 +316,28 @@ public void TestCreateTypeIncompleteEnumStaticField ()
Assert.Fail ("Expected CreateInstance of a broken type to throw TLE");
}
+ [Test]
+ public void TestCreateInvalidEnumWithAnIncompleteUnderlyingEnumType ()
+ {
+ var mb = GenerateModule ();
+ var incomplete = GenerateEnum (mb);
+ GenerateField (incomplete);
+
+ var eb = mb.DefineEnum (
+ _enumNamespace + ".IncompleteUnderlying",
+ TypeAttributes.Public,
+ incomplete);
+
+ bool caught = false;
+ try {
+ var t = eb.CreateType ();
+ } catch (TypeLoadException exn) {
+ caught = true;
+ }
+ if (!caught)
+ Assert.Fail ("Expected CreateType of a broken type to throw TLE");
+ }
+
[Test]
public void TestEnumBuilderTokenUsable () {
// Regression test for https://bugzilla.xamarin.com/show_bug.cgi?id=58361
diff --git a/mcs/tools/resgen/monoresgen.cs b/mcs/tools/resgen/monoresgen.cs
index c5f5ac1e900d..6681bd4e5585 100644
--- a/mcs/tools/resgen/monoresgen.cs
+++ b/mcs/tools/resgen/monoresgen.cs
@@ -72,7 +72,9 @@ static IResourceReader GetReader (Stream stream, string name, bool useSourcePath
return new ResourceReader (stream);
case ".resx":
var reader = new ResXResourceReader (stream);
- reader.BasePath = Path.GetDirectoryName (name);
+ if (useSourcePath) {
+ reader.BasePath = Path.GetDirectoryName (name);
+ }
return reader;
default:
throw new Exception ("Unknown format in file " + name);
diff --git a/mono/CMakeLists.txt b/mono/CMakeLists.txt
index ab9dc695aaad..6f86d9a26ccf 100644
--- a/mono/CMakeLists.txt
+++ b/mono/CMakeLists.txt
@@ -1,8 +1,8 @@
-project (mono)
+project(mono)
-#set (subdirs eglib arch utils cil sgen metadata mini dis profiler)
-set (subdirs mini)
+#set(subdirs eglib arch utils cil sgen metadata mini dis profiler)
+set(subdirs mini profiler)
-foreach (dir ${subdirs})
- add_subdirectory (${dir})
-endforeach ()
+foreach(dir ${subdirs})
+ add_subdirectory(${dir})
+endforeach()
diff --git a/mono/cil/cil-opcodes.xml b/mono/cil/cil-opcodes.xml
index 365b258eaf3d..50b70144d16a 100644
--- a/mono/cil/cil-opcodes.xml
+++ b/mono/cil/cil-opcodes.xml
@@ -325,4 +325,6 @@
+
+
diff --git a/mono/cil/opcode.def b/mono/cil/opcode.def
index 43722f6d3282..a39b315bac5e 100644
--- a/mono/cil/opcode.def
+++ b/mono/cil/opcode.def
@@ -325,6 +325,8 @@ OPDEF(CEE_MONO_LDPTR_PROFILER_ALLOCATION_COUNT, "mono_ldptr_profiler_allocation_
OPDEF(CEE_MONO_LD_DELEGATE_METHOD_PTR, "mono_ld_delegate_method_ptr", Pop1, PushI, InlineNone, 0, 2, 0xF0, 0x1E, NEXT)
OPDEF(CEE_MONO_RETHROW, "mono_rethrow", PopRef, Push0, InlineNone, 0, 2, 0xF0, 0x1F, ERROR)
OPDEF(CEE_MONO_GET_SP, "mono_get_sp", Pop0, PushI, InlineNone, 0, 2, 0xF0, 0x20, NEXT)
+OPDEF(CEE_MONO_METHODCONST, "mono_methodconst", Pop0, PushI, InlineI, 0, 2, 0xF0, 0x21, NEXT)
+OPDEF(CEE_MONO_PINVOKE_ADDR_CACHE, "mono_pinvoke_addr_cache", Pop0, PushI, InlineI, 0, 2, 0xF0, 0x22, NEXT)
#ifndef OPALIAS
#define _MONO_CIL_OPALIAS_DEFINED_
#define OPALIAS(a,s,r)
diff --git a/mono/eglib/eglib-remap.h b/mono/eglib/eglib-remap.h
index c9751049c3b7..6434803195e8 100644
--- a/mono/eglib/eglib-remap.h
+++ b/mono/eglib/eglib-remap.h
@@ -159,6 +159,7 @@
#define g_ptr_array_sized_new monoeg_g_ptr_array_sized_new
#define g_ptr_array_sort monoeg_g_ptr_array_sort
#define g_ptr_array_sort_with_data monoeg_g_ptr_array_sort_with_data
+#define g_ptr_array_find monoeg_g_ptr_array_find
#define g_qsort_with_data monoeg_g_qsort_with_data
#define g_queue_free monoeg_g_queue_free
#define g_queue_is_empty monoeg_g_queue_is_empty
diff --git a/mono/eglib/glib.h b/mono/eglib/glib.h
index 4272679aeb13..698ad614e4ee 100644
--- a/mono/eglib/glib.h
+++ b/mono/eglib/glib.h
@@ -726,6 +726,7 @@ void g_ptr_array_set_size (GPtrArray *array, gint length);
gpointer *g_ptr_array_free (GPtrArray *array, gboolean free_seg);
void g_ptr_array_foreach (GPtrArray *array, GFunc func, gpointer user_data);
guint g_ptr_array_capacity (GPtrArray *array);
+gboolean g_ptr_array_find (GPtrArray *array, gconstpointer needle, guint *index);
#define g_ptr_array_index(array,index) (array)->pdata[(index)]
//FIXME previous missing parens
diff --git a/mono/eglib/gptrarray.c b/mono/eglib/gptrarray.c
index 09ea774d21c7..18509bc4accf 100644
--- a/mono/eglib/gptrarray.c
+++ b/mono/eglib/gptrarray.c
@@ -229,3 +229,18 @@ g_ptr_array_capacity (GPtrArray *array)
{
return ((GPtrArrayPriv *)array)->size;
}
+
+gboolean
+g_ptr_array_find (GPtrArray *array, gconstpointer needle, guint *index)
+{
+ g_assert (array);
+ for (int i = 0; i < array->len; i++) {
+ if (array->pdata [i] == needle) {
+ if (index)
+ *index = i;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c
index 11d04619eb13..88686b608281 100644
--- a/mono/metadata/appdomain.c
+++ b/mono/metadata/appdomain.c
@@ -2480,7 +2480,7 @@ mono_domain_assembly_preload (MonoAssemblyLoadContext *alc,
char *base_dir = get_app_context_base_directory (error);
search_path [0] = base_dir;
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Domain %s (%p) ApplicationBase is %s", domain->friendly_name, domain, base_dir);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Domain (%p) ApplicationBase is %s", domain, base_dir);
result = real_load (search_path, aname->culture, aname->name, &req);
@@ -2821,7 +2821,7 @@ mono_alc_load_raw_bytes (MonoAssemblyLoadContext *alc, guint8 *assembly_data, gu
{
MonoAssembly *ass = NULL;
MonoImageOpenStatus status;
- MonoImage *image = mono_image_open_from_data_internal (alc, (char*)assembly_data, raw_assembly_len, FALSE, NULL, refonly, FALSE, NULL);
+ MonoImage *image = mono_image_open_from_data_internal (alc, (char*)assembly_data, raw_assembly_len, FALSE, NULL, refonly, FALSE, NULL, NULL);
if (!image) {
mono_error_set_bad_image_by_name (error, "In memory assembly", "0x%p", assembly_data);
diff --git a/mono/metadata/appdomain.h b/mono/metadata/appdomain.h
index ab260646e900..bc8a1f2de199 100644
--- a/mono/metadata/appdomain.h
+++ b/mono/metadata/appdomain.h
@@ -106,6 +106,9 @@ mono_domain_foreach (MonoDomainFunc func, void* user_data);
MONO_API MONO_RT_EXTERNAL_ONLY MonoAssembly *
mono_domain_assembly_open (MonoDomain *domain, const char *name);
+MONO_API void
+mono_domain_ensure_entry_assembly (MonoDomain *domain, MonoAssembly *assembly);
+
MONO_API mono_bool
mono_domain_finalize (MonoDomain *domain, uint32_t timeout);
diff --git a/mono/metadata/assembly-load-context.c b/mono/metadata/assembly-load-context.c
index 7aa927d21af2..ec46fbc2b528 100644
--- a/mono/metadata/assembly-load-context.c
+++ b/mono/metadata/assembly-load-context.c
@@ -15,7 +15,7 @@
GENERATE_GET_CLASS_WITH_CACHE (assembly_load_context, "System.Runtime.Loader", "AssemblyLoadContext");
-void
+static void
mono_alc_init (MonoAssemblyLoadContext *alc, MonoDomain *domain, gboolean collectible)
{
MonoLoadedImages *li = g_new0 (MonoLoadedImages, 1);
@@ -30,36 +30,63 @@ mono_alc_init (MonoAssemblyLoadContext *alc, MonoDomain *domain, gboolean collec
mono_coop_mutex_init (&alc->pinvoke_lock);
}
+static MonoAssemblyLoadContext *
+mono_alc_create (MonoDomain *domain, gboolean is_default, gboolean collectible)
+{
+ MonoAssemblyLoadContext *alc = NULL;
+
+ mono_domain_alcs_lock (domain);
+ if (is_default && domain->default_alc)
+ goto leave;
+
+ alc = g_new0 (MonoAssemblyLoadContext, 1);
+ mono_alc_init (alc, domain, collectible);
+
+ domain->alcs = g_slist_prepend (domain->alcs, alc);
+ if (is_default)
+ domain->default_alc = alc;
+
+leave:
+ mono_domain_alcs_unlock (domain);
+ return alc;
+}
+
void
-mono_alc_cleanup (MonoAssemblyLoadContext *alc)
+mono_alc_create_default (MonoDomain *domain)
{
- /*
- * This is still very much WIP. It needs to be split up into various other functions and adjusted to work with the
- * managed LoaderAllocator design. For now, I've put it all in this function, but don't look at it too closely.
- *
- * Of particular note: the minimum refcount on assemblies is 2: one for the domain and one for the ALC.
- * The domain refcount might be less than optimal on netcore, but its removal is too likely to cause issues for now.
- */
- GSList *tmp;
- MonoDomain *domain = alc->domain;
+ if (domain->default_alc)
+ return;
+ mono_alc_create (domain, TRUE, FALSE);
+}
- g_assert (alc != mono_domain_default_alc (domain));
- g_assert (alc->collectible == TRUE);
+MonoAssemblyLoadContext *
+mono_alc_create_individual (MonoDomain *domain, MonoGCHandle this_gchandle, gboolean collectible, MonoError *error)
+{
+ MonoAssemblyLoadContext *alc = mono_alc_create (domain, FALSE, collectible);
+
+ alc->gchandle = this_gchandle;
+
+ return alc;
+}
- // FIXME: alc unloading profiler event
+static void
+mono_alc_cleanup_assemblies (MonoAssemblyLoadContext *alc)
+{
+ // The minimum refcount on assemblies is 2: one for the domain and one for the ALC.
+ // The domain refcount might be less than optimal on netcore, but its removal is too likely to cause issues for now.
+ GSList *tmp;
+ MonoDomain *domain = alc->domain;
// Remove the assemblies from domain_assemblies
mono_domain_assemblies_lock (domain);
for (tmp = alc->loaded_assemblies; tmp; tmp = tmp->next) {
MonoAssembly *assembly = (MonoAssembly *)tmp->data;
- g_slist_remove (domain->domain_assemblies, assembly);
- mono_atomic_dec_i32 (&assembly->ref_count);
+ domain->domain_assemblies = g_slist_remove (domain->domain_assemblies, assembly);
+ mono_assembly_decref (assembly);
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Unloading ALC [%p], removing assembly %s[%p] from domain_assemblies, ref_count=%d\n", alc, assembly->aname.name, assembly, assembly->ref_count);
}
mono_domain_assemblies_unlock (domain);
- // Some equivalent to mono_gc_clear_domain? I guess in our case we just have to assert that we have no lingering references?
-
// Release the GC roots
for (tmp = alc->loaded_assemblies; tmp; tmp = tmp->next) {
MonoAssembly *assembly = (MonoAssembly *)tmp->data;
@@ -99,17 +126,48 @@ mono_alc_cleanup (MonoAssemblyLoadContext *alc)
g_slist_free (alc->loaded_assemblies);
alc->loaded_assemblies = NULL;
- // FIXME: alc unloaded profiler event
-
- g_hash_table_destroy (alc->pinvoke_scopes);
mono_coop_mutex_destroy (&alc->assemblies_lock);
- mono_coop_mutex_destroy (&alc->pinvoke_lock);
mono_loaded_images_free (alc->loaded_images);
+ alc->loaded_images = NULL;
// TODO: free mempool stuff/jit info tables, see domain freeing for an example
}
+static void
+mono_alc_cleanup (MonoAssemblyLoadContext *alc)
+{
+ MonoDomain *domain = alc->domain;
+
+ g_assert (alc != mono_domain_default_alc (domain));
+ g_assert (alc->collectible == TRUE);
+
+ // TODO: alc unloading profiler event
+
+ // Remove from domain list
+ mono_domain_alcs_lock (domain);
+ domain->alcs = g_slist_remove (domain->alcs, alc);
+ mono_domain_alcs_unlock (domain);
+
+ mono_alc_cleanup_assemblies (alc);
+
+ mono_gchandle_free_internal (alc->gchandle);
+ alc->gchandle = NULL;
+
+ g_hash_table_destroy (alc->pinvoke_scopes);
+ alc->pinvoke_scopes = NULL;
+ mono_coop_mutex_destroy (&alc->pinvoke_lock);
+
+ // TODO: alc unloaded profiler event
+}
+
+static void
+mono_alc_free (MonoAssemblyLoadContext *alc)
+{
+ mono_alc_cleanup (alc);
+ g_free (alc);
+}
+
void
mono_alc_assemblies_lock (MonoAssemblyLoadContext *alc)
{
@@ -136,10 +194,9 @@ ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalInitializeNativeALC
g_assert (alc);
if (!alc->gchandle)
alc->gchandle = this_gchandle;
- } else {
- /* create it */
- alc = mono_domain_create_individual_alc (domain, this_gchandle, collectible, error);
- }
+ } else
+ alc = mono_alc_create_individual (domain, this_gchandle, collectible, error);
+
return alc;
}
@@ -149,10 +206,13 @@ ves_icall_System_Runtime_Loader_AssemblyLoadContext_PrepareForAssemblyLoadContex
MonoGCHandle strong_gchandle = (MonoGCHandle)strong_gchandle_ptr;
MonoAssemblyLoadContext *alc = (MonoAssemblyLoadContext *)alc_pointer;
- g_assert (alc->collectible == TRUE);
- g_assert (alc->unloading == FALSE);
+ g_assert (alc->collectible);
+ g_assert (!alc->unloading);
+ g_assert (alc->gchandle);
+
alc->unloading = TRUE;
+ // Replace the weak gchandle with the new strong one to keep the managed ALC alive
MonoGCHandle weak_gchandle = alc->gchandle;
alc->gchandle = strong_gchandle;
mono_gchandle_free_internal (weak_gchandle);
@@ -176,9 +236,10 @@ mono_alc_is_default (MonoAssemblyLoadContext *alc)
MonoAssemblyLoadContext *
mono_alc_from_gchandle (MonoGCHandle alc_gchandle)
{
+ HANDLE_FUNCTION_ENTER ();
MonoManagedAssemblyLoadContextHandle managed_alc = MONO_HANDLE_CAST (MonoManagedAssemblyLoadContext, mono_gchandle_get_target_handle (alc_gchandle));
- MonoAssemblyLoadContext *alc = (MonoAssemblyLoadContext *)MONO_HANDLE_GETVAL (managed_alc, native_assembly_load_context);
- return alc;
+ MonoAssemblyLoadContext *alc = MONO_HANDLE_GETVAL (managed_alc, native_assembly_load_context);
+ HANDLE_FUNCTION_RETURN_VAL (alc);
}
MonoGCHandle
diff --git a/mono/metadata/assembly.c b/mono/metadata/assembly.c
index 5f37bb0c8e23..4d8893bdc8d6 100644
--- a/mono/metadata/assembly.c
+++ b/mono/metadata/assembly.c
@@ -1310,10 +1310,16 @@ assemblyref_public_tok_checked (MonoImage *image, guint32 key_index, guint32 fla
* The reference count is reduced every time the method mono_assembly_close() is
* invoked.
*/
-void
+gint32
mono_assembly_addref (MonoAssembly *assembly)
{
- mono_atomic_inc_i32 (&assembly->ref_count);
+ return mono_atomic_inc_i32 (&assembly->ref_count);
+}
+
+gint32
+mono_assembly_decref (MonoAssembly *assembly)
+{
+ return mono_atomic_dec_i32 (&assembly->ref_count);
}
/*
@@ -1644,6 +1650,27 @@ load_reference_by_aname_individual_asmctx (MonoAssemblyName *aname, MonoAssembly
return reference;
}
#else
+static MonoAssembly *
+search_bundle_for_assembly (MonoAssemblyLoadContext *alc, MonoAssemblyName *aname)
+{
+ if (bundles == NULL)
+ return NULL;
+
+ MonoImageOpenStatus status;
+ MonoImage *image;
+ MonoAssemblyLoadRequest req;
+ image = mono_assembly_open_from_bundle (alc, aname->name, &status, FALSE);
+ if (!image) {
+ char *name = g_strdup_printf ("%s.dll", aname->name);
+ image = mono_assembly_open_from_bundle (alc, name, &status, FALSE);
+ }
+ if (image) {
+ mono_assembly_request_prepare_load (&req, MONO_ASMCTX_DEFAULT, alc);
+ return mono_assembly_request_load_from (image, aname->name, &req, &status);
+ }
+ return NULL;
+}
+
static MonoAssembly*
netcore_load_reference (MonoAssemblyName *aname, MonoAssemblyLoadContext *alc, MonoAssembly *requesting, gboolean postload)
{
@@ -1665,61 +1692,85 @@ netcore_load_reference (MonoAssemblyName *aname, MonoAssemblyLoadContext *alc, M
* Try these until one of them succeeds (by returning a non-NULL reference):
* 1. Check if it's already loaded by the ALC.
*
- * 2. If it's a non-default ALC, call the Load() method.
+ * 2. If we have a bundle registered, search the images for a matching name.
+ *
+ * 3. If it's a non-default ALC, call the Load() method.
*
- * 3. If the ALC is not the default and this is not a satellite request,
+ * 4. If the ALC is not the default and this is not a satellite request,
* check if it's already loaded by the default ALC.
*
- * 4. If the ALC is the default or this is not a satellite request,
+ * 5. If the ALC is the default or this is not a satellite request,
* check the TPA list, APP_PATHS, and ApplicationBase.
*
- * 5. If this is a satellite request, call the ALC ResolveSatelliteAssembly method.
+ * 6. If this is a satellite request, call the ALC ResolveSatelliteAssembly method.
*
- * 6. Call the ALC Resolving event.
+ * 7. Call the ALC Resolving event.
*
- * 7. Call the ALC AssemblyResolve event (except for corlib satellite assemblies).
+ * 8. Call the ALC AssemblyResolve event (except for corlib satellite assemblies).
*
- * 8. Return NULL.
+ * 9. Return NULL.
*/
reference = mono_assembly_loaded_internal (alc, aname, FALSE);
- if (reference)
+ if (reference) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly already loaded in the active ALC: '%s'.", aname->name);
goto leave;
+ }
+
+ if (bundles != NULL) {
+ reference = search_bundle_for_assembly (alc, aname);
+ if (reference) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly found in the bundle: '%s'.", aname->name);
+ goto leave;
+ }
+ }
if (!is_default) {
reference = mono_alc_invoke_resolve_using_load_nofail (alc, aname);
- if (reference)
+ if (reference) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly found using Load method: '%s'.", aname->name);
goto leave;
+ }
}
if (!is_default && !is_satellite) {
reference = mono_assembly_loaded_internal (mono_domain_default_alc (mono_alc_domain (alc)), aname, FALSE);
- if (reference)
+ if (reference) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly already loaded in the default ALC: '%s'.", aname->name);
goto leave;
+ }
}
if (is_default || !is_satellite) {
reference = invoke_assembly_preload_hook (mono_domain_default_alc (mono_alc_domain (alc)), aname, assemblies_path);
- if (reference)
+ if (reference) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly found with the filesystem probing logic: '%s'.", aname->name);
goto leave;
+ }
}
if (is_satellite) {
reference = mono_alc_invoke_resolve_using_resolve_satellite_nofail (alc, aname);
- if (reference)
+ if (reference) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly found with ResolveSatelliteAssembly method: '%s'.", aname->name);
goto leave;
+ }
}
reference = mono_alc_invoke_resolve_using_resolving_event_nofail (alc, aname);
- if (reference)
+ if (reference) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly found with the Resolving event: '%s'.", aname->name);
goto leave;
+ }
// Looking up corlib resources here can cause an infinite loop
// See: https://github.com/dotnet/coreclr/blob/0a762eb2f3a299489c459da1ddeb69e042008f07/src/vm/appdomain.cpp#L5178-L5239
if (!(strcmp (aname->name, MONO_ASSEMBLY_CORLIB_RESOURCE_NAME) == 0 && is_satellite) && postload) {
reference = mono_assembly_invoke_search_hook_internal (alc, requesting, aname, FALSE, TRUE);
- if (reference)
+ if (reference) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly found with AssemblyResolve event: '%s'.", aname->name);
goto leave;
+ }
}
leave:
@@ -2502,7 +2553,12 @@ mono_assembly_open_from_bundle (MonoAssemblyLoadContext *alc, const char *filena
name = g_path_get_basename (filename);
for (i = 0; !image && bundles [i]; ++i) {
if (strcmp (bundles [i]->name, is_satellite ? filename : name) == 0) {
- image = mono_image_open_from_data_internal (alc, (char*)bundles [i]->data, bundles [i]->size, FALSE, status, refonly, FALSE, name);
+#ifdef ENABLE_NETCORE
+ // Since bundled images don't exist on disk, don't give them a legit filename
+ image = mono_image_open_from_data_internal (alc, (char*)bundles [i]->data, bundles [i]->size, FALSE, status, refonly, FALSE, name, NULL);
+#else
+ image = mono_image_open_from_data_internal (alc, (char*)bundles [i]->data, bundles [i]->size, FALSE, status, refonly, FALSE, name, name);
+#endif
break;
}
}
@@ -2725,8 +2781,10 @@ mono_assembly_request_open (const char *filename, const MonoAssemblyOpenRequest
if (!loaded_from_bundle)
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY,
"Assembly Loader loaded assembly from location: '%s'.", filename);
+#ifndef ENABLE_NETCORE // no XML file loading on netcore
if (!refonly)
mono_config_for_assembly_internal (ass->image);
+#endif
}
/* Clear the reference added by mono_image_open */
@@ -4851,20 +4909,7 @@ mono_assembly_request_byname (MonoAssemblyName *aname, const MonoAssemblyByNameR
result = prevent_reference_assembly_from_running (result, refonly);
}
#else
- result = NULL;
- if (bundles != NULL) {
- MonoImageOpenStatus status;
- MonoImage *image;
- image = mono_assembly_open_from_bundle (req->request.alc, aname->name, &status, FALSE);
- if (!image) {
- char *name = g_strdup_printf ("%s.dll", aname->name);
- image = mono_assembly_open_from_bundle (req->request.alc, name, &status, FALSE);
- }
- if (image)
- result = mono_assembly_request_load_from (image, aname->name, &req->request, &status);
- }
- if (!result)
- result = netcore_load_reference (aname, req->request.alc, req->requesting_assembly, !req->no_postload_search);
+ result = netcore_load_reference (aname, req->request.alc, req->requesting_assembly, !req->no_postload_search);
#endif
return result;
}
@@ -5020,7 +5065,7 @@ mono_assembly_close_except_image_pools (MonoAssembly *assembly)
return FALSE;
/* Might be 0 already */
- if (mono_atomic_dec_i32 (&assembly->ref_count) > 0)
+ if (mono_assembly_decref (assembly) > 0)
return FALSE;
MONO_PROFILER_RAISE (assembly_unloading, (assembly));
diff --git a/mono/metadata/debug-mono-ppdb.c b/mono/metadata/debug-mono-ppdb.c
index c4dd3d1d4d67..38c619a61b85 100644
--- a/mono/metadata/debug-mono-ppdb.c
+++ b/mono/metadata/debug-mono-ppdb.c
@@ -194,7 +194,7 @@ mono_ppdb_load_file (MonoImage *image, const guint8 *raw_contents, int size)
MonoAssemblyLoadContext *alc = mono_image_get_alc (image);
if (raw_contents) {
if (size > 4 && strncmp ((char*)raw_contents, "BSJB", 4) == 0)
- ppdb_image = mono_image_open_from_data_internal (alc, (char*)raw_contents, size, TRUE, &status, FALSE, TRUE, NULL);
+ ppdb_image = mono_image_open_from_data_internal (alc, (char*)raw_contents, size, TRUE, &status, FALSE, TRUE, NULL, NULL);
} else {
/* ppdb files drop the .exe/.dll extension */
filename = mono_image_get_filename (image);
diff --git a/mono/metadata/domain-internals.h b/mono/metadata/domain-internals.h
index 2acdd85d20d4..3968a773ddf4 100644
--- a/mono/metadata/domain-internals.h
+++ b/mono/metadata/domain-internals.h
@@ -692,15 +692,21 @@ mono_runtime_install_appctx_properties (void);
gboolean
mono_domain_set_fast (MonoDomain *domain, gboolean force);
-void
-mono_domain_ensure_entry_assembly (MonoDomain *domain, MonoAssembly *assembly);
-
MonoAssemblyLoadContext *
mono_domain_default_alc (MonoDomain *domain);
#ifdef ENABLE_NETCORE
-MonoAssemblyLoadContext *
-mono_domain_create_individual_alc (MonoDomain *domain, MonoGCHandle this_gchandle, gboolean collectible, MonoError *error);
+static inline void
+mono_domain_alcs_lock (MonoDomain *domain)
+{
+ mono_coop_mutex_lock (&domain->alcs_lock);
+}
+
+static inline void
+mono_domain_alcs_unlock (MonoDomain *domain)
+{
+ mono_coop_mutex_unlock (&domain->alcs_lock);
+}
#endif
static inline
diff --git a/mono/metadata/domain.c b/mono/metadata/domain.c
index 4f4294adda2e..36271f8c2022 100644
--- a/mono/metadata/domain.c
+++ b/mono/metadata/domain.c
@@ -128,17 +128,6 @@ get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image);
static const MonoRuntimeInfo*
get_runtime_by_version (const char *version);
-#ifdef ENABLE_NETCORE
-static void
-mono_domain_alcs_lock (MonoDomain *domain);
-
-static void
-mono_domain_alcs_unlock (MonoDomain *domain);
-
-static void
-mono_domain_create_default_alc (MonoDomain *domain);
-#endif
-
static LockFreeMempool*
lock_free_mempool_new (void)
{
@@ -482,7 +471,7 @@ mono_domain_create (void)
mono_debug_domain_create (domain);
#ifdef ENABLE_NETCORE
- mono_domain_create_default_alc (domain);
+ mono_alc_create_default (domain);
#endif
if (create_domain_hook)
@@ -2075,60 +2064,3 @@ mono_domain_default_alc (MonoDomain *domain)
return domain->default_alc;
#endif
}
-
-#ifdef ENABLE_NETCORE
-static inline void
-mono_domain_alcs_lock (MonoDomain *domain)
-{
- mono_coop_mutex_lock (&domain->alcs_lock);
-}
-
-static inline void
-mono_domain_alcs_unlock (MonoDomain *domain)
-{
- mono_coop_mutex_unlock (&domain->alcs_lock);
-}
-
-static MonoAssemblyLoadContext *
-create_alc (MonoDomain *domain, gboolean is_default, gboolean collectible)
-{
- MonoAssemblyLoadContext *alc = NULL;
-
- mono_domain_alcs_lock (domain);
- if (is_default && domain->default_alc)
- goto leave;
-
- alc = g_new0 (MonoAssemblyLoadContext, 1);
- mono_alc_init (alc, domain, collectible);
-
- domain->alcs = g_slist_prepend (domain->alcs, alc);
- if (is_default)
- domain->default_alc = alc;
-leave:
- mono_domain_alcs_unlock (domain);
- return alc;
-}
-
-void
-mono_domain_create_default_alc (MonoDomain *domain)
-{
- if (domain->default_alc)
- return;
- create_alc (domain, TRUE, FALSE);
-}
-
-MonoAssemblyLoadContext *
-mono_domain_create_individual_alc (MonoDomain *domain, MonoGCHandle this_gchandle, gboolean collectible, MonoError *error)
-{
- MonoAssemblyLoadContext *alc = create_alc (domain, FALSE, collectible);
- alc->gchandle = this_gchandle;
- return alc;
-}
-
-static void
-mono_alc_free (MonoAssemblyLoadContext *alc)
-{
- mono_alc_cleanup (alc);
- g_free (alc);
-}
-#endif
diff --git a/mono/metadata/filewatcher.c b/mono/metadata/filewatcher.c
index 69ab3a89fb08..cf1646114cd2 100644
--- a/mono/metadata/filewatcher.c
+++ b/mono/metadata/filewatcher.c
@@ -10,6 +10,7 @@
*/
#include
+#include
#if !ENABLE_NETCORE
@@ -186,4 +187,8 @@ ves_icall_System_IO_KqueueMonitor_kevent_notimeout (int *kq_ptr, gpointer change
#endif /* #if HAVE_KQUEUE */
+#else
+
+MONO_EMPTY_SOURCE_FILE (filewatcher);
+
#endif /* !ENABLE_NETCORE */
diff --git a/mono/metadata/handle.h b/mono/metadata/handle.h
index 6a9ad056deb7..0be5c18d206f 100644
--- a/mono/metadata/handle.h
+++ b/mono/metadata/handle.h
@@ -517,7 +517,10 @@ TYPED_HANDLE_DECL (MonoException);
TYPED_HANDLE_DECL (MonoAppContext);
/* Simpler version of MONO_HANDLE_NEW if the handle is not used */
-#define MONO_HANDLE_PIN(object) MONO_HANDLE_NEW (MonoObject, (object))
+#define MONO_HANDLE_PIN(object) do { \
+ if ((object) != NULL) \
+ MONO_HANDLE_NEW (MonoObject, (MonoObject*)(object)); \
+ } while (0)
// Structs cannot be cast to structs.
// As well, a function is needed because an anonymous struct cannot be initialized in C.
diff --git a/mono/metadata/icall-decl.h b/mono/metadata/icall-decl.h
index 2c153f8cd6c9..858a7b8830a6 100644
--- a/mono/metadata/icall-decl.h
+++ b/mono/metadata/icall-decl.h
@@ -304,4 +304,8 @@ ICALL_EXPORT gint32 ves_icall_System_Threading_LowLevelLifoSemaphore_TimedWait
ICALL_EXPORT void ves_icall_System_Threading_LowLevelLifoSemaphore_ReleaseInternal (gpointer sem_ptr, gint32 count);
#endif
+#if defined(ENABLE_NETCORE) && defined(TARGET_AMD64)
+ICALL_EXPORT void ves_icall_System_Runtime_Intrinsics_X86_X86Base___cpuidex (int abcd[4], int function_id, int subfunction_id);
+#endif
+
#endif // __MONO_METADATA_ICALL_DECL_H__
diff --git a/mono/metadata/icall-def-netcore.h b/mono/metadata/icall-def-netcore.h
index 8e3a61820b65..60283d09e9da 100644
--- a/mono/metadata/icall-def-netcore.h
+++ b/mono/metadata/icall-def-netcore.h
@@ -373,6 +373,11 @@ HANDLES(NATIVEL_2, "GetSymbol", ves_icall_System_Runtime_InteropServices_NativeL
HANDLES(NATIVEL_3, "LoadByName", ves_icall_System_Runtime_InteropServices_NativeLibrary_LoadByName, gpointer, 5, (MonoString, MonoReflectionAssembly, MonoBoolean, guint32, MonoBoolean))
HANDLES(NATIVEL_4, "LoadFromPath", ves_icall_System_Runtime_InteropServices_NativeLibrary_LoadFromPath, gpointer, 2, (MonoString, MonoBoolean))
+#if defined(TARGET_AMD64)
+ICALL_TYPE(X86BASE, "System.Runtime.Intrinsics.X86.X86Base", X86BASE_1)
+NOHANDLES(ICALL(X86BASE_1, "__cpuidex", ves_icall_System_Runtime_Intrinsics_X86_X86Base___cpuidex))
+#endif
+
ICALL_TYPE(ALC, "System.Runtime.Loader.AssemblyLoadContext", ALC_5)
HANDLES(ALC_5, "GetLoadContextForAssembly", ves_icall_System_Runtime_Loader_AssemblyLoadContext_GetLoadContextForAssembly, gpointer, 1, (MonoReflectionAssembly))
HANDLES(ALC_4, "InternalGetLoadedAssemblies", ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalGetLoadedAssemblies, MonoArray, 0, ())
diff --git a/mono/metadata/icall-eventpipe.c b/mono/metadata/icall-eventpipe.c
index 4222ffb72e80..ae86f89ac426 100644
--- a/mono/metadata/icall-eventpipe.c
+++ b/mono/metadata/icall-eventpipe.c
@@ -320,7 +320,7 @@ ves_icall_System_Diagnostics_Tracing_EventPipeInternal_Enable (
(EventPipeSerializationFormat)format,
true,
NULL,
- true);
+ NULL);
ep_start_streaming (session_id);
if (config_providers) {
@@ -341,7 +341,7 @@ ves_icall_System_Diagnostics_Tracing_EventPipeInternal_EventActivityIdControl (
/* GUID * */uint8_t *activity_id)
{
int32_t result = 0;
- EventPipeThread *thread = ep_thread_get ();
+ EventPipeThread *thread = ep_thread_get_or_create ();
if (thread == NULL)
return 1;
@@ -359,9 +359,14 @@ ves_icall_System_Diagnostics_Tracing_EventPipeInternal_EventActivityIdControl (
ep_thread_create_activity_id (activity_id, EP_ACTIVITY_ID_SIZE);
break;
case EP_ACTIVITY_CONTROL_GET_SET_ID:
+ ep_thread_get_activity_id (thread, current_activity_id, EP_ACTIVITY_ID_SIZE);
+ ep_thread_set_activity_id (thread, activity_id, EP_ACTIVITY_ID_SIZE);
+ memcpy (activity_id, current_activity_id, EP_ACTIVITY_ID_SIZE);
+ break;
+ case EP_ACTIVITY_CONTROL_CREATE_SET_ID:
ep_thread_get_activity_id (thread, activity_id, EP_ACTIVITY_ID_SIZE);
- ep_thread_create_activity_id (current_activity_id, G_N_ELEMENTS (current_activity_id));
- ep_thread_set_activity_id (thread, current_activity_id, G_N_ELEMENTS (current_activity_id));
+ ep_thread_create_activity_id (current_activity_id, EP_ACTIVITY_ID_SIZE);
+ ep_thread_set_activity_id (thread, current_activity_id, EP_ACTIVITY_ID_SIZE);
break;
default:
result = 1;
diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c
index 948b43f9dec5..df5d20a7f32f 100644
--- a/mono/metadata/icall.c
+++ b/mono/metadata/icall.c
@@ -7230,7 +7230,7 @@ ves_icall_System_Reflection_RuntimeModule_ResolveSignature (MonoImage *image, gu
}
static void
-check_for_invalid_type (MonoClass *klass, MonoError *error)
+check_for_invalid_array_type (MonoClass *klass, MonoError *error)
{
char *name;
@@ -7243,13 +7243,23 @@ check_for_invalid_type (MonoClass *klass, MonoError *error)
mono_error_set_type_load_name (error, name, g_strdup (""), "");
}
+static void
+check_for_invalid_byref_or_pointer_type (MonoClass *klass, MonoError *error)
+{
+#ifdef ENABLE_NETCORE
+ return;
+#else
+ check_for_invalid_array_type (klass, error);
+#endif
+}
+
MonoReflectionTypeHandle
ves_icall_RuntimeType_make_array_type (MonoReflectionTypeHandle ref_type, int rank, MonoError *error)
{
MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
MonoClass *klass = mono_class_from_mono_type_internal (type);
- check_for_invalid_type (klass, error);
+ check_for_invalid_array_type (klass, error);
return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
MonoClass *aklass;
@@ -7276,7 +7286,7 @@ ves_icall_RuntimeType_make_byref_type (MonoReflectionTypeHandle ref_type, MonoEr
mono_class_init_checked (klass, error);
return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
- check_for_invalid_type (klass, error);
+ check_for_invalid_byref_or_pointer_type (klass, error);
return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
@@ -7292,7 +7302,7 @@ ves_icall_RuntimeType_MakePointerType (MonoReflectionTypeHandle ref_type, MonoEr
mono_class_init_checked (klass, error);
return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
- check_for_invalid_type (klass, error);
+ check_for_invalid_byref_or_pointer_type (klass, error);
return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
MonoClass *pklass = mono_class_create_ptr (type);
diff --git a/mono/metadata/image.c b/mono/metadata/image.c
index d0b6c8b42089..2c1a454702de 100644
--- a/mono/metadata/image.c
+++ b/mono/metadata/image.c
@@ -47,6 +47,7 @@
#include
#include
#include
+#include
#include
#include
#ifdef HAVE_UNISTD_H
@@ -1882,7 +1883,7 @@ register_image (MonoLoadedImages *li, MonoImage *image, gboolean *problematic)
}
MonoImage *
-mono_image_open_from_data_internal (MonoAssemblyLoadContext *alc, char *data, guint32 data_len, gboolean need_copy, MonoImageOpenStatus *status, gboolean refonly, gboolean metadata_only, const char *name)
+mono_image_open_from_data_internal (MonoAssemblyLoadContext *alc, char *data, guint32 data_len, gboolean need_copy, MonoImageOpenStatus *status, gboolean refonly, gboolean metadata_only, const char *name, const char *filename)
{
MonoCLIImageInfo *iinfo;
MonoImage *image;
@@ -1904,12 +1905,12 @@ mono_image_open_from_data_internal (MonoAssemblyLoadContext *alc, char *data, gu
memcpy (datac, data, data_len);
}
- MonoImageStorage *storage = mono_image_storage_new_raw_data (datac, data_len, need_copy, name);
+ MonoImageStorage *storage = mono_image_storage_new_raw_data (datac, data_len, need_copy, filename);
image = g_new0 (MonoImage, 1);
image->storage = storage;
mono_image_init_raw_data (image, storage);
- image->name = (name == NULL) ? g_strdup_printf ("data-%p", datac) : g_strdup(name);
- image->filename = name ? g_strdup (name) : NULL;
+ image->name = (name == NULL) ? g_strdup_printf ("data-%p", datac) : g_strdup (name);
+ image->filename = filename ? g_strdup (filename) : NULL;
iinfo = g_new0 (MonoCLIImageInfo, 1);
image->image_info = iinfo;
image->ref_only = refonly;
@@ -1926,6 +1927,21 @@ mono_image_open_from_data_internal (MonoAssemblyLoadContext *alc, char *data, gu
return register_image (mono_alc_get_loaded_images (alc), image, NULL);
}
+MonoImage *
+mono_image_open_from_data_alc (MonoAssemblyLoadContextGCHandle alc_gchandle, char *data, uint32_t data_len, mono_bool need_copy, MonoImageOpenStatus *status, const char *name)
+{
+ MonoImage *result;
+ MONO_ENTER_GC_UNSAFE;
+#ifdef ENABLE_NETCORE
+ MonoAssemblyLoadContext *alc = mono_alc_from_gchandle (alc_gchandle);
+#else
+ MonoAssemblyLoadContext *alc = mono_domain_default_alc (mono_domain_get ());
+#endif
+ result = mono_image_open_from_data_internal (alc, data, data_len, need_copy, status, FALSE, FALSE, name, name);
+ MONO_EXIT_GC_UNSAFE;
+ return result;
+}
+
/**
* mono_image_open_from_data_with_name:
*/
@@ -1935,7 +1951,7 @@ mono_image_open_from_data_with_name (char *data, guint32 data_len, gboolean need
MonoImage *result;
MONO_ENTER_GC_UNSAFE;
MonoDomain *domain = mono_domain_get ();
- result = mono_image_open_from_data_internal (mono_domain_default_alc (domain), data, data_len, need_copy, status, refonly, FALSE, name);
+ result = mono_image_open_from_data_internal (mono_domain_default_alc (domain), data, data_len, need_copy, status, refonly, FALSE, name, name);
MONO_EXIT_GC_UNSAFE;
return result;
}
@@ -1949,7 +1965,7 @@ mono_image_open_from_data_full (char *data, guint32 data_len, gboolean need_copy
MonoImage *result;
MONO_ENTER_GC_UNSAFE;
MonoDomain *domain = mono_domain_get ();
- result = mono_image_open_from_data_internal (mono_domain_default_alc (domain), data, data_len, need_copy, status, refonly, FALSE, NULL);
+ result = mono_image_open_from_data_internal (mono_domain_default_alc (domain), data, data_len, need_copy, status, refonly, FALSE, NULL, NULL);
MONO_EXIT_GC_UNSAFE;
return result;
}
@@ -1963,7 +1979,7 @@ mono_image_open_from_data (char *data, guint32 data_len, gboolean need_copy, Mon
MonoImage *result;
MONO_ENTER_GC_UNSAFE;
MonoDomain *domain = mono_domain_get ();
- result = mono_image_open_from_data_internal (mono_domain_default_alc (domain), data, data_len, need_copy, status, FALSE, FALSE, NULL);
+ result = mono_image_open_from_data_internal (mono_domain_default_alc (domain), data, data_len, need_copy, status, FALSE, FALSE, NULL, NULL);
MONO_EXIT_GC_UNSAFE;
return result;
}
diff --git a/mono/metadata/jit-icall-reg.h b/mono/metadata/jit-icall-reg.h
index 3abbdf45da4d..a9bff58883d7 100644
--- a/mono/metadata/jit-icall-reg.h
+++ b/mono/metadata/jit-icall-reg.h
@@ -340,6 +340,7 @@ MONO_JIT_ICALL (ves_icall_runtime_class_init) \
MONO_JIT_ICALL (ves_icall_string_alloc) \
MONO_JIT_ICALL (ves_icall_string_new_wrapper) \
MONO_JIT_ICALL (ves_icall_thread_finish_async_abort) \
+MONO_JIT_ICALL (mono_marshal_lookup_pinvoke) \
\
MONO_JIT_ICALL (count) \
diff --git a/mono/metadata/loader-internals.h b/mono/metadata/loader-internals.h
index 43134540d59a..6d5f493c8140 100644
--- a/mono/metadata/loader-internals.h
+++ b/mono/metadata/loader-internals.h
@@ -90,10 +90,10 @@ void
mono_set_pinvoke_search_directories (int dir_count, char **dirs);
void
-mono_alc_init (MonoAssemblyLoadContext *alc, MonoDomain *domain, gboolean collectible);
+mono_alc_create_default (MonoDomain *domain);
-void
-mono_alc_cleanup (MonoAssemblyLoadContext *alc);
+MonoAssemblyLoadContext *
+mono_alc_create_individual (MonoDomain *domain, MonoGCHandle this_gchandle, gboolean collectible, MonoError *error);
void
mono_alc_assemblies_lock (MonoAssemblyLoadContext *alc);
@@ -115,7 +115,6 @@ mono_alc_invoke_resolve_using_resolve_satellite_nofail (MonoAssemblyLoadContext
MonoAssemblyLoadContext *
mono_alc_from_gchandle (MonoGCHandle alc_gchandle);
-
#endif /* ENABLE_NETCORE */
static inline MonoDomain *
diff --git a/mono/metadata/marshal-ilgen.c b/mono/metadata/marshal-ilgen.c
index ecff9d08de86..0d80e942e796 100644
--- a/mono/metadata/marshal-ilgen.c
+++ b/mono/metadata/marshal-ilgen.c
@@ -2023,6 +2023,7 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi
MonoClass *klass;
int i, argnum, *tmp_locals;
int type, param_shift = 0;
+ int func_addr_local = -1;
gboolean need_gc_safe = FALSE;
GCSafeTransitionBuilder gc_safe_transition_builder;
@@ -2067,9 +2068,43 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi
mono_mb_add_local (mb, sig->ret);
}
- if (need_gc_safe) {
- gc_safe_transition_builder_add_locals (&gc_safe_transition_builder);
+ if (need_gc_safe)
+ gc_safe_transition_builder_add_locals (&gc_safe_transition_builder);
+
+#ifdef ENABLE_NETCORE
+ if (!func && !aot && !func_param && !MONO_CLASS_IS_IMPORT (mb->method->klass)) {
+ /*
+ * On netcore, its possible to register pinvoke resolvers at runtime, so
+ * a pinvoke lookup can fail, and then succeed later. So if the
+ * original lookup failed, do a lookup every time until it
+ * succeeds.
+ * This adds some overhead, but only when the pinvoke lookup
+ * was not initially successful.
+ * FIXME: AOT case
+ */
+ func_addr_local = mono_mb_add_local (mb, int_type);
+
+ int cache_local = mono_mb_add_local (mb, int_type);
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_op (mb, CEE_MONO_PINVOKE_ADDR_CACHE, &piinfo->method);
+ mono_mb_emit_stloc (mb, cache_local);
+
+ mono_mb_emit_ldloc (mb, cache_local);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ int pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
+
+ mono_mb_emit_ldloc (mb, cache_local);
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_op (mb, CEE_MONO_METHODCONST, &piinfo->method);
+ mono_mb_emit_icall (mb, mono_marshal_lookup_pinvoke);
+ mono_mb_emit_byte (mb, CEE_STIND_I);
+
+ mono_mb_patch_branch (mb, pos);
+ mono_mb_emit_ldloc (mb, cache_local);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_stloc (mb, func_addr_local);
}
+#endif
/*
* cookie = mono_threads_enter_gc_safe_region_unbalanced (ref dummy);
@@ -2139,22 +2174,23 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi
g_assert_not_reached ();
#endif
} else {
- if (aot) {
- /* Reuse the ICALL_ADDR opcode for pinvokes too */
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_op (mb, CEE_MONO_ICALL_ADDR, &piinfo->method);
- if (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) {
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_byte (mb, CEE_MONO_SAVE_LAST_ERROR);
- }
- mono_mb_emit_calli (mb, csig);
+ if (func_addr_local != -1) {
+ mono_mb_emit_ldloc (mb, func_addr_local);
} else {
- if (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) {
+ if (aot) {
+ /* Reuse the ICALL_ADDR opcode for pinvokes too */
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_byte (mb, CEE_MONO_SAVE_LAST_ERROR);
+ mono_mb_emit_op (mb, CEE_MONO_ICALL_ADDR, &piinfo->method);
}
- mono_mb_emit_native_call (mb, csig, func);
}
+ if (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) {
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_SAVE_LAST_ERROR);
+ }
+ if (func_addr_local != -1 || aot)
+ mono_mb_emit_calli (mb, csig);
+ else
+ mono_mb_emit_native_call (mb, csig, func);
}
if (MONO_TYPE_ISSTRUCT (sig->ret)) {
diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c
index 3faa290b12c0..146f90d2b3b9 100644
--- a/mono/metadata/marshal.c
+++ b/mono/metadata/marshal.c
@@ -255,6 +255,7 @@ mono_marshal_init (void)
register_icall (mono_threads_attach_coop, mono_icall_sig_ptr_ptr_ptr, TRUE);
register_icall (mono_threads_detach_coop, mono_icall_sig_void_ptr_ptr, TRUE);
register_icall (mono_marshal_get_type_object, mono_icall_sig_object_ptr, TRUE);
+ register_icall (mono_marshal_lookup_pinvoke, mono_icall_sig_ptr_ptr, FALSE);
mono_cominterop_init ();
mono_remoting_init ();
@@ -3530,6 +3531,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
GHashTable *cache;
gboolean pinvoke = FALSE;
gboolean skip_gc_trans = FALSE;
+ gboolean pinvoke_not_found = FALSE;
gpointer iter;
int i;
ERROR_DECL (emitted_error);
@@ -3678,12 +3680,17 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
return res;
}
-
/*
* In AOT mode and embedding scenarios, it is possible that the icall is not
* registered in the runtime doing the AOT compilation.
*/
- if (!piinfo->addr && !aot) {
+#ifdef ENABLE_NETCORE
+ /* Handled at runtime */
+ pinvoke_not_found = !pinvoke && !piinfo->addr && !aot;
+#else
+ pinvoke_not_found = !piinfo->addr && !aot;
+#endif
+ if (pinvoke_not_found) {
/* if there's no code but the error isn't set, just use a fairly generic exception. */
if (is_ok (emitted_error))
mono_error_set_generic_error (emitted_error, "System", "MissingMethodException", "");
@@ -3702,8 +3709,6 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
return res;
}
- g_assert (is_ok (emitted_error));
-
/* internal calls: we simply push all arguments and call the method (no conversions) */
if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME) && !pinvoke) {
if (sig->hasthis)
@@ -3732,8 +3737,6 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
}
g_assert (pinvoke);
- if (!aot)
- g_assert (piinfo->addr);
csig = mono_metadata_signature_dup_full (get_method_image (method), sig);
mono_marshal_set_callconv_from_modopt (method, csig, FALSE);
@@ -6809,6 +6812,20 @@ mono_marshal_get_type_object (MonoClass *klass)
return result;
}
+gpointer
+mono_marshal_lookup_pinvoke (MonoMethod *method)
+{
+ ERROR_DECL (error);
+ gpointer addr;
+
+ g_assert (method);
+ addr = mono_lookup_pinvoke_call_internal (method, error);
+ if (!addr)
+ g_assert (!is_ok (error));
+ mono_error_set_pending_exception (error);
+ return addr;
+}
+
void
mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func, gboolean aot, gboolean check_exceptions, gboolean func_param, gboolean skip_gc_trans)
{
diff --git a/mono/metadata/marshal.h b/mono/metadata/marshal.h
index 0d35659368cb..18e237363459 100644
--- a/mono/metadata/marshal.h
+++ b/mono/metadata/marshal.h
@@ -605,6 +605,10 @@ mono_marshal_need_free (MonoType *t, MonoMethodPInvoke *piinfo, MonoMarshalSpec
ICALL_EXTERN_C
MonoObject* mono_marshal_get_type_object (MonoClass *klass);
+ICALL_EXTERN_C
+gpointer
+mono_marshal_lookup_pinvoke (MonoMethod *method);
+
ICALL_EXPORT
guint32
ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void);
diff --git a/mono/metadata/metadata-internals.h b/mono/metadata/metadata-internals.h
index 34ef1d307d4b..4767debd6603 100644
--- a/mono/metadata/metadata-internals.h
+++ b/mono/metadata/metadata-internals.h
@@ -216,7 +216,7 @@ struct _MonoAssembly {
* the additional reference, they can be freed at any time.
* The ref_count is initially 0.
*/
- int ref_count; /* use atomic operations only */
+ gint32 ref_count; /* use atomic operations only */
char *basedir;
MonoAssemblyName aname;
MonoImage *image;
@@ -1011,10 +1011,14 @@ gboolean
mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2);
void mono_dynamic_stream_reset (MonoDynamicStream* stream);
-MONO_API void mono_assembly_addref (MonoAssembly *assembly);
void mono_assembly_load_friends (MonoAssembly* ass);
gboolean mono_assembly_has_skip_verification (MonoAssembly* ass);
+MONO_API gint32
+mono_assembly_addref (MonoAssembly *assembly);
+gint32
+mono_assembly_decref (MonoAssembly *assembly);
+
void mono_assembly_release_gc_roots (MonoAssembly *assembly);
gboolean mono_assembly_close_except_image_pools (MonoAssembly *assembly);
void mono_assembly_close_finish (MonoAssembly *assembly);
@@ -1104,7 +1108,7 @@ MonoImage *mono_image_open_raw (MonoAssemblyLoadContext *alc, const char *fname,
MonoImage *mono_image_open_metadata_only (MonoAssemblyLoadContext *alc, const char *fname, MonoImageOpenStatus *status);
-MonoImage *mono_image_open_from_data_internal (MonoAssemblyLoadContext *alc, char *data, guint32 data_len, gboolean need_copy, MonoImageOpenStatus *status, gboolean refonly, gboolean metadata_only, const char *name);
+MonoImage *mono_image_open_from_data_internal (MonoAssemblyLoadContext *alc, char *data, guint32 data_len, gboolean need_copy, MonoImageOpenStatus *status, gboolean refonly, gboolean metadata_only, const char *name, const char *filename);
MonoException *mono_get_exception_field_access_msg (const char *msg);
diff --git a/mono/metadata/mono-private-unstable.h b/mono/metadata/mono-private-unstable.h
index c7d2531a7c74..002b8193ac75 100644
--- a/mono/metadata/mono-private-unstable.h
+++ b/mono/metadata/mono-private-unstable.h
@@ -19,6 +19,9 @@ typedef MonoGCHandle MonoAssemblyLoadContextGCHandle;
MONO_API MONO_RT_EXTERNAL_ONLY MonoAssembly *
mono_assembly_load_full_alc (MonoAssemblyLoadContextGCHandle alc_gchandle, MonoAssemblyName *aname, const char *basedir, MonoImageOpenStatus *status);
+MONO_API MONO_RT_EXTERNAL_ONLY MonoImage *
+mono_image_open_from_data_alc (MonoAssemblyLoadContextGCHandle alc_gchandle, char *data, uint32_t data_len, mono_bool need_copy, MonoImageOpenStatus *status, const char *name);
+
typedef MonoAssembly * (*MonoAssemblyPreLoadFuncV3) (MonoAssemblyLoadContextGCHandle alc_gchandle, MonoAssemblyName *aname, char **assemblies_path, void *user_data, MonoError *error);
MONO_API MONO_RT_EXTERNAL_ONLY void
diff --git a/mono/metadata/native-library.c b/mono/metadata/native-library.c
index ff2c6cc8d647..f53b8d01d78f 100644
--- a/mono/metadata/native-library.c
+++ b/mono/metadata/native-library.c
@@ -28,8 +28,10 @@ typedef enum
DLLIMPORTSEARCHPATH_SAFE_DIRECTORIES = 0x1000,
DLLIMPORTSEARCHPATH_ASSEMBLY_DIRECTORY = 0x2, // search the assembly directory first regardless of platform, not passed on to LoadLibraryEx
} DllImportSearchPath;
-//static const int DLLIMPORTSEARCHPATH_LOADLIBRARY_FLAG_MASK = DLLIMPORTSEARCHPATH_USE_DLL_DIRECTORY_FOR_DEPENDENCIES | DLLIMPORTSEARCHPATH_APPLICATION_DIRECTORY |
-// DLLIMPORTSEARCHPATH_USER_DIRECTORIES | DLLIMPORTSEARCHPATH_SYSTEM32 | DLLIMPORTSEARCHPATH_SAFE_DIRECTORIES;
+#ifdef HOST_WIN32
+static const int DLLIMPORTSEARCHPATH_LOADLIBRARY_FLAG_MASK = DLLIMPORTSEARCHPATH_USE_DLL_DIRECTORY_FOR_DEPENDENCIES | DLLIMPORTSEARCHPATH_APPLICATION_DIRECTORY |
+ DLLIMPORTSEARCHPATH_USER_DIRECTORIES | DLLIMPORTSEARCHPATH_SYSTEM32 | DLLIMPORTSEARCHPATH_SAFE_DIRECTORIES;
+#endif
// This lock may be taken within an ALC lock, and should never be the other way around.
static MonoCoopMutex native_library_module_lock;
@@ -490,18 +492,28 @@ netcore_check_blocklist (MonoDl *module)
return g_hash_table_contains (native_library_module_blocklist, module);
}
+static int
+convert_dllimport_flags (int flags)
+{
+#ifdef HOST_WIN32
+ return flags & DLLIMPORTSEARCHPATH_LOADLIBRARY_FLAG_MASK;
+#else
+ // DllImportSearchPath is Windows-only, other than DLLIMPORTSEARCHPATH_ASSEMBLY_DIRECTORY
+ return 0;
+#endif
+}
+
static MonoDl *
-netcore_probe_for_module_variations (const char *mdirname, const char *file_name)
+netcore_probe_for_module_variations (const char *mdirname, const char *file_name, int raw_flags)
{
void *iter = NULL;
char *full_name;
MonoDl *module = NULL;
- // This does not actually mirror CoreCLR's algorithm; if that becomes a problem, potentially use theirs
// FIXME: this appears to search *.dylib twice for some reason
while ((full_name = mono_dl_build_path (mdirname, file_name, &iter)) && module == NULL) {
char *error_msg;
- module = mono_dl_open (full_name, MONO_DL_LAZY, &error_msg);
+ module = mono_dl_open_full (full_name, MONO_DL_LAZY, raw_flags, &error_msg);
if (!module) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "DllImport error loading library '%s': '%s'.", full_name, error_msg);
g_free (error_msg);
@@ -517,19 +529,23 @@ static MonoDl *
netcore_probe_for_module (MonoImage *image, const char *file_name, int flags)
{
MonoDl *module = NULL;
+ int lflags = convert_dllimport_flags (flags);
+
+ // TODO: this algorithm doesn't quite match CoreCLR, so respecting DLLIMPORTSEARCHPATH_LEGACY_BEHAVIOR makes little sense
+ // If the difference becomes a problem, overhaul this algorithm to match theirs exactly
// Try without any path additions
- module = netcore_probe_for_module_variations (NULL, file_name);
+ module = netcore_probe_for_module_variations (NULL, file_name, lflags);
// Check the NATIVE_DLL_SEARCH_DIRECTORIES
for (int i = 0; i < pinvoke_search_directories_count && module == NULL; ++i)
- module = netcore_probe_for_module_variations (pinvoke_search_directories[i], file_name);
+ module = netcore_probe_for_module_variations (pinvoke_search_directories[i], file_name, lflags);
// Check the assembly directory if the search flag is set and the image exists
if (flags & DLLIMPORTSEARCHPATH_ASSEMBLY_DIRECTORY && image != NULL && module == NULL) {
char *mdirname = g_path_get_dirname (image->filename);
if (mdirname)
- module = netcore_probe_for_module_variations (mdirname, file_name);
+ module = netcore_probe_for_module_variations (mdirname, file_name, lflags);
g_free (mdirname);
}
@@ -772,6 +788,8 @@ netcore_lookup_native_library (MonoAssemblyLoadContext *alc, MonoImage *image, c
g_free (error_msg);
}
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Native library found via __Internal: '%s'.", scope);
+
return module;
}
@@ -796,16 +814,22 @@ netcore_lookup_native_library (MonoAssemblyLoadContext *alc, MonoImage *image, c
alc_pinvoke_lock (alc);
module = netcore_check_alc_cache (alc, scope);
alc_pinvoke_unlock (alc);
- if (module)
+ if (module) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Native library found in the active ALC cache: '%s'.", scope);
goto leave;
+ }
module = (MonoDl *)netcore_resolve_with_dll_import_resolver_nofail (alc, assembly, scope, flags);
- if (module)
+ if (module) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Native library found via DllImportResolver: '%s'.", scope);
goto add_to_alc_cache;
+ }
module = (MonoDl *)netcore_resolve_with_load_nofail (alc, scope);
- if (module)
+ if (module) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Native library found via LoadUnmanagedDll: '%s'.", scope);
goto add_to_alc_cache;
+ }
MONO_ENTER_GC_SAFE;
mono_global_loader_data_lock ();
@@ -814,18 +838,24 @@ netcore_lookup_native_library (MonoAssemblyLoadContext *alc, MonoImage *image, c
MONO_ENTER_GC_SAFE;
mono_global_loader_data_unlock ();
MONO_EXIT_GC_SAFE;
- if (module)
+ if (module) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Native library found in the global cache: '%s'.", scope);
goto add_to_alc_cache;
+ }
module = netcore_probe_for_module (image, scope, flags);
- if (module)
+ if (module) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Native library found via filesystem probing: '%s'.", scope);
goto add_to_global_cache;
+ }
/* As this is last chance, I've opted not to put it in a cache, but that is not necessarily the correct decision.
* It is rather convenient here, however, because it means the global cache will only be populated by libraries
* resolved via netcore_probe_for_module and not NativeLibrary, eliminating potential races/conflicts.
*/
module = netcore_resolve_with_resolving_event_nofail (alc, assembly, scope);
+ if (module)
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Native library found via the Resolving event: '%s'.", scope);
goto leave;
add_to_global_cache:
@@ -1293,6 +1323,13 @@ lookup_pinvoke_call_impl (MonoMethod *method, MonoLookupPInvokeStatus *status_ou
if (strcmp (new_scope, "QCall") == 0) {
piinfo->addr = mono_lookup_pinvoke_qcall_internal (method, status_out);
+ if (!piinfo->addr) {
+ mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_DLLIMPORT,
+ "Unable to find qcall for '%s'.",
+ new_import);
+ status_out->err_code = LOOKUP_PINVOKE_ERR_NO_SYM;
+ status_out->err_arg = g_strdup (new_import);
+ }
return piinfo->addr;
}
diff --git a/mono/metadata/object-internals.h b/mono/metadata/object-internals.h
index ff255bbbdc47..0175b9134d3b 100644
--- a/mono/metadata/object-internals.h
+++ b/mono/metadata/object-internals.h
@@ -1663,7 +1663,7 @@ typedef struct {
MonoEvent *resolving;
MonoEvent *unloading;
MonoString *name;
- gpointer *native_assembly_load_context;
+ MonoAssemblyLoadContext *native_assembly_load_context;
gint64 id;
gint32 internal_state;
MonoBoolean is_collectible;
diff --git a/mono/metadata/object.c b/mono/metadata/object.c
index 140c91e9de62..6925708cfcfc 100644
--- a/mono/metadata/object.c
+++ b/mono/metadata/object.c
@@ -5446,10 +5446,11 @@ mono_runtime_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **ex
* On failure sets @error and returns NULL.
*/
static gpointer
-invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, gboolean* has_byref_nullables, MonoError *error)
+invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, MonoObject **pa_obj, gboolean* has_byref_nullables, MonoError *error)
{
MonoType *t_orig = t;
gpointer result = NULL;
+ *pa_obj = NULL;
error_init (error);
again:
switch (t->type) {
@@ -5470,7 +5471,8 @@ invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, gboolean*
case MONO_TYPE_VALUETYPE:
if (t->type == MONO_TYPE_VALUETYPE && mono_class_is_nullable (mono_class_from_mono_type_internal (t_orig))) {
/* The runtime invoke wrapper needs the original boxed vtype, it does handle byref values as well. */
- result = mono_array_get_internal (params, MonoObject*, i);
+ *pa_obj = mono_array_get_internal (params, MonoObject*, i);
+ result = *pa_obj;
if (t->byref)
*has_byref_nullables = TRUE;
} else {
@@ -5496,8 +5498,8 @@ invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, gboolean*
return_val_if_nok (error, NULL);
mono_array_setref_internal (params, i, copy);
}
-
- result = mono_object_unbox_internal (mono_array_get_internal (params, MonoObject*, i));
+ *pa_obj = mono_array_get_internal (params, MonoObject*, i);
+ result = mono_object_unbox_internal (*pa_obj);
if (!t->byref && was_null)
mono_array_setref_internal (params, i, NULL);
}
@@ -5507,11 +5509,13 @@ invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, gboolean*
case MONO_TYPE_CLASS:
case MONO_TYPE_ARRAY:
case MONO_TYPE_SZARRAY:
- if (t->byref)
+ if (t->byref) {
result = mono_array_addr_internal (params, MonoObject*, i);
// FIXME: I need to check this code path
- else
- result = mono_array_get_internal (params, MonoObject*, i);
+ } else {
+ *pa_obj = mono_array_get_internal (params, MonoObject*, i);
+ result = *pa_obj;
+ }
break;
case MONO_TYPE_GENERICINST:
if (t->byref)
@@ -5680,12 +5684,13 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
MonoObject **exc, MonoError *error)
{
MONO_REQ_GC_UNSAFE_MODE;
+ HANDLE_FUNCTION_ENTER ();
error_init (error);
MonoMethodSignature *sig = mono_method_signature_internal (method);
gpointer *pa = NULL;
- MonoObject *res;
+ MonoObject *res = NULL;
int i;
gboolean has_byref_nullables = FALSE;
@@ -5693,8 +5698,11 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
pa = g_newa (gpointer, mono_array_length_internal (params));
for (i = 0; i < mono_array_length_internal (params); i++) {
MonoType *t = sig->params [i];
- pa [i] = invoke_array_extract_argument (params, i, t, &has_byref_nullables, error);
- return_val_if_nok (error, NULL);
+ MonoObject *pa_obj;
+ pa [i] = invoke_array_extract_argument (params, i, t, &pa_obj, &has_byref_nullables, error);
+ if (pa_obj)
+ MONO_HANDLE_PIN (pa_obj);
+ goto_if_nok (error, exit_null);
}
}
@@ -5705,16 +5713,18 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
/* Need to create a boxed vtype instead */
g_assert (!obj);
- if (!params)
- return NULL;
- else {
- return mono_value_box_checked (mono_domain_get (), m_class_get_cast_class (method->klass), pa [0], error);
+ if (!params) {
+ goto_if_nok (error, exit_null);
+ } else {
+ res = mono_value_box_checked (mono_domain_get (), m_class_get_cast_class (method->klass), pa [0], error);
+ goto exit;
}
}
if (!obj) {
- obj = mono_object_new_checked (mono_domain_get (), method->klass, error);
- return_val_if_nok (error, NULL);
+ MonoObjectHandle obj_h = mono_object_new_handle (mono_domain_get (), method->klass, error);
+ goto_if_nok (error, exit_null);
+ obj = MONO_HANDLE_RAW (obj_h);
g_assert (obj); /*maybe we should raise a TLE instead?*/
#ifndef DISABLE_REMOTING
if (mono_object_is_transparent_proxy (obj)) {
@@ -5727,8 +5737,9 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
else
o = obj;
} else if (m_class_is_valuetype (method->klass)) {
- obj = mono_value_box_checked (mono_domain_get (), method->klass, obj, error);
- return_val_if_nok (error, NULL);
+ MonoObjectHandle obj_h = mono_value_box_handle (mono_domain_get (), method->klass, obj, error);
+ goto_if_nok (error, exit_null);
+ obj = MONO_HANDLE_RAW (obj_h);
}
if (exc) {
@@ -5737,20 +5748,20 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
mono_runtime_invoke_checked (method, o, pa, error);
}
- return (MonoObject *)obj;
+ res = (MonoObject*)obj;
} else {
if (mono_class_is_nullable (method->klass)) {
if (method->flags & METHOD_ATTRIBUTE_STATIC) {
obj = NULL;
} else {
- MonoObject *nullable;
/* Convert the unboxed vtype into a Nullable structure */
- nullable = mono_object_new_checked (mono_domain_get (), method->klass, error);
- return_val_if_nok (error, NULL);
+ MonoObjectHandle nullable_h = mono_object_new_handle (mono_domain_get (), method->klass, error);
+ goto_if_nok (error, exit_null);
+ MonoObject* nullable = MONO_HANDLE_RAW (nullable_h);
- MonoObject *boxed = mono_value_box_checked (mono_domain_get (), m_class_get_cast_class (method->klass), obj, error);
- return_val_if_nok (error, NULL);
- mono_nullable_init ((guint8 *)mono_object_unbox_internal (nullable), boxed, method->klass);
+ MonoObjectHandle boxed_h = mono_value_box_handle (mono_domain_get (), m_class_get_cast_class (method->klass), obj, error);
+ goto_if_nok (error, exit_null);
+ mono_nullable_init ((guint8 *)mono_object_unbox_internal (nullable), MONO_HANDLE_RAW (boxed_h), method->klass);
obj = mono_object_unbox_internal (nullable);
}
}
@@ -5761,7 +5772,8 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
} else {
res = mono_runtime_invoke_checked (method, obj, pa, error);
}
- return_val_if_nok (error, NULL);
+ MONO_HANDLE_PIN (res);
+ goto_if_nok (error, exit_null);
if (sig->ret->type == MONO_TYPE_PTR) {
MonoClass *pointer_class;
@@ -5790,12 +5802,14 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
// byref is already unboxed by the invoke code
MonoType *tmpret = mono_metadata_type_dup (NULL, sig->ret);
tmpret->byref = FALSE;
- box_args [1] = mono_type_get_object_checked (mono_domain_get (), tmpret, error);
+ MonoReflectionTypeHandle type_h = mono_type_get_object_handle (mono_domain_get (), tmpret, error);
+ box_args [1] = MONO_HANDLE_RAW (type_h);
mono_metadata_free_type (tmpret);
} else {
- box_args [1] = mono_type_get_object_checked (mono_domain_get (), sig->ret, error);
+ MonoReflectionTypeHandle type_h = mono_type_get_object_handle (mono_domain_get (), sig->ret, error);
+ box_args [1] = MONO_HANDLE_RAW (type_h);
}
- return_val_if_nok (error, NULL);
+ goto_if_nok (error, exit_null);
res = mono_runtime_try_invoke (box_method, NULL, box_args, &box_exc, error);
g_assert (box_exc == NULL);
@@ -5815,9 +5829,12 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
mono_array_setref_internal (params, i, pa [i]);
}
}
-
- return res;
}
+ goto exit;
+exit_null:
+ res = NULL;
+exit:
+ HANDLE_FUNCTION_RETURN_VAL (res);
}
// FIXME these will move to header soon
diff --git a/mono/metadata/reflection.c b/mono/metadata/reflection.c
index c28ce829a499..49c907829eb7 100644
--- a/mono/metadata/reflection.c
+++ b/mono/metadata/reflection.c
@@ -570,7 +570,7 @@ mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *err
res->type = type;
mono_g_hash_table_insert_internal (domain->type_hash, type, res);
- if (type->type == MONO_TYPE_VOID)
+ if (type->type == MONO_TYPE_VOID && !type->byref)
domain->typeof_void = (MonoObject*)res;
mono_domain_unlock (domain);
@@ -3131,7 +3131,11 @@ mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, Mono
error_init (error);
if (method == NULL) {
+#ifdef ENABLE_NETCORE
+ method = mono_class_get_method_from_name_checked (mono_class_get_type_builder_class (), "IsAssignableToInternal", 1, 0, error);
+#else
method = mono_class_get_method_from_name_checked (mono_class_get_type_builder_class (), "IsAssignableTo", 1, 0, error);
+#endif
mono_error_assert_ok (error);
g_assert (method);
}
diff --git a/mono/metadata/sgen-client-mono.h b/mono/metadata/sgen-client-mono.h
index 0023ece4b045..211d9ed55498 100644
--- a/mono/metadata/sgen-client-mono.h
+++ b/mono/metadata/sgen-client-mono.h
@@ -722,6 +722,7 @@ gboolean sgen_is_critical_method (MonoMethod *method);
void sgen_set_use_managed_allocator (gboolean flag);
gboolean sgen_is_managed_allocator (MonoMethod *method);
gboolean sgen_has_managed_allocator (void);
+void sgen_disable_native_stack_scan (void);
void sgen_scan_for_registered_roots_in_domain (MonoDomain *domain, int root_type);
void sgen_null_links_for_domain (MonoDomain *domain);
diff --git a/mono/metadata/sgen-mono.c b/mono/metadata/sgen-mono.c
index ca00a3066b7a..2a434422c4f7 100644
--- a/mono/metadata/sgen-mono.c
+++ b/mono/metadata/sgen-mono.c
@@ -993,6 +993,7 @@ static MonoMethod* alloc_method_cache [ATYPE_NUM];
static MonoMethod* slowpath_alloc_method_cache [ATYPE_NUM];
static MonoMethod* profiler_alloc_method_cache [ATYPE_NUM];
static gboolean use_managed_allocator = TRUE;
+static gboolean debug_coop_no_stack_scan;
#ifdef MANAGED_ALLOCATION
/* FIXME: Do this in the JIT, where specialized allocation sequences can be created
@@ -1122,6 +1123,12 @@ sgen_set_use_managed_allocator (gboolean flag)
use_managed_allocator = flag;
}
+void
+sgen_disable_native_stack_scan (void)
+{
+ debug_coop_no_stack_scan = TRUE;
+}
+
MonoMethod*
mono_gc_get_managed_allocator_by_type (int atype, ManagedAllocatorVariant variant)
{
@@ -2361,30 +2368,32 @@ sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean p
aligned_stack_start = get_aligned_stack_start (info);
g_assert (info->client_info.suspend_done);
- SGEN_LOG (3, "Scanning thread %p, range: %p-%p, size: %" G_GSIZE_FORMAT "d, pinned=%" G_GSIZE_FORMAT "d", info, info->client_info.stack_start, info->client_info.info.stack_end, (char*)info->client_info.info.stack_end - (char*)info->client_info.stack_start, sgen_get_pinned_count ());
- if (mono_gc_get_gc_callbacks ()->thread_mark_func && !conservative_stack_mark) {
- mono_gc_get_gc_callbacks ()->thread_mark_func (info->client_info.runtime_data, (guint8 *)aligned_stack_start, (guint8 *)info->client_info.info.stack_end, precise, &ctx);
- } else if (!precise) {
- if (!conservative_stack_mark) {
- fprintf (stderr, "Precise stack mark not supported - disabling.\n");
- conservative_stack_mark = TRUE;
+ if (!debug_coop_no_stack_scan) {
+ SGEN_LOG (3, "Scanning thread %p, range: %p-%p, size: %" G_GSIZE_FORMAT "d, pinned=%" G_GSIZE_FORMAT "d", info, info->client_info.stack_start, info->client_info.info.stack_end, (char*)info->client_info.info.stack_end - (char*)info->client_info.stack_start, sgen_get_pinned_count ());
+ if (mono_gc_get_gc_callbacks ()->thread_mark_func && !conservative_stack_mark) {
+ mono_gc_get_gc_callbacks ()->thread_mark_func (info->client_info.runtime_data, (guint8 *)aligned_stack_start, (guint8 *)info->client_info.info.stack_end, precise, &ctx);
+ } else if (!precise) {
+ if (!conservative_stack_mark) {
+ fprintf (stderr, "Precise stack mark not supported - disabling.\n");
+ conservative_stack_mark = TRUE;
+ }
+ //FIXME we should eventually use the new stack_mark from coop
+ sgen_conservatively_pin_objects_from ((void **)aligned_stack_start, (void **)info->client_info.info.stack_end, start_nursery, end_nursery, PIN_TYPE_STACK);
}
- //FIXME we should eventually use the new stack_mark from coop
- sgen_conservatively_pin_objects_from ((void **)aligned_stack_start, (void **)info->client_info.info.stack_end, start_nursery, end_nursery, PIN_TYPE_STACK);
- }
- if (!precise) {
- sgen_conservatively_pin_objects_from ((void**)&info->client_info.ctx, (void**)(&info->client_info.ctx + 1),
- start_nursery, end_nursery, PIN_TYPE_STACK);
-
- {
- // This is used on Coop GC for platforms where we cannot get the data for individual registers.
- // We force a spill of all registers into the stack and pass a chunk of data into sgen.
- //FIXME under coop, for now, what we need to ensure is that we scan any extra memory from info->client_info.info.stack_end to stack_mark
- MonoThreadUnwindState *state = &info->client_info.info.thread_saved_state [SELF_SUSPEND_STATE_INDEX];
- if (state && state->gc_stackdata) {
- sgen_conservatively_pin_objects_from ((void **)state->gc_stackdata, (void**)((char*)state->gc_stackdata + state->gc_stackdata_size),
- start_nursery, end_nursery, PIN_TYPE_STACK);
+ if (!precise) {
+ sgen_conservatively_pin_objects_from ((void**)&info->client_info.ctx, (void**)(&info->client_info.ctx + 1),
+ start_nursery, end_nursery, PIN_TYPE_STACK);
+
+ {
+ // This is used on Coop GC for platforms where we cannot get the data for individual registers.
+ // We force a spill of all registers into the stack and pass a chunk of data into sgen.
+ //FIXME under coop, for now, what we need to ensure is that we scan any extra memory from info->client_info.info.stack_end to stack_mark
+ MonoThreadUnwindState *state = &info->client_info.info.thread_saved_state [SELF_SUSPEND_STATE_INDEX];
+ if (state && state->gc_stackdata) {
+ sgen_conservatively_pin_objects_from ((void **)state->gc_stackdata, (void**)((char*)state->gc_stackdata + state->gc_stackdata_size),
+ start_nursery, end_nursery, PIN_TYPE_STACK);
+ }
}
}
}
diff --git a/mono/metadata/sre-save.c b/mono/metadata/sre-save.c
index f2371b511b65..e61514de08e7 100644
--- a/mono/metadata/sre-save.c
+++ b/mono/metadata/sre-save.c
@@ -630,17 +630,22 @@ static gboolean
mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
{
MONO_REQ_GC_UNSAFE_MODE;
+ /* We need to clear handles for rmb fields created in mono_reflection_methodbuilder_from_method_builder */
+ HANDLE_FUNCTION_ENTER ();
MonoDynamicTable *table;
guint32 *values;
ReflectionMethodBuilder rmb;
int i;
+ gboolean ret = TRUE;
error_init (error);
if (!mono_reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
- !mono_image_basic_method (&rmb, assembly, error))
- return FALSE;
+ !mono_image_basic_method (&rmb, assembly, error)) {
+ ret = FALSE;
+ goto exit;
+ }
mb->table_idx = *rmb.table_idx;
@@ -685,26 +690,33 @@ mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *a
(MonoReflectionGenericParam *)mono_array_get_internal (mb->generic_params, gpointer, i), owner, assembly);
}
}
-
- return TRUE;
+exit:
+ HANDLE_FUNCTION_RETURN_VAL (ret);
}
static gboolean
mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
{
+ /* We need to clear handles for rmb fields created in mono_reflection_methodbuilder_from_ctor_builder */
+ HANDLE_FUNCTION_ENTER ();
MONO_REQ_GC_UNSAFE_MODE;
+ gboolean ret = TRUE;
ReflectionMethodBuilder rmb;
- if (!mono_reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
- return FALSE;
+ if (!mono_reflection_methodbuilder_from_ctor_builder (&rmb, mb, error)) {
+ ret = FALSE;
+ goto exit;
+ }
- if (!mono_image_basic_method (&rmb, assembly, error))
- return FALSE;
+ if (!mono_image_basic_method (&rmb, assembly, error)) {
+ ret = FALSE;
+ goto exit;
+ }
mb->table_idx = *rmb.table_idx;
-
- return TRUE;
+exit:
+ HANDLE_FUNCTION_RETURN_VAL (ret);
}
#endif
diff --git a/mono/metadata/sre.c b/mono/metadata/sre.c
index 6881617fedc5..d2ee825173f6 100644
--- a/mono/metadata/sre.c
+++ b/mono/metadata/sre.c
@@ -480,27 +480,39 @@ mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
memset (rmb, 0, sizeof (ReflectionMethodBuilder));
rmb->ilgen = mb->ilgen;
+ MONO_HANDLE_PIN (rmb->ilgen);
rmb->rtype = (MonoReflectionType*)mb->rtype;
- return_val_if_nok (error, FALSE);
+ MONO_HANDLE_PIN (rmb->rtype);
rmb->parameters = mb->parameters;
+ MONO_HANDLE_PIN (rmb->parameters);
rmb->generic_params = mb->generic_params;
+ MONO_HANDLE_PIN (rmb->generic_params);
rmb->generic_container = mb->generic_container;
rmb->opt_types = NULL;
rmb->pinfo = mb->pinfo;
+ MONO_HANDLE_PIN (rmb->pinfo);
rmb->attrs = mb->attrs;
rmb->iattrs = mb->iattrs;
rmb->call_conv = mb->call_conv;
rmb->code = mb->code;
+ MONO_HANDLE_PIN (rmb->code);
rmb->type = mb->type;
+ MONO_HANDLE_PIN (rmb->type);
rmb->name = mb->name;
+ MONO_HANDLE_PIN (rmb->name);
rmb->table_idx = &mb->table_idx;
rmb->init_locals = mb->init_locals;
rmb->skip_visibility = FALSE;
rmb->return_modreq = mb->return_modreq;
+ MONO_HANDLE_PIN (rmb->return_modreq);
rmb->return_modopt = mb->return_modopt;
+ MONO_HANDLE_PIN (rmb->return_modopt);
rmb->param_modreq = mb->param_modreq;
+ MONO_HANDLE_PIN (rmb->param_modreq);
rmb->param_modopt = mb->param_modopt;
+ MONO_HANDLE_PIN (rmb->param_modopt);
rmb->permissions = mb->permissions;
+ MONO_HANDLE_PIN (rmb->permissions);
rmb->mhandle = mb->mhandle;
rmb->nrefs = 0;
rmb->refs = NULL;
@@ -510,7 +522,9 @@ mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
rmb->extra_flags = mb->extra_flags;
rmb->native_cc = mb->native_cc;
rmb->dllentry = mb->dllentry;
+ MONO_HANDLE_PIN (rmb->dllentry);
rmb->dll = mb->dll;
+ MONO_HANDLE_PIN (rmb->dll);
}
return TRUE;
@@ -528,28 +542,37 @@ mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, M
memset (rmb, 0, sizeof (ReflectionMethodBuilder));
rmb->ilgen = mb->ilgen;
+ MONO_HANDLE_PIN (rmb->ilgen);
rmb->rtype = mono_type_get_object_checked (mono_domain_get (), mono_get_void_type (), error);
return_val_if_nok (error, FALSE);
+ MONO_HANDLE_PIN (rmb->rtype);
rmb->parameters = mb->parameters;
+ MONO_HANDLE_PIN (rmb->parameters);
rmb->generic_params = NULL;
rmb->generic_container = NULL;
rmb->opt_types = NULL;
rmb->pinfo = mb->pinfo;
+ MONO_HANDLE_PIN (rmb->pinfo);
rmb->attrs = mb->attrs;
rmb->iattrs = mb->iattrs;
rmb->call_conv = mb->call_conv;
rmb->code = NULL;
rmb->type = mb->type;
+ MONO_HANDLE_PIN (rmb->type);
rmb->name = mono_string_new_checked (mono_domain_get (), name, error);
return_val_if_nok (error, FALSE);
+ MONO_HANDLE_PIN (rmb->name);
rmb->table_idx = &mb->table_idx;
rmb->init_locals = mb->init_locals;
rmb->skip_visibility = FALSE;
rmb->return_modreq = NULL;
rmb->return_modopt = NULL;
rmb->param_modreq = mb->param_modreq;
+ MONO_HANDLE_PIN (rmb->param_modreq);
rmb->param_modopt = mb->param_modopt;
+ MONO_HANDLE_PIN (rmb->param_modopt);
rmb->permissions = mb->permissions;
+ MONO_HANDLE_PIN (rmb->permissions);
rmb->mhandle = mb->mhandle;
rmb->nrefs = 0;
rmb->refs = NULL;
@@ -565,8 +588,11 @@ reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, Mono
memset (rmb, 0, sizeof (ReflectionMethodBuilder));
rmb->ilgen = mb->ilgen;
+ MONO_HANDLE_PIN (rmb->ilgen);
rmb->rtype = mb->rtype;
+ MONO_HANDLE_PIN (rmb->type);
rmb->parameters = mb->parameters;
+ MONO_HANDLE_PIN (rmb->parameters);
rmb->generic_params = NULL;
rmb->generic_container = NULL;
rmb->opt_types = NULL;
@@ -576,7 +602,9 @@ reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, Mono
rmb->call_conv = mb->call_conv;
rmb->code = NULL;
rmb->type = (MonoObject *) mb->owner;
+ MONO_HANDLE_PIN (rmb->type);
rmb->name = mb->name;
+ MONO_HANDLE_PIN (rmb->name);
rmb->table_idx = NULL;
rmb->init_locals = mb->init_locals;
rmb->skip_visibility = mb->skip_visibility;
@@ -3262,23 +3290,26 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
static MonoMethod*
ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
{
+ /* We need to clear handles for rmb fields created in mono_reflection_methodbuilder_from_ctor_builder */
+ HANDLE_FUNCTION_ENTER ();
ReflectionMethodBuilder rmb;
MonoMethodSignature *sig;
+ MonoMethod *ret;
mono_loader_lock ();
if (!mono_reflection_methodbuilder_from_ctor_builder (&rmb, mb, error)) {
mono_loader_unlock ();
- return NULL;
+ goto exit_null;
}
g_assert (klass->image != NULL);
sig = ctor_builder_to_signature_raw (klass->image, mb, error); /* FIXME use handles */
mono_loader_unlock ();
- return_val_if_nok (error, NULL);
+ goto_if_nok (error, exit_null);
mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
- return_val_if_nok (error, NULL);
+ goto_if_nok (error, exit_null);
mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
@@ -3286,14 +3317,22 @@ ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, Mon
mb->ilgen = NULL;
}
- return mb->mhandle;
+ ret = mb->mhandle;
+ goto exit;
+exit_null:
+ ret = NULL;
+exit:
+ HANDLE_FUNCTION_RETURN_VAL (ret);
}
static MonoMethod*
methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilderHandle ref_mb, MonoError *error)
{
+ /* We need to clear handles for rmb fields created in mono_reflection_methodbuilder_from_method_builder */
+ HANDLE_FUNCTION_ENTER ();
ReflectionMethodBuilder rmb;
MonoMethodSignature *sig;
+ MonoMethod *ret, *method;
error_init (error);
@@ -3302,23 +3341,28 @@ methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilderHandl
MonoReflectionMethodBuilder *mb = MONO_HANDLE_RAW (ref_mb); /* FIXME use handles */
if (!mono_reflection_methodbuilder_from_method_builder (&rmb, mb, error)) {
mono_loader_unlock ();
- return NULL;
+ goto exit_null;
}
g_assert (klass->image != NULL);
sig = method_builder_to_signature (klass->image, ref_mb, error);
mono_loader_unlock ();
- return_val_if_nok (error, NULL);
+ goto_if_nok (error, exit_null);
- MonoMethod *method = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
- return_val_if_nok (error, NULL);
+ method = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
+ goto_if_nok (error, exit_null);
MONO_HANDLE_SETVAL (ref_mb, mhandle, MonoMethod*, method);
mono_save_custom_attrs (klass->image, method, mb->cattrs);
if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save)
/* ilgen is no longer needed */
mb->ilgen = NULL;
- return method;
+ ret = method;
+ goto exit;
+exit_null:
+ ret = NULL;
+exit:
+ HANDLE_FUNCTION_RETURN_VAL (ret);
}
static MonoMethod*
@@ -3668,9 +3712,11 @@ typebuilder_setup_one_field (MonoDynamicImage *dynamic_image, MonoClass *klass,
if (klass->enumtype && strcmp (field->name, "value__") == 0) // used by enum classes to store the instance value
field->type->attrs |= FIELD_ATTRIBUTE_RT_SPECIAL_NAME;
- if (!klass->enumtype && !mono_type_get_underlying_type (field->type)) {
- mono_class_set_type_load_failure (klass, "Field '%s' is an enum type with a bad underlying type", field->name);
- goto leave;
+ if (!mono_type_get_underlying_type (field->type)) {
+ if (!(klass->enumtype && mono_metadata_type_equal (field->type, m_class_get_byval_arg (klass)))) {
+ mono_class_set_type_load_failure (klass, "Field '%s' is an enum type with a bad underlying type", field->name);
+ goto leave;
+ }
}
if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
@@ -4105,6 +4151,8 @@ free_dynamic_method (void *dynamic_method)
static gboolean
reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, MonoError *error)
{
+ /* We need to clear handles for rmb fields created in reflection_methodbuilder_from_dynamic_method */
+ HANDLE_FUNCTION_ENTER ();
MonoReferenceQueue *queue;
MonoMethod *handle;
DynamicMethodReleaseData *release_data;
@@ -4114,6 +4162,9 @@ reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, Mono
MonoDomain *domain;
GSList *l;
int i;
+ gboolean ret = TRUE;
+ MonoReflectionDynamicMethod *mb;
+ MonoAssembly *ass = NULL;
error_init (error);
@@ -4125,9 +4176,9 @@ reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, Mono
}
sig = dynamic_method_to_signature (ref_mb, error);
- return_val_if_nok (error, FALSE);
+ goto_if_nok (error, exit_false);
- MonoReflectionDynamicMethod *mb = MONO_HANDLE_RAW (ref_mb); /* FIXME convert reflection_create_dynamic_method to use handles */
+ mb = MONO_HANDLE_RAW (ref_mb); /* FIXME convert reflection_create_dynamic_method to use handles */
reflection_methodbuilder_from_dynamic_method (&rmb, mb);
/*
@@ -4143,6 +4194,7 @@ reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, Mono
MonoClass *handle_class;
gpointer ref;
MonoObject *obj = mono_array_get_internal (mb->refs, MonoObject*, i);
+ MONO_HANDLE_PIN (obj);
if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
@@ -4155,19 +4207,18 @@ reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, Mono
if (method->mhandle) {
ref = method->mhandle;
} else {
- /* FIXME: GC object stored in unmanaged memory */
ref = method;
- /* FIXME: GC object stored in unmanaged memory */
method->referenced_by = g_slist_append (method->referenced_by, mb);
}
handle_class = mono_defaults.methodhandle_class;
} else {
MonoException *ex = NULL;
ref = mono_reflection_resolve_object (mb->module->image, obj, &handle_class, NULL, error);
+ /* ref should not be a reference. Otherwise we would need a handle for it */
if (!is_ok (error)) {
g_free (rmb.refs);
- return FALSE;
+ goto exit_false;
}
if (!ref)
ex = mono_get_exception_type_load (NULL, NULL);
@@ -4177,20 +4228,19 @@ reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, Mono
if (ex) {
g_free (rmb.refs);
mono_error_set_exception_instance (error, ex);
- return FALSE;
+ goto exit_false;
}
}
- rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
+ rmb.refs [i] = ref;
rmb.refs [i + 1] = handle_class;
}
- MonoAssembly *ass = NULL;
if (mb->owner) {
MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
if (!is_ok (error)) {
g_free (rmb.refs);
- return FALSE;
+ goto exit_false;
}
klass = mono_class_from_mono_type_internal (owner_type);
ass = klass->image->assembly;
@@ -4202,7 +4252,7 @@ reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, Mono
mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
((MonoDynamicMethod*)handle)->assembly = ass;
g_free (rmb.refs);
- return_val_if_nok (error, FALSE);
+ goto_if_nok (error, exit_false);
release_data = g_new (DynamicMethodReleaseData, 1);
release_data->handle = handle;
@@ -4233,7 +4283,11 @@ reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, Mono
g_hash_table_insert (domain->method_to_dyn_method, handle, mono_gchandle_new_weakref_internal ((MonoObject *)mb, TRUE));
mono_domain_unlock (domain);
- return TRUE;
+ goto exit;
+exit_false:
+ ret = FALSE;
+exit:
+ HANDLE_FUNCTION_RETURN_VAL (ret);
}
void
diff --git a/mono/metadata/w32file.c b/mono/metadata/w32file.c
index 67cc6412c447..bee7f7174009 100644
--- a/mono/metadata/w32file.c
+++ b/mono/metadata/w32file.c
@@ -913,4 +913,8 @@ mono_filesize_from_fd (int fd)
return (gint64)buf.st_size;
}
+#else
+
+MONO_EMPTY_SOURCE_FILE (w32file);
+
#endif
diff --git a/mono/metadata/w32process-unix-bsd.c b/mono/metadata/w32process-unix-bsd.c
index d09bc9f506ed..e368c19bd8bd 100644
--- a/mono/metadata/w32process-unix-bsd.c
+++ b/mono/metadata/w32process-unix-bsd.c
@@ -175,6 +175,11 @@ mono_w32process_get_modules (pid_t pid)
return g_slist_reverse (ret);
}
+void
+mono_w32process_platform_init_once (void)
+{
+}
+
#else
MONO_EMPTY_SOURCE_FILE (w32process_unix_bsd);
diff --git a/mono/metadata/w32process-unix-default.c b/mono/metadata/w32process-unix-default.c
index e2fda17fb5a0..eb73b89b75da 100644
--- a/mono/metadata/w32process-unix-default.c
+++ b/mono/metadata/w32process-unix-default.c
@@ -360,4 +360,13 @@ mono_w32process_get_modules (pid_t pid)
#endif
}
+void
+mono_w32process_platform_init_once (void)
+{
+}
+
+#else
+
+MONO_EMPTY_SOURCE_FILE (w32process_unix_default);
+
#endif
diff --git a/mono/metadata/w32process-unix-haiku.c b/mono/metadata/w32process-unix-haiku.c
index 0b3c82436c7f..dbd312c8d864 100644
--- a/mono/metadata/w32process-unix-haiku.c
+++ b/mono/metadata/w32process-unix-haiku.c
@@ -57,6 +57,11 @@ mono_w32process_get_modules (pid_t pid)
return g_slist_reverse (ret);
}
+void
+mono_w32process_platform_init_once (void)
+{
+}
+
#else
MONO_EMPTY_SOURCE_FILE (w32process_unix_haiku);
diff --git a/mono/metadata/w32process-unix-internals.h b/mono/metadata/w32process-unix-internals.h
index 7ba5f7e002e1..056177dd22a9 100644
--- a/mono/metadata/w32process-unix-internals.h
+++ b/mono/metadata/w32process-unix-internals.h
@@ -40,6 +40,9 @@ mono_w32process_get_name (pid_t pid);
GSList*
mono_w32process_get_modules (pid_t pid);
+void
+mono_w32process_platform_init_once (void);
+
static void G_GNUC_UNUSED
mono_w32process_module_free (MonoW32ProcessModule *module)
{
diff --git a/mono/metadata/w32process-unix-osx.c b/mono/metadata/w32process-unix-osx.c
index c687f6a70a11..2568a44223e3 100644
--- a/mono/metadata/w32process-unix-osx.c
+++ b/mono/metadata/w32process-unix-osx.c
@@ -15,6 +15,7 @@
#include
#include
#include
+#include
/* sys/resource.h (for rusage) is required when using osx 10.3 (but not 10.4) */
#ifdef __APPLE__
@@ -117,58 +118,128 @@ mono_w32process_get_path (pid_t pid)
#endif
}
-GSList*
+struct mono_dyld_image_info
+{
+ const void *header_addr;
+ const void *data_section_start;
+ const void *data_section_end;
+ const char *name;
+ guint64 order;
+};
+
+static guint64 dyld_order = 0;
+static GHashTable *images;
+static mono_mutex_t images_mutex;
+
+static int
+sort_modules_by_load_order (gconstpointer a, gconstpointer b)
+{
+ MonoW32ProcessModule *ma = (MonoW32ProcessModule *) a;
+ MonoW32ProcessModule *mb = (MonoW32ProcessModule *) b;
+ return ma->inode == mb->inode ? 0 : ma->inode < mb->inode ? -1 : 1;
+}
+
+GSList *
mono_w32process_get_modules (pid_t pid)
{
GSList *ret = NULL;
- MonoW32ProcessModule *mod;
- guint32 count;
- int i = 0;
-
+ MONO_ENTER_GC_SAFE;
if (pid != getpid ())
- return NULL;
+ goto done;
- count = _dyld_image_count ();
- for (i = 0; i < count; i++) {
-#if SIZEOF_VOID_P == 8
- const struct mach_header_64 *hdr;
- const struct section_64 *sec;
-#else
- const struct mach_header *hdr;
- const struct section *sec;
-#endif
- const char *name;
-
- name = _dyld_get_image_name (i);
-#if SIZEOF_VOID_P == 8
- hdr = (const struct mach_header_64*)_dyld_get_image_header (i);
- sec = getsectbynamefromheader_64 (hdr, SEG_DATA, SECT_DATA);
-#else
- hdr = _dyld_get_image_header (i);
- sec = getsectbynamefromheader (hdr, SEG_DATA, SECT_DATA);
-#endif
+ GHashTableIter it;
+ g_hash_table_iter_init (&it, images);
- /* Some dynlibs do not have data sections on osx (#533893) */
- if (sec == 0)
- continue;
+ gpointer val;
- mod = g_new0 (MonoW32ProcessModule, 1);
- mod->address_start = GINT_TO_POINTER (sec->addr);
- mod->address_end = GINT_TO_POINTER (sec->addr+sec->size);
+ mono_os_mutex_lock (&images_mutex);
+ while (g_hash_table_iter_next (&it, NULL, &val)) {
+ struct mono_dyld_image_info *info = (struct mono_dyld_image_info *) val;
+ MonoW32ProcessModule *mod = g_new0 (MonoW32ProcessModule, 1);
+ mod->address_start = GINT_TO_POINTER (info->data_section_start);
+ mod->address_end = GINT_TO_POINTER (info->data_section_end);
mod->perms = g_strdup ("r--p");
mod->address_offset = 0;
- mod->device = makedev (0, 0);
- mod->inode = i;
- mod->filename = g_strdup (name);
-
- if (g_slist_find_custom (ret, mod, mono_w32process_module_equals) == NULL) {
- ret = g_slist_prepend (ret, mod);
- } else {
- mono_w32process_module_free (mod);
- }
+ mod->device = 0;
+ mod->inode = info->order;
+ mod->filename = g_strdup (info->name);
+ ret = g_slist_prepend (ret, mod);
}
+ mono_os_mutex_unlock (&images_mutex);
+ ret = g_slist_sort (ret, &sort_modules_by_load_order);
+done:
+ MONO_EXIT_GC_SAFE;
+ return ret;
+}
+
+static void
+mono_dyld_image_info_free (void *info)
+{
+ struct mono_dyld_image_info *dinfo = (struct mono_dyld_image_info *) info;
+ g_free ((void *) dinfo->name);
+ g_free (dinfo);
+}
+
+static void
+image_added (const struct mach_header *hdr32, intptr_t vmaddr_slide)
+{
+ #if SIZEOF_VOID_P == 8
+ const struct mach_header_64 *hdr64 = (const struct mach_header_64 *)hdr32;
+ const struct section_64 *sec = getsectbynamefromheader_64 (hdr64, SEG_DATA, SECT_DATA);
+ #else
+ const struct section *sec = getsectbynamefromheader (hdr32, SEG_DATA, SECT_DATA);
+ #endif
+ Dl_info dlinfo;
+ if (!dladdr (hdr32, &dlinfo)) return;
+ if (sec == NULL) return;
+
+ mono_os_mutex_lock (&images_mutex);
+ gpointer found = g_hash_table_lookup (images, (gpointer) hdr32);
+ mono_os_mutex_unlock (&images_mutex);
+
+ if (found == NULL) {
+ struct mono_dyld_image_info *info = g_new0 (struct mono_dyld_image_info, 1);
+ info->header_addr = hdr32;
+ info->data_section_start = GINT_TO_POINTER (sec->addr);
+ info->data_section_end = GINT_TO_POINTER (sec->addr + sec->size);
+ info->name = g_strdup (dlinfo.dli_fname);
+ info->order = dyld_order;
+ ++dyld_order;
+
+ mono_os_mutex_lock (&images_mutex);
+ g_hash_table_insert (images, (gpointer) hdr32, info);
+ mono_os_mutex_unlock (&images_mutex);
+ }
+}
+
+static void
+image_removed (const struct mach_header *hdr32, intptr_t vmaddr_slide)
+{
+ mono_os_mutex_lock (&images_mutex);
+ g_hash_table_remove (images, hdr32);
+ mono_os_mutex_unlock (&images_mutex);
+}
- return g_slist_reverse (ret);
+void
+mono_w32process_platform_init_once (void)
+{
+ mono_os_mutex_init (&images_mutex);
+ images = g_hash_table_new_full (NULL, NULL, NULL, &mono_dyld_image_info_free);
+
+ /* Ensure that the functions used within the lock-protected region in
+ * mono_w32process_get_modules have been loaded, in case these symbols
+ * are lazily bound. g_new0 and g_strdup will be called by
+ * _dyld_register_func_for_add_image when it calls image_added with the
+ * current list of all loaded dynamic libraries
+ */
+ GSList *dummy = g_slist_prepend (NULL, NULL);
+ g_slist_free (dummy);
+ GHashTableIter it;
+ g_hash_table_iter_init (&it, images);
+ g_hash_table_iter_next (&it, NULL, NULL);
+
+ _dyld_register_func_for_add_image (&image_added);
+ _dyld_register_func_for_remove_image (&image_removed);
}
#else
diff --git a/mono/metadata/w32process-unix.c b/mono/metadata/w32process-unix.c
index 5ce501fd5a81..c1ccbca77c95 100644
--- a/mono/metadata/w32process-unix.c
+++ b/mono/metadata/w32process-unix.c
@@ -85,6 +85,7 @@
#include
#include
#include
+#include
#include
#include
#include "object-internals.h"
@@ -594,6 +595,8 @@ process_set_name (MonoW32HandleProcess *process_handle)
}
}
+static mono_once_t init_state = MONO_ONCE_INIT;
+
void
mono_w32process_init (void)
{
@@ -615,6 +618,7 @@ mono_w32process_init (void)
g_assert (current_process != INVALID_HANDLE_VALUE);
mono_coop_mutex_init (&processes_mutex);
+ mono_once (&init_state, &mono_w32process_platform_init_once);
}
void
diff --git a/mono/metadata/w32socket-internals.h b/mono/metadata/w32socket-internals.h
index 6cdb94063b17..0fe5209c321d 100644
--- a/mono/metadata/w32socket-internals.h
+++ b/mono/metadata/w32socket-internals.h
@@ -64,7 +64,7 @@ SOCKET
mono_w32socket_accept (SOCKET s, struct sockaddr *addr, socklen_t *addrlen, gboolean blocking);
int
-mono_w32socket_connect (SOCKET s, const struct sockaddr *name, int namelen, gboolean blocking);
+mono_w32socket_connect (SOCKET s, const struct sockaddr *name, socklen_t namelen, gboolean blocking);
int
mono_w32socket_recv (SOCKET s, char *buf, int len, int flags, gboolean blocking);
diff --git a/mono/metadata/w32socket-unix.c b/mono/metadata/w32socket-unix.c
index ac3bd0f85ff2..f5803a42a40b 100644
--- a/mono/metadata/w32socket-unix.c
+++ b/mono/metadata/w32socket-unix.c
@@ -191,7 +191,7 @@ mono_w32socket_accept (SOCKET sock, struct sockaddr *addr, socklen_t *addrlen, g
}
int
-mono_w32socket_connect (SOCKET sock, const struct sockaddr *addr, int addrlen, gboolean blocking)
+mono_w32socket_connect (SOCKET sock, const struct sockaddr *addr, socklen_t addrlen, gboolean blocking)
{
SocketHandle *sockethandle;
gint ret;
diff --git a/mono/mini/CMakeLists.txt b/mono/mini/CMakeLists.txt
index d98715012547..3d63d99b790f 100644
--- a/mono/mini/CMakeLists.txt
+++ b/mono/mini/CMakeLists.txt
@@ -1,15 +1,17 @@
-project (mini)
+project(mini)
-function (addprefix var prefix list)
- foreach (i ${list})
- set (f ${f} ${prefix}/${i})
- endforeach ()
- set (${var} ${f} PARENT_SCOPE)
+function(addprefix var prefix list)
+ foreach(i ${list})
+ set(f ${f} ${prefix}/${i})
+ endforeach()
+ set(${var} ${f} PARENT_SCOPE)
endfunction()
include_directories(
${PROJECT_BINARY_DIR}/
${PROJECT_BINARY_DIR}/../..
+ ${PROJECT_BINARY_DIR}/../../mono/eglib
+ ${CMAKE_SOURCE_DIR}/
${PROJECT_SOURCE_DIR}/../
${PROJECT_SOURCE_DIR}/../eglib
${PROJECT_SOURCE_DIR}/../sgen)
@@ -18,672 +20,840 @@ include_directories(
# EGLIB/
#
-set (eglib_win32_sources
- eglib-config.hw
- gdate-win32.c gdir-win32.c gfile-win32.c gmisc-win32.c
- gmodule-win32.c gmodule-win32-internals.h gtimer-win32.c gunicode-win32.c)
+set(eglib_win32_sources
+ eglib-config.hw
+ gdate-win32.c gdir-win32.c gfile-win32.c gmisc-win32.c
+ gmodule-win32.c gmodule-win32-internals.h gtimer-win32.c gunicode-win32.c)
-set (eglib_unix_sources
- gdate-unix.c gdir-unix.c gfile-unix.c gmisc-unix.c
- gmodule-unix.c gtimer-unix.c)
+set(eglib_unix_sources
+ gdate-unix.c gdir-unix.c gfile-unix.c gmisc-unix.c
+ gmodule-unix.c gtimer-unix.c)
-if (HOST_WIN32)
-set (eglib_platform_sources ${eglib_win32_sources})
+if(HOST_WIN32)
+set(eglib_platform_sources ${eglib_win32_sources})
else()
-set (eglib_platform_sources ${eglib_unix_sources})
+set(eglib_platform_sources ${eglib_unix_sources})
endif()
-set (eglib_common_sources
- eglib-remap.h
- sort.frag.h
- glib.h
- garray.c
- gbytearray.c
- gerror.c
- ghashtable.c
- giconv.c
- gmem.c
- gmodule.h
- goutput.c
- gqsort.c
- gstr.c
- gslist.c
- gstring.c
- gptrarray.c
- glist.c
- gqueue.c
- gpath.c
- gshell.c
- gspawn.c
- gfile.c
- gfile-posix.c
- gpattern.c
- gmarkup.c
- gutf8.c
- gunicode.c
- unicode-data.h)
-
-addprefix (eglib_sources ../eglib/ "${eglib_platform_sources};${eglib_common_sources}")
+set(eglib_common_sources
+ eglib-remap.h
+ sort.frag.h
+ glib.h
+ garray.c
+ gbytearray.c
+ gerror.c
+ ghashtable.c
+ giconv.c
+ gmem.c
+ gmodule.h
+ goutput.c
+ gqsort.c
+ gstr.c
+ gslist.c
+ gstring.c
+ gptrarray.c
+ glist.c
+ gqueue.c
+ gpath.c
+ gshell.c
+ gspawn.c
+ gfile.c
+ gfile-posix.c
+ gpattern.c
+ gmarkup.c
+ gutf8.c
+ gunicode.c
+ unicode-data.h)
+
+addprefix(eglib_sources ../eglib/ "${eglib_platform_sources};${eglib_common_sources}")
#
# UTILS/
#
-set (utils_win32_sources
- os-event-win32.c
- mono-os-wait-win32.c)
+set(utils_win32_sources
+ os-event-win32.c
+ mono-os-wait-win32.c)
-set (utils_unix_sources
- os-event-unix.c)
+set(utils_unix_sources
+ os-event-unix.c)
-if (HOST_WIN32)
-set (utils_platform_sources ${utils_win32_sources})
+if(HOST_WIN32)
+set(utils_platform_sources ${utils_win32_sources})
else()
-set (utils_platform_sources ${utils_unix_sources})
+set(utils_platform_sources ${utils_unix_sources})
endif()
-set (utils_common_sources
- mono-md5.c
- mono-sha1.c
- mono-logger.c
- mono-logger-internals.h
- mono-codeman.c
- dlmalloc.h
- dlmalloc.c
- mono-counters.c
- mono-compiler.h
- mono-complex.h
- mono-dl.c
- mono-dl-windows.c
- mono-dl-darwin.c
- mono-dl-posix.c
- mono-dl-wasm.c
- mono-dl.h
- mono-dl-windows-internals.h
- mono-log-windows.c
- mono-log-common.c
- mono-log-posix.c
- mono-log-android.c
- mono-log-darwin.c
- mono-log-flight-recorder.c
- mono-merp.c
- mono-merp.h
- mono-state.h
- mono-state.c
- mono-internal-hash.c
- mono-internal-hash.h
- mono-io-portability.c
- mono-io-portability.h
- monobitset.c
- mono-filemap.c
- mono-math-c.c
- mono-mmap.c
- mono-mmap-windows.c
- mono-mmap.h
- mono-mmap-internals.h
- mono-mmap-windows-internals.h
- mono-os-mutex.h
- mono-os-mutex.c
- mono-flight-recorder.h
- mono-flight-recorder.c
- mono-os-wait.h
- mono-coop-mutex.h
- mono-once.h
- mono-lazy-init.h
- mono-networkinterfaces.c
- mono-networkinterfaces.h
- mono-proclib.c
- mono-proclib-windows.c
- mono-proclib.h
- mono-proclib-windows-internals.h
- mono-publib.c
- mono-jemalloc.c
- mono-string.h
- mono-time.c
- mono-time.h
- strenc.h
- strenc.c
- mono-uri.c
- mono-poll.c
- mono-path.c
- mono-os-semaphore.h
- mono-coop-semaphore.h
- mono-sigcontext.h
- mono-stdlib.c
- mono-property-hash.h
- mono-property-hash.c
- mono-value-hash.h
- mono-value-hash.c
- freebsd-elf_common.h
- freebsd-elf32.h
- freebsd-elf64.h
- freebsd-dwarf.h
- dtrace.h
- gc_wrapper.h
- mono-error.c
- mono-error-internals.h
- monobitset.h
- mono-codeman.h
- mono-counters.h
- mono-digest.h
- mono-error.h
- mono-machine.h
- mono-math.h
- mono-membar.h
- mono-path.h
- mono-poll.h
- mono-uri.h
- mono-stdlib.h
- valgrind.h
- mach-support.h
- memcheck.h
- mono-context.c
- mono-context.h
- mono-stack-unwinding.h
- hazard-pointer.c
- hazard-pointer.h
- lock-free-queue.c
- lock-free-queue.h
- lock-free-alloc.c
- lock-free-alloc.h
- lock-free-array-queue.c
- lock-free-array-queue.h
- mono-linked-list-set.c
- mono-linked-list-set.h
- mono-threads.c
- mono-threads-state-machine.c
- mono-threads-posix.c
- mono-threads-posix-signals.c
- mono-threads-mach.c
- mono-threads-mach-helper.c
- mono-threads-windows.c
- mono-threads-linux.c
- mono-threads-freebsd.c
- mono-threads-netbsd.c
- mono-threads-openbsd.c
- mono-threads-android.c
- mono-threads-haiku.c
- mono-threads-aix.c
- mono-threads-wasm.c
- mono-threads.h
- mono-threads-debug.h
- mono-threads-api.h
- mono-threads-coop.c
- mono-threads-coop.h
- mono-utility-thread.c
- mono-utility-thread.h
- mono-tls.h
- mono-tls.c
- mono-utils-debug.c
- mono-utils-debug.h
- linux_magic.h
- mono-memory-model.h
- atomic.h
- atomic.c
- mono-hwcap.h
- mono-hwcap.c
- mono-hwcap-vars.h
- bsearch.h
- bsearch.c
- mono-signal-handler.h
- mono-conc-hashtable.h
- mono-conc-hashtable.c
- json.h
- json.c
- networking.c
- networking-posix.c
- networking-fallback.c
- networking-missing.c
- networking-windows.c
- networking.h
- mono-rand.c
- mono-rand-windows.c
- mono-rand.h
- memfuncs.c
- memfuncs.h
- parse.c
- parse.h
- checked-build.c
- checked-build.h
- os-event.h
- refcount.h
- w32api.h
- unlocked.h
- ward.h)
-
-if (TARGET_AMD64)
-set (utils_arch_sources
- mach-support-amd64.c)
+set(utils_common_sources
+ mono-md5.c
+ mono-sha1.c
+ mono-logger.c
+ mono-logger-internals.h
+ mono-codeman.c
+ dlmalloc.h
+ dlmalloc.c
+ mono-counters.c
+ mono-compiler.h
+ mono-complex.h
+ mono-dl.c
+ mono-dl-windows.c
+ mono-dl-darwin.c
+ mono-dl-posix.c
+ mono-dl-wasm.c
+ mono-dl.h
+ mono-dl-windows-internals.h
+ mono-log-windows.c
+ mono-log-common.c
+ mono-log-posix.c
+ mono-log-android.c
+ mono-log-darwin.c
+ mono-log-flight-recorder.c
+ mono-merp.c
+ mono-merp.h
+ mono-state.h
+ mono-state.c
+ mono-internal-hash.c
+ mono-internal-hash.h
+ mono-io-portability.c
+ mono-io-portability.h
+ monobitset.c
+ mono-filemap.c
+ mono-math-c.c
+ mono-mmap.c
+ mono-mmap-windows.c
+ mono-mmap.h
+ mono-mmap-internals.h
+ mono-mmap-windows-internals.h
+ mono-os-mutex.h
+ mono-os-mutex.c
+ mono-flight-recorder.h
+ mono-flight-recorder.c
+ mono-os-wait.h
+ mono-coop-mutex.h
+ mono-once.h
+ mono-lazy-init.h
+ mono-networkinterfaces.c
+ mono-networkinterfaces.h
+ mono-proclib.c
+ mono-proclib-windows.c
+ mono-proclib.h
+ mono-proclib-windows-internals.h
+ mono-publib.c
+ mono-jemalloc.c
+ mono-string.h
+ mono-time.c
+ mono-time.h
+ strenc.h
+ strenc.c
+ mono-uri.c
+ mono-poll.c
+ mono-path.c
+ mono-os-semaphore.h
+ mono-coop-semaphore.h
+ mono-sigcontext.h
+ mono-stdlib.c
+ mono-property-hash.h
+ mono-property-hash.c
+ mono-value-hash.h
+ mono-value-hash.c
+ freebsd-elf_common.h
+ freebsd-elf32.h
+ freebsd-elf64.h
+ freebsd-dwarf.h
+ dtrace.h
+ gc_wrapper.h
+ mono-error.c
+ mono-error-internals.h
+ monobitset.h
+ mono-codeman.h
+ mono-counters.h
+ mono-digest.h
+ mono-error.h
+ mono-machine.h
+ mono-math.h
+ mono-membar.h
+ mono-path.h
+ mono-poll.h
+ mono-uri.h
+ mono-stdlib.h
+ valgrind.h
+ mach-support.h
+ memcheck.h
+ mono-context.c
+ mono-context.h
+ mono-stack-unwinding.h
+ hazard-pointer.c
+ hazard-pointer.h
+ lock-free-queue.c
+ lock-free-queue.h
+ lock-free-alloc.c
+ lock-free-alloc.h
+ lock-free-array-queue.c
+ lock-free-array-queue.h
+ lifo-semaphore.c
+ lifo-semaphore.h
+ mono-linked-list-set.c
+ mono-linked-list-set.h
+ mono-threads.c
+ mono-threads-state-machine.c
+ mono-threads-posix.c
+ mono-threads-posix-signals.c
+ mono-threads-mach.c
+ mono-threads-mach-helper.c
+ mono-threads-windows.c
+ mono-threads-linux.c
+ mono-threads-freebsd.c
+ mono-threads-netbsd.c
+ mono-threads-openbsd.c
+ mono-threads-android.c
+ mono-threads-haiku.c
+ mono-threads-aix.c
+ mono-threads-wasm.c
+ mono-threads-sunos.c
+ mono-threads.h
+ mono-threads-debug.h
+ mono-threads-api.h
+ mono-threads-coop.c
+ mono-threads-coop.h
+ mono-utility-thread.c
+ mono-utility-thread.h
+ mono-tls.h
+ mono-tls.c
+ mono-utils-debug.c
+ mono-utils-debug.h
+ linux_magic.h
+ mono-memory-model.h
+ atomic.h
+ atomic.c
+ mono-hwcap.h
+ mono-hwcap.c
+ mono-hwcap-vars.h
+ bsearch.h
+ bsearch.c
+ mono-signal-handler.h
+ mono-signal-handler.c
+ mono-conc-hashtable.h
+ mono-conc-hashtable.c
+ json.h
+ json.c
+ networking.c
+ networking-posix.c
+ networking-fallback.c
+ networking-missing.c
+ networking-windows.c
+ networking.h
+ mono-rand.c
+ mono-rand-windows.c
+ mono-rand.h
+ memfuncs.c
+ memfuncs.h
+ parse.c
+ parse.h
+ checked-build.c
+ checked-build.h
+ os-event.h
+ refcount.h
+ w32api.h
+ unlocked.h
+ ward.h)
+
+if(MONO_CROSS_COMPILE)
+set(utils_arch_sources mach-support-unknown.c)
+elseif(HOST_AMD64)
+set(utils_arch_sources
+ mach-support-amd64.c)
+elseif(HOST_X86)
+set(utils_arch_sources
+ mach-support-x86.c)
+elseif(HOST_ARM64)
+set(utils_arch_sources
+ mach-support-arm64.c)
+elseif(HOST_ARM)
+set(utils_arch_sources
+ mach-support-arm.c)
else()
-#message (FATAL_ERROR "")
+#message(FATAL_ERROR "")
endif()
-if (CROSS_COMPILE)
-set (utils_arch_sources "${utils_arch_sources};mono-hwcap-cross.c")
-elseif (TARGET_AMD64)
-set (utils_arch_sources "${utils_arch_sources};mono-hwcap-x86.c")
+if(MONO_CROSS_COMPILE)
+set(utils_arch_sources "${utils_arch_sources};mono-hwcap-cross.c")
+elseif(TARGET_AMD64)
+set(utils_arch_sources "${utils_arch_sources};mono-hwcap-x86.c")
+elseif(TARGET_X86)
+set(utils_arch_sources "${utils_arch_sources};mono-hwcap-x86.c")
+elseif(TARGET_ARM64)
+set(utils_arch_sources "${utils_arch_sources};mono-hwcap-arm64.c")
+elseif(TARGET_ARM)
+set(utils_arch_sources "${utils_arch_sources};mono-hwcap-arm.c")
+elseif(TARGET_WASM)
+set(utils_arch_sources "${utils_arch_sources};mono-hwcap-wasm.c;mono-mmap-wasm.c")
else()
- message (FATAL_ERROR "")
+ message(FATAL_ERROR "")
endif()
-addprefix (utils_sources ../utils/ "${utils_platform_sources};${utils_arch_sources};${utils_common_sources}")
+addprefix(utils_sources ../utils/ "${utils_platform_sources};${utils_arch_sources};${utils_common_sources}")
+
+set(utils_public_headers_base
+ mono-logger.h
+ mono-error.h
+ mono-forward.h
+ mono-publib.h
+ mono-jemalloc.h
+ mono-dl-fallback.h
+ mono-private-unstable.h
+ mono-counters.h)
+addprefix(utils_public_headers ../utils "${utils_public_headers_base}")
#
# METADATA
#
-set (metadata_win32_sources
- console-win32.c
- console-win32-internals.h
- cominterop-win32-internals.h
- w32file-win32.c
- w32file-win32-internals.h
- icall-windows.c
- icall-windows-internals.h
- marshal-windows.c
- marshal-windows-internals.h
- mono-security-windows.c
- mono-security-windows-internals.h
- w32mutex-win32.c
- w32semaphore-win32.c
- w32event-win32.c
- w32process-win32.c
- w32process-win32-internals.h
- w32socket-win32.c
- w32error-win32.c
- w32subset.h)
-
-set (metadata_unix_sources
- console-unix.c
- w32mutex-unix.c
- w32semaphore-unix.c
- w32event-unix.c
- w32process-unix.c
- w32process-unix-internals.h
- w32process-unix-osx.c
- w32process-unix-bsd.c
- w32process-unix-haiku.c
- w32process-unix-default.c
- w32socket-unix.c
- w32file-unix.c
- w32file-unix-glob.c
- w32file-unix-glob.h
- w32error-unix.c)
-
-if (HOST_WIN32)
-set (metadata_platform_sources ${metadata_win32_sources})
+#
+# This library contains the icall tables if the runtime was configured with DISABLE_ICALL_TABLES
+#
+if(DISABLE_ICALL_TABLES)
+add_library(mono-icall-table STATIC "../metadata/icall-table.c")
+install(TARGETS mono-icall-table LIBRARY)
+else()
+set(icall_table_sources "icall-table.c")
+endif()
+
+#
+# This library contains runtime IL code generation
+#
+set(ilgen_base_sources
+ method-builder-ilgen.c
+ method-builder-ilgen.h
+ method-builder-ilgen-internals.h
+ marshal-ilgen.c
+ marshal-ilgen.h
+ sgen-mono-ilgen.c
+ sgen-mono-ilgen.h)
+
+if(NOT ENABLE_ILGEN)
+addprefix(mono_ilgen_sources ../metadata "${ilgen_base_sources}")
+set_source_files_properties(${mono_ilgen_sources} PROPERTIES COMPILE_DEFINITIONS "HAVE_SGEN_GC")
+add_library(mono-ilgen STATIC "${mono_ilgen_sources}")
+install(TARGETS mono-ilgen LIBRARY)
+else()
+set(ilgen_sources ${ilgen_base_sources})
+endif()
+
+set(metadata_win32_sources
+ console-win32.c
+ console-win32-internals.h
+ cominterop-win32-internals.h
+ w32file-win32.c
+ w32file-win32-internals.h
+ icall-windows.c
+ icall-windows-internals.h
+ marshal-windows.c
+ marshal-windows-internals.h
+ mono-security-windows.c
+ mono-security-windows-internals.h
+ w32mutex-win32.c
+ w32semaphore-win32.c
+ w32event-win32.c
+ w32process-win32.c
+ w32process-win32-internals.h
+ w32socket-win32.c
+ w32error-win32.c
+ w32subset.h)
+
+set(metadata_unix_sources
+ console-unix.c
+ w32mutex-unix.c
+ w32semaphore-unix.c
+ w32event-unix.c
+ w32process-unix.c
+ w32process-unix-internals.h
+ w32process-unix-osx.c
+ w32process-unix-bsd.c
+ w32process-unix-haiku.c
+ w32process-unix-default.c
+ w32socket-unix.c
+ w32file-unix.c
+ w32file-unix-glob.c
+ w32file-unix-glob.h
+ w32error-unix.c)
+
+if(HOST_WIN32)
+set(metadata_platform_sources ${metadata_win32_sources})
else()
-set (metadata_platform_sources ${metadata_unix_sources})
+set(metadata_platform_sources ${metadata_unix_sources})
endif()
set(metadata_common_sources
- appdomain.c
- domain.c
- appdomain-icalls.h
- assembly.c
- assembly-internals.h
- attach.h
- attach.c
- cil-coff.h
- class.c
- class-getters.h
- class-init.h
- class-init.c
- class-internals.h
- class-inlines.h
- class-private-definition.h
- class-accessors.c
- cominterop.c
- cominterop.h
- console-io.h
- coree.c
- coree.h
- coree-internals.h
- culture-info.h
- culture-info-tables.h
- debug-helpers.c
- debug-mono-symfile.h
- debug-mono-symfile.c
- debug-mono-ppdb.h
- debug-mono-ppdb.c
- domain-internals.h
- environment.c
- environment.h
- exception.c
- exception.h
- exception-internals.h
- w32file.c
- w32file.h
- w32file-internals.h
- filewatcher.c
- filewatcher.h
- gc-internals.h
- icall.c
- icall-internals.h
- icall-def.h
- icall-table.h
- image.c
- image-internals.h
- jit-info.c
- loader.c
- locales.c
- locales.h
- lock-tracer.c
- lock-tracer.h
- marshal.c
- marshal.h
- marshal-internals.h
- mempool.c
- mempool.h
- mempool-internals.h
- metadata.c
- metadata-verify.c
- metadata-internals.h
- method-builder.h
- method-builder-internals.h
- method-builder.c
- mono-basic-block.c
- mono-basic-block.h
- mono-config.c
- mono-debug.h
- mono-debug.c
- debug-internals.h
- mono-endian.c
- mono-endian.h
- mono-hash.c
- mono-hash.h
- mono-conc-hash.c
- mono-conc-hash.h
- mono-mlist.c
- mono-mlist.h
- mono-perfcounters.c
- mono-perfcounters.h
- mono-perfcounters-def.h
- mono-ptr-array.h
- mono-route.c
- monitor.h
- normalization-tables.h
- number-formatter.h
- number-ms.h
- object.c
- object-forward.h
- object-internals.h
- opcodes.c
- property-bag.h
- property-bag.c
- w32socket.c
- w32socket.h
- w32socket-internals.h
- w32process.c
- w32process.h
- w32process-internals.h
- profiler.c
- profiler-private.h
- rand.h
- rand.c
- remoting.h
- remoting.c
- runtime.c
- mono-security.c
- security.h
- security-core-clr.c
- security-core-clr.h
- security-manager.c
- security-manager.h
- string-icalls.c
- string-icalls.h
- sysmath.c
- tabledefs.h
- threads.c
- threads-types.h
- threadpool.c
- threadpool.h
- threadpool-worker.h
- threadpool-io.c
- threadpool-io.h
- verify.c
- verify-internals.h
- wrapper-types.h
- dynamic-image-internals.h
- dynamic-stream.c
- dynamic-stream-internals.h
- reflection-cache.h
- custom-attrs-internals.h
- sre-internals.h
- reflection-internals.h
- file-mmap-posix.c
- file-mmap-windows.c
- file-mmap.h
- object-offsets.h
- abi-details.h
- class-abi-details.h
- metadata-cross-helpers.c
- seq-points-data.h
- seq-points-data.c
- handle.c
- handle.h
- w32mutex.h
- w32semaphore.h
- w32event.h
- w32handle-namespace.h
- w32handle-namespace.c
- w32handle.h
- w32handle.c
- w32error.h
- reflection.c
- dynamic-image.c
- sre.c
- sre-encode.c
- sre-save.c
- custom-attrs.c
- fdhandle.h
- fdhandle.c
- callspec.h
- callspec.c
- assembly-load-context.c
- icall-eventpipe.c
- native-library.h
- native-library.c
- native-library-qcall.c
- qcalllist.h
- loaded-images-internals.h
- loaded-images.c
- loaded-images-netcore.c
- abi-details.h
- abi.c
- mono-config-dirs.h
- mono-config-dirs.c
- icall-table.h
- icall-table.c
- method-builder-ilgen.h
- method-builder-ilgen.c
- marshal-ilgen.h
- marshal-ilgen.c)
-
-set (metadata_gc_dependent_sources
+ appdomain.c
+ domain.c
+ appdomain-icalls.h
+ assembly.c
+ assembly-internals.h
+ attach.h
+ attach.c
+ cil-coff.h
+ class.c
+ class-getters.h
+ class-init.h
+ class-init-internals.h
+ class-init.c
+ class-internals.h
+ class-inlines.h
+ class-private-definition.h
+ class-accessors.c
+ class-setup-vtable.c
+ cominterop.c
+ cominterop.h
+ console-io.h
+ coree.c
+ coree.h
+ coree-internals.h
+ debug-helpers.c
+ debug-mono-symfile.h
+ debug-mono-symfile.c
+ debug-mono-ppdb.h
+ debug-mono-ppdb.c
+ domain-internals.h
+ environment.c
+ environment.h
+ exception.c
+ exception.h
+ exception-internals.h
+ w32file.c
+ w32file.h
+ w32file-internals.h
+ filewatcher.c
+ filewatcher.h
+ gc-internals.h
+ icall.c
+ icall-internals.h
+ icall-def.h
+ icall-table.h
+ icall-eventpipe.c
+ image.c
+ image-internals.h
+ jit-info.c
+ loader.c
+ lock-tracer.c
+ lock-tracer.h
+ marshal.c
+ marshal.h
+ marshal-internals.h
+ mempool.c
+ mempool.h
+ mempool-internals.h
+ metadata.c
+ metadata-verify.c
+ metadata-internals.h
+ method-builder.h
+ method-builder-internals.h
+ method-builder.c
+ mono-basic-block.c
+ mono-basic-block.h
+ mono-config.c
+ mono-debug.h
+ mono-debug.c
+ debug-internals.h
+ mono-endian.c
+ mono-endian.h
+ mono-hash.c
+ mono-hash.h
+ mono-conc-hash.c
+ mono-conc-hash.h
+ mono-mlist.c
+ mono-mlist.h
+ mono-perfcounters.c
+ mono-perfcounters.h
+ mono-perfcounters-def.h
+ mono-ptr-array.h
+ mono-route.c
+ monitor.h
+ normalization-tables.h
+ number-formatter.h
+ number-ms.h
+ object.c
+ object-forward.h
+ object-internals.h
+ opcodes.c
+ property-bag.h
+ property-bag.c
+ w32socket.c
+ w32socket.h
+ w32socket-internals.h
+ w32process.c
+ w32process.h
+ w32process-internals.h
+ profiler.c
+ profiler-private.h
+ rand.h
+ rand.c
+ remoting.h
+ remoting.c
+ runtime.c
+ mono-security.c
+ security.h
+ security-core-clr.c
+ security-core-clr.h
+ security-manager.c
+ security-manager.h
+ string-icalls.c
+ string-icalls.h
+ sysmath.c
+ tabledefs.h
+ threads.c
+ threads-types.h
+ threadpool.c
+ threadpool.h
+ threadpool-worker.h
+ threadpool-io.c
+ threadpool-io.h
+ verify.c
+ verify-internals.h
+ wrapper-types.h
+ dynamic-image-internals.h
+ dynamic-stream.c
+ dynamic-stream-internals.h
+ reflection-cache.h
+ custom-attrs-internals.h
+ sre-internals.h
+ reflection-internals.h
+ file-mmap-posix.c
+ file-mmap-windows.c
+ file-mmap.h
+ object-offsets.h
+ abi-details.h
+ class-abi-details.h
+ metadata-cross-helpers.c
+ seq-points-data.h
+ seq-points-data.c
+ handle.c
+ handle.h
+ w32mutex.h
+ w32semaphore.h
+ w32event.h
+ w32handle-namespace.h
+ w32handle-namespace.c
+ w32handle.h
+ w32handle.c
+ w32error.h
+ reflection.c
+ dynamic-image.c
+ sre.c
+ sre-encode.c
+ sre-save.c
+ custom-attrs.c
+ fdhandle.h
+ fdhandle.c
+ callspec.h
+ callspec.c
+ assembly-load-context.c
+ icall-eventpipe.c
+ native-library.h
+ native-library.c
+ native-library-qcall.c
+ qcall-def.h
+ loaded-images-internals.h
+ loaded-images.c
+ loaded-images-netcore.c
+ abi-details.h
+ abi.c
+ mono-config-dirs.h
+ mono-config-dirs.c
+ icall-table.h
+ ${icall_table_sources})
+
+set(metadata_gc_dependent_sources
gc-stats.c
gc.c
monitor.c)
-set (metadata_sgen_sources
- sgen-bridge.c
- sgen-bridge.h
- sgen-bridge-internals.h
- sgen-old-bridge.c
- sgen-new-bridge.c
- sgen-tarjan-bridge.c
- sgen-toggleref.c
- sgen-toggleref.h
- sgen-stw.c
- sgen-mono.c
- sgen-mono.h
- sgen-client-mono.h
- sgen-mono-ilgen.h
- sgen-mono-ilgen.c)
-
-addprefix (metadata_gc_dependent_real_sources ../metadata "${metadata_gc_dependent_sources}")
-addprefix (metadata_sgen_real_sources ../metadata "${metadata_sgen_sources}")
-set_source_files_properties (${metadata_sgen_real_sources};${metadata_gc_dependent_real_sources} PROPERTIES COMPILE_DEFINITIONS "HAVE_SGEN_GC")
+set(metadata_sgen_sources
+ sgen-bridge.c
+ sgen-bridge.h
+ sgen-bridge-internals.h
+ sgen-old-bridge.c
+ sgen-new-bridge.c
+ sgen-tarjan-bridge.c
+ sgen-toggleref.c
+ sgen-toggleref.h
+ sgen-stw.c
+ sgen-mono.c
+ sgen-mono.h
+ sgen-client-mono.h)
+
+addprefix(metadata_gc_dependent_real_sources ../metadata "${metadata_gc_dependent_sources}")
+addprefix(metadata_sgen_real_sources ../metadata "${metadata_sgen_sources}")
+addprefix(ilgen_real_sources ../metadata "${ilgen_sources}")
+set_source_files_properties(${metadata_sgen_real_sources};${metadata_gc_dependent_real_sources};${ilgen_real_sources} PROPERTIES COMPILE_DEFINITIONS "HAVE_SGEN_GC")
#
# We localize the usage of MONO_BINDIR etc. to just one source file, thus enabling
# ccache to work even if the value of these defines change.
#
-set (bindir "${CMAKE_INSTALL_FULL_BINDIR}")
-set (assembliesdir "${CMAKE_INSTALL_FULL_LIBDIR}")
-set (confdir "${CMAKE_INSTALL_FULL_SYSCONFDIR}")
-set (reloc_libdir "${CMAKE_INSTALL_LIBDIR}")
+set(bindir "${CMAKE_INSTALL_FULL_BINDIR}")
+set(assembliesdir "${CMAKE_INSTALL_FULL_LIBDIR}")
+set(confdir "${CMAKE_INSTALL_FULL_SYSCONFDIR}")
+set(reloc_libdir "${CMAKE_INSTALL_LIBDIR}")
-set_source_files_properties (../metadata/mono-config-dirs.c PROPERTIES COMPILE_DEFINITIONS "MONO_BINDIR=\"${bindir}\";MONO_ASSEMBLIES=\"${assembliesdir}\";MONO_CFG_DIR=\"${confdir}\";MONO_RELOC_LIBDIR=\"../${reloc_libdir}\"")
+set_source_files_properties(../metadata/mono-config-dirs.c PROPERTIES COMPILE_DEFINITIONS "MONO_BINDIR=\"${bindir}\";MONO_ASSEMBLIES=\"${assembliesdir}\";MONO_CFG_DIR=\"${confdir}\";MONO_RELOC_LIBDIR=\"../${reloc_libdir}\"")
-addprefix (metadata_sources ../metadata/ "${metadata_platform_sources};${metadata_common_sources};${metadata_gc_dependent_sources};${metadata_sgen_sources}")
+addprefix(metadata_sources ../metadata/ "${metadata_platform_sources};${metadata_common_sources};${metadata_gc_dependent_sources};${metadata_sgen_sources};${ilgen_real_sources}")
+
+set(metadata_public_headers_base
+ appdomain.h
+ assembly.h
+ attrdefs.h
+ blob.h
+ class.h
+ debug-helpers.h
+ debug-mono-symfile.h
+ environment.h
+ exception.h
+ image.h
+ loader.h
+ metadata.h
+ mono-config.h
+ mono-debug.h
+ mono-gc.h
+ mono-private-unstable.h
+ object.h
+ object-forward.h
+ opcodes.h
+ profiler.h
+ profiler-events.h
+ reflection.h
+ row-indexes.h
+ sgen-bridge.h
+ threads.h
+ tokentype.h
+ verify.h)
+addprefix(metadata_public_headers ../metadata/ "${metadata_public_headers_base}")
#
# SGEN
#
set(sgen_sources_base
- gc-internal-agnostic.h
- sgen-alloc.c
- sgen-archdep.h
- sgen-cardtable.c
- sgen-cardtable.h
- sgen-client.h
- sgen-conf.h
- sgen-copy-object.h
- sgen-debug.c
- sgen-descriptor.c
- sgen-descriptor.h
- sgen-fin-weak-hash.c
- sgen-gc.c
- sgen-gc.h
- sgen-gchandles.c
- sgen-gray.c
- sgen-gray.h
- sgen-hash-table.c
- sgen-hash-table.h
- sgen-internal.c
- sgen-layout-stats.c
- sgen-layout-stats.h
- sgen-los.c
- sgen-major-copy-object.h
- sgen-marksweep-drain-gray-stack.h
- sgen-marksweep.c
- sgen-memory-governor.c
- sgen-memory-governor.h
- sgen-minor-copy-object.h
- sgen-minor-scan-object.h
- sgen-nursery-allocator.c
- sgen-pinning-stats.c
- sgen-pinning.c
- sgen-pinning.h
- sgen-pointer-queue.c
- sgen-pointer-queue.h
- sgen-array-list.h
- sgen-array-list.c
- sgen-protocol-def.h
- sgen-protocol.c
- sgen-protocol.h
- sgen-qsort.c
- sgen-qsort.h
- sgen-scan-object.h
- sgen-simple-nursery.c
- sgen-split-nursery.c
- sgen-tagged-pointer.h
- sgen-thread-pool.c
- sgen-thread-pool.h
- sgen-workers.c
- sgen-workers.h)
-
-addprefix (sgen_sources ../sgen/ "${sgen_sources_base}")
-set_source_files_properties (${sgen_sources} PROPERTIES COMPILE_DEFINITIONS "HAVE_SGEN_GC")
+ gc-internal-agnostic.h
+ sgen-alloc.c
+ sgen-archdep.h
+ sgen-cardtable.c
+ sgen-cardtable.h
+ sgen-client.h
+ sgen-conf.h
+ sgen-copy-object.h
+ sgen-debug.c
+ sgen-descriptor.c
+ sgen-descriptor.h
+ sgen-fin-weak-hash.c
+ sgen-gc.c
+ sgen-gc.h
+ sgen-gchandles.c
+ sgen-gray.c
+ sgen-gray.h
+ sgen-hash-table.c
+ sgen-hash-table.h
+ sgen-internal.c
+ sgen-layout-stats.c
+ sgen-layout-stats.h
+ sgen-los.c
+ sgen-major-copy-object.h
+ sgen-marksweep-drain-gray-stack.h
+ sgen-marksweep.c
+ sgen-memory-governor.c
+ sgen-memory-governor.h
+ sgen-minor-copy-object.h
+ sgen-minor-scan-object.h
+ sgen-nursery-allocator.c
+ sgen-pinning-stats.c
+ sgen-pinning.c
+ sgen-pinning.h
+ sgen-pointer-queue.c
+ sgen-pointer-queue.h
+ sgen-array-list.h
+ sgen-array-list.c
+ sgen-protocol-def.h
+ sgen-protocol.c
+ sgen-protocol.h
+ sgen-qsort.c
+ sgen-qsort.h
+ sgen-scan-object.h
+ sgen-simple-nursery.c
+ sgen-split-nursery.c
+ sgen-tagged-pointer.h
+ sgen-thread-pool.c
+ sgen-thread-pool.h
+ sgen-workers.c
+ sgen-workers.h)
+
+addprefix(sgen_sources ../sgen/ "${sgen_sources_base}")
+set_source_files_properties(${sgen_sources} PROPERTIES COMPILE_DEFINITIONS "HAVE_SGEN_GC")
+
+# EVENTPIPE
+
+set(eventpipe_sources_base
+ ep.c
+ ep.h
+ ep-block.c
+ ep-block.h
+ ep-buffer.c
+ ep-buffer.h
+ ep-buffer-manager.c
+ ep-buffer-manager.h
+ ep-config.c
+ ep-config.h
+ ep-config-internals.h
+ ep-event.c
+ ep-event.h
+ ep-event-instance.h
+ ep-event-instance.c
+ ep-event-payload.c
+ ep-event-payload.h
+ ep-event-source.c
+ ep-event-source.h
+ ep-file.c
+ ep-file.h
+ ep-getter-setter.h
+ ep-metadata-generator.c
+ ep-metadata-generator.h
+ ep-provider.c
+ ep-provider.h
+ ep-provider-internals.h
+ ep-rt.h
+ ep-rt-config.h
+ ep-rt-config-mono.h
+ ep-rt-mono.c
+ ep-rt-mono.h
+ ep-rt-types.h
+ ep-rt-types-mono.h
+ ep-thread.c
+ ep-thread.h
+ ep-types.h
+ ep-session.c
+ ep-session.h
+ ep-session-provider.c
+ ep-stack-contents.c
+ ep-stack-contents.h
+ ep-stream.c
+ ep-stream.h)
+if(ENABLE_PERFTRACING)
+ addprefix(eventpipe_sources ../eventpipe "${eventpipe_sources_base}")
+endif()
+
+# ICU
+if(HAVE_SYS_ICU)
+if(STATIC_ICU)
+set(pal_icushim_sources_base
+ pal_icushim_static.c)
+else()
+set(pal_icushim_sources_base
+ pal_icushim.c)
+endif()
+
+set(icu_shim_sources_base
+ pal_calendarData.c
+ pal_casing.c
+ pal_collation.c
+ pal_idna.c
+ pal_locale.c
+ pal_localeNumberData.c
+ pal_localeStringData.c
+ pal_normalization.c
+ pal_timeZoneInfo.c
+ entrypoints.c
+ ${pal_icushim_sources_base})
+addprefix(icu_shim_sources "${ICU_SHIM_PATH}" "${icu_shim_sources_base}")
+set_source_files_properties(${icu_shim_sources} PROPERTIES COMPILE_DEFINITIONS OSX_ICU_LIBRARY_PATH="${OSX_ICU_LIBRARY_PATH}")
+set_source_files_properties(${icu_shim_sources} PROPERTIES COMPILE_FLAGS "-I${ICU_INCLUDEDIR} -I${CMAKE_SOURCE_DIR}/../libraries/Native/Unix/System.Globalization.Native/ -I${CMAKE_SOURCE_DIR}/../libraries/Native/Unix/Common/ ${ICU_FLAGS}")
+set(ICU_LIBS "icucore")
+set(ICU_LDFLAGS "-L${ICU_LIBDIR}")
+endif()
#
# MINI
#
-set (mini_common_sources
- mini.c
- mini-runtime.c
- seq-points.c
- seq-points.h
- ir-emit.h
- method-to-ir.c
- cfgdump.h
- cfgdump.c
- calls.c
- decompose.c
- mini.h
- version.h
- optflags-def.h
- jit-icalls.h
- jit-icalls.c
- trace.c
- trace.h
- patch-info.h
- mini-ops.h
- mini-arch.h
- dominators.c
- cfold.c
- regalloc.h
- helpers.c
- liveness.c
- ssa.c
- abcremoval.c
- abcremoval.h
- local-propagation.c
- driver.c
- debug-mini.c
- linear-scan.c
- aot-compiler.h
- aot-compiler.c
- aot-runtime.c
- aot-runtime-wasm.c
- wasm_m2n_invoke.g.h
- graph.c
- mini-codegen.c
- mini-exceptions.c
- mini-trampolines.c
- branch-opts.c
- mini-generic-sharing.c
- simd-methods.h
- tasklets.c
- tasklets.h
- simd-intrinsics.c
- mini-native-types.c
- mini-unwind.h
- unwind.c
- image-writer.h
- image-writer.c
- dwarfwriter.h
- dwarfwriter.c
- mini-gc.h
- mini-gc.c
- xdebug.c
- mini-llvm.h
- mini-llvm-cpp.h
- llvm-jit.h
- alias-analysis.c
- mini-cross-helpers.c
- arch-stubs.c
- llvm-runtime.h
- type-checking.c
- lldb.h
- lldb.c
- memory-access.c
- intrinsics.c
- mini-profiler.c
- interp-stubs.c
- aot-runtime.h
- ee.h
- mini-runtime.h
- llvmonly-runtime.h
- llvmonly-runtime.c
- simd-intrinsics-netcore.c
- monovm.h
- monovm.c)
-
-set (debugger_sources
+set(mini_common_sources
+ mini.c
+ mini-runtime.c
+ seq-points.c
+ seq-points.h
+ ir-emit.h
+ method-to-ir.c
+ cfgdump.h
+ cfgdump.c
+ calls.c
+ decompose.c
+ mini.h
+ version.h
+ optflags-def.h
+ jit-icalls.h
+ jit-icalls.c
+ trace.c
+ trace.h
+ patch-info.h
+ mini-ops.h
+ mini-arch.h
+ dominators.c
+ cfold.c
+ regalloc.h
+ helpers.c
+ liveness.c
+ ssa.c
+ abcremoval.c
+ abcremoval.h
+ local-propagation.c
+ driver.c
+ debug-mini.c
+ linear-scan.c
+ aot-compiler.h
+ aot-compiler.c
+ aot-runtime.c
+ graph.c
+ mini-codegen.c
+ mini-exceptions.c
+ mini-trampolines.c
+ branch-opts.c
+ mini-generic-sharing.c
+ simd-methods.h
+ tasklets.c
+ tasklets.h
+ simd-intrinsics.c
+ mini-native-types.c
+ mini-unwind.h
+ unwind.c
+ image-writer.h
+ image-writer.c
+ dwarfwriter.h
+ dwarfwriter.c
+ mini-gc.h
+ mini-gc.c
+ xdebug.c
+ mini-llvm.h
+ mini-llvm-cpp.h
+ llvm-jit.h
+ alias-analysis.c
+ mini-cross-helpers.c
+ arch-stubs.c
+ llvm-runtime.h
+ llvm-intrinsics.h
+ type-checking.c
+ lldb.h
+ lldb.c
+ memory-access.c
+ intrinsics.c
+ mini-profiler.c
+ interp-stubs.c
+ aot-runtime.h
+ ee.h
+ mini-runtime.h
+ llvmonly-runtime.h
+ llvmonly-runtime.c
+ simd-intrinsics-netcore.c
+ monovm.h
+ monovm.c)
+
+set(debugger_sources
debugger-engine.h
debugger-engine.c
debugger-agent.h
@@ -692,94 +862,205 @@ set (debugger_sources
debugger-state-machine.h
debugger-state-machine.c)
-set (amd64_sources
- mini-amd64.c
- mini-amd64.h
- exceptions-amd64.c
- tramp-amd64.c
- mini-amd64-gsharedvt.c
- mini-amd64-gsharedvt.h
- tramp-amd64-gsharedvt.c
- cpu-amd64.h)
-
-if (TARGET_AMD64)
-set (arch_sources ${amd64_sources})
+set(amd64_sources
+ mini-amd64.c
+ mini-amd64.h
+ exceptions-amd64.c
+ tramp-amd64.c
+ mini-amd64-gsharedvt.c
+ mini-amd64-gsharedvt.h
+ tramp-amd64-gsharedvt.c
+ cpu-amd64.h)
+
+set(x86_sources
+ mini-x86.c
+ mini-x86.h
+ exceptions-x86.c
+ tramp-x86.c
+ mini-x86-gsharedvt.c
+ tramp-x86-gsharedvt.c
+ cpu-x86.h)
+
+set(arm64_sources
+ mini-arm64.c
+ mini-arm64.h
+ exceptions-arm64.c
+ tramp-arm64.c
+ mini-arm64-gsharedvt.c
+ mini-arm64-gsharedvt.h
+ tramp-arm64-gsharedvt.c
+ cpu-arm64.h)
+
+set(arm_sources
+ mini-arm.c
+ mini-arm.h
+ exceptions-arm.c
+ tramp-arm.c
+ mini-arm-gsharedvt.c
+ mini-arm-gsharedvt.h
+ tramp-arm-gsharedvt.c
+ cpu-arm.h)
+
+set(wasm_sources
+ mini-wasm.c
+ tramp-wasm.c
+ exceptions-wasm.c
+ aot-runtime-wasm.c
+ mini-wasm-debugger.c
+ wasm_m2n_invoke.g.h)
+
+if(TARGET_AMD64)
+set(arch_sources ${amd64_sources})
+elseif(TARGET_X86)
+set(arch_sources ${x86_sources})
+elseif(TARGET_ARM64)
+set(arch_sources ${arm64_sources})
+elseif(TARGET_ARM)
+set(arch_sources ${arm_sources})
+elseif(TARGET_WASM)
+set(arch_sources ${wasm_sources})
endif()
-set (darwin_sources
- mini-darwin.c)
+set(darwin_sources
+ mini-darwin.c)
-set (windows_sources
- mini-windows.c
- mini-windows.h
- mini-windows-dllmain.c
- mini-windows-dlldac.c)
+set(windows_sources
+ mini-windows.c
+ mini-windows.h
+ mini-windows-dllmain.c
+ mini-windows-dlldac.c)
-set (posix_sources
- mini-posix.c)
+set(posix_sources
+ mini-posix.c)
-if (HOST_DARWIN)
-set (os_sources "${darwin_sources};${posix_sources}")
+if(HOST_DARWIN)
+set(os_sources "${darwin_sources};${posix_sources}")
+endif()
+
+set(interp_sources
+ interp/interp.h
+ interp/interp-internals.h
+ interp/interp.c
+ interp/interp-intrins.h
+ interp/interp-intrins.c
+ interp/mintops.h
+ interp/mintops.c
+ interp/transform.c)
+set(interp_stub_sources
+ interp-stubs.c)
+
+if(NOT DISABLE_INTERPRETER)
+set(mini_interp_sources ${interp_sources})
+else()
+set(mini_interp_sources ${interp_stub_sources})
endif()
-if (NOT DISABLE_INTERPRETER)
-set (interp_sources
- interp/interp.h
- interp/interp-internals.h
- interp/interp.c
- interp/mintops.h
- interp/mintops.c
- interp/transform.c)
-else ()
-set (interp_sources
- interp-stubs.c)
+if(ENABLE_INTERP_LIB)
+add_library(mono-ee-interp STATIC "${interp_sources}")
+install(TARGETS mono-ee-interp LIBRARY)
endif()
-if (ENABLE_LLVM)
-set (llvm_sources
- mini-llvm.c
- mini-llvm-cpp.cpp
- llvm-jit.cpp)
+if(ENABLE_LLVM)
+set(llvm_sources
+ mini-llvm.c
+ mini-llvm-cpp.cpp
+ llvm-jit.cpp)
endif()
-if (ENABLE_LLVM)
-set (llvm_runtime_sources
- llvm-runtime.cpp)
-elseif (ENABLE_LLVM_RUNTIME)
-set (llvm_runtime_sources
- llvm-runtime.cpp)
+if(ENABLE_LLVM)
+set(llvm_runtime_sources
+ llvm-runtime.cpp)
+elseif(ENABLE_LLVM_RUNTIME)
+set(llvm_runtime_sources
+ llvm-runtime.cpp)
endif()
-set (mini_sources "${CMAKE_CURRENT_BINARY_DIR}/buildver-sgen.h;main-core.c;${mini_common_sources};${arch_sources};${os_sources};${interp_sources};${llvm_sources};${debugger_sources};${llvm_runtime_sources}")
+set(mini_public_headers_base
+ jit.h
+ mono-private-unstable.h)
+addprefix(mini_public_headers ../mini "${mini_public_headers_base}")
-add_library(monosgen-objects OBJECT "${eglib_sources};${metadata_sources};${utils_sources};${sgen_sources};${mini_sources}")
-add_library (monosgen-static STATIC $)
-add_library (monosgen SHARED $)
+set(mini_sources "${CMAKE_CURRENT_BINARY_DIR}/buildver-sgen.h;main-core.c;${mini_common_sources};${arch_sources};${os_sources};${mini_interp_sources};${llvm_sources};${debugger_sources};${llvm_runtime_sources}")
-set_target_properties(monosgen PROPERTIES OUTPUT_NAME monosgen-2.0)
-set_target_properties(monosgen PROPERTIES LIBRARY_OUTPUT_DIRECTORY .libs)
+if(LLVM_LIBDIR)
+ link_directories(${LLVM_LIBDIR})
+endif()
+
+if(HOST_DARWIN)
+set(OS_LIBS "-framework CoreFoundation" "-framework Foundation")
+endif()
+add_library(monosgen-objects OBJECT "${eglib_sources};${metadata_sources};${utils_sources};${sgen_sources};${icu_shim_sources};${eventpipe_sources};${mini_sources}")
+add_library(monosgen-static STATIC $)
+set_target_properties(monosgen-static PROPERTIES OUTPUT_NAME monosgen-2.0)
+if(NOT DISABLE_LIBS)
+ install(TARGETS monosgen-static LIBRARY)
+ install(FILES ${metadata_public_headers}
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mono-2.0/mono/metadata)
+ install(FILES ${utils_public_headers}
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mono-2.0/mono/utils)
+ install(FILES ${mini_public_headers}
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mono-2.0/mono/jit)
+endif()
+if(NOT DISABLE_SHARED_LIBS)
+ add_library(monosgen SHARED $)
+ set_target_properties(monosgen PROPERTIES OUTPUT_NAME monosgen-2.0)
+ set_target_properties(monosgen PROPERTIES LIBRARY_OUTPUT_DIRECTORY .libs)
+ target_link_libraries(monosgen ${OS_LIBS} "iconv" ${LLVM_LIBS} ${ICU_LIBS})
+ install(TARGETS monosgen LIBRARY)
+endif()
+
+# FIXME: Always rebuilds, creates non-deterministic builds
# FIXME: Use the previous format
-string(TIMESTAMP BUILD_DATE)
+#string(TIMESTAMP BUILD_DATE)
-add_custom_command (
+#add_custom_command(
+# OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/buildver-sgen.h
+# COMMAND echo "const char *build_date = \"${BUILD_DATE}\";" > ${CMAKE_CURRENT_BINARY_DIR}/buildver-sgen.h
+# VERBATIM
+#)
+add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/buildver-sgen.h
- COMMAND echo "const char *build_date = \"${BUILD_DATE}\";" > ${CMAKE_CURRENT_BINARY_DIR}/buildver-sgen.h
+ COMMAND echo "const char *build_date = \"\";" > ${CMAKE_CURRENT_BINARY_DIR}/buildver-sgen.h
VERBATIM
)
-add_custom_command (
+add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version.h
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/gen-version-h.sh ${CMAKE_CURRENT_SOURCE_DIR}/../..
VERBATIM
)
-add_custom_command (
+add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cpu-amd64.h
COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/genmdesc.py TARGET_AMD64 ${CMAKE_CURRENT_SOURCE_DIR} cpu-amd64.h amd64_desc ${CMAKE_CURRENT_SOURCE_DIR}/cpu-amd64.md
VERBATIM
)
-add_executable (mono-sgen "main-sgen.c")
-target_link_libraries (mono-sgen monosgen-static "-framework CoreFoundation" "-framework Foundation" "iconv" ${LLVM_LIBS})
-target_link_libraries (monosgen "-framework CoreFoundation" "-framework Foundation" "iconv" ${LLVM_LIBS})
+add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cpu-x86.h
+ COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/genmdesc.py TARGET_X86 ${CMAKE_CURRENT_SOURCE_DIR} cpu-x86.h x86_desc ${CMAKE_CURRENT_SOURCE_DIR}/cpu-x86.md
+ VERBATIM
+)
+
+add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cpu-arm64.h
+ COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/genmdesc.py TARGET_ARM64 ${CMAKE_CURRENT_SOURCE_DIR} cpu-arm64.h arm64_cpu_desc ${CMAKE_CURRENT_SOURCE_DIR}/cpu-arm64.md
+ VERBATIM
+)
+
+add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cpu-arm.h
+ COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/genmdesc.py TARGET_ARM ${CMAKE_CURRENT_SOURCE_DIR} cpu-arm.h arm_cpu_desc ${CMAKE_CURRENT_SOURCE_DIR}/cpu-arm.md
+ VERBATIM
+)
+
+if(NOT DISABLE_EXECUTABLES)
+set(CMAKE_SKIP_RPATH 1)
+add_executable(mono-sgen "main-sgen.c")
+target_link_libraries(mono-sgen monosgen-static ${OS_LIBS} "iconv" ${LLVM_LIBS} ${ICU_LIBS})
+if(ICU_LDFLAGS)
+ set_target_properties(mono-sgen monosgen PROPERTIES LINK_FLAGS ${ICU_LDFLAGS})
+endif()
+install(TARGETS mono-sgen RUNTIME)
+endif()
diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c
index 5e8d1d3ab734..5ca434fcf1be 100644
--- a/mono/mini/aot-compiler.c
+++ b/mono/mini/aot-compiler.c
@@ -3424,12 +3424,14 @@ get_shared_ginst_ref (MonoAotCompile *acfg, MonoGenericInst *ginst)
guint32 offset = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->ginst_blob_hash, ginst));
if (!offset) {
guint8 *buf2, *p2;
+ int len;
- buf2 = (guint8 *)g_malloc (1024);
+ len = 1024 + (ginst->type_argc * 32);
+ buf2 = (guint8 *)g_malloc (len);
p2 = buf2;
encode_ginst (acfg, ginst, p2, &p2);
- g_assert (p2 - buf2 < 1024);
+ g_assert (p2 - buf2 < len);
offset = add_to_blob (acfg, buf2, p2 - buf2);
g_free (buf2);
@@ -5191,6 +5193,17 @@ check_type_depth (MonoType *t, int depth)
static void
add_types_from_method_header (MonoAotCompile *acfg, MonoMethod *method);
+static gboolean
+inst_has_vtypes (MonoGenericInst *inst)
+{
+ for (int i = 0; i < inst->type_argc; ++i) {
+ MonoType *t = inst->type_argv [i];
+ if (MONO_TYPE_ISSTRUCT (t))
+ return TRUE;
+ }
+ return FALSE;
+}
+
/*
* add_generic_class:
*
@@ -5203,6 +5216,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
MonoClassField *field;
gpointer iter;
gboolean use_gsharedvt = FALSE;
+ gboolean use_gsharedvt_for_array = FALSE;
if (!acfg->ginst_hash)
acfg->ginst_hash = g_hash_table_new (NULL, NULL);
@@ -5246,6 +5260,18 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
(!strcmp (m_class_get_name (klass), "Dictionary`2") || !strcmp (m_class_get_name (klass), "List`1") || !strcmp (m_class_get_name (klass), "ReadOnlyCollection`1")))
use_gsharedvt = TRUE;
+#ifdef TARGET_WASM
+ /*
+ * Use gsharedvt for instances with vtype arguments.
+ * WASM only since other platforms depend on the
+ * previous behavior.
+ */
+ if ((acfg->jit_opts & MONO_OPT_GSHAREDVT) && mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst && is_vt_inst (mono_class_get_generic_class (klass)->context.class_inst)) {
+ use_gsharedvt = TRUE;
+ use_gsharedvt_for_array = TRUE;
+ }
+#endif
+
iter = NULL;
while ((method = mono_class_get_methods (klass, &iter))) {
if ((acfg->jit_opts & MONO_OPT_GSHAREDVT) && method->is_inflated && mono_method_get_context (method)->method_inst) {
@@ -5254,7 +5280,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
*/
continue;
}
-
+
if (mono_method_is_generic_sharable_full (method, FALSE, FALSE, use_gsharedvt)) {
/* Already added */
add_types_from_method_header (acfg, method);
@@ -5335,7 +5361,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth,
if (!strncmp (method->name, name_prefix, strlen (name_prefix))) {
MonoMethod *m = mono_aot_get_array_helper_from_wrapper (method);
- if (m->is_inflated && !mono_method_is_generic_sharable_full (m, FALSE, FALSE, FALSE))
+ if (m->is_inflated && !mono_method_is_generic_sharable_full (m, FALSE, FALSE, use_gsharedvt_for_array))
add_extra_method_with_depth (acfg, m, depth);
}
}
@@ -6605,6 +6631,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
case MONO_PATCH_INFO_ICALL_ADDR_CALL:
case MONO_PATCH_INFO_METHOD_RGCTX:
case MONO_PATCH_INFO_METHOD_CODE_SLOT:
+ case MONO_PATCH_INFO_METHOD_PINVOKE_ADDR_CACHE:
encode_method_ref (acfg, patch_info->data.method, p, &p);
break;
case MONO_PATCH_INFO_AOT_JIT_INFO:
@@ -8484,7 +8511,8 @@ can_encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
case MONO_PATCH_INFO_METHOD:
case MONO_PATCH_INFO_METHOD_FTNDESC:
case MONO_PATCH_INFO_METHODCONST:
- case MONO_PATCH_INFO_METHOD_CODE_SLOT: {
+ case MONO_PATCH_INFO_METHOD_CODE_SLOT:
+ case MONO_PATCH_INFO_METHOD_PINVOKE_ADDR_CACHE: {
MonoMethod *method = patch_info->data.method;
return can_encode_method (acfg, method);
diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c
index b42c76efba75..27d27add698c 100644
--- a/mono/mini/aot-runtime.c
+++ b/mono/mini/aot-runtime.c
@@ -3691,10 +3691,14 @@ mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
code1 = (guint8 *)methods [pos];
if (pos + 1 == methods_len) {
+#ifdef HOST_WASM
+ code2 = code1 + 1;
+#else
if (code1 >= amodule->jit_code_start && code1 < amodule->jit_code_end)
code2 = amodule->jit_code_end;
else
code2 = amodule->llvm_code_end;
+#endif
} else {
code2 = (guint8 *)methods [pos + 1];
}
@@ -3707,6 +3711,11 @@ mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
break;
}
+#ifdef HOST_WASM
+ if (addr != methods [pos])
+ return NULL;
+#endif
+
g_assert (addr >= methods [pos]);
if (pos + 1 < methods_len)
g_assert (addr < methods [pos + 1]);
@@ -3729,6 +3738,10 @@ mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
code = (guint8 *)amodule->methods [method_index];
ex_info = &amodule->blob [mono_aot_get_offset (amodule->ex_info_offsets, method_index)];
+#ifdef HOST_WASM
+ /* WASM methods have no length, can only look up the method address */
+ code_len = 1;
+#else
if (pos == methods_len - 1) {
if (code >= amodule->jit_code_start && code < amodule->jit_code_end)
code_len = amodule->jit_code_end - code;
@@ -3737,6 +3750,7 @@ mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
} else {
code_len = (guint8*)methods [pos + 1] - (guint8*)methods [pos];
}
+#endif
g_assert ((guint8*)code <= (guint8*)addr && (guint8*)addr < (guint8*)code + code_len);
@@ -3854,7 +3868,8 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
case MONO_PATCH_INFO_ICALL_ADDR:
case MONO_PATCH_INFO_ICALL_ADDR_CALL:
case MONO_PATCH_INFO_METHOD_RGCTX:
- case MONO_PATCH_INFO_METHOD_CODE_SLOT: {
+ case MONO_PATCH_INFO_METHOD_CODE_SLOT:
+ case MONO_PATCH_INFO_METHOD_PINVOKE_ADDR_CACHE: {
MethodRef ref;
gboolean res;
@@ -4518,6 +4533,20 @@ add_module_cb (gpointer key, gpointer value, gpointer user_data)
g_ptr_array_add ((GPtrArray*)user_data, value);
}
+static gboolean
+inst_is_private (MonoGenericInst *inst)
+{
+ for (int i = 0; i < inst->type_argc; ++i) {
+ MonoType *t = inst->type_argv [i];
+ if ((t->type == MONO_TYPE_CLASS || t->type == MONO_TYPE_VALUETYPE)) {
+ int access_level = mono_class_get_flags (t->data.klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
+ if (access_level == TYPE_ATTRIBUTE_NESTED_PRIVATE || access_level == TYPE_ATTRIBUTE_NOT_PUBLIC)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
gboolean
mono_aot_can_dedup (MonoMethod *method)
{
@@ -4543,9 +4572,16 @@ mono_aot_can_dedup (MonoMethod *method)
if (method->is_inflated && !mono_method_is_generic_sharable_full (method, TRUE, FALSE, FALSE) &&
!mini_is_gsharedvt_signature (mono_method_signature_internal (method)) &&
- !mini_is_gsharedvt_klass (method->klass))
+ !mini_is_gsharedvt_klass (method->klass)) {
+ MonoGenericContext *context = mono_method_get_context (method);
+ if (context->method_inst && mini_is_gsharedvt_inst (context->method_inst))
+ return FALSE;
+ /* No point in dedup-ing private instances */
+ if ((context->class_inst && inst_is_private (context->class_inst)) ||
+ (context->method_inst && inst_is_private (context->method_inst)))
+ return FALSE;
return TRUE;
-
+ }
return FALSE;
#else
gboolean not_normal_gshared = method->is_inflated && !mono_method_is_generic_sharable_full (method, TRUE, FALSE, FALSE);
diff --git a/mono/mini/cpu-amd64.md b/mono/mini/cpu-amd64.md
index 06abb8e7e0d7..e581a983944f 100644
--- a/mono/mini/cpu-amd64.md
+++ b/mono/mini/cpu-amd64.md
@@ -24,9 +24,9 @@
#
# len:number describe the maximun length in bytes of the instruction
# number is a positive integer. If the length is not specified
-# it defaults to zero. But lengths are only checked if the given opcode
-# is encountered during compilation. Some opcodes, like CONV_U4 are
-# transformed into other opcodes in the brg files, so they do not show up
+# it defaults to zero. But lengths are only checked if the given opcode
+# is encountered during compilation. Some opcodes, like CONV_U4 are
+# transformed into other opcodes in the brg files, so they do not show up
# during code generation.
#
# cost:number describe how many cycles are needed to complete the instruction (unused)
@@ -270,7 +270,7 @@ float_conv_to_u1: dest:i src1:f len:49
float_conv_to_i: dest:i src1:f len:49
float_conv_to_ovf_i: dest:a src1:f len:40
float_conv_to_ovd_u: dest:a src1:f len:40
-float_mul_ovf:
+float_mul_ovf:
float_ceq: dest:i src1:f src2:f len:35
float_cgt: dest:i src1:f src2:f len:35
float_cgt_un: dest:i src1:f src2:f len:48
@@ -711,11 +711,11 @@ unpack_highq: dest:x src1:x src2:x len:5 clob:1
unpack_highps: dest:x src1:x src2:x len:5 clob:1
unpack_highpd: dest:x src1:x src2:x len:5 clob:1
-packw: dest:x src1:x src2:x len:5 clob:1
-packd: dest:x src1:x src2:x len:5 clob:1
+packw: dest:x src1:x src2:x len:5 clob:1
+packd: dest:x src1:x src2:x len:5 clob:1
-packw_un: dest:x src1:x src2:x len:5 clob:1
-packd_un: dest:x src1:x src2:x len:6 clob:1
+packw_un: dest:x src1:x src2:x len:5 clob:1
+packd_un: dest:x src1:x src2:x len:6 clob:1
paddb_sat: dest:x src1:x src2:x len:5 clob:1
paddb_sat_un: dest:x src1:x src2:x len:5 clob:1
@@ -782,7 +782,7 @@ extract_i2: dest:i src1:x len:13
extract_u2: dest:i src1:x len:13
extract_i1: dest:i src1:x len:13
extract_u1: dest:i src1:x len:13
-extract_r8: dest:f src1:x len:5
+extract_r8: dest:f src1:x len:5
iconv_to_r4_raw: dest:f src1:i len:10
@@ -804,7 +804,7 @@ loadx_aligned_membase: dest:x src1:b len:7
storex_aligned_membase_reg: dest:b src1:x len:7
storex_nta_membase_reg: dest:b src1:x len:7
-fconv_to_r8_x: dest:x src1:f len:4
+fconv_to_r8_x: dest:x src1:f len:4
xconv_r8_to_i4: dest:y src1:x len:7
prefetch_membase: src1:b len:4
diff --git a/mono/mini/cpu-arm.md b/mono/mini/cpu-arm.md
index f3b6641d3f53..a58d4bb0e29b 100644
--- a/mono/mini/cpu-arm.md
+++ b/mono/mini/cpu-arm.md
@@ -130,8 +130,8 @@ storei2_membase_imm: dest:b len:20
storei2_membase_reg: dest:b src1:i len:12
storei4_membase_imm: dest:b len:20
storei4_membase_reg: dest:b src1:i len:20
-storei8_membase_imm: dest:b
-storei8_membase_reg: dest:b src1:i
+storei8_membase_imm: dest:b
+storei8_membase_reg: dest:b src1:i
storer4_membase_reg: dest:b src1:f len:60
storer8_membase_reg: dest:b src1:f len:24
store_memindex: dest:b src1:i src2:i len:4
diff --git a/mono/mini/cpu-mips.md b/mono/mini/cpu-mips.md
index cbe7788a6b0f..96920a0747b5 100644
--- a/mono/mini/cpu-mips.md
+++ b/mono/mini/cpu-mips.md
@@ -118,7 +118,7 @@ storei2_membase_imm: dest:b len:20
storei2_membase_reg: dest:b src1:i len:20
storei4_membase_imm: dest:b len:20
storei4_membase_reg: dest:b src1:i len:20
-storei8_membase_imm: dest:b
+storei8_membase_imm: dest:b
storei8_membase_reg: dest:b src1:i len:20
storer4_membase_reg: dest:b src1:f len:20
storer8_membase_reg: dest:b src1:f len:20
@@ -156,7 +156,7 @@ add_imm: dest:i src1:i len:12
sub_imm: dest:i src1:i len:12
mul_imm: dest:i src1:i len:20
# there is no actual support for division or reminder by immediate
-# we simulate them, though (but we need to change the burg rules
+# we simulate them, though (but we need to change the burg rules
# to allocate a symbolic reg for src2)
div_imm: dest:i src1:i src2:i len:20
div_un_imm: dest:i src1:i src2:i len:12
@@ -346,7 +346,7 @@ long_xor_imm: dest:i src1:i clob:1 len:4
lcompare: src1:i src2:i len:4
lcompare_imm: src1:i len:12
-long_conv_to_r_un: dest:f src1:i src2:i len:37
+long_conv_to_r_un: dest:f src1:i src2:i len:37
float_beq: len:16
float_bne_un: len:16
diff --git a/mono/mini/cpu-ppc.md b/mono/mini/cpu-ppc.md
index cb31d18c908c..6ef33f288722 100644
--- a/mono/mini/cpu-ppc.md
+++ b/mono/mini/cpu-ppc.md
@@ -137,7 +137,7 @@ add_imm: dest:i src1:i len:4
sub_imm: dest:i src1:i len:4
mul_imm: dest:i src1:i len:4
# there is no actual support for division or reminder by immediate
-# we simulate them, though (but we need to change the burg rules
+# we simulate them, though (but we need to change the burg rules
# to allocate a symbolic reg for src2)
div_imm: dest:i src1:i src2:i len:20
div_un_imm: dest:i src1:i src2:i len:12
@@ -164,8 +164,8 @@ cond_exc_no: len:8
cond_exc_c: len:12
cond_exc_nc: len:8
long_conv_to_ovf_i: dest:i src1:i src2:i len:32
-long_mul_ovf:
-long_conv_to_r_un: dest:f src1:i src2:i len:37
+long_mul_ovf:
+long_conv_to_r_un: dest:f src1:i src2:i len:37
float_beq: len:8
float_bne_un: len:8
float_blt: len:8
diff --git a/mono/mini/cpu-ppc64.md b/mono/mini/cpu-ppc64.md
index f0651f5f8d05..fc0e634baa46 100644
--- a/mono/mini/cpu-ppc64.md
+++ b/mono/mini/cpu-ppc64.md
@@ -141,7 +141,7 @@ add_imm: dest:i src1:i len:4
sub_imm: dest:i src1:i len:4
mul_imm: dest:i src1:i len:4
# there is no actual support for division or reminder by immediate
-# we simulate them, though (but we need to change the burg rules
+# we simulate them, though (but we need to change the burg rules
# to allocate a symbolic reg for src2)
div_imm: dest:i src1:i src2:i len:20
div_un_imm: dest:i src1:i src2:i len:12
diff --git a/mono/mini/cpu-s390x.md b/mono/mini/cpu-s390x.md
index 34295c32bde9..5db404947639 100644
--- a/mono/mini/cpu-s390x.md
+++ b/mono/mini/cpu-s390x.md
@@ -229,7 +229,7 @@ storei2_membase_reg: dest:b src1:i len:26
storei4_membase_imm: dest:b len:46
storei4_membase_reg: dest:b src1:i len:26
storei8_membase_imm: dest:b len:46
-storei8_membase_reg: dest:b src1:i len:26
+storei8_membase_reg: dest:b src1:i len:26
storer4_membase_reg: dest:b src1:f len:28
storer8_membase_reg: dest:b src1:f len:24
sub_imm: dest:i src1:i len:18
@@ -332,8 +332,8 @@ long_div: dest:i src1:i src2:i len:12
long_div_un: dest:i src1:i src2:i len:16
long_mul: dest:i src1:i src2:i len:12
long_mul_imm: dest:i src1:i len:20
-long_mul_ovf: dest:i src1:i src2:i len:56
-long_mul_ovf_un: dest:i src1:i src2:i len:64
+long_mul_ovf: dest:i src1:i src2:i len:56
+long_mul_ovf_un: dest:i src1:i src2:i len:64
long_and: dest:i src1:i src2:i len:8
long_or: dest:i src1:i src2:i len:8
long_xor: dest:i src1:i src2:i len:8
@@ -368,7 +368,7 @@ long_conv_to_u2: dest:i src1:i len:24
long_conv_to_u4: dest:i src1:i len:4
long_conv_to_u8: dest:i src1:i len:4
long_conv_to_u: dest:i src1:i len:4
-long_conv_to_r_un: dest:f src1:i len:37
+long_conv_to_r_un: dest:f src1:i len:37
long_beq: len:8
long_bge_un: len:8
@@ -399,7 +399,7 @@ int_conv_to_i: dest:i src1:i len:4
int_conv_to_u1: dest:i src1:i len:10
int_conv_to_u2: dest:i src1:i len:16
int_conv_to_u4: dest:i src1:i len:4
-int_conv_to_r_un: dest:f src1:i len:37
+int_conv_to_r_un: dest:f src1:i len:37
cond_exc_ic: len:8
cond_exc_ieq: len:8
@@ -431,9 +431,9 @@ vcall2_membase: src1:b len:12 clob:c
vcall2_reg: src1:i len:8 clob:c
s390_int_add_ovf: len:32 dest:i src1:i src2:i
-s390_int_add_ovf_un: len:32 dest:i src1:i src2:i
+s390_int_add_ovf_un: len:32 dest:i src1:i src2:i
s390_int_sub_ovf: len:32 dest:i src1:i src2:i
-s390_int_sub_ovf_un: len:32 dest:i src1:i src2:i
+s390_int_sub_ovf_un: len:32 dest:i src1:i src2:i
s390_long_add_ovf: dest:i src1:i src2:i len:32
s390_long_add_ovf_un: dest:i src1:i src2:i len:32
diff --git a/mono/mini/cpu-sparc.md b/mono/mini/cpu-sparc.md
index 341b11e5b348..403a73c380ee 100644
--- a/mono/mini/cpu-sparc.md
+++ b/mono/mini/cpu-sparc.md
@@ -263,8 +263,8 @@ long_shl: dest:i src1:i src2:i len:64
long_shr: dest:i src1:i src2:i len:64
long_shr_un: dest:i src1:i src2:i len:64
long_conv_to_ovf_i: dest:i src1:i src2:i len:48
-long_mul_ovf:
-long_conv_to_r_un: dest:f src1:i src2:i len:64
+long_mul_ovf:
+long_conv_to_r_un: dest:f src1:i src2:i len:64
long_shr_imm: dest:i src1:i len:64
long_shr_un_imm: dest:i src1:i len:64
long_shl_imm: dest:i src1:i len:64
diff --git a/mono/mini/cpu-x86.md b/mono/mini/cpu-x86.md
index 85e3ea7cf4ea..a0f0fc14f15d 100644
--- a/mono/mini/cpu-x86.md
+++ b/mono/mini/cpu-x86.md
@@ -25,9 +25,9 @@
#
# len:number describe the maximun length in bytes of the instruction
# number is a positive integer. If the length is not specified
-# it defaults to zero. But lengths are only checked if the given opcode
-# is encountered during compilation. Some opcodes, like CONV_U4 are
-# transformed into other opcodes in the brg files, so they do not show up
+# it defaults to zero. But lengths are only checked if the given opcode
+# is encountered during compilation. Some opcodes, like CONV_U4 are
+# transformed into other opcodes in the brg files, so they do not show up
# during code generation.
#
# cost:number describe how many cycles are needed to complete the instruction (unused)
@@ -180,8 +180,8 @@ storei2_membase_imm: dest:b len:11
storei2_membase_reg: dest:b src1:i len:7
storei4_membase_imm: dest:b len:10
storei4_membase_reg: dest:b src1:i len:7
-storei8_membase_imm: dest:b
-storei8_membase_reg: dest:b src1:i
+storei8_membase_imm: dest:b
+storei8_membase_reg: dest:b src1:i
storer4_membase_reg: dest:b src1:f len:7
storer8_membase_reg: dest:b src1:f len:7
load_membase: dest:i src1:b len:7
@@ -257,7 +257,7 @@ float_conv_to_u1: dest:y src1:f len:39
float_conv_to_i: dest:i src1:f len:39
float_conv_to_ovf_i: dest:a src1:f len:30
float_conv_to_ovd_u: dest:a src1:f len:30
-float_mul_ovf:
+float_mul_ovf:
float_ceq: dest:y src1:f src2:f len:25
float_cgt: dest:y src1:f src2:f len:25
float_cgt_un: dest:y src1:f src2:f len:37
@@ -425,7 +425,7 @@ cmov_ile_un: dest:i src1:i src2:i len:16 clob:1
cmov_ilt_un: dest:i src1:i src2:i len:16 clob:1
long_conv_to_ovf_i4_2: dest:i src1:i src2:i len:30
-long_conv_to_r8_2: dest:f src1:i src2:i len:14
+long_conv_to_r8_2: dest:f src1:i src2:i len:14
long_conv_to_r4_2: dest:f src1:i src2:i len:14
long_conv_to_r_un_2: dest:f src1:i src2:i len:40
@@ -565,11 +565,11 @@ unpack_highq: dest:x src1:x src2:x len:4 clob:1
unpack_highps: dest:x src1:x src2:x len:3 clob:1
unpack_highpd: dest:x src1:x src2:x len:4 clob:1
-packw: dest:x src1:x src2:x len:4 clob:1
-packd: dest:x src1:x src2:x len:4 clob:1
+packw: dest:x src1:x src2:x len:4 clob:1
+packd: dest:x src1:x src2:x len:4 clob:1
-packw_un: dest:x src1:x src2:x len:4 clob:1
-packd_un: dest:x src1:x src2:x len:5 clob:1
+packw_un: dest:x src1:x src2:x len:4 clob:1
+packd_un: dest:x src1:x src2:x len:5 clob:1
paddb_sat: dest:x src1:x src2:x len:4 clob:1
paddb_sat_un: dest:x src1:x src2:x len:4 clob:1
@@ -634,7 +634,7 @@ extract_i2: dest:i src1:x len:10
extract_u2: dest:i src1:x len:10
extract_i1: dest:i src1:x len:10
extract_u1: dest:i src1:x len:10
-extract_r8: dest:f src1:x len:8
+extract_r8: dest:f src1:x len:8
insert_i2: dest:x src1:x src2:i len:5 clob:1
@@ -653,7 +653,7 @@ loadx_aligned_membase: dest:x src1:b len:7
storex_aligned_membase_reg: dest:b src1:x len:7
storex_nta_membase_reg: dest:b src1:x len:7
-fconv_to_r8_x: dest:x src1:f len:14
+fconv_to_r8_x: dest:x src1:f len:14
xconv_r8_to_i4: dest:y src1:x len:7
prefetch_membase: src1:b len:4
diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c
index 5b6d729a3390..780332672fc6 100644
--- a/mono/mini/debugger-agent.c
+++ b/mono/mini/debugger-agent.c
@@ -4027,6 +4027,9 @@ process_event (EventKind event, gpointer arg, gint32 il_offset, MonoContext *ctx
DebuggerTlsData *tls;
tls = (DebuggerTlsData *)mono_native_tls_get_value (debugger_tls_id);
g_assert (tls);
+ // We are already processing a breakpoint event
+ if (tls->disable_breakpoints)
+ return;
mono_stopwatch_stop (&tls->step_time);
break;
}
diff --git a/mono/mini/helpers.c b/mono/mini/helpers.c
index eddfe646d78f..15cbd0a2277c 100644
--- a/mono/mini/helpers.c
+++ b/mono/mini/helpers.c
@@ -129,10 +129,8 @@ mono_disassemble_code (MonoCompile *cfg, guint8 *code, int size, char *id)
#ifdef HOST_WIN32
const char *tmp = g_get_tmp_dir ();
#endif
- char *objdump_args = g_getenv ("MONO_OBJDUMP_ARGS");
char *as_file;
char *o_file;
- char *cmd;
int unused G_GNUC_UNUSED;
#ifdef HOST_WIN32
@@ -260,9 +258,10 @@ mono_disassemble_code (MonoCompile *cfg, guint8 *code, int size, char *id)
#endif
#ifdef HAVE_SYSTEM
- cmd = g_strdup_printf (ARCH_PREFIX AS_CMD " %s -o %s", as_file, o_file);
+ char *cmd = g_strdup_printf (ARCH_PREFIX AS_CMD " %s -o %s", as_file, o_file);
unused = system (cmd);
g_free (cmd);
+ char *objdump_args = g_getenv ("MONO_OBJDUMP_ARGS");
if (!objdump_args)
objdump_args = g_strdup ("");
diff --git a/mono/mini/interp/interp-internals.h b/mono/mini/interp/interp-internals.h
index e3f3e04c8c9e..a08467100ee3 100644
--- a/mono/mini/interp/interp-internals.h
+++ b/mono/mini/interp/interp-internals.h
@@ -51,50 +51,10 @@ typedef gint64 mono_i;
#define MINT_TYPE_I MINT_TYPE_I8
#endif
-
-/*
- * GC SAFETY:
- *
- * The interpreter executes in gc unsafe (non-preempt) mode. On wasm, the C stack is
- * scannable but the wasm stack is not, so to make the code GC safe, the following rules
- * should be followed:
- * - every objref handled by the code needs to either be stored volatile or stored
- * into a volatile; volatile stores are stack packable, volatile values are not.
- * Use either OBJREF or stackval->data.o.
- * This will ensure the objects are pinned. A volatile local
- * is on the stack and not in registers. Volatile stores ditto.
- * - minimize the number of MonoObject* locals/arguments (or make them volatile).
- *
- * Volatile on a type/local forces all reads and writes to go to memory/stack,
- * and each such local to have a unique address.
- *
- * Volatile absence on a type/local allows multiple locals to share storage,
- * if their lifetimes do not overlap. This is called "stack packing".
- *
- * Volatile absence on a type/local allows the variable to live in
- * both stack and register, for fast reads and "write through".
- */
#ifdef TARGET_WASM
-
-#define WASM_VOLATILE volatile
-
-static inline MonoObject * WASM_VOLATILE *
-mono_interp_objref (MonoObject **o)
-{
- return o;
-}
-
-#define OBJREF(x) (*mono_interp_objref (&x))
-
-#else
-
-#define WASM_VOLATILE /* nothing */
-
-#define OBJREF(x) x
-
+#define INTERP_NO_STACK_SCAN 1
#endif
-
/*
* Value types are represented on the eval stack as pointers to the
* actual storage. A value type cannot be larger than 16 MB.
@@ -109,7 +69,12 @@ typedef struct {
} pair;
float f_r4;
double f;
- MonoObject * WASM_VOLATILE o;
+#ifdef INTERP_NO_STACK_SCAN
+ /* Ensure objref is always flushed to interp stack */
+ MonoObject * volatile o;
+#else
+ MonoObject *o;
+#endif
/* native size integer and pointer types */
gpointer p;
mono_u nati;
diff --git a/mono/mini/interp/interp.c b/mono/mini/interp/interp.c
index 53d20e1997c8..9cafe0736df5 100644
--- a/mono/mini/interp/interp.c
+++ b/mono/mini/interp/interp.c
@@ -1080,9 +1080,15 @@ interp_throw (ThreadContext *context, MonoException *ex, InterpFrame *frame, con
g_assert (context->has_resume_state);
}
+// We conservatively pin exception object here to avoid tweaking the
+// numerous call sites of this macro, even though, in a few cases,
+// this is not needed.
#define THROW_EX_GENERAL(exception,ex_ip, rethrow) \
do { \
- interp_throw (context, (exception), (frame), (ex_ip), (rethrow)); \
+ MonoException *__ex = (exception); \
+ MONO_HANDLE_ASSIGN_RAW (tmp_handle, (MonoObject*)__ex); \
+ interp_throw (context, __ex, (frame), (ex_ip), (rethrow)); \
+ MONO_HANDLE_ASSIGN_RAW (tmp_handle, (MonoObject*)NULL); \
goto resume; \
} while (0)
@@ -1146,12 +1152,12 @@ ves_array_calculate_index (MonoArray *ao, stackval *sp, gboolean safe)
guint32 pos = 0;
if (ao->bounds) {
for (gint32 i = 0; i < m_class_get_rank (ac); i++) {
- guint32 idx = sp [i].data.i;
- guint32 lower = ao->bounds [i].lower_bound;
+ gint32 idx = sp [i].data.i;
+ gint32 lower = ao->bounds [i].lower_bound;
guint32 len = ao->bounds [i].length;
- if (safe && (idx < lower || (idx - lower) >= len))
+ if (safe && (idx < lower || (guint32)(idx - lower) >= len))
return -1;
- pos = (pos * len) + idx - lower;
+ pos = (pos * len) + (guint32)(idx - lower);
}
} else {
pos = sp [0].data.i;
@@ -3264,11 +3270,10 @@ mono_interp_box_nullable (InterpFrame* frame, const guint16* ip, stackval* sp, M
}
static int
-mono_interp_box_vt (InterpFrame* frame, const guint16* ip, stackval* sp)
+mono_interp_box_vt (InterpFrame* frame, const guint16* ip, stackval* sp, MonoObjectHandle tmp_handle)
{
InterpMethod* const imethod = frame->imethod;
- MonoObject* o; // See the comment about GC safety.
MonoVTable * const vtable = (MonoVTable*)imethod->data_items [ip [1]];
MonoClass* const c = vtable->klass;
@@ -3277,26 +3282,27 @@ mono_interp_box_vt (InterpFrame* frame, const guint16* ip, stackval* sp)
guint16 offset = ip [2];
guint16 pop_vt_sp = !ip [3];
- OBJREF (o) = mono_gc_alloc_obj (vtable, m_class_get_instance_size (vtable->klass));
+ MonoObject* o = mono_gc_alloc_obj (vtable, m_class_get_instance_size (vtable->klass));
+ MONO_HANDLE_ASSIGN_RAW (tmp_handle, o);
mono_value_copy_internal (mono_object_get_data (o), sp [-1 - offset].data.p, c);
+ MONO_HANDLE_ASSIGN_RAW (tmp_handle, NULL);
- sp [-1 - offset].data.p = o;
+ sp [-1 - offset].data.o = o;
return pop_vt_sp ? ALIGN_TO (size, MINT_VT_ALIGNMENT) : 0;
}
static void
-mono_interp_box (InterpFrame* frame, const guint16* ip, stackval* sp)
+mono_interp_box (InterpFrame* frame, const guint16* ip, stackval* sp, MonoObjectHandle tmp_handle)
{
- MonoObject *o; // See the comment about GC safety.
MonoVTable * const vtable = (MonoVTable*)frame->imethod->data_items [ip [1]];
-
- OBJREF (o) = mono_gc_alloc_obj (vtable, m_class_get_instance_size (vtable->klass));
-
guint16 const offset = ip [2];
+ MonoObject *o = mono_gc_alloc_obj (vtable, m_class_get_instance_size (vtable->klass));
+ MONO_HANDLE_ASSIGN_RAW (tmp_handle, o);
stackval_to_data (m_class_get_byval_arg (vtable->klass), &sp [-1 - offset], mono_object_get_data (o), FALSE);
+ MONO_HANDLE_ASSIGN_RAW (tmp_handle, NULL);
- sp [-1 - offset].data.p = o;
+ sp [-1 - offset].data.o = o;
}
static int
@@ -3436,6 +3442,24 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs
};
#endif
+ HANDLE_FUNCTION_ENTER ();
+ /*
+ * GC SAFETY:
+ *
+ * The interpreter executes in gc unsafe (non-preempt) mode. On wasm, we cannot rely on
+ * scanning the stack or any registers. In order to make the code GC safe, every objref
+ * handled by the code needs to be kept alive and pinned in any of the following ways:
+ * - the object needs to be stored on the interpreter stack. In order to make sure the
+ * object actually gets stored on the interp stack and the store is not optimized out,
+ * the store/variable should be volatile.
+ * - if the execution of an opcode requires an object not coming from interp stack to be
+ * kept alive, the tmp_handle below can be used. This handle will keep only one object
+ * pinned by the GC. Ideally, once this object is no longer needed, the handle should be
+ * cleared. If we will need to have more objects pinned simultaneously, additional handles
+ * can be reserved here.
+ */
+ MonoObjectHandle tmp_handle = MONO_HANDLE_NEW (MonoObject, NULL);
+
if (method_entry (context, frame,
#if DEBUG_INTERP
&tracing,
@@ -3823,6 +3847,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs
frame->state.ip = ip + 6;
ves_pinvoke_method (csignature, (MonoFuncV)code, context, frame, &retval, save_last_error, cache, sp);
+ EXCEPTION_CHECKPOINT_GC_UNSAFE;
CHECK_RESUME_STATE (context);
if (csignature->ret->type != MONO_TYPE_VOID) {
@@ -5123,7 +5148,6 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs
MINT_IN_CASE(MINT_NEWOBJ_FAST) {
MonoVTable *vtable = (MonoVTable*) frame->imethod->data_items [ip [3]];
INIT_VTABLE (vtable);
- MonoObject *o; // See the comment about GC safety.
guint16 param_count;
guint16 imethod_index = ip [1];
@@ -5137,7 +5161,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs
memmove (sp + 2, sp, param_count * sizeof (stackval));
}
- OBJREF (o) = mono_gc_alloc_obj (vtable, m_class_get_instance_size (vtable->klass));
+ MonoObject *o = mono_gc_alloc_obj (vtable, m_class_get_instance_size (vtable->klass));
if (G_UNLIKELY (!o)) {
mono_error_set_out_of_memory (error, "Could not allocate %i bytes", m_class_get_instance_size (vtable->klass));
THROW_EX (mono_error_convert_to_exception (error), ip);
@@ -5241,13 +5265,13 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs
THROW_EX (exc, ip);
}
error_init_reuse (error);
- MonoObject* o = NULL; // See the comment about GC safety.
- OBJREF (o) = mono_object_new_checked (domain, newobj_class, error);
+ MonoObject* o = mono_object_new_checked (domain, newobj_class, error);
+ sp [0].data.o = o; // return value
+ sp [1].data.o = o; // first parameter
+
mono_error_cleanup (error); // FIXME: do not swallow the error
error_init_reuse (error);
EXCEPTION_CHECKPOINT;
- sp [0].data.o = o; // return value
- sp [1].data.o = o; // first parameter
#ifndef DISABLE_REMOTING
if (mono_object_is_transparent_proxy (o)) {
MonoMethod *remoting_invoke_method = mono_marshal_get_remoting_invoke_with_check (cmethod->method, error);
@@ -5946,12 +5970,12 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs
MINT_IN_BREAK;
}
MINT_IN_CASE(MINT_BOX) {
- mono_interp_box (frame, ip, sp);
+ mono_interp_box (frame, ip, sp, tmp_handle);
ip += 3;
MINT_IN_BREAK;
}
MINT_IN_CASE(MINT_BOX_VT) {
- vt_sp -= mono_interp_box_vt (frame, ip, sp);
+ vt_sp -= mono_interp_box_vt (frame, ip, sp, tmp_handle);
ip += 4;
MINT_IN_BREAK;
}
@@ -6078,12 +6102,12 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs
g_assert (ao->bounds);
guint32 pos = 0;
for (int i = 0; i < rank; i++) {
- guint32 idx = sp [i].data.i;
- guint32 lower = ao->bounds [i].lower_bound;
+ gint32 idx = sp [i].data.i;
+ gint32 lower = ao->bounds [i].lower_bound;
guint32 len = ao->bounds [i].length;
- if (idx < lower || (idx - lower) >= len)
+ if (idx < lower || (guint32)(idx - lower) >= len)
THROW_EX (mono_get_exception_index_out_of_range (), ip);
- pos = (pos * len) + idx - lower;
+ pos = (pos * len) + (guint32)(idx - lower);
}
sp [-1].data.p = mono_array_addr_with_size_fast (ao, esize, pos);
@@ -7381,6 +7405,8 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs
context->stack_pointer = (guchar*)frame->stack;
DEBUG_LEAVE ();
+
+ HANDLE_FUNCTION_RETURN ();
}
static void
diff --git a/mono/mini/interp/mintops.h b/mono/mini/interp/mintops.h
index 4a6f760f3b50..fe264b58ff6f 100644
--- a/mono/mini/interp/mintops.h
+++ b/mono/mini/interp/mintops.h
@@ -59,6 +59,8 @@ typedef enum {
#define MINT_IS_MOVLOC(op) ((op) >= MINT_MOVLOC_1 && (op) <= MINT_MOVLOC_VT)
#define MINT_IS_STLOC_NP(op) ((op) >= MINT_STLOC_NP_I4 && (op) <= MINT_STLOC_NP_O)
#define MINT_IS_CONDITIONAL_BRANCH(op) ((op) >= MINT_BRFALSE_I4 && (op) <= MINT_BLT_UN_R8_S)
+#define MINT_IS_UNOP_CONDITIONAL_BRANCH(op) ((op) >= MINT_BRFALSE_I4 && (op) <= MINT_BRTRUE_R8_S)
+#define MINT_IS_BINOP_CONDITIONAL_BRANCH(op) ((op) >= MINT_BEQ_I4 && (op) <= MINT_BLT_UN_R8_S)
#define MINT_IS_CALL(op) ((op) >= MINT_CALL && (op) <= MINT_JIT_CALL)
#define MINT_IS_PATCHABLE_CALL(op) ((op) >= MINT_CALL && (op) <= MINT_VCALL)
#define MINT_IS_NEWOBJ(op) ((op) >= MINT_NEWOBJ && (op) <= MINT_NEWOBJ_MAGIC)
diff --git a/mono/mini/interp/transform.c b/mono/mini/interp/transform.c
index 1fd13dd4bec3..e35976db2640 100644
--- a/mono/mini/interp/transform.c
+++ b/mono/mini/interp/transform.c
@@ -326,6 +326,51 @@ interp_prev_ins (InterpInst *ins)
#endif
+#define SET_SIMPLE_TYPE(s, ty) \
+ do { \
+ (s)->type = (ty); \
+ (s)->flags = 0; \
+ (s)->klass = NULL; \
+ } while (0)
+
+#define SET_TYPE(s, ty, k) \
+ do { \
+ (s)->type = (ty); \
+ (s)->flags = 0; \
+ (s)->klass = k; \
+ } while (0)
+
+#define REALLOC_STACK(td, sppos) \
+ do { \
+ (td)->stack_capacity *= 2; \
+ (td)->stack = (StackInfo*)realloc ((td)->stack, (td)->stack_capacity * sizeof (td->stack [0])); \
+ (td)->sp = (td)->stack + (sppos); \
+ } while (0);
+
+#define PUSH_SIMPLE_TYPE(td, ty) \
+ do { \
+ int sp_height; \
+ (td)->sp++; \
+ sp_height = (td)->sp - (td)->stack; \
+ if (sp_height > (td)->max_stack_height) \
+ (td)->max_stack_height = sp_height; \
+ if (sp_height > (td)->stack_capacity) \
+ REALLOC_STACK(td, sp_height); \
+ SET_SIMPLE_TYPE((td)->sp - 1, ty); \
+ } while (0)
+
+#define PUSH_TYPE(td, ty, k) \
+ do { \
+ int sp_height; \
+ (td)->sp++; \
+ sp_height = (td)->sp - (td)->stack; \
+ if (sp_height > (td)->max_stack_height) \
+ (td)->max_stack_height = sp_height; \
+ if (sp_height > (td)->stack_capacity) \
+ REALLOC_STACK(td, sp_height); \
+ SET_TYPE((td)->sp - 1, ty, k); \
+ } while (0)
+
static void
handle_branch (TransformData *td, int short_op, int long_op, int offset)
@@ -376,23 +421,31 @@ two_arg_branch(TransformData *td, int mint_op, int offset)
{
int type1 = td->sp [-1].type == STACK_TYPE_O || td->sp [-1].type == STACK_TYPE_MP ? STACK_TYPE_I : td->sp [-1].type;
int type2 = td->sp [-2].type == STACK_TYPE_O || td->sp [-2].type == STACK_TYPE_MP ? STACK_TYPE_I : td->sp [-2].type;
- int long_op = mint_op + type1 - STACK_TYPE_I4;
- int short_op = long_op + MINT_BEQ_I4_S - MINT_BEQ_I4;
CHECK_STACK(td, 2);
+
if (type1 == STACK_TYPE_I4 && type2 == STACK_TYPE_I8) {
// The il instruction starts with the actual branch, and not with the conversion opcodes
interp_insert_ins (td, td->last_ins, MINT_CONV_I8_I4);
+ SET_SIMPLE_TYPE (td->sp - 1, STACK_TYPE_I8);
+ type1 = STACK_TYPE_I8;
} else if (type1 == STACK_TYPE_I8 && type2 == STACK_TYPE_I4) {
interp_insert_ins (td, td->last_ins, MINT_CONV_I8_I4_SP);
+ SET_SIMPLE_TYPE (td->sp - 2, STACK_TYPE_I8);
} else if (type1 == STACK_TYPE_R4 && type2 == STACK_TYPE_R8) {
interp_insert_ins (td, td->last_ins, MINT_CONV_R8_R4);
+ SET_SIMPLE_TYPE (td->sp - 1, STACK_TYPE_R8);
+ type1 = STACK_TYPE_R8;
} else if (type1 == STACK_TYPE_R8 && type2 == STACK_TYPE_R4) {
interp_insert_ins (td, td->last_ins, MINT_CONV_R8_R4_SP);
+ SET_SIMPLE_TYPE (td->sp - 2, STACK_TYPE_R8);
} else if (type1 != type2) {
g_warning("%s.%s: branch type mismatch %d %d",
m_class_get_name (td->method->klass), td->method->name,
td->sp [-1].type, td->sp [-2].type);
}
+
+ int long_op = mint_op + type1 - STACK_TYPE_I4;
+ int short_op = long_op + MINT_BEQ_I4_S - MINT_BEQ_I4;
td->sp -= 2;
handle_branch (td, short_op, long_op, offset);
}
@@ -470,51 +523,6 @@ can_store (int st_value, int vt_value)
return st_value == vt_value;
}
-#define SET_SIMPLE_TYPE(s, ty) \
- do { \
- (s)->type = (ty); \
- (s)->flags = 0; \
- (s)->klass = NULL; \
- } while (0)
-
-#define SET_TYPE(s, ty, k) \
- do { \
- (s)->type = (ty); \
- (s)->flags = 0; \
- (s)->klass = k; \
- } while (0)
-
-#define REALLOC_STACK(td, sppos) \
- do { \
- (td)->stack_capacity *= 2; \
- (td)->stack = (StackInfo*)realloc ((td)->stack, (td)->stack_capacity * sizeof (td->stack [0])); \
- (td)->sp = (td)->stack + (sppos); \
- } while (0);
-
-#define PUSH_SIMPLE_TYPE(td, ty) \
- do { \
- int sp_height; \
- (td)->sp++; \
- sp_height = (td)->sp - (td)->stack; \
- if (sp_height > (td)->max_stack_height) \
- (td)->max_stack_height = sp_height; \
- if (sp_height > (td)->stack_capacity) \
- REALLOC_STACK(td, sp_height); \
- SET_SIMPLE_TYPE((td)->sp - 1, ty); \
- } while (0)
-
-#define PUSH_TYPE(td, ty, k) \
- do { \
- int sp_height; \
- (td)->sp++; \
- sp_height = (td)->sp - (td)->stack; \
- if (sp_height > (td)->max_stack_height) \
- (td)->max_stack_height = sp_height; \
- if (sp_height > (td)->stack_capacity) \
- REALLOC_STACK(td, sp_height); \
- SET_TYPE((td)->sp - 1, ty, k); \
- } while (0)
-
static void
move_stack (TransformData *td, int start, int amount)
{
@@ -988,18 +996,15 @@ interp_method_get_header (MonoMethod* method, MonoError *error)
static void
emit_store_value_as_local (TransformData *td, MonoType *src)
{
- int size = mini_magic_type_size (NULL, src);
int local = create_interp_local (td, mini_native_type_replace_type (src));
store_local (td, local);
- size = ALIGN_TO (size, MINT_VT_ALIGNMENT);
- interp_add_ins (td, MINT_LDLOC_VT);
+ interp_add_ins (td, MINT_LDLOCA_S);
td->last_ins->data [0] = local;
- WRITE32_INS (td->last_ins, 1, &size);
+ td->locals [local].indirects++;
- PUSH_VT (td, size);
- PUSH_TYPE (td, STACK_TYPE_VT, NULL);
+ PUSH_SIMPLE_TYPE (td, STACK_TYPE_MP);
}
// Returns whether we can optimize away the instructions starting at start.
@@ -1200,9 +1205,11 @@ interp_emit_ldelema (TransformData *td, MonoClass *array_class, MonoClass *check
int rank = m_class_get_rank (array_class);
int size = mono_class_array_element_size (element_class);
+ gboolean bounded = m_class_get_byval_arg (array_class) ? m_class_get_byval_arg (array_class)->type == MONO_TYPE_ARRAY : FALSE;
+
// We only need type checks when writing to array of references
if (!check_class || m_class_is_valuetype (element_class)) {
- if (rank == 1) {
+ if (rank == 1 && !bounded) {
interp_add_ins (td, MINT_LDELEMA1);
WRITE32_INS (td->last_ins, 0, &size);
} else {
@@ -1367,10 +1374,11 @@ interp_handle_magic_type_intrinsics (TransformData *td, MonoMethod *target_metho
return TRUE;
} else if (!strcmp ("CompareTo", tm) || !strcmp ("Equals", tm)) {
MonoType *arg = csignature->params [0];
+ int mt = mint_type (arg);
/* on 'System.n*::{CompareTo,Equals} (System.n*)' variant we need to push managed
* pointer instead of value */
- if (arg->type == MONO_TYPE_VALUETYPE)
+ if (mt != MINT_TYPE_O)
emit_store_value_as_local (td, arg);
/* emit call to managed conversion method */
@@ -4941,6 +4949,20 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
klass = mini_get_class (method, token, generic_context);
CHECK_TYPELOAD (klass);
+ // Common in generic code:
+ // box T + unbox.any T -> nop
+ if ((td->last_ins->opcode == MINT_BOX || td->last_ins->opcode == MINT_BOX_VT) &&
+ (td->sp - 1)->klass == klass && !td->is_bb_start[in_offset]) {
+ gboolean is_vt = td->last_ins->opcode == MINT_BOX_VT;
+ interp_clear_ins(td, td->last_ins);
+ if (is_vt)
+ PUSH_VT(td, mono_class_value_size(klass, NULL));
+ int mt = mint_type(m_class_get_byval_arg(klass));
+ SET_TYPE(td->sp - 1, stack_type[mt], klass);
+ td->ip += 5;
+ break;
+ }
+
if (mini_type_is_reference (m_class_get_byval_arg (klass))) {
int mt = mint_type (m_class_get_byval_arg (klass));
interp_handle_isinst (td, klass, FALSE);
@@ -6111,12 +6133,24 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
}
case CEE_MONO_LDPTR:
case CEE_MONO_CLASSCONST:
+ case CEE_MONO_METHODCONST:
token = read32 (td->ip + 1);
td->ip += 5;
interp_add_ins (td, MINT_MONO_LDPTR);
td->last_ins->data [0] = get_data_item_index (td, mono_method_get_wrapper_data (method, token));
PUSH_SIMPLE_TYPE (td, STACK_TYPE_I);
break;
+ case CEE_MONO_PINVOKE_ADDR_CACHE: {
+ token = read32 (td->ip + 1);
+ td->ip += 5;
+ interp_add_ins (td, MINT_MONO_LDPTR);
+ g_assert (method->wrapper_type != MONO_WRAPPER_NONE);
+ /* This is a memory slot used by the wrapper */
+ gpointer addr = mono_domain_alloc0 (td->rtm->domain, sizeof (gpointer));
+ td->last_ins->data [0] = get_data_item_index (td, addr);
+ PUSH_SIMPLE_TYPE (td, STACK_TYPE_I);
+ break;
+ }
case CEE_MONO_OBJADDR:
CHECK_STACK (td, 1);
++td->ip;
@@ -7138,6 +7172,42 @@ interp_fold_unop (TransformData *td, StackContentInfo *sp, InterpInst *ins)
return ins;
}
+#define INTERP_FOLD_UNOP_BR(_opcode,_stack_type,_cond) \
+ case _opcode: \
+ g_assert (sp->val.type == _stack_type); \
+ if (_cond) \
+ ins->opcode = MINT_BR_S; \
+ else \
+ interp_clear_ins (td, ins); \
+ break;
+
+static InterpInst*
+interp_fold_unop_cond_br (TransformData *td, StackContentInfo *sp, InterpInst *ins)
+{
+ sp--;
+ // If we can't remove the instruction pushing the constant, don't bother
+ if (sp->ins == NULL)
+ return ins;
+ if (sp->val.type != STACK_VALUE_I4 && sp->val.type != STACK_VALUE_I8)
+ return ins;
+ // Top of the stack is a constant
+ switch (ins->opcode) {
+ INTERP_FOLD_UNOP_BR (MINT_BRFALSE_I4_S, STACK_VALUE_I4, sp [0].val.i == 0);
+ INTERP_FOLD_UNOP_BR (MINT_BRFALSE_I8_S, STACK_VALUE_I8, sp [0].val.l == 0);
+ INTERP_FOLD_UNOP_BR (MINT_BRTRUE_I4_S, STACK_VALUE_I4, sp [0].val.i != 0);
+ INTERP_FOLD_UNOP_BR (MINT_BRTRUE_I8_S, STACK_VALUE_I8, sp [0].val.l != 0);
+
+ default:
+ return ins;
+ }
+
+ mono_interp_stats.constant_folds++;
+ mono_interp_stats.killed_instructions++;
+ interp_clear_ins (td, sp->ins);
+ sp->val.type = STACK_VALUE_NONE;
+ return ins;
+}
+
#define INTERP_FOLD_BINOP(opcode,stack_type,field,op) \
case opcode: \
g_assert (sp [0].val.type == stack_type && sp [1].val.type == stack_type); \
@@ -7272,6 +7342,63 @@ interp_fold_binop (TransformData *td, StackContentInfo *sp, InterpInst *ins)
return ins;
}
+#define INTERP_FOLD_BINOP_BR(_opcode,_stack_type,_cond) \
+ case _opcode: \
+ g_assert (sp [0].val.type == _stack_type); \
+ g_assert (sp [1].val.type == _stack_type); \
+ if (_cond) \
+ ins->opcode = MINT_BR_S; \
+ else \
+ interp_clear_ins (td, ins); \
+ break;
+
+static InterpInst*
+interp_fold_binop_cond_br (TransformData *td, StackContentInfo *sp, InterpInst *ins)
+{
+ sp -= 2;
+ // If we can't remove the instructions pushing the constants, don't bother
+ if (sp [0].ins == NULL || sp [1].ins == NULL)
+ return ins;
+ if (sp [0].val.type != STACK_VALUE_I4 && sp [0].val.type != STACK_VALUE_I8)
+ return ins;
+ if (sp [1].val.type != STACK_VALUE_I4 && sp [1].val.type != STACK_VALUE_I8)
+ return ins;
+
+ switch (ins->opcode) {
+ INTERP_FOLD_BINOP_BR (MINT_BEQ_I4_S, STACK_VALUE_I4, sp [0].val.i == sp [1].val.i);
+ INTERP_FOLD_BINOP_BR (MINT_BEQ_I8_S, STACK_VALUE_I8, sp [0].val.l == sp [1].val.l);
+ INTERP_FOLD_BINOP_BR (MINT_BGE_I4_S, STACK_VALUE_I4, sp [0].val.i >= sp [1].val.i);
+ INTERP_FOLD_BINOP_BR (MINT_BGE_I8_S, STACK_VALUE_I8, sp [0].val.l >= sp [1].val.l);
+ INTERP_FOLD_BINOP_BR (MINT_BGT_I4_S, STACK_VALUE_I4, sp [0].val.i > sp [1].val.i);
+ INTERP_FOLD_BINOP_BR (MINT_BGT_I8_S, STACK_VALUE_I8, sp [0].val.l > sp [1].val.l);
+ INTERP_FOLD_BINOP_BR (MINT_BLT_I4_S, STACK_VALUE_I4, sp [0].val.i < sp [1].val.i);
+ INTERP_FOLD_BINOP_BR (MINT_BLT_I8_S, STACK_VALUE_I8, sp [0].val.l < sp [1].val.l);
+ INTERP_FOLD_BINOP_BR (MINT_BLE_I4_S, STACK_VALUE_I4, sp [0].val.i <= sp [1].val.i);
+ INTERP_FOLD_BINOP_BR (MINT_BLE_I8_S, STACK_VALUE_I8, sp [0].val.l <= sp [1].val.l);
+
+ INTERP_FOLD_BINOP_BR (MINT_BNE_UN_I4_S, STACK_VALUE_I4, sp [0].val.i != sp [1].val.i);
+ INTERP_FOLD_BINOP_BR (MINT_BNE_UN_I8_S, STACK_VALUE_I8, sp [0].val.l != sp [1].val.l);
+ INTERP_FOLD_BINOP_BR (MINT_BGE_UN_I4_S, STACK_VALUE_I4, (guint32)sp [0].val.i >= (guint32)sp [1].val.i);
+ INTERP_FOLD_BINOP_BR (MINT_BGE_UN_I8_S, STACK_VALUE_I8, (guint64)sp [0].val.l >= (guint64)sp [1].val.l);
+ INTERP_FOLD_BINOP_BR (MINT_BGT_UN_I4_S, STACK_VALUE_I4, (guint32)sp [0].val.i > (guint32)sp [1].val.i);
+ INTERP_FOLD_BINOP_BR (MINT_BGT_UN_I8_S, STACK_VALUE_I8, (guint64)sp [0].val.l > (guint64)sp [1].val.l);
+ INTERP_FOLD_BINOP_BR (MINT_BLE_UN_I4_S, STACK_VALUE_I4, (guint32)sp [0].val.i <= (guint32)sp [1].val.i);
+ INTERP_FOLD_BINOP_BR (MINT_BLE_UN_I8_S, STACK_VALUE_I8, (guint64)sp [0].val.l <= (guint64)sp [1].val.l);
+ INTERP_FOLD_BINOP_BR (MINT_BLT_UN_I4_S, STACK_VALUE_I4, (guint32)sp [0].val.i < (guint32)sp [1].val.i);
+ INTERP_FOLD_BINOP_BR (MINT_BLT_UN_I8_S, STACK_VALUE_I8, (guint64)sp [0].val.l < (guint64)sp [1].val.l);
+
+ default:
+ return ins;
+ }
+ mono_interp_stats.constant_folds++;
+ mono_interp_stats.killed_instructions += 2;
+ interp_clear_ins (td, sp [0].ins);
+ interp_clear_ins (td, sp [1].ins);
+ sp [0].val.type = STACK_VALUE_NONE;
+ sp [1].val.type = STACK_VALUE_NONE;
+ return ins;
+}
+
static gboolean
interp_local_equal (StackValue *locals, int local1, int local2)
{
@@ -7371,36 +7498,40 @@ interp_cprop (TransformData *td)
mono_interp_stats.killed_instructions++;
}
}
- } else if (locals [loaded_local].type == STACK_VALUE_LOCAL) {
- g_assert (!td->locals [loaded_local].indirects);
- // do copy propagation of the original source
- mono_interp_stats.copy_propagations++;
- local_ref_count [loaded_local]--;
- // We can't propagate a local that has its address taken
- g_assert (!td->locals [locals [loaded_local].local].indirects);
- ins->data [0] = locals [loaded_local].local;
- local_ref_count [ins->data [0]]++;
- if (td->verbose_level) {
- g_print ("cprop loc %d -> loc %d :\n\t", loaded_local, locals [loaded_local].local);
- dump_interp_inst_newline (ins);
- }
- } else if (locals [loaded_local].type == STACK_VALUE_I4 || locals [loaded_local].type == STACK_VALUE_I8) {
- gboolean is_i4 = locals [loaded_local].type == STACK_VALUE_I4;
- g_assert (!td->locals [loaded_local].indirects);
- if (is_i4)
- ins = interp_get_ldc_i4_from_const (td, ins, locals [loaded_local].i);
- else
- ins = interp_inst_replace_with_i8_const (td, ins, locals [loaded_local].l);
- sp->ins = ins;
- sp->val = locals [loaded_local];
- local_ref_count [loaded_local]--;
- mono_interp_stats.copy_propagations++;
- if (td->verbose_level) {
- g_print ("cprop loc %d -> ct :\n\t", loaded_local);
- dump_interp_inst_newline (ins);
+ }
+ /* If we didn't replace this ldloc with a stloc.np, try other optimizations */
+ if (!replace_op) {
+ if (locals [loaded_local].type == STACK_VALUE_LOCAL) {
+ g_assert (!td->locals [loaded_local].indirects);
+ // do copy propagation of the original source
+ mono_interp_stats.copy_propagations++;
+ local_ref_count [loaded_local]--;
+ // We can't propagate a local that has its address taken
+ g_assert (!td->locals [locals [loaded_local].local].indirects);
+ ins->data [0] = locals [loaded_local].local;
+ local_ref_count [ins->data [0]]++;
+ if (td->verbose_level) {
+ g_print ("cprop loc %d -> loc %d :\n\t", loaded_local, locals [loaded_local].local);
+ dump_interp_inst_newline (ins);
+ }
+ } else if (locals [loaded_local].type == STACK_VALUE_I4 || locals [loaded_local].type == STACK_VALUE_I8) {
+ gboolean is_i4 = locals [loaded_local].type == STACK_VALUE_I4;
+ g_assert (!td->locals [loaded_local].indirects);
+ if (is_i4)
+ ins = interp_get_ldc_i4_from_const (td, ins, locals [loaded_local].i);
+ else
+ ins = interp_inst_replace_with_i8_const (td, ins, locals [loaded_local].l);
+ sp->ins = ins;
+ sp->val = locals [loaded_local];
+ local_ref_count [loaded_local]--;
+ mono_interp_stats.copy_propagations++;
+ if (td->verbose_level) {
+ g_print ("cprop loc %d -> ct :\n\t", loaded_local);
+ dump_interp_inst_newline (ins);
+ }
+ // FIXME this replace_op got ugly
+ replace_op = ins->opcode;
}
- // FIXME this replace_op got ugly
- replace_op = ins->opcode;
}
if (!replace_op) {
// Save the ldloc on the stack if it wasn't optimized away
@@ -7568,9 +7699,16 @@ interp_cprop (TransformData *td)
} else if (ins->opcode == MINT_CASTCLASS || ins->opcode == MINT_CASTCLASS_COMMON || ins->opcode == MINT_CASTCLASS_INTERFACE) {
// Keep the value on the stack, but prevent optimizing away
sp [-1].ins = NULL;
- } else if (MINT_IS_CONDITIONAL_BRANCH (ins->opcode)) {
- sp -= pop;
- g_assert (push == 0);
+ } else if (MINT_IS_UNOP_CONDITIONAL_BRANCH (ins->opcode)) {
+ ins = interp_fold_unop_cond_br (td, sp, ins);
+ sp--;
+ // We can't clear any instruction that pushes the stack, because the
+ // branched code will expect a certain stack size.
+ for (StackContentInfo *sp_iter = stack; sp_iter < sp; sp_iter++)
+ sp_iter->ins = NULL;
+ } else if (MINT_IS_BINOP_CONDITIONAL_BRANCH (ins->opcode)) {
+ ins = interp_fold_binop_cond_br (td, sp, ins);
+ sp -= 2;
// We can't clear any instruction that pushes the stack, because the
// branched code will expect a certain stack size.
for (StackContentInfo *sp_iter = stack; sp_iter < sp; sp_iter++)
diff --git a/mono/mini/intrinsics.c b/mono/mini/intrinsics.c
index cf8bcc936aaa..912e12e427d6 100644
--- a/mono/mini/intrinsics.c
+++ b/mono/mini/intrinsics.c
@@ -31,7 +31,7 @@ emit_array_generic_access (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst
MonoClass *eklass = mono_class_from_mono_type_internal (fsig->params [1]);
/* the bounds check is already done by the callers */
- addr = mini_emit_ldelema_1_ins (cfg, eklass, args [0], args [1], FALSE);
+ addr = mini_emit_ldelema_1_ins (cfg, eklass, args [0], args [1], FALSE, FALSE);
MonoType *etype = m_class_get_byval_arg (eklass);
if (is_set) {
EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, load, etype, args [2]->dreg, 0);
@@ -2005,7 +2005,7 @@ emit_array_unsafe_access (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst
if (is_set) {
return mini_emit_array_store (cfg, eklass, args, FALSE);
} else {
- MonoInst *ins, *addr = mini_emit_ldelema_1_ins (cfg, eklass, args [0], args [1], FALSE);
+ MonoInst *ins, *addr = mini_emit_ldelema_1_ins (cfg, eklass, args [0], args [1], FALSE, FALSE);
EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, m_class_get_byval_arg (eklass), addr->dreg, 0);
return ins;
}
diff --git a/mono/mini/main.c b/mono/mini/main.c
index b857ec3ca4d0..7cc3fecfa17d 100644
--- a/mono/mini/main.c
+++ b/mono/mini/main.c
@@ -35,6 +35,9 @@
# include "buildver-boehm.h"
# endif
#endif
+#ifdef TARGET_OSX
+#include
+#endif
//#define TEST_ICALL_SYMBOL_MAP 1
@@ -179,8 +182,68 @@ probe_embedded (const char *program, int *ref_argc, char **ref_argv [])
goto doclose;
if (read (fd, sigbuffer, sizeof (sigbuffer)) == -1)
goto doclose;
- if (memcmp (sigbuffer+sizeof(uint64_t), "xmonkeysloveplay", 16) != 0)
- goto doclose;
+ // First, see if "xmonkeysloveplay" is at the end of file
+ if (memcmp (sigbuffer + sizeof (uint64_t), "xmonkeysloveplay", 16) == 0)
+ goto found;
+
+#ifdef TARGET_OSX
+ {
+ /*
+ * If "xmonkeysloveplay" is not at the end of file,
+ * on Mac OS X, we try a little harder, by actually
+ * reading the binary's header structure, to see
+ * if it is located at the end of a LC_SYMTAB section.
+ *
+ * This is because Apple code-signing appends a
+ * LC_CODE_SIGNATURE section to the binary, so
+ * for a signed binary, "xmonkeysloveplay" is no
+ * longer at the end of file.
+ *
+ * The rest is sanity-checks for the header and section structures.
+ */
+ struct mach_header_64 bin_header;
+ if ((sigstart = lseek (fd, 0, SEEK_SET)) == -1)
+ goto doclose;
+ // Find and check binary header
+ if (read (fd, &bin_header, sizeof (bin_header)) == -1)
+ goto doclose;
+ if (bin_header.magic != MH_MAGIC_64)
+ goto doclose;
+
+ off_t total = bin_header.sizeofcmds;
+ uint32_t count = bin_header.ncmds;
+ while (total > 0 && count > 0) {
+ struct load_command lc;
+ off_t sig_stored = lseek (fd, 0, SEEK_CUR); // get current offset
+ if (read (fd, &lc, sizeof (lc)) == -1)
+ goto doclose;
+ if (lc.cmd == LC_SYMTAB) {
+ struct symtab_command stc;
+ if ((sigstart = lseek (fd, -sizeof (lc), SEEK_CUR)) == -1)
+ goto doclose;
+ if (read (fd, &stc, sizeof (stc)) == -1)
+ goto doclose;
+
+ // Check the end of the LC_SYMTAB section for "xmonkeysloveplay"
+ if ((sigstart = lseek (fd, -(16 + sizeof (uint64_t)) + stc.stroff + stc.strsize, SEEK_SET)) == -1)
+ goto doclose;
+ if (read (fd, sigbuffer, sizeof (sigbuffer)) == -1)
+ goto doclose;
+ if (memcmp (sigbuffer + sizeof (uint64_t), "xmonkeysloveplay", 16) == 0)
+ goto found;
+ }
+ if ((sigstart = lseek (fd, sig_stored + lc.cmdsize, SEEK_SET)) == -1)
+ goto doclose;
+ total -= sizeof (lc.cmdsize);
+ count--;
+ }
+ }
+#endif
+
+ // did not find "xmonkeysloveplay" at end of file or end of LC_SYMTAB section
+ goto doclose;
+
+found:
directory_location = GUINT64_FROM_LE ((*(uint64_t *) &sigbuffer [0]));
if (lseek (fd, directory_location, SEEK_SET) == -1)
goto doclose;
diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c
index ead3c2e63b2d..c5125df0c9f9 100644
--- a/mono/mini/method-to-ir.c
+++ b/mono/mini/method-to-ir.c
@@ -4082,11 +4082,11 @@ mini_emit_sext_index_reg (MonoCompile *cfg, MonoInst *index)
}
MonoInst*
-mini_emit_ldelema_1_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, MonoInst *index, gboolean bcheck)
+mini_emit_ldelema_1_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, MonoInst *index, gboolean bcheck, gboolean bounded)
{
MonoInst *ins;
guint32 size;
- int mult_reg, add_reg, array_reg, index2_reg;
+ int mult_reg, add_reg, array_reg, index2_reg, bounds_reg, lower_bound_reg, realidx2_reg;
int context_used;
if (mini_is_gsharedvt_variable_klass (klass)) {
@@ -4099,16 +4099,37 @@ mini_emit_ldelema_1_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, Mono
mult_reg = alloc_preg (cfg);
array_reg = arr->dreg;
- index2_reg = mini_emit_sext_index_reg (cfg, index);
+ realidx2_reg = index2_reg = mini_emit_sext_index_reg (cfg, index);
+
+ if (bounded) {
+ bounds_reg = alloc_preg (cfg);
+ lower_bound_reg = alloc_preg (cfg);
+ realidx2_reg = alloc_preg (cfg);
+
+ MonoBasicBlock *is_null_bb = NULL;
+ NEW_BBLOCK (cfg, is_null_bb);
+
+ // gint32 lower_bound = 0;
+ // if (arr->bounds)
+ // lower_bound = arr->bounds.lower_bound;
+ // realidx2 = index2 - lower_bound;
+ MONO_EMIT_NEW_PCONST (cfg, lower_bound_reg, NULL);
+ MONO_EMIT_NEW_LOAD_MEMBASE (cfg, bounds_reg, arr->dreg, MONO_STRUCT_OFFSET (MonoArray, bounds));
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, bounds_reg, 0);
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, is_null_bb);
+ MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, lower_bound_reg, bounds_reg, MONO_STRUCT_OFFSET (MonoArrayBounds, lower_bound));
+ MONO_START_BB (cfg, is_null_bb);
+ MONO_EMIT_NEW_BIALU (cfg, OP_PSUB, realidx2_reg, index2_reg, lower_bound_reg);
+ }
if (bcheck)
- MONO_EMIT_BOUNDS_CHECK (cfg, array_reg, MonoArray, max_length, index2_reg);
+ MONO_EMIT_BOUNDS_CHECK (cfg, array_reg, MonoArray, max_length, realidx2_reg);
#if defined(TARGET_X86) || defined(TARGET_AMD64)
if (size == 1 || size == 2 || size == 4 || size == 8) {
static const int fast_log2 [] = { 1, 0, 1, -1, 2, -1, -1, -1, 3 };
- EMIT_NEW_X86_LEA (cfg, ins, array_reg, index2_reg, fast_log2 [size], MONO_STRUCT_OFFSET (MonoArray, vector));
+ EMIT_NEW_X86_LEA (cfg, ins, array_reg, realidx2_reg, fast_log2 [size], MONO_STRUCT_OFFSET (MonoArray, vector));
ins->klass = klass;
ins->type = STACK_MP;
@@ -4126,9 +4147,9 @@ mini_emit_ldelema_1_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, Mono
context_used = mini_class_check_context_used (cfg, klass);
g_assert (context_used);
rgctx_ins = mini_emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE);
- MONO_EMIT_NEW_BIALU (cfg, OP_IMUL, mult_reg, index2_reg, rgctx_ins->dreg);
+ MONO_EMIT_NEW_BIALU (cfg, OP_IMUL, mult_reg, realidx2_reg, rgctx_ins->dreg);
} else {
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_MUL_IMM, mult_reg, index2_reg, size);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_MUL_IMM, mult_reg, realidx2_reg, size);
}
MONO_EMIT_NEW_BIALU (cfg, OP_PADD, add_reg, array_reg, mult_reg);
NEW_BIALU_IMM (cfg, ins, OP_PADD_IMM, add_reg, add_reg, MONO_STRUCT_OFFSET (MonoArray, vector));
@@ -4221,10 +4242,12 @@ mini_emit_ldelema_ins (MonoCompile *cfg, MonoMethod *cmethod, MonoInst **sp, guc
int element_size;
MonoClass *eclass = m_class_get_element_class (cmethod->klass);
+ gboolean bounded = m_class_get_byval_arg (cmethod->klass) ? m_class_get_byval_arg (cmethod->klass)->type == MONO_TYPE_ARRAY : FALSE;
+
rank = mono_method_signature_internal (cmethod)->param_count - (is_set? 1: 0);
if (rank == 1)
- return mini_emit_ldelema_1_ins (cfg, eclass, sp [0], sp [1], TRUE);
+ return mini_emit_ldelema_1_ins (cfg, eclass, sp [0], sp [1], TRUE, bounded);
/* emit_ldelema_2 depends on OP_LMUL */
if (!cfg->backend->emulate_mul_div && rank == 2 && (cfg->opt & MONO_OPT_INTRINS) && !mini_is_gsharedvt_variable_klass (eclass)) {
@@ -4277,7 +4300,7 @@ mini_emit_array_store (MonoCompile *cfg, MonoClass *klass, MonoInst **sp, gboole
MonoInst *addr;
// FIXME-VT: OP_ICONST optimization
- addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE);
+ addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE, FALSE);
EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, m_class_get_byval_arg (klass), addr->dreg, 0, sp [2]->dreg);
ins->opcode = OP_STOREV_MEMBASE;
} else if (sp [1]->opcode == OP_ICONST) {
@@ -4292,7 +4315,7 @@ mini_emit_array_store (MonoCompile *cfg, MonoClass *klass, MonoInst **sp, gboole
MONO_EMIT_BOUNDS_CHECK (cfg, array_reg, MonoArray, max_length, index_reg);
EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, m_class_get_byval_arg (klass), array_reg, offset, sp [2]->dreg);
} else {
- MonoInst *addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], safety_checks);
+ MonoInst *addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], safety_checks, FALSE);
if (!mini_debug_options.weak_memory_model && mini_class_is_reference (klass))
mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL);
EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, m_class_get_byval_arg (klass), addr->dreg, 0, sp [2]->dreg);
@@ -6064,7 +6087,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
MonoBitSet *seq_point_set_locs = NULL;
gboolean emitted_funccall_seq_point = FALSE;
- cfg->disable_inline = is_jit_optimizer_disabled (method);
+ cfg->disable_inline = (method->iflags & METHOD_IMPL_ATTRIBUTE_NOOPTIMIZATION) || is_jit_optimizer_disabled (method);
cfg->current_method = method;
image = m_class_get_image (method->klass);
@@ -10072,7 +10095,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
}
readonly = FALSE;
- ins = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE);
+ ins = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE, FALSE);
*sp++ = ins;
break;
case MONO_CEE_LDELEM:
@@ -10106,7 +10129,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
if (mini_is_gsharedvt_variable_klass (klass)) {
// FIXME-VT: OP_ICONST optimization
- addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE);
+ addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE, FALSE);
EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, m_class_get_byval_arg (klass), addr->dreg, 0);
ins->opcode = OP_LOADV_MEMBASE;
} else if (sp [1]->opcode == OP_ICONST) {
@@ -10120,7 +10143,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
MONO_EMIT_BOUNDS_CHECK (cfg, array_reg, MonoArray, max_length, index_reg);
EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, m_class_get_byval_arg (klass), array_reg, offset);
} else {
- addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE);
+ addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE, FALSE);
EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, m_class_get_byval_arg (klass), addr->dreg, 0);
}
*sp++ = ins;
@@ -10777,6 +10800,24 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
*sp++ = ins;
inline_costs += CALL_COST * MIN(10, num_calls++);
break;
+ case MONO_CEE_MONO_METHODCONST:
+ g_assert (method->wrapper_type != MONO_WRAPPER_NONE);
+ EMIT_NEW_METHODCONST (cfg, ins, mono_method_get_wrapper_data (method, token));
+ *sp++ = ins;
+ break;
+ case MONO_CEE_MONO_PINVOKE_ADDR_CACHE: {
+ g_assert (method->wrapper_type != MONO_WRAPPER_NONE);
+ MonoMethod *pinvoke_method = (MonoMethod*)mono_method_get_wrapper_data (method, token);
+ /* This is a memory slot used by the wrapper */
+ if (cfg->compile_aot) {
+ EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_METHOD_PINVOKE_ADDR_CACHE, pinvoke_method);
+ } else {
+ gpointer addr = mono_domain_alloc0 (cfg->domain, sizeof (gpointer));
+ EMIT_NEW_PCONST (cfg, ins, addr);
+ }
+ *sp++ = ins;
+ break;
+ }
case MONO_CEE_MONO_NOT_TAKEN:
g_assert (method->wrapper_type != MONO_WRAPPER_NONE);
cfg->cbb->out_of_line = TRUE;
diff --git a/mono/mini/mini-arm64.c b/mono/mini/mini-arm64.c
index 30992b6cd881..317390249d67 100644
--- a/mono/mini/mini-arm64.c
+++ b/mono/mini/mini-arm64.c
@@ -4198,6 +4198,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
arm_uxthw (code, dreg, dreg);
break;
case OP_FCONV_TO_I4:
+ case OP_FCONV_TO_I:
arm_fcvtzs_dx (code, dreg, sreg1);
arm_sxtwx (code, dreg, dreg);
break;
diff --git a/mono/mini/mini-codegen.c b/mono/mini/mini-codegen.c
index fcee745b5a78..5b26a6c1ec68 100644
--- a/mono/mini/mini-codegen.c
+++ b/mono/mini/mini-codegen.c
@@ -1748,7 +1748,8 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
}
if (spec [MONO_INST_CLOB] == 'c') {
- int j, s, dreg, dreg2, cur_bank;
+ int j, dreg, dreg2, cur_bank;
+ regmask_t s;
guint64 clob_mask;
clob_mask = MONO_ARCH_CALLEE_REGS;
diff --git a/mono/mini/mini-darwin.c b/mono/mini/mini-darwin.c
index b0d2a4d674ed..834a60a13e72 100644
--- a/mono/mini/mini-darwin.c
+++ b/mono/mini/mini-darwin.c
@@ -79,6 +79,29 @@ mono_runtime_install_handlers (void)
{
mono_runtime_posix_install_handlers ();
+#if !defined (HOST_WATCHOS) && !defined (HOST_TVOS)
+ /* LLDB installs task-wide Mach exception handlers. XNU dispatches Mach
+ * exceptions first to any registered "activation" handler and then to
+ * any registered task handler before dispatching the exception to a
+ * host-wide Mach exception handler that does translation to POSIX
+ * signals. This makes it impossible to use LLDB with an
+ * implicit-null-check-enabled Mono; continuing execution after LLDB
+ * traps an EXC_BAD_ACCESS will result in LLDB's EXC_BAD_ACCESS handler
+ * being invoked again. This also interferes with the translation of
+ * SIGFPEs to .NET-level ArithmeticExceptions. Work around this here by
+ * installing a no-op task-wide Mach exception handler for
+ * EXC_BAD_ACCESS and EXC_ARITHMETIC.
+ */
+ kern_return_t kr = task_set_exception_ports (
+ mach_task_self (),
+ EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, /* SIGSEGV, SIGFPE */
+ MACH_PORT_NULL,
+ EXCEPTION_STATE_IDENTITY,
+ MACHINE_THREAD_STATE);
+ if (kr != KERN_SUCCESS)
+ g_warning ("mono_runtime_install_handlers: task_set_exception_ports failed");
+#endif
+
/* Snow Leopard has a horrible bug: http://openradar.appspot.com/7209349
* This causes obscure SIGTRAP's for any application that comes across this built on
* Snow Leopard. This is a horrible hack to ensure that the private __CFInitialize
diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c
index e75267929377..9f88c52baa2a 100644
--- a/mono/mini/mini-exceptions.c
+++ b/mono/mini/mini-exceptions.c
@@ -61,6 +61,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -1047,19 +1048,28 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info
return res;
}
+ HANDLE_FUNCTION_ENTER ();
+
+ MONO_HANDLE_PIN (ta);
+
len = mono_array_length_internal (ta) / TRACE_IP_ENTRY_SIZE;
res = mono_array_new_checked (domain, mono_defaults.stack_frame_class, len > skip ? len - skip : 0, error);
- if (mono_error_set_pending_exception (error))
- return NULL;
+ if (!is_ok (error))
+ goto fail;
+
+ MONO_HANDLE_PIN (res);
+
+ MonoObjectHandle sf_h;
+ sf_h = MONO_HANDLE_NEW (MonoObject, NULL);
for (i = skip; i < len; i++) {
MonoJitInfo *ji;
MonoStackFrame *sf = (MonoStackFrame *)mono_object_new_checked (domain, mono_defaults.stack_frame_class, error);
- if (!is_ok (error)) {
- mono_error_set_pending_exception (error);
- return NULL;
- }
+ if (!is_ok (error))
+ goto fail;
+ MONO_HANDLE_ASSIGN_RAW (sf_h, sf);
+
ExceptionTraceIp trace_ip;
memcpy (&trace_ip, mono_array_addr_fast (ta, ExceptionTraceIp, i), sizeof (ExceptionTraceIp));
gpointer ip = trace_ip.ip;
@@ -1091,18 +1101,14 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info
s = mono_method_get_name_full (method, TRUE, FALSE, MONO_TYPE_NAME_FORMAT_REFLECTION);
MonoString *name = mono_string_new_checked (domain, s, error);
g_free (s);
- if (!is_ok (error)) {
- mono_error_set_pending_exception (error);
- return NULL;
- }
+ if (!is_ok (error))
+ goto fail;
MONO_OBJECT_SETREF_INTERNAL (sf, internal_method_name, name);
}
else {
MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, NULL, error);
- if (!is_ok (error)) {
- mono_error_set_pending_exception (error);
- return NULL;
- }
+ if (!is_ok (error))
+ goto fail;
MONO_OBJECT_SETREF_INTERNAL (sf, method, rm);
}
@@ -1129,10 +1135,8 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info
if (need_file_info) {
if (location && location->source_file) {
MonoString *filename = mono_string_new_checked (domain, location->source_file, error);
- if (!is_ok (error)) {
- mono_error_set_pending_exception (error);
- return NULL;
- }
+ if (!is_ok (error))
+ goto fail;
MONO_OBJECT_SETREF_INTERNAL (sf, filename, filename);
sf->line = location->row;
sf->column = location->column;
@@ -1145,8 +1149,13 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info
mono_debug_free_source_location (location);
mono_array_setref_internal (res, i - skip, sf);
}
+ goto exit;
- return res;
+ fail:
+ mono_error_set_pending_exception (error);
+ res = NULL;
+ exit:
+ HANDLE_FUNCTION_RETURN_VAL (res);
}
static void
diff --git a/mono/mini/mini-generic-sharing.c b/mono/mini/mini-generic-sharing.c
index 5fb8bbb39c96..2ad21ecc1b56 100644
--- a/mono/mini/mini-generic-sharing.c
+++ b/mono/mini/mini-generic-sharing.c
@@ -1276,6 +1276,10 @@ get_wrapper_shared_type_full (MonoType *t, gboolean is_field)
#else
return m_class_get_byval_arg (mono_defaults.uint32_class);
#endif
+ case MONO_TYPE_R4:
+ return m_class_get_byval_arg (mono_defaults.single_class);
+ case MONO_TYPE_R8:
+ return m_class_get_byval_arg (mono_defaults.double_class);
case MONO_TYPE_OBJECT:
case MONO_TYPE_CLASS:
case MONO_TYPE_SZARRAY:
@@ -4464,6 +4468,21 @@ mini_is_gsharedvt_sharable_inst (MonoGenericInst *inst)
return has_vt;
}
+gboolean
+mini_is_gsharedvt_inst (MonoGenericInst *inst)
+{
+ int i;
+
+ for (i = 0; i < inst->type_argc; ++i) {
+ MonoType *type = inst->type_argv [i];
+
+ if (mini_is_gsharedvt_type (type))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
gboolean
mini_is_gsharedvt_sharable_method (MonoMethod *method)
{
diff --git a/mono/mini/mini-llvm.c b/mono/mini/mini-llvm.c
index 4ac4e72eece2..5102826ce3b8 100644
--- a/mono/mini/mini-llvm.c
+++ b/mono/mini/mini-llvm.c
@@ -316,6 +316,12 @@ const_int32 (int v)
return LLVMConstInt (LLVMInt32Type (), v, FALSE);
}
+static LLVMValueRef
+const_int64 (int64_t v)
+{
+ return LLVMConstInt (LLVMInt64Type (), v, FALSE);
+}
+
/*
* IntPtrType:
*
@@ -5712,6 +5718,28 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
values [ins->dreg] = LLVMBuildAdd (builder, v2, LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), dname);
break;
}
+ case OP_X86_BSF32:
+ case OP_X86_BSF64: {
+ LLVMValueRef args [] = {
+ lhs,
+ LLVMConstInt (LLVMInt1Type (), 1, TRUE),
+ };
+ int op = ins->opcode == OP_X86_BSF32 ? INTRINS_CTTZ_I32 : INTRINS_CTTZ_I64;
+ values [ins->dreg] = call_intrins (ctx, op, args, dname);
+ break;
+ }
+ case OP_X86_BSR32:
+ case OP_X86_BSR64: {
+ LLVMValueRef args [] = {
+ lhs,
+ LLVMConstInt (LLVMInt1Type (), 1, TRUE),
+ };
+ int op = ins->opcode == OP_X86_BSR32 ? INTRINS_CTLZ_I32 : INTRINS_CTLZ_I64;
+ LLVMValueRef width = ins->opcode == OP_X86_BSR32 ? const_int32 (31) : const_int64 (63);
+ LLVMValueRef tz = call_intrins (ctx, op, args, "");
+ values [ins->dreg] = LLVMBuildXor (builder, tz, width, dname);
+ break;
+ }
#endif
case OP_ICONV_TO_I1:
diff --git a/mono/mini/mini-mips.c b/mono/mini/mini-mips.c
index c816d01596a1..13cf4e578038 100644
--- a/mono/mini/mini-mips.c
+++ b/mono/mini/mini-mips.c
@@ -5597,3 +5597,10 @@ mono_arch_load_function (MonoJitICallId jit_icall_id)
{
return NULL;
}
+
+GSList*
+mono_arch_get_cie_program (void)
+{
+ NOT_IMPLEMENTED;
+ return NULL;
+}
diff --git a/mono/mini/mini-ops.h b/mono/mini/mini-ops.h
index 2e255fc0a383..0af9976d134d 100644
--- a/mono/mini/mini-ops.h
+++ b/mono/mini/mini-ops.h
@@ -1330,6 +1330,10 @@ MINI_OP(OP_X86_FP_LOAD_I4, "x86_fp_load_i4", FREG, IREG, NONE)
MINI_OP(OP_X86_SETEQ_MEMBASE, "x86_seteq_membase", NONE, IREG, NONE)
MINI_OP(OP_X86_SETNE_MEMBASE, "x86_setne_membase", NONE, IREG, NONE)
MINI_OP(OP_X86_FXCH, "x86_fxch", NONE, NONE, NONE)
+MINI_OP(OP_X86_BSF32, "x86_bsf32", IREG, IREG, NONE)
+MINI_OP(OP_X86_BSR32, "x86_bsr32", IREG, IREG, NONE)
+MINI_OP(OP_X86_BSF64, "x86_bsf64", LREG, LREG, NONE)
+MINI_OP(OP_X86_BSR64, "x86_bsr64", LREG, LREG, NONE)
#endif
#if defined(TARGET_AMD64)
diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c
index caf65d40e88a..c2f4ebbcbab6 100644
--- a/mono/mini/mini-runtime.c
+++ b/mono/mini/mini-runtime.c
@@ -165,6 +165,7 @@ static GSList *tramp_infos;
GSList *mono_interp_only_classes;
static void register_icalls (void);
+static void runtime_cleanup (MonoDomain *domain, gpointer user_data);
gboolean
mono_running_on_valgrind (void)
@@ -1239,6 +1240,7 @@ mono_patch_info_hash (gconstpointer data)
case MONO_PATCH_INFO_SIGNATURE:
case MONO_PATCH_INFO_METHOD_CODE_SLOT:
case MONO_PATCH_INFO_AOT_JIT_INFO:
+ case MONO_PATCH_INFO_METHOD_PINVOKE_ADDR_CACHE:
return hash | (gssize)ji->data.target;
case MONO_PATCH_INFO_GSHAREDVT_CALL:
return hash | (gssize)ji->data.gsharedvt->method;
@@ -1444,6 +1446,10 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
target = code_slot;
break;
}
+ case MONO_PATCH_INFO_METHOD_PINVOKE_ADDR_CACHE: {
+ target = mono_domain_alloc0 (domain, sizeof (gpointer));
+ break;
+ }
case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
target = (gpointer)&mono_polling_required;
break;
@@ -1965,6 +1971,8 @@ enum {
ELF_MACHINE = EM_S390,
#elif HOST_RISCV
ELF_MACHINE = EM_RISCV,
+#elif HOST_MIPS
+ ELF_MACHINE = EM_MIPS,
#endif
JIT_CODE_LOAD = 0
};
@@ -4550,6 +4558,7 @@ mini_init (const char *filename, const char *runtime_version)
#if defined(ENABLE_PERFTRACING) && !defined(DISABLE_EVENTPIPE)
ep_init ();
+ ep_finish_init ();
#endif
if (mono_aot_only) {
@@ -4613,7 +4622,7 @@ mini_init (const char *filename, const char *runtime_version)
#define JIT_RUNTIME_WORKS
#ifdef JIT_RUNTIME_WORKS
- mono_install_runtime_cleanup ((MonoDomainFunc)mini_cleanup);
+ mono_install_runtime_cleanup (runtime_cleanup);
mono_runtime_init_checked (domain, (MonoThreadStartCB)mono_thread_start_cb, mono_thread_attach_cb, error);
mono_error_assert_ok (error);
mono_thread_attach (domain);
@@ -4987,6 +4996,12 @@ jit_stats_cleanup (void)
mono_jit_stats.biggest_method = NULL;
}
+static void
+runtime_cleanup (MonoDomain *domain, gpointer user_data)
+{
+ mini_cleanup (domain);
+}
+
#ifdef DISABLE_CLEANUP
void
mini_cleanup (MonoDomain *domain)
diff --git a/mono/mini/mini-wasm-debugger.c b/mono/mini/mini-wasm-debugger.c
index dc1f5d38f3d2..43e61020b1f4 100644
--- a/mono/mini/mini-wasm-debugger.c
+++ b/mono/mini/mini-wasm-debugger.c
@@ -24,6 +24,12 @@ static int log_level = 1;
#define DEBUG_PRINTF(level, ...) do { if (G_UNLIKELY ((level) <= log_level)) { fprintf (stdout, __VA_ARGS__); } } while (0)
+enum {
+ EXCEPTION_MODE_NONE,
+ EXCEPTION_MODE_UNCAUGHT,
+ EXCEPTION_MODE_ALL
+};
+
//functions exported to be used by JS
G_BEGIN_DECLS
@@ -31,22 +37,21 @@ EMSCRIPTEN_KEEPALIVE int mono_wasm_set_breakpoint (const char *assembly_name, in
EMSCRIPTEN_KEEPALIVE int mono_wasm_remove_breakpoint (int bp_id);
EMSCRIPTEN_KEEPALIVE int mono_wasm_current_bp_id (void);
EMSCRIPTEN_KEEPALIVE void mono_wasm_enum_frames (void);
-EMSCRIPTEN_KEEPALIVE void mono_wasm_get_var_info (int scope, int* pos, int len);
+EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_get_local_vars (int scope, int* pos, int len);
EMSCRIPTEN_KEEPALIVE void mono_wasm_clear_all_breakpoints (void);
EMSCRIPTEN_KEEPALIVE int mono_wasm_setup_single_step (int kind);
-EMSCRIPTEN_KEEPALIVE void mono_wasm_get_object_properties (int object_id, gboolean expand_value_types);
-EMSCRIPTEN_KEEPALIVE void mono_wasm_get_array_values (int object_id);
-EMSCRIPTEN_KEEPALIVE void mono_wasm_get_array_value_expanded (int object_id, int idx);
-EMSCRIPTEN_KEEPALIVE void mono_wasm_invoke_getter_on_object (int object_id, const char* name);
-EMSCRIPTEN_KEEPALIVE void mono_wasm_get_deref_ptr_value (void *value_addr, MonoClass *klass);
+EMSCRIPTEN_KEEPALIVE int mono_wasm_pause_on_exceptions (int state);
+EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_get_object_properties (int object_id, gboolean expand_value_types);
+EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_get_array_values (int object_id, int start_idx, int count, gboolean expand_value_types);
+EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_invoke_getter_on_object (int object_id, const char* name);
+EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_invoke_getter_on_value (void *value, MonoClass *klass, const char *name);
+EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_get_deref_ptr_value (void *value_addr, MonoClass *klass);
//JS functions imported that we use
extern void mono_wasm_add_frame (int il_offset, int method_token, const char *assembly_name, const char *method_name);
extern void mono_wasm_fire_bp (void);
+extern void mono_wasm_fire_exception (int exception_obj_id, const char* message, const char* class_name, gboolean uncaught);
extern void mono_wasm_add_obj_var (const char*, const char*, guint64);
-extern void mono_wasm_add_value_type_unexpanded_var (const char*, const char*);
-extern void mono_wasm_begin_value_type_var (const char*, const char*);
-extern void mono_wasm_end_value_type_var (void);
extern void mono_wasm_add_enum_var (const char*, const char*, guint64);
extern void mono_wasm_add_func_var (const char*, const char*, guint64);
extern void mono_wasm_add_properties_var (const char*, gint32);
@@ -57,6 +62,7 @@ extern void mono_wasm_add_typed_value (const char *type, const char *str_value,
G_END_DECLS
static void describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAsyncLocalThis, gboolean expandValueType);
+static void handle_exception (MonoException *exc, MonoContext *throw_ctx, MonoContext *catch_ctx, StackFrameInfo *catch_frame);
//FIXME move all of those fields to the profiler object
static gboolean debugger_enabled;
@@ -65,6 +71,7 @@ static int event_request_id;
static GHashTable *objrefs;
static GHashTable *obj_to_objref;
static int objref_id = 0;
+static int pause_on_exc = EXCEPTION_MODE_NONE;
static const char*
all_getters_allowed_class_names[] = {
@@ -133,7 +140,7 @@ collect_frames (MonoStackFrameInfo *info, MonoContext *ctx, gpointer data)
DEBUG_PRINTF (2, "Reporting method %s native_offset %d\n", method->name, info->native_offset);
if (!mono_find_prev_seq_point_for_native_offset (mono_get_root_domain (), method, info->native_offset, NULL, &sp))
- DEBUG_PRINTF (2, "Failed to lookup sequence point\n");
+ DEBUG_PRINTF (2, "collect_frames: Failed to lookup sequence point. method: %s, native_offset: %d \n", method->name, info->native_offset);
DbgEngineStackFrame *frame = g_new0 (DbgEngineStackFrame, 1);
@@ -249,7 +256,7 @@ typedef struct {
static void*
create_breakpoint_events (GPtrArray *ss_reqs, GPtrArray *bp_reqs, MonoJitInfo *ji, EventKind kind)
{
- printf ("ss_reqs %d bp_reqs %d\n", ss_reqs->len, bp_reqs->len);
+ DEBUG_PRINTF (1, "ss_reqs %d bp_reqs %d\n", ss_reqs->len, bp_reqs->len);
if ((ss_reqs && ss_reqs->len) || (bp_reqs && bp_reqs->len)) {
BpEvents *evts = g_new0 (BpEvents, 1); //just a non-null value to make sure we can raise it on process_breakpoint_events
evts->is_ss = (ss_reqs && ss_reqs->len);
@@ -276,7 +283,7 @@ no_seq_points_found (MonoMethod *method, int offset)
/*
* This can happen in full-aot mode with assemblies AOTed without the 'soft-debug' option to save space.
*/
- printf ("Unable to find seq points for method '%s', offset 0x%x.\n", mono_method_full_name (method, TRUE), offset);
+ DEBUG_PRINTF (1, "Unable to find seq points for method '%s', offset 0x%x.\n", mono_method_full_name (method, TRUE), offset);
}
#define DBG_NOT_SUSPENDED 1
@@ -284,7 +291,7 @@ no_seq_points_found (MonoMethod *method, int offset)
static int
ss_create_init_args (SingleStepReq *ss_req, SingleStepArgs *ss_args)
{
- printf ("ss_create_init_args\n");
+ DEBUG_PRINTF (1, "ss_create_init_args\n");
int dummy = 0;
ss_req->start_sp = ss_req->last_sp = &dummy;
compute_frames ();
@@ -363,6 +370,8 @@ mono_wasm_debugger_init (void)
obj_to_objref = g_hash_table_new (NULL, NULL);
objrefs = g_hash_table_new_full (NULL, NULL, NULL, mono_debugger_free_objref);
+
+ mini_get_dbg_callbacks ()->handle_exception = handle_exception;
}
MONO_API void
@@ -373,6 +382,14 @@ mono_wasm_enable_debugging (int debug_level)
log_level = debug_level;
}
+EMSCRIPTEN_KEEPALIVE int
+mono_wasm_pause_on_exceptions (int state)
+{
+ pause_on_exc = state;
+ DEBUG_PRINTF (1, "setting pause on exception: %d\n", pause_on_exc);
+ return 1;
+}
+
EMSCRIPTEN_KEEPALIVE int
mono_wasm_setup_single_step (int kind)
{
@@ -428,6 +445,50 @@ mono_wasm_setup_single_step (int kind)
return isBPOnNativeCode;
}
+static int
+get_object_id(MonoObject *obj)
+{
+ ObjRef *ref;
+ if (!obj)
+ return 0;
+
+ ref = (ObjRef *)g_hash_table_lookup (obj_to_objref, GINT_TO_POINTER (~((gsize)obj)));
+ if (ref)
+ return ref->id;
+ ref = g_new0 (ObjRef, 1);
+ ref->id = mono_atomic_inc_i32 (&objref_id);
+ ref->handle = mono_gchandle_new_weakref_internal (obj, FALSE);
+ g_hash_table_insert (objrefs, GINT_TO_POINTER (ref->id), ref);
+ g_hash_table_insert (obj_to_objref, GINT_TO_POINTER (~((gsize)obj)), ref);
+ return ref->id;
+}
+
+static void
+handle_exception (MonoException *exc, MonoContext *throw_ctx, MonoContext *catch_ctx, StackFrameInfo *catch_frame)
+{
+ ERROR_DECL (error);
+ DEBUG_PRINTF (1, "handle exception - %d - %p - %p - %p\n", pause_on_exc, exc, throw_ctx, catch_ctx);
+
+ if (pause_on_exc == EXCEPTION_MODE_NONE)
+ return;
+ if (pause_on_exc == EXCEPTION_MODE_UNCAUGHT && catch_ctx != NULL)
+ return;
+
+ int obj_id = get_object_id ((MonoObject *)exc);
+ const char *error_message = mono_string_to_utf8_checked_internal (exc->message, error);
+
+ if (!is_ok (error))
+ error_message = "Failed to get exception message.";
+
+ const char *class_name = mono_class_full_name (mono_object_class (exc));
+ DEBUG_PRINTF (2, "handle exception - calling mono_wasm_fire_exc(): %d - message - %s, class_name: %s\n", obj_id, error_message, class_name);
+
+ mono_wasm_fire_exception (obj_id, error_message, class_name, !catch_ctx);
+
+ DEBUG_PRINTF (2, "handle exception - done\n");
+}
+
+
EMSCRIPTEN_KEEPALIVE void
mono_wasm_clear_all_breakpoints (void)
{
@@ -567,21 +628,20 @@ mono_wasm_current_bp_id (void)
return evt->id;
}
-static int get_object_id(MonoObject *obj)
+static MonoObject*
+get_object_from_id (int objectId)
{
- ObjRef *ref;
+ ObjRef *ref = (ObjRef *)g_hash_table_lookup (objrefs, GINT_TO_POINTER (objectId));
+ if (!ref) {
+ DEBUG_PRINTF (2, "get_object_from_id !ref: %d\n", objectId);
+ return NULL;
+ }
+
+ MonoObject *obj = mono_gchandle_get_target_internal (ref->handle);
if (!obj)
- return 0;
+ DEBUG_PRINTF (2, "get_object_from_id !obj: %d\n", objectId);
- ref = (ObjRef *)g_hash_table_lookup (obj_to_objref, GINT_TO_POINTER (~((gsize)obj)));
- if (ref)
- return ref->id;
- ref = g_new0 (ObjRef, 1);
- ref->id = mono_atomic_inc_i32 (&objref_id);
- ref->handle = mono_gchandle_new_weakref_internal (obj, FALSE);
- g_hash_table_insert (objrefs, GINT_TO_POINTER (ref->id), ref);
- g_hash_table_insert (obj_to_objref, GINT_TO_POINTER (~((gsize)obj)), ref);
- return ref->id;
+ return obj;
}
static gboolean
@@ -607,7 +667,7 @@ list_frames (MonoStackFrameInfo *info, MonoContext *ctx, gpointer data)
DEBUG_PRINTF (2, "Reporting method %s native_offset %d\n", method->name, info->native_offset);
if (!mono_find_prev_seq_point_for_native_offset (mono_get_root_domain (), method, info->native_offset, NULL, &sp))
- DEBUG_PRINTF (1, "Failed to lookup sequence point\n");
+ DEBUG_PRINTF (2, "list_frames: Failed to lookup sequence point. method: %s, native_offset: %d\n", method->name, info->native_offset);
method_full_name = mono_method_full_name (method, FALSE);
while (method->is_inflated)
@@ -921,17 +981,28 @@ static gboolean describe_value(MonoType * type, gpointer addr, gboolean expandVa
mono_wasm_add_enum_var (class_name, enum_members->str, value__);
g_string_free (enum_members, TRUE);
- } else if (expandValueType) {
- char *to_string_val = get_to_string_description (class_name, klass, addr);
- mono_wasm_begin_value_type_var (class_name, to_string_val);
- g_free (to_string_val);
-
- // FIXME: isAsyncLocalThis
- describe_object_properties_for_klass ((MonoObject*)addr, klass, FALSE, expandValueType);
- mono_wasm_end_value_type_var ();
} else {
char *to_string_val = get_to_string_description (class_name, klass, addr);
- mono_wasm_add_value_type_unexpanded_var (class_name, to_string_val);
+
+ if (expandValueType) {
+ int32_t size = mono_class_value_size (klass, NULL);
+ void *value_buf = g_malloc0 (size);
+ mono_value_copy_internal (value_buf, addr, klass);
+
+ EM_ASM ({
+ MONO.mono_wasm_add_typed_value ($0, $1, { toString: $2, value_addr: $3, value_size: $4, klass: $5 });
+ }, "begin_vt", class_name, to_string_val, value_buf, size, klass);
+
+ g_free (value_buf);
+
+ // FIXME: isAsyncLocalThis
+ describe_object_properties_for_klass (addr, klass, FALSE, expandValueType);
+ mono_wasm_add_typed_value ("end_vt", NULL, 0);
+ } else {
+ EM_ASM ({
+ MONO.mono_wasm_add_typed_value ($0, $1, { toString: $2 });
+ }, "unexpanded_vt", class_name, to_string_val);
+ }
g_free (to_string_val);
}
g_free (class_name);
@@ -989,7 +1060,7 @@ describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAs
gboolean is_valuetype;
int pnum;
char *klass_name;
- gboolean getters_allowed;
+ gboolean auto_invoke_getters;
g_assert (klass);
is_valuetype = m_class_is_valuetype(klass);
@@ -1022,7 +1093,7 @@ describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAs
}
klass_name = mono_class_full_name (klass);
- getters_allowed = are_getters_allowed (klass_name);
+ auto_invoke_getters = are_getters_allowed (klass_name);
iter = NULL;
pnum = 0;
@@ -1034,29 +1105,24 @@ describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAs
mono_wasm_add_properties_var (p->name, pnum);
sig = mono_method_signature_internal (p->get);
- // automatic properties will get skipped
- if (!getters_allowed) {
+ gboolean vt_self_type_getter = is_valuetype && mono_class_from_mono_type_internal (sig->ret) == klass;
+ if (auto_invoke_getters && !vt_self_type_getter) {
+ invoke_and_describe_getter_value (obj, p);
+ } else {
// not allowed to call the getter here
char *ret_class_name = mono_class_full_name (mono_class_from_mono_type_internal (sig->ret));
- // getters not supported for valuetypes, yet
- gboolean invokable = !is_valuetype && sig->param_count == 0;
+ gboolean invokable = sig->param_count == 0;
mono_wasm_add_typed_value ("getter", ret_class_name, invokable);
g_free (ret_class_name);
continue;
}
-
- if (is_valuetype && mono_class_from_mono_type_internal (sig->ret) == klass) {
- // Property of the same valuetype, avoid endlessly recursion!
- mono_wasm_add_typed_value ("getter", klass_name, 0);
- continue;
- }
-
- invoke_and_describe_getter_value (obj, p);
}
pnum ++;
}
+
+ g_free (klass_name);
}
/*
@@ -1085,17 +1151,10 @@ static gboolean
describe_object_properties (guint64 objectId, gboolean isAsyncLocalThis, gboolean expandValueType)
{
DEBUG_PRINTF (2, "describe_object_properties %llu\n", objectId);
- ObjRef *ref = (ObjRef *)g_hash_table_lookup (objrefs, GINT_TO_POINTER (objectId));
- if (!ref) {
- DEBUG_PRINTF (2, "describe_object_properties !ref\n");
- return FALSE;
- }
- MonoObject *obj = mono_gchandle_get_target_internal (ref->handle);
- if (!obj) {
- DEBUG_PRINTF (2, "describe_object_properties !obj\n");
+ MonoObject *obj = get_object_from_id (objectId);
+ if (!obj)
return FALSE;
- }
if (m_class_is_delegate (mono_object_class (obj))) {
// delegates get the same id format as regular objects
@@ -1108,21 +1167,13 @@ describe_object_properties (guint64 objectId, gboolean isAsyncLocalThis, gboolea
}
static gboolean
-invoke_getter_on_object (guint64 objectId, const char *name)
+invoke_getter (void *obj_or_value, MonoClass *klass, const char *name)
{
- ObjRef *ref = (ObjRef *)g_hash_table_lookup (objrefs, GINT_TO_POINTER (objectId));
- if (!ref) {
- DEBUG_PRINTF (1, "invoke_getter_on_object no objRef found for id %llu\n", objectId);
- return FALSE;
- }
-
- MonoObject *obj = mono_gchandle_get_target_internal (ref->handle);
- if (!obj) {
- DEBUG_PRINTF (1, "invoke_getter_on_object !obj\n");
+ if (!obj_or_value || !klass || !name) {
+ DEBUG_PRINTF (2, "invoke_getter: none of the arguments can be null");
return FALSE;
}
- MonoClass *klass = mono_object_class (obj);
gpointer iter = NULL;
MonoProperty *p;
while ((p = mono_class_get_properties (klass, &iter))) {
@@ -1130,7 +1181,7 @@ invoke_getter_on_object (guint64 objectId, const char *name)
if (!p->get->name || strcasecmp (p->name, name) != 0)
continue;
- invoke_and_describe_getter_value (obj, p);
+ invoke_and_describe_getter_value (obj_or_value, p);
return TRUE;
}
@@ -1138,50 +1189,48 @@ invoke_getter_on_object (guint64 objectId, const char *name)
}
static gboolean
-describe_array_values (guint64 objectId)
+describe_array_values (guint64 objectId, int startIdx, int count, gboolean expandValueType)
{
+ if (count == 0)
+ return TRUE;
+
int esize;
gpointer elem;
- ObjRef *ref = (ObjRef *)g_hash_table_lookup (objrefs, GINT_TO_POINTER (objectId));
- if (!ref) {
+ MonoArray *arr = (MonoArray*) get_object_from_id (objectId);
+ if (!arr)
return FALSE;
- }
- MonoArray *arr = (MonoArray *)mono_gchandle_get_target_internal (ref->handle);
- MonoObject *obj = &arr->obj;
- if (!obj) {
+
+ MonoClass *klass = mono_object_class (arr);
+ MonoTypeEnum type = m_class_get_byval_arg (klass)->type;
+ if (type != MONO_TYPE_SZARRAY && type != MONO_TYPE_ARRAY) {
+ DEBUG_PRINTF (1, "describe_array_values: object is not an array. type: 0x%x\n", type);
return FALSE;
}
- esize = mono_array_element_size (obj->vtable->klass);
- for (int i = 0; i < arr->max_length; i++) {
- mono_wasm_add_array_item(i);
- elem = (gpointer*)((char*)arr->vector + (i * esize));
- describe_value (m_class_get_byval_arg (m_class_get_element_class (arr->obj.vtable->klass)), elem, FALSE);
+
+ int len = arr->max_length;
+ if (len == 0 && startIdx == 0 && count <= 0) {
+ // Nothing to do
+ return TRUE;
}
- return TRUE;
-}
-/* Expands valuetypes */
-static gboolean
-describe_array_value_expanded (guint64 objectId, guint64 idx)
-{
- int esize;
- gpointer elem;
- ObjRef *ref = (ObjRef *)g_hash_table_lookup (objrefs, GINT_TO_POINTER (objectId));
- if (!ref) {
+ if (startIdx < 0 || (len > 0 && startIdx >= len)) {
+ DEBUG_PRINTF (1, "describe_array_values: invalid startIdx (%d) for array of length %d\n", startIdx, len);
return FALSE;
}
- MonoArray *arr = (MonoArray *)mono_gchandle_get_target_internal (ref->handle);
- MonoObject *obj = &arr->obj;
- if (!obj) {
+
+ if (count > 0 && (startIdx + count) > len) {
+ DEBUG_PRINTF (1, "describe_array_values: invalid count (%d) for startIdx: %d, and array of length %d\n", count, startIdx, len);
return FALSE;
}
- if (idx >= arr->max_length)
- return FALSE;
- esize = mono_array_element_size (obj->vtable->klass);
- elem = (gpointer*)((char*)arr->vector + (idx * esize));
- describe_value (m_class_get_byval_arg (m_class_get_element_class (arr->obj.vtable->klass)), elem, TRUE);
+ esize = mono_array_element_size (klass);
+ int endIdx = count < 0 ? len : startIdx + count;
+ for (int i = startIdx; i < endIdx; i ++) {
+ mono_wasm_add_array_item(i);
+ elem = (gpointer*)((char*)arr->vector + (i * esize));
+ describe_value (m_class_get_byval_arg (m_class_get_element_class (klass)), elem, expandValueType);
+ }
return TRUE;
}
@@ -1284,22 +1333,23 @@ describe_variables_on_frame (MonoStackFrameInfo *info, MonoContext *ctx, gpointe
return TRUE;
}
-EMSCRIPTEN_KEEPALIVE void
+EMSCRIPTEN_KEEPALIVE gboolean
mono_wasm_get_deref_ptr_value (void *value_addr, MonoClass *klass)
{
MonoType *type = m_class_get_byval_arg (klass);
if (type->type != MONO_TYPE_PTR && type->type != MONO_TYPE_FNPTR) {
DEBUG_PRINTF (2, "BUG: mono_wasm_get_deref_ptr_value: Expected to get a ptr type, but got 0x%x\n", type->type);
- return;
+ return FALSE;
}
mono_wasm_add_properties_var ("deref", -1);
describe_value (type->data.type, value_addr, TRUE);
+ return TRUE;
}
//FIXME this doesn't support getting the return value pseudo-var
-EMSCRIPTEN_KEEPALIVE void
-mono_wasm_get_var_info (int scope, int* pos, int len)
+EMSCRIPTEN_KEEPALIVE gboolean
+mono_wasm_get_local_vars (int scope, int* pos, int len)
{
FrameDescData data;
data.target_frame = scope;
@@ -1308,37 +1358,51 @@ mono_wasm_get_var_info (int scope, int* pos, int len)
data.pos = pos;
mono_walk_stack_with_ctx (describe_variables_on_frame, NULL, MONO_UNWIND_NONE, &data);
+
+ return TRUE;
}
-EMSCRIPTEN_KEEPALIVE void
+EMSCRIPTEN_KEEPALIVE gboolean
mono_wasm_get_object_properties (int object_id, gboolean expand_value_types)
{
DEBUG_PRINTF (2, "getting properties of object %d\n", object_id);
- describe_object_properties (object_id, FALSE, expand_value_types);
+ return describe_object_properties (object_id, FALSE, expand_value_types);
}
-EMSCRIPTEN_KEEPALIVE void
-mono_wasm_get_array_values (int object_id)
+EMSCRIPTEN_KEEPALIVE gboolean
+mono_wasm_get_array_values (int object_id, int start_idx, int count, gboolean expand_value_types)
{
- DEBUG_PRINTF (2, "getting array values %d\n", object_id);
+ DEBUG_PRINTF (2, "getting array values %d, startIdx: %d, count: %d, expandValueType: %d\n", object_id, start_idx, count, expand_value_types);
- describe_array_values(object_id);
+ return describe_array_values (object_id, start_idx, count, expand_value_types);
}
-EMSCRIPTEN_KEEPALIVE void
-mono_wasm_get_array_value_expanded (int object_id, int idx)
+EMSCRIPTEN_KEEPALIVE gboolean
+mono_wasm_invoke_getter_on_object (int object_id, const char* name)
{
- DEBUG_PRINTF (2, "getting array value %d for idx %d\n", object_id, idx);
+ MonoObject *obj = get_object_from_id (object_id);
+ if (!obj)
+ return FALSE;
- describe_array_value_expanded (object_id, idx);
+ return invoke_getter (obj, mono_object_class (obj), name);
}
-EMSCRIPTEN_KEEPALIVE void
-mono_wasm_invoke_getter_on_object (int object_id, const char* name)
+EMSCRIPTEN_KEEPALIVE gboolean
+mono_wasm_invoke_getter_on_value (void *value, MonoClass *klass, const char *name)
{
- invoke_getter_on_object (object_id, name);
+ DEBUG_PRINTF (2, "mono_wasm_invoke_getter_on_value: v: %p klass: %p, name: %s\n", value, klass, name);
+ if (!klass || !value)
+ return FALSE;
+
+ if (!m_class_is_valuetype (klass)) {
+ DEBUG_PRINTF (2, "mono_wasm_invoke_getter_on_value: klass is not a valuetype. name: %s\n", mono_class_full_name (klass));
+ return FALSE;
+ }
+
+ return invoke_getter (value, klass, name);
}
+
// Functions required by debugger-state-machine.
gsize
mono_debugger_tls_thread_id (DebuggerTlsData *debuggerTlsData)
diff --git a/mono/mini/mini.h b/mono/mini/mini.h
index 58eb136d3181..b242d1223d8a 100644
--- a/mono/mini/mini.h
+++ b/mono/mini/mini.h
@@ -2261,7 +2261,7 @@ void mini_emit_stobj (MonoCompile *cfg, MonoInst *dest, MonoInst *s
void mini_emit_initobj (MonoCompile *cfg, MonoInst *dest, const guchar *ip, MonoClass *klass);
void mini_emit_init_rvar (MonoCompile *cfg, int dreg, MonoType *rtype);
int mini_emit_sext_index_reg (MonoCompile *cfg, MonoInst *index);
-MonoInst* mini_emit_ldelema_1_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, MonoInst *index, gboolean bcheck);
+MonoInst* mini_emit_ldelema_1_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, MonoInst *index, gboolean bcheck, gboolean bounded);
MonoInst* mini_emit_get_gsharedvt_info_klass (MonoCompile *cfg, MonoClass *klass, MonoRgctxInfoType rgctx_type);
MonoInst* mini_emit_get_rgctx_method (MonoCompile *cfg, int context_used,
MonoMethod *cmethod, MonoRgctxInfoType rgctx_type);
@@ -2719,6 +2719,9 @@ mono_is_partially_sharable_inst (MonoGenericInst *inst);
gboolean
mini_is_gsharedvt_gparam (MonoType *t);
+gboolean
+mini_is_gsharedvt_inst (MonoGenericInst *inst);
+
MonoGenericContext* mini_method_get_context (MonoMethod *method);
int mono_method_check_context_used (MonoMethod *method);
diff --git a/mono/mini/patch-info.h b/mono/mini/patch-info.h
index 3adcde561526..6807f92b5c64 100644
--- a/mono/mini/patch-info.h
+++ b/mono/mini/patch-info.h
@@ -82,3 +82,6 @@ PATCH_INFO(SPECIFIC_TRAMPOLINES_GOT_SLOTS_BASE, "specific_trampolines_got_slots_
*/
PATCH_INFO(R8_GOT, "r8_got")
PATCH_INFO(R4_GOT, "r4_got")
+
+/* MonoMethod* -> the address of a memory slot which is used to cache the pinvoke address */
+PATCH_INFO(METHOD_PINVOKE_ADDR_CACHE, "pinvoke_addr_cache")
diff --git a/mono/mini/simd-intrinsics-netcore.c b/mono/mini/simd-intrinsics-netcore.c
index a93b334fe4ab..3888ea3bf1d5 100644
--- a/mono/mini/simd-intrinsics-netcore.c
+++ b/mono/mini/simd-intrinsics-netcore.c
@@ -4,6 +4,7 @@
#include
#include
+#include
#include "mini.h"
#if defined(DISABLE_JIT)
@@ -27,6 +28,7 @@ mono_simd_intrinsics_init (void)
#include "mono/utils/bsearch.h"
#include
#include
+#include
#if defined (MONO_ARCH_SIMD_INTRINSICS) && defined(ENABLE_NETCORE)
@@ -533,7 +535,7 @@ emit_sys_numerics_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
MONO_EMIT_BOUNDS_CHECK (cfg, array_ins->dreg, MonoArray, max_length, end_index_reg);
/* Load the array slice into the simd reg */
- ldelema_ins = mini_emit_ldelema_1_ins (cfg, mono_class_from_mono_type_internal (etype), array_ins, index_ins, TRUE);
+ ldelema_ins = mini_emit_ldelema_1_ins (cfg, mono_class_from_mono_type_internal (etype), array_ins, index_ins, TRUE, FALSE);
g_assert (args [0]->opcode == OP_LDADDR);
var = (MonoInst*)args [0]->inst_p0;
EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADX_MEMBASE, var->dreg, ldelema_ins->dreg, 0);
@@ -568,7 +570,7 @@ emit_sys_numerics_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
MONO_EMIT_NEW_COND_EXC (cfg, LT, "ArgumentException");
/* Load the array slice into the simd reg */
- ldelema_ins = mini_emit_ldelema_1_ins (cfg, mono_class_from_mono_type_internal (etype), array_ins, index_ins, FALSE);
+ ldelema_ins = mini_emit_ldelema_1_ins (cfg, mono_class_from_mono_type_internal (etype), array_ins, index_ins, FALSE, FALSE);
EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STOREX_MEMBASE, ldelema_ins->dreg, 0, val_vreg);
ins->klass = cmethod->klass;
return ins;
@@ -1119,6 +1121,12 @@ static SimdIntrinsic bmi2_methods [] = {
{SN_get_IsSupported}
};
+static SimdIntrinsic x86base_methods [] = {
+ {SN_BitScanForward},
+ {SN_BitScanReverse},
+ {SN_get_IsSupported}
+};
+
static MonoInst*
emit_x86_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
{
@@ -1887,6 +1895,39 @@ emit_x86_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature
}
}
+ if (is_hw_intrinsics_class (klass, "X86Base", &is_64bit)) {
+ if (!COMPILE_LLVM (cfg))
+ return NULL;
+
+ info = lookup_intrins_info (x86base_methods, sizeof (x86base_methods), cmethod);
+ if (!info)
+ return NULL;
+ int id = info->id;
+
+ switch (id) {
+ case SN_get_IsSupported:
+ EMIT_NEW_ICONST (cfg, ins, 1);
+ ins->type = STACK_I4;
+ return ins;
+ case SN_BitScanForward:
+ MONO_INST_NEW (cfg, ins, is_64bit ? OP_X86_BSF64 : OP_X86_BSF32);
+ ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg);
+ ins->sreg1 = args [0]->dreg;
+ ins->type = is_64bit ? STACK_I8 : STACK_I4;
+ MONO_ADD_INS (cfg->cbb, ins);
+ return ins;
+ case SN_BitScanReverse:
+ MONO_INST_NEW (cfg, ins, is_64bit ? OP_X86_BSR64 : OP_X86_BSR32);
+ ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg);
+ ins->sreg1 = args [0]->dreg;
+ ins->type = is_64bit ? STACK_I8 : STACK_I4;
+ MONO_ADD_INS (cfg->cbb, ins);
+ return ins;
+ default:
+ g_assert_not_reached ();
+ }
+ }
+
return NULL;
}
@@ -2134,3 +2175,13 @@ MONO_EMPTY_SOURCE_FILE (simd_intrinsics_netcore);
#endif
#endif /* DISABLE_JIT */
+
+
+#if defined(ENABLE_NETCORE) && defined(TARGET_AMD64)
+void
+ves_icall_System_Runtime_Intrinsics_X86_X86Base___cpuidex (int abcd[4], int function_id, int subfunction_id)
+{
+ mono_hwcap_x86_call_cpuidex (function_id, subfunction_id,
+ &abcd [0], &abcd [1], &abcd [2], &abcd [3]);
+}
+#endif
diff --git a/mono/mini/simd-intrinsics.c b/mono/mini/simd-intrinsics.c
index 95367010fe36..cd1aa96c40dd 100644
--- a/mono/mini/simd-intrinsics.c
+++ b/mono/mini/simd-intrinsics.c
@@ -2410,7 +2410,7 @@ emit_vector_t_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSigna
MONO_EMIT_BOUNDS_CHECK (cfg, array_ins->dreg, MonoArray, max_length, end_index_reg);
/* Load the array slice into the simd reg */
- ldelema_ins = mini_emit_ldelema_1_ins (cfg, mono_class_from_mono_type_internal (etype), array_ins, index_ins, TRUE);
+ ldelema_ins = mini_emit_ldelema_1_ins (cfg, mono_class_from_mono_type_internal (etype), array_ins, index_ins, TRUE, FALSE);
g_assert (args [0]->opcode == OP_LDADDR);
var = (MonoInst*)args [0]->inst_p0;
EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADX_MEMBASE, var->dreg, ldelema_ins->dreg, 0);
@@ -2554,7 +2554,7 @@ emit_vector_t_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSigna
MONO_EMIT_NEW_COND_EXC (cfg, LE_UN, "ArgumentException");
/* Load the simd reg into the array slice */
- ldelema_ins = mini_emit_ldelema_1_ins (cfg, mono_class_from_mono_type_internal (etype), array_ins, index_ins, TRUE);
+ ldelema_ins = mini_emit_ldelema_1_ins (cfg, mono_class_from_mono_type_internal (etype), array_ins, index_ins, TRUE, FALSE);
g_assert (args [0]->opcode == OP_LDADDR);
var = (MonoInst*)args [0]->inst_p0;
EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STOREX_MEMBASE, ldelema_ins->dreg, 0, var->dreg);
diff --git a/mono/mini/simd-methods-netcore.h b/mono/mini/simd-methods-netcore.h
index 6ea5b9c4a217..b68dd69eb4fb 100644
--- a/mono/mini/simd-methods-netcore.h
+++ b/mono/mini/simd-methods-netcore.h
@@ -233,3 +233,6 @@ METHOD(ReverseElementBits)
// Crc32
METHOD(ComputeCrc32)
METHOD(ComputeCrc32C)
+// X86Base
+METHOD(BitScanForward)
+METHOD(BitScanReverse)
diff --git a/mono/profiler/CMakeLists.txt b/mono/profiler/CMakeLists.txt
new file mode 100644
index 000000000000..4777a84a757d
--- /dev/null
+++ b/mono/profiler/CMakeLists.txt
@@ -0,0 +1,16 @@
+project(profiler)
+
+include_directories(
+ ${PROJECT_BINARY_DIR}/
+ ${PROJECT_BINARY_DIR}/../..
+ ${PROJECT_BINARY_DIR}/../../mono/eglib
+ ${CMAKE_SOURCE_DIR}/
+ ${PROJECT_SOURCE_DIR}/../
+ ${PROJECT_SOURCE_DIR}/../eglib
+ ${PROJECT_SOURCE_DIR}/../sgen)
+
+if(NOT DISABLE_LIBS)
+ add_library(mono-profiler-aot-static STATIC aot.c helper.c)
+ set_target_properties(mono-profiler-aot-static PROPERTIES OUTPUT_NAME mono-profiler-aot)
+ install(TARGETS mono-profiler-aot-static LIBRARY)
+endif()
diff --git a/mono/sgen/sgen-gc.c b/mono/sgen/sgen-gc.c
index e6719fae0585..94196085fc6e 100644
--- a/mono/sgen/sgen-gc.c
+++ b/mono/sgen/sgen-gc.c
@@ -3749,6 +3749,8 @@ sgen_gc_init (void)
#endif
/* If aot code is used, allocation from there won't expect the layout with canaries enabled */
sgen_set_use_managed_allocator (FALSE);
+ } else if (!strcmp (opt, "coop-no-stack-scan")) {
+ sgen_disable_native_stack_scan ();
} else if (!sgen_client_handle_gc_debug (opt)) {
sgen_env_var_error (MONO_GC_DEBUG_NAME, "Ignoring.", "Unknown option `%s`.", opt);
@@ -3776,6 +3778,7 @@ sgen_gc_init (void)
fprintf (stderr, " print-allowance\n");
fprintf (stderr, " print-pinning\n");
fprintf (stderr, " print-gchandles\n");
+ fprintf (stderr, " coop-no-stack-scan\n");
fprintf (stderr, " heap-dump=\n");
fprintf (stderr, " binary-protocol=[:]\n");
fprintf (stderr, " nursery-canaries\n");
diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am
index 6a3af788dfe4..8b689e9eb553 100755
--- a/mono/tests/Makefile.am
+++ b/mono/tests/Makefile.am
@@ -1741,7 +1741,7 @@ LLVM = $(filter --llvm, $(MONO_ENV_OPTIONS) $(AOT_BUILD_FLAGS))
# abort-try-holes.exe is flaky due to unwinding failure to the finally block when aborting
# appdomain-marshalbyref-assemblyload.exe: https://bugzilla.xamarin.com/show_bug.cgi?id=49308
# threads-init.exe: runs out of system threads
-# dim-constrainedcall.exe: fails on dontnet as well (https://github.com/dotnet/coreclr/issues/15353)
+# dim-constrainedcall.exe: fails on dontnet as well (https://github.com/dotnet/runtime/issues/9378)
#
# tailcall-rgctxb.exe
# tailcall-member-function-in-valuetype.exe
diff --git a/mono/tests/metadata-verifier/cli-blob-tests.md b/mono/tests/metadata-verifier/cli-blob-tests.md
index 89c2e87ce1c7..b93426a47ff8 100644
--- a/mono/tests/metadata-verifier/cli-blob-tests.md
+++ b/mono/tests/metadata-verifier/cli-blob-tests.md
@@ -20,7 +20,7 @@ method-def-sig {
invalid offset blob.i (table-row (6 0) + 10) + 1 set-byte 0x2E
invalid offset blob.i (table-row (6 0) + 10) + 1 set-byte 0x2F
- #upper nimble flags 0x80 is invalid
+ #upper nimble flags 0x80 is invalid
invalid offset blob.i (table-row (6 0) + 10) + 1 set-bit 7
#sig is too small to decode param count
@@ -89,7 +89,7 @@ method-def-ret-misc {
method-ref-sig {
assembly assembly-with-signatures.exe
- #member ref 0 is has a vararg sig
+ #member ref 0 is has a vararg sig
#member ref 1 don't use vararg
#2 sentinels
@@ -156,23 +156,23 @@ locals-sig {
#bad local sig
#row 0 has tons of locals
- #row 1 is int32&, int32
+ #row 1 is int32&, int32
#row 2 is typedref
#typedref with byref
- #row 1 is: cconv pcount(2) byref int32 int32
+ #row 1 is: cconv pcount(2) byref int32 int32
#row 1 goes to: cconv pcount(2) byref typedbyref int32
invalid offset blob.i (table-row (0x11 1)) + 4 set-byte 0x16
#byref pinned int32
- #row 1 is: cconv pcount(2) byref int32 int32
+ #row 1 is: cconv pcount(2) byref int32 int32
#row 1 goes to: cconv pcount(1) byref pinned int32
invalid offset blob.i (table-row (0x11 1)) + 2 set-byte 0x01,
offset blob.i (table-row (0x11 1)) + 4 set-byte 0x45
#pinned pinned int32
- #row 1 is: cconv pcount(2) byref int32 int32
+ #row 1 is: cconv pcount(2) byref int32 int32
#row 1 goes to: cconv pcount(1) pinned pinned int32
#LAMEIMPL MS doesn't care about this
valid offset blob.i (table-row (0x11 1)) + 2 set-byte 0x01,
@@ -215,7 +215,7 @@ type-enc {
invalid offset blob.i (table-row (0x04 3) + 4) + 3 set-byte 0x16
#LAMEIMPL MS verifier doesn't catch this one (runtime does)
- #rank 0
+ #rank 0
invalid offset blob.i (table-row (0x04 3) + 4) + 4 set-byte 0x00
#large nsizes
invalid offset blob.i (table-row (0x04 3) + 4) + 5 set-byte 0x1F
@@ -240,7 +240,7 @@ type-enc {
#fnptr
#field 10 is a fnptr
#format is: cconv FNPTR cconv pcount ret param* sentinel? param*
- #LAMESPEC, it lacks the fact that fnptr allows for unmanaged call conv
+ #LAMESPEC, it lacks the fact that fnptr allows for unmanaged call conv
#bad callconv
invalid offset blob.i (table-row (0x04 10) + 4) + 3 set-byte 0x88
@@ -263,10 +263,10 @@ typespec-sig {
#type zero is invalid
invalid offset blob.i (table-row (0x1B 0)) + 1 set-byte 0x0
- #LAMESPEC part II, MS allows for cmods on a typespec as well
+ #LAMESPEC part II, MS allows for cmods on a typespec as well
#modreq int32 is invalid
#typespec 2 is "modreq int32*" encoded as: PTR CMOD_REQD token INT32
- #change int to CMOD_REQD token INT32
+ #change int to CMOD_REQD token INT32
valid offset blob.i (table-row (0x1B 2)) + 1 set-byte 0x1f, #CMOD_REQD
offset blob.i (table-row (0x1B 2)) + 2 set-byte read.byte (blob.i (table-row (0x1B 2)) + 3), #token
offset blob.i (table-row (0x1B 2)) + 3 set-byte 0x08 #int8
@@ -321,7 +321,7 @@ method-header {
#bad fat header flags
#only 0x08 and 0x10 allowed
- #regular value is
+ #regular value is
invalid offset translate.rva.ind (table-row (0x06 1)) + 0 set-ushort 0x3033 #or 0x20
invalid offset translate.rva.ind (table-row (0x06 1)) + 0 set-ushort 0x3053
invalid offset translate.rva.ind (table-row (0x06 1)) + 0 set-ushort 0x3093
diff --git a/mono/tests/metadata-verifier/cli-cattr-tests.md b/mono/tests/metadata-verifier/cli-cattr-tests.md
index ac6849b8a15b..7d852b3a5f80 100644
--- a/mono/tests/metadata-verifier/cli-cattr-tests.md
+++ b/mono/tests/metadata-verifier/cli-cattr-tests.md
@@ -10,7 +10,7 @@ cattr-without-named-args {
#WARNING: peverify don't check custom attributes format beyond the prolog
#so it's pointless to use it for this.
#We'll take the easy road as well and when verifying the encoded data
- #assume that the target constructor can be decoded and use the runtime signature.
+ #assume that the target constructor can be decoded and use the runtime signature.
#bad size
invalid offset blob.i (table-row (0x0C 0) + 4) + 0 set-byte 0x0
diff --git a/mono/tests/metadata-verifier/cli-global-props-tests.md b/mono/tests/metadata-verifier/cli-global-props-tests.md
index ccbdca2e319b..481113390c38 100644
--- a/mono/tests/metadata-verifier/cli-global-props-tests.md
+++ b/mono/tests/metadata-verifier/cli-global-props-tests.md
@@ -24,4 +24,4 @@ fielddef-global-props {
badrt offset table-row (4 1) + 2 set-ushort read.ushort (table-row (4 0) + 2), #name
offset table-row (4 1) + 4 set-ushort read.ushort (table-row (4 0) + 4) #signature
-}
\ No newline at end of file
+}
diff --git a/mono/tests/metadata-verifier/cli-metadata-tests.md b/mono/tests/metadata-verifier/cli-metadata-tests.md
index 1ce3b3e187a9..fd04a9719566 100644
--- a/mono/tests/metadata-verifier/cli-metadata-tests.md
+++ b/mono/tests/metadata-verifier/cli-metadata-tests.md
@@ -54,6 +54,6 @@ cli-metadata-stream-headers {
#unkwnown name
invalid offset stream-header ( 0 ) + 8 set-byte 0x42
- #duplicate name, change #~ to #US
+ #duplicate name, change #~ to #US
invalid offset stream-header ( 0 ) + 9 set-byte 0x55 , offset stream-header ( 0 ) + 10 set-byte 0x53
-}
\ No newline at end of file
+}
diff --git a/mono/tests/metadata-verifier/cli-tables-tests.md b/mono/tests/metadata-verifier/cli-tables-tests.md
index cec99ac9f9d0..5412ec803ef0 100644
--- a/mono/tests/metadata-verifier/cli-tables-tests.md
+++ b/mono/tests/metadata-verifier/cli-tables-tests.md
@@ -5,7 +5,7 @@ tables-header {
valid offset cli-metadata + read.uint ( stream-header ( 0 ) ) + 4 set-byte 2
valid offset tables-header + 4 set-byte 2
- #major/minor versions
+ #major/minor versions
invalid offset tables-header + 4 set-byte 22
invalid offset tables-header + 5 set-byte 1
@@ -67,7 +67,7 @@ module-table {
valid offset tables-header + 24 set-uint 1
invalid offset tables-header + 24 set-uint 0
invalid offset tables-header + 24 set-uint 2 , offset tables-header + 32 set-uint 1
-
+
#name
#invalid string
invalid offset table-row ( 0 0 ) + 2 set-ushort 0x8888
@@ -120,7 +120,7 @@ typedef-table {
valid offset tables-header + 32 set-uint 2
invalid offset tables-header + 32 set-uint 0
- #This part of the test suite only verifies structural properties, not table relationships
+ #This part of the test suite only verifies structural properties, not table relationships
#Flags invalid bits: 6,9,14,15,19,21,24-31
invalid offset table-row ( 2 1 ) set-bit 6
@@ -186,7 +186,7 @@ typedef-table-field-list {
valid offset table-row ( 2 1 ) + 10 set-ushort 1
- #bad field list
+ #bad field list
invalid offset table-row ( 2 1 ) + 10 set-ushort 999
#this type is bigger than the next
@@ -202,7 +202,7 @@ typedef-table-method-list {
valid offset table-row ( 2 1 ) + 12 set-ushort 1
- #bad field list
+ #bad field list
invalid offset table-row ( 2 1 ) + 12 set-ushort 999
#this type is bigger than the next
@@ -262,11 +262,11 @@ field-table {
#if it's a global variable, it must be static and (public|compiler controler|private) (16)
#static + compiler controled
- valid offset table-row ( 2 1 ) + 10 set-ushort 2 , offset table-row ( 4 0 ) set-ushort 0x10
+ valid offset table-row ( 2 1 ) + 10 set-ushort 2 , offset table-row ( 4 0 ) set-ushort 0x10
#static + private
valid offset table-row ( 2 1 ) + 10 set-ushort 2 , offset table-row ( 4 0 ) set-ushort 0x11
#static + public
- valid offset table-row ( 2 1 ) + 10 set-ushort 2 , offset table-row ( 4 0 ) set-ushort 0x16
+ valid offset table-row ( 2 1 ) + 10 set-ushort 2 , offset table-row ( 4 0 ) set-ushort 0x16
#static + bad visibility
#LAMEIMPL MS doesn't verify visibility
invalid offset table-row ( 2 1 ) + 10 set-ushort 2 , offset table-row ( 4 0 ) set-ushort 0x12
@@ -275,7 +275,7 @@ field-table {
invalid offset table-row ( 2 1 ) + 10 set-ushort 2 , offset table-row ( 4 0 ) set-ushort 0x15
#public and not static
- invalid offset table-row ( 2 1 ) + 10 set-ushort 2 , offset table-row ( 4 0 ) set-ushort 0x06
+ invalid offset table-row ( 2 1 ) + 10 set-ushort 2 , offset table-row ( 4 0 ) set-ushort 0x06
#field is constant but has no row in the contant table
#LAMESPEC this check is missing from the spec
@@ -300,7 +300,7 @@ methoddef-table {
#bad flags (4)
#no unused bits
-
+
#invalid .ctor with generic params and specialname (6)
#method 0 is a .ctor, method 1 is generic
invalid offset table-row ( 6 1 ) + 6 or-ushort 0x1800 , offset table-row ( 6 1 ) + 8 set-ushort read.ushort ( table-row ( 6 0 ) + 8 )
@@ -343,8 +343,8 @@ methoddef-table {
#Interface cannot have .ctors (15)
#method 3 belongs to an inteface
invalid offset table-row ( 6 3 ) + 8 set-ushort read.ushort ( table-row ( 6 0 ) + 8 )
- #Interface methods can't be static
- invalid offset table-row ( 6 3 ) + 6 or-ushort 0x0010
+ #Interface methods can't be static
+ invalid offset table-row ( 6 3 ) + 6 or-ushort 0x0010
#XXX we don't care about CLS names (17)
@@ -377,7 +377,7 @@ methoddef-table {
invalid offset table-row ( 6 5 ) set-uint read.uint ( table-row ( 6 2 ) )
#pinvoke with runtime
- #LAMEIMPL/SPEC either MS ignores it or the spec is ill defined
+ #LAMEIMPL/SPEC either MS ignores it or the spec is ill defined
#invalid offset table-row ( 6 5 ) + 4 or-ushort 0x1000
#if compilercontroled (0x0) it must have an RVA or a pinvoke
@@ -389,7 +389,7 @@ methoddef-table {
#if RVA = 0 then one of (abstract, runtime, pinvoke) (34)
#let's test with an abstract class, method 6 is abstract and belongs to one.
invalid offset table-row ( 6 7 ) + 6 set-ushort 0x0006
- #icall
+ #icall
valid offset table-row ( 6 7 ) + 6 set-ushort 0x01c6 , offset table-row ( 6 7 ) + 4 or-ushort 0x1000
#if rva != 0 then abstract == 0 and codetypemask must be (native,cil,runtime) and rva shall be valid (35)
@@ -429,7 +429,7 @@ methoddef-table-global-methods {
assembly assembly-with-global-method.exe
#checks for methods owned by (20)
-
+
#static + public
valid offset table-row ( 6 0 ) + 6 set-ushort 0x0010
#static + private
@@ -458,10 +458,10 @@ methoddef-table-global-methods {
methoddef-table-params {
assembly assembly-with-methods.exe
- #method 12,13,14 have 3 params and params: 2,5,8
+ #method 12,13,14 have 3 params and params: 2,5,8
#method 13 has 3 params and params: 5
invalid offset table-row ( 6 12 ) + 12 set-ushort 6
- invalid offset table-row ( 6 13 ) + 12 set-ushort 99
+ invalid offset table-row ( 6 13 ) + 12 set-ushort 99
}
@@ -489,7 +489,7 @@ param-table {
invalid offset table-row ( 8 0 ) + 2 set-ushort 2
invalid offset table-row ( 8 1 ) + 2 set-ushort 1
-
+
#if HasDefault = 1 then there must be a row in the constant table (6)
#param 2 doesn't have a default
invalid offset table-row ( 8 2 ) or-ushort 0x1000
@@ -534,7 +534,7 @@ interfaceimpl-table {
memberref-table {
assembly assembly-with-complex-type.exe
-
+
#class must be a valid token (1 2)
#null
invalid offset table-row ( 10 0 ) set-ushort 0
@@ -555,13 +555,13 @@ memberref-table {
#signature must be valid (5)
invalid offset table-row ( 10 0 ) + 4 set-ushort 0x9900
-
+
#TODO validate the signature (5)
#LAMESPEC CompilerControled visibility (9,10) is nice but no impl care about
- #LAMESPEC what does (11) mean?
+ #LAMESPEC what does (11) mean?
}
constant-table {
@@ -588,7 +588,7 @@ constant-table {
#First remove default from param 'a' (param table idx 0)
#Then set the has default flag in the property table
#Finally, make the first constant point from the part to the property (const 1, prop 0, token 0x6)
- valid offset table-row ( 0x8 0 ) set-ushort 0 , offset table-row ( 0x17 0 ) or-ushort 0x1000 , offset table-row ( 0xB 1 ) + 2 set-ushort 0x6
+ valid offset table-row ( 0x8 0 ) set-ushort 0 , offset table-row ( 0x17 0 ) or-ushort 0x1000 , offset table-row ( 0xB 1 ) + 2 set-ushort 0x6
#Invalid coded table
invalid offset table-row ( 0xB 0 ) + 2 set-ushort 0x0013 , offset table-row ( 0x04 0 ) set-ushort 0x16
@@ -608,7 +608,7 @@ constant-table {
invalid offset table-row ( 0xB 0 ) + 4 set-ushort read.uint ( stream-header ( 3 ) + 4 )
#LAMEIMPL, MS doesn't bound check the constant size. Lame of them.
- invalid offset table-row ( 0xB 0 ) + 4 set-ushort read.uint ( stream-header ( 3 ) + 4 ) - 1
+ invalid offset table-row ( 0xB 0 ) + 4 set-ushort read.uint ( stream-header ( 3 ) + 4 ) - 1
}
cattr-table {
@@ -708,7 +708,7 @@ class-layout-table {
#packing must be (0,1,2,4,8,16,32,64,128) (4)
invalid offset table-row ( 0xF 0 ) set-ushort 0x0003
- #TODO do checks depending on the kind of parent (4)
+ #TODO do checks depending on the kind of parent (4)
#Check layout along the inheritance chain. (7)
}
@@ -753,7 +753,7 @@ event-table {
assembly assembly-with-events.exe
#event flags have valid bits (3)
- #only bits 9 and 10 are used
+ #only bits 9 and 10 are used
invalid offset table-row ( 0x14 0 ) set-bit 0
invalid offset table-row ( 0x14 0 ) set-bit 1
@@ -816,7 +816,7 @@ property-table {
assembly assembly-with-properties.exe
#valid flags (3)
- #only bits 9, 10 and 12 are used
+ #only bits 9, 10 and 12 are used
invalid offset table-row ( 0x17 0 ) set-bit 0
invalid offset table-row ( 0x17 0 ) set-bit 1
invalid offset table-row ( 0x17 0 ) set-bit 2
@@ -846,7 +846,7 @@ property-table {
#field zero has default value
valid offset table-row (0x17 0) + 0 or-ushort 0x1000, #mark the property with hasdefault
offset table-row (0x04 0) + 0 set-ushort 0x0011, #clear literal and hasdefault from the field
- offset table-row (0x0B 0) + 2 set-ushort 0x0006 #change the parent token to row 1 of the property table (0x2)
+ offset table-row (0x0B 0) + 2 set-ushort 0x0006 #change the parent token to row 1 of the property table (0x2)
invalid offset table-row (0x17 0) + 0 or-ushort 0x1000
@@ -857,32 +857,32 @@ methodimpl-table {
assembly assembly-with-complex-type.exe
#class shall be valid (2)
- invalid offset table-row (0x19 0) set-ushort 0
+ invalid offset table-row (0x19 0) set-ushort 0
invalid offset table-row (0x19 0) set-ushort 0x8800
#methodbody shall be valid (3)
#null
- invalid offset table-row (0x19 0) + 2 set-ushort 0x0000
+ invalid offset table-row (0x19 0) + 2 set-ushort 0x0000
invalid offset table-row (0x19 0) + 2 set-ushort 0x0001
#out of range
- invalid offset table-row (0x19 0) + 2 set-ushort 0x8800
+ invalid offset table-row (0x19 0) + 2 set-ushort 0x8800
invalid offset table-row (0x19 0) + 2 set-ushort 0x8801
#MethodDeclaration shall be valid
#null
- invalid offset table-row (0x19 0) + 4 set-ushort 0x0000
+ invalid offset table-row (0x19 0) + 4 set-ushort 0x0000
invalid offset table-row (0x19 0) + 4 set-ushort 0x0001
#out of range
- invalid offset table-row (0x19 0) + 4 set-ushort 0x8800
+ invalid offset table-row (0x19 0) + 4 set-ushort 0x8800
invalid offset table-row (0x19 0) + 4 set-ushort 0x8801
-
- #TODO check MethodDeclaration method for virtual and owner type for !sealed (4,5)
+
+ #TODO check MethodDeclaration method for virtual and owner type for !sealed (4,5)
#TODO check MethodBody for belonging to a super type of Class,been virtual and rva != 0 (6,7,8)
#TODO check MethodBody must belong to any ancestor or iface of Class (9)
#TODO check MethodDeclaration method shall not be final (10)
#TODO if MethodDeclaration is strict, it must be visible to Class (11)
- #TODO the method signature of MethodBody must match of MethodDeclaration (12)
+ #TODO the method signature of MethodBody must match of MethodDeclaration (12)
#TODO no dups
}
@@ -959,7 +959,7 @@ fieldrva-table {
invalid offset table-row (0x1D 0) + 4 set-ushort 0,
offset table-row (0x04 17) set-ushort 0x0013 #remove fieldrva from target field
invalid offset table-row (0x1D 0) + 4 set-ushort 0x9901,
- offset table-row (0x04 17) set-ushort 0x0013
+ offset table-row (0x04 17) set-ushort 0x0013
#TODO verify if the field is a blitable valuetype
@@ -974,7 +974,7 @@ assembly-table {
invalid offset tables-header + 40 set-uint 2,
offset stream-header (0) + 4 set-uint read.uint (stream-header (0) + 4) + 22 #increase the size of the #~ section
- #bad hasalg (2)
+ #bad hasalg (2)
valid offset table-row (0x20 0) set-uint 0
valid offset table-row (0x20 0) set-uint 0x8003
valid offset table-row (0x20 0) set-uint 0x8004
@@ -997,7 +997,7 @@ assembly-table {
#valid pub key (5)
- valid offset table-row (0x20 0) + 16 set-ushort 0
+ valid offset table-row (0x20 0) + 16 set-ushort 0
invalid offset table-row (0x20 0) + 16 set-ushort 0x9990
#name is a valid non-empty string (5)
@@ -1005,7 +1005,7 @@ assembly-table {
invalid offset table-row (0x20 0) + 18 set-ushort 0x9990
#culture is an optional valid non-empty string (8)
- valid offset table-row (0x20 0) + 20 set-ushort 0
+ valid offset table-row (0x20 0) + 20 set-ushort 0
invalid offset table-row (0x20 0) + 20 set-ushort 0x9990
#TODO check if culture is one of the listed cultures (9) (23.1.3)
@@ -1036,7 +1036,7 @@ assembly-ref-table {
invalid offset table-row (0x23 0) + 14 set-ushort 0
#culture is an optional valid non-empty string (6)
- valid offset table-row (0x23 0) + 16 set-ushort 0
+ valid offset table-row (0x23 0) + 16 set-ushort 0
invalid offset table-row (0x23 0) + 16 set-ushort 0x9990
#TODO check if culture is one of the listed cultures (7) (23.1.3)
@@ -1104,11 +1104,11 @@ exported-type-table {
#if Implementation points to exported type table visibility must be nested public (5)
#invalid offset table-row (0x27 1) set-uint 0x100005 #LAMEIMPL/SPEC this check is not really relevant
-
+
#typename is a valid non-empty string (7)
invalid offset table-row (0x27 0) + 8 set-ushort 0
invalid offset table-row (0x27 0) + 8 set-ushort 0x9900
-
+
#typenamedpace is a valid string (8,9)
invalid offset table-row (0x27 0) + 10 set-ushort 0x9900
@@ -1151,13 +1151,13 @@ manifest-resource-table {
valid offset table-row (0x28 0) + 10 set-ushort 0,
offset table-row (0x28 0) + 0 set-uint 1
- #LAMEIMPL it doesn't check the resource offset!
+ #LAMEIMPL it doesn't check the resource offset!
invalid offset table-row (0x28 0) + 10 set-ushort 0,
offset table-row (0x28 0) + 0 set-uint 0x990000
-
+
#implementation is a valid token (8)
- #does it accept exported type?
+ #does it accept exported type?
invalid offset table-row (0x28 0) + 10 set-ushort 0x0006
#coded table 4 is invalid
@@ -1169,7 +1169,7 @@ manifest-resource-table {
#if implementation point to a file it's index must be zero (10)
#row 0 is a file resource
invalid offset table-row (0x28 0) set-uint 1
-
+
#TODO check for dups (9)
}
@@ -1185,7 +1185,7 @@ nested-class-table {
invalid offset table-row (0x29 0) + 2 set-ushort read.ushort (table-row (0x29 0))
- #TODO check for dups based on nestedclass (5)
+ #TODO check for dups based on nestedclass (5)
}
@@ -1214,7 +1214,7 @@ generic-param-table {
invalid offset table-row (0x2A 0) + 4 set-ushort 0x8800
invalid offset table-row (0x2A 0) + 4 set-ushort 0x8801
- #bad or empty name
+ #bad or empty name
invalid offset table-row (0x2A 0) + 6 set-ushort 0
invalid offset table-row (0x2A 0) + 6 set-ushort 0x8800
diff --git a/mono/tests/metadata-verifier/data-directory-tests.md b/mono/tests/metadata-verifier/data-directory-tests.md
index 03be4f38c5fc..d58e567e9b93 100644
--- a/mono/tests/metadata-verifier/data-directory-tests.md
+++ b/mono/tests/metadata-verifier/data-directory-tests.md
@@ -3,18 +3,18 @@ pe-data-directories-export-table {
assembly simple-assembly.exe
#zero is fine
- valid offset pe-optional-header + 96 set-uint 0
+ valid offset pe-optional-header + 96 set-uint 0
valid offset pe-optional-header + 100 set-uint 0
#RVA must be zero
- invalid offset pe-optional-header + 96 set-uint 0x2000 , offset pe-optional-header + 100 set-uint 10
+ invalid offset pe-optional-header + 96 set-uint 0x2000 , offset pe-optional-header + 100 set-uint 10
}
pe-data-directories-import-table {
#Simple assembly has 2 sections since it doesn't have any resources
assembly simple-assembly.exe
-
+
#The IT is 40 bytes long
invalid offset pe-optional-header + 108 set-uint 0
invalid offset pe-optional-header + 108 set-uint 8
@@ -34,35 +34,35 @@ pe-data-directories-bad-tables {
#export
invalid offset pe-optional-header + 96 set-uint 0x2000
- #exception
- invalid offset pe-optional-header + 120 set-uint 0x2000
+ #exception
+ invalid offset pe-optional-header + 120 set-uint 0x2000
#certificate some assemblies have it.
- #invalid offset pe-optional-header + 128 set-uint 0x2000
+ #invalid offset pe-optional-header + 128 set-uint 0x2000
- #debug MS uses it for putting debug info in the assembly
- #invalid offset pe-optional-header + 144 set-uint 0x2000
+ #debug MS uses it for putting debug info in the assembly
+ #invalid offset pe-optional-header + 144 set-uint 0x2000
- #copyright
- invalid offset pe-optional-header + 152 set-uint 0x2000
+ #copyright
+ invalid offset pe-optional-header + 152 set-uint 0x2000
- #global ptr
- invalid offset pe-optional-header + 160 set-uint 0x2000
+ #global ptr
+ invalid offset pe-optional-header + 160 set-uint 0x2000
- #tls table
- invalid offset pe-optional-header + 168 set-uint 0x2000
+ #tls table
+ invalid offset pe-optional-header + 168 set-uint 0x2000
- #load config
- invalid offset pe-optional-header + 176 set-uint 0x2000
+ #load config
+ invalid offset pe-optional-header + 176 set-uint 0x2000
- #bound import
- invalid offset pe-optional-header + 184 set-uint 0x2000
+ #bound import
+ invalid offset pe-optional-header + 184 set-uint 0x2000
#delay import
- invalid offset pe-optional-header + 200 set-uint 0x2000
+ invalid offset pe-optional-header + 200 set-uint 0x2000
#reserved import
- invalid offset pe-optional-header + 216 set-uint 0x2000
+ invalid offset pe-optional-header + 216 set-uint 0x2000
}
diff --git a/mono/tests/metadata-verifier/gen-md-tests.c b/mono/tests/metadata-verifier/gen-md-tests.c
index 374a2cdd4dc1..b59bc86db617 100644
--- a/mono/tests/metadata-verifier/gen-md-tests.c
+++ b/mono/tests/metadata-verifier/gen-md-tests.c
@@ -272,7 +272,7 @@ init_test_set (test_set_t *test_set)
if (test_set->init)
return;
test_set->assembly_data = read_whole_file_and_close (test_set->assembly, &test_set->assembly_size);
- test_set->image = mono_image_open_from_data_internal (mono_domain_default_alc (mono_root_domain_get ()), test_set->assembly_data, test_set->assembly_size, FALSE, &status, FALSE, FALSE, NULL);
+ test_set->image = mono_image_open_from_data_internal (mono_domain_default_alc (mono_root_domain_get ()), test_set->assembly_data, test_set->assembly_size, FALSE, &status, FALSE, FALSE, NULL, NULL);
if (!test_set->image || status != MONO_IMAGE_OK) {
printf ("Could not parse image %s\n", test_set->assembly);
exit (INVALID_BAD_FILE);
diff --git a/mono/tests/metadata-verifier/header-tests.md b/mono/tests/metadata-verifier/header-tests.md
index 4534ba2299da..4ce8616a6a74 100644
--- a/mono/tests/metadata-verifier/header-tests.md
+++ b/mono/tests/metadata-verifier/header-tests.md
@@ -24,21 +24,21 @@ msdos-lfanew {
invalid offset 0x3f truncate
#not enough space for the PE water mark
- invalid offset 0x3c set-uint 0xffffffff
- invalid offset 0x3c set-uint file-size - 1
+ invalid offset 0x3c set-uint 0xffffffff
+ invalid offset 0x3c set-uint file-size - 1
invalid offset 0x3c set-uint file-size - 2
}
pe-signature {
assembly simple-assembly.exe
- valid offset pe-signature + 0 set-byte 'P'
- valid offset pe-signature + 1 set-byte 'E'
+ valid offset pe-signature + 0 set-byte 'P'
+ valid offset pe-signature + 1 set-byte 'E'
valid offset pe-signature + 2 set-byte 0
valid offset pe-signature + 3 set-byte 0
- invalid offset pe-signature + 0 set-byte 'M'
- invalid offset pe-signature + 1 set-byte 'K'
+ invalid offset pe-signature + 0 set-byte 'M'
+ invalid offset pe-signature + 1 set-byte 'K'
invalid offset pe-signature + 2 set-byte 1
invalid offset pe-signature + 3 set-byte 2
@@ -100,7 +100,7 @@ pe-optional-header-standard-fields {
valid offset pe-optional-header + 3 set-byte 0
valid offset pe-optional-header + 3 set-byte 99
-
+
#Code size is just an informative field as well, nobody cares
valid offset pe-optional-header + 4 set-uint 0
valid offset pe-optional-header + 4 set-uint 0x999999
diff --git a/mono/tests/metadata-verifier/resources-tests.md b/mono/tests/metadata-verifier/resources-tests.md
index 2443d1f5d06a..06f5d1e09403 100644
--- a/mono/tests/metadata-verifier/resources-tests.md
+++ b/mono/tests/metadata-verifier/resources-tests.md
@@ -15,4 +15,4 @@ resources-master-directory {
invalid offset translate.rva.ind ( pe-optional-header + 112 ) + 14 set-ushort 0x9999
#I won't check anything more than that for now as this is only used by out asp.net stack.
-}
\ No newline at end of file
+}
diff --git a/mono/tests/metadata-verifier/section-table-tests.md b/mono/tests/metadata-verifier/section-table-tests.md
index 07f85ecda0e4..8bb851119320 100644
--- a/mono/tests/metadata-verifier/section-table-tests.md
+++ b/mono/tests/metadata-verifier/section-table-tests.md
@@ -25,7 +25,7 @@ pe-section-headers {
#VirtualSize = file size + PointerToRawData + 32
invalid offset section-table + 16 set-uint file-size - read.uint ( section-table + 20 ) + 32
invalid offset section-table + 56 set-uint file-size - read.uint ( section-table + 60 ) + 32
-
+
invalid offset section-table + 60 set-uint 90000
#FIXME add section relocation tests
@@ -35,12 +35,12 @@ pe-section-header-flags {
#Simple assembly has 2 sections since it doesn't have any resources
assembly simple-assembly.exe
- #first section is always text
+ #first section is always text
valid offset section-table + 36 set-uint 0x60000020
valid offset section-table + 76 set-uint 0x42000040
-
+
invalid offset section-table + 36 set-uint 0
invalid offset section-table + 36 set-uint 0xFFFFFFFF
-}
\ No newline at end of file
+}
diff --git a/mono/tools/offsets-tool/offsets-tool.py b/mono/tools/offsets-tool/offsets-tool.py
index f9f7170aac31..e7c2021694cb 100644
--- a/mono/tools/offsets-tool/offsets-tool.py
+++ b/mono/tools/offsets-tool/offsets-tool.py
@@ -130,6 +130,11 @@ def require_emscipten_path (args):
self.target = Target ("TARGET_X86", "", IOS_DEFINES)
self.target_args += ["-arch", "i386"]
self.target_args += ["-isysroot", args.sysroot]
+ elif "x86_64-apple-darwin10" == args.abi:
+ require_sysroot (args)
+ self.target = Target ("TARGET_AMD64", "", IOS_DEFINES)
+ self.target_args += ["-arch", "x86_64"]
+ self.target_args += ["-isysroot", args.sysroot]
# watchOS
elif "armv7k-apple-darwin" == args.abi:
diff --git a/mono/utils/mono-dl-posix.c b/mono/utils/mono-dl-posix.c
index a6c767c8285d..7b19cd5174af 100644
--- a/mono/utils/mono-dl-posix.c
+++ b/mono/utils/mono-dl-posix.c
@@ -130,21 +130,21 @@ mono_dl_lookup_symbol (MonoDl *module, const char *name)
}
int
-mono_dl_convert_flags (int flags)
+mono_dl_convert_flags (int mono_flags, int native_flags)
{
- int lflags = 0;
+ int lflags = native_flags;
#ifdef ENABLE_NETCORE
// Specifying both will default to LOCAL
- if (flags & MONO_DL_GLOBAL && !(flags & MONO_DL_LOCAL))
+ if (mono_flags & MONO_DL_GLOBAL && !(mono_flags & MONO_DL_LOCAL))
lflags |= RTLD_GLOBAL;
else
lflags |= RTLD_LOCAL;
#else
- lflags = flags & MONO_DL_LOCAL ? RTLD_LOCAL : RTLD_GLOBAL;
+ lflags = mono_flags & MONO_DL_LOCAL ? RTLD_LOCAL : RTLD_GLOBAL;
#endif
- if (flags & MONO_DL_LAZY)
+ if (mono_flags & MONO_DL_LAZY)
lflags |= RTLD_LAZY;
else
lflags |= RTLD_NOW;
diff --git a/mono/utils/mono-dl-wasm.c b/mono/utils/mono-dl-wasm.c
index cd1ce22495e9..333d54db7991 100644
--- a/mono/utils/mono-dl-wasm.c
+++ b/mono/utils/mono-dl-wasm.c
@@ -1,4 +1,5 @@
#include
+#include
#if defined (HOST_WASM)
@@ -55,23 +56,23 @@ mono_dl_current_error_string (void)
return g_strdup ("");
}
-
+// Copied from mono-dl-posix.c
int
-mono_dl_convert_flags (int flags)
+mono_dl_convert_flags (int mono_flags, int native_flags)
{
- int lflags = 0;
+ int lflags = native_flags;
#ifdef ENABLE_NETCORE
// Specifying both will default to LOCAL
- if (flags & MONO_DL_LOCAL)
- lflags |= RTLD_LOCAL;
- else if (flags & MONO_DL_GLOBAL)
+ if (mono_flags & MONO_DL_GLOBAL && !(mono_flags & MONO_DL_LOCAL))
lflags |= RTLD_GLOBAL;
+ else
+ lflags |= RTLD_LOCAL;
#else
- lflags = flags & MONO_DL_LOCAL ? RTLD_LOCAL : RTLD_GLOBAL;
+ lflags = mono_flags & MONO_DL_LOCAL ? RTLD_LOCAL : RTLD_GLOBAL;
#endif
- if (flags & MONO_DL_LAZY)
+ if (mono_flags & MONO_DL_LAZY)
lflags |= RTLD_LAZY;
else
lflags |= RTLD_NOW;
@@ -91,4 +92,8 @@ mono_dl_close_handle (MonoDl *module)
{
}
+#else
+
+MONO_EMPTY_SOURCE_FILE (mono_dl_wasm);
+
#endif
diff --git a/mono/utils/mono-dl-windows.c b/mono/utils/mono-dl-windows.c
index 88c4911ee2b6..966d71a6b00c 100644
--- a/mono/utils/mono-dl-windows.c
+++ b/mono/utils/mono-dl-windows.c
@@ -57,7 +57,7 @@ mono_dl_open_file (const char *file, int flags)
guint32 last_error = 0;
#if HAVE_API_SUPPORT_WIN32_LOAD_LIBRARY
- hModule = LoadLibraryW (file_utf16);
+ hModule = LoadLibraryExW (file_utf16, NULL, flags);
#elif HAVE_API_SUPPORT_WIN32_LOAD_PACKAGED_LIBRARY
hModule = LoadPackagedLibrary (file_utf16, NULL);
#else
@@ -160,9 +160,10 @@ mono_dl_lookup_symbol (MonoDl *module, const char *symbol_name)
}
int
-mono_dl_convert_flags (int flags)
+mono_dl_convert_flags (int mono_flags, int native_flags)
{
- return 0;
+ // Mono flags are not applicable on Windows
+ return native_flags;
}
#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
diff --git a/mono/utils/mono-dl.c b/mono/utils/mono-dl.c
index 32fc1daed7db..ab4712778e26 100644
--- a/mono/utils/mono-dl.c
+++ b/mono/utils/mono-dl.c
@@ -220,11 +220,17 @@ mono_dl_open_self (char **error_msg)
*/
MonoDl*
mono_dl_open (const char *name, int flags, char **error_msg)
+{
+ return mono_dl_open_full (name, flags, 0, error_msg);
+}
+
+MonoDl *
+mono_dl_open_full (const char *name, int mono_flags, int native_flags, char **error_msg)
{
MonoDl *module;
void *lib;
MonoDlFallbackHandler *dl_fallback = NULL;
- int lflags = mono_dl_convert_flags (flags);
+ int lflags = mono_dl_convert_flags (mono_flags, native_flags);
char *found_name;
if (error_msg)
diff --git a/mono/utils/mono-dl.h b/mono/utils/mono-dl.h
index 6efee6feabfd..0f6132e150f3 100644
--- a/mono/utils/mono-dl.h
+++ b/mono/utils/mono-dl.h
@@ -43,7 +43,11 @@ char* mono_dl_build_path (const char *directory, const char *name, void **
MonoDl* mono_dl_open_runtime_lib (const char *lib_name, int flags, char **error_msg);
-MonoDl* mono_dl_open_self (char **error_msg);
+MonoDl *
+mono_dl_open_self (char **error_msg);
+// This converts the MONO_DL_* enum to native flags, combines it with the other flags passed, and resolves some inconsistencies
+MonoDl *
+mono_dl_open_full (const char *name, int mono_flags, int native_flags, char **error_msg);
//Platform API for mono_dl
@@ -52,7 +56,7 @@ const char** mono_dl_get_so_suffixes (void);
void* mono_dl_open_file (const char *file, int flags);
void mono_dl_close_handle (MonoDl *module);
void* mono_dl_lookup_symbol (MonoDl *module, const char *name);
-int mono_dl_convert_flags (int flags);
+int mono_dl_convert_flags (int mono_flags, int native_flags);
char* mono_dl_current_error_string (void);
int mono_dl_get_executable_path (char *buf, int buflen);
const char* mono_dl_get_system_dir (void);
diff --git a/mono/utils/mono-hwcap-vars.h b/mono/utils/mono-hwcap-vars.h
index b408568c729f..2c60a6441394 100644
--- a/mono/utils/mono-hwcap-vars.h
+++ b/mono/utils/mono-hwcap-vars.h
@@ -81,4 +81,7 @@ MONO_HWCAP_VAR(x86_has_lzcnt)
MONO_HWCAP_VAR(x86_has_popcnt)
MONO_HWCAP_VAR(x86_has_avx)
+gboolean
+mono_hwcap_x86_call_cpuidex (int id, int sub_id, int *p_eax, int *p_ebx, int *p_ecx, int *p_edx);
+
#endif
diff --git a/mono/utils/mono-hwcap-x86.c b/mono/utils/mono-hwcap-x86.c
index 7bbaa2a88a8e..40bf6d37fe78 100644
--- a/mono/utils/mono-hwcap-x86.c
+++ b/mono/utils/mono-hwcap-x86.c
@@ -29,8 +29,8 @@
#include
#endif
-static gboolean
-cpuid (int id, int *p_eax, int *p_ebx, int *p_ecx, int *p_edx)
+gboolean
+mono_hwcap_x86_call_cpuidex (int id, int sub_id, int *p_eax, int *p_ebx, int *p_ecx, int *p_edx)
{
#if defined(_MSC_VER)
int info [4];
@@ -80,7 +80,7 @@ cpuid (int id, int *p_eax, int *p_ebx, int *p_ecx, int *p_edx)
/* Now issue the actual cpuid instruction. We can use
MSVC's __cpuid on both 32-bit and 64-bit. */
#if defined(_MSC_VER)
- __cpuid (info, id);
+ __cpuidex (info, id, sub_id);
*p_eax = info [0];
*p_ebx = info [1];
*p_ecx = info [2];
@@ -93,13 +93,13 @@ cpuid (int id, int *p_eax, int *p_ebx, int *p_ecx, int *p_edx)
"cpuid\n\t"
"xchgl\t%%ebx, %k1\n\t"
: "=a" (*p_eax), "=&r" (*p_ebx), "=c" (*p_ecx), "=d" (*p_edx)
- : "0" (id)
+ : "0" (id), "2" (sub_id)
);
#else
__asm__ __volatile__ (
"cpuid\n\t"
: "=a" (*p_eax), "=b" (*p_ebx), "=c" (*p_ecx), "=d" (*p_edx)
- : "a" (id)
+ : "a" (id), "2" (sub_id)
);
#endif
@@ -111,7 +111,7 @@ mono_hwcap_arch_init (void)
{
int eax, ebx, ecx, edx;
- if (cpuid (1, &eax, &ebx, &ecx, &edx)) {
+ if (mono_hwcap_x86_call_cpuidex (1, 0, &eax, &ebx, &ecx, &edx)) {
if (edx & (1 << 15)) {
mono_hwcap_x86_has_cmov = TRUE;
@@ -144,16 +144,16 @@ mono_hwcap_arch_init (void)
mono_hwcap_x86_has_avx = TRUE;
}
- if (cpuid (0x80000000, &eax, &ebx, &ecx, &edx)) {
+ if (mono_hwcap_x86_call_cpuidex (0x80000000, 0, &eax, &ebx, &ecx, &edx)) {
if ((unsigned int) eax >= 0x80000001 && ebx == 0x68747541 && ecx == 0x444D4163 && edx == 0x69746E65) {
- if (cpuid (0x80000001, &eax, &ebx, &ecx, &edx)) {
+ if (mono_hwcap_x86_call_cpuidex (0x80000001, 0, &eax, &ebx, &ecx, &edx)) {
if (ecx & (1 << 6))
mono_hwcap_x86_has_sse4a = TRUE;
}
}
}
- if (cpuid (0x80000001, &eax, &ebx, &ecx, &edx)) {
+ if (mono_hwcap_x86_call_cpuidex (0x80000001, 0, &eax, &ebx, &ecx, &edx)) {
if (ecx & (1 << 5))
mono_hwcap_x86_has_lzcnt = TRUE;
}
diff --git a/mono/utils/mono-mmap.c b/mono/utils/mono-mmap.c
index 2dff889c4ca0..fa4686f0acac 100644
--- a/mono/utils/mono-mmap.c
+++ b/mono/utils/mono-mmap.c
@@ -305,6 +305,9 @@ mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type)
}
if ((flags & MONO_MMAP_JIT) && (use_mmap_jit || is_hardened_runtime == 1))
mflags |= MAP_JIT;
+ /* Patching code on apple silicon seems to cause random crashes without this flag */
+ if (__builtin_available (macOS 11, *))
+ mflags |= MAP_JIT;
}
#endif
diff --git a/mono/utils/mono-threads-wasm.c b/mono/utils/mono-threads-wasm.c
index e0b20fe1a8c9..33f4688fac64 100644
--- a/mono/utils/mono-threads-wasm.c
+++ b/mono/utils/mono-threads-wasm.c
@@ -2,7 +2,7 @@
#include
#include
-
+#include
#if defined (USE_WASM_BACKEND)
@@ -319,4 +319,8 @@ mono_memory_barrier_process_wide (void)
{
}
+#else
+
+MONO_EMPTY_SOURCE_FILE (mono_threads_wasm);
+
#endif
diff --git a/mono/utils/mono-threads-windows.c b/mono/utils/mono-threads-windows.c
index 8e94bf2db258..0ec80177326a 100644
--- a/mono/utils/mono-threads-windows.c
+++ b/mono/utils/mono-threads-windows.c
@@ -103,7 +103,7 @@ abort_apc (ULONG_PTR param)
// thread is going away meaning that no more IO calls will be issued against the
// same resource that was part of the cancelation. Current implementation of
// .NET Framework and .NET Core currently don't support the ability to abort a thread
-// blocked on sync IO calls, see https://github.com/dotnet/corefx/issues/5749.
+// blocked on sync IO calls, see https://github.com/dotnet/runtime/issues/16236.
// Since there is no solution covering all scenarios aborting blocking syscall this
// will be on best effort and there might still be a slight risk that the blocking call
// won't abort (depending on overlapped IO support for current file, socket).
diff --git a/sdks/android/Makefile b/sdks/android/Makefile
index 03bf58a1ca3e..ef9550e209ac 100644
--- a/sdks/android/Makefile
+++ b/sdks/android/Makefile
@@ -5,8 +5,8 @@ include $(TOP)/sdks/paths.mk
UNAME=$(shell uname)
-SDK_DIR = $(ANDROID_TOOLCHAIN_DIR)/sdk
-NDK_DIR = $(ANDROID_TOOLCHAIN_DIR)/ndk
+SDK_DIR = $(or $(ANDROID_SDK_ROOT),$(ANDROID_TOOLCHAIN_DIR)/sdk)
+NDK_DIR = $(or $(ANDROID_NDK_ROOT),$(ANDROID_TOOLCHAIN_DIR)/ndk)
ADB = $(SDK_DIR)/platform-tools/adb
@@ -62,7 +62,7 @@ shell:
.PHONY: accept-android-license
accept-android-license:
- yes | $(SDK_DIR)/tools/bin/sdkmanager --licenses
+ yes | $(SDK_DIR)/tools/bin/sdkmanager --sdk_root=$(SDK_DIR) --licenses
## Check targets
diff --git a/sdks/builds/wasm.mk b/sdks/builds/wasm.mk
index 5aaf58041890..077c6b6b0624 100644
--- a/sdks/builds/wasm.mk
+++ b/sdks/builds/wasm.mk
@@ -1,7 +1,7 @@
#emcc has lots of bash'isms
SHELL:=/bin/bash
-EMSCRIPTEN_VERSION=1.40.0
+EMSCRIPTEN_VERSION=2.0.1
EMSCRIPTEN_LOCAL_SDK_DIR=$(TOP)/sdks/builds/toolchains/emsdk
EMSCRIPTEN_SDK_DIR ?= $(EMSCRIPTEN_LOCAL_SDK_DIR)
diff --git a/sdks/wasm/ProxyDriver/ProxyDriver.csproj b/sdks/wasm/BrowserDebugHost/BrowserDebugHost.csproj
similarity index 50%
rename from sdks/wasm/ProxyDriver/ProxyDriver.csproj
rename to sdks/wasm/BrowserDebugHost/BrowserDebugHost.csproj
index c0551057f5ad..aee852c016ed 100644
--- a/sdks/wasm/ProxyDriver/ProxyDriver.csproj
+++ b/sdks/wasm/BrowserDebugHost/BrowserDebugHost.csproj
@@ -5,11 +5,9 @@
-
+
-
-
-
+
diff --git a/sdks/wasm/BrowserDebugHost/Program.cs b/sdks/wasm/BrowserDebugHost/Program.cs
new file mode 100644
index 000000000000..442e5ac1fd57
--- /dev/null
+++ b/sdks/wasm/BrowserDebugHost/Program.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Microsoft.WebAssembly.Diagnostics
+{
+ public class ProxyOptions
+ {
+ public Uri DevToolsUrl { get; set; } = new Uri("http://localhost:9222");
+ }
+
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ var host = new WebHostBuilder()
+ .UseSetting("UseIISIntegration", false.ToString())
+ .UseKestrel()
+ .UseContentRoot(Directory.GetCurrentDirectory())
+ .UseStartup()
+ .ConfigureAppConfiguration((hostingContext, config) =>
+ {
+ config.AddCommandLine(args);
+ })
+ .UseUrls("http://localhost:9300")
+ .Build();
+
+ host.Run();
+ }
+ }
+}
diff --git a/sdks/wasm/ProxyDriver/Properties/launchSettings.json b/sdks/wasm/BrowserDebugHost/Properties/launchSettings.json
similarity index 95%
rename from sdks/wasm/ProxyDriver/Properties/launchSettings.json
rename to sdks/wasm/BrowserDebugHost/Properties/launchSettings.json
index 22258c4cb66d..0acb48fc9728 100644
--- a/sdks/wasm/ProxyDriver/Properties/launchSettings.json
+++ b/sdks/wasm/BrowserDebugHost/Properties/launchSettings.json
@@ -15,7 +15,7 @@
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
- "ProxyDriver": {
+ "BrowserDebugHost": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
diff --git a/sdks/wasm/BrowserDebugHost/Startup.cs b/sdks/wasm/BrowserDebugHost/Startup.cs
new file mode 100644
index 000000000000..81c70187ed07
--- /dev/null
+++ b/sdks/wasm/BrowserDebugHost/Startup.cs
@@ -0,0 +1,164 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Text.Json;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Routing;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+
+namespace Microsoft.WebAssembly.Diagnostics
+{
+ internal class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services) =>
+ services.AddRouting()
+ .Configure(Configuration);
+
+ public Startup(IConfiguration configuration) =>
+ Configuration = configuration;
+
+ public IConfiguration Configuration { get; }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IOptionsMonitor optionsAccessor, IWebHostEnvironment env)
+ {
+ var options = optionsAccessor.CurrentValue;
+ app.UseDeveloperExceptionPage()
+ .UseWebSockets()
+ .UseDebugProxy(options);
+ }
+ }
+
+ static class DebugExtensions
+ {
+ public static Dictionary MapValues(Dictionary response, HttpContext context, Uri debuggerHost)
+ {
+ var filtered = new Dictionary();
+ var request = context.Request;
+
+ foreach (var key in response.Keys)
+ {
+ switch (key)
+ {
+ case "devtoolsFrontendUrl":
+ var front = response[key];
+ filtered[key] = $"{debuggerHost.Scheme}://{debuggerHost.Authority}{front.Replace($"ws={debuggerHost.Authority}", $"ws={request.Host}")}";
+ break;
+ case "webSocketDebuggerUrl":
+ var page = new Uri(response[key]);
+ filtered[key] = $"{page.Scheme}://{request.Host}{page.PathAndQuery}";
+ break;
+ default:
+ filtered[key] = response[key];
+ break;
+ }
+ }
+ return filtered;
+ }
+
+ public static IApplicationBuilder UseDebugProxy(this IApplicationBuilder app, ProxyOptions options) =>
+ UseDebugProxy(app, options, MapValues);
+
+ public static IApplicationBuilder UseDebugProxy(
+ this IApplicationBuilder app,
+ ProxyOptions options,
+ Func, HttpContext, Uri, Dictionary> mapFunc)
+ {
+ var devToolsHost = options.DevToolsUrl;
+ app.UseRouter(router =>
+ {
+ router.MapGet("/", Copy);
+ router.MapGet("/favicon.ico", Copy);
+ router.MapGet("json", RewriteArray);
+ router.MapGet("json/list", RewriteArray);
+ router.MapGet("json/version", RewriteSingle);
+ router.MapGet("json/new", RewriteSingle);
+ router.MapGet("devtools/page/{pageId}", ConnectProxy);
+ router.MapGet("devtools/browser/{pageId}", ConnectProxy);
+
+ string GetEndpoint(HttpContext context)
+ {
+ var request = context.Request;
+ var requestPath = request.Path;
+ return $"{devToolsHost.Scheme}://{devToolsHost.Authority}{request.Path}{request.QueryString}";
+ }
+
+ async Task Copy(HttpContext context)
+ {
+ using (var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(5) })
+ {
+ var response = await httpClient.GetAsync(GetEndpoint(context));
+ context.Response.ContentType = response.Content.Headers.ContentType.ToString();
+ if ((response.Content.Headers.ContentLength ?? 0) > 0)
+ context.Response.ContentLength = response.Content.Headers.ContentLength;
+ var bytes = await response.Content.ReadAsByteArrayAsync();
+ await context.Response.Body.WriteAsync(bytes);
+
+ }
+ }
+
+ async Task RewriteSingle(HttpContext context)
+ {
+ var version = await ProxyGetJsonAsync>(GetEndpoint(context));
+ context.Response.ContentType = "application/json";
+ await context.Response.WriteAsync(
+ JsonSerializer.Serialize(mapFunc(version, context, devToolsHost)));
+ }
+
+ async Task RewriteArray(HttpContext context)
+ {
+ var tabs = await ProxyGetJsonAsync[]>(GetEndpoint(context));
+ var alteredTabs = tabs.Select(t => mapFunc(t, context, devToolsHost)).ToArray();
+ context.Response.ContentType = "application/json";
+ await context.Response.WriteAsync(JsonSerializer.Serialize(alteredTabs));
+ }
+
+ async Task ConnectProxy(HttpContext context)
+ {
+ if (!context.WebSockets.IsWebSocketRequest)
+ {
+ context.Response.StatusCode = 400;
+ return;
+ }
+
+ var endpoint = new Uri($"ws://{devToolsHost.Authority}{context.Request.Path.ToString()}");
+ try
+ {
+ using var loggerFactory = LoggerFactory.Create(
+ builder => builder.AddConsole().AddFilter(null, LogLevel.Information));
+ var proxy = new DebuggerProxy(loggerFactory);
+ var ideSocket = await context.WebSockets.AcceptWebSocketAsync();
+
+ await proxy.Run(endpoint, ideSocket);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("got exception {0}", e);
+ }
+ }
+ });
+ return app;
+ }
+
+ static async Task ProxyGetJsonAsync(string url)
+ {
+ using (var httpClient = new HttpClient())
+ {
+ var response = await httpClient.GetAsync(url);
+ return await JsonSerializer.DeserializeAsync(await response.Content.ReadAsStreamAsync());
+ }
+ }
+ }
+}
diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/Mono.WebAssembly.DebuggerProxy.csproj b/sdks/wasm/BrowserDebugProxy/BrowserDebugProxy.csproj
similarity index 89%
rename from sdks/wasm/Mono.WebAssembly.DebuggerProxy/Mono.WebAssembly.DebuggerProxy.csproj
rename to sdks/wasm/BrowserDebugProxy/BrowserDebugProxy.csproj
index 4063416ceb07..4ac612f127a8 100644
--- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/Mono.WebAssembly.DebuggerProxy.csproj
+++ b/sdks/wasm/BrowserDebugProxy/BrowserDebugProxy.csproj
@@ -1,7 +1,7 @@
- netstandard2.1
+ netcoreapp3.0
true
diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/Mono.WebAssembly.DebuggerProxy.sln b/sdks/wasm/BrowserDebugProxy/BrowserDebugProxy.sln
similarity index 80%
rename from sdks/wasm/Mono.WebAssembly.DebuggerProxy/Mono.WebAssembly.DebuggerProxy.sln
rename to sdks/wasm/BrowserDebugProxy/BrowserDebugProxy.sln
index c99f5389610b..cfb208d1562f 100644
--- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/Mono.WebAssembly.DebuggerProxy.sln
+++ b/sdks/wasm/BrowserDebugProxy/BrowserDebugProxy.sln
@@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28407.52
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyDriver", "..\ProxyDriver\ProxyDriver.csproj", "{954F768A-23E6-4B14-90E0-27EA6B41FBCC}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BrowserDebugHost", "..\BrowserDebugHost\BrowserDebugHost.csproj", "{954F768A-23E6-4B14-90E0-27EA6B41FBCC}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.WebAssembly.DebuggerProxy", "Mono.WebAssembly.DebuggerProxy.csproj", "{490128B6-9F21-46CA-878A-F22BCF51EF3C}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BrowserDebugProxy", "BrowserDebugProxy.csproj", "{490128B6-9F21-46CA-878A-F22BCF51EF3C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/sdks/wasm/BrowserDebugProxy/DebugStore.cs b/sdks/wasm/BrowserDebugProxy/DebugStore.cs
new file mode 100644
index 000000000000..9f9c7a6bd080
--- /dev/null
+++ b/sdks/wasm/BrowserDebugProxy/DebugStore.cs
@@ -0,0 +1,883 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net.Http;
+using System.Runtime.CompilerServices;
+using System.Security.Cryptography;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Mono.Cecil.Pdb;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+namespace Microsoft.WebAssembly.Diagnostics
+{
+ internal class BreakpointRequest
+ {
+ public string Id { get; private set; }
+ public string Assembly { get; private set; }
+ public string File { get; private set; }
+ public int Line { get; private set; }
+ public int Column { get; private set; }
+ public MethodInfo Method { get; private set; }
+
+ JObject request;
+
+ public bool IsResolved => Assembly != null;
+ public List Locations { get; } = new List();
+
+ public override string ToString() => $"BreakpointRequest Assembly: {Assembly} File: {File} Line: {Line} Column: {Column}";
+
+ public object AsSetBreakpointByUrlResponse(IEnumerable