rm -rf `find $(top_distdir)/external -path '*\.git'`
rm -f `find $(top_distdir)/external -path '*\.exe' -not -path '*/roslyn-binaries/*'`
rm -f `find $(top_distdir)/external -path '*\.dll' -not -path '*/binary-reference-assemblies/*' -not -path '*/roslyn-binaries/*'`
- cp mcs/class/lib/basic/System.Configuration.dll mcs/class/lib/monolite/
- cp mcs/class/lib/basic/System.Security.dll mcs/class/lib/monolite/
-# Disable this for now because it is very slow and causes wrench to timeout:
-# test ! -d $(GIT_DIR) || ./scripts/commits-to-changelog.py --root=$(distdir) last-commit-with-compulsory-changelog-entry
pkgconfigdir = $(libdir)/pkgconfig
noinst_DATA = mono-uninstalled.pc
# building with monolite
mcslib = $(mcs_topdir)/class/lib
-monolite = $(mcslib)/monolite
monolite_url = https://download.mono-project.com/monolite/monolite-$(MONO_CORLIB_VERSION)-latest.tar.gz
.PHONY: get-monolite-latest
get-monolite-latest:
- -rm -fr $(mcslib)/monolite-*
- -mkdir -p $(mcslib)
- test ! -d $(monolite) || test ! -d $(monolite).old || rm -fr $(monolite).old
- test ! -d $(monolite) || mv -f $(monolite) $(monolite).old
+ -rm -fr $(mcslib)/monolite/$(MONO_CORLIB_VERSION)
+ -mkdir -p $(mcslib)/monolite
cd $(mcslib) && { (wget -O- $(monolite_url) || curl -L $(monolite_url)) | gzip -d | tar xf - ; }
- cd $(mcslib) && mv -f monolite-* monolite
+ cd $(mcslib) && mv -f monolite-* monolite/$(MONO_CORLIB_VERSION)
if BITCODE
BITCODE_CHECK=yes
# Process this file with autoconf to produce a configure script.
#AC_PREREQ([2.62])
-AC_INIT(mono, [5.1.0],
+AC_INIT(mono, [5.3.0],
[http://bugzilla.xamarin.com/enter_bug.cgi?classification=Mono])
AC_CONFIG_SRCDIR([README.md])
AC_CHECK_FUNCS(system)
AC_CHECK_FUNCS(fork execv execve)
AC_CHECK_FUNCS(accept4)
+ AC_CHECK_FUNCS(localtime_r)
+ AC_CHECK_FUNCS(mkdtemp)
AC_CHECK_SIZEOF(size_t)
AC_CHECK_TYPES([blksize_t], [AC_DEFINE(HAVE_BLKSIZE_T)], ,
[#include <sys/types.h>
gchar *
g_mkdtemp (char *tmp_template)
{
+#ifdef HAVE_MKDTEMP
char *template_copy = g_strdup (tmp_template);
return mkdtemp (template_copy);
+#else
+ g_error("Function not supported");
+#endif
}
* Misc.
*/
-const gchar * g_getenv(const gchar *variable);
+gboolean g_hasenv(const gchar *variable);
+gchar * g_getenv(const gchar *variable);
gboolean g_setenv(const gchar *variable, const gchar *value, gboolean overwrite);
void g_unsetenv(const gchar *variable);
#include <unistd.h>
#endif
+static pthread_mutex_t env_lock = PTHREAD_MUTEX_INITIALIZER;
-const gchar *
-g_getenv(const gchar *variable)
+/* MONO Comment
+ *
+ * As per the UNIX spec,
+ * "The return value from getenv() may point to static data which may be overwritten by subsequent calls to getenv(), setenv(), or unsetenv()."
+ * Source: Unix Manual Pages for getenv, IEEE Std 1003.1
+ *
+ * This means that using pointers returned from getenv may (and does) lead to many
+ * pointers which refer to the same piece of memory. When one is freed, all will be freed.
+ *
+ * This is unsafe and an ergonomics risk to fix in the callers. While the caller could lock,
+ * this introduces the risk for looping or exiting while inside of a lock. For this reason,
+ * g_getenv does not mimic the behavior of POSIX getenv anymore.
+ *
+ * The memory address returned will be unique to the invocaton, and must be freed.
+ * */
+gchar *
+g_getenv (const gchar *variable)
+{
+ gchar *ret = NULL;
+ pthread_mutex_lock (&env_lock);
+ gchar *res = getenv(variable);
+ if (res)
+ ret = g_strdup(res);
+ pthread_mutex_unlock (&env_lock);
+
+ return ret;
+}
+
+/*
+ * This function checks if the given variable is non-NULL
+ * in the environment. It's useful because it removes memory
+ * freeing requirements.
+ *
+ */
+gboolean
+g_hasenv (const gchar *variable)
{
- return getenv(variable);
+ pthread_mutex_lock (&env_lock);
+ gchar *res = getenv(variable);
+ gboolean not_null = (res != NULL);
+ pthread_mutex_unlock (&env_lock);
+
+ return not_null;
}
gboolean
g_setenv(const gchar *variable, const gchar *value, gboolean overwrite)
{
- return setenv(variable, value, overwrite) == 0;
+ gboolean res;
+ pthread_mutex_lock (&env_lock);
+ res = (setenv(variable, value, overwrite) == 0);
+ pthread_mutex_unlock (&env_lock);
+ return res;
}
void
g_unsetenv(const gchar *variable)
{
+ pthread_mutex_lock (&env_lock);
unsetenv(variable);
+ pthread_mutex_unlock (&env_lock);
}
gchar*
#include <io.h>
#include <assert.h>
-const gchar *
+gboolean
+g_hasenv (const gchar *variable)
+{
+ return g_getenv (variable) != NULL;
+}
+
+gchar *
g_getenv(const gchar *variable)
{
gunichar2 *var, *buffer;
-Subproject commit 6c77197318fe85dfddf75a1b344b9bf8d0007b0b
+Subproject commit febc100f0313f0dc9d75dd1bcea45e87134b5b55
-Subproject commit 229946f543f65db2b102188427cda4b68fc08ee6
+Subproject commit 5f93431f2d699e9b090a5a14db5941a18b1e171b
-Subproject commit f646c9d6a61cfc067df42b0e452448c4da7d144b
+Subproject commit 78360b22e71b70de1d8cc9588cb4ef0040449c31
# -*- makefile -*-
-with_mono_path_monolite = MONO_PATH="$(topdir)/class/lib/monolite$(PLATFORM_PATH_SEPARATOR)$(topdir)/class/lib/monolite/Facades$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH"
+monolite_path := $(topdir)/class/lib/monolite/$(MONO_CORLIB_VERSION)
+
+with_mono_path_monolite = MONO_PATH="$(monolite_path)$(PLATFORM_PATH_SEPARATOR)$(monolite_path)/Facades$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH"
monolite_flag := $(depsdir)/use-monolite
use_monolite := $(wildcard $(monolite_flag))
-MONOLITE_MSCORLIB = $(topdir)/class/lib/monolite/mscorlib.dll
+MONOLITE_MSCORLIB = $(monolite_path)/mscorlib.dll
ifdef use_monolite
ifdef MCS_MODE
- CSC_LOCATION = $(topdir)/class/lib/monolite/mcs.exe
+ CSC_LOCATION = $(monolite_path)/mcs.exe
endif
PROFILE_RUNTIME = $(with_mono_path_monolite) $(RUNTIME)
$(MAKE) $(MAKE_Q) do-profile-check-monolite ; \
else \
echo "*** The runtime '$(PROFILE_RUNTIME)' doesn't appear to be usable." 1>&2; \
- echo "*** You need Mono version 4.8 or better installed to build MCS" 1>&2 ; \
- echo "*** Check mono README for information on how to bootstrap a Mono installation." 1>&2 ; \
+ echo "*** Check README for information on how to bootstrap a Mono installation." 1>&2 ; \
exit 1; fi; fi
do-get-monolite:
do-profile-check-monolite:
- @echo "*** The contents of your 'monolite' directory may be out-of-date" 1>&2
+ @echo "*** The contents of your 'monolite/$(MONO_CORLIB_VERSION)' directory may be out-of-date" 1>&2
@echo "*** You may want to try 'make get-monolite-latest'" 1>&2
rm -f $(monolite_flag)
exit 1
else
do-get-monolite:
- @echo "*** Downloading bootstrap required 'monolite'" 1>&2
+ @echo "*** Downloading bootstrap required 'monolite/$(MONO_CORLIB_VERSION)'" 1>&2
$(MAKE) $(MAKE_Q) -C $(mono_build_root) get-monolite-latest
do-profile-check-monolite: $(depsdir)/.stamp
@echo "*** The runtime '$(PROFILE_RUNTIME)' doesn't appear to be usable." 1>&2
- @echo "*** Trying the 'monolite' directory." 1>&2
+ @echo "*** Trying the 'monolite/$(MONO_CORLIB_VERSION)' directory." 1>&2
@echo dummy > $(monolite_flag)
$(MAKE) do-profile-check
-d:MOBILE,MOBILE_LEGACY \
-d:FULL_AOT_DESKTOP \
-d:FULL_AOT_RUNTIME \
+ -d:ORBIS \
-d:DISABLE_REMOTING \
-d:DISABLE_COM \
-nowarn:1699 \
MOBILE_PROFILE = yes
NO_VTS_TEST = yes
NO_CONSOLE = yes
+PROFILE_DISABLE_BTLS = yes
# Note need for trailing comma. If you add, keep it
PROFILE_TEST_HARNESS_EXCLUDES = MobileNotWorking,PKITS,
USE_MBAS_FLAGS = /codepage:$(CODEPAGE) $(LOCAL_MBAS_FLAGS) $(PLATFORM_MBAS_FLAGS) $(PROFILE_MBAS_FLAGS) $(MBAS_FLAGS)
USE_CFLAGS = $(LOCAL_CFLAGS) $(CFLAGS) $(CPPFLAGS)
CSCOMPILE = $(Q_MCS) $(MCS) $(USE_MCS_FLAGS)
-CSC_RUNTIME_FLAGS = --aot-path=$(topdir)/class/lib/$(BUILD_TOOLS_PROFILE) --gc-params=nursery-size=64m
+CSC_RUNTIME_FLAGS = --aot-path=$(abspath $(topdir)/class/lib/$(BUILD_TOOLS_PROFILE)) --gc-params=nursery-size=64m
BASCOMPILE = $(MBAS) $(USE_MBAS_FLAGS)
CCOMPILE = $(CC) $(USE_CFLAGS)
BOOT_COMPILE = $(Q_MCS) $(BOOTSTRAP_MCS) $(USE_MCS_FLAGS)
KEY_FILE = ../../msfinal.pub
SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699
LIB_REFS = System
-LIB_MCS_FLAGS = $(SIGN_FLAGS) -unsafe -nowarn:3021
+LIB_MCS_FLAGS = $(SIGN_FLAGS)
-RESX_RESOURCE_STRING = \
- ../../../../external/corefx/src/System.Threading.Overlapped/src/Resources/Strings.resx
+PLATFORM_DEBUG_FLAGS =
NO_TEST = yes
TypeForwarders.cs
AssemblyInfo.cs
-
-corefx/SR.cs
-
-../../../../external/corefx/src/Common/src/System/HResults.cs
-../../../../external/corefx/src/System.Threading.Overlapped/src/System/Threading/ClrThreadPoolBoundHandle.cs
-../../../../external/corefx/src/System.Threading.Overlapped/src/System/Threading/ClrThreadPoolBoundHandleOverlapped.cs
-../../../../external/corefx/src/System.Threading.Overlapped/src/System/Threading/ClrThreadPoolPreAllocatedOverlapped.cs
-../../../../external/corefx/src/System.Threading.Overlapped/src/System/Threading/DeferredDisposableLifetime.cs
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Threading.IOCompletionCallback))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Threading.NativeOverlapped))]
+[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Threading.PreAllocatedOverlapped))]
+[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Threading.ThreadPoolBoundHandle))]
+++ /dev/null
-//
-// This file was generated by resx2sr tool
-//
-
-partial class SR
-{
- public const string Argument_AlreadyBoundOrSyncHandle = "'handle' has already been bound to the thread pool, or was not opened for asynchronous I/O.";
- public const string Argument_InvalidHandle = "'handle' has been disposed or is an invalid handle.";
- public const string Argument_NativeOverlappedAlreadyFree = "'overlapped' has already been freed.";
- public const string Argument_NativeOverlappedWrongBoundHandle = "'overlapped' was not allocated by this ThreadPoolBoundHandle instance.";
- public const string Argument_PreAllocatedAlreadyAllocated = "'preAllocated' is already in use.";
- public const string InvalidOperation_NativeOverlappedReused = "NativeOverlapped cannot be reused for multiple operations.";
-}
$(xbuild_2_0_dirs) \
Microsoft.Build
+orbis_exclude_dirs := \
+ Microsoft.CSharp \
+ Mono.CSharp \
+ Mono.Data.Sqlite
+
monodroid_SUBDIRS := $(monodroid_dirs)
monotouch_SUBDIRS := $(monotouch_dirs)
monotouch_watch_SUBDIRS := $(monotouch_watch_dirs)
xbuild_12_SUBDIRS := $(xbuild_4_0_dirs)
xbuild_14_SUBDIRS := $(xbuild_4_0_dirs) Microsoft.NuGet.Build.Tasks
winaot_SUBDIRS := $(winaot_dirs)
-orbis_SUBDIRS := $(monotouch_dirs)
+orbis_SUBDIRS := $(filter-out $(orbis_exclude_dirs),$(monotouch_dirs))
include ../build/rules.make
all-local-aot:
-monolite_dir := monolite
+monolite_dir := monolite/$(MONO_CORLIB_VERSION)
# Files needed to bootstrap C# compiler
build_files = mscorlib.dll System.dll System.Xml.dll Mono.Security.dll System.Core.dll System.Security.dll System.Configuration.dll \
namespace MonoTests.System.Linq.Expressions {
[TestFixture]
- public class ExpressionTest_Loop {
+ public class ExpressionTest_Loop
+ {
+ public static void Print (int arg)
+ {
+ }
[Test]
public void ComplexTest ()
{
- var breakLabel = Expression.Label ("LoopBreak");
- var counter = Expression.Variable (typeof (int), "counter");
+ var breakLabel = Expression.Label ("LoopBreak");
+ var counter = Expression.Variable (typeof (int), "counter");
- var l = Expression.Block (new[] { counter },
- Expression.Assign (counter, Expression.Constant (-1)),
- Expression.Loop (
- Expression.Block (Expression.IfThenElse (
- Expression.Equal (Expression.Assign (counter, Expression.Add (counter, Expression.Constant (1))), Expression.Constant (1000)),
- Expression.Block (Expression.Break (breakLabel)),
- Expression.Call (null, typeof (Console).GetMethod ("WriteLine", new Type[] { typeof (int) }), counter)
- )),
- breakLabel)
- );
+ var l = Expression.Block (new[] { counter },
+ Expression.Assign (counter, Expression.Constant (-1)),
+ Expression.Loop (
+ Expression.Block (Expression.IfThenElse (
+ Expression.Equal (Expression.Assign (counter, Expression.Add (counter, Expression.Constant (1))), Expression.Constant (1000)),
+ Expression.Block (Expression.Break (breakLabel)),
+ Expression.Call (null, typeof (ExpressionTest_Loop).GetMethod ("Print", new Type[] { typeof (int) }), counter)
+ )),
+ breakLabel)
+ );
- var res = Expression.Lambda<Action> (l).Compile ();
- }
+ var res = Expression.Lambda<Action> (l).Compile ();
+ }
[Test]
public void ComplexTest_2 ()
{
- var breakLabel = Expression.Label ("LoopBreak");
- var counter = Expression.Variable (typeof (int), "counter");
+ var breakLabel = Expression.Label ("LoopBreak");
+ var counter = Expression.Variable (typeof (int), "counter");
- var l = Expression.Block (new[] { counter },
- Expression.Assign (counter, Expression.Constant(-1)),
- Expression.Loop (
- Expression.IfThenElse (
- Expression.Equal (Expression.Assign (counter, Expression.Add (counter, Expression.Constant (1))), Expression.Constant (1000)),
- Expression.Break (breakLabel),
- Expression.Call (null, typeof (Console).GetMethod ("WriteLine", new Type[] { typeof (int) }), counter)
- ),
- breakLabel)
- );
+ var l = Expression.Block (new[] { counter },
+ Expression.Assign (counter, Expression.Constant(-1)),
+ Expression.Loop (
+ Expression.IfThenElse (
+ Expression.Equal (Expression.Assign (counter, Expression.Add (counter, Expression.Constant (1))), Expression.Constant (1000)),
+ Expression.Break (breakLabel),
+ Expression.Call (null, typeof (ExpressionTest_Loop).GetMethod ("Print", new Type[] { typeof (int) }), counter)
+ ),
+ breakLabel)
+ );
- var res = Expression.Lambda<Action> (l).Compile ();
+ var res = Expression.Lambda<Action> (l).Compile ();
}
}
}
System.Security.Cryptography/MD5Cng.cs
System.Security.Cryptography/SHA1Cng.cs
System.Security.Cryptography/SHA256Cng.cs
-System.Security.Cryptography/SHA256CryptoServiceProvider.cs
System.Security.Cryptography/SHA384Cng.cs
-System.Security.Cryptography/SHA384CryptoServiceProvider.cs
System.Security.Cryptography/SHA512Cng.cs
-System.Security.Cryptography/SHA512CryptoServiceProvider.cs
../referencesource/System.Core/System/Security/Cryptography/AesManaged.cs
../referencesource/System.Core/System/Security/Cryptography/ECDiffieHellman.cs
System.Security.Cryptography/MD5Cng.cs
System.Security.Cryptography/SHA1Cng.cs
System.Security.Cryptography/SHA256Cng.cs
-System.Security.Cryptography/SHA256CryptoServiceProvider.cs
System.Security.Cryptography/SHA384Cng.cs
-System.Security.Cryptography/SHA384CryptoServiceProvider.cs
System.Security.Cryptography/SHA512Cng.cs
-System.Security.Cryptography/SHA512CryptoServiceProvider.cs
../referencesource/System.Core/System/Security/Cryptography/AesManaged.cs
../referencesource/System.Core/System/Security/Cryptography/ECDiffieHellman.cs
--- /dev/null
+#include common_System.Security.dll.sources
<Compile Include="..\referencesource\System.Web\Configuration\WebLevel.cs" />\r
<Compile Include="..\referencesource\System.Web\Configuration\XhtmlConformanceMode.cs" />\r
<Compile Include="..\referencesource\System.Web\Hosting\AppDomainProtocolHandler.cs" />\r
+ <Compile Include="..\referencesource\System.Web\Hosting\BackgroundWorkScheduler.cs" />\r
<Compile Include="..\referencesource\System.Web\Hosting\HostingEnvironmentException.cs" />\r
<Compile Include="..\referencesource\System.Web\Hosting\HTTP_COOKED_URL.cs" />\r
<Compile Include="..\referencesource\System.Web\Hosting\IApplicationHost.cs" />\r
<Compile Include="..\referencesource\System.Web\Util\AppVerifierException.cs" />\r
<Compile Include="..\referencesource\System.Web\Util\AssemblyUtil.cs" />\r
<Compile Include="..\referencesource\System.Web\Util\BinaryCompatibility.cs" />\r
+ <Compile Include="..\referencesource\System.Web\Util\CancellationTokenHelper.cs" />\r
<Compile Include="..\referencesource\System.Web\Util\DateTimeUtil.cs" />\r
<Compile Include="..\referencesource\System.Web\Util\Debug.cs" />\r
<Compile Include="..\referencesource\System.Web\Util\DisposableAction.cs" />\r
<Compile Include="..\referencesource\System.Web\Configuration\WebLevel.cs" />\r
<Compile Include="..\referencesource\System.Web\Configuration\XhtmlConformanceMode.cs" />\r
<Compile Include="..\referencesource\System.Web\Hosting\AppDomainProtocolHandler.cs" />\r
+ <Compile Include="..\referencesource\System.Web\Hosting\BackgroundWorkScheduler.cs" />\r
<Compile Include="..\referencesource\System.Web\Hosting\HostingEnvironmentException.cs" />\r
<Compile Include="..\referencesource\System.Web\Hosting\HTTP_COOKED_URL.cs" />\r
<Compile Include="..\referencesource\System.Web\Hosting\IApplicationHost.cs" />\r
<Compile Include="..\referencesource\System.Web\Util\AppVerifierException.cs" />\r
<Compile Include="..\referencesource\System.Web\Util\AssemblyUtil.cs" />\r
<Compile Include="..\referencesource\System.Web\Util\BinaryCompatibility.cs" />\r
+ <Compile Include="..\referencesource\System.Web\Util\CancellationTokenHelper.cs" />\r
<Compile Include="..\referencesource\System.Web\Util\DateTimeUtil.cs" />\r
<Compile Include="..\referencesource\System.Web\Util\Debug.cs" />\r
<Compile Include="..\referencesource\System.Web\Util\DisposableAction.cs" />\r
using System;
+using System.Collections.Generic;
using System.Globalization;
+using System.Linq;
using System.Security.Permissions;
using System.Threading;
+using System.Threading.Tasks;
using System.Web.Configuration;
using System.Web.Caching;
using System.Web.Util;
static VirtualPathProvider vpath_provider = (HttpRuntime.AppDomainAppVirtualPath == null) ? null :
new DefaultVirtualPathProvider ();
static int busy_count;
+ static BackgroundWorkScheduler _backgroundWorkScheduler = null; // created on demand
+ static readonly Task<object> _completedTask = Task.FromResult<object>(null);
internal static bool HaveCustomVPP {
get;
if (Host != null)
Host.UnregisterObject (obj);
}
+
+ // Schedules a task which can run in the background, independent of any request.
+ // This differs from a normal ThreadPool work item in that ASP.NET can keep track
+ // of how many work items registered through this API are currently running, and
+ // the ASP.NET runtime will try not to delay AppDomain shutdown until these work
+ // items have finished executing.
+ //
+ // Usage notes:
+ // - This API cannot be called outside of an ASP.NET-managed AppDomain.
+ // - The caller's ExecutionContext is not flowed to the work item.
+ // - Scheduled work items are not guaranteed to ever execute, e.g., when AppDomain
+ // shutdown has already started by the time this API was called.
+ // - The provided CancellationToken will be signaled when the application is
+ // shutting down. The work item should make every effort to honor this token.
+ // If a work item does not honor this token and continues executing it will
+ // eventually be considered rogue, and the ASP.NET runtime will rudely unload
+ // the AppDomain without waiting for the work item to finish.
+ //
+ // This overload of QueueBackgroundWorkItem takes a void-returning callback; the
+ // work item will be considered finished when the callback returns.
+ [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public static void QueueBackgroundWorkItem(Action<CancellationToken> workItem) {
+ if (workItem == null) {
+ throw new ArgumentNullException("workItem");
+ }
+
+ QueueBackgroundWorkItem(ct => { workItem(ct); return _completedTask; });
+ }
+
+ // See documentation on the other overload for a general API overview.
+ //
+ // This overload of QueueBackgroundWorkItem takes a Task-returning callback; the
+ // work item will be considered finished when the returned Task transitions to a
+ // terminal state.
+ [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public static void QueueBackgroundWorkItem(Func<CancellationToken, Task> workItem) {
+ if (workItem == null) {
+ throw new ArgumentNullException("workItem");
+ }
+ if (Host == null) {
+ throw new InvalidOperationException(); // can only be called within an ASP.NET AppDomain
+ }
+
+ QueueBackgroundWorkItemInternal(workItem);
+ }
+
+ static void QueueBackgroundWorkItemInternal(Func<CancellationToken, Task> workItem) {
+ Debug.Assert(workItem != null);
+
+ BackgroundWorkScheduler scheduler = Volatile.Read(ref _backgroundWorkScheduler);
+
+ // If the scheduler doesn't exist, lazily create it, but only allow one instance to ever be published to the backing field
+ if (scheduler == null) {
+ BackgroundWorkScheduler newlyCreatedScheduler = new BackgroundWorkScheduler(UnregisterObject, WriteUnhandledException);
+ scheduler = Interlocked.CompareExchange(ref _backgroundWorkScheduler, newlyCreatedScheduler, null) ?? newlyCreatedScheduler;
+ if (scheduler == newlyCreatedScheduler) {
+ RegisterObject(scheduler); // Only call RegisterObject if we just created the "winning" one
+ }
+ }
+
+ scheduler.ScheduleWorkItem(workItem);
+ }
+
+ static void WriteUnhandledException (AppDomain appDomain, Exception exception)
+ {
+ Console.Error.WriteLine ("Error in background work item: " + exception);
+ }
}
}
System.Web.Hosting/ApplicationInfo.cs
System.Web.Hosting/ApplicationHost.cs
System.Web.Hosting/ApplicationManager.cs
+../referencesource/System.Web/Hosting/BackgroundWorkScheduler.cs
System.Web.Hosting/BareApplicationHost.cs
System.Web.Hosting/DefaultVirtualDirectory.cs
System.Web.Hosting/DefaultVirtualFile.cs
System.Web.UI/XhtmlTextWriter.cs
System.Web.UI/XPathBinder.cs
System.Web.Util/AltSerialization.cs
+../referencesource/System.Web/Util/CancellationTokenHelper.cs
System.Web.Util/DataSourceHelper.cs
System.Web.Util/DataSourceResolver.cs
System.Web.Util/FileUtils.cs
RESX_RESOURCE_STRING = \
../../../external/corefx/src/System.Collections.Concurrent/src/Resources/Strings.resx \
- ../../../external/corefx/src/System.Collections/src/Resources/Strings.resx
+ ../../../external/corefx/src/System.Collections/src/Resources/Strings.resx \
+ ../../../external/corefx/src/System.Buffers/src/Resources/Strings.resx
TEST_RESOURCES = \
Test/System/test-uri-props.txt \
{
#if MONOTOUCH
is_macosx = true;
-#elif MONODROID
+#elif MONODROID || ORBIS
is_macosx = false;
#else
is_macosx = Environment.OSVersion.Platform != PlatformID.Win32NT && System.IO.File.Exists (OSX509Certificates.SecurityLibrary);
}
#else
if (is_macosx) {
+#if !ORBIS
// Attempt to use OSX certificates
// Ideally we should return the SecTrustResult
OSX509Certificates.SecTrustResult trustResult = OSX509Certificates.SecTrustResult.Deny;
status11 = (int)trustResult;
errors |= SslPolicyErrors.RemoteCertificateChainErrors;
}
+#else
+ throw new PlatformNotSupportedException ();
+#endif
} else {
result = BuildX509Chain (certs, chain, ref errors, ref status11);
}
<Compile Include="..\..\..\external\corefx\src\Common\src\System\Collections\Generic\LargeArrayBuilder.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Common\src\System\CSharpHelpers.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Common\src\System\IO\TempFileCollection.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\Logging\NetEventSource.Common.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\SecurityProtocol.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\UriScheme.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\WebSockets\ManagedWebSocket.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\WebSockets\WebSocketValidate.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\StringExtensions.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Buffers\src\System\Buffers\ArrayPool.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Buffers\src\System\Buffers\ArrayPoolEventSource.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Buffers\src\System\Buffers\DefaultArrayPool.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Buffers\src\System\Buffers\DefaultArrayPoolBucket.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Buffers\src\System\Buffers\Utilities.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.CodeDom\src\Microsoft\CSharp\CSharpCodeGenerator.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.CodeDom\src\Microsoft\CSharp\CSharpCodeProvider.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.CodeDom\src\Microsoft\CSharp\CSharpMemberAttributeConverter.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.IO.Compression\src\System\IO\Compression\CompressionLevel.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.IO.Compression\src\System\IO\Compression\CompressionMode.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.IO.Compression\src\System\IO\Compression\GZipStream.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.HttpListener\src\System\Net\WebSockets\HttpListenerWebSocketContext.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets.Client\src\System\Net\WebSockets\ClientWebSocket.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets.Client\src\System\Net\WebSockets\ClientWebSocketOptions.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets.Client\src\System\Net\WebSockets\WebSocketHandle.Managed.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocket.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketCloseStatus.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketContext.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketError.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketException.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketMessageType.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketReceiveResult.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketState.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Runtime.Extensions\src\System\CodeDom\Compiler\IndentedTextWriter.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Runtime\src\System\Collections\Generic\ISet.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Security.Cryptography.X509Certificates\src\System\Security\Cryptography\X509Certificates\OpenFlags.cs" />\r
<Compile Include="System.Net.Sockets\SocketReceiveFromResult.cs" />\r
<Compile Include="System.Net.Sockets\SocketReceiveMessageFromResult.cs" />\r
<Compile Include="System.Net.Sockets\SocketTaskExtensions.cs" />\r
- <Compile Include="System.Net.WebSockets\ClientWebSocket.cs" />\r
- <Compile Include="System.Net.WebSockets\ClientWebSocketOptions.cs" />\r
- <Compile Include="System.Net.WebSockets\HttpListenerWebSocketContext.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocket.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketCloseStatus.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketContext.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketError.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketException.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketMessageType.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketReceiveResult.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketState.cs" />\r
<Compile Include="System.Net\AuthenticationManager.cs" />\r
<Compile Include="System.Net\BasicClient.cs" />\r
<Compile Include="System.Net\BindIPEndPoint.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Common\src\System\Collections\Generic\LargeArrayBuilder.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Common\src\System\CSharpHelpers.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Common\src\System\IO\TempFileCollection.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\Logging\NetEventSource.Common.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\SecurityProtocol.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\UriScheme.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\WebSockets\ManagedWebSocket.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\WebSockets\WebSocketValidate.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\StringExtensions.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Buffers\src\System\Buffers\ArrayPool.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Buffers\src\System\Buffers\ArrayPoolEventSource.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Buffers\src\System\Buffers\DefaultArrayPool.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Buffers\src\System\Buffers\DefaultArrayPoolBucket.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Buffers\src\System\Buffers\Utilities.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.CodeDom\src\Microsoft\CSharp\CSharpCodeGenerator.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.CodeDom\src\Microsoft\CSharp\CSharpCodeProvider.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.CodeDom\src\Microsoft\CSharp\CSharpMemberAttributeConverter.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.IO.Compression\src\System\IO\Compression\CompressionLevel.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.IO.Compression\src\System\IO\Compression\CompressionMode.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.IO.Compression\src\System\IO\Compression\GZipStream.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.HttpListener\src\System\Net\WebSockets\HttpListenerWebSocketContext.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets.Client\src\System\Net\WebSockets\ClientWebSocket.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets.Client\src\System\Net\WebSockets\ClientWebSocketOptions.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets.Client\src\System\Net\WebSockets\WebSocketHandle.Managed.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocket.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketCloseStatus.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketContext.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketError.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketException.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketMessageType.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketReceiveResult.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketState.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Runtime.Extensions\src\System\CodeDom\Compiler\IndentedTextWriter.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Runtime\src\System\Collections\Generic\ISet.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Security.Cryptography.X509Certificates\src\System\Security\Cryptography\X509Certificates\OpenFlags.cs" />\r
<Compile Include="System.Net.Sockets\SocketReceiveFromResult.cs" />\r
<Compile Include="System.Net.Sockets\SocketReceiveMessageFromResult.cs" />\r
<Compile Include="System.Net.Sockets\SocketTaskExtensions.cs" />\r
- <Compile Include="System.Net.WebSockets\ClientWebSocket.cs" />\r
- <Compile Include="System.Net.WebSockets\ClientWebSocketOptions.cs" />\r
- <Compile Include="System.Net.WebSockets\HttpListenerWebSocketContext.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocket.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketCloseStatus.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketContext.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketError.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketException.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketMessageType.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketReceiveResult.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketState.cs" />\r
<Compile Include="System.Net\AuthenticationManager.cs" />\r
<Compile Include="System.Net\BasicClient.cs" />\r
<Compile Include="System.Net\BindIPEndPoint.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Common\src\System\Collections\Generic\LargeArrayBuilder.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Common\src\System\CSharpHelpers.cs" />\r
<Compile Include="..\..\..\external\corefx\src\Common\src\System\IO\TempFileCollection.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\Logging\NetEventSource.Common.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\SecurityProtocol.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\UriScheme.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\WebSockets\ManagedWebSocket.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\WebSockets\WebSocketValidate.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\Common\src\System\StringExtensions.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Buffers\src\System\Buffers\ArrayPool.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Buffers\src\System\Buffers\ArrayPoolEventSource.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Buffers\src\System\Buffers\DefaultArrayPool.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Buffers\src\System\Buffers\DefaultArrayPoolBucket.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Buffers\src\System\Buffers\Utilities.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.CodeDom\src\Microsoft\CSharp\CSharpCodeGenerator.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.CodeDom\src\Microsoft\CSharp\CSharpCodeProvider.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.CodeDom\src\Microsoft\CSharp\CSharpMemberAttributeConverter.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.IO.Compression\src\System\IO\Compression\CompressionLevel.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.IO.Compression\src\System\IO\Compression\CompressionMode.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.IO.Compression\src\System\IO\Compression\GZipStream.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.HttpListener\src\System\Net\WebSockets\HttpListenerWebSocketContext.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets.Client\src\System\Net\WebSockets\ClientWebSocket.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets.Client\src\System\Net\WebSockets\ClientWebSocketOptions.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets.Client\src\System\Net\WebSockets\WebSocketHandle.Managed.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocket.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketCloseStatus.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketContext.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketError.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketException.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketMessageType.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketReceiveResult.cs" />\r
+ <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets\src\System\Net\WebSockets\WebSocketState.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Runtime.Extensions\src\System\CodeDom\Compiler\IndentedTextWriter.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Runtime\src\System\Collections\Generic\ISet.cs" />\r
<Compile Include="..\..\..\external\corefx\src\System.Security.Cryptography.X509Certificates\src\System\Security\Cryptography\X509Certificates\OpenFlags.cs" />\r
<Compile Include="System.Net.Sockets\SocketReceiveFromResult.cs" />\r
<Compile Include="System.Net.Sockets\SocketReceiveMessageFromResult.cs" />\r
<Compile Include="System.Net.Sockets\SocketTaskExtensions.cs" />\r
- <Compile Include="System.Net.WebSockets\ClientWebSocket.cs" />\r
- <Compile Include="System.Net.WebSockets\ClientWebSocketOptions.cs" />\r
- <Compile Include="System.Net.WebSockets\HttpListenerWebSocketContext.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocket.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketCloseStatus.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketContext.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketError.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketException.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketMessageType.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketReceiveResult.cs" />\r
- <Compile Include="System.Net.WebSockets\WebSocketState.cs" />\r
<Compile Include="System.Net\AuthenticationManager.cs" />\r
<Compile Include="System.Net\BasicClient.cs" />\r
<Compile Include="System.Net\BindIPEndPoint.cs" />\r
const string LIBNAME = "MonoPosixHelper";
#endif
+#if !ORBIS
[DllImport (LIBNAME, CallingConvention=CallingConvention.Cdecl)]
static extern IntPtr CreateZStream (CompressionMode compress, bool gzip, UnmanagedReadOrWrite feeder, IntPtr data);
[DllImport (LIBNAME, CallingConvention=CallingConvention.Cdecl)]
static extern int WriteZStream (IntPtr stream, IntPtr buffer, int length);
+#else
+ static IntPtr CreateZStream (CompressionMode compress, bool gzip, UnmanagedReadOrWrite feeder, IntPtr data)
+ {
+ throw new PlatformNotSupportedException ();
+ }
+
+ static int CloseZStream (IntPtr stream)
+ {
+ throw new PlatformNotSupportedException ();
+ }
+
+ static int Flush (IntPtr stream)
+ {
+ throw new PlatformNotSupportedException ();
+ }
+
+ static int ReadZStream (IntPtr stream, IntPtr buffer, int length)
+ {
+ throw new PlatformNotSupportedException ();
+ }
+
+ static int WriteZStream (IntPtr stream, IntPtr buffer, int length)
+ {
+ throw new PlatformNotSupportedException ();
+ }
+#endif
+
}
}
[DllImport ("libc")]
static extern int gethostname ([MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 1)] byte [] name, int len);
+#if !ORBIS
[DllImport ("libc")]
static extern int getdomainname ([MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 1)] byte [] name, int len);
+#else
+ static int getdomainname ([MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 1)] byte [] name, int len)
+ {
+ throw new PlatformNotSupportedException ();
+ }
+#endif
public override string DhcpScopeName {
get { return String.Empty; }
static void MaybeCreate ()
{
-#if MONOTOUCH_WATCH
+#if MONOTOUCH_WATCH || ORBIS
throw new PlatformNotSupportedException ("NetworkInformation.NetworkChange is not supported on the current platform.");
#else
if (networkChange != null)
}
}
-#if !MONOTOUCH_WATCH
+#if !MONOTOUCH_WATCH && !ORBIS
internal sealed class MacNetworkChange : INetworkChange
{
const string DL_LIB = "/usr/lib/libSystem.dylib";
}
#endif // !MONOTOUCH_WATCH
-#if !NETWORK_CHANGE_STANDALONE && !MONOTOUCH
+#if !NETWORK_CHANGE_STANDALONE && !MONOTOUCH && !ORBIS
internal sealed class LinuxNetworkChange : INetworkChange {
[Flags]
{
internal abstract class UnixNetworkInterfaceAPI : NetworkInterfaceFactory
{
+#if ORBIS
+ public static int if_nametoindex(string ifname)
+ {
+ throw new PlatformNotSupportedException ();
+ }
+
+ protected static int getifaddrs (out IntPtr ifap)
+ {
+ throw new PlatformNotSupportedException ();
+ }
+
+ protected static void freeifaddrs (IntPtr ifap)
+ {
+ throw new PlatformNotSupportedException ();
+ }
+#else
[DllImport("libc")]
public static extern int if_nametoindex(string ifname);
[DllImport ("libc")]
protected static extern void freeifaddrs (IntPtr ifap);
+#endif
}
class MacOsNetworkInterfaceAPI : UnixNetworkInterfaceAPI
public event PingCompletedEventHandler PingCompleted;
-#if !MONOTOUCH
+#if !MONOTOUCH && !ORBIS
static Ping ()
{
if (Environment.OSVersion.Platform == PlatformID.Unix) {
identifier = (ushort)(randomIdentifier [0] + (randomIdentifier [1] << 8));
}
-#if !MONOTOUCH
+#if !MONOTOUCH && !ORBIS
[DllImport ("libc", EntryPoint="capget")]
static extern int capget (ref cap_user_header_t header, ref cap_user_data_t data);
using HashAlgorithmType = System.Security.Authentication.HashAlgorithmType;
using ExchangeAlgorithmType = System.Security.Authentication.ExchangeAlgorithmType;
-using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Permissions;
using System.Security.Principal;
using System.Security.Cryptography;
-
using System.Threading.Tasks;
using MNS = Mono.Net.Security;
}
}
#else // !SECURITY_DEP
+
+using System.IO;
+using System.Threading.Tasks;
+
namespace System.Net.Security
{
- public class SslStream
+ public class SslStream : Stream
{
+ public SslStream (object innerStream)
+ {
+ }
+
+ public override bool CanRead {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+
+ public override bool CanSeek {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+
+ public override bool CanWrite {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+
+ public override long Length {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+
+ public override long Position {
+ get {
+ throw new NotImplementedException ();
+ }
+
+ set {
+ throw new NotImplementedException ();
+ }
+ }
+
+ public override void Flush ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override int Read (System.Byte [] buffer, int offset, int count)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override long Seek (long offset, SeekOrigin origin)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override void SetLength (long value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override void Write (System.Byte [] buffer, int offset, int count)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public virtual Task AuthenticateAsClientAsync (string targetHost, object clientCertificates, object enabledSslProtocols, bool checkCertificateRevocation)
+ {
+ throw new NotImplementedException ();
+ }
}
}
#endif
+++ /dev/null
-//
-// ClientWebSocket.cs
-//
-// Authors:
-// Jérémie Laval <jeremie dot laval at xamarin dot com>
-//
-// Copyright 2013 Xamarin Inc (http://www.xamarin.com).
-//
-// Lightly inspired from WebSocket4Net distributed under the Apache License 2.0
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-
-using System;
-using System.Net;
-using System.Net.Sockets;
-using System.Security.Principal;
-using System.Security.Cryptography.X509Certificates;
-using System.Runtime.CompilerServices;
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Globalization;
-using System.Text;
-using System.Security.Cryptography;
-
-namespace System.Net.WebSockets
-{
- public class ClientWebSocket : WebSocket, IDisposable
- {
- const string Magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
- const string VersionTag = "13";
-
- ClientWebSocketOptions options;
- WebSocketState state;
- string subProtocol;
-
- HttpWebRequest req;
- WebConnection connection;
- Socket underlyingSocket;
-
- Random random = new Random ();
-
- const int HeaderMaxLength = 14;
- byte[] headerBuffer;
- byte[] sendBuffer;
- long remaining;
- WebSocketMessageType currentMessageType;
-
- public ClientWebSocket ()
- {
- options = new ClientWebSocketOptions ();
- state = WebSocketState.None;
- headerBuffer = new byte[HeaderMaxLength];
- }
-
- public override void Dispose ()
- {
- if (connection != null)
- connection.Close (false);
- }
-
- [MonoTODO]
- public override void Abort ()
- {
- throw new NotImplementedException ();
- }
-
- public ClientWebSocketOptions Options {
- get {
- return options;
- }
- }
-
- public override WebSocketState State {
- get {
- return state;
- }
- }
-
- public override WebSocketCloseStatus? CloseStatus {
- get {
- if (state != WebSocketState.Closed)
- return (WebSocketCloseStatus?)null;
- return WebSocketCloseStatus.Empty;
- }
- }
-
- public override string CloseStatusDescription {
- get {
- return null;
- }
- }
-
- public override string SubProtocol {
- get {
- return subProtocol;
- }
- }
-
- public async Task ConnectAsync (Uri uri, CancellationToken cancellationToken)
- {
- state = WebSocketState.Connecting;
- var httpUri = new UriBuilder (uri);
- if (uri.Scheme == "wss")
- httpUri.Scheme = "https";
- else
- httpUri.Scheme = "http";
- req = (HttpWebRequest)WebRequest.Create (httpUri.Uri);
- req.ReuseConnection = true;
- if (options.Cookies != null)
- req.CookieContainer = options.Cookies;
-
- if (options.CustomRequestHeaders.Count > 0) {
- foreach (var header in options.CustomRequestHeaders)
- req.Headers[header.Key] = header.Value;
- }
-
- var secKey = Convert.ToBase64String (Encoding.ASCII.GetBytes (Guid.NewGuid ().ToString ().Substring (0, 16)));
- string expectedAccept = Convert.ToBase64String (SHA1.Create ().ComputeHash (Encoding.ASCII.GetBytes (secKey + Magic)));
-
- req.Headers["Upgrade"] = "WebSocket";
- req.Headers["Sec-WebSocket-Version"] = VersionTag;
- req.Headers["Sec-WebSocket-Key"] = secKey;
- req.Headers["Sec-WebSocket-Origin"] = uri.Host;
- if (options.SubProtocols.Count > 0)
- req.Headers["Sec-WebSocket-Protocol"] = string.Join (",", options.SubProtocols);
-
- if (options.Credentials != null)
- req.Credentials = options.Credentials;
- if (options.ClientCertificates != null)
- req.ClientCertificates = options.ClientCertificates;
- if (options.Proxy != null)
- req.Proxy = options.Proxy;
- req.UseDefaultCredentials = options.UseDefaultCredentials;
- req.Connection = "Upgrade";
-
- HttpWebResponse resp = null;
- try {
- resp = (HttpWebResponse)(await req.GetResponseAsync ().ConfigureAwait (false));
- } catch (Exception e) {
- throw new WebSocketException (WebSocketError.Success, e);
- }
-
- connection = req.StoredConnection;
- underlyingSocket = connection.socket;
-
- if (resp.StatusCode != HttpStatusCode.SwitchingProtocols)
- throw new WebSocketException ("The server returned status code '" + (int)resp.StatusCode + "' when status code '101' was expected");
- if (!string.Equals (resp.Headers["Upgrade"], "WebSocket", StringComparison.OrdinalIgnoreCase)
- || !string.Equals (resp.Headers["Connection"], "Upgrade", StringComparison.OrdinalIgnoreCase)
- || !string.Equals (resp.Headers["Sec-WebSocket-Accept"], expectedAccept))
- throw new WebSocketException ("HTTP header error during handshake");
- if (resp.Headers["Sec-WebSocket-Protocol"] != null) {
- if (!options.SubProtocols.Contains (resp.Headers["Sec-WebSocket-Protocol"]))
- throw new WebSocketException (WebSocketError.UnsupportedProtocol);
- subProtocol = resp.Headers["Sec-WebSocket-Protocol"];
- }
-
- state = WebSocketState.Open;
- }
-
- public override Task SendAsync (ArraySegment<byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken)
- {
- EnsureWebSocketConnected ();
- ValidateArraySegment (buffer);
- if (connection == null)
- throw new WebSocketException (WebSocketError.Faulted);
- var count = Math.Max (options.SendBufferSize, buffer.Count) + HeaderMaxLength;
- if (sendBuffer == null || sendBuffer.Length != count)
- sendBuffer = new byte[count];
- return Task.Run (() => {
- EnsureWebSocketState (WebSocketState.Open, WebSocketState.CloseReceived);
- var maskOffset = WriteHeader (messageType, buffer, endOfMessage);
-
- if (buffer.Count > 0)
- MaskData (buffer, maskOffset);
- //underlyingSocket.Send (headerBuffer, 0, maskOffset + 4, SocketFlags.None);
- var headerLength = maskOffset + 4;
- Array.Copy (headerBuffer, sendBuffer, headerLength);
- underlyingSocket.Send (sendBuffer, 0, buffer.Count + headerLength, SocketFlags.None);
- });
- }
-
- const int messageTypeContinuation = 0;
- const int messageTypeText = 1;
- const int messageTypeBinary = 2;
- const int messageTypeClose = 8;
-
- WebSocketMessageType WireToMessageType (byte msgType)
- {
-
- if (msgType == messageTypeContinuation)
- return currentMessageType;
- if (msgType == messageTypeText)
- return WebSocketMessageType.Text;
- if (msgType == messageTypeBinary)
- return WebSocketMessageType.Binary;
- return WebSocketMessageType.Close;
- }
-
- static byte MessageTypeToWire (WebSocketMessageType type)
- {
- if (type == WebSocketMessageType.Text)
- return messageTypeText;
- if (type == WebSocketMessageType.Binary)
- return messageTypeBinary;
- return messageTypeClose;
- }
-
- public override Task<WebSocketReceiveResult> ReceiveAsync (ArraySegment<byte> buffer, CancellationToken cancellationToken)
- {
- EnsureWebSocketConnected ();
- ValidateArraySegment (buffer);
- return Task.Run (() => {
- EnsureWebSocketState (WebSocketState.Open, WebSocketState.CloseSent);
-
- bool isLast;
- long length;
-
- if (remaining == 0) {
- // First read the two first bytes to know what we are doing next
- connection.Read (req, headerBuffer, 0, 2);
- isLast = (headerBuffer[0] >> 7) > 0;
- var isMasked = (headerBuffer[1] >> 7) > 0;
- int mask = 0;
- currentMessageType = WireToMessageType ((byte)(headerBuffer[0] & 0xF));
- length = headerBuffer[1] & 0x7F;
- int offset = 0;
- if (length == 126) {
- offset = 2;
- connection.Read (req, headerBuffer, 2, offset);
- length = (headerBuffer[2] << 8) | headerBuffer[3];
- } else if (length == 127) {
- offset = 8;
- connection.Read (req, headerBuffer, 2, offset);
- length = 0;
- for (int i = 2; i <= 9; i++)
- length = (length << 8) | headerBuffer[i];
- }
-
- if (isMasked) {
- connection.Read (req, headerBuffer, 2 + offset, 4);
- for (int i = 0; i < 4; i++) {
- var pos = i + offset + 2;
- mask = (mask << 8) | headerBuffer[pos];
- }
- }
- } else {
- isLast = (headerBuffer[0] >> 7) > 0;
- currentMessageType = WireToMessageType ((byte)(headerBuffer[0] & 0xF));
- length = remaining;
- }
-
- if (currentMessageType == WebSocketMessageType.Close) {
- state = WebSocketState.Closed;
- var tmpBuffer = new byte[length];
- connection.Read (req, tmpBuffer, 0, tmpBuffer.Length);
- var closeStatus = (WebSocketCloseStatus)(tmpBuffer[0] << 8 | tmpBuffer[1]);
- var closeDesc = tmpBuffer.Length > 2 ? Encoding.UTF8.GetString (tmpBuffer, 2, tmpBuffer.Length - 2) : string.Empty;
- return new WebSocketReceiveResult ((int)length, currentMessageType, isLast, closeStatus, closeDesc);
- } else {
- var readLength = (int)(buffer.Count < length ? buffer.Count : length);
- connection.Read (req, buffer.Array, buffer.Offset, readLength);
- remaining = length - readLength;
-
- return new WebSocketReceiveResult ((int)readLength, currentMessageType, isLast && remaining == 0);
- }
- });
- }
-
- // The damn difference between those two methods is that CloseAsync will wait for server acknowledgement before completing
- // while CloseOutputAsync will send the close packet and simply complete.
-
- public async override Task CloseAsync (WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken)
- {
- EnsureWebSocketConnected ();
- await SendCloseFrame (closeStatus, statusDescription, cancellationToken).ConfigureAwait (false);
- state = WebSocketState.CloseSent;
- // TODO: figure what's exceptions are thrown if the server returns something faulty here
- await ReceiveAsync (new ArraySegment<byte> (new byte[0]), cancellationToken).ConfigureAwait (false);
- state = WebSocketState.Closed;
- }
-
- public async override Task CloseOutputAsync (WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken)
- {
- EnsureWebSocketConnected ();
- await SendCloseFrame (closeStatus, statusDescription, cancellationToken).ConfigureAwait (false);
- state = WebSocketState.CloseSent;
- }
-
- async Task SendCloseFrame (WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken)
- {
- var statusDescBuffer = string.IsNullOrEmpty (statusDescription) ? new byte[2] : new byte[2 + Encoding.UTF8.GetByteCount (statusDescription)];
- statusDescBuffer[0] = (byte)(((ushort)closeStatus) >> 8);
- statusDescBuffer[1] = (byte)(((ushort)closeStatus) & 0xFF);
- if (!string.IsNullOrEmpty (statusDescription))
- Encoding.UTF8.GetBytes (statusDescription, 0, statusDescription.Length, statusDescBuffer, 2);
- await SendAsync (new ArraySegment<byte> (statusDescBuffer), WebSocketMessageType.Close, true, cancellationToken).ConfigureAwait (false);
- }
-
- int WriteHeader (WebSocketMessageType type, ArraySegment<byte> buffer, bool endOfMessage)
- {
- var opCode = MessageTypeToWire (type);
- var length = buffer.Count;
-
- headerBuffer[0] = (byte)(opCode | (endOfMessage ? 0x80 : 0));
- if (length < 126) {
- headerBuffer[1] = (byte)length;
- } else if (length <= ushort.MaxValue) {
- headerBuffer[1] = (byte)126;
- headerBuffer[2] = (byte)(length / 256);
- headerBuffer[3] = (byte)(length % 256);
- } else {
- headerBuffer[1] = (byte)127;
-
- int left = length;
- int unit = 256;
-
- for (int i = 9; i > 1; i--) {
- headerBuffer[i] = (byte)(left % unit);
- left = left / unit;
- }
- }
-
- var l = Math.Max (0, headerBuffer[1] - 125);
- var maskOffset = 2 + l * l * 2;
- GenerateMask (headerBuffer, maskOffset);
-
- // Since we are client only, we always mask the payload
- headerBuffer[1] |= 0x80;
-
- return maskOffset;
- }
-
- void GenerateMask (byte[] mask, int offset)
- {
- mask[offset + 0] = (byte)random.Next (0, 255);
- mask[offset + 1] = (byte)random.Next (0, 255);
- mask[offset + 2] = (byte)random.Next (0, 255);
- mask[offset + 3] = (byte)random.Next (0, 255);
- }
-
- void MaskData (ArraySegment<byte> buffer, int maskOffset)
- {
- var sendBufferOffset = maskOffset + 4;
- for (var i = 0; i < buffer.Count; i++)
- sendBuffer[i + sendBufferOffset] = (byte)(buffer.Array[buffer.Offset + i] ^ headerBuffer[maskOffset + (i % 4)]);
- }
-
- void EnsureWebSocketConnected ()
- {
- if (state < WebSocketState.Open)
- throw new InvalidOperationException ("The WebSocket is not connected");
- }
-
- void EnsureWebSocketState (params WebSocketState[] validStates)
- {
- foreach (var validState in validStates)
- if (state == validState)
- return;
- throw new WebSocketException ("The WebSocket is in an invalid state ('" + state + "') for this operation. Valid states are: " + string.Join (", ", validStates));
- }
-
- void ValidateArraySegment (ArraySegment<byte> segment)
- {
- if (segment.Array == null)
- throw new ArgumentNullException ("buffer.Array");
- if (segment.Offset < 0)
- throw new ArgumentOutOfRangeException ("buffer.Offset");
- if (segment.Offset + segment.Count > segment.Array.Length)
- throw new ArgumentOutOfRangeException ("buffer.Count");
- }
- }
-}
-
+++ /dev/null
-//
-// ClientWebSocket.cs
-//
-// Author:
-// Rolf Bjarne Kvinge <rolf@xamarin.com>
-//
-// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace System.Net.WebSockets
-{
- public class ClientWebSocket : WebSocket, IDisposable
- {
- const string EXCEPTION_MESSAGE = "System.Net.WebSockets.ClientWebSocket is not supported on the current platform.";
-
- public ClientWebSocket ()
- {
- throw new PlatformNotSupportedException (EXCEPTION_MESSAGE);
- }
-
- public override void Dispose ()
- {
- throw new PlatformNotSupportedException (EXCEPTION_MESSAGE);
- }
-
- public override void Abort ()
- {
- throw new PlatformNotSupportedException (EXCEPTION_MESSAGE);
- }
-
- public ClientWebSocketOptions Options {
- get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); }
- }
-
- public override WebSocketState State {
- get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); }
- }
-
- public override WebSocketCloseStatus? CloseStatus {
- get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); }
- }
-
- public override string CloseStatusDescription {
- get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); }
- }
-
- public override string SubProtocol {
- get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); }
- }
-
- public Task ConnectAsync (Uri uri, CancellationToken cancellationToken)
- {
- throw new PlatformNotSupportedException (EXCEPTION_MESSAGE);
- }
-
- public override Task SendAsync (ArraySegment<byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken)
- {
- throw new PlatformNotSupportedException (EXCEPTION_MESSAGE);
- }
-
- public override Task<WebSocketReceiveResult> ReceiveAsync (ArraySegment<byte> buffer, CancellationToken cancellationToken)
- {
- throw new PlatformNotSupportedException (EXCEPTION_MESSAGE);
- }
-
- public override Task CloseAsync (WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken)
- {
- throw new PlatformNotSupportedException (EXCEPTION_MESSAGE);
- }
-
- public override Task CloseOutputAsync (WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken)
- {
- throw new PlatformNotSupportedException (EXCEPTION_MESSAGE);
- }
- }
-}
+++ /dev/null
-//
-// ClientWebSocketOptions.cs
-//
-// Authors:
-// Jérémie Laval <jeremie dot laval at xamarin dot com>
-//
-// Copyright 2013 Xamarin Inc (http://www.xamarin.com).
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-//
-
-
-using System;
-using System.Net;
-using System.Security.Principal;
-using System.Security.Cryptography.X509Certificates;
-using System.Runtime.CompilerServices;
-using System.Collections.Generic;
-
-namespace System.Net.WebSockets
-{
- public sealed class ClientWebSocketOptions
- {
- List<string> subprotocols = new List<string> ();
- Dictionary<string, string> customRequestHeaders = new Dictionary<string, string> ();
-
- public X509CertificateCollection ClientCertificates { get; set; }
-
- public CookieContainer Cookies { get; set; }
-
- public ICredentials Credentials { get; set; }
-
- public TimeSpan KeepAliveInterval { get; set; }
-
- public IWebProxy Proxy { get; set; }
-
- public bool UseDefaultCredentials { get; set; }
-
- internal IList<string> SubProtocols {
- get {
- return subprotocols.AsReadOnly ();
- }
- }
-
- internal Dictionary<string, string> CustomRequestHeaders {
- get {
- return customRequestHeaders;
- }
- }
-
- internal int ReceiveBufferSize {
- get;
- private set;
- }
-
- internal ArraySegment<byte> CustomReceiveBuffer {
- get;
- private set;
- }
-
- internal int SendBufferSize {
- get;
- private set;
- }
-
- public void AddSubProtocol (string subProtocol)
- {
- subprotocols.Add (subProtocol);
- }
-
- public void SetBuffer (int receiveBufferSize, int sendBufferSize)
- {
- SetBuffer (receiveBufferSize, sendBufferSize, new ArraySegment<byte> ());
- }
-
- public void SetBuffer (int receiveBufferSize, int sendBufferSize, ArraySegment<byte> buffer)
- {
- ReceiveBufferSize = receiveBufferSize;
- SendBufferSize = sendBufferSize;
- CustomReceiveBuffer = buffer;
- }
-
- public void SetRequestHeader (string headerName, string headerValue)
- {
- customRequestHeaders[headerName] = headerValue;
- }
- }
-}
-
+++ /dev/null
-//
-// HttpListenerWebSocketContext.cs
-//
-// Authors:
-// Jérémie Laval <jeremie dot laval at xamarin dot com>
-//
-// Copyright 2013 Xamarin Inc (http://www.xamarin.com).
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-//
-
-#if SECURITY_DEP
-
-using System;
-using System.Net;
-using System.Collections.Specialized;
-using System.Collections.Generic;
-using System.Security.Principal;
-using System.Security.Cryptography.X509Certificates;
-using System.Runtime.CompilerServices;
-
-namespace System.Net.WebSockets
-{
- public class HttpListenerWebSocketContext : WebSocketContext
- {
- [MonoTODO]
- public override CookieCollection CookieCollection {
- get {
- throw new NotImplementedException ();
- }
- }
-
- [MonoTODO]
- public override NameValueCollection Headers {
- get {
- throw new NotImplementedException ();
- }
- }
-
- [MonoTODO]
- public override bool IsAuthenticated {
- get {
- throw new NotImplementedException ();
- }
- }
-
- [MonoTODO]
- public override bool IsLocal {
- get {
- throw new NotImplementedException ();
- }
- }
-
- [MonoTODO]
- public override bool IsSecureConnection {
- get {
- throw new NotImplementedException ();
- }
- }
-
- [MonoTODO]
- public override string Origin {
- get {
- throw new NotImplementedException ();
- }
- }
-
- [MonoTODO]
- public override Uri RequestUri {
- get {
- throw new NotImplementedException ();
- }
- }
-
- [MonoTODO]
- public override string SecWebSocketKey {
- get {
- throw new NotImplementedException ();
- }
- }
-
- [MonoTODO]
- public override IEnumerable<string> SecWebSocketProtocols {
- get {
- throw new NotImplementedException ();
- }
- }
-
- [MonoTODO]
- public override string SecWebSocketVersion {
- get {
- throw new NotImplementedException ();
- }
- }
-
- [MonoTODO]
- public override IPrincipal User {
- get {
- throw new NotImplementedException ();
- }
- }
-
- [MonoTODO]
- public override WebSocket WebSocket {
- get {
- throw new NotImplementedException ();
- }
- }
- }
-}
-#endif
+++ /dev/null
-//
-// WebSocket.cs
-//
-// Authors:
-// Jérémie Laval <jeremie dot laval at xamarin dot com>
-//
-// Copyright 2013 Xamarin Inc (http://www.xamarin.com).
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-//
-
-
-using System;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Runtime.CompilerServices;
-
-namespace System.Net.WebSockets
-{
- public abstract class WebSocket : IDisposable
- {
- protected WebSocket ()
- {
-
- }
-
- public abstract Nullable<WebSocketCloseStatus> CloseStatus { get; }
- public abstract string CloseStatusDescription { get; }
- public abstract WebSocketState State { get; }
- public abstract string SubProtocol { get; }
-
- [MonoTODO]
- public static TimeSpan DefaultKeepAliveInterval {
- get {
- throw new NotImplementedException ();
- }
- }
-
- public abstract void Abort ();
-
- public abstract Task CloseAsync (WebSocketCloseStatus closeStatus,
- string statusDescription,
- CancellationToken cancellationToken);
-
- public abstract Task CloseOutputAsync (WebSocketCloseStatus closeStatus,
- string statusDescription,
- CancellationToken cancellationToken);
-
- public abstract Task<WebSocketReceiveResult> ReceiveAsync (ArraySegment<byte> buffer,
- CancellationToken cancellationToken);
-
- public abstract Task SendAsync (ArraySegment<byte> buffer,
- WebSocketMessageType messageType,
- bool endOfMessage,
- CancellationToken cancellationToken);
-
- [MonoTODO]
- public static ArraySegment<byte> CreateClientBuffer (int receiveBufferSize, int sendBufferSize)
- {
- throw new NotImplementedException ();
- }
-
- [MonoTODO]
- public static WebSocket CreateClientWebSocket (Stream innerStream,
- string subProtocol,
- int receiveBufferSize,
- int sendBufferSize,
- TimeSpan keepAliveInterval,
- bool useZeroMaskingKey,
- ArraySegment<byte> internalBuffer)
- {
- throw new NotImplementedException ();
- }
-
- [MonoTODO]
- public static ArraySegment<byte> CreateServerBuffer (int receiveBufferSize)
- {
- throw new NotImplementedException ();
- }
-
- [ObsoleteAttribute, MonoTODO]
- public static bool IsApplicationTargeting45 ()
- {
- return true;
- }
-
- [MonoTODO]
- public static void RegisterPrefixes ()
- {
- throw new NotImplementedException ();
- }
-
- public abstract void Dispose ();
-
- protected static bool IsStateTerminal (WebSocketState state)
- {
- return state == WebSocketState.Closed || state == WebSocketState.Aborted;
- }
-
- [MonoTODO]
- protected static void ThrowOnInvalidState (WebSocketState state, params WebSocketState[] validStates)
- {
- foreach (var validState in validStates)
- if (validState == state)
- return;
-
- throw new NotImplementedException ();
- }
- }
-}
-
+++ /dev/null
-//
-// WebSocketCloseStatus.cs
-//
-// Authors:
-// Jérémie Laval <jeremie dot laval at xamarin dot com>
-//
-// Copyright 2013 Xamarin Inc (http://www.xamarin.com).
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-//
-
-
-using System;
-using System.Runtime.CompilerServices;
-
-namespace System.Net.WebSockets
-{
- public enum WebSocketCloseStatus
- {
- NormalClosure = 1000,
- EndpointUnavailable = 1001,
- ProtocolError = 1002,
- InvalidMessageType = 1003,
- Empty = 1005,
- InvalidPayloadData = 1007,
- PolicyViolation = 1008,
- MessageTooBig = 1009,
- MandatoryExtension = 1010,
- InternalServerError = 1011
- }
-}
-
+++ /dev/null
-//
-// WebSocketContext.cs
-//
-// Authors:
-// Jérémie Laval <jeremie dot laval at xamarin dot com>
-//
-// Copyright 2013 Xamarin Inc (http://www.xamarin.com).
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-//
-
-
-using System;
-using System.Collections.Specialized;
-using System.Collections.Generic;
-using System.Security.Principal;
-using System.Runtime.CompilerServices;
-
-namespace System.Net.WebSockets
-{
- public abstract class WebSocketContext
- {
- protected WebSocketContext ()
- {
-
- }
-
- public abstract CookieCollection CookieCollection { get; }
-
- public abstract NameValueCollection Headers { get; }
-
- public abstract bool IsAuthenticated { get; }
-
- public abstract bool IsLocal { get; }
-
- public abstract bool IsSecureConnection { get; }
-
- public abstract string Origin { get; }
-
- public abstract Uri RequestUri { get; }
-
- public abstract string SecWebSocketKey { get; }
-
- public abstract IEnumerable<string> SecWebSocketProtocols { get; }
-
- public abstract string SecWebSocketVersion { get; }
-
- public abstract IPrincipal User { get; }
-
- public abstract WebSocket WebSocket { get; }
- }
-}
-
+++ /dev/null
-//
-// WebSocketError.cs
-//
-// Authors:
-// Jérémie Laval <jeremie dot laval at xamarin dot com>
-//
-// Copyright 2013 Xamarin Inc (http://www.xamarin.com).
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-//
-
-
-using System;
-using System.Runtime.CompilerServices;
-
-namespace System.Net.WebSockets
-{
- public enum WebSocketError
- {
- Success,
- InvalidMessageType,
- Faulted,
- NativeError,
- NotAWebSocket,
- UnsupportedVersion,
- UnsupportedProtocol,
- HeaderError,
- ConnectionClosedPrematurely,
- InvalidState
- }
-}
-
+++ /dev/null
-//
-// WebSocketException.cs
-//
-// Authors:
-// Jérémie Laval <jeremie dot laval at xamarin dot com>
-//
-// Copyright 2013 Xamarin Inc (http://www.xamarin.com).
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-//
-
-
-using System;
-using System.ComponentModel;
-using System.Runtime.CompilerServices;
-
-namespace System.Net.WebSockets
-{
- public sealed class WebSocketException : Win32Exception
- {
- const string DefaultMessage = "Generic WebSocket exception";
-
- public WebSocketException () : this (WebSocketError.Success, -1, DefaultMessage, null)
- {
-
- }
-
- public WebSocketException (int nativeError) : this (WebSocketError.Success, nativeError, DefaultMessage, null)
- {
-
- }
-
- public WebSocketException (string message) : this (WebSocketError.Success, -1, message, null)
- {
-
- }
-
- public WebSocketException (WebSocketError error) : this (error, -1, DefaultMessage, null)
- {
- }
-
- public WebSocketException (int nativeError, Exception innerException) : this (WebSocketError.Success, nativeError, DefaultMessage, innerException)
- {
-
- }
-
- public WebSocketException (int nativeError, string message) : this (WebSocketError.Success, nativeError, message, null)
- {
-
- }
-
- public WebSocketException (string message, Exception innerException) : this (WebSocketError.Success, -1, message, innerException)
- {
-
- }
-
- public WebSocketException (WebSocketError error, Exception innerException) : this (error, -1, DefaultMessage, innerException)
- {
-
- }
-
- public WebSocketException (WebSocketError error, int nativeError) : this (error, nativeError, DefaultMessage, null)
- {
- }
-
- public WebSocketException (WebSocketError error, string message) : this (error, -1, message, null)
- {
- }
-
- public WebSocketException (WebSocketError error, int nativeError, Exception innerException) : this (error, nativeError, DefaultMessage, innerException)
- {
- }
-
- public WebSocketException (WebSocketError error, int nativeError, string message) : this (error, nativeError, message, null)
- {
- }
-
- public WebSocketException (WebSocketError error, string message, Exception innerException) : this (error, -1, message, innerException)
- {
- }
-
- public WebSocketException (WebSocketError error, int nativeError, string message, Exception innerException) : base (message, innerException)
- {
- WebSocketErrorCode = error;
- }
-
- public WebSocketError WebSocketErrorCode {
- get;
- private set;
- }
- }
-}
-
+++ /dev/null
-//
-// WebSocketMessageType.cs
-//
-// Authors:
-// Jérémie Laval <jeremie dot laval at xamarin dot com>
-//
-// Copyright 2013 Xamarin Inc (http://www.xamarin.com).
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-//
-
-
-using System;
-using System.Runtime.CompilerServices;
-
-namespace System.Net.WebSockets
-{
- public enum WebSocketMessageType
- {
- Text = 0,
- Binary = 1,
- Close = 2
- }
-}
-
+++ /dev/null
-//
-// WebSocketReceiveResult.cs
-//
-// Authors:
-// Jérémie Laval <jeremie dot laval at xamarin dot com>
-//
-// Copyright 2013 Xamarin Inc (http://www.xamarin.com).
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-//
-
-
-using System;
-using System.Security.Principal;
-using System.Runtime.CompilerServices;
-
-namespace System.Net.WebSockets
-{
- public class WebSocketReceiveResult
- {
- public WebSocketReceiveResult (int count, WebSocketMessageType messageType, bool endOfMessage)
- : this (count, messageType, endOfMessage, null, null)
- {
- }
-
- public WebSocketReceiveResult (int count,
- WebSocketMessageType messageType,
- bool endOfMessage,
- WebSocketCloseStatus? closeStatus,
- string closeStatusDescription)
- {
- MessageType = messageType;
- CloseStatus = closeStatus;
- CloseStatusDescription = closeStatusDescription;
- Count = count;
- EndOfMessage = endOfMessage;
- }
-
- public WebSocketCloseStatus? CloseStatus {
- get;
- private set;
- }
-
- public string CloseStatusDescription {
- get;
- private set;
- }
-
- public int Count {
- get;
- private set;
- }
-
- public bool EndOfMessage {
- get;
- private set;
- }
-
- public WebSocketMessageType MessageType {
- get;
- private set;
- }
- }
-}
-
+++ /dev/null
-//
-// WebSocketState.cs
-//
-// Authors:
-// Jérémie Laval <jeremie dot laval at xamarin dot com>
-//
-// Copyright 2013 Xamarin Inc (http://www.xamarin.com).
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-//
-
-
-using System;
-using System.Runtime.CompilerServices;
-
-namespace System.Net.WebSockets
-{
- public enum WebSocketState
- {
- None,
- Connecting,
- Open,
- CloseSent,
- CloseReceived,
- Closed,
- Aborted
- }
-}
-
public static extern IntPtr dlopen (string path, int mode);
[DllImport (SystemLibrary)]
- public static extern IntPtr dlsym (IntPtr handle, string symbol);
+ static extern IntPtr dlsym (IntPtr handle, string symbol);
[DllImport (SystemLibrary)]
public static extern void dlclose (IntPtr handle);
if (handle == IntPtr.Zero)
return;
try {
- True = new CFBoolean (CFObject.dlsym (handle, "kCFBooleanTrue"), false);
- False = new CFBoolean (CFObject.dlsym (handle, "kCFBooleanFalse"), false);
+ True = new CFBoolean (CFObject.GetCFObjectHandle (handle, "kCFBooleanTrue"), false);
+ False = new CFBoolean (CFObject.GetCFObjectHandle (handle, "kCFBooleanFalse"), false);
}
finally {
CFObject.dlclose (handle);
isMacOS = true;
checkedOS = true;
}
+
+#elif ORBIS
+ const bool isFreeBSD = true;
+
+ private static void CheckOS() {
+ checkedOS = true;
+ }
+
#else
static bool isFreeBSD;
}
[Test]
- [Category ("MobileNotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran
+ [Category ("NotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran
public void ServerHandshakeReturnCrapStatusCodeTest ()
{
// On purpose,
Assert.AreEqual (WebSocketState.CloseSent, socket.State);
var resp = socket.ReceiveAsync (new ArraySegment<byte> (new byte[0]), CancellationToken.None).Result;
- Assert.AreEqual (WebSocketState.Closed, socket.State);
+ Assert.AreEqual (WebSocketState.CloseReceived, socket.State);
Assert.AreEqual (WebSocketMessageType.Close, resp.MessageType);
Assert.AreEqual (WebSocketCloseStatus.NormalClosure, resp.CloseStatus);
Assert.AreEqual (string.Empty, resp.CloseStatusDescription);
Assert.IsTrue (socket.CloseAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (5000));
Assert.IsTrue (socket.ReceiveAsync (new ArraySegment<byte> (new byte[0]), CancellationToken.None).Wait (5000));
} catch (AggregateException e) {
- AssertWebSocketException (e, WebSocketError.Success);
+ AssertWebSocketException (e, WebSocketError.InvalidState);
return;
}
Assert.Fail ("Should have thrown");
Assert.IsTrue (socket.CloseAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (5000));
Assert.IsTrue (socket.SendAsync (new ArraySegment<byte> (new byte[0]), WebSocketMessageType.Text, true, CancellationToken.None).Wait (5000));
} catch (AggregateException e) {
- AssertWebSocketException (e, WebSocketError.Success);
+ AssertWebSocketException (e, WebSocketError.InvalidState);
return;
}
Assert.Fail ("Should have thrown");
Assert.IsTrue (socket.CloseOutputAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (5000));
Assert.IsTrue (socket.SendAsync (new ArraySegment<byte> (new byte[0]), WebSocketMessageType.Text, true, CancellationToken.None).Wait (5000));
} catch (AggregateException e) {
- AssertWebSocketException (e, WebSocketError.Success);
+ AssertWebSocketException (e, WebSocketError.InvalidState);
return;
}
Assert.Fail ("Should have thrown");
void AssertWebSocketException (AggregateException e, WebSocketError error, Type inner = null)
{
var wsEx = e.InnerException as WebSocketException;
- Console.WriteLine (e.InnerException.ToString ());
Assert.IsNotNull (wsEx, "Not a websocketexception");
Assert.AreEqual (error, wsEx.WebSocketErrorCode);
if (inner != null) {
System.Net.Sockets/SocketReceiveMessageFromResult.cs
System.Net.Sockets/SocketTaskExtensions.cs
-System.Net.WebSockets/ClientWebSocket.cs
-System.Net.WebSockets/ClientWebSocketOptions.cs
-System.Net.WebSockets/HttpListenerWebSocketContext.cs
-System.Net.WebSockets/WebSocket.cs
-System.Net.WebSockets/WebSocketCloseStatus.cs
-System.Net.WebSockets/WebSocketContext.cs
-System.Net.WebSockets/WebSocketError.cs
-System.Net.WebSockets/WebSocketException.cs
-System.Net.WebSockets/WebSocketMessageType.cs
-System.Net.WebSockets/WebSocketReceiveResult.cs
-System.Net.WebSockets/WebSocketState.cs
-
System.Runtime.InteropServices.ComTypes/ADVF.cs
System.Runtime.InteropServices.ComTypes/DATADIR.cs
System.Runtime.InteropServices.ComTypes/DVASPECT.cs
corefx/SR.cs
+../../../external/corefx/src/Common/src/System/StringExtensions.cs
+
../../../external/corefx/src/Common/src/System/Collections/Generic/ArrayBuilder.cs
../../../external/corefx/src/Common/src/System/Collections/Generic/EnumerableHelpers.cs
../../../external/corefx/src/Common/src/System/Collections/Generic/LargeArrayBuilder.cs
+../../../external/corefx/src/Common/src/System/Net/SecurityProtocol.cs
+../../../external/corefx/src/Common/src/System/Net/UriScheme.cs
+
+../../../external/corefx/src/Common/src/System/Net/Logging/NetEventSource.Common.cs
+
+../../../external/corefx/src/Common/src/System/Net/WebSockets/ManagedWebSocket.cs
+../../../external/corefx/src/Common/src/System/Net/WebSockets/WebSocketValidate.cs
+
../../../external/corefx/src/System.Runtime/src/System/Collections/Generic/ISet.cs
+../../../external/corefx/src/System.Buffers/src/System/Buffers/ArrayPool.cs
+../../../external/corefx/src/System.Buffers/src/System/Buffers/ArrayPoolEventSource.cs
+../../../external/corefx/src/System.Buffers/src/System/Buffers/DefaultArrayPool.cs
+../../../external/corefx/src/System.Buffers/src/System/Buffers/DefaultArrayPoolBucket.cs
+../../../external/corefx/src/System.Buffers/src/System/Buffers/Utilities.cs
+
../../../external/corefx/src/System.Collections/src/System/Collections/Generic/BitHelper.cs
../../../external/corefx/src/System.Collections/src/System/Collections/Generic/ICollectionDebugView.cs
../../../external/corefx/src/System.Collections/src/System/Collections/Generic/IDictionaryDebugView.cs
../../../external/corefx/src/System.IO.Compression/src/System/IO/Compression/CompressionMode.cs
../../../external/corefx/src/System.IO.Compression/src/System/IO/Compression/GZipStream.cs
+../../../external/corefx/src/System.Net.WebSockets/src/System/Net/WebSockets/WebSocket.cs
+../../../external/corefx/src/System.Net.WebSockets/src/System/Net/WebSockets/WebSocketCloseStatus.cs
+../../../external/corefx/src/System.Net.WebSockets/src/System/Net/WebSockets/WebSocketContext.cs
+../../../external/corefx/src/System.Net.WebSockets/src/System/Net/WebSockets/WebSocketError.cs
+../../../external/corefx/src/System.Net.WebSockets/src/System/Net/WebSockets/WebSocketException.cs
+../../../external/corefx/src/System.Net.WebSockets/src/System/Net/WebSockets/WebSocketMessageType.cs
+../../../external/corefx/src/System.Net.WebSockets/src/System/Net/WebSockets/WebSocketReceiveResult.cs
+../../../external/corefx/src/System.Net.WebSockets/src/System/Net/WebSockets/WebSocketState.cs
+
+../../../external/corefx/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/ClientWebSocket.cs
+../../../external/corefx/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/ClientWebSocketOptions.cs
+../../../external/corefx/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/WebSocketHandle.Managed.cs
+
+../../../external/corefx/src/System.Net.HttpListener/src/System/Net/WebSockets/HttpListenerWebSocketContext.cs
+
../../../external/corefx/src/System.Runtime.Extensions/src/System/CodeDom/Compiler/IndentedTextWriter.cs
public const string Serialization_MismatchedCount = "The serialized Count information doesn't match the number of items.";
public const string Serialization_MissingKeys = "The keys for this dictionary are missing.";
public const string Serialization_MissingValues = "The values for this dictionary are missing.";
+ public const string ArgumentException_BufferNotFromPool = "The buffer is not associated with this pool and may not be returned to it.";
}
System.Net.Sockets/TcpClient.platformnotsupported.cs
System.Net.Sockets/TcpListener.platformnotsupported.cs
System.Net.Sockets/UdpClient.platformnotsupported.cs
-System.Net.WebSockets/ClientWebSocket.platformnotsupported.cs
System.Net/AuthenticationManager.platformnotsupported.cs
System.Net/FtpRequestCreator.platformnotsupported.cs
System.Net/FtpWebRequest.platformnotsupported.cs
--- /dev/null
+System.Net/MacProxy.cs
+System.Security.Cryptography.X509Certificates/OSX509Certificates.cs
TargetMode mode = TargetMode.Internal;
if (node.Attributes["TargetMode"] != null)
mode = (TargetMode) Enum.Parse (typeof(TargetMode), node.Attributes ["TargetMode"].Value);
-
- CreateRelationship (new Uri (node.Attributes["Target"].Value.ToString(), UriKind.RelativeOrAbsolute),
- mode,
- node.Attributes["Type"].Value.ToString (),
- node.Attributes["Id"].Value.ToString (),
- true);
+
+ // Workaround for Mono relative paths
+ // http://www.mono-project.com/docs/faq/known-issues/urikind-relativeorabsolute/
+ var kind = (UriKind) 300;
+ CreateRelationship (new Uri (node.Attributes["Target"].Value.ToString(), kind),
+ mode,
+ node.Attributes["Type"].Value.ToString (),
+ node.Attributes["Id"].Value.ToString (),
+ true);
}
}
\r
return pack;\r
}\r
+\r
+ Package CreateSpreadsheet(Stream stream)\r
+ {\r
+ Package pack = Package.Open(stream, FileMode.Create);\r
+\r
+ // Create package parts.\r
+ PackagePart workbookPart = pack.CreatePart(new Uri("/xl/workbook.xml", UriKind.Relative), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml");\r
+ PackagePart sharedStringsPart = pack.CreatePart(new Uri("/xl/sharedStrings.xml", UriKind.Relative), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml");\r
+\r
+ workbookPart.CreateRelationship(new Uri("/xl/sharedStrings.xml", UriKind.Relative), TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings", "rel1");\r
+\r
+ // Load some basic data into the different parts.\r
+ foreach (PackagePart part in package.GetParts())\r
+ using (Stream s = part.GetStream())\r
+ s.Write(new byte[10], 0, 10);\r
+\r
+ return pack;\r
+ }\r
+\r
+ [Test]\r
+ public void TestExcelWorkbook()\r
+ {\r
+ MemoryStream stream = new MemoryStream();\r
+ Package package = CreateSpreadsheet(stream);\r
+ Assert.IsTrue(package.PartExists(new Uri("/xl/workbook.xml", UriKind.Relative)), "#1");\r
+ Assert.IsTrue(package.PartExists(new Uri("/xl/sharedStrings.xml", UriKind.Relative)), "#2");\r
+\r
+ package.Close();\r
+ package = Package.Open(new MemoryStream(stream.ToArray()), FileMode.Open);\r
+\r
+ PackagePart workbookPart = package.GetPart(new Uri("/xl/workbook.xml", UriKind.Relative));\r
+ Assert.IsTrue(workbookPart.RelationshipExists("rel1"), "#3");\r
+\r
+ var r = workbookPart.GetRelationship("rel1");\r
+ Assert.IsFalse(r.TargetUri.IsAbsoluteUri, "#4");\r
+ package.Close();\r
+ }\r
}\r
}\r
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.ConstrainedExecution;
-#if !FULL_AOT_RUNTIME
-using System.Reflection.Emit;
-#endif
namespace System
{
return false;
}
- int IList.IndexOf (object value)
+ internal void InternalArray__ICollection_CopyTo<T> (T[] array, int arrayIndex)
{
- if (this.Rank > 1)
- throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
-
- int length = this.Length;
- for (int i = 0; i < length; i++) {
- if (Object.Equals (this.GetValueImpl (i), value))
- // array index may not be zero-based.
- // use lower bound
- return i + this.GetLowerBound (0);
- }
-
- unchecked {
- // lower bound may be MinValue
- return this.GetLowerBound (0) - 1;
- }
- }
-
- internal void InternalArray__ICollection_CopyTo<T> (T[] array, int index)
- {
- if (array == null)
- throw new ArgumentNullException ("array");
-
- // The order of these exception checks may look strange,
- // but that's how the microsoft runtime does it.
- if (this.Rank > 1)
- throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
- if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
- throw new ArgumentException ("Destination array was not long " +
- "enough. Check destIndex and length, and the array's " +
- "lower bounds.");
- if (array.Rank > 1)
- throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
- if (index < 0)
- throw new ArgumentOutOfRangeException (
- "index", Locale.GetText ("Value has to be >= 0."));
-
- Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
+ Copy (this, GetLowerBound (0), array, arrayIndex, Length);
}
internal T InternalArray__IReadOnlyList_get_Item<T> (int index)
[MethodImplAttribute (MethodImplOptions.InternalCall)]
internal extern static Array CreateInstanceImpl (Type elementType, int[] lengths, int[] bounds);
- public bool IsReadOnly {
- get {
- return false;
- }
- }
-
[ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
public int GetUpperBound (int dimension)
{
return GetValue (ind);
}
- [ComVisible (false)]
- public void SetValue (object value, long index)
- {
- if (index < 0 || index > Int32.MaxValue)
- throw new ArgumentOutOfRangeException ("index", Locale.GetText (
- "Value must be >= 0 and <= Int32.MaxValue."));
-
- SetValue (value, (int) index);
- }
-
- [ComVisible (false)]
- public void SetValue (object value, long index1, long index2)
- {
- if (index1 < 0 || index1 > Int32.MaxValue)
- throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
- "Value must be >= 0 and <= Int32.MaxValue."));
-
- if (index2 < 0 || index2 > Int32.MaxValue)
- throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
- "Value must be >= 0 and <= Int32.MaxValue."));
-
- int[] ind = {(int) index1, (int) index2};
- SetValue (value, ind);
- }
-
- [ComVisible (false)]
- public void SetValue (object value, long index1, long index2, long index3)
- {
- if (index1 < 0 || index1 > Int32.MaxValue)
- throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
- "Value must be >= 0 and <= Int32.MaxValue."));
-
- if (index2 < 0 || index2 > Int32.MaxValue)
- throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
- "Value must be >= 0 and <= Int32.MaxValue."));
-
- if (index3 < 0 || index3 > Int32.MaxValue)
- throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
- "Value must be >= 0 and <= Int32.MaxValue."));
-
- int[] ind = {(int) index1, (int) index2, (int) index3};
- SetValue (value, ind);
- }
-
public void SetValue (object value, int index)
{
if (Rank != 1)
throw new NotSupportedException ("Array type can not be void");
if (elementType.ContainsGenericParameters)
throw new NotSupportedException ("Array type can not be an open generic type");
-#if !FULL_AOT_RUNTIME
- if ((elementType is TypeBuilder) && !(elementType as TypeBuilder).IsCreated ())
- throw new NotSupportedException ("Can't create an array of the unfinished type '" + elementType + "'.");
-#endif
return CreateInstanceImpl (elementType, lengths, bounds);
}
return CreateInstanceImpl (elementType, lengths, lowerBounds);
}
- static int [] GetIntArray (long [] values)
- {
- int len = values.Length;
- int [] ints = new int [len];
- for (int i = 0; i < len; i++) {
- long current = values [i];
- if (current < 0 || current > (long) Int32.MaxValue)
- throw new ArgumentOutOfRangeException ("values", Locale.GetText (
- "Each value has to be >= 0 and <= Int32.MaxValue."));
-
- ints [i] = (int) current;
- }
- return ints;
- }
-
- public static Array CreateInstance (Type elementType, params long [] lengths)
- {
- if (lengths == null)
- throw new ArgumentNullException ("lengths");
- return CreateInstance (elementType, GetIntArray (lengths));
- }
-
- [ComVisible (false)]
- public void SetValue (object value, params long [] indices)
- {
- if (indices == null)
- throw new ArgumentNullException ("indices");
- SetValue (value, GetIntArray (indices));
- }
-
[ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
public static void Clear (Array array, int index, int length)
{
return source.IsAssignableFrom (target) || target.IsAssignableFrom (source);
}
- public static T [] FindAll<T> (T [] array, Predicate <T> match)
+ public static T[] FindAll<T> (T[] array, Predicate<T> match)
{
if (array == null)
throw new ArgumentNullException ("array");
throw new ArgumentNullException ("match");
int pos = 0;
- T [] d = new T [array.Length];
- foreach (T t in array)
- if (match (t))
- d [pos++] = t;
+ T[] d = Empty<T>();
+ for (int i = 0; i < array.Length; i++) {
+ if (match (array [i])) {
+ if (pos == d.Length)
+ Resize (ref d, pos == 0 ? 4 : pos * 2);
+
+ d [pos++] = array [i];
+ }
+ }
+
+ if (pos != d.Length)
+ Resize (ref d, pos);
- Resize <T> (ref d, pos);
return d;
}
{
public abstract partial class Array : ICollection, IEnumerable, IList, IStructuralComparable, IStructuralEquatable, ICloneable
{
+ public static Array CreateInstance(Type elementType, params long[] lengths)
+ {
+ if (lengths == null)
+ throw new ArgumentNullException(nameof(lengths));
+ if (lengths.Length == 0)
+ throw new ArgumentException(SR.Arg_NeedAtLeast1Rank);
+
+ int[] intLengths = new int[lengths.Length];
+
+ for (int i = 0; i < lengths.Length; ++i)
+ {
+ long len = lengths[i];
+ if (len > int.MaxValue || len < int.MinValue)
+ throw new ArgumentOutOfRangeException("len", SR.ArgumentOutOfRange_HugeArrayNotSupported);
+ intLengths[i] = (int)len;
+ }
+
+ return Array.CreateInstance(elementType, intLengths);
+ }
+
public static ReadOnlyCollection<T> AsReadOnly<T>(T[] array)
{
if (array == null)
void IList.Clear()
{
- Array.Clear(this, 0, this.Length);
+ Array.Clear(this, GetLowerBound(0), this.Length);
+ }
+
+ int IList.IndexOf(Object value)
+ {
+ return Array.IndexOf(this, value);
}
void IList.Insert(int index, Object value)
if (array != null && array.Rank != 1)
throw new ArgumentException(SR.Arg_RankMultiDimNotSupported);
- Array.Copy(this, 0, array, index, Length);
+ Array.Copy(this, GetLowerBound(0), array, index, Length);
}
// Make a new array which is a deep copy of the original array.
{
if (array == null)
throw new ArgumentNullException(nameof(array));
- return BinarySearch(array, 0, array.Length, value, null);
+ return BinarySearch(array, array.GetLowerBound(0), array.Length, value, null);
}
public static TOutput[] ConvertAll<TInput, TOutput>(TInput[] array, Converter<TInput, TOutput> converter)
public bool IsFixedSize { get { return true; } }
+ public bool IsReadOnly { get { return false; } }
+
// Is this Array synchronized (i.e., thread-safe)? If you want a synchronized
// collection, you can use SyncRoot as an object to synchronize your
// collection with. You could also call GetSynchronized()
{
if (array == null)
throw new ArgumentNullException(nameof(array));
- return BinarySearch(array, 0, array.Length, value, comparer);
+ return BinarySearch(array, array.GetLowerBound(0), array.Length, value, comparer);
}
// Searches a section of an array for a given element using a binary search
throw new ArgumentNullException(nameof(array));
}
- return IndexOf(array, value, 0, array.Length);
+ return IndexOf(array, value, array.GetLowerBound(0), array.Length);
}
// Returns the index of the first occurrence of a given value in a range of
throw new ArgumentNullException(nameof(array));
}
- return IndexOf(array, value, startIndex, array.Length - startIndex);
+ int lb = array.GetLowerBound(0);
+ return IndexOf(array, value, startIndex, array.Length - startIndex + lb);
}
// Returns the index of the first occurrence of a given value in a range of
throw new ArgumentNullException(nameof(array));
if (array.Rank != 1)
throw new RankException(SR.Rank_MultiDimNotSupported);
- if (startIndex < 0 || startIndex > array.Length)
+ int lb = array.GetLowerBound(0);
+ if (startIndex < lb || startIndex > array.Length + lb)
throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index);
- if (count < 0 || count > array.Length - startIndex)
+ if (count < 0 || count > array.Length - startIndex + lb)
throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count);
Object[] objArray = array as Object[];
}
}
}
- return -1;
+ return lb - 1;
}
/// <summary>
if (array == null)
throw new ArgumentNullException(nameof(array));
- Reverse(array, 0, array.Length);
+ Reverse(array, array.GetLowerBound(0), array.Length);
}
// Reverses the elements in a range of an array. Following a call to this
}
}
+ public void SetValue(object value, long index)
+ {
+ if (index > int.MaxValue || index < int.MinValue)
+ throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_HugeArrayNotSupported);
+
+ SetValue(value, (int)index);
+ }
+
+ public void SetValue(object value, long index1, long index2)
+ {
+ if (index1 > int.MaxValue || index1 < int.MinValue)
+ throw new ArgumentOutOfRangeException(nameof(index1), SR.ArgumentOutOfRange_HugeArrayNotSupported);
+ if (index2 > int.MaxValue || index2 < int.MinValue)
+ throw new ArgumentOutOfRangeException(nameof(index2), SR.ArgumentOutOfRange_HugeArrayNotSupported);
+
+ SetValue(value, (int)index1, (int)index2);
+ }
+
+ public void SetValue(object value, long index1, long index2, long index3)
+ {
+ if (index1 > int.MaxValue || index1 < int.MinValue)
+ throw new ArgumentOutOfRangeException(nameof(index1), SR.ArgumentOutOfRange_HugeArrayNotSupported);
+ if (index2 > int.MaxValue || index2 < int.MinValue)
+ throw new ArgumentOutOfRangeException(nameof(index2), SR.ArgumentOutOfRange_HugeArrayNotSupported);
+ if (index3 > int.MaxValue || index3 < int.MinValue)
+ throw new ArgumentOutOfRangeException(nameof(index3), SR.ArgumentOutOfRange_HugeArrayNotSupported);
+
+ SetValue(value, (int)index1, (int)index2, (int)index3);
+ }
+
+ public void SetValue(object value, params long[] indices)
+ {
+ if (indices == null)
+ throw new ArgumentNullException(nameof(indices));
+ if (Rank != indices.Length)
+ throw new ArgumentException(SR.Arg_RankIndices);
+
+ int[] intIndices = new int[indices.Length];
+
+ for (int i = 0; i < indices.Length; ++i)
+ {
+ long index = indices[i];
+ if (index > int.MaxValue || index < int.MinValue)
+ throw new ArgumentOutOfRangeException("index", SR.ArgumentOutOfRange_HugeArrayNotSupported);
+ intIndices[i] = (int)index;
+ }
+
+ SetValue(value, intIndices);
+ }
+
// Sorts the elements of an array. The sort compares the elements to each
// other using the IComparable interface, which must be implemented
// by all elements of the array.
if (array == null)
throw new ArgumentNullException(nameof(array));
- Sort(array, null, 0, array.Length, null);
+ Sort(array, null, array.GetLowerBound(0), array.Length, null);
}
// Sorts the elements in a section of an array. The sort compares the
if (array == null)
throw new ArgumentNullException(nameof(array));
- Sort(array, null, 0, array.Length, comparer);
+ Sort(array, null, array.GetLowerBound(0), array.Length, comparer);
}
// Sorts the elements in a section of an array. The sort compares the
PROFILE_DIR=$(DESTDIR)$(mono_libdir)/mono
+build-reference-assemblies:
+ $(MAKE) -C ../../../external/binary-reference-assemblies CSC="MONO_PATH=$(abspath $(topdir)/class/lib/$(BUILD_TOOLS_PROFILE)) $(INTERNAL_CSC)"
+
install-local:
$(MKINSTALLDIRS) $(PROFILE_DIR)/2.0-api
$(MKINSTALLDIRS) $(PROFILE_DIR)/3.5-api
$(MKINSTALLDIRS) $(PROFILE_DIR)/4.0-api
$(MKINSTALLDIRS) $(PROFILE_DIR)/4.5-api
+ $(MKINSTALLDIRS) $(PROFILE_DIR)/4.5.1-api
+ $(MKINSTALLDIRS) $(PROFILE_DIR)/4.5.2-api
+ $(MKINSTALLDIRS) $(PROFILE_DIR)/4.6-api
+ $(MKINSTALLDIRS) $(PROFILE_DIR)/4.6.1-api
+ $(MKINSTALLDIRS) $(PROFILE_DIR)/4.6.2-api
$(MKINSTALLDIRS) $(PROFILE_DIR)/4.5-api/Facades
+ $(MKINSTALLDIRS) $(PROFILE_DIR)/4.5.1-api/Facades
+ $(MKINSTALLDIRS) $(PROFILE_DIR)/4.5.2-api/Facades
+ $(MKINSTALLDIRS) $(PROFILE_DIR)/4.6-api/Facades
+ $(MKINSTALLDIRS) $(PROFILE_DIR)/4.6.1-api/Facades
+ $(MKINSTALLDIRS) $(PROFILE_DIR)/4.6.2-api/Facades
+
$(INSTALL_LIB) ../../../external/binary-reference-assemblies/v2.0/*.dll $(PROFILE_DIR)/2.0-api
$(INSTALL_LIB) ../../../external/binary-reference-assemblies/v3.5/*.dll $(PROFILE_DIR)/3.5-api
$(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.0/*.dll $(PROFILE_DIR)/4.0-api
$(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.5/*.dll $(PROFILE_DIR)/4.5-api
+ $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.5.1/*.dll $(PROFILE_DIR)/4.5.1-api
+ $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.5.2/*.dll $(PROFILE_DIR)/4.5.2-api
+ $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.6/*.dll $(PROFILE_DIR)/4.6-api
+ $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.6.1/*.dll $(PROFILE_DIR)/4.6.1-api
+ $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.6.2/*.dll $(PROFILE_DIR)/4.6.2-api
$(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.5/Facades/*.dll $(PROFILE_DIR)/4.5-api/Facades
+ $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.5.1/Facades/*.dll $(PROFILE_DIR)/4.5.1-api/Facades
+ $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.5.2/Facades/*.dll $(PROFILE_DIR)/4.5.2-api/Facades
+ $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.6/Facades/*.dll $(PROFILE_DIR)/4.6-api/Facades
+ $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.6.1/Facades/*.dll $(PROFILE_DIR)/4.6.1-api/Facades
+ $(INSTALL_LIB) ../../../external/binary-reference-assemblies/v4.6.2/Facades/*.dll $(PROFILE_DIR)/4.6.2-api/Facades
# Unfortunately, a few programs (most notably NUnit and FSharp) have hardcoded checks for <prefix>/lib/mono/4.0/mscorlib.dll or Mono.Posix.dll,
# so we need to place something there or those tools break. We decided to symlink to the reference assembly for now.
ln -sf ../4.0-api/mscorlib.dll $(PROFILE_DIR)/4.0/mscorlib.dll
ln -sf ../4.0-api/Mono.Posix.dll $(PROFILE_DIR)/4.0/Mono.Posix.dll
-DISTFILES = $(wildcard ../../../external/binary-reference-assemblies/v4.5/Facades/*.dll) $(wildcard ../../../external/binary-reference-assemblies/v4.5/*.dll) $(wildcard ../../../external/binary-reference-assemblies/v4.0/*.dll) $(wildcard ../../../external/binary-reference-assemblies/v3.5/*.dll) $(wildcard ../../../external/binary-reference-assemblies/v2.0/*.dll) Makefile
+DISTFILES = \
+ $(wildcard ../../../external/binary-reference-assemblies/v4.6.2/Facades/*.dll) \
+ $(wildcard ../../../external/binary-reference-assemblies/v4.6.1/Facades/*.dll) \
+ $(wildcard ../../../external/binary-reference-assemblies/v4.6/Facades/*.dll) \
+ $(wildcard ../../../external/binary-reference-assemblies/v4.5.2/Facades/*.dll) \
+ $(wildcard ../../../external/binary-reference-assemblies/v4.5.1/Facades/*.dll) \
+ $(wildcard ../../../external/binary-reference-assemblies/v4.5/Facades/*.dll) \
+ $(wildcard ../../../external/binary-reference-assemblies/v4.6.2/*.dll) \
+ $(wildcard ../../../external/binary-reference-assemblies/v4.6.1/*.dll) \
+ $(wildcard ../../../external/binary-reference-assemblies/v4.6/*.dll) \
+ $(wildcard ../../../external/binary-reference-assemblies/v4.5.2/*.dll) \
+ $(wildcard ../../../external/binary-reference-assemblies/v4.5.1/*.dll) \
+ $(wildcard ../../../external/binary-reference-assemblies/v4.5/*.dll) \
+ $(wildcard ../../../external/binary-reference-assemblies/v4.0/*.dll) \
+ $(wildcard ../../../external/binary-reference-assemblies/v3.5/*.dll) \
+ $(wildcard ../../../external/binary-reference-assemblies/v2.0/*.dll) \
+ $(wildcard ../../../external/binary-reference-assemblies/src/v4.6.2/Facades/*.cs) \
+ $(wildcard ../../../external/binary-reference-assemblies/src/v4.6.1/Facades/*.cs) \
+ $(wildcard ../../../external/binary-reference-assemblies/src/v4.6/Facades/*.cs) \
+ $(wildcard ../../../external/binary-reference-assemblies/src/v4.5.2/Facades/*.cs) \
+ $(wildcard ../../../external/binary-reference-assemblies/src/v4.5.1/Facades/*.cs) \
+ $(wildcard ../../../external/binary-reference-assemblies/src/v4.5/Facades/*.cs) \
+ $(wildcard ../../../external/binary-reference-assemblies/src/v4.6.2/*.cs) \
+ $(wildcard ../../../external/binary-reference-assemblies/src/v4.6.1/*.cs) \
+ $(wildcard ../../../external/binary-reference-assemblies/src/v4.6/*.cs) \
+ $(wildcard ../../../external/binary-reference-assemblies/src/v4.5.2/*.cs) \
+ $(wildcard ../../../external/binary-reference-assemblies/src/v4.5.1/*.cs) \
+ $(wildcard ../../../external/binary-reference-assemblies/src/v4.5/*.cs) \
+ $(wildcard ../../../external/binary-reference-assemblies/src/v4.0/*.cs) \
+ $(wildcard ../../../external/binary-reference-assemblies/src/v3.5/*.cs) \
+ $(wildcard ../../../external/binary-reference-assemblies/src/v2.0/*.cs) \
+ ../../../external/binary-reference-assemblies/v4.6.2/Makefile \
+ ../../../external/binary-reference-assemblies/v4.6.1/Makefile \
+ ../../../external/binary-reference-assemblies/v4.6/Makefile \
+ ../../../external/binary-reference-assemblies/v4.5.2/Makefile \
+ ../../../external/binary-reference-assemblies/v4.5.1/Makefile \
+ ../../../external/binary-reference-assemblies/v4.5/Makefile \
+ ../../../external/binary-reference-assemblies/v4.0/Makefile \
+ ../../../external/binary-reference-assemblies/v3.5/Makefile \
+ ../../../external/binary-reference-assemblies/v2.0/Makefile \
+ ../../../external/binary-reference-assemblies/Makefile \
+ Makefile
dist-local: dist-default
#if MONO
public static IWebProxy CreateDefaultProxy ()
{
-#if FEATURE_NO_BSD_SOCKETS
+#if FEATURE_NO_BSD_SOCKETS || ORBIS
throw new PlatformNotSupportedException ();
#elif MONOTOUCH
return Mono.Net.CFNetwork.GetDefaultProxy ();
sdk_directory.Add ("4", new string[] { "4.0-api", "v4.0.30319" });
sdk_directory.Add ("4.0", new string[] { "4.0-api", "v4.0.30319" });
sdk_directory.Add ("4.5", new string[] { "4.5-api", "v4.0.30319" });
- sdk_directory.Add ("4.6", new string [] { "4.5", "net_4_x", "v4.0.30319" });
+ sdk_directory.Add ("4.5.1", new string[] { "4.5.1-api", "v4.0.30319" });
+ sdk_directory.Add ("4.5.2", new string[] { "4.5.2-api", "v4.0.30319" });
+ sdk_directory.Add ("4.6", new string[] { "4.6-api", "v4.0.30319" });
+ sdk_directory.Add ("4.6.1", new string[] { "4.6.1-api", "v4.0.30319" });
+ sdk_directory.Add ("4.6.2", new string [] { "4.6.2-api", "v4.0.30319" });
+ sdk_directory.Add ("4.x", new string [] { "4.5", "net_4_x", "v4.0.30319" });
}
public StaticLoader (StaticImporter importer, CompilerContext compiler)
string sdk_path = null;
- string sdk_version = compiler.Settings.SdkVersion ?? "4.6";
+ string sdk_version = compiler.Settings.SdkVersion ?? "4.x";
string[] sdk_sub_dirs;
if (!sdk_directory.TryGetValue (sdk_version, out sdk_sub_dirs))
<?xml version="1.0" encoding="utf-8"?>
-<FileList Name=".NET Framework 4.5.1" TargetFrameworkDirectory="..\..\..\..\4.5-api">
+<FileList Name=".NET Framework 4.5.1" TargetFrameworkDirectory="..\..\..\..\4.5.1-api">
</FileList>
<?xml version="1.0" encoding="utf-8"?>
-<FileList Name=".NET Framework 4.5.2" TargetFrameworkDirectory="..\..\..\..\4.5-api">
+<FileList Name=".NET Framework 4.5.2" TargetFrameworkDirectory="..\..\..\..\4.5.2-api">
</FileList>
<?xml version="1.0" encoding="utf-8"?>
-<FileList Name=".NET Framework 4.6.1" TargetFrameworkDirectory="..\..\..\..\4.5">
+<FileList Name=".NET Framework 4.6.1" TargetFrameworkDirectory="..\..\..\..\4.6.1-api">
</FileList>
<?xml version="1.0" encoding="utf-8"?>
-<FileList Name=".NET Framework 4.6.2" TargetFrameworkDirectory="..\..\..\..\4.5">
+<FileList Name=".NET Framework 4.6.2" TargetFrameworkDirectory="..\..\..\..\4.6.2-api">
</FileList>
<?xml version="1.0" encoding="utf-8"?>
-<FileList Name=".NET Framework 4.6" TargetFrameworkDirectory="..\..\..\..\4.5">
+<FileList Name=".NET Framework 4.6" TargetFrameworkDirectory="..\..\..\..\4.6-api">
</FileList>
system (cmd);
g_free (cmd);
if (!objdump_args)
- objdump_args = "";
+ objdump_args = strdup("");
cmd = g_strdup_printf (DIS_CMD " %s %s", objdump_args, o_file);
system (cmd);
g_free (cmd);
+ g_free (objdump_args);
g_free (o_file);
g_free (as_file);
<opcode name="mono_lddomain" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x19" flow="next" />
<opcode name="mono_atomic_store_i4" input="PopI+PopI" output="Push0" args="InlineI" o1="0xF0" o2="0x1A" flow="next" />
<opcode name="mono_get_last_error" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x1B" flow="next" />
+<opcode name="mono_get_rgctx_arg" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x1C" flow="next" />
</opdesc>
OPDEF(CEE_MONO_LDDOMAIN, "mono_lddomain", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x19, NEXT)
OPDEF(CEE_MONO_ATOMIC_STORE_I4, "mono_atomic_store_i4", PopI+PopI, Push0, InlineI, X, 2, 0xF0, 0x1A, NEXT)
OPDEF(CEE_MONO_GET_LAST_ERROR, "mono_get_last_error", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x1B, NEXT)
+OPDEF(CEE_MONO_GET_RGCTX_ARG, "mono_get_rgctx_arg", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x1C, NEXT)
#ifndef OPALIAS
#define _MONO_CIL_OPALIAS_DEFINED_
#define OPALIAS(a,s,r)
* Unloading seems to cause problems when running NUnit/NAnt, hence
* this workaround.
*/
- if (g_getenv ("MONO_NO_UNLOAD"))
+ if (g_hasenv ("MONO_NO_UNLOAD"))
return;
+
#ifdef __native_client__
return;
#endif
}
*dest = *splitted;
- if (g_getenv ("MONO_DEBUG") == NULL)
+ if (g_hasenv ("MONO_DEBUG"))
return;
splitted = assemblies_path;
static void
check_path_env (void)
{
- const char* path;
- path = g_getenv ("MONO_PATH");
+ if (assemblies_path != NULL)
+ return;
+
+ char* path = g_getenv ("MONO_PATH");
#ifdef __native_client__
if (!path)
- path = nacl_mono_path;
+ path = strdup (nacl_mono_path);
#endif
- if (!path || assemblies_path != NULL)
+ if (!path)
return;
mono_set_assemblies_path(path);
+ g_free (path);
}
static void
-check_extra_gac_path_env (void) {
- const char *path;
+check_extra_gac_path_env (void)
+{
+ char *path;
char **splitted, **dest;
path = g_getenv ("MONO_GAC_PREFIX");
return;
splitted = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, 1000);
+ g_free (path);
+
if (extra_gac_paths)
g_strfreev (extra_gac_paths);
extra_gac_paths = dest = splitted;
}
*dest = *splitted;
- if (g_getenv ("MONO_DEBUG") == NULL)
+ if (!g_hasenv ("MONO_DEBUG"))
return;
while (*splitted) {
log_finalizers = 1;
}
}
+ g_free (env);
}
}
*/
}
}
+ g_free (env);
g_strfreev (opts);
}
gboolean
mono_gc_is_disabled (void)
{
- if (GC_dont_gc || g_getenv ("GC_DONT_GC"))
+ if (GC_dont_gc || g_hasenv ("GC_DONT_GC"))
return TRUE;
else
return FALSE;
static gboolean disabled;
static gboolean inited = FALSE;
if (!inited) {
- disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
+ disabled = g_hasenv ("MONO_DISABLE_WCF_HACK");
inited = TRUE;
}
return disabled;
return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
}
+static int
+apply_override (MonoClass *klass, MonoMethod **vtable, MonoMethod *decl, MonoMethod *override)
+{
+ int dslot;
+ dslot = mono_method_get_vtable_slot (decl);
+ if (dslot == -1) {
+ mono_class_set_type_load_failure (klass, "");
+ return FALSE;
+ }
+
+ dslot += mono_class_interface_offset (klass, decl->klass);
+ vtable [dslot] = override;
+ if (!MONO_CLASS_IS_INTERFACE (override->klass)) {
+ /*
+ * If override from an interface, then it is an override of a default interface method,
+ * don't override its slot.
+ */
+ vtable [dslot]->slot = dslot;
+ }
+
+ if (mono_security_core_clr_enabled ())
+ mono_security_core_clr_check_override (klass, vtable [dslot], decl);
+
+ return TRUE;
+}
+
/*
* LOCKING: this is supposed to be called with the loader lock held.
*/
}
TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
+
+ /* Process overrides from interface default methods */
+ // FIXME: Ordering between interfaces
+ for (int ifindex = 0; ifindex < klass->interface_offsets_count; ifindex++) {
+ ic = klass->interfaces_packed [ifindex];
+
+ mono_class_setup_methods (ic);
+ if (mono_class_has_failure (ic))
+ goto fail;
+
+ MonoMethod **iface_overrides;
+ int iface_onum;
+ gboolean ok = mono_class_get_overrides_full (ic->image, ic->type_token, &iface_overrides, &iface_onum, mono_class_get_context (ic));
+ if (ok) {
+ for (int i = 0; i < iface_onum; i++) {
+ MonoMethod *decl = iface_overrides [i*2];
+ MonoMethod *override = iface_overrides [i*2 + 1];
+ if (!apply_override (klass, vtable, decl, override))
+ goto fail;
+
+ if (!override_map)
+ override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
+ g_hash_table_insert (override_map, decl, override);
+ }
+ g_free (iface_overrides);
+ }
+ }
+
/* override interface methods */
for (i = 0; i < onum; i++) {
MonoMethod *decl = overrides [i*2];
+ MonoMethod *override = overrides [i*2 + 1];
if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
- int dslot;
- dslot = mono_method_get_vtable_slot (decl);
- if (dslot == -1) {
- mono_class_set_type_load_failure (klass, "");
+ if (!apply_override (klass, vtable, decl, override))
goto fail;
- }
- dslot += mono_class_interface_offset (klass, decl->klass);
- vtable [dslot] = overrides [i*2 + 1];
- vtable [dslot]->slot = dslot;
if (!override_map)
override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
-
- g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
-
- if (mono_security_core_clr_enabled ())
- mono_security_core_clr_check_override (klass, vtable [dslot], decl);
+ g_hash_table_insert (override_map, decl, override);
}
}
+
TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
}
}
+
+ if (vtable [im_slot] == NULL) {
+ if (!(im->flags & METHOD_ATTRIBUTE_ABSTRACT)) {
+ TRACE_INTERFACE_VTABLE (printf (" Using default iface method %s.\n", mono_method_full_name (im, 1)));
+ vtable [im_slot] = im;
+ }
+ }
} else {
g_assert (vtable [im_slot] == override_im);
}
void
mono_cominterop_init (void)
{
- const char* com_provider_env;
+ char* com_provider_env;
mono_os_mutex_init_recursive (&cominterop_mutex);
com_provider_env = g_getenv ("MONO_COM");
if (com_provider_env && !strcmp(com_provider_env, "MS"))
com_provider = MONO_COM_MS;
+ if (com_provider_env)
+ g_free (com_provider_env);
register_icall (cominterop_get_method_interface, "cominterop_get_method_interface", "ptr ptr", FALSE);
register_icall (cominterop_get_function_pointer, "cominterop_get_function_pointer", "ptr ptr int32", FALSE);
#include <mono/metadata/console-io.h>
#include <mono/metadata/exception.h>
+#include <mono/metadata/w32file.h>
+#include <mono/utils/w32api.h>
void
mono_console_init (void)
if (dims == -1){
int cols = 0, rows = 0;
- const char *str = g_getenv ("COLUMNS");
- if (str != NULL)
+ char *str = g_getenv ("COLUMNS");
+ if (str != NULL) {
cols = atoi (str);
+ g_free (str);
+ }
str = g_getenv ("LINES");
- if (str != NULL)
+ if (str != NULL) {
rows = atoi (str);
+ g_free (str);
+ }
if (cols != 0 && rows != 0)
cols_and_lines = (cols << 16) | rows;
ICALL_TYPE(ENV, "System.Environment", ENV_1)
ICALL(ENV_1, "Exit", ves_icall_System_Environment_Exit)
-ICALL(ENV_2, "GetCommandLineArgs", ves_icall_System_Environment_GetCoomandLineArgs)
+ICALL(ENV_2, "GetCommandLineArgs", ves_icall_System_Environment_GetCommandLineArgs)
ICALL(ENV_3, "GetEnvironmentVariableNames", ves_icall_System_Environment_GetEnvironmentVariableNames)
ICALL(ENV_31, "GetIs64BitOperatingSystem", ves_icall_System_Environment_GetIs64BitOperatingSystem)
ICALL(ENV_4, "GetLogicalDrivesInternal", ves_icall_System_Environment_GetLogicalDrives )
ICALL_EXPORT MonoStringHandle
ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
{
- const gchar *value;
+ gchar *value;
if (utf8_name == NULL)
return NULL_HANDLE_STRING;
if (value == 0)
return NULL_HANDLE_STRING;
- return mono_string_new_handle (mono_domain_get (), value, error);
+ MonoStringHandle res = mono_string_new_handle (mono_domain_get (), value, error);
+ g_free (value);
+ return res;
}
/*
#endif
ICALL_EXPORT MonoArray *
-ves_icall_System_Environment_GetCoomandLineArgs (void)
+ves_icall_System_Environment_GetCommandLineArgs (void)
{
MonoError error;
MonoArray *result = mono_runtime_get_main_args_checked (&error);
for(hash_idx = 0; hash_idx < IMAGES_HASH_COUNT; hash_idx++)
loaded_images_hashes [hash_idx] = g_hash_table_new (g_str_hash, g_str_equal);
- debug_assembly_unload = g_getenv ("MONO_DEBUG_ASSEMBLY_UNLOAD") != NULL;
+ debug_assembly_unload = g_hasenv ("MONO_DEBUG_ASSEMBLY_UNLOAD");
install_pe_loader ();
static char *
get_posix_locale (void)
{
- const char *locale;
+ char *locale;
locale = g_getenv ("LC_ALL");
if (locale == NULL) {
locale = g_getenv ("LANG");
- if (locale == NULL)
- locale = setlocale (LC_ALL, NULL);
+ if (locale == NULL) {
+ char *static_locale = setlocale (LC_ALL, NULL);
+ if (static_locale)
+ locale = g_strdup (static_locale);
+ }
}
if (locale == NULL)
return NULL;
/* Skip English-only locale 'C' */
- if (strcmp (locale, "C") == 0)
+ if (strcmp (locale, "C") == 0) {
+ g_free (locale);
return NULL;
+ }
- return g_strdup (locale);
+ return locale;
}
int res;
char *name;
mono_os_mutex_init_recursive (&tracer_lock);
- if (!g_getenv ("MONO_ENABLE_LOCK_TRACER"))
+
+ if (!g_hasenv ("MONO_ENABLE_LOCK_TRACER"))
return;
+
name = g_strdup_printf ("locks.%d", getpid ());
trace_file = fopen (name, "w+");
g_free (name);
static void init_safe_handle (void);
static void*
-ves_icall_marshal_alloc (gulong size);
+ves_icall_marshal_alloc (gsize size);
void
mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text);
register_icall (mono_ftnptr_to_delegate, "mono_ftnptr_to_delegate", "object ptr ptr", FALSE);
register_icall (mono_marshal_asany, "mono_marshal_asany", "ptr object int32 int32", FALSE);
register_icall (mono_marshal_free_asany, "mono_marshal_free_asany", "void object ptr int32 int32", FALSE);
- register_icall (ves_icall_marshal_alloc, "ves_icall_marshal_alloc", "ptr int32", FALSE);
+ register_icall (ves_icall_marshal_alloc, "ves_icall_marshal_alloc", "ptr ptr", FALSE);
register_icall (mono_marshal_free, "mono_marshal_free", "void ptr", FALSE);
register_icall (mono_marshal_set_last_error, "mono_marshal_set_last_error", "void", FALSE);
register_icall (mono_marshal_set_last_error_windows, "mono_marshal_set_last_error_windows", "void int32", FALSE);
* mono_marshal_alloc:
*/
void*
-mono_marshal_alloc (gulong size, MonoError *error)
+mono_marshal_alloc (gsize size, MonoError *error)
{
gpointer res;
/* This is a JIT icall, it sets the pending exception and returns NULL on error. */
static void*
-ves_icall_marshal_alloc (gulong size)
+ves_icall_marshal_alloc (gsize size)
{
MonoError error;
void *ret = mono_marshal_alloc (size, &error);
/* Subtypes of MONO_WRAPPER_UNKNOWN */
WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG,
WRAPPER_SUBTYPE_GSHAREDVT_OUT_SIG,
+ WRAPPER_SUBTYPE_INTERP_IN
} WrapperSubtype;
typedef struct {
MonoMethod *method;
} DelegateInvokeWrapperInfo;
+typedef struct {
+ MonoMethodSignature *sig;
+} InterpInWrapperInfo;
+
/*
* This structure contains additional information to uniquely identify a given wrapper
* method. It can be retrieved by mono_marshal_get_wrapper_info () for certain types
GsharedvtWrapperInfo gsharedvt;
/* DELEGATE_INVOKE */
DelegateInvokeWrapperInfo delegate_invoke;
+ /* INTERP_IN */
+ InterpInWrapperInfo interp_in;
} d;
} WrapperInfo;
/* marshaling internal calls */
void *
-mono_marshal_alloc (gulong size, MonoError *error);
+mono_marshal_alloc (gsize size, MonoError *error);
void
mono_marshal_free (gpointer ptr);
static GHashTable *config_handlers;
-static const char *mono_cfg_dir = NULL;
-static char *mono_cfg_dir_allocated = NULL;
+static char *mono_cfg_dir = NULL;
/* when this interface is stable, export it. */
typedef struct MonoParseHandler MonoParseHandler;
{
if (config_handlers)
g_hash_table_destroy (config_handlers);
- g_free (mono_cfg_dir_allocated);
+ g_free (mono_cfg_dir);
}
/* FIXME: error handling */
return;
}
- home = g_getenv ("MONO_CONFIG");
- if (home) {
- mono_config_parse_file (home);
+ // FIXME: leak, do we store any references to home
+ char *env_home = g_getenv ("MONO_CONFIG");
+ if (env_home) {
+ mono_config_parse_file (env_home);
return;
}
void
mono_set_config_dir (const char *dir)
{
- /* If this variable is set, overrides the directory computed */
- mono_cfg_dir = g_getenv ("MONO_CFG_DIR");
- if (mono_cfg_dir == NULL)
- mono_cfg_dir = mono_cfg_dir_allocated = g_strdup (dir);
+ /* If this environment variable is set, overrides the directory computed */
+ char *env_mono_cfg_dir = g_getenv ("MONO_CFG_DIR");
+ if (env_mono_cfg_dir == NULL && dir != NULL)
+ env_mono_cfg_dir = strdup (dir);
+
+ mono_cfg_dir = env_mono_cfg_dir;
}
/**
#include "sgen/sgen-client.h"
#include "sgen/sgen-cardtable.h"
#include "sgen/sgen-pinning.h"
-#include "sgen/sgen-thread-pool.h"
+#include "sgen/sgen-workers.h"
#include "metadata/marshal.h"
#include "metadata/method-builder.h"
#include "metadata/abi-details.h"
* lock-free data structure for the queue as multiple threads will be
* adding to it at the same time.
*/
- if (sgen_thread_pool_is_thread_pool_thread (mono_native_thread_id_get ())) {
+ if (sgen_workers_is_worker_thread (mono_native_thread_id_get ())) {
sgen_pointer_queue_add (&moved_objects_queue, obj);
sgen_pointer_queue_add (&moved_objects_queue, destination);
} else {
void
mono_gc_base_cleanup (void)
{
- sgen_thread_pool_shutdown ();
+ sgen_thread_pool_shutdown (major_collector.get_sweep_pool ());
+
+ sgen_workers_shutdown ();
// We should have consumed any outstanding moves.
g_assert (sgen_pointer_queue_is_empty (&moved_objects_queue));
#include "sgen/sgen-gc.h"
#include "sgen/sgen-protocol.h"
#include "sgen/sgen-memory-governor.h"
-#include "sgen/sgen-thread-pool.h"
+#include "sgen/sgen-workers.h"
#include "metadata/profiler-private.h"
#include "sgen/sgen-client.h"
#include "metadata/sgen-bridge-internals.h"
We can't suspend the workers that will do all the heavy lifting.
FIXME Use some state bit in SgenThreadInfo for this.
*/
- if (sgen_thread_pool_is_thread_pool_thread (mono_thread_info_get_tid (info))) {
+ if (sgen_thread_pool_is_thread_pool_thread (major_collector.get_sweep_pool (), mono_thread_info_get_tid (info)) ||
+ sgen_workers_is_worker_thread (mono_thread_info_get_tid (info))) {
if (reason)
*reason = 4;
return FALSE;
threadpool_io->updates_size = 0;
threadpool_io->backend = backend_poll;
- if (g_getenv ("MONO_ENABLE_AIO") != NULL) {
+ if (g_hasenv ("MONO_ENABLE_AIO")) {
#if defined(HAVE_EPOLL)
threadpool_io->backend = backend_epoll;
#elif defined(HAVE_KQUEUE)
/* mono_w32handle_register_capabilities (MONO_W32HANDLE_CONSOLE, */
/* MONO_W32HANDLE_CAP_WAIT); */
- if (g_getenv ("MONO_STRICT_IO_EMULATION"))
+ if (g_hasenv ("MONO_STRICT_IO_EMULATION"))
lock_while_writing = TRUE;
}
basic-vectors.cs \
aot-tests.cs \
gc-test.cs \
- gshared.cs
+ gshared.cs \
+ mixed.cs
if NACL_CODEGEN
test_sources += nacl.cs
richeck: mono $(regtests)
$(INTERP_RUNTIME) --regression $(regtests)
+mixedcheck: mono mixed.exe
+ $(MINI_RUNTIME) --interp=jit=JitClass mixed.exe
+
if ARM
check-seq-points:
else
#endif
mono_counters_register ("Async JIT info size", MONO_COUNTER_INT|MONO_COUNTER_JIT, &async_jit_info_size);
- if (g_getenv ("MONO_LASTAOT"))
- mono_last_aot_method = atoi (g_getenv ("MONO_LASTAOT"));
+ char *lastaot = g_getenv ("MONO_LASTAOT");
+ if (lastaot) {
+ mono_last_aot_method = atoi (lastaot);
+ g_free (lastaot);
+ }
aot_cache_init ();
}
char **args, **ptr;
char *host;
int port;
- const char *extra;
+ char *extra;
#ifndef MONO_ARCH_SOFT_DEBUG_SUPPORTED
fprintf (stderr, "--debugger-agent is not supported on this platform.\n");
#endif
extra = g_getenv ("MONO_SDB_ENV_OPTIONS");
- if (extra)
+ if (extra) {
options = g_strdup_printf ("%s,%s", options, extra);
+ g_free (extra);
+ }
agent_config.enabled = TRUE;
agent_config.suspend = TRUE;
break;
case OP_BOUNDS_CHECK:
MONO_EMIT_NULL_CHECK (cfg, ins->sreg1);
- if (COMPILE_LLVM (cfg))
- MONO_EMIT_DEFAULT_BOUNDS_CHECK (cfg, ins->sreg1, ins->inst_imm, ins->sreg2, ins->flags & MONO_INST_FAULT);
- else
+ if (COMPILE_LLVM (cfg)) {
+ int index2_reg = alloc_preg (cfg);
+ MONO_EMIT_NEW_UNALU (cfg, OP_SEXT_I4, index2_reg, ins->sreg2);
+ MONO_EMIT_DEFAULT_BOUNDS_CHECK (cfg, ins->sreg1, ins->inst_imm, index2_reg, ins->flags & MONO_INST_FAULT);
+ } else {
MONO_ARCH_EMIT_BOUNDS_CHECK (cfg, ins->sreg1, ins->inst_imm, ins->sreg2);
+ }
break;
case OP_NEWARR:
if (cfg->opt & MONO_OPT_SHARED) {
darwin_change_default_file_handles ();
#endif
- if (g_getenv ("MONO_NO_SMP"))
+ if (g_hasenv ("MONO_NO_SMP"))
mono_set_use_smp (FALSE);
g_log_set_always_fatal (G_LOG_LEVEL_ERROR);
#endif
} else if (strcmp (argv [i], "--nollvm") == 0){
mono_use_llvm = FALSE;
+ } else if ((strcmp (argv [i], "--interpreter") == 0) || !strcmp (argv [i], "--interp")) {
#ifdef ENABLE_INTERPRETER
- } else if (strcmp (argv [i], "--interpreter") == 0) {
mono_use_interpreter = TRUE;
+#else
+ fprintf (stderr, "Mono Warning: --interpreter not enabled in this runtime.\n");
+#endif
+ } else if (strncmp (argv [i], "--interp=", 9) == 0) {
+#ifdef ENABLE_INTERPRETER
+ mono_use_interpreter = TRUE;
+ mono_interp_parse_options (argv [i] + 9);
+#else
+ fprintf (stderr, "Mono Warning: --interp= not enabled in this runtime.\n");
#endif
#ifdef __native_client__
}
#endif
- if (g_getenv ("MONO_XDEBUG"))
+ if (g_hasenv ("MONO_XDEBUG"))
enable_debugging = TRUE;
#ifdef MONO_CROSS_COMPILE
{
char *ret;
- const char *env_options = g_getenv ("MONO_ENV_OPTIONS");
+ char *env_options = g_getenv ("MONO_ENV_OPTIONS");
if (env_options == NULL)
return;
ret = mono_parse_options_from (env_options, ref_argc, ref_argv);
+ g_free (env_options);
if (ret == NULL)
return;
fprintf (stderr, "%s", ret);
}
return 0;
}
+
+ public class MyException : Exception {
+ public int marker = 0;
+ public string res = "";
+
+ public MyException (String res) {
+ this.res = res;
+ }
+
+ public bool FilterWithoutState () {
+ return this.marker == 0x666;
+ }
+
+ public bool FilterWithState () {
+ bool ret = this.marker == 0x566;
+ this.marker += 0x100;
+ return ret;
+ }
+
+ public bool FilterWithStringState () {
+ bool ret = this.marker == 0x777;
+ this.res = "fromFilter_" + this.res;
+ return ret;
+ }
+ }
+
+ public static int test_1_basic_filter_catch () {
+ try {
+ MyException e = new MyException ("");
+ e.marker = 0x1337;
+ throw e;
+ } catch (MyException ex) when (ex.marker == 0x1337) {
+ return 1;
+ }
+ return 0;
+ }
+
+ public static int test_1234_complicated_filter_catch () {
+ string res = "init";
+ try {
+ MyException e = new MyException (res);
+ e.marker = 0x566;
+ try {
+ try {
+ throw e;
+ } catch (MyException ex) when (ex.FilterWithoutState ()) {
+ res = "WRONG_" + res;
+ } finally {
+ e.marker = 0x777;
+ res = "innerFinally_" + res;
+ }
+ } catch (MyException ex) when (ex.FilterWithState ()) {
+ res = "2ndcatch_" + res;
+ }
+ // "2ndcatch_innerFinally_init"
+ // Console.WriteLine ("res1: " + res);
+ e.res = res;
+ throw e;
+ } catch (MyException ex) when (ex.FilterWithStringState ()) {
+ res = "fwos_" + ex.res;
+ } finally {
+ res = "outerFinally_" + res;
+ }
+ // Console.WriteLine ("res2: " + res);
+ return "outerFinally_fwos_fromFilter_2ndcatch_innerFinally_init" == res ? 1234 : 0;
+ }
}
#if !__MOBILE__
#ifdef HOST_WIN32
const char *tmp = g_get_tmp_dir ();
#endif
- const char *objdump_args = g_getenv ("MONO_OBJDUMP_ARGS");
+ char *objdump_args = g_getenv ("MONO_OBJDUMP_ARGS");
char *as_file;
char *o_file;
char *cmd;
unused = system (cmd);
g_free (cmd);
if (!objdump_args)
- objdump_args = "";
+ objdump_args = g_strdup ("");
fflush (stdout);
cmd = g_strdup_printf (ARCH_PREFIX DIS_CMD " %s %s", objdump_args, o_file);
unused = system (cmd);
g_free (cmd);
+ g_free (objdump_args);
#else
g_assert_not_reached ();
#endif /* HAVE_SYSTEM */
}
.method public static int32 test_1_filters () {
- .custom instance void [TestDriver]CategoryAttribute::.ctor(string) = ( 01 00 0C 21 49 4E 54 45 52 50 52 45 54 45 52 00 00 ) // ...!INTERPRETER.
.custom instance void [TestDriver]CategoryAttribute::.ctor(string) = ( 01 00 08 21 42 49 54 43 4F 44 45 00 00 ) // ...!BITCODE..
.maxstack 16
.locals init (
guint32 *local_offsets;
unsigned int param_count;
unsigned int hasthis;
+ gpointer jit_wrapper;
+ gpointer jit_addr;
+ MonoMethodSignature *jit_sig;
+ gpointer jit_entry;
+ MonoType *rtype;
+ MonoType **param_types;
} RuntimeMethod;
struct _MonoInvocation {
} ThreadContext;
extern int mono_interp_traceopt;
+extern GSList *jit_classes;
MonoException *
mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *context);
#endif
#endif
-#define INIT_FRAME(frame,parent_frame,method_args,method_retval,domain,mono_method,error) \
- do { \
- (frame)->parent = (parent_frame); \
- (frame)->stack_args = (method_args); \
- (frame)->retval = (method_retval); \
- (frame)->runtime_method = mono_interp_get_runtime_method ((domain), (mono_method), (error)); \
- (frame)->ex = NULL; \
- (frame)->ip = NULL; \
- (frame)->invoke_trap = 0; \
+static inline void
+init_frame (MonoInvocation *frame, MonoInvocation *parent_frame, RuntimeMethod *rmethod, stackval *method_args, stackval *method_retval)
+{
+ frame->parent = parent_frame;
+ frame->stack_args = method_args;
+ frame->retval = method_retval;
+ frame->runtime_method = rmethod;
+ frame->ex = NULL;
+ frame->ip = NULL;
+ frame->invoke_trap = 0;
+}
+
+#define INIT_FRAME(frame,parent_frame,method_args,method_retval,domain,mono_method,error) do { \
+ RuntimeMethod *_rmethod = mono_interp_get_runtime_method ((domain), (mono_method), (error)); \
+ init_frame ((frame), (parent_frame), _rmethod, (method_args), (method_retval)); \
} while (0)
+/*
+ * List of classes whose methods will be executed by transitioning to JITted code.
+ * Used for testing.
+ */
+GSList *jit_classes;
+
void ves_exec_method (MonoInvocation *frame);
static char* dump_stack (stackval *stack, stackval *sp);
mono_interp_get_runtime_method (MonoDomain *domain, MonoMethod *method, MonoError *error)
{
RuntimeMethod *rtm;
+ MonoJitDomainInfo *info;
+ MonoMethodSignature *sig;
+ int i;
+
error_init (error);
+ info = domain_jit_info (domain);
mono_domain_jit_code_hash_lock (domain);
- if ((rtm = mono_internal_hash_table_lookup (&domain->jit_code_hash, method))) {
- mono_domain_jit_code_hash_unlock (domain);
+ rtm = mono_internal_hash_table_lookup (&info->interp_code_hash, method);
+ mono_domain_jit_code_hash_unlock (domain);
+ if (rtm)
return rtm;
- }
+
+ sig = mono_method_signature (method);
+
rtm = mono_domain_alloc0 (domain, sizeof (RuntimeMethod));
rtm->method = method;
- rtm->param_count = mono_method_signature (method)->param_count;
- rtm->hasthis = mono_method_signature (method)->hasthis;
- mono_internal_hash_table_insert (&domain->jit_code_hash, method, rtm);
+ rtm->param_count = sig->param_count;
+ rtm->hasthis = sig->hasthis;
+ rtm->rtype = mini_get_underlying_type (sig->ret);
+ rtm->param_types = mono_domain_alloc0 (domain, sizeof (MonoType*) * sig->param_count);
+ for (i = 0; i < sig->param_count; ++i)
+ rtm->param_types [i] = mini_get_underlying_type (sig->params [i]);
+
+ mono_domain_jit_code_hash_lock (domain);
+ if (!mono_internal_hash_table_lookup (&info->interp_code_hash, method))
+ mono_internal_hash_table_insert (&info->interp_code_hash, method, rtm);
mono_domain_jit_code_hash_unlock (domain);
return rtm;
return retval;
}
+typedef struct {
+ RuntimeMethod *rmethod;
+ gpointer this_arg;
+ gpointer res;
+ gpointer args [16];
+ gpointer *many_args;
+} InterpEntryData;
+
+/* Main function for entering the interpreter from compiled code */
+static void
+interp_entry (InterpEntryData *data)
+{
+ MonoInvocation frame;
+ RuntimeMethod *rmethod = data->rmethod;
+ ThreadContext *context = mono_native_tls_get_value (thread_context_id);
+ ThreadContext context_struct;
+ MonoInvocation *old_frame;
+ stackval result;
+ stackval *args;
+ MonoMethod *method;
+ MonoMethodSignature *sig;
+ MonoType *type;
+ int i;
+
+ method = rmethod->method;
+ sig = mono_method_signature (method);
+
+ // FIXME: Optimize this
+
+ //printf ("%s\n", mono_method_full_name (method, 1));
+
+ frame.ex = NULL;
+ if (context == NULL) {
+ context = &context_struct;
+ memset (context, 0, sizeof (ThreadContext));
+ context_struct.base_frame = &frame;
+ context_struct.env_frame = &frame;
+ mono_native_tls_set_value (thread_context_id, context);
+ }
+ else
+ old_frame = context->current_frame;
+ context->domain = mono_domain_get ();
+
+ args = alloca (sizeof (stackval) * (sig->param_count + (sig->hasthis ? 1 : 0)));
+ if (sig->hasthis)
+ args [0].data.p = data->this_arg;
+
+ gpointer *params;
+ if (data->many_args)
+ params = data->many_args;
+ else
+ params = data->args;
+ for (i = 0; i < sig->param_count; ++i) {
+ int a_index = i + (sig->hasthis ? 1 : 0);
+ if (sig->params [i]->byref) {
+ args [a_index].data.p = params [i];
+ continue;
+ }
+ type = rmethod->param_types [i];
+ switch (type->type) {
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I1:
+ args [a_index].data.i = *(MonoBoolean*)params [i];
+ break;
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I2:
+ args [a_index].data.i = *(gint16*)params [i];
+ break;
+ case MONO_TYPE_U:
+#if SIZEOF_VOID_P == 4
+ args [a_index].data.p = GINT_TO_POINTER (*(guint32*)params [i]);
+#else
+ args [a_index].data.p = GINT_TO_POINTER (*(guint64*)params [i]);
+#endif
+ break;
+ case MONO_TYPE_I:
+#if SIZEOF_VOID_P == 4
+ args [a_index].data.p = GINT_TO_POINTER (*(gint32*)params [i]);
+#else
+ args [a_index].data.p = GINT_TO_POINTER (*(gint64*)params [i]);
+#endif
+ break;
+ case MONO_TYPE_U4:
+ args [a_index].data.i = *(guint32*)params [i];
+ break;
+ case MONO_TYPE_I4:
+ args [a_index].data.i = *(gint32*)params [i];
+ break;
+ case MONO_TYPE_U8:
+ args [a_index].data.l = *(guint64*)params [i];
+ break;
+ case MONO_TYPE_I8:
+ args [a_index].data.l = *(gint64*)params [i];
+ break;
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_OBJECT:
+ args [a_index].data.p = *(MonoObject**)params [i];
+ break;
+ case MONO_TYPE_VALUETYPE:
+ args [a_index].data.p = params [i];
+ break;
+ case MONO_TYPE_GENERICINST:
+ if (MONO_TYPE_IS_REFERENCE (type))
+ args [a_index].data.p = params [i];
+ else
+ args [a_index].data.vt = params [i];
+ break;
+ default:
+ printf ("%s\n", mono_type_full_name (sig->params [i]));
+ NOT_IMPLEMENTED;
+ break;
+ }
+ }
+
+ init_frame (&frame, context->current_frame, data->rmethod, args, &result);
+ context->managed_code = 1;
+
+ type = rmethod->rtype;
+ switch (type->type) {
+ case MONO_TYPE_GENERICINST:
+ if (!MONO_TYPE_IS_REFERENCE (type))
+ frame.retval->data.vt = data->res;
+ break;
+ case MONO_TYPE_VALUETYPE:
+ frame.retval->data.vt = data->res;
+ break;
+ default:
+ break;
+ }
+
+ ves_exec_method_with_context (&frame, context);
+ context->managed_code = 0;
+ if (context == &context_struct)
+ mono_native_tls_set_value (thread_context_id, NULL);
+ else
+ context->current_frame = old_frame;
+
+ // FIXME:
+ g_assert (frame.ex == NULL);
+
+ type = rmethod->rtype;
+ switch (type->type) {
+ case MONO_TYPE_VOID:
+ break;
+ case MONO_TYPE_I1:
+ *(gint8*)data->res = frame.retval->data.i;
+ break;
+ case MONO_TYPE_U1:
+ *(guint8*)data->res = frame.retval->data.i;
+ break;
+ case MONO_TYPE_I2:
+ *(gint16*)data->res = frame.retval->data.i;
+ break;
+ case MONO_TYPE_U2:
+ *(guint16*)data->res = frame.retval->data.i;
+ break;
+ case MONO_TYPE_I4:
+ *(gint32*)data->res = frame.retval->data.i;
+ break;
+ case MONO_TYPE_U4:
+ *(guint64*)data->res = frame.retval->data.i;
+ break;
+ case MONO_TYPE_I8:
+ *(gint64*)data->res = frame.retval->data.i;
+ break;
+ case MONO_TYPE_U8:
+ *(guint64*)data->res = frame.retval->data.i;
+ break;
+ case MONO_TYPE_I:
+#if SIZEOF_VOID_P == 8
+ *(gint64*)data->res = (gint64)frame.retval->data.p;
+#else
+ *(gint32*)data->res = (gint32)frame.retval->data.p;
+#endif
+ break;
+ case MONO_TYPE_U:
+#if SIZEOF_VOID_P == 8
+ *(guint64*)data->res = (guint64)frame.retval->data.p;
+#else
+ *(guint32*)data->res = (guint32)frame.retval->data.p;
+#endif
+ break;
+ case MONO_TYPE_OBJECT:
+ /* No need for a write barrier */
+ *(MonoObject**)data->res = (MonoObject*)frame.retval->data.p;
+ break;
+ case MONO_TYPE_GENERICINST:
+ if (MONO_TYPE_IS_REFERENCE (type)) {
+ *(MonoObject**)data->res = *(MonoObject**)frame.retval->data.p;
+ } else {
+ /* Already set before the call */
+ }
+ break;
+ case MONO_TYPE_VALUETYPE:
+ /* Already set before the call */
+ break;
+ default:
+ printf ("%s\n", mono_type_full_name (sig->ret));
+ NOT_IMPLEMENTED;
+ break;
+ }
+}
+
static stackval *
do_icall (ThreadContext *context, int op, stackval *sp, gpointer ptr)
{
return sp;
}
-static mono_mutex_t create_method_pointer_mutex;
-
-static GHashTable *method_pointer_hash = NULL;
-
-#define TRAMPS_USED 8
-
-static MonoMethod *method_pointers [TRAMPS_USED] = {0};
-
-#define GEN_METHOD_PTR_TRAMP(num) \
- static MonoObject * mp_tramp_ ## num (MonoObject *this_obj, void **params, MonoObject **exc, void *compiled_method) { \
- MonoError error; \
- void *params_real[] = {this_obj, ¶ms, &exc, &compiled_method}; \
- MonoObject *ret = mono_interp_runtime_invoke (method_pointers [num], NULL, params_real, NULL, &error); \
- mono_error_cleanup (&error); \
- return ret; \
- }
-
+/*
+ * These functions are the entry points into the interpreter from compiled code.
+ * They are called by the interp_in wrappers. They have the following signature:
+ * void (<optional this_arg>, <optional retval pointer>, <arg1>, ..., <argn>, <method ptr>)
+ * They pack up their arguments into an InterpEntryData structure and call interp_entry ().
+ * It would be possible for the wrappers to pack up the arguments etc, but that would make them bigger, and there are
+ * more wrappers then these functions.
+ * this/static * ret/void * 16 arguments -> 64 functions.
+ */
-GEN_METHOD_PTR_TRAMP (0);
-GEN_METHOD_PTR_TRAMP (1);
-GEN_METHOD_PTR_TRAMP (2);
-GEN_METHOD_PTR_TRAMP (3);
-GEN_METHOD_PTR_TRAMP (4);
-GEN_METHOD_PTR_TRAMP (5);
-GEN_METHOD_PTR_TRAMP (6);
-GEN_METHOD_PTR_TRAMP (7);
+#define MAX_INTERP_ENTRY_ARGS 8
-#undef GEN_METHOD_PTR_TRAMP
+#define INTERP_ENTRY_BASE(_method, _this_arg, _res) \
+ InterpEntryData data; \
+ (data).rmethod = (_method); \
+ (data).res = (_res); \
+ (data).this_arg = (_this_arg); \
+ (data).many_args = NULL;
-gpointer *mp_tramps[TRAMPS_USED] = {
- (gpointer) mp_tramp_0, (gpointer) mp_tramp_1, (gpointer) mp_tramp_2, (gpointer) mp_tramp_3,
- (gpointer) mp_tramp_4, (gpointer) mp_tramp_5, (gpointer) mp_tramp_6, (gpointer) mp_tramp_7
-};
+#define INTERP_ENTRY0(_this_arg, _res, _method) { \
+ INTERP_ENTRY_BASE (_method, _this_arg, _res); \
+ interp_entry (&data); \
+ }
+#define INTERP_ENTRY1(_this_arg, _res, _method) { \
+ INTERP_ENTRY_BASE (_method, _this_arg, _res); \
+ (data).args [0] = arg1; \
+ interp_entry (&data); \
+ }
+#define INTERP_ENTRY2(_this_arg, _res, _method) { \
+ INTERP_ENTRY_BASE (_method, _this_arg, _res); \
+ (data).args [0] = arg1; \
+ (data).args [1] = arg2; \
+ interp_entry (&data); \
+ }
+#define INTERP_ENTRY3(_this_arg, _res, _method) { \
+ INTERP_ENTRY_BASE (_method, _this_arg, _res); \
+ (data).args [0] = arg1; \
+ (data).args [1] = arg2; \
+ (data).args [2] = arg3; \
+ interp_entry (&data); \
+ }
+#define INTERP_ENTRY4(_this_arg, _res, _method) { \
+ INTERP_ENTRY_BASE (_method, _this_arg, _res); \
+ (data).args [0] = arg1; \
+ (data).args [1] = arg2; \
+ (data).args [2] = arg3; \
+ (data).args [3] = arg4; \
+ interp_entry (&data); \
+ }
+#define INTERP_ENTRY5(_this_arg, _res, _method) { \
+ INTERP_ENTRY_BASE (_method, _this_arg, _res); \
+ (data).args [0] = arg1; \
+ (data).args [1] = arg2; \
+ (data).args [2] = arg3; \
+ (data).args [3] = arg4; \
+ (data).args [4] = arg5; \
+ interp_entry (&data); \
+ }
+#define INTERP_ENTRY6(_this_arg, _res, _method) { \
+ INTERP_ENTRY_BASE (_method, _this_arg, _res); \
+ (data).args [0] = arg1; \
+ (data).args [1] = arg2; \
+ (data).args [2] = arg3; \
+ (data).args [3] = arg4; \
+ (data).args [4] = arg5; \
+ (data).args [5] = arg6; \
+ interp_entry (&data); \
+ }
+#define INTERP_ENTRY7(_this_arg, _res, _method) { \
+ INTERP_ENTRY_BASE (_method, _this_arg, _res); \
+ (data).args [0] = arg1; \
+ (data).args [1] = arg2; \
+ (data).args [2] = arg3; \
+ (data).args [3] = arg4; \
+ (data).args [4] = arg5; \
+ (data).args [5] = arg6; \
+ (data).args [6] = arg7; \
+ interp_entry (&data); \
+ }
+#define INTERP_ENTRY8(_this_arg, _res, _method) { \
+ INTERP_ENTRY_BASE (_method, _this_arg, _res); \
+ (data).args [0] = arg1; \
+ (data).args [1] = arg2; \
+ (data).args [2] = arg3; \
+ (data).args [3] = arg4; \
+ (data).args [4] = arg5; \
+ (data).args [5] = arg6; \
+ (data).args [6] = arg7; \
+ (data).args [7] = arg8; \
+ interp_entry (&data); \
+ }
-static int tramps_used = 0;
+#define ARGLIST0 RuntimeMethod *rmethod
+#define ARGLIST1 gpointer arg1, RuntimeMethod *rmethod
+#define ARGLIST2 gpointer arg1, gpointer arg2, RuntimeMethod *rmethod
+#define ARGLIST3 gpointer arg1, gpointer arg2, gpointer arg3, RuntimeMethod *rmethod
+#define ARGLIST4 gpointer arg1, gpointer arg2, gpointer arg3, gpointer arg4, RuntimeMethod *rmethod
+#define ARGLIST5 gpointer arg1, gpointer arg2, gpointer arg3, gpointer arg4, gpointer arg5, RuntimeMethod *rmethod
+#define ARGLIST6 gpointer arg1, gpointer arg2, gpointer arg3, gpointer arg4, gpointer arg5, gpointer arg6, RuntimeMethod *rmethod
+#define ARGLIST7 gpointer arg1, gpointer arg2, gpointer arg3, gpointer arg4, gpointer arg5, gpointer arg6, gpointer arg7, RuntimeMethod *rmethod
+#define ARGLIST8 gpointer arg1, gpointer arg2, gpointer arg3, gpointer arg4, gpointer arg5, gpointer arg6, gpointer arg7, gpointer arg8, RuntimeMethod *rmethod
+
+static void interp_entry_static_0 (ARGLIST0) INTERP_ENTRY0 (NULL, NULL, rmethod)
+static void interp_entry_static_1 (ARGLIST1) INTERP_ENTRY1 (NULL, NULL, rmethod)
+static void interp_entry_static_2 (ARGLIST2) INTERP_ENTRY2 (NULL, NULL, rmethod)
+static void interp_entry_static_3 (ARGLIST3) INTERP_ENTRY3 (NULL, NULL, rmethod)
+static void interp_entry_static_4 (ARGLIST4) INTERP_ENTRY4 (NULL, NULL, rmethod)
+static void interp_entry_static_5 (ARGLIST5) INTERP_ENTRY5 (NULL, NULL, rmethod)
+static void interp_entry_static_6 (ARGLIST6) INTERP_ENTRY6 (NULL, NULL, rmethod)
+static void interp_entry_static_7 (ARGLIST7) INTERP_ENTRY7 (NULL, NULL, rmethod)
+static void interp_entry_static_8 (ARGLIST8) INTERP_ENTRY8 (NULL, NULL, rmethod)
+static void interp_entry_static_ret_0 (gpointer res, ARGLIST0) INTERP_ENTRY0 (NULL, res, rmethod)
+static void interp_entry_static_ret_1 (gpointer res, ARGLIST1) INTERP_ENTRY1 (NULL, res, rmethod)
+static void interp_entry_static_ret_2 (gpointer res, ARGLIST2) INTERP_ENTRY2 (NULL, res, rmethod)
+static void interp_entry_static_ret_3 (gpointer res, ARGLIST3) INTERP_ENTRY3 (NULL, res, rmethod)
+static void interp_entry_static_ret_4 (gpointer res, ARGLIST4) INTERP_ENTRY4 (NULL, res, rmethod)
+static void interp_entry_static_ret_5 (gpointer res, ARGLIST5) INTERP_ENTRY5 (NULL, res, rmethod)
+static void interp_entry_static_ret_6 (gpointer res, ARGLIST6) INTERP_ENTRY6 (NULL, res, rmethod)
+static void interp_entry_static_ret_7 (gpointer res, ARGLIST7) INTERP_ENTRY7 (NULL, res, rmethod)
+static void interp_entry_static_ret_8 (gpointer res, ARGLIST8) INTERP_ENTRY8 (NULL, res, rmethod)
+static void interp_entry_instance_0 (gpointer this_arg, ARGLIST0) INTERP_ENTRY0 (this_arg, NULL, rmethod)
+static void interp_entry_instance_1 (gpointer this_arg, ARGLIST1) INTERP_ENTRY1 (this_arg, NULL, rmethod)
+static void interp_entry_instance_2 (gpointer this_arg, ARGLIST2) INTERP_ENTRY2 (this_arg, NULL, rmethod)
+static void interp_entry_instance_3 (gpointer this_arg, ARGLIST3) INTERP_ENTRY3 (this_arg, NULL, rmethod)
+static void interp_entry_instance_4 (gpointer this_arg, ARGLIST4) INTERP_ENTRY4 (this_arg, NULL, rmethod)
+static void interp_entry_instance_5 (gpointer this_arg, ARGLIST5) INTERP_ENTRY5 (this_arg, NULL, rmethod)
+static void interp_entry_instance_6 (gpointer this_arg, ARGLIST6) INTERP_ENTRY6 (this_arg, NULL, rmethod)
+static void interp_entry_instance_7 (gpointer this_arg, ARGLIST7) INTERP_ENTRY7 (this_arg, NULL, rmethod)
+static void interp_entry_instance_8 (gpointer this_arg, ARGLIST8) INTERP_ENTRY8 (this_arg, NULL, rmethod)
+static void interp_entry_instance_ret_0 (gpointer this_arg, gpointer res, ARGLIST0) INTERP_ENTRY0 (this_arg, res, rmethod)
+static void interp_entry_instance_ret_1 (gpointer this_arg, gpointer res, ARGLIST1) INTERP_ENTRY1 (this_arg, res, rmethod)
+static void interp_entry_instance_ret_2 (gpointer this_arg, gpointer res, ARGLIST2) INTERP_ENTRY2 (this_arg, res, rmethod)
+static void interp_entry_instance_ret_3 (gpointer this_arg, gpointer res, ARGLIST3) INTERP_ENTRY3 (this_arg, res, rmethod)
+static void interp_entry_instance_ret_4 (gpointer this_arg, gpointer res, ARGLIST4) INTERP_ENTRY4 (this_arg, res, rmethod)
+static void interp_entry_instance_ret_5 (gpointer this_arg, gpointer res, ARGLIST5) INTERP_ENTRY5 (this_arg, res, rmethod)
+static void interp_entry_instance_ret_6 (gpointer this_arg, gpointer res, ARGLIST6) INTERP_ENTRY6 (this_arg, res, rmethod)
+static void interp_entry_instance_ret_7 (gpointer this_arg, gpointer res, ARGLIST7) INTERP_ENTRY6 (this_arg, res, rmethod)
+static void interp_entry_instance_ret_8 (gpointer this_arg, gpointer res, ARGLIST8) INTERP_ENTRY6 (this_arg, res, rmethod)
+
+#define INTERP_ENTRY_FUNCLIST(type) interp_entry_ ## type ## _0, interp_entry_ ## type ## _1, interp_entry_ ## type ## _2, interp_entry_ ## type ## _3, interp_entry_ ## type ## _4, interp_entry_ ## type ## _5, interp_entry_ ## type ## _6, interp_entry_ ## type ## _7, interp_entry_ ## type ## _8
+
+gpointer entry_funcs_static [MAX_INTERP_ENTRY_ARGS + 1] = { INTERP_ENTRY_FUNCLIST (static) };
+gpointer entry_funcs_static_ret [MAX_INTERP_ENTRY_ARGS + 1] = { INTERP_ENTRY_FUNCLIST (static_ret) };
+gpointer entry_funcs_instance [MAX_INTERP_ENTRY_ARGS + 1] = { INTERP_ENTRY_FUNCLIST (instance) };
+gpointer entry_funcs_instance_ret [MAX_INTERP_ENTRY_ARGS + 1] = { INTERP_ENTRY_FUNCLIST (instance_ret) };
+
+/* General version for methods with more than MAX_INTERP_ENTRY_ARGS arguments */
+static void
+interp_entry_general (gpointer this_arg, gpointer res, gpointer *args, gpointer rmethod)
+{
+ INTERP_ENTRY_BASE (rmethod, this_arg, res);
+ data.many_args = args;
+ interp_entry (&data);
+}
+/*
+ * mono_interp_create_method_pointer:
+ *
+ * Return a function pointer which can be used to call METHOD using the
+ * interpreter. Return NULL for methods which are not supported.
+ */
gpointer
mono_interp_create_method_pointer (MonoMethod *method, MonoError *error)
{
gpointer addr;
- MonoJitInfo *ji;
+ MonoMethodSignature *sig = mono_method_signature (method);
+ MonoMethod *wrapper;
+ RuntimeMethod *rmethod;
- mono_os_mutex_lock (&create_method_pointer_mutex);
- if (!method_pointer_hash) {
- // FIXME: is registering method table as GC root really necessary?
- // MONO_GC_REGISTER_ROOT_FIXED (method_pointer_hash);
- method_pointer_hash = g_hash_table_new (NULL, NULL);
- }
- addr = g_hash_table_lookup (method_pointer_hash, method);
- if (addr) {
- mono_os_mutex_unlock (&create_method_pointer_mutex);
- return addr;
+ if (method->wrapper_type && method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE)
+ return NULL;
+
+ rmethod = mono_interp_get_runtime_method (mono_domain_get (), method, error);
+ if (rmethod->jit_entry)
+ return rmethod->jit_entry;
+ wrapper = mini_get_interp_in_wrapper (sig);
+
+ gpointer jit_wrapper = mono_jit_compile_method_jit_only (wrapper, error);
+ mono_error_assert_ok (error);
+
+ //printf ("%s %s\n", mono_method_full_name (method, 1), mono_method_full_name (wrapper, 1));
+ gpointer entry_func;
+ if (sig->param_count > MAX_INTERP_ENTRY_ARGS) {
+ entry_func = interp_entry_general;
+ } else if (sig->hasthis) {
+ if (sig->ret->type == MONO_TYPE_VOID)
+ entry_func = entry_funcs_instance [sig->param_count];
+ else
+ entry_func = entry_funcs_instance_ret [sig->param_count];
+ } else {
+ if (sig->ret->type == MONO_TYPE_VOID)
+ entry_func = entry_funcs_static [sig->param_count];
+ else
+ entry_func = entry_funcs_static_ret [sig->param_count];
}
+ g_assert (entry_func);
+
+ /* This is the argument passed to the interp_in wrapper by the static rgctx trampoline */
+ MonoFtnDesc *ftndesc = g_new0 (MonoFtnDesc, 1);
+ ftndesc->addr = entry_func;
+ ftndesc->arg = rmethod;
+ mono_error_assert_ok (error);
/*
- * If it is a static P/Invoke method, we can just return the pointer
- * to the method implementation.
+ * The wrapper is called by compiled code, which doesn't pass the extra argument, so we pass it in the
+ * rgctx register using a trampoline.
*/
- if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL && ((MonoMethodPInvoke*) method)->addr) {
- ji = g_new0 (MonoJitInfo, 1);
- ji->d.method = method;
- ji->code_size = 1;
- ji->code_start = addr = ((MonoMethodPInvoke*) method)->addr;
-
- mono_jit_info_table_add (mono_get_root_domain (), ji);
- }
- else {
- g_assert (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE);
- g_assert (tramps_used < TRAMPS_USED);
-
- /* FIXME: needs locking */
- method_pointers [tramps_used] = method;
- addr = mp_tramps [tramps_used];
- tramps_used++;
- }
- g_hash_table_insert (method_pointer_hash, method, addr);
- mono_os_mutex_unlock (&create_method_pointer_mutex);
+ // FIXME: AOT
+ g_assert (!mono_aot_only);
+ addr = mono_arch_get_static_rgctx_trampoline (ftndesc, jit_wrapper);
+
+ mono_memory_barrier ();
+ rmethod->jit_entry = addr;
return addr;
}
#define MINT_IN_DEFAULT default:
#endif
+static void
+ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context);
+
static void
-ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
+ves_exec_method_with_context_with_ip (MonoInvocation *frame, ThreadContext *context, unsigned short *start_with_ip, MonoException *filter_exception)
{
MonoInvocation child_frame;
GSList *finally_ips = NULL;
}
rtm = frame->runtime_method;
- frame->args = alloca (rtm->alloca_size);
- memset (frame->args, 0, rtm->alloca_size);
-
- sp = frame->stack = (stackval *)((char *)frame->args + rtm->args_size);
- memset (sp, 0, rtm->stack_size);
+ if (!start_with_ip ) {
+ frame->args = alloca (rtm->alloca_size);
+ memset (frame->args, 0, rtm->alloca_size);
+ ip = rtm->code;
+ } else {
+ ip = start_with_ip;
+ }
+ sp = frame->stack = (stackval *) ((char *) frame->args + rtm->args_size);
vt_sp = (unsigned char *) sp + rtm->stack_size;
- memset (vt_sp, 0, rtm->vt_stack_size);
#if DEBUG_INTERP
vtalloc = vt_sp;
#endif
-
locals = (unsigned char *) vt_sp + rtm->vt_stack_size;
- memset (vt_sp, 0, rtm->locals_size);
-
child_frame.parent = frame;
- /* ready to go */
- ip = rtm->code;
+ if (filter_exception) {
+ sp->data.p = filter_exception;
+ sp++;
+ }
/*
* using while (ip < end) may result in a 15% performance drop,
child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
}
+
ves_exec_method_with_context (&child_frame, context);
context->current_frame = frame;
}
MINT_IN_BREAK;
}
+
+ MINT_IN_CASE(MINT_JIT_CALL) {
+ MonoMethodSignature *sig;
+ RuntimeMethod *rmethod = rtm->data_items [* (guint16 *)(ip + 1)];
+ MonoFtnDesc ftndesc;
+ guint8 res_buf [256];
+ MonoType *type;
+
+ //printf ("%s\n", mono_method_full_name (rmethod->method, 1));
+
+ /*
+ * Call JITted code through a gsharedvt_out wrapper. These wrappers receive every argument
+ * by ref and return a return value using an explicit return value argument.
+ */
+ if (!rmethod->jit_wrapper) {
+ MonoMethod *method = rmethod->method;
+ MonoError error;
+
+ sig = mono_method_signature (method);
+ g_assert (sig);
+
+ MonoMethod *wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
+ //printf ("J: %s %s\n", mono_method_full_name (method, 1), mono_method_full_name (wrapper, 1));
+
+ gpointer jit_wrapper = mono_jit_compile_method_jit_only (wrapper, &error);
+ mono_error_assert_ok (&error);
+
+ gpointer addr = mono_jit_compile_method_jit_only (method, &error);
+ g_assert (addr);
+ mono_error_assert_ok (&error);
+
+ rmethod->jit_addr = addr;
+ rmethod->jit_sig = sig;
+ mono_memory_barrier ();
+ rmethod->jit_wrapper = jit_wrapper;
+
+ } else {
+ sig = rmethod->jit_sig;
+ }
+
+ frame->ip = ip;
+ ip += 2;
+ sp -= sig->param_count;
+ if (sig->hasthis)
+ --sp;
+
+ ftndesc.addr = rmethod->jit_addr;
+ ftndesc.arg = NULL;
+
+ // FIXME: Optimize this
+
+ gpointer args [32];
+ int pindex = 0;
+ int stack_index = 0;
+ if (rmethod->hasthis) {
+ args [pindex ++] = sp [0].data.p;
+ stack_index ++;
+ }
+ type = rmethod->rtype;
+ if (type->type != MONO_TYPE_VOID) {
+ if (MONO_TYPE_ISSTRUCT (type))
+ args [pindex ++] = vt_sp;
+ else
+ args [pindex ++] = res_buf;
+ }
+ for (int i = 0; i < rmethod->param_count; ++i) {
+ MonoType *t = rmethod->param_types [i];
+ stackval *sval = &sp [stack_index + i];
+ if (sig->params [i]->byref) {
+ args [pindex ++] = sval->data.p;
+ } else if (MONO_TYPE_ISSTRUCT (t)) {
+ args [pindex ++] = sval->data.p;
+ } else if (MONO_TYPE_IS_REFERENCE (t)) {
+ args [pindex ++] = &sval->data.p;
+ } else {
+ switch (t->type) {
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_VALUETYPE:
+ args [pindex ++] = &sval->data.i;
+ break;
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_FNPTR:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ case MONO_TYPE_OBJECT:
+ args [pindex ++] = &sval->data.p;
+ break;
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ args [pindex ++] = &sval->data.l;
+ break;
+ default:
+ printf ("%s\n", mono_type_full_name (t));
+ g_assert_not_reached ();
+ }
+ }
+ }
+
+ switch (pindex) {
+ case 0: {
+ void (*func)(gpointer) = rmethod->jit_wrapper;
+
+ func (&ftndesc);
+ break;
+ }
+ case 1: {
+ void (*func)(gpointer, gpointer) = rmethod->jit_wrapper;
+
+ func (args [0], &ftndesc);
+ break;
+ }
+ case 2: {
+ void (*func)(gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+ func (args [0], args [1], &ftndesc);
+ break;
+ }
+ case 3: {
+ void (*func)(gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+ func (args [0], args [1], args [2], &ftndesc);
+ break;
+ }
+ case 4: {
+ void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+ func (args [0], args [1], args [2], args [3], &ftndesc);
+ break;
+ }
+ case 5: {
+ void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+ func (args [0], args [1], args [2], args [3], args [4], &ftndesc);
+ break;
+ }
+ case 6: {
+ void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+ func (args [0], args [1], args [2], args [3], args [4], args [5], &ftndesc);
+ break;
+ }
+ case 7: {
+ void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+ func (args [0], args [1], args [2], args [3], args [4], args [5], args [6], &ftndesc);
+ break;
+ }
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ MonoType *rtype = rmethod->rtype;
+ switch (rtype->type) {
+ case MONO_TYPE_VOID:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ sp->data.p = *(gpointer*)res_buf;
+ break;
+ case MONO_TYPE_I1:
+ sp->data.i = *(gint8*)res_buf;
+ break;
+ case MONO_TYPE_U1:
+ sp->data.i = *(guint8*)res_buf;
+ break;
+ case MONO_TYPE_I2:
+ sp->data.i = *(gint16*)res_buf;
+ break;
+ case MONO_TYPE_U2:
+ sp->data.i = *(guint16*)res_buf;
+ break;
+ case MONO_TYPE_I4:
+ sp->data.i = *(gint32*)res_buf;
+ break;
+ case MONO_TYPE_U4:
+ sp->data.i = *(guint32*)res_buf;
+ break;
+ case MONO_TYPE_VALUETYPE:
+ /* The result was written to vt_sp */
+ sp->data.p = vt_sp;
+ break;
+ case MONO_TYPE_GENERICINST:
+ if (MONO_TYPE_IS_REFERENCE (rtype)) {
+ sp->data.p = *(gpointer*)res_buf;
+ } else {
+ /* The result was written to vt_sp */
+ sp->data.p = vt_sp;
+ }
+ break;
+ default:
+ printf ("%s\n", mono_type_full_name (rtype));
+ g_assert_not_reached ();
+ break;
+ }
+ if (rtype->type != MONO_TYPE_VOID)
+ sp++;
+ MINT_IN_BREAK;
+ }
+
MINT_IN_CASE(MINT_CALLVIRT) {
stackval *endsp = sp;
MonoObject *this_arg;
BINOP_CAST(l, -, guint64);
MINT_IN_BREAK;
MINT_IN_CASE(MINT_ENDFINALLY)
+ while (sp > frame->stack) {
+ --sp;
+ }
if (finally_ips) {
ip = finally_ips->data;
finally_ips = g_slist_remove (finally_ips, ip);
++ip;
MINT_IN_BREAK;
}
-#if 0
- MINT_IN_CASE(MINT_ENDFILTER) ves_abort(); MINT_IN_BREAK;
-#endif
+ MINT_IN_CASE(MINT_ENDFILTER)
+ /* top of stack is result of filter */
+ frame->retval = &sp [-1];
+ goto exit_frame;
MINT_IN_CASE(MINT_INITOBJ)
--sp;
memset (sp->data.vt, 0, READ32(ip + 1));
inv->ex_handler = NULL; /* clear this in case we are trhowing an exception while handling one - this one wins */
for (i = 0; i < inv->runtime_method->num_clauses; ++i) {
clause = &inv->runtime_method->clauses [i];
- if (clause->flags <= 1 && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
- if (!clause->flags) {
- MonoObject *isinst_obj = mono_object_isinst_checked ((MonoObject*)frame->ex, clause->data.catch_class, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- if (isinst_obj) {
- /*
- * OK, we found an handler, now we need to execute the finally
- * and fault blocks before branching to the handler code.
- */
- inv->ex_handler = clause;
#if DEBUG_INTERP
- if (tracing)
- g_print ("* Found handler at '%s'\n", method->name);
+ g_print ("* clause [%d]: %p\n", i, clause);
#endif
- goto handle_finally;
- }
- } else {
- g_error ("FIXME: handle filter clause");
+ if (!MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
+ continue;
+ }
+ if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
+#if DEBUG_INTERP
+ if (tracing)
+ g_print ("* Filter found at '%s'\n", method->name);
+#endif
+ MonoInvocation dup_frame;
+ stackval retval;
+ memcpy (&dup_frame, inv, sizeof (MonoInvocation));
+ dup_frame.retval = &retval;
+ ves_exec_method_with_context_with_ip (&dup_frame, context, inv->runtime_method->code + clause->data.filter_offset, frame->ex);
+ if (dup_frame.retval->data.i) {
+#if DEBUG_INTERP
+ if (tracing)
+ g_print ("* Matched Filter at '%s'\n", method->name);
+#endif
+ inv->ex_handler = clause;
+ goto handle_finally;
+ }
+ } else if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE) {
+ MonoObject *isinst_obj = mono_object_isinst_checked ((MonoObject*)frame->ex, clause->data.catch_class, &error);
+ mono_error_cleanup (&error); /* FIXME: don't swallow the error */
+ if (isinst_obj) {
+ /*
+ * OK, we found an handler, now we need to execute the finally
+ * and fault blocks before branching to the handler code.
+ */
+#if DEBUG_INTERP
+ if (tracing)
+ g_print ("* Found handler at '%s'\n", method->name);
+#endif
+ inv->ex_handler = clause;
+ goto handle_finally;
}
}
}
DEBUG_LEAVE ();
}
+static void
+ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
+{
+ ves_exec_method_with_context_with_ip (frame, context, NULL, NULL);
+}
+
void
ves_exec_method (MonoInvocation *frame)
{
return res;
}
+void
+mono_interp_parse_options (const char *options)
+{
+ char **args, **ptr;
+
+ args = g_strsplit (options, ",", -1);
+ for (ptr = args; ptr && *ptr; ptr ++) {
+ char *arg = *ptr;
+
+ if (strncmp (arg, "jit=", 4) == 0)
+ jit_classes = g_slist_prepend (jit_classes, arg + 4);
+ }
+}
+
void
mono_interp_init ()
{
mono_native_tls_alloc (&thread_context_id, NULL);
- mono_native_tls_set_value (thread_context_id, NULL);
- mono_os_mutex_init_recursive (&create_method_pointer_mutex);
+ mono_native_tls_set_value (thread_context_id, NULL);
mono_interp_transform_init ();
}
*total += failed + cfailed;
*total_run += run;
}
+
static int
interp_regression (MonoImage *image, int verbose, int *total_run)
{
gpointer
mono_interp_create_trampoline (MonoDomain *domain, MonoMethod *method, MonoError *error);
+void
+mono_interp_parse_options (const char *options);
+
void
interp_walk_stack_with_ctx (MonoInternalStackWalk func, MonoContext *ctx, MonoUnwindOptions options, void *user_data);
#endif /* __MONO_MINI_INTERPRETER_H__ */
OPDEF(MINT_CALLRUN, "callrun", 1, MintOpNoArgs)
+OPDEF(MINT_ENDFILTER, "endfilter", 1, MintOpNoArgs)
+
OPDEF(MINT_NEWOBJ, "newobj", 2, MintOpMethodToken)
OPDEF(MINT_INITOBJ, "initobj", 3, MintOpInt)
OPDEF(MINT_CASTCLASS, "castclass", 2, MintOpClassToken)
OPDEF(MINT_MONO_RETOBJ, "mono_retobj", 1, MintOpNoArgs)
OPDEF(MINT_MONO_FREE, "mono_free", 1, MintOpNoArgs)
-
+// FIXME: MintOp
+OPDEF(MINT_JIT_CALL, "mono_jit_call", 2, MintOpNoArgs)
return index;
}
+static gboolean
+jit_call_supported (MonoMethod *method, MonoMethodSignature *sig)
+{
+ GSList *l;
+
+ if (sig->param_count > 6)
+ return FALSE;
+ if (sig->pinvoke)
+ return FALSE;
+ if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
+ return FALSE;
+ if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
+ return FALSE;
+ if (method->is_inflated)
+ return FALSE;
+ if (method->string_ctor)
+ return FALSE;
+
+ for (l = jit_classes; l; l = l->next) {
+ char *class_name = l->data;
+ // FIXME: Namespaces
+ if (!strcmp (method->klass->name, class_name))
+ return TRUE;
+ }
+
+ //return TRUE;
+ return FALSE;
+}
+
static void
interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target_method, MonoDomain *domain, MonoGenericContext *generic_context, unsigned char *is_bb_start, int body_start_offset, MonoClass *constrained_class, gboolean readonly)
{
ADD_CODE (td, get_data_item_index (td, target_method->klass));
ADD_CODE (td, 1 + target_method->klass->rank);
}
+ } else if (!calli && !virtual && jit_call_supported (target_method, csignature)) {
+ ADD_CODE(td, MINT_JIT_CALL);
+ ADD_CODE(td, get_data_item_index (td, (void *)mono_interp_get_runtime_method (domain, target_method, &error)));
+ mono_error_assert_ok (&error);
} else {
if (calli)
ADD_CODE(td, native ? MINT_CALLI_NAT : MINT_CALLI);
ADD_CODE(td, is_void ? MINT_VCALLVIRT : MINT_CALLVIRT);
else
ADD_CODE(td, is_void ? MINT_VCALL : MINT_CALL);
-
+
if (calli) {
ADD_CODE(td, get_data_item_index (td, (void *)csignature));
} else {
td.stack_state [c->handler_offset] = g_malloc0(sizeof(StackInfo));
td.stack_state [c->handler_offset][0].type = STACK_TYPE_O;
td.stack_state [c->handler_offset][0].klass = NULL; /*FIX*/
+
+ if (c->flags & MONO_EXCEPTION_CLAUSE_FILTER) {
+ td.stack_height [c->data.filter_offset] = 0;
+ td.vt_stack_size [c->data.filter_offset] = 0;
+ td.is_bb_start [c->data.filter_offset] = 1;
+
+ td.stack_height [c->data.filter_offset] = 1;
+ td.stack_state [c->data.filter_offset] = g_malloc0(sizeof(StackInfo));
+ td.stack_state [c->data.filter_offset][0].type = STACK_TYPE_O;
+ td.stack_state [c->data.filter_offset][0].klass = NULL; /*FIX*/
+ }
}
td.ip = header->code;
++td.ip;
break;
case CEE_ENDFINALLY:
+ td.sp = td.stack;
SIMPLE_OP (td, MINT_ENDFINALLY);
generating_code = 0;
break;
break;
#if 0
case CEE_UNUSED57: ves_abort(); break;
- case CEE_ENDFILTER: ves_abort(); break;
#endif
+ case CEE_ENDFILTER:
+ ADD_CODE (&td, MINT_ENDFILTER);
+ ++td.ip;
+ break;
case CEE_UNALIGNED_:
++td.ip;
/* FIX: should do something? */;
CHECK_STACK(&td, 3);
ADD_CODE(&td, MINT_INITBLK);
td.sp -= 3;
+ td.ip += 1;
break;
#if 0
case CEE_NO_:
end_off = c->handler_offset + c->handler_len;
c->handler_offset = td.in_offsets [c->handler_offset];
c->handler_len = td.in_offsets [end_off] - c->handler_offset;
+ if (c->flags & MONO_EXCEPTION_CLAUSE_FILTER)
+ c->data.filter_offset = td.in_offsets [c->data.filter_offset];
}
rtm->vt_stack_size = td.max_vt_sp;
rtm->alloca_size = rtm->locals_size + rtm->args_size + rtm->vt_stack_size + rtm->stack_size;
ins->inst_false_bb = NULL; \
mono_link_bblock ((cfg), (cfg)->cbb, (truebb)); \
MONO_ADD_INS ((cfg)->cbb, ins); \
- if (g_getenv ("COUNT2") && ccount == atoi (g_getenv ("COUNT2")) - 1) { printf ("HIT: %d\n", cfg->cbb->block_num); } \
- if (g_getenv ("COUNT2") && ccount < atoi (g_getenv ("COUNT2"))) { \
+ char *count2 = g_getenv ("COUNT2"); \
+ if (count2 && ccount == atoi (count2) - 1) { printf ("HIT: %d\n", cfg->cbb->block_num); } \
+ if (count2 && ccount < atoi (count2)) { \
cfg->cbb->extended = TRUE; \
} else { NEW_BBLOCK ((cfg), falsebb); ins->inst_false_bb = (falsebb); mono_link_bblock ((cfg), (cfg)->cbb, (falsebb)); MONO_START_BB ((cfg), falsebb); } \
+ if (count2) g_free (count2); \
} \
} while (0)
#else
static guint32 disabled = -1;
if (disabled == -1)
- disabled = g_getenv ("DISABLED") != NULL;
+ disabled = g_hasenv ("DISABLED");
if (disabled)
return;
force_pass_linking (void)
{
// Make sure the rest is linked in, but never executed
- if (g_getenv ("FOO") != (char*)-1)
+ char *foo = g_getenv ("FOO");
+ gboolean ret = (foo != (char*)-1);
+ g_free (foo);
+
+ if (ret)
return;
// This is a subset of the passes in LinkAllPasses.h
return cfg->got_var;
}
-static MonoInst *
-mono_get_vtable_var (MonoCompile *cfg)
+static void
+mono_create_rgctx_var (MonoCompile *cfg)
{
- g_assert (cfg->gshared);
-
if (!cfg->rgctx_var) {
cfg->rgctx_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
/* force the var to be stack allocated */
cfg->rgctx_var->flags |= MONO_INST_VOLATILE;
}
+}
+
+static MonoInst *
+mono_get_vtable_var (MonoCompile *cfg)
+{
+ g_assert (cfg->gshared);
+
+ mono_create_rgctx_var (cfg);
return cfg->rgctx_var;
}
wbarrier->sreg1 = ptr->dreg;
wbarrier->sreg2 = value->dreg;
MONO_ADD_INS (cfg->cbb, wbarrier);
- } else if (card_table && !cfg->compile_aot && !mono_gc_card_table_nursery_check ()) {
+ } else if (card_table) {
int offset_reg = alloc_preg (cfg);
int card_reg;
MonoInst *ins;
+ /*
+ * We emit a fast light weight write barrier. This always marks cards as in the concurrent
+ * collector case, so, for the serial collector, it might slightly slow down nursery
+ * collections. We also expect that the host system and the target system have the same card
+ * table configuration, which is the case if they have the same pointer size.
+ */
+
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_UN_IMM, offset_reg, ptr->dreg, card_table_shift_bits);
if (card_table_mask)
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_PAND_IMM, offset_reg, offset_reg, card_table_mask);
mrgctx_loc = mono_get_vtable_var (cfg);
EMIT_NEW_TEMPLOAD (cfg, mrgctx_var, mrgctx_loc->inst_c0);
+ return mrgctx_var;
+ } else if (MONO_CLASS_IS_INTERFACE (cfg->method->klass)) {
+ MonoInst *mrgctx_loc, *mrgctx_var;
+
+ /* Default interface methods need an mrgctx since the vtabke at runtime points at an implementing class */
+ mrgctx_loc = mono_get_vtable_var (cfg);
+ EMIT_NEW_TEMPLOAD (cfg, mrgctx_var, mrgctx_loc->inst_c0);
+
+ g_assert (mono_method_needs_static_rgctx_invoke (cfg->method, TRUE));
+
return mrgctx_var;
} else if (method->flags & METHOD_ATTRIBUTE_STATIC || method->klass->valuetype) {
MonoInst *vtable_loc, *vtable_var;
/* also consider num_locals? */
/* Do the size check early to avoid creating vtables */
if (!inline_limit_inited) {
- if (g_getenv ("MONO_INLINELIMIT"))
- inline_limit = atoi (g_getenv ("MONO_INLINELIMIT"));
- else
+ char *inlinelimit;
+ if ((inlinelimit = g_getenv ("MONO_INLINELIMIT"))) {
+ inline_limit = atoi (inlinelimit);
+ g_free (inlinelimit);
+ } else
inline_limit = INLINE_LENGTH_LIMIT;
inline_limit_inited = TRUE;
}
#if SIZEOF_REGISTER == 8
/* The array reg is 64 bits but the index reg is only 32 */
if (COMPILE_LLVM (cfg)) {
- /* Not needed */
+ /*
+ * abcrem can't handle the OP_SEXT_I4, so add this after abcrem,
+ * during OP_BOUNDS_CHECK decomposition, and in the implementation
+ * of OP_X86_LEA for llvm.
+ */
index2_reg = index_reg;
} else {
index2_reg = alloc_preg (cfg);
ins->type = STACK_I4;
MONO_ADD_INS (cfg->cbb, ins);
+ ip += 2;
+ *sp++ = ins;
+ break;
+ case CEE_MONO_GET_RGCTX_ARG:
+ CHECK_OPSIZE (2);
+ CHECK_STACK_OVF (1);
+
+ mono_create_rgctx_var (cfg);
+
+ MONO_INST_NEW (cfg, ins, OP_MOVE);
+ ins->dreg = alloc_dreg (cfg, STACK_PTR);
+ ins->sreg1 = cfg->rgctx_var->dreg;
+ ins->type = STACK_PTR;
+ MONO_ADD_INS (cfg->cbb, ins);
+
ip += 2;
*sp++ = ins;
break;
if (soft && !strncmp (soft, "1", 1))
arm_fpu = MONO_ARM_FPU_NONE;
+ g_free (soft);
#endif
#endif
thumb_supported = strstr (cpu_arch, "thumb") != NULL;
thumb2_supported = strstr (cpu_arch, "thumb2") != NULL;
+ g_free (cpu_arch);
}
}
#endif
#ifndef USED_CROSS_COMPILER_OFFSETS
- if (g_getenv ("DUMP_CROSS_OFFSETS"))
+ if (g_hasenv ("DUMP_CROSS_OFFSETS"))
mono_dump_jit_offsets ();
#endif
* Debugging aid to control the number of frames scanned precisely
*/
if (!precise_frame_limit_inited) {
- if (g_getenv ("MONO_PRECISE_COUNT"))
- precise_frame_limit = atoi (g_getenv ("MONO_PRECISE_COUNT"));
+ char *mono_precise_count = g_getenv ("MONO_PRECISE_COUNT");
+ if (mono_precise_count) {
+ precise_frame_limit = atoi (mono_precise_count);
+ g_free (mono_precise_count);
+ }
precise_frame_limit_inited = TRUE;
}
static int precise_count;
precise_count ++;
- if (g_getenv ("MONO_GCMAP_COUNT")) {
- if (precise_count == atoi (g_getenv ("MONO_GCMAP_COUNT")))
+ char *mono_gcmap_count = g_getenv ("MONO_GCMAP_COUNT");
+ if (mono_gcmap_count) {
+ int count = atoi (mono_gcmap_count);
+ g_free (mono_gcmap_count);
+ if (precise_count == count)
printf ("LAST: %s\n", mono_method_full_name (cfg->method, TRUE));
- if (precise_count > atoi (g_getenv ("MONO_GCMAP_COUNT")))
+ if (precise_count > count)
return;
}
}
exit (1);
}
g_strfreev (opts);
+ g_free (env);
}
void
sig = mini_get_underlying_signature (sig);
// FIXME: Normal cache
+ gshared_lock ();
if (!cache)
cache = g_hash_table_new_full ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal, NULL, NULL);
- gshared_lock ();
res = g_hash_table_lookup (cache, sig);
gshared_unlock ();
if (res) {
sig = mini_get_underlying_signature (sig);
// FIXME: Normal cache
+ gshared_lock ();
if (!cache)
cache = g_hash_table_new_full ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal, NULL, NULL);
- gshared_lock ();
res = g_hash_table_lookup (cache, sig);
gshared_unlock ();
if (res) {
return res;
}
+/*
+ * mini_get_interp_in_wrapper:
+ *
+ * Return a wrapper which can be used to transition from compiled code to the interpreter.
+ * The wrapper has the same signature as SIG. It is very similar to a gsharedvt_in wrapper,
+ * except the 'extra_arg' is passed in the rgctx reg, so this wrapper needs to be
+ * called through a static rgctx trampoline.
+ * FIXME: Move this elsewhere.
+ */
+MonoMethod*
+mini_get_interp_in_wrapper (MonoMethodSignature *sig)
+{
+ MonoMethodBuilder *mb;
+ MonoMethod *res, *cached;
+ WrapperInfo *info;
+ MonoMethodSignature *csig, *entry_sig;
+ int i, pindex, retval_var = 0;
+ static GHashTable *cache;
+ const char *name;
+ gboolean generic = FALSE;
+
+ sig = mini_get_underlying_signature (sig);
+
+ gshared_lock ();
+ if (!cache)
+ cache = g_hash_table_new_full ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal, NULL, NULL);
+ res = g_hash_table_lookup (cache, sig);
+ gshared_unlock ();
+ if (res) {
+ g_free (sig);
+ return res;
+ }
+
+ if (sig->param_count > 8)
+ /* Call the generic interpreter entry point, the specialized ones only handle a limited number of arguments */
+ generic = TRUE;
+
+ /* Create the signature for the wrapper */
+ csig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + (sig->param_count * sizeof (MonoType*)));
+ memcpy (csig, sig, mono_metadata_signature_size (sig));
+
+ /* Create the signature for the callee callconv */
+ if (generic) {
+ /*
+ * The called function has the following signature:
+ * interp_entry_general (gpointer this_arg, gpointer res, gpointer *args, gpointer rmethod)
+ */
+ entry_sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + (4 * sizeof (MonoType*)));
+ entry_sig->ret = &mono_defaults.void_class->byval_arg;
+ entry_sig->param_count = 4;
+ entry_sig->params [0] = &mono_defaults.int_class->byval_arg;
+ entry_sig->params [1] = &mono_defaults.int_class->byval_arg;
+ entry_sig->params [2] = &mono_defaults.int_class->byval_arg;
+ entry_sig->params [3] = &mono_defaults.int_class->byval_arg;
+ name = "interp_in_generic";
+ generic = TRUE;
+ } else {
+ /*
+ * The called function has the following signature:
+ * void entry(<optional this ptr>, <optional return ptr>, <arguments>, <extra arg>)
+ */
+ entry_sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + ((sig->param_count + 2) * sizeof (MonoType*)));
+ memcpy (entry_sig, sig, mono_metadata_signature_size (sig));
+ pindex = 0;
+ /* The return value is returned using an explicit vret argument */
+ if (sig->ret->type != MONO_TYPE_VOID) {
+ entry_sig->params [pindex ++] = &mono_defaults.int_class->byval_arg;
+ entry_sig->ret = &mono_defaults.void_class->byval_arg;
+ }
+ for (i = 0; i < sig->param_count; i++) {
+ entry_sig->params [pindex] = sig->params [i];
+ if (!sig->params [i]->byref) {
+ entry_sig->params [pindex] = mono_metadata_type_dup (NULL, entry_sig->params [pindex]);
+ entry_sig->params [pindex]->byref = 1;
+ }
+ pindex ++;
+ }
+ /* Extra arg */
+ entry_sig->params [pindex ++] = &mono_defaults.int_class->byval_arg;
+ entry_sig->param_count = pindex;
+ name = sig->hasthis ? "interp_in" : "interp_in_static";
+ }
+
+ mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_UNKNOWN);
+
+ // FIXME: save lmf
+
+#ifndef DISABLE_JIT
+ if (sig->ret->type != MONO_TYPE_VOID)
+ retval_var = mono_mb_add_local (mb, sig->ret);
+
+ /* Make the call */
+ if (generic) {
+ /* Collect arguments */
+ int args_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+
+ mono_mb_emit_icon (mb, sizeof (gpointer) * sig->param_count);
+ mono_mb_emit_byte (mb, CEE_PREFIX1);
+ mono_mb_emit_byte (mb, CEE_LOCALLOC);
+ mono_mb_emit_stloc (mb, args_var);
+
+ for (i = 0; i < sig->param_count; i++) {
+ mono_mb_emit_ldloc (mb, args_var);
+ mono_mb_emit_icon (mb, sizeof (gpointer) * i);
+ mono_mb_emit_byte (mb, CEE_ADD);
+ if (sig->params [i]->byref)
+ mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
+ else
+ mono_mb_emit_ldarg_addr (mb, i + (sig->hasthis == TRUE));
+ mono_mb_emit_byte (mb, CEE_STIND_I);
+ }
+
+ if (sig->hasthis)
+ mono_mb_emit_ldarg (mb, 0);
+ else
+ mono_mb_emit_byte (mb, CEE_LDNULL);
+ if (sig->ret->type != MONO_TYPE_VOID)
+ mono_mb_emit_ldloc_addr (mb, retval_var);
+ else
+ mono_mb_emit_byte (mb, CEE_LDNULL);
+ mono_mb_emit_ldloc (mb, args_var);
+ } else {
+ if (sig->hasthis)
+ mono_mb_emit_ldarg (mb, 0);
+ if (sig->ret->type != MONO_TYPE_VOID)
+ mono_mb_emit_ldloc_addr (mb, retval_var);
+ for (i = 0; i < sig->param_count; i++) {
+ if (sig->params [i]->byref)
+ mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
+ else
+ mono_mb_emit_ldarg_addr (mb, i + (sig->hasthis == TRUE));
+ }
+ }
+ /* Extra arg */
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_GET_RGCTX_ARG);
+ mono_mb_emit_icon (mb, sizeof (gpointer));
+ mono_mb_emit_byte (mb, CEE_ADD);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ /* Method to call */
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_GET_RGCTX_ARG);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_calli (mb, entry_sig);
+ if (sig->ret->type != MONO_TYPE_VOID)
+ mono_mb_emit_ldloc (mb, retval_var);
+ mono_mb_emit_byte (mb, CEE_RET);
+#endif
+
+ info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_INTERP_IN);
+ info->d.interp_in.sig = sig;
+
+ res = mono_mb_create (mb, csig, sig->param_count + 16, info);
+
+ gshared_lock ();
+ cached = g_hash_table_lookup (cache, sig);
+ if (cached)
+ res = cached;
+ else
+ g_hash_table_insert (cache, sig, res);
+ gshared_unlock ();
+ return res;
+}
+
MonoMethodSignature*
mini_get_gsharedvt_out_sig_wrapper_signature (gboolean has_this, gboolean has_ret, int param_count)
{
return TRUE;
return ((method->flags & METHOD_ATTRIBUTE_STATIC) ||
- method->klass->valuetype) &&
+ method->klass->valuetype ||
+ MONO_CLASS_IS_INTERFACE (method->klass)) &&
(mono_class_is_ginst (method->klass) || mono_class_is_gtd (method->klass));
}
case OP_X86_LEA: {
LLVMValueRef v1, v2;
+ rhs = LLVMBuildSExt (builder, convert (ctx, rhs, LLVMInt32Type ()), LLVMInt64Type (), "");
+
v1 = LLVMBuildMul (builder, convert (ctx, rhs, IntPtrType ()), LLVMConstInt (IntPtrType (), (1 << ins->backend.shift_amount), FALSE), "");
v2 = LLVMBuildAdd (builder, convert (ctx, lhs, IntPtrType ()), v1, "");
values [ins->dreg] = LLVMBuildAdd (builder, v2, LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), dname);
static int count = 0;
count ++;
- if (g_getenv ("LLVM_COUNT")) {
- if (count == atoi (g_getenv ("LLVM_COUNT"))) {
+ char *llvm_count_str = g_getenv ("LLVM_COUNT");
+ if (llvm_count_str) {
+ int lcount = atoi (llvm_count_str);
+ g_free (llvm_count_str);
+ if (count == lcount) {
printf ("LAST: %s\n", mono_method_full_name (cfg->method, TRUE));
fflush (stdout);
last = TRUE;
}
- if (count > atoi (g_getenv ("LLVM_COUNT"))) {
+ if (count > lcount) {
set_failure (ctx, "count");
return;
}
#ifdef DEBUG_ELFABIV2
#define DEBUG_ELFABIV2_printf(a, ...) \
-{if (getenv("DEBUG_ELFABIV2")) { printf(a, ##__VA_ARGS__); fflush(stdout); } }
+{char *debug_env; if (debug_env = getenv("DEBUG_ELFABIV2")) { printf(a, ##__VA_ARGS__); fflush(stdout); g_free (debug_env); } }
#define DEBUG_ELFABIV2_mono_print_ins(a) \
-{if (getenv("DEBUG_ELFABIV2")) { if (!a) {printf("null\n");} else {mono_print_ins(a);} fflush(stdout); } }
+{char *debug_env; if (debug_env = getenv("DEBUG_ELFABIV2")) { if (!a) {printf("null\n");} else {mono_print_ins(a);} fflush(stdout); g_free (debug_env); } }
extern char* mono_type_full_name (MonoType *type);
#define DEBUG_ELFABIV2_mono_print_type(a) \
-{if (getenv("DEBUG_ELFABIV2")) { printf("%s, size: %d\n", mono_type_get_name(a), mini_type_stack_size (a, 0)); fflush(stdout); } }
+{char *debug_env; if (debug_env = getenv("DEBUG_ELFABIV2")) { printf("%s, size: %d\n", mono_type_get_name(a), mini_type_stack_size (a, 0)); fflush(stdout); g_free (debug_env); } }
#define DEBUG_ELFABIV2_mono_print_class(a) \
-{if (getenv("DEBUG_ELFABIV2")) { printf("%s\n", mono_type_get_name(&a->byval_arg)); fflush(stdout); } }
+{char *debug_env; if (debug_env = getenv("DEBUG_ELFABIV2")) { printf("%s\n", mono_type_get_name(&a->byval_arg)); fflush(stdout); g_free (debug_env); } }
#else
{
static int count = 0;
static gboolean inited;
- static const char *value;
+ static char *value;
count ++;
if (!value)
return TRUE;
- if (count == atoi (value))
+ int int_val = atoi (value);
+ g_free (value);
+
+ if (count == int_val)
break_count ();
- if (count > atoi (value))
+ if (count > int_val)
return FALSE;
return TRUE;
}
static gpointer
-mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoError *error)
+mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, gboolean jit_only, MonoError *error)
{
MonoDomain *target_domain, *domain = mono_domain_get ();
MonoJitInfo *info;
error_init (error);
#ifdef ENABLE_INTERPRETER
- if (mono_use_interpreter)
- return mono_interp_create_method_pointer (method, error);
+ if (mono_use_interpreter && !jit_only) {
+ code = mono_interp_create_method_pointer (method, error);
+ if (code)
+ return code;
+ }
#endif
if (mono_llvm_only)
{
gpointer code;
- code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), error);
+ code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), FALSE, error);
+ return code;
+}
+
+/*
+ * mono_jit_compile_method_jit_only:
+ *
+ * Compile METHOD using the JIT/AOT, even in interpreted mode.
+ */
+gpointer
+mono_jit_compile_method_jit_only (MonoMethod *method, MonoError *error)
+{
+ gpointer code;
+
+ code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), TRUE, error);
return code;
}
}
if (callee) {
- compiled_method = mono_jit_compile_method_with_opt (callee, mono_get_optimizations_for_method (callee, default_opt), error);
+ compiled_method = mono_jit_compile_method (callee, error);
if (!compiled_method) {
g_assert (!mono_error_ok (error));
return NULL;
static void
mini_parse_debug_options (void)
{
- const char *options = g_getenv ("MONO_DEBUG");
+ char *options = g_getenv ("MONO_DEBUG");
gchar **args, **ptr;
if (!options)
return;
args = g_strsplit (options, ",", -1);
+ g_free (options);
for (ptr = args; ptr && *ptr; ptr++) {
const char *arg = *ptr;
info->seq_points = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, mono_seq_point_info_free);
info->arch_seq_points = g_hash_table_new (mono_aligned_addr_hash, NULL);
info->jump_target_hash = g_hash_table_new (NULL, NULL);
+ mono_jit_code_hash_init (&info->interp_code_hash);
domain->runtime_info = info;
}
mono_threads_runtime_init (&ticallbacks);
- if (g_getenv ("MONO_DEBUG") != NULL)
+ if (g_hasenv ("MONO_DEBUG")) {
mini_parse_debug_options ();
+ }
mono_code_manager_init ();
mono_unwind_init ();
- if (mini_get_debug_options ()->lldb || g_getenv ("MONO_LLDB")) {
+ if (mini_get_debug_options ()->lldb || g_hasenv ("MONO_LLDB")) {
mono_lldb_init ("");
mono_dont_free_domains = TRUE;
}
#ifdef XDEBUG_ENABLED
- if (g_getenv ("MONO_XDEBUG")) {
- const char *xdebug_opts = g_getenv ("MONO_XDEBUG");
- mono_xdebug_init (xdebug_opts);
+ char *mono_xdebug = g_getenv ("MONO_XDEBUG");
+ if (mono_xdebug) {
+ mono_xdebug_init (mono_xdebug);
+ g_free (mono_xdebug);
/* So methods for multiple domains don't have the same address */
mono_dont_free_domains = TRUE;
mono_using_xdebug = TRUE;
void
mono_arch_finish_init (void)
{
- if (!g_getenv ("MONO_NO_TLS")) {
+ char *mono_no_tls = g_getenv ("MONO_NO_TLS");
+ if (!mono_no_tls) {
#ifndef TARGET_WIN32
#if MONO_XEN_OPT
optimize_for_xen = access ("/proc/xen", F_OK) == 0;
#endif
#endif
- }
+ } else {
+ g_free (mono_no_tls);
+ }
}
void
gboolean llvm = (flags & JIT_FLAG_LLVM) ? 1 : 0;
#endif
static gboolean verbose_method_inited;
- static const char *verbose_method_name;
+ static char *verbose_method_name;
InterlockedIncrement (&mono_jit_stats.methods_compiled);
if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
gpointer llvm_module;
/* Maps MonoMethod -> GSlist of addresses */
GHashTable *llvm_jit_callees;
+ /* Maps MonoMethod -> RuntimeMethod */
+ MonoInternalHashTable interp_code_hash;
} MonoJitDomainInfo;
typedef struct {
gpointer mono_jit_find_compiled_method_with_jit_info (MonoDomain *domain, MonoMethod *method, MonoJitInfo **ji);
gpointer mono_jit_find_compiled_method (MonoDomain *domain, MonoMethod *method);
gpointer mono_jit_compile_method (MonoMethod *method, MonoError *error);
+gpointer mono_jit_compile_method_jit_only (MonoMethod *method, MonoError *error);
gpointer mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, int opt, MonoError *error);
MonoLMF * mono_get_lmf (void);
MonoLMF** mono_get_lmf_addr (void);
MonoMethod* mini_get_gsharedvt_out_sig_wrapper (MonoMethodSignature *sig);
MonoMethodSignature* mini_get_gsharedvt_out_sig_wrapper_signature (gboolean has_this, gboolean has_ret, int param_count);
gboolean mini_gsharedvt_runtime_invoke_supported (MonoMethodSignature *sig);
+MonoMethod* mini_get_interp_in_wrapper (MonoMethodSignature *sig);
/* SIMD support */
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+/*
+ * Regression tests for the mixed-mode execution.
+ * Run with --interp=jit=JitClass
+ */
+
+struct AStruct {
+ public int i;
+}
+
+struct GStruct<T> {
+ public int i;
+}
+
+class InterpClass
+{
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static void entry_void_0 () {
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static int entry_int_int (int i) {
+ return i + 1;
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public int entry_int_this_int (int i) {
+ return i + 1;
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static string entry_string_string (string s1, string s2) {
+ return s1 + s2;
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static AStruct entry_struct_struct (AStruct l) {
+ return l;
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static List<string> entry_ginst_ginst (List<string> l) {
+ return l;
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static GStruct<string> entry_ginst_ginst_vtype (GStruct<string> l) {
+ return l;
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static void entry_void_byref_int (ref int i) {
+ i = i + 1;
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static int entry_8_int_args (int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8) {
+ return i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8;
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static int entry_9_int_args (int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9) {
+ return i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9;
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static IntPtr entry_intptr_intptr (IntPtr i) {
+ return i;
+ }
+
+}
+
+/* The methods in this class will always be JITted */
+class JitClass
+{
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static int entry () {
+ InterpClass.entry_void_0 ();
+ InterpClass.entry_void_0 ();
+ int res = InterpClass.entry_int_int (1);
+ if (res != 2)
+ return 1;
+ var c = new InterpClass ();
+ res = c.entry_int_this_int (1);
+ if (res != 2)
+ return 2;
+ var s = InterpClass.entry_string_string ("A", "B");
+ if (s != "AB")
+ return 3;
+ var astruct = new AStruct () { i = 1 };
+ var astruct2 = InterpClass.entry_struct_struct (astruct);
+ if (astruct2.i != 1)
+ return 4;
+ var l = new List<string> ();
+ var l2 = InterpClass.entry_ginst_ginst (l);
+ if (l != l2)
+ return 5;
+ var gstruct = new GStruct<string> () { i = 1 };
+ var gstruct2 = InterpClass.entry_ginst_ginst_vtype (gstruct);
+ if (gstruct2.i != 1)
+ return 6;
+ int val = 1;
+ InterpClass.entry_void_byref_int (ref val);
+ if (val != 2)
+ return 7;
+ res = InterpClass.entry_8_int_args (1, 2, 3, 4, 5, 6, 7, 8);
+ if (res != 36)
+ return 8;
+ res = InterpClass.entry_9_int_args (1, 2, 3, 4, 5, 6, 7, 8, 9);
+ if (res != 45)
+ return 9;
+ var ptr = new IntPtr (32);
+ var ptr2 = InterpClass.entry_intptr_intptr (ptr);
+ if (ptr != ptr2)
+ return 10;
+ return 0;
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static AStruct exit_vtype (AStruct s) {
+ return s;
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static List<string> exit_ginst (List<string> l) {
+ return l;
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static GStruct<string> exit_ginst_vtype (GStruct<string> l) {
+ return l;
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static void exit_byref (ref int i) {
+ i += 1;
+ }
+}
+
+#if __MOBILE__
+class MixedTests
+#else
+class Tests
+#endif
+{
+
+#if !__MOBILE__
+ public static int Main (string[] args) {
+ return TestDriver.RunTests (typeof (Tests), args);
+ }
+#endif
+
+ public static int test_0_entry () {
+ // This does an interp->jit transition
+ return JitClass.entry ();
+ }
+
+ public static int test_0_exit () {
+ var astruct = new AStruct () { i = 1};
+ var astruct2 = JitClass.exit_vtype (astruct);
+ if (astruct2.i != 1)
+ return 1;
+ var ginst = new List<string> ();
+ var ginst2 = JitClass.exit_ginst (ginst);
+ if (ginst != ginst2)
+ return 2;
+ var gstruct = new GStruct<string> () { i = 1 };
+ var gstruct2 = JitClass.exit_ginst_vtype (gstruct);
+ if (gstruct2.i != 1)
+ return 3;
+ var anint = 1;
+ JitClass.exit_byref (ref anint);
+ if (anint != 2)
+ return 4;
+ return 0;
+ }
+}
\ No newline at end of file
public static int test_0_vector_array_cast () {
Array arr1 = Array.CreateInstance (typeof (int), new int[] {1}, new int[] {0});
Array arr2 = Array.CreateInstance (typeof (int), new int[] {1}, new int[] {10});
+ Array arr5 = Array.CreateInstance (typeof (string), new int[] {1}, new int[] {10});
if (arr1.GetType () != typeof (int[]))
return 1;
if (arr2 is int[])
return 4;
+ var as_object_arr = arr5 as object [];
+ if (as_object_arr != null)
+ return 5;
int [,] [] arr3 = new int [1, 1] [];
object o = arr3;
MonoJumpInfo *ji = NULL;
GSList *unwind_ops = NULL;
static int farg_regs[] = {AMD64_XMM0, AMD64_XMM1, AMD64_XMM2};
- int i, framesize = 0, off_rbp, off_methodargs, off_targetaddr;
+ int buf_len, i, framesize = 0, off_rbp, off_methodargs, off_targetaddr;
- start = code = (guint8 *) mono_global_codeman_reserve (256 + MONO_TRAMPOLINE_UNWINDINFO_SIZE(0));
+ buf_len = 512 + MONO_TRAMPOLINE_UNWINDINFO_SIZE(0);
+ start = code = (guint8 *) mono_global_codeman_reserve (buf_len);
off_rbp = -framesize;
amd64_dec_reg_size (code, AMD64_RAX, 1);
}
- for (i = 0; i < fregs_num; i++) {
+ for (i = 0; i < fregs_num; i++)
x86_patch (label_fexits [i], code);
- }
/* load pointer to MethodArguments* into R11 */
amd64_mov_reg_reg (code, AMD64_R11, AMD64_ARG_REG2, sizeof (mgreg_t));
amd64_dec_reg_size (code, AMD64_RAX, 1);
}
- for (i = 0; i < gregs_num; i++) {
+ for (i = 0; i < gregs_num; i++)
x86_patch (label_gexits [i], code);
- }
/* load target addr */
amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, off_targetaddr, sizeof (mgreg_t));
label_is_float_ret = code;
x86_branch8 (code, X86_CC_NZ, 0, FALSE);
-
-
/* greg return */
/* load MethodArguments */
amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, off_methodargs, sizeof (mgreg_t));
label_leave_tramp [1] = code;
x86_jump8 (code, 0);
-
-
/* freg return */
x86_patch (label_is_float_ret, code);
/* load MethodArguments */
amd64_pop_reg (code, AMD64_RBP);
amd64_ret (code);
+ g_assert (code - start < buf_len);
+
mono_arch_flush_icache (start, code - start);
mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
addr = mono_get_addr_from_ftnptr (addr);
- /* Compute size of code needed to emit mrgctx */
+ /* Compute size of code needed to emit the arg */
p = imm_buf;
ppc_load_ptr (p, MONO_ARCH_RGCTX_REG, arg);
imm_size = p - imm_buf;
mono_domain_unlock (domain);
if (short_branch) {
- ppc_load_ptr (code, MONO_ARCH_RGCTX_REG, mrgctx);
+ ppc_load_ptr (code, MONO_ARCH_RGCTX_REG, arg);
ppc_emit32 (code, short_branch);
} else {
ppc_load_ptr (code, ppc_r0, addr);
ppc_mtctr (code, ppc_r0);
- ppc_load_ptr (code, MONO_ARCH_RGCTX_REG, mrgctx);
+ ppc_load_ptr (code, MONO_ARCH_RGCTX_REG, arg);
ppc_bcctr (code, 20, 0);
}
mono_arch_flush_icache (start, code - start);
int rank_reg = alloc_preg (cfg);
int eclass_reg = alloc_preg (cfg);
+ if ((klass->rank == 1) && (klass->byval_arg.type == MONO_TYPE_SZARRAY)) {
+ /* Check that the object is a vector too */
+ int bounds_reg = alloc_preg (cfg);
+ MONO_EMIT_NEW_LOAD_MEMBASE (cfg, bounds_reg, obj_reg, 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_PBNE_UN, false_bb);
+ }
+
g_assert (!context_used);
MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU1_MEMBASE, rank_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, rank));
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, rank_reg, klass->rank);
} else if (mono_class_is_interface (klass->cast_class)) {
mini_emit_iface_class_cast (cfg, eclass_reg, klass->cast_class, false_bb, is_null_bb);
} else {
- if ((klass->rank == 1) && (klass->byval_arg.type == MONO_TYPE_SZARRAY)) {
- /* Check that the object is a vector too */
- int bounds_reg = alloc_preg (cfg);
- MONO_EMIT_NEW_LOAD_MEMBASE (cfg, bounds_reg, obj_reg, 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_PBNE_UN, false_bb);
- }
-
/* the is_null_bb target simply copies the input register to the output */
mini_emit_isninst_cast (cfg, eclass_reg, klass->cast_class, false_bb, is_null_bb);
}
if ((opt = match_option (p, "coverage", NULL)) != p) {
do_coverage = 1;
events |= MONO_PROFILE_ENTER_LEAVE;
- debug_coverage = (g_getenv ("MONO_PROFILER_DEBUG_COVERAGE") != NULL);
+ debug_coverage = g_hasenv ("MONO_PROFILER_DEBUG_COVERAGE");
continue;
}
if ((opt = match_option (p, "onlycoverage", NULL)) != p) {
static guint64 large_objects;
static guint64 bloby_objects;
#endif
-static guint64 major_card_scan_time;
-static guint64 los_card_scan_time;
-
-static guint64 last_major_scan_time;
-static guint64 last_los_scan_time;
-
-static void sgen_card_tables_collect_stats (gboolean begin);
mword
sgen_card_table_number_of_cards_in_range (mword address, mword size)
}
static void
-sgen_card_table_finish_minor_collection (void)
-{
- sgen_card_tables_collect_stats (FALSE);
-}
-
-static void
-sgen_card_table_scan_remsets (ScanCopyContext ctx)
+sgen_card_table_start_scan_remsets (void)
{
- SGEN_TV_DECLARE (atv);
- SGEN_TV_DECLARE (btv);
-
- sgen_card_tables_collect_stats (TRUE);
-
#ifdef SGEN_HAVE_OVERLAPPING_CARDS
/*FIXME we should have a bit on each block/los object telling if the object have marked cards.*/
/*First we copy*/
/*Then we clear*/
sgen_card_table_clear_cards ();
#endif
- SGEN_TV_GETTIME (atv);
- sgen_get_major_collector ()->scan_card_table (CARDTABLE_SCAN_GLOBAL, ctx, 0, 1);
- SGEN_TV_GETTIME (btv);
- last_major_scan_time = SGEN_TV_ELAPSED (atv, btv);
- major_card_scan_time += last_major_scan_time;
- sgen_los_scan_card_table (CARDTABLE_SCAN_GLOBAL, ctx, 0, 1);
- SGEN_TV_GETTIME (atv);
- last_los_scan_time = SGEN_TV_ELAPSED (btv, atv);
- los_card_scan_time += last_los_scan_time;
-
- sgen_wbroots_scan_card_table (ctx);
}
guint8*
binary_protocol_card_scan (obj, sgen_safe_object_get_size (obj));
}
-#ifdef CARDTABLE_STATS
-
-typedef struct {
- int total, marked, remarked, gc_marked;
-} card_stats;
-
-static card_stats major_stats, los_stats;
-static card_stats *cur_stats;
-
-static void
-count_marked_cards (mword start, mword size)
-{
- mword end = start + size;
- while (start <= end) {
- guint8 card = *sgen_card_table_get_card_address (start);
- ++cur_stats->total;
- if (card)
- ++cur_stats->marked;
- if (card == 2)
- ++cur_stats->gc_marked;
- start += CARD_SIZE_IN_BYTES;
- }
-}
-
-static void
-count_remarked_cards (mword start, mword size)
-{
- mword end = start + size;
- while (start <= end) {
- if (sgen_card_table_address_is_marked (start)) {
- ++cur_stats->remarked;
- *sgen_card_table_get_card_address (start) = 2;
- }
- start += CARD_SIZE_IN_BYTES;
- }
-}
-
-#endif
-
-static void
-sgen_card_tables_collect_stats (gboolean begin)
-{
-#ifdef CARDTABLE_STATS
- if (begin) {
- memset (&major_stats, 0, sizeof (card_stats));
- memset (&los_stats, 0, sizeof (card_stats));
- cur_stats = &major_stats;
- sgen_major_collector_iterate_live_block_ranges (count_marked_cards);
- cur_stats = &los_stats;
- sgen_los_iterate_live_block_ranges (count_marked_cards);
- } else {
- cur_stats = &major_stats;
- sgen_major_collector_iterate_live_block_ranges (count_remarked_cards);
- cur_stats = &los_stats;
- sgen_los_iterate_live_block_ranges (count_remarked_cards);
- printf ("cards major (t %d m %d g %d r %d) los (t %d m %d g %d r %d) major_scan %.2fms los_scan %.2fms\n",
- major_stats.total, major_stats.marked, major_stats.gc_marked, major_stats.remarked,
- los_stats.total, los_stats.marked, los_stats.gc_marked, los_stats.remarked,
- last_major_scan_time / 10000.0f, last_los_scan_time / 10000.0f);
- }
-#endif
-}
-
void
sgen_card_table_init (SgenRememberedSet *remset)
{
mono_counters_register ("cardtable large objects", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &large_objects);
mono_counters_register ("cardtable bloby objects", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &bloby_objects);
#endif
- mono_counters_register ("cardtable major scan time", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &major_card_scan_time);
- mono_counters_register ("cardtable los scan time", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &los_card_scan_time);
-
remset->wbarrier_set_field = sgen_card_table_wbarrier_set_field;
remset->wbarrier_arrayref_copy = sgen_card_table_wbarrier_arrayref_copy;
remset->wbarrier_generic_nostore = sgen_card_table_wbarrier_generic_nostore;
remset->record_pointer = sgen_card_table_record_pointer;
- remset->scan_remsets = sgen_card_table_scan_remsets;
+ remset->start_scan_remsets = sgen_card_table_start_scan_remsets;
- remset->finish_minor_collection = sgen_card_table_finish_minor_collection;
remset->clear_cards = sgen_card_table_clear_cards;
remset->find_address = sgen_card_table_find_address;
GRAY_OBJECT_ENQUEUE_PARALLEL (queue, (GCObject *)destination, sgen_vtable_get_descriptor (vt));
}
} else {
+ /*
+ * Unlikely case. Clear the allocated object so it doesn't confuse nursery
+ * card table scanning, since it can contain old invalid refs.
+ * FIXME make sure it is not a problem if another threads scans it while we clear
+ */
+ mono_gc_bzero_aligned (destination, objsize);
destination = final_destination;
}
}
static guint64 time_minor_pre_collection_fragment_clear = 0;
static guint64 time_minor_pinning = 0;
static guint64 time_minor_scan_remsets = 0;
+static guint64 time_minor_scan_major_blocks = 0;
+static guint64 time_minor_scan_los = 0;
static guint64 time_minor_scan_pinned = 0;
static guint64 time_minor_scan_roots = 0;
static guint64 time_minor_finish_gray_stack = 0;
static void
gray_queue_redirect (SgenGrayQueue *queue)
{
- SGEN_ASSERT (0, concurrent_collection_in_progress, "Where are we redirecting the gray queue to, without a concurrent collection?");
-
sgen_workers_take_from_queue (queue);
}
mono_counters_register ("Minor fragment clear", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_minor_pre_collection_fragment_clear);
mono_counters_register ("Minor pinning", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_minor_pinning);
mono_counters_register ("Minor scan remembered set", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_minor_scan_remsets);
+ mono_counters_register ("Minor scan major blocks", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_minor_scan_major_blocks);
+ mono_counters_register ("Minor scan los", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_minor_scan_los);
mono_counters_register ("Minor scan pinned", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_minor_scan_pinned);
mono_counters_register ("Minor scan roots", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_minor_scan_roots);
mono_counters_register ("Minor fragment creation", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_minor_fragment_creation);
return CONTEXT_FROM_OBJECT_OPERATIONS (job->ops, sgen_workers_get_job_gray_queue (worker_data, job->gc_thread_gray_queue));
}
-static void
-job_remembered_set_scan (void *worker_data_untyped, SgenThreadPoolJob *job)
-{
- remset.scan_remsets (scan_copy_context_for_scan_job (worker_data_untyped, (ScanJob*)job));
-}
-
typedef struct {
ScanJob scan_job;
char *heap_start;
scan_finalizer_entries (job_data->queue, ctx);
}
+static void
+job_scan_wbroots (void *worker_data_untyped, SgenThreadPoolJob *job)
+{
+ ScanJob *job_data = (ScanJob*)job;
+ ScanCopyContext ctx = scan_copy_context_for_scan_job (worker_data_untyped, job_data);
+
+ sgen_wbroots_scan_card_table (ctx);
+}
+
+static void
+job_scan_major_card_table (void *worker_data_untyped, SgenThreadPoolJob *job)
+{
+ SGEN_TV_DECLARE (atv);
+ SGEN_TV_DECLARE (btv);
+ ParallelScanJob *job_data = (ParallelScanJob*)job;
+ ScanCopyContext ctx = scan_copy_context_for_scan_job (worker_data_untyped, (ScanJob*)job_data);
+
+ SGEN_TV_GETTIME (atv);
+ major_collector.scan_card_table (CARDTABLE_SCAN_GLOBAL, ctx, job_data->job_index, sgen_workers_get_job_split_count ());
+ SGEN_TV_GETTIME (btv);
+ time_minor_scan_major_blocks += SGEN_TV_ELAPSED (atv, btv);
+}
+
+static void
+job_scan_los_card_table (void *worker_data_untyped, SgenThreadPoolJob *job)
+{
+ SGEN_TV_DECLARE (atv);
+ SGEN_TV_DECLARE (btv);
+ ParallelScanJob *job_data = (ParallelScanJob*)job;
+ ScanCopyContext ctx = scan_copy_context_for_scan_job (worker_data_untyped, (ScanJob*)job_data);
+
+ SGEN_TV_GETTIME (atv);
+ sgen_los_scan_card_table (CARDTABLE_SCAN_GLOBAL, ctx, job_data->job_index, sgen_workers_get_job_split_count ());
+ SGEN_TV_GETTIME (btv);
+ time_minor_scan_los += SGEN_TV_ELAPSED (atv, btv);
+}
+
static void
job_scan_major_mod_union_card_table (void *worker_data_untyped, SgenThreadPoolJob *job)
{
sgen_gray_object_queue_init (gc_thread_gray_queue, NULL, TRUE);
}
+static void
+enqueue_scan_remembered_set_jobs (SgenGrayQueue *gc_thread_gray_queue, SgenObjectOperations *ops, gboolean enqueue)
+{
+ int i, split_count = sgen_workers_get_job_split_count ();
+ ScanJob *sj;
+
+ sj = (ScanJob*)sgen_thread_pool_job_alloc ("scan wbroots", job_scan_wbroots, sizeof (ScanJob));
+ sj->ops = ops;
+ sj->gc_thread_gray_queue = gc_thread_gray_queue;
+ sgen_workers_enqueue_job (&sj->job, enqueue);
+
+ for (i = 0; i < split_count; i++) {
+ ParallelScanJob *psj;
+
+ psj = (ParallelScanJob*)sgen_thread_pool_job_alloc ("scan major remsets", job_scan_major_card_table, sizeof (ParallelScanJob));
+ psj->scan_job.ops = ops;
+ psj->scan_job.gc_thread_gray_queue = gc_thread_gray_queue;
+ psj->job_index = i;
+ sgen_workers_enqueue_job (&psj->scan_job.job, enqueue);
+
+ psj = (ParallelScanJob*)sgen_thread_pool_job_alloc ("scan LOS remsets", job_scan_los_card_table, sizeof (ParallelScanJob));
+ psj->scan_job.ops = ops;
+ psj->scan_job.gc_thread_gray_queue = gc_thread_gray_queue;
+ psj->job_index = i;
+ sgen_workers_enqueue_job (&psj->scan_job.job, enqueue);
+ }
+}
+
static void
enqueue_scan_from_roots_jobs (SgenGrayQueue *gc_thread_gray_queue, char *heap_start, char *heap_end, SgenObjectOperations *ops, gboolean enqueue)
{
static gboolean
collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_queue)
{
- gboolean needs_major;
+ gboolean needs_major, is_parallel = FALSE;
size_t max_garbage_amount;
char *nursery_next;
mword fragment_total;
- ScanJob *sj;
SgenGrayQueue gc_thread_gray_queue;
- SgenObjectOperations *object_ops;
+ SgenObjectOperations *object_ops_nopar, *object_ops_par = NULL;
ScanCopyContext ctx;
TV_DECLARE (atv);
TV_DECLARE (btv);
binary_protocol_collection_begin (gc_stats.minor_gc_count, GENERATION_NURSERY);
- if (sgen_concurrent_collection_in_progress ())
- object_ops = &sgen_minor_collector.serial_ops_with_concurrent_major;
- else
- object_ops = &sgen_minor_collector.serial_ops;
+ if (sgen_concurrent_collection_in_progress ()) {
+ /* FIXME Support parallel nursery collections with concurrent major */
+ object_ops_nopar = &sgen_minor_collector.serial_ops_with_concurrent_major;
+ } else {
+ object_ops_nopar = &sgen_minor_collector.serial_ops;
+ if (sgen_minor_collector.is_parallel) {
+ object_ops_par = &sgen_minor_collector.parallel_ops;
+ is_parallel = TRUE;
+ }
+ }
if (do_verify_nursery || do_dump_nursery_content)
sgen_debug_verify_nursery (do_dump_nursery_content);
sgen_memgov_minor_collection_start ();
- init_gray_queue (&gc_thread_gray_queue, FALSE);
- ctx = CONTEXT_FROM_OBJECT_OPERATIONS (object_ops, &gc_thread_gray_queue);
+ init_gray_queue (&gc_thread_gray_queue, is_parallel);
+ ctx = CONTEXT_FROM_OBJECT_OPERATIONS (object_ops_nopar, &gc_thread_gray_queue);
gc_stats.minor_gc_count ++;
SGEN_LOG (2, "Finding pinned pointers: %zd in %lld usecs", sgen_get_pinned_count (), (long long)TV_ELAPSED (btv, atv));
SGEN_LOG (4, "Start scan with %zd pinned objects", sgen_get_pinned_count ());
- sj = (ScanJob*)sgen_thread_pool_job_alloc ("scan remset", job_remembered_set_scan, sizeof (ScanJob));
- sj->ops = object_ops;
- sj->gc_thread_gray_queue = &gc_thread_gray_queue;
- sgen_workers_enqueue_job (&sj->job, FALSE);
+ remset.start_scan_remsets ();
+
+ enqueue_scan_remembered_set_jobs (&gc_thread_gray_queue, is_parallel ? object_ops_par : object_ops_nopar, is_parallel);
/* we don't have complete write barrier yet, so we scan all the old generation sections */
TV_GETTIME (btv);
TV_GETTIME (atv);
time_minor_scan_pinned += TV_ELAPSED (btv, atv);
- enqueue_scan_from_roots_jobs (&gc_thread_gray_queue, sgen_get_nursery_start (), nursery_next, object_ops, FALSE);
+ enqueue_scan_from_roots_jobs (&gc_thread_gray_queue, sgen_get_nursery_start (), nursery_next, is_parallel ? object_ops_par : object_ops_nopar, is_parallel);
+
+ if (is_parallel) {
+ gray_queue_redirect (&gc_thread_gray_queue);
+ sgen_workers_start_all_workers (object_ops_nopar, object_ops_par, NULL);
+ sgen_workers_join ();
+ }
TV_GETTIME (btv);
time_minor_scan_roots += TV_ELAPSED (atv, btv);
sgen_gray_object_queue_dispose (&gc_thread_gray_queue);
- remset.finish_minor_collection ();
-
check_scan_starts ();
binary_protocol_flush_buffers (FALSE);
SGEN_ASSERT (0, sgen_workers_all_done (), "Why are the workers not done when we start or finish a major collection?");
if (mode == COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT) {
- sgen_workers_set_num_active_workers (0);
+ if (object_ops_par != NULL)
+ sgen_workers_set_num_active_workers (0);
if (sgen_workers_have_idle_work ()) {
/*
* We force the finish of the worker with the new object ops context
if (mode == COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT) {
int i, split_count = sgen_workers_get_job_split_count ();
+ gboolean parallel = object_ops_par != NULL;
- gray_queue_redirect (gc_thread_gray_queue);
+ /* If we're not parallel we finish the collection on the gc thread */
+ if (parallel)
+ gray_queue_redirect (gc_thread_gray_queue);
/* Mod union card table */
for (i = 0; i < split_count; i++) {
psj = (ParallelScanJob*)sgen_thread_pool_job_alloc ("scan mod union cardtable", job_scan_major_mod_union_card_table, sizeof (ParallelScanJob));
psj->scan_job.ops = object_ops_par ? object_ops_par : object_ops_nopar;
- psj->scan_job.gc_thread_gray_queue = NULL;
+ psj->scan_job.gc_thread_gray_queue = gc_thread_gray_queue;
psj->job_index = i;
- sgen_workers_enqueue_job (&psj->scan_job.job, TRUE);
+ sgen_workers_enqueue_job (&psj->scan_job.job, parallel);
psj = (ParallelScanJob*)sgen_thread_pool_job_alloc ("scan LOS mod union cardtable", job_scan_los_mod_union_card_table, sizeof (ParallelScanJob));
psj->scan_job.ops = object_ops_par ? object_ops_par : object_ops_nopar;
- psj->scan_job.gc_thread_gray_queue = NULL;
+ psj->scan_job.gc_thread_gray_queue = gc_thread_gray_queue;
psj->job_index = i;
- sgen_workers_enqueue_job (&psj->scan_job.job, TRUE);
+ sgen_workers_enqueue_job (&psj->scan_job.job, parallel);
}
- /*
- * If we enqueue a job while workers are running we need to sgen_workers_ensure_awake
- * in order to make sure that we are running the idle func and draining all worker
- * gray queues. The operation of starting workers implies this, so we start them after
- * in order to avoid doing this operation twice. The workers will drain the main gray
- * stack that contained roots and pinned objects and also scan the mod union card
- * table.
- */
- sgen_workers_start_all_workers (object_ops_nopar, object_ops_par, NULL);
- sgen_workers_join ();
+ if (parallel) {
+ /*
+ * If we enqueue a job while workers are running we need to sgen_workers_ensure_awake
+ * in order to make sure that we are running the idle func and draining all worker
+ * gray queues. The operation of starting workers implies this, so we start them after
+ * in order to avoid doing this operation twice. The workers will drain the main gray
+ * stack that contained roots and pinned objects and also scan the mod union card
+ * table.
+ */
+ sgen_workers_start_all_workers (object_ops_nopar, object_ops_par, NULL);
+ sgen_workers_join ();
+ }
}
sgen_pin_stats_report ();
void
sgen_gc_init (void)
{
- const char *env;
+ char *env;
char **opts, **ptr;
char *major_collector_opt = NULL;
char *minor_collector_opt = NULL;
if ((env = g_getenv (MONO_GC_PARAMS_NAME)) || gc_params_options) {
params_opts = g_strdup_printf ("%s,%s", gc_params_options ? gc_params_options : "", env ? env : "");
+ g_free (env);
}
if (params_opts) {
sgen_client_init ();
if (!minor_collector_opt) {
- sgen_simple_nursery_init (&sgen_minor_collector);
+ sgen_simple_nursery_init (&sgen_minor_collector, FALSE);
} else {
if (!strcmp (minor_collector_opt, "simple")) {
use_simple_nursery:
- sgen_simple_nursery_init (&sgen_minor_collector);
+ sgen_simple_nursery_init (&sgen_minor_collector, FALSE);
+ } else if (!strcmp (minor_collector_opt, "simple-par")) {
+ sgen_simple_nursery_init (&sgen_minor_collector, TRUE);
} else if (!strcmp (minor_collector_opt, "split")) {
sgen_split_nursery_init (&sgen_minor_collector);
} else {
if ((env = g_getenv (MONO_GC_DEBUG_NAME)) || gc_debug_options) {
debug_opts = g_strdup_printf ("%s,%s", gc_debug_options ? gc_debug_options : "", env ? env : "");
+ g_free (env);
}
if (debug_opts) {
if (major_collector.post_param_init)
major_collector.post_param_init (&major_collector);
- if (major_collector.needs_thread_pool) {
+ if (major_collector.is_concurrent || sgen_minor_collector.is_parallel) {
int num_workers = 1;
- if (major_collector.is_parallel) {
+ if (major_collector.is_parallel || sgen_minor_collector.is_parallel) {
/* FIXME Detect the number of physical cores, instead of logical */
num_workers = mono_cpu_count () / 2;
if (num_workers < 1)
return &major_collector;
}
+SgenMinorCollector*
+sgen_get_minor_collector (void)
+{
+ return &sgen_minor_collector;
+}
+
SgenRememberedSet*
sgen_get_remset (void)
{
#include "mono/sgen/sgen-hash-table.h"
#include "mono/sgen/sgen-protocol.h"
#include "mono/sgen/gc-internal-agnostic.h"
+#include "mono/sgen/sgen-thread-pool.h"
/* The method used to clear the nursery */
/* Clearing at nursery collections is the safest, but has bad interactions with caches.
g_error (__VA_ARGS__); \
} } while (0)
-#ifndef HOST_WIN32
+#ifdef HAVE_LOCALTIME_R
# define LOG_TIMESTAMP \
do { \
time_t t; \
typedef struct {
gboolean is_split;
+ gboolean is_parallel;
GCObject* (*alloc_for_promotion) (GCVTable vtable, GCObject *obj, size_t objsize, gboolean has_references);
SgenObjectOperations serial_ops;
SgenObjectOperations serial_ops_with_concurrent_major;
+ SgenObjectOperations parallel_ops;
void (*prepare_to_space) (char *to_space_bitmap, size_t space_bitmap_size);
void (*clear_fragments) (void);
extern SgenMinorCollector sgen_minor_collector;
-void sgen_simple_nursery_init (SgenMinorCollector *collector);
+void sgen_simple_nursery_init (SgenMinorCollector *collector, gboolean parallel);
void sgen_split_nursery_init (SgenMinorCollector *collector);
/* Updating references */
{
if (!allow_null)
SGEN_ASSERT (0, o, "Cannot update a reference with a NULL pointer");
- SGEN_ASSERT (0, !sgen_thread_pool_is_thread_pool_thread (mono_native_thread_id_get ()), "Can't update a reference in the worker thread");
+ SGEN_ASSERT (0, !sgen_workers_is_worker_thread (mono_native_thread_id_get ()), "Can't update a reference in the worker thread");
*p = o;
}
size_t section_size;
gboolean is_concurrent;
gboolean is_parallel;
- gboolean needs_thread_pool;
gboolean supports_cardtable;
gboolean sweeps_lazily;
guint8* (*get_cardtable_mod_union_for_reference) (char *object);
long long (*get_and_reset_num_major_objects_marked) (void);
void (*count_cards) (long long *num_total_cards, long long *num_marked_cards);
+ SgenThreadPool* (*get_sweep_pool) (void);
void (*worker_init_cb) (gpointer worker);
};
void sgen_marksweep_conc_init (SgenMajorCollector *collector);
void sgen_marksweep_conc_par_init (SgenMajorCollector *collector);
SgenMajorCollector* sgen_get_major_collector (void);
+SgenMinorCollector* sgen_get_minor_collector (void);
typedef struct _SgenRememberedSet {
void (*wbarrier_generic_nostore) (gpointer ptr);
void (*record_pointer) (gpointer ptr);
- void (*scan_remsets) (ScanCopyContext ctx);
+ void (*start_scan_remsets) (void);
void (*clear_cards) (void);
- void (*finish_minor_collection) (void);
gboolean (*find_address) (char *addr);
gboolean (*find_address_with_cards) (char *cards_start, guint8 *cards, char *addr);
} SgenRememberedSet;
#define SGEN_GRAY_QUEUE_HEADER_SIZE 3
#endif
-#define SGEN_GRAY_QUEUE_SECTION_SIZE (128 - SGEN_GRAY_QUEUE_HEADER_SIZE)
+#define SGEN_GRAY_QUEUE_SECTION_SIZE (512 - SGEN_GRAY_QUEUE_HEADER_SIZE)
#ifdef SGEN_CHECK_GRAY_OBJECT_SECTIONS
typedef enum {
static gboolean concurrent_mark;
static gboolean concurrent_sweep = TRUE;
+SgenThreadPool sweep_pool_inst;
+SgenThreadPool *sweep_pool;
+
#define BLOCK_IS_TAGGED_HAS_REFERENCES(bl) SGEN_POINTER_IS_TAGGED_1 ((bl))
#define BLOCK_TAG_HAS_REFERENCES(bl) SGEN_POINTER_TAG_1 ((bl))
*/
if (SGEN_CAS_PTR ((volatile gpointer *)&free_blocks [size_index], next_free, block) != block)
goto get_block;
- g_assert (block->free_list);
block->next_free = free_blocks_local [size_index];
free_blocks_local [size_index] = block;
wait:
job = sweep_job;
if (job)
- sgen_thread_pool_job_wait (job);
+ sgen_thread_pool_job_wait (sweep_pool, job);
SGEN_ASSERT (0, !sweep_job, "Why did the sweep job not null itself?");
SGEN_ASSERT (0, sweep_state == SWEEP_STATE_SWEPT, "How is the sweep job done but we're not swept?");
}
}
}
+static void
+sgen_worker_clear_free_block_lists_evac (WorkerData *worker)
+{
+ int i, j;
+
+ if (!worker->free_block_lists)
+ return;
+
+ for (i = 0; i < MS_BLOCK_TYPE_MAX; i++) {
+ for (j = 0; j < num_block_obj_sizes; j++) {
+ if (((MSBlockInfo***) worker->free_block_lists) [i][j])
+ SGEN_ASSERT (0, !((MSBlockInfo***) worker->free_block_lists) [i][j]->next_free, "Why do we have linked free blocks on the workers");
+
+ if (evacuate_block_obj_sizes [j])
+ ((MSBlockInfo***) worker->free_block_lists) [i][j] = NULL;
+ }
+ }
+}
+
static void
sweep_start (void)
{
*/
if (concurrent_sweep && lazy_sweep) {
sweep_blocks_job = sgen_thread_pool_job_alloc ("sweep_blocks", sweep_blocks_job_func, sizeof (SgenThreadPoolJob));
- sgen_thread_pool_job_enqueue (sweep_blocks_job);
+ sgen_thread_pool_job_enqueue (sweep_pool, sweep_blocks_job);
}
sweep_finish ();
SGEN_ASSERT (0, !sweep_job, "We haven't finished the last sweep?");
if (concurrent_sweep) {
sweep_job = sgen_thread_pool_job_alloc ("sweep", sweep_job_func, sizeof (SgenThreadPoolJob));
- sgen_thread_pool_job_enqueue (sweep_job);
+ sgen_thread_pool_job_enqueue (sweep_pool, sweep_job);
} else {
sweep_job_func (NULL, NULL);
}
sgen_evacuation_freelist_blocks (&free_block_lists [MS_BLOCK_FLAG_REFS][i], i);
}
+ /* We expect workers to have very few blocks on the freelist, just evacuate them */
+ sgen_workers_foreach (sgen_worker_clear_free_block_lists_evac);
+
if (lazy_sweep && concurrent_sweep) {
/*
* sweep_blocks_job is created before sweep_finish, which we wait for above
*/
SgenThreadPoolJob *job = sweep_blocks_job;
if (job)
- sgen_thread_pool_job_wait (job);
+ sgen_thread_pool_job_wait (sweep_pool, job);
}
if (lazy_sweep && !concurrent_sweep)
#endif
}
+static SgenThreadPool*
+major_get_sweep_pool (void)
+{
+ return sweep_pool;
+}
+
static int
compare_pointers (const void *va, const void *vb) {
char *a = *(char**)va, *b = *(char**)vb;
post_param_init (SgenMajorCollector *collector)
{
collector->sweeps_lazily = lazy_sweep;
- collector->needs_thread_pool = concurrent_mark || concurrent_sweep;
}
/* We are guaranteed to be called by the worker in question */
mono_native_tls_set_value (worker_block_free_list_key, worker_free_blocks);
}
+static void
+thread_pool_init_func (void *data_untyped)
+{
+ sgen_client_thread_register_worker ();
+}
+
static void
sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurrent, gboolean is_parallel)
{
for (i = 0; i < MS_NUM_FAST_BLOCK_OBJ_SIZE_INDEXES * 8; ++i)
g_assert (MS_BLOCK_OBJ_SIZE_INDEX (i) == ms_find_block_obj_size_index (i));
+ /* We can do this because we always init the minor before the major */
+ if (is_parallel || sgen_get_minor_collector ()->is_parallel) {
+ mono_native_tls_alloc (&worker_block_free_list_key, NULL);
+ collector->worker_init_cb = sgen_worker_init_callback;
+ }
+
mono_counters_register ("# major blocks allocated", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_alloced);
mono_counters_register ("# major blocks freed", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed);
mono_counters_register ("# major blocks lazy swept", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_lazy_swept);
concurrent_mark = is_concurrent;
collector->is_concurrent = is_concurrent;
collector->is_parallel = is_parallel;
- collector->needs_thread_pool = is_concurrent || concurrent_sweep;
collector->get_and_reset_num_major_objects_marked = major_get_and_reset_num_major_objects_marked;
collector->supports_cardtable = TRUE;
collector->is_valid_object = major_is_valid_object;
collector->describe_pointer = major_describe_pointer;
collector->count_cards = major_count_cards;
+ collector->get_sweep_pool = major_get_sweep_pool;
collector->major_ops_serial.copy_or_mark_object = major_copy_or_mark_object_canonical;
collector->major_ops_serial.scan_object = major_scan_object_with_evacuation;
collector->major_ops_conc_par_finish.scan_vtype = major_scan_vtype_par_with_evacuation;
collector->major_ops_conc_par_finish.scan_ptr_field = major_scan_ptr_field_par_with_evacuation;
collector->major_ops_conc_par_finish.drain_gray_stack = drain_gray_stack_par;
-
- collector->worker_init_cb = sgen_worker_init_callback;
-
- mono_native_tls_alloc (&worker_block_free_list_key, NULL);
}
}
/*cardtable requires major pages to be 8 cards aligned*/
g_assert ((MS_BLOCK_SIZE % (8 * CARD_SIZE_IN_BYTES)) == 0);
+
+ if (concurrent_sweep) {
+ SgenThreadPool **thread_datas = &sweep_pool;
+ sweep_pool = &sweep_pool_inst;
+ sgen_thread_pool_init (sweep_pool, 1, thread_pool_init_func, NULL, NULL, NULL, (SgenThreadPoolData**)&thread_datas);
+ }
}
void
#include "mono/sgen/sgen-gc.h"
#include "mono/sgen/sgen-memory-governor.h"
-#include "mono/sgen/sgen-thread-pool.h"
+#include "mono/sgen/sgen-workers.h"
#include "mono/sgen/sgen-client.h"
#define MIN_MINOR_COLLECTION_ALLOWANCE ((mword)(DEFAULT_NURSERY_SIZE * default_allowance_nursery_size_ratio))
sgen_memgov_try_alloc_space (mword size, int space)
{
if (sgen_memgov_available_free_space () < size) {
- SGEN_ASSERT (4, !sgen_thread_pool_is_thread_pool_thread (mono_native_thread_id_get ()), "Memory shouldn't run out in worker thread");
+ SGEN_ASSERT (4, !sgen_workers_is_worker_thread (mono_native_thread_id_get ()), "Memory shouldn't run out in worker thread");
return FALSE;
}
#if defined(SGEN_SIMPLE_NURSERY)
+#ifdef SGEN_SIMPLE_PAR_NURSERY
+/* Not supported with concurrent major yet */
+#define SERIAL_COPY_OBJECT simple_par_nursery_copy_object
+#define SERIAL_COPY_OBJECT_FROM_OBJ simple_par_nursery_copy_object_from_obj
+#else
#ifdef SGEN_CONCURRENT_MAJOR
#define SERIAL_COPY_OBJECT simple_nursery_serial_with_concurrent_major_copy_object
#define SERIAL_COPY_OBJECT_FROM_OBJ simple_nursery_serial_with_concurrent_major_copy_object_from_obj
#define SERIAL_COPY_OBJECT simple_nursery_serial_copy_object
#define SERIAL_COPY_OBJECT_FROM_OBJ simple_nursery_serial_copy_object_from_obj
#endif
+#endif
#elif defined (SGEN_SPLIT_NURSERY)
HEAVY_STAT (++stat_objects_copied_nursery);
+#ifdef SGEN_SIMPLE_PAR_NURSERY
+ copy = copy_object_no_checks_par (obj, queue);
+#else
copy = copy_object_no_checks (obj, queue);
+#endif
SGEN_UPDATE_REFERENCE (obj_slot, copy);
}
HEAVY_STAT (++stat_objects_copied_nursery);
+#ifdef SGEN_SIMPLE_PAR_NURSERY
+ copy = copy_object_no_checks_par (obj, queue);
+#else
copy = copy_object_no_checks (obj, queue);
+#endif
#ifdef SGEN_CONCURRENT_MAJOR
/*
* If an object is evacuated to the major heap and a reference to it, from the major
#if defined(SGEN_SIMPLE_NURSERY)
+#ifdef SGEN_SIMPLE_PAR_NURSERY
+#define SERIAL_SCAN_OBJECT simple_par_nursery_serial_scan_object
+#define SERIAL_SCAN_VTYPE simple_par_nursery_serial_scan_vtype
+#define SERIAL_SCAN_PTR_FIELD simple_par_nursery_serial_scan_ptr_field
+#define SERIAL_DRAIN_GRAY_STACK simple_par_nursery_serial_drain_gray_stack
+#else
#ifdef SGEN_CONCURRENT_MAJOR
#define SERIAL_SCAN_OBJECT simple_nursery_serial_with_concurrent_major_scan_object
#define SERIAL_SCAN_VTYPE simple_nursery_serial_with_concurrent_major_scan_vtype
#define SERIAL_SCAN_PTR_FIELD simple_nursery_serial_scan_ptr_field
#define SERIAL_DRAIN_GRAY_STACK simple_nursery_serial_drain_gray_stack
#endif
+#endif
#elif defined (SGEN_SPLIT_NURSERY)
static gboolean
SERIAL_DRAIN_GRAY_STACK (SgenGrayQueue *queue)
{
- for (;;) {
- GCObject *obj;
- SgenDescriptor desc;
+#ifdef SGEN_SIMPLE_PAR_NURSERY
+ int i;
+ /*
+ * We do bounded iteration so we can switch to optimized context
+ * when we are the last worker remaining.
+ */
+ for (i = 0; i < 32; i++) {
+#else
+ for (;;) {
+#endif
+ GCObject *obj;
+ SgenDescriptor desc;
+
+#ifdef SGEN_SIMPLE_PAR_NURSERY
+ GRAY_OBJECT_DEQUEUE_PARALLEL (queue, &obj, &desc);
+#else
+ GRAY_OBJECT_DEQUEUE_SERIAL (queue, &obj, &desc);
+#endif
+ if (!obj)
+ return TRUE;
- GRAY_OBJECT_DEQUEUE_SERIAL (queue, &obj, &desc);
- if (!obj)
- return TRUE;
+ SERIAL_SCAN_OBJECT (obj, desc, queue);
+ }
- SERIAL_SCAN_OBJECT (obj, desc, queue);
- }
+ return FALSE;
}
#define FILL_MINOR_COLLECTOR_SCAN_OBJECT(ops) do { \
#include "sgen-gc.h"
#include "sgen-protocol.h"
#include "sgen-memory-governor.h"
-#include "sgen-thread-pool.h"
+#include "sgen-workers.h"
#include "sgen-client.h"
#include "mono/utils/mono-membar.h"
#include "mono/utils/mono-proclib.h"
buffer->buffer [index++] = type;
/* We should never change the header format */
if (include_worker_index) {
+ int worker_index;
+ MonoNativeThreadId tid = mono_native_thread_id_get ();
/*
* If the thread is not a worker thread we insert 0, which is interpreted
* as gc thread. Worker indexes are 1 based.
*/
- buffer->buffer [index++] = (unsigned char) sgen_thread_pool_is_thread_pool_thread (mono_native_thread_id_get ());
+ worker_index = sgen_workers_is_worker_thread (tid);
+ if (!worker_index)
+ worker_index = sgen_thread_pool_is_thread_pool_thread (major_collector.get_sweep_pool (), tid);
+ /* FIXME Consider using different index bases for different thread pools */
+ buffer->buffer [index++] = (unsigned char) worker_index;
}
memcpy (buffer->buffer + index, data, size);
index += size;
#define collector_pin_object(obj, queue) sgen_pin_object (obj, queue);
#define COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION alloc_for_promotion
+#define COPY_OR_MARK_PARALLEL
#include "sgen-copy-object.h"
#define SGEN_SIMPLE_NURSERY
FILL_MINOR_COLLECTOR_SCAN_OBJECT (ops);
}
+#define SGEN_SIMPLE_PAR_NURSERY
+
+#include "sgen-minor-copy-object.h"
+#include "sgen-minor-scan-object.h"
+
+static void
+fill_parallel_ops (SgenObjectOperations *ops)
+{
+ ops->copy_or_mark_object = SERIAL_COPY_OBJECT;
+ FILL_MINOR_COLLECTOR_SCAN_OBJECT (ops);
+}
+
+#undef SGEN_SIMPLE_PAR_NURSERY
#define SGEN_CONCURRENT_MAJOR
#include "sgen-minor-copy-object.h"
}
void
-sgen_simple_nursery_init (SgenMinorCollector *collector)
+sgen_simple_nursery_init (SgenMinorCollector *collector, gboolean parallel)
{
collector->is_split = FALSE;
+ collector->is_parallel = parallel;
collector->alloc_for_promotion = alloc_for_promotion;
fill_serial_ops (&collector->serial_ops);
fill_serial_with_concurrent_major_ops (&collector->serial_ops_with_concurrent_major);
+ fill_parallel_ops (&collector->parallel_ops);
}
sgen_split_nursery_init (SgenMinorCollector *collector)
{
collector->is_split = TRUE;
+ collector->is_parallel = FALSE;
collector->alloc_for_promotion = minor_alloc_for_promotion;
#include "mono/sgen/sgen-gc.h"
#include "mono/sgen/sgen-thread-pool.h"
-#include "mono/sgen/sgen-pointer-queue.h"
#include "mono/utils/mono-os-mutex.h"
-#ifndef SGEN_WITHOUT_MONO
-#include "mono/utils/mono-threads.h"
-#endif
-
-#define MAX_NUM_THREADS 8
-
-static mono_mutex_t lock;
-static mono_cond_t work_cond;
-static mono_cond_t done_cond;
-
-static int threads_num = 0;
-static MonoNativeThreadId threads [MAX_NUM_THREADS];
-
-/* Only accessed with the lock held. */
-static SgenPointerQueue job_queue;
-
-static SgenThreadPoolThreadInitFunc thread_init_func;
-static SgenThreadPoolIdleJobFunc idle_job_func;
-static SgenThreadPoolContinueIdleJobFunc continue_idle_job_func;
-static SgenThreadPoolShouldWorkFunc should_work_func;
-
-static volatile gboolean threadpool_shutdown;
-static volatile int threads_finished = 0;
enum {
STATE_WAITING,
/* Assumes that the lock is held. */
static SgenThreadPoolJob*
-get_job_and_set_in_progress (void)
+get_job_and_set_in_progress (SgenThreadPool *pool)
{
- for (size_t i = 0; i < job_queue.next_slot; ++i) {
- SgenThreadPoolJob *job = (SgenThreadPoolJob *)job_queue.data [i];
+ for (size_t i = 0; i < pool->job_queue.next_slot; ++i) {
+ SgenThreadPoolJob *job = (SgenThreadPoolJob *)pool->job_queue.data [i];
if (job->state == STATE_WAITING) {
job->state = STATE_IN_PROGRESS;
return job;
/* Assumes that the lock is held. */
static ssize_t
-find_job_in_queue (SgenThreadPoolJob *job)
+find_job_in_queue (SgenThreadPool *pool, SgenThreadPoolJob *job)
{
- for (ssize_t i = 0; i < job_queue.next_slot; ++i) {
- if (job_queue.data [i] == job)
+ for (ssize_t i = 0; i < pool->job_queue.next_slot; ++i) {
+ if (pool->job_queue.data [i] == job)
return i;
}
return -1;
/* Assumes that the lock is held. */
static void
-remove_job (SgenThreadPoolJob *job)
+remove_job (SgenThreadPool *pool, SgenThreadPoolJob *job)
{
ssize_t index;
SGEN_ASSERT (0, job->state == STATE_DONE, "Why are we removing a job that's not done?");
- index = find_job_in_queue (job);
+ index = find_job_in_queue (pool, job);
SGEN_ASSERT (0, index >= 0, "Why is the job we're trying to remove not in the queue?");
- job_queue.data [index] = NULL;
- sgen_pointer_queue_remove_nulls (&job_queue);
+ pool->job_queue.data [index] = NULL;
+ sgen_pointer_queue_remove_nulls (&pool->job_queue);
sgen_thread_pool_job_free (job);
}
static gboolean
-continue_idle_job (void *thread_data)
+continue_idle_job (SgenThreadPool *pool, void *thread_data)
{
- if (!continue_idle_job_func)
+ if (!pool->continue_idle_job_func)
return FALSE;
- return continue_idle_job_func (thread_data);
+ return pool->continue_idle_job_func (thread_data);
}
static gboolean
-should_work (void *thread_data)
+should_work (SgenThreadPool *pool, void *thread_data)
{
- if (!should_work_func)
+ if (!pool->should_work_func)
return TRUE;
- return should_work_func (thread_data);
+ return pool->should_work_func (thread_data);
}
static mono_native_thread_return_t
-thread_func (void *thread_data)
+thread_func (SgenThreadPoolData *thread_data)
{
- thread_init_func (thread_data);
+ SgenThreadPool *pool = thread_data->pool;
+
+ pool->thread_init_func (thread_data);
- mono_os_mutex_lock (&lock);
+ mono_os_mutex_lock (&pool->lock);
for (;;) {
gboolean do_idle;
SgenThreadPoolJob *job;
- if (!should_work (thread_data)) {
- mono_os_cond_wait (&work_cond, &lock);
+ if (!should_work (pool, thread_data) && !pool->threadpool_shutdown) {
+ mono_os_cond_wait (&pool->work_cond, &pool->lock);
continue;
}
/*
* main thread might then set continue idle and signal us before we can take
* the lock, and we'd lose the signal.
*/
- do_idle = continue_idle_job (thread_data);
- job = get_job_and_set_in_progress ();
+ do_idle = continue_idle_job (pool, thread_data);
+ job = get_job_and_set_in_progress (pool);
- if (!job && !do_idle && !threadpool_shutdown) {
+ if (!job && !do_idle && !pool->threadpool_shutdown) {
/*
* pthread_cond_wait() can return successfully despite the condition
* not being signalled, so we have to run this in a loop until we
* really have work to do.
*/
- mono_os_cond_wait (&work_cond, &lock);
+ mono_os_cond_wait (&pool->work_cond, &pool->lock);
continue;
}
- mono_os_mutex_unlock (&lock);
+ mono_os_mutex_unlock (&pool->lock);
if (job) {
job->func (thread_data, job);
- mono_os_mutex_lock (&lock);
+ mono_os_mutex_lock (&pool->lock);
SGEN_ASSERT (0, job->state == STATE_IN_PROGRESS, "The job should still be in progress.");
job->state = STATE_DONE;
- remove_job (job);
+ remove_job (pool, job);
/*
* Only the main GC thread will ever wait on the done condition, so we don't
* have to broadcast.
*/
- mono_os_cond_signal (&done_cond);
+ mono_os_cond_signal (&pool->done_cond);
} else if (do_idle) {
- SGEN_ASSERT (0, idle_job_func, "Why do we have idle work when there's no idle job function?");
+ SGEN_ASSERT (0, pool->idle_job_func, "Why do we have idle work when there's no idle job function?");
do {
- idle_job_func (thread_data);
- do_idle = continue_idle_job (thread_data);
- } while (do_idle && !job_queue.next_slot);
+ pool->idle_job_func (thread_data);
+ do_idle = continue_idle_job (pool, thread_data);
+ } while (do_idle && !pool->job_queue.next_slot);
- mono_os_mutex_lock (&lock);
+ mono_os_mutex_lock (&pool->lock);
if (!do_idle)
- mono_os_cond_signal (&done_cond);
+ mono_os_cond_signal (&pool->done_cond);
} else {
- SGEN_ASSERT (0, threadpool_shutdown, "Why did we unlock if no jobs and not shutting down?");
- mono_os_mutex_lock (&lock);
- threads_finished++;
- mono_os_cond_signal (&done_cond);
- mono_os_mutex_unlock (&lock);
+ SGEN_ASSERT (0, pool->threadpool_shutdown, "Why did we unlock if no jobs and not shutting down?");
+ mono_os_mutex_lock (&pool->lock);
+ pool->threads_finished++;
+ mono_os_cond_signal (&pool->done_cond);
+ mono_os_mutex_unlock (&pool->lock);
return 0;
}
}
}
void
-sgen_thread_pool_init (int num_threads, SgenThreadPoolThreadInitFunc init_func, SgenThreadPoolIdleJobFunc idle_func, SgenThreadPoolContinueIdleJobFunc continue_idle_func, SgenThreadPoolShouldWorkFunc should_work_func_p, void **thread_datas)
+sgen_thread_pool_init (SgenThreadPool *pool, int num_threads, SgenThreadPoolThreadInitFunc init_func, SgenThreadPoolIdleJobFunc idle_func, SgenThreadPoolContinueIdleJobFunc continue_idle_func, SgenThreadPoolShouldWorkFunc should_work_func_p, SgenThreadPoolData **thread_datas)
{
int i;
- threads_num = (num_threads < MAX_NUM_THREADS) ? num_threads : MAX_NUM_THREADS;
+ SGEN_ASSERT (0, num_threads > 0, "Why are we creating a threadpool with no threads?");
+
+ pool->threads_num = (num_threads < MAX_NUM_THREADS) ? num_threads : MAX_NUM_THREADS;
- mono_os_mutex_init (&lock);
- mono_os_cond_init (&work_cond);
- mono_os_cond_init (&done_cond);
+ mono_os_mutex_init (&pool->lock);
+ mono_os_cond_init (&pool->work_cond);
+ mono_os_cond_init (&pool->done_cond);
- thread_init_func = init_func;
- idle_job_func = idle_func;
- continue_idle_job_func = continue_idle_func;
- should_work_func = should_work_func_p;
+ pool->thread_init_func = init_func;
+ pool->idle_job_func = idle_func;
+ pool->continue_idle_job_func = continue_idle_func;
+ pool->should_work_func = should_work_func_p;
- for (i = 0; i < threads_num; i++)
- mono_native_thread_create (&threads [i], thread_func, thread_datas ? thread_datas [i] : NULL);
+ sgen_pointer_queue_init (&pool->job_queue, 0);
+ pool->threads_finished = 0;
+ pool->threadpool_shutdown = FALSE;
+
+ for (i = 0; i < pool->threads_num; i++) {
+ thread_datas [i]->pool = pool;
+ mono_native_thread_create (&pool->threads [i], thread_func, thread_datas [i]);
+ }
}
void
-sgen_thread_pool_shutdown (void)
+sgen_thread_pool_shutdown (SgenThreadPool *pool)
{
- if (!threads_num)
+ if (!pool)
return;
- mono_os_mutex_lock (&lock);
- threadpool_shutdown = TRUE;
- mono_os_cond_broadcast (&work_cond);
- while (threads_finished < threads_num)
- mono_os_cond_wait (&done_cond, &lock);
- mono_os_mutex_unlock (&lock);
+ mono_os_mutex_lock (&pool->lock);
+ pool->threadpool_shutdown = TRUE;
+ mono_os_cond_broadcast (&pool->work_cond);
+ while (pool->threads_finished < pool->threads_num)
+ mono_os_cond_wait (&pool->done_cond, &pool->lock);
+ mono_os_mutex_unlock (&pool->lock);
- mono_os_mutex_destroy (&lock);
- mono_os_cond_destroy (&work_cond);
- mono_os_cond_destroy (&done_cond);
+ mono_os_mutex_destroy (&pool->lock);
+ mono_os_cond_destroy (&pool->work_cond);
+ mono_os_cond_destroy (&pool->done_cond);
}
SgenThreadPoolJob*
}
void
-sgen_thread_pool_job_enqueue (SgenThreadPoolJob *job)
+sgen_thread_pool_job_enqueue (SgenThreadPool *pool, SgenThreadPoolJob *job)
{
- mono_os_mutex_lock (&lock);
+ mono_os_mutex_lock (&pool->lock);
- sgen_pointer_queue_add (&job_queue, job);
- mono_os_cond_signal (&work_cond);
+ sgen_pointer_queue_add (&pool->job_queue, job);
+ mono_os_cond_signal (&pool->work_cond);
- mono_os_mutex_unlock (&lock);
+ mono_os_mutex_unlock (&pool->lock);
}
void
-sgen_thread_pool_job_wait (SgenThreadPoolJob *job)
+sgen_thread_pool_job_wait (SgenThreadPool *pool, SgenThreadPoolJob *job)
{
SGEN_ASSERT (0, job, "Where's the job?");
- mono_os_mutex_lock (&lock);
+ mono_os_mutex_lock (&pool->lock);
- while (find_job_in_queue (job) >= 0)
- mono_os_cond_wait (&done_cond, &lock);
+ while (find_job_in_queue (pool, job) >= 0)
+ mono_os_cond_wait (&pool->done_cond, &pool->lock);
- mono_os_mutex_unlock (&lock);
+ mono_os_mutex_unlock (&pool->lock);
}
void
-sgen_thread_pool_idle_signal (void)
+sgen_thread_pool_idle_signal (SgenThreadPool *pool)
{
- SGEN_ASSERT (0, idle_job_func, "Why are we signaling idle without an idle function?");
+ SGEN_ASSERT (0, pool->idle_job_func, "Why are we signaling idle without an idle function?");
- mono_os_mutex_lock (&lock);
+ mono_os_mutex_lock (&pool->lock);
- if (continue_idle_job_func (NULL))
- mono_os_cond_broadcast (&work_cond);
+ if (pool->continue_idle_job_func (NULL))
+ mono_os_cond_broadcast (&pool->work_cond);
- mono_os_mutex_unlock (&lock);
+ mono_os_mutex_unlock (&pool->lock);
}
void
-sgen_thread_pool_idle_wait (void)
+sgen_thread_pool_idle_wait (SgenThreadPool *pool)
{
- SGEN_ASSERT (0, idle_job_func, "Why are we waiting for idle without an idle function?");
+ SGEN_ASSERT (0, pool->idle_job_func, "Why are we waiting for idle without an idle function?");
- mono_os_mutex_lock (&lock);
+ mono_os_mutex_lock (&pool->lock);
- while (continue_idle_job_func (NULL))
- mono_os_cond_wait (&done_cond, &lock);
+ while (pool->continue_idle_job_func (NULL))
+ mono_os_cond_wait (&pool->done_cond, &pool->lock);
- mono_os_mutex_unlock (&lock);
+ mono_os_mutex_unlock (&pool->lock);
}
void
-sgen_thread_pool_wait_for_all_jobs (void)
+sgen_thread_pool_wait_for_all_jobs (SgenThreadPool *pool)
{
- mono_os_mutex_lock (&lock);
+ mono_os_mutex_lock (&pool->lock);
- while (!sgen_pointer_queue_is_empty (&job_queue))
- mono_os_cond_wait (&done_cond, &lock);
+ while (!sgen_pointer_queue_is_empty (&pool->job_queue))
+ mono_os_cond_wait (&pool->done_cond, &pool->lock);
- mono_os_mutex_unlock (&lock);
+ mono_os_mutex_unlock (&pool->lock);
}
/* Return 0 if is not a thread pool thread or the thread number otherwise */
int
-sgen_thread_pool_is_thread_pool_thread (MonoNativeThreadId some_thread)
+sgen_thread_pool_is_thread_pool_thread (SgenThreadPool *pool, MonoNativeThreadId some_thread)
{
int i;
- for (i = 0; i < threads_num; i++) {
- if (some_thread == threads [i])
+ if (!pool)
+ return 0;
+
+ for (i = 0; i < pool->threads_num; i++) {
+ if (some_thread == pool->threads [i])
return i + 1;
}
#ifndef __MONO_SGEN_THREAD_POOL_H__
#define __MONO_SGEN_THREAD_POOL_H__
+#include "mono/sgen/sgen-pointer-queue.h"
+#include "mono/utils/mono-threads.h"
+
typedef struct _SgenThreadPoolJob SgenThreadPoolJob;
+typedef struct _SgenThreadPool SgenThreadPool;
+typedef struct _SgenThreadPoolData SgenThreadPoolData;
typedef void (*SgenThreadPoolJobFunc) (void *thread_data, SgenThreadPoolJob *job);
+typedef void (*SgenThreadPoolThreadInitFunc) (void*);
+typedef void (*SgenThreadPoolIdleJobFunc) (void*);
+typedef gboolean (*SgenThreadPoolContinueIdleJobFunc) (void*);
+typedef gboolean (*SgenThreadPoolShouldWorkFunc) (void*);
struct _SgenThreadPoolJob {
const char *name;
volatile gint32 state;
};
-typedef void (*SgenThreadPoolThreadInitFunc) (void*);
-typedef void (*SgenThreadPoolIdleJobFunc) (void*);
-typedef gboolean (*SgenThreadPoolContinueIdleJobFunc) (void*);
-typedef gboolean (*SgenThreadPoolShouldWorkFunc) (void*);
+#define MAX_NUM_THREADS 8
+
+struct _SgenThreadPool {
+ mono_mutex_t lock;
+ mono_cond_t work_cond;
+ mono_cond_t done_cond;
+
+ int threads_num;
+ MonoNativeThreadId threads [MAX_NUM_THREADS];
+
+ /* Only accessed with the lock held. */
+ SgenPointerQueue job_queue;
+
+ SgenThreadPoolThreadInitFunc thread_init_func;
+ SgenThreadPoolIdleJobFunc idle_job_func;
+ SgenThreadPoolContinueIdleJobFunc continue_idle_job_func;
+ SgenThreadPoolShouldWorkFunc should_work_func;
+
+ volatile gboolean threadpool_shutdown;
+ volatile int threads_finished;
+};
+
+struct _SgenThreadPoolData {
+ SgenThreadPool *pool;
+};
-void sgen_thread_pool_init (int num_threads, SgenThreadPoolThreadInitFunc init_func, SgenThreadPoolIdleJobFunc idle_func, SgenThreadPoolContinueIdleJobFunc continue_idle_func, SgenThreadPoolShouldWorkFunc should_work_func, void **thread_datas);
+void sgen_thread_pool_init (SgenThreadPool *pool, int num_threads, SgenThreadPoolThreadInitFunc init_func, SgenThreadPoolIdleJobFunc idle_func, SgenThreadPoolContinueIdleJobFunc continue_idle_func, SgenThreadPoolShouldWorkFunc should_work_func, SgenThreadPoolData **thread_datas);
-void sgen_thread_pool_shutdown (void);
+void sgen_thread_pool_shutdown (SgenThreadPool *pool);
SgenThreadPoolJob* sgen_thread_pool_job_alloc (const char *name, SgenThreadPoolJobFunc func, size_t size);
/* This only needs to be called on jobs that are not enqueued. */
void sgen_thread_pool_job_free (SgenThreadPoolJob *job);
-void sgen_thread_pool_job_enqueue (SgenThreadPoolJob *job);
+void sgen_thread_pool_job_enqueue (SgenThreadPool *pool, SgenThreadPoolJob *job);
/* This must only be called after the job has been enqueued. */
-void sgen_thread_pool_job_wait (SgenThreadPoolJob *job);
+void sgen_thread_pool_job_wait (SgenThreadPool *pool, SgenThreadPoolJob *job);
-void sgen_thread_pool_idle_signal (void);
-void sgen_thread_pool_idle_wait (void);
+void sgen_thread_pool_idle_signal (SgenThreadPool *pool);
+void sgen_thread_pool_idle_wait (SgenThreadPool *pool);
-void sgen_thread_pool_wait_for_all_jobs (void);
+void sgen_thread_pool_wait_for_all_jobs (SgenThreadPool *pool);
-int sgen_thread_pool_is_thread_pool_thread (MonoNativeThreadId thread);
+int sgen_thread_pool_is_thread_pool_thread (SgenThreadPool *pool, MonoNativeThreadId thread);
#endif
static WorkerData *workers_data;
static SgenWorkerCallback worker_init_cb;
+static SgenThreadPool pool_inst;
+static SgenThreadPool *pool; /* null if we're not using workers */
+
/*
* When using multiple workers, we need to have the last worker
* enqueue the preclean jobs (if there are any). This lock ensures
STATE_WORK_ENQUEUED
};
+#define SGEN_WORKER_MIN_SECTIONS_SIGNAL 4
+
typedef gint32 State;
static SgenObjectOperations * volatile idle_func_object_ops;
else if (new_state == STATE_WORKING)
SGEN_ASSERT (0, old_state == STATE_WORK_ENQUEUED, "We can only transition to WORKING from WORK ENQUEUED");
if (new_state == STATE_NOT_WORKING || new_state == STATE_WORKING)
- SGEN_ASSERT (6, sgen_thread_pool_is_thread_pool_thread (mono_native_thread_id_get ()), "Only the worker thread is allowed to transition to NOT_WORKING or WORKING");
+ SGEN_ASSERT (6, sgen_thread_pool_is_thread_pool_thread (pool, mono_native_thread_id_get ()), "Only the worker thread is allowed to transition to NOT_WORKING or WORKING");
return InterlockedCompareExchange (&data->state, new_state, old_state) == old_state;
}
}
if (need_signal)
- sgen_thread_pool_idle_signal ();
+ sgen_thread_pool_idle_signal (pool);
}
static void
return;
}
- sgen_thread_pool_job_enqueue (job);
+ sgen_thread_pool_job_enqueue (pool, job);
}
static gboolean
workers_get_work (WorkerData *data)
{
- SgenMajorCollector *major;
+ SgenMajorCollector *major = sgen_get_major_collector ();
+ SgenMinorCollector *minor = sgen_get_minor_collector ();
+ GrayQueueSection *section;
g_assert (sgen_gray_object_queue_is_empty (&data->private_gray_queue));
+ g_assert (major->is_concurrent || minor->is_parallel);
- /* If we're concurrent, steal from the workers distribute gray queue. */
- major = sgen_get_major_collector ();
- if (major->is_concurrent) {
- GrayQueueSection *section = sgen_section_gray_queue_dequeue (&workers_distribute_gray_queue);
- if (section) {
- sgen_gray_object_enqueue_section (&data->private_gray_queue, section, major->is_parallel);
- return TRUE;
- }
+ section = sgen_section_gray_queue_dequeue (&workers_distribute_gray_queue);
+ if (section) {
+ sgen_gray_object_enqueue_section (&data->private_gray_queue, section, major->is_parallel);
+ return TRUE;
}
/* Nobody to steal from */
workers_steal_work (WorkerData *data)
{
SgenMajorCollector *major = sgen_get_major_collector ();
+ SgenMinorCollector *minor = sgen_get_minor_collector ();
+ int generation = sgen_get_current_collection_generation ();
GrayQueueSection *section = NULL;
int i, current_worker;
- if (!major->is_parallel)
+ if ((generation == GENERATION_OLD && !major->is_parallel) ||
+ (generation == GENERATION_NURSERY && !minor->is_parallel))
return FALSE;
/* If we're parallel, steal from other workers' private gray queues */
{
WorkerData *data = (WorkerData *)data_untyped;
SgenMajorCollector *major = sgen_get_major_collector ();
+ SgenMinorCollector *minor = sgen_get_minor_collector ();
sgen_client_thread_register_worker ();
- if (!major->is_concurrent)
+ if (!major->is_concurrent && !minor->is_parallel)
return;
init_private_gray_queue (data);
WorkerData *data = (WorkerData *)data_untyped;
SGEN_ASSERT (0, continue_idle_func (data_untyped), "Why are we called when we're not supposed to work?");
- SGEN_ASSERT (0, sgen_concurrent_collection_in_progress (), "The worker should only mark in concurrent collections.");
if (data->state == STATE_WORK_ENQUEUED) {
set_state (data, STATE_WORK_ENQUEUED, STATE_WORKING);
sgen_drain_gray_stack (ctx);
- if (data->private_gray_queue.num_sections > 16 && workers_finished && worker_awakenings < active_workers_num) {
+ if (data->private_gray_queue.num_sections >= SGEN_WORKER_MIN_SECTIONS_SIGNAL
+ && workers_finished && worker_awakenings < active_workers_num) {
/* We bound the number of worker awakenings just to be sure */
worker_awakenings++;
mono_os_mutex_lock (&finished_lock);
void
sgen_workers_init_distribute_gray_queue (void)
{
- SGEN_ASSERT (0, sgen_get_major_collector ()->is_concurrent,
+ SGEN_ASSERT (0, sgen_get_major_collector ()->is_concurrent || sgen_get_minor_collector ()->is_parallel,
"Why should we init the distribute gray queue if we don't need it?");
init_distribute_gray_queue ();
}
sgen_workers_init (int num_workers, SgenWorkerCallback callback)
{
int i;
- void **workers_data_ptrs = (void **)alloca(num_workers * sizeof(void *));
-
- if (!sgen_get_major_collector ()->is_concurrent) {
- sgen_thread_pool_init (num_workers, thread_pool_init_func, NULL, NULL, NULL, NULL);
- return;
- }
+ WorkerData **workers_data_ptrs = (WorkerData**)alloca(num_workers * sizeof(WorkerData*));
mono_os_mutex_init (&finished_lock);
//g_print ("initing %d workers\n", num_workers);
init_distribute_gray_queue ();
for (i = 0; i < num_workers; ++i)
- workers_data_ptrs [i] = (void *) &workers_data [i];
+ workers_data_ptrs [i] = &workers_data [i];
worker_init_cb = callback;
- sgen_thread_pool_init (num_workers, thread_pool_init_func, marker_idle_func, continue_idle_func, should_work_func, workers_data_ptrs);
+ pool = &pool_inst;
+ sgen_thread_pool_init (pool, num_workers, thread_pool_init_func, marker_idle_func, continue_idle_func, should_work_func, (SgenThreadPoolData**)workers_data_ptrs);
mono_counters_register ("# workers finished", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_workers_num_finished);
}
+void
+sgen_workers_shutdown (void)
+{
+ if (pool)
+ sgen_thread_pool_shutdown (pool);
+}
+
void
sgen_workers_stop_all_workers (void)
{
mono_memory_write_barrier ();
forced_stop = TRUE;
- sgen_thread_pool_wait_for_all_jobs ();
- sgen_thread_pool_idle_wait ();
+ sgen_thread_pool_wait_for_all_jobs (pool);
+ sgen_thread_pool_idle_wait (pool);
SGEN_ASSERT (0, sgen_workers_all_done (), "Can only signal enqueue work when in no work state");
}
{
int i;
- sgen_thread_pool_wait_for_all_jobs ();
- sgen_thread_pool_idle_wait ();
+ sgen_thread_pool_wait_for_all_jobs (pool);
+ sgen_thread_pool_idle_wait (pool);
SGEN_ASSERT (0, sgen_workers_all_done (), "Can only signal enqueue work when in no work state");
/* At this point all the workers have stopped. */
callback (&workers_data [i]);
}
+gboolean
+sgen_workers_is_worker_thread (MonoNativeThreadId id)
+{
+ if (!pool)
+ return FALSE;
+ return sgen_thread_pool_is_thread_pool_thread (pool, id);
+}
+
#endif
typedef struct _WorkerData WorkerData;
struct _WorkerData {
+ /*
+ * Threadpool threads receive as their starting argument a WorkerData.
+ * tp_data is meant for use inside the sgen thread pool and must be first.
+ */
+ SgenThreadPoolData tp_data;
gint32 state;
SgenGrayQueue private_gray_queue; /* only read/written by worker thread */
/*
typedef void (*SgenWorkerCallback) (WorkerData *data);
void sgen_workers_init (int num_workers, SgenWorkerCallback callback);
+void sgen_workers_shutdown (void);
void sgen_workers_stop_all_workers (void);
void sgen_workers_set_num_active_workers (int num_workers);
void sgen_workers_start_all_workers (SgenObjectOperations *object_ops_nopar, SgenObjectOperations *object_ops_par, SgenWorkersFinishCallback finish_job);
SgenObjectOperations* sgen_workers_get_idle_func_object_ops (void);
int sgen_workers_get_job_split_count (void);
void sgen_workers_foreach (SgenWorkerCallback callback);
+gboolean sgen_workers_is_worker_thread (MonoNativeThreadId id);
#endif
#endif
}
g_strfreev (env_split);
+ g_free (env_string);
}
check_mode = env_check_mode;
static int transition_limit = -1;
if (transition_limit < 0) {
const gchar *env_string = g_getenv ("MONO_CHECK_THREAD_TRANSITION_HISTORY");
- if (env_string)
+ if (env_string) {
transition_limit = atoi (env_string);
- else
+ g_free (env_string);
+ } else {
transition_limit = 3;
+ }
}
return transition_limit;
}
void
mono_hwcap_init (void)
{
- const char *verbose = g_getenv ("MONO_VERBOSE_HWCAP");
- const char *conservative = g_getenv ("MONO_CONSERVATIVE_HWCAP");
+ char *verbose = g_getenv ("MONO_VERBOSE_HWCAP");
+ char *conservative = g_getenv ("MONO_CONSERVATIVE_HWCAP");
if (hwcap_inited)
return;
if (verbose && !strncmp (verbose, "1", 1))
mono_hwcap_print ();
+
+ g_free (verbose);
+ g_free (conservative);
}
void
void mono_portability_helpers_init (void)
{
- const gchar *env;
+ gchar *env;
if (mono_io_portability_helpers != PORTABILITY_UNKNOWN)
return;
mono_io_portability_helpers |= (PORTABILITY_DRIVE | PORTABILITY_CASE);
}
}
+ g_free (env);
}
}
pid_t pid;
char logTime [80];
-#ifndef HOST_WIN32
+#ifdef HAVE_LOCALTIME_R
struct tm tod;
time(&t);
localtime_r(&t, &tod);
- pid = getpid();
strftime(logTime, sizeof(logTime), "%Y-%m-%d %H:%M:%S", &tod);
#else
struct tm *tod;
time(&t);
tod = localtime(&t);
- pid = mono_process_current_pid ();
strftime(logTime, sizeof(logTime), "%F %T", tod);
#endif
+
+ pid = mono_process_current_pid ();
+
fprintf (logFile, "%s level[%c] mono[%d]: %s\n", logTime, mapLogFileLevel (level), pid, message);
} else {
fprintf (logFile, "%s%s%s\n",
mono_internal_current_level = G_LOG_LEVEL_ERROR;
level_stack = g_queue_new();
- mono_trace_set_mask_string(g_getenv("MONO_LOG_MASK"));
- mono_trace_set_level_string(g_getenv("MONO_LOG_LEVEL"));
- mono_trace_set_logheader_string(g_getenv("MONO_LOG_HEADER"));
- mono_trace_set_logdest_string(g_getenv("MONO_LOG_DEST"));
+ char *mask = g_getenv ("MONO_LOG_MASK");
+ char *level = g_getenv ("MONO_LOG_LEVEL");
+ char *header = g_getenv ("MONO_LOG_HEADER");
+ char *dest = g_getenv ("MONO_LOG_DEST");
+
+ mono_trace_set_mask_string(mask);
+ mono_trace_set_level_string(level);
+ mono_trace_set_logheader_string(header);
+ mono_trace_set_logdest_string(dest);
+
+ g_free (mask);
+ g_free (level);
+ g_free (header);
+ g_free (dest);
}
}
shared_area_disabled (void)
{
if (!use_shared_area) {
- if (g_getenv ("MONO_DISABLE_SHARED_AREA"))
+ if (g_hasenv ("MONO_DISABLE_SHARED_AREA"))
use_shared_area = -1;
else
use_shared_area = 1;
file = open (NAME_DEV_RANDOM, O_RDONLY);
#endif
if (file < 0)
- use_egd = g_getenv("MONO_EGD_SOCKET") != NULL;
+ use_egd = g_hasenv ("MONO_EGD_SOCKET");
status = 2;
error_init (error);
if (use_egd) {
- const char *socket_path = g_getenv ("MONO_EGD_SOCKET");
+ char *socket_path = g_getenv ("MONO_EGD_SOCKET");
/* exception will be thrown in managed code */
if (socket_path == NULL) {
*handle = NULL;
return FALSE;
}
get_entropy_from_egd (socket_path, buffer, buffer_size, error);
+ g_free (socket_path);
} else {
/* Read until the buffer is filled. This may block if using NAME_DEV_RANDOM. */
gint count = 0;
#else
static int is_coop_enabled = -1;
if (G_UNLIKELY (is_coop_enabled == -1))
- is_coop_enabled = g_getenv ("MONO_ENABLE_COOP") != NULL ? 1 : 0;
+ is_coop_enabled = g_hasenv ("MONO_ENABLE_COOP") ? 1 : 0;
return is_coop_enabled == 1;
#endif
}
gboolean res;
threads_callbacks = *callbacks;
thread_info_size = info_size;
- const char *sleepLimit;
+ char *sleepLimit;
#ifdef HOST_WIN32
res = mono_native_tls_alloc (&thread_info_key, NULL);
res = mono_native_tls_alloc (&thread_exited_key, NULL);
sleepWarnDuration = threshold / 20;
} else
g_warning("MONO_SLEEP_ABORT_LIMIT must be a number >= 40");
+ g_free (sleepLimit);
}
mono_os_sem_init (&global_suspend_semaphore, 1);
{
gchar *res=NULL;
gchar **encodings;
- const gchar *encoding_list;
+ gchar *encoding_list;
int i;
glong lbytes;
encoding_list=g_getenv ("MONO_EXTERNAL_ENCODINGS");
if(encoding_list==NULL) {
- encoding_list = "";
+ encoding_list = g_strdup("");
}
encodings=g_strsplit (encoding_list, ":", 0);
+ g_free (encoding_list);
for(i=0;encodings[i]!=NULL; i++) {
/* "default_locale" is a special case encoding */
if(!strcmp (encodings[i], "default_locale")) {
{
gchar *res=NULL;
gchar **encodings;
- const gchar *encoding_list;
+ gchar *encoding_list;
int i;
if(in==NULL) {
encoding_list=g_getenv ("MONO_EXTERNAL_ENCODINGS");
if(encoding_list==NULL) {
- encoding_list = "";
+ encoding_list = g_strdup("");
}
encodings=g_strsplit (encoding_list, ":", 0);
+ g_free (encoding_list);
for(i=0;encodings[i]!=NULL; i++) {
/* "default_locale" is a special case encoding */
gchar *mono_unicode_to_external (const gunichar2 *uni)
{
gchar *utf8;
- const gchar *encoding_list;
+ gchar *encoding_list;
/* Turn the unicode into utf8 to start with, because its
* easier to work with gchar * than gunichar2 *
int i;
encodings=g_strsplit (encoding_list, ":", 0);
+ g_free (encoding_list);
for(i=0; encodings[i]!=NULL; i++) {
if(!strcmp (encodings[i], "default_locale")) {
res=g_locale_from_utf8 (utf8, -1, NULL, NULL,
export TESTCMD=`dirname "${BASH_SOURCE[0]}"`/run-step.sh
${TESTCMD} --label=interpreter-regression --timeout=10m make -C mono/mini richeck
+${TESTCMD} --label=mixedmode-regression --timeout=10m make -C mono/mini mixedcheck
${TESTCMD} --label=compile-runtime-tests --timeout=40m make -w -C mono/tests -j4 tests
${TESTCMD} --label=runtime-interp --timeout=160m make -w -C mono/tests -k testinterp V=1