From 1e726ce7a38a92860acab28f4427813d2ba14c13 Mon Sep 17 00:00:00 2001 From: Elijah Taylor Date: Thu, 31 Jan 2013 12:04:20 -0800 Subject: [PATCH] NaCl runtime fixes - fix compile/runtime issues caused by upstream changes - add NaCl glibc support - various changes to support running tests in NaCl glibc from 'make check' --- configure.in | 30 +++- eglib/src/eglib-config.h.in | 3 - eglib/src/gfile-posix.c | 10 ++ eglib/src/gmodule-unix.c | 42 +---- ikvm-native/os.c | 5 + libgc/dyn_load.c | 10 +- libgc/include/private/gcconfig.h | 59 +++---- libgc/misc.c | 12 ++ libgc/pthread_stop_world.c | 12 +- libgc/pthread_support.c | 24 ++- mono/dis/dump.c | 5 + mono/io-layer/io.c | 29 ++++ mono/io-layer/shared.c | 2 +- mono/metadata/appdomain.c | 3 + mono/metadata/assembly.c | 6 +- mono/metadata/boehm-gc.c | 2 +- mono/metadata/decimal.c | 7 +- mono/metadata/gc.c | 4 + mono/metadata/icall.c | 12 ++ mono/metadata/nacl-stub.c | 31 ++++ mono/metadata/null-gc.c | 3 + mono/metadata/rand.c | 2 + mono/metadata/threads.c | 8 + mono/mini/Makefile.am.in | 16 +- mono/mini/aot-runtime.c | 2 + mono/mini/arrays.cs | 4 +- mono/mini/basic-calls.cs | 4 +- mono/mini/basic-float.cs | 4 +- mono/mini/basic-long.cs | 4 +- mono/mini/basic-math.cs | 4 +- mono/mini/basic.cs | 6 +- mono/mini/driver.c | 11 +- mono/mini/exceptions.cs | 6 +- mono/mini/fsacheck.c | 269 ------------------------------- mono/mini/genmdesc.c | 5 + mono/mini/helpers.c | 3 + mono/mini/ldscript | 3 + mono/mini/mini-amd64.h | 10 +- mono/mini/mini-gc.c | 4 + mono/mini/mini-posix.c | 10 ++ mono/mini/mini.c | 7 + mono/mini/mini.h | 7 + mono/mini/nacl.cs | 146 +++++++++++++---- mono/mini/objects.cs | 4 +- mono/mini/regalloc.h | 5 +- mono/mini/wapihandles.c | 2 +- mono/monograph/monograph.c | 7 +- mono/profiler/Makefile.am | 4 + mono/profiler/decode.c | 5 + mono/tests/Makefile.am | 102 ++++++++++++ mono/utils/mono-codeman.c | 26 +-- mono/utils/mono-context.c | 4 + mono/utils/mono-mmap.c | 15 ++ mono/utils/mono-path.c | 5 - mono/utils/mono-threads-posix.c | 3 + mono/utils/monobitset.c | 9 +- runtime/Makefile.am | 4 + runtime/mono-wrapper.in | 9 ++ 58 files changed, 607 insertions(+), 443 deletions(-) delete mode 100644 mono/mini/fsacheck.c diff --git a/configure.in b/configure.in index b400832a1dd..72ad17034e3 100644 --- a/configure.in +++ b/configure.in @@ -1074,6 +1074,8 @@ AC_TRY_COMPILE([ AC_DEFINE_UNQUOTED(MONO_ZERO_LEN_ARRAY, 1, [Length of zero length arrays]) ]) +AC_CHECK_HEADERS(nacl/nacl_dyncode.h) + if test x$target_win32 = xno; then dnl hires monotonic clock support @@ -1784,11 +1786,13 @@ if test x$target_win32 = xno; then dnl ********************************** dnl *** epoll *** dnl ********************************** - AC_CHECK_HEADERS(sys/epoll.h) - haveepoll=no - AC_CHECK_FUNCS(epoll_ctl, [haveepoll=yes], ) - if test "x$haveepoll" = "xyes" -a "x$ac_cv_header_sys_epoll_h" = "xyes" ; then - AC_DEFINE(HAVE_EPOLL, 1, [epoll supported]) + if test "x$ac_cv_header_nacl_nacl_dyncode_h" = "xno"; then + AC_CHECK_HEADERS(sys/epoll.h) + haveepoll=no + AC_CHECK_FUNCS(epoll_ctl, [haveepoll=yes], ) + if test "x$haveepoll" = "xyes" -a "x$ac_cv_header_sys_epoll_h" = "xyes"; then + AC_DEFINE(HAVE_EPOLL, 1, [epoll supported]) + fi fi havekqueue=no @@ -2304,6 +2308,16 @@ AC_ARG_ENABLE(nacl_codegen, [ --enable-nacl-codegen Enable Native Client c AC_ARG_ENABLE(nacl_gc, [ --enable-nacl-gc Enable Native Client garbage collection], enable_nacl_gc=$enableval, enable_nacl_gc=no) AM_CONDITIONAL(NACL_CODEGEN, test x$enable_nacl_codegen != xno) + +dnl +dnl Hack to use system mono for operations in build/install not allowed in NaCl. +dnl +nacl_self_host="" +if test "x$ac_cv_header_nacl_nacl_dyncode_h" = "xyes"; then + nacl_self_host="nacl_self_host" +fi +AC_SUBST(nacl_self_host) + if test "x$enable_nacl_codegen" = "xyes"; then MONO_NACL_ALIGN_MASK_OFF=1 CPPFLAGS="$CPPFLAGS -D__native_client_codegen__" @@ -2472,6 +2486,10 @@ case "$host" in TARGET=AMD64; arch_target=amd64; JIT_SUPPORTED=yes + if test "x$ac_cv_sizeof_void_p" = "x4"; then + AC_DEFINE(__mono_ilp32__, 1, [64 bit mode with 4 byte longs and pointers]) + sizeof_register=8 + fi case $host_os in linux*) sgen_supported=true @@ -2632,7 +2650,7 @@ if test "x$host" != "x$target"; then AC_DEFINE(__mono_ilp32__, 1, [64 bit mode with 4 byte longs and pointers]) sizeof_register=8 ;; - *-*-nacl) + i686-*-nacl) TARGET=X86 arch_target=x86 AC_DEFINE(TARGET_X86, 1, [...]) diff --git a/eglib/src/eglib-config.h.in b/eglib/src/eglib-config.h.in index 19e4f4d59e2..ba0f93f9be5 100644 --- a/eglib/src/eglib-config.h.in +++ b/eglib/src/eglib-config.h.in @@ -37,9 +37,6 @@ typedef signed @GSIZE@ gssize; #endif #if defined (__native_client__) -#define sem_trywait(x) sem_wait(x) -#define sem_timedwait(x,y) sem_wait(x) -#define getdtablesize() (32768) #undef G_BREAKPOINT #define G_BREAKPOINT() #endif diff --git a/eglib/src/gfile-posix.c b/eglib/src/gfile-posix.c index 48a9192ab69..d52ad948802 100644 --- a/eglib/src/gfile-posix.c +++ b/eglib/src/gfile-posix.c @@ -154,6 +154,15 @@ g_file_open_tmp (const gchar *tmpl, gchar **name_used, GError **error) gchar * g_get_current_dir (void) { +#ifdef __native_client__ + char *buffer; + if ((buffer = getenv("NACL_PWD"))) { + buffer = g_strdup(buffer); + } else { + buffer = g_strdup("."); + } + return buffer; +#else int s = 32; char *buffer = NULL, *r; gboolean fail; @@ -172,4 +181,5 @@ g_get_current_dir (void) * so we return the buffer here since it has a pointer to the valid string */ return buffer; +#endif } diff --git a/eglib/src/gmodule-unix.c b/eglib/src/gmodule-unix.c index 87eb27aef2a..9dd5eaa3d54 100644 --- a/eglib/src/gmodule-unix.c +++ b/eglib/src/gmodule-unix.c @@ -28,46 +28,12 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include + #include #include -#if defined(__native_client__) -GModule * -g_module_open (const gchar *file, GModuleFlags flags) -{ - printf("dlopen() not supported on Native Client.\n"); - return NULL; -} - - -gboolean -g_module_symbol (GModule *module, const gchar *symbol_name, gpointer *symbol) -{ - return FALSE; -} - - -const gchar* -g_module_error(void) -{ - return "dlopen not supported on Native Client."; -} - -gboolean -g_module_close (GModule *module) -{ - return FALSE; -} - -gchar* -g_module_build_path (const gchar *directory, const gchar *module_name) -{ - return NULL; -} - -#else - -#ifdef G_OS_UNIX +#if defined(G_OS_UNIX) && defined(HAVE_DLFCN_H) #include /* For Linux and Solaris, need to add others as we port this */ @@ -322,5 +288,3 @@ g_module_build_path (const gchar *directory, const gchar *module_name) return g_strdup_printf ("%s%s" LIBSUFFIX, lib_prefix, module_name); } -#endif /* __native_client__ */ - diff --git a/ikvm-native/os.c b/ikvm-native/os.c index 65d49e2a2ae..9f2115f712b 100644 --- a/ikvm-native/os.c +++ b/ikvm-native/os.c @@ -95,6 +95,11 @@ JNIEXPORT int JNICALL ikvm_msync(void* address, jint size) { +#if defined(__native_client__) && defined(USE_NEWLIB) + g_assert_not_reached (); + return -1; +#else return msync(address, size, MS_SYNC); +#endif } #endif diff --git a/libgc/dyn_load.c b/libgc/dyn_load.c index e4be3c7d183..ca7ce54f194 100644 --- a/libgc/dyn_load.c +++ b/libgc/dyn_load.c @@ -26,7 +26,7 @@ * None of this is safe with dlclose and incremental collection. * But then not much of anything is safe in the presence of dlclose. */ -#if defined(__linux__) && !defined(_GNU_SOURCE) +#if (defined(__linux__) || defined(__native_client__)) && !defined(_GNU_SOURCE) /* Can't test LINUX, since this must be define before other includes */ # define _GNU_SOURCE #endif @@ -54,7 +54,7 @@ #if !defined(SUNOS4) && !defined(SUNOS5DL) && !defined(IRIX5) && \ !defined(MSWIN32) && !defined(MSWINCE) && \ !(defined(ALPHA) && defined(OSF1)) && \ - !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \ + !defined(HPUX) && !((defined(LINUX) || defined(NACL)) && defined(__ELF__)) && \ !defined(RS6000) && !defined(SCO_ELF) && !defined(DGUX) && \ !(defined(FREEBSD) && defined(__ELF__)) && \ !(defined(OPENBSD) && (defined(__ELF__) || defined(M68K))) && \ @@ -91,7 +91,7 @@ # define ELFSIZE ARCH_ELFSIZE #endif -#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \ +#if (defined(LINUX) || defined(NACL)) && defined(__ELF__) || defined(SCO_ELF) || \ (defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \ (defined(OPENBSD) && defined(__ELF__)) || \ (defined(NETBSD) && defined(__ELF__)) || defined(HURD) @@ -297,7 +297,7 @@ void GC_register_dynamic_libraries() # endif /* !USE_PROC ... */ # endif /* SUNOS */ -#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \ +#if (defined(LINUX) || defined(NACL)) && defined(__ELF__) || defined(SCO_ELF) || \ (defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \ (defined(OPENBSD) && defined(__ELF__)) || \ (defined(NETBSD) && defined(__ELF__)) || defined(HURD) @@ -394,7 +394,7 @@ GC_bool GC_register_main_static_data() /* For glibc 2.2.4+. Unfortunately, it doesn't work for older */ /* versions. Thanks to Jakub Jelinek for most of the code. */ -# if defined(LINUX) /* Are others OK here, too? */ \ +# if (defined(LINUX) || defined(NACL)) /* Are others OK here, too? */ \ && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \ || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG))) diff --git a/libgc/include/private/gcconfig.h b/libgc/include/private/gcconfig.h index ec53e3a95ea..49ffccddf50 100644 --- a/libgc/include/private/gcconfig.h +++ b/libgc/include/private/gcconfig.h @@ -67,8 +67,12 @@ /* Determine the machine type: */ # if defined(__native_client__) # define NACL -# define I386 -# define mach_type_known +# if !defined(__portable_native_client__) +# define I386 +# define mach_type_known +# else + /* Here we will rely upon arch-specific defines. */ +# endif # endif # if defined(__arm__) || defined(__thumb__) # define ARM32 @@ -928,6 +932,30 @@ # endif # endif + +# ifdef NACL +# define OS_TYPE "NACL" +# if defined(__GLIBC__) +# define DYNAMIC_LOADING +# endif +# define DATASTART ((ptr_t)0x10020000) + extern int _end[]; +# define DATAEND (_end) +# ifdef STACK_GRAN +# undef STACK_GRAN +# endif /* STACK_GRAN */ +# define STACK_GRAN 0x10000 +# define HEURISTIC1 +# define USE_MMAP +# define USE_MUNMAP +# define USE_MMAP_ANON +# ifdef USE_MMAP_FIXED +# undef USE_MMAP_FIXED +# endif +# define GETPAGESIZE() 65536 +# define MAX_NACL_GC_THREADS 1024 +# endif + # ifdef VAX # define MACH_TYPE "VAX" # define ALIGNMENT 4 /* Pointers are longword aligned by 4.2 C compiler */ @@ -1204,33 +1232,6 @@ # define HEAP_START DATAEND # endif /* USE_MMAP */ # endif /* DGUX */ -# ifdef NACL -# define OS_TYPE "NACL" - extern int etext[]; -//# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff)) -# define DATASTART ((ptr_t)0x10000000) - extern int _end[]; -# define DATAEND (_end) -# ifdef STACK_GRAN -# undef STACK_GRAN -# endif /* STACK_GRAN */ -# define STACK_GRAN 0x10000 -# define HEURISTIC1 -# ifdef USE_MMAP -# undef USE_MMAP -# endif -# ifdef USE_MUNMAP -# undef USE_MUNMAP -# endif -# ifdef USE_MMAP_ANON -# undef USE_MMAP_ANON -# endif -# ifdef USE_MMAP_FIXED -# undef USE_MMAP_FIXED -# endif -# define GETPAGESIZE() 65536 -# define MAX_NACL_GC_THREADS 1024 -# endif # ifdef LINUX # ifndef __GNUC__ /* The Intel compiler doesn't like inline assembly */ diff --git a/libgc/misc.c b/libgc/misc.c index 5b2868d808b..53d47c53dbc 100644 --- a/libgc/misc.c +++ b/libgc/misc.c @@ -1003,7 +1003,11 @@ long a, b, c, d, e, f; buf[1024] = 0x15; (void) sprintf(buf, format, a, b, c, d, e, f); if (buf[1024] != 0x15) ABORT("GC_printf clobbered stack"); +#ifdef NACL + WRITE(GC_stdout, buf, strlen(buf)); +#else if (WRITE(GC_stdout, buf, strlen(buf)) < 0) ABORT("write to stdout failed"); +#endif } void GC_err_printf(format, a, b, c, d, e, f) @@ -1015,13 +1019,21 @@ long a, b, c, d, e, f; buf[1024] = 0x15; (void) sprintf(buf, format, a, b, c, d, e, f); if (buf[1024] != 0x15) ABORT("GC_err_printf clobbered stack"); +#ifdef NACL + WRITE(GC_stderr, buf, strlen(buf)); +#else if (WRITE(GC_stderr, buf, strlen(buf)) < 0) ABORT("write to stderr failed"); +#endif } void GC_err_puts(s) GC_CONST char *s; { +#ifdef NACL + WRITE(GC_stderr, s, strlen(s)); +#else if (WRITE(GC_stderr, s, strlen(s)) < 0) ABORT("write to stderr failed"); +#endif } #if defined(LINUX) && !defined(SMALL_CONFIG) diff --git a/libgc/pthread_stop_world.c b/libgc/pthread_stop_world.c index 05e897fb739..8b25376b54a 100644 --- a/libgc/pthread_stop_world.c +++ b/libgc/pthread_stop_world.c @@ -24,7 +24,7 @@ #endif #ifdef NACL -int nacl_park_threads_now = 0; +volatile int __nacl_thread_suspension_needed = 0; pthread_t nacl_thread_parker = -1; volatile int nacl_thread_parked[MAX_NACL_GC_THREADS]; @@ -471,7 +471,7 @@ static void pthread_stop_world() GC_printf1("pthread_stop_world: num_threads %d\n", nacl_num_gc_threads - 1); #endif nacl_thread_parker = pthread_self(); - nacl_park_threads_now = 1; + __nacl_thread_suspension_needed = 1; while (1) { #define NACL_PARK_WAIT_NANOSECONDS 100000 @@ -549,6 +549,8 @@ void nacl_pre_syscall_hook() } } +void __nacl_suspend_thread_if_needed(); + void nacl_post_syscall_hook() { /* Calling __nacl_suspend_thread_if_needed() right away should guarantee we don't mutate the GC set. */ @@ -559,7 +561,7 @@ void nacl_post_syscall_hook() } void __nacl_suspend_thread_if_needed() { - if (nacl_park_threads_now) { + if (__nacl_thread_suspension_needed) { pthread_t self = pthread_self(); int local_dummy = 0; /* Don't try to park the thread parker. */ @@ -578,7 +580,7 @@ void __nacl_suspend_thread_if_needed() { nacl_gc_thread_self->stop_info.stack_ptr = (ptr_t)(&local_dummy); } nacl_thread_parked[nacl_thread_idx] = 1; - while (nacl_park_threads_now) + while (__nacl_thread_suspension_needed) ; /* spin */ nacl_thread_parked[nacl_thread_idx] = 0; @@ -688,7 +690,7 @@ static void pthread_start_world() # if DEBUG_THREADS GC_printf0("World starting\n"); # endif - nacl_park_threads_now = 0; + __nacl_thread_suspension_needed = 0; if (GC_notify_event) GC_notify_event (GC_EVENT_POST_START_WORLD); #endif /* NACL */ diff --git a/libgc/pthread_support.c b/libgc/pthread_support.c index 50241e44bf8..b302688a76e 100644 --- a/libgc/pthread_support.c +++ b/libgc/pthread_support.c @@ -699,10 +699,20 @@ extern void nacl_pre_syscall_hook(); extern void nacl_post_syscall_hook(); extern void nacl_register_gc_hooks(void (*pre)(), void (*post)()); +#include + +struct nacl_irt_blockhook { + int (*register_block_hooks)(void (*pre)(void), void (*post)(void)); +}; + +extern size_t nacl_interface_query(const char *interface_ident, + void *table, size_t tablesize); + void nacl_initialize_gc_thread() { int i; - nacl_register_gc_hooks(nacl_pre_syscall_hook, nacl_post_syscall_hook); + static struct nacl_irt_blockhook gc_hook; + pthread_mutex_lock(&nacl_thread_alloc_lock); if (!nacl_thread_parking_inited) { @@ -710,6 +720,10 @@ void nacl_initialize_gc_thread() nacl_thread_used[i] = 0; nacl_thread_parked[i] = 0; } + // TODO: replace with public 'register hook' function when + // available from glibc + nacl_interface_query("nacl-irt-blockhook-0.1", &gc_hook, sizeof(gc_hook)); + gc_hook.register_block_hooks(nacl_pre_syscall_hook, nacl_post_syscall_hook); nacl_thread_parking_inited = 1; } GC_ASSERT(nacl_num_gc_threads <= MAX_NACL_GC_THREADS); @@ -942,6 +956,7 @@ int GC_segment_is_thread_stack(ptr_t lo, ptr_t hi) /* Return the number of processors, or i<= 0 if it can't be determined. */ int GC_get_nprocs() { +#ifndef NACL /* Should be "return sysconf(_SC_NPROCESSORS_ONLN);" but that */ /* appears to be buggy in many cases. */ /* We look for lines "cpu" in /proc/stat. */ @@ -971,6 +986,9 @@ int GC_get_nprocs() } close(f); return result; +#else /* NACL */ + return sysconf(_SC_NPROCESSORS_ONLN); +#endif } #endif /* GC_LINUX_THREADS */ @@ -1362,12 +1380,10 @@ int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval) } #ifdef NACL -/* Native Client doesn't support pthread cleanup functions, */ -/* so wrap pthread_exit and manually cleanup the thread. */ +/* TODO: remove, NaCl glibc now supports pthread cleanup functions. */ void WRAP_FUNC(pthread_exit)(void *status) { - GC_thread_exit_proc(0); REAL_FUNC(pthread_exit)(status); } #endif diff --git a/mono/dis/dump.c b/mono/dis/dump.c index 327218e1686..72e528d2e31 100644 --- a/mono/dis/dump.c +++ b/mono/dis/dump.c @@ -29,6 +29,11 @@ extern int isinf (double); #endif +#if defined(__native_client__) && defined(__GLIBC__) +volatile int __nacl_thread_suspension_needed = 0; +void __nacl_suspend_thread_if_needed() {} +#endif + void dump_table_assembly (MonoImage *m) { diff --git a/mono/io-layer/io.c b/mono/io-layer/io.c index 3e61f0cfbbd..a3e5ad15b56 100755 --- a/mono/io-layer/io.c +++ b/mono/io-layer/io.c @@ -708,6 +708,8 @@ static gboolean file_setendoffile(gpointer handle) } #endif +/* Native Client has no ftruncate function, even in standalone sel_ldr. */ +#ifndef __native_client__ /* always truncate, because the extend write() adds an extra * byte to the end of the file */ @@ -722,6 +724,7 @@ static gboolean file_setendoffile(gpointer handle) _wapi_set_last_error_from_errno (); return(FALSE); } +#endif return(TRUE); } @@ -1512,6 +1515,13 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess, return(INVALID_HANDLE_VALUE); } +#ifdef __native_client__ + /* Workaround: Native Client currently returns the same fake inode + * for all files, so do a simple hash on the filename so we don't + * use the same share info for each file. + */ + statbuf.st_ino = g_str_hash(filename); +#endif if (share_check (&statbuf, sharemode, fileaccess, &file_handle.share_info, fd) == FALSE) { @@ -2746,6 +2756,7 @@ retry: goto retry; } +#ifndef __native_client__ result = _wapi_lstat (filename, &linkbuf); if (result != 0) { DEBUG ("%s: lstat failed: %s", __func__, filename); @@ -2753,6 +2764,7 @@ retry: g_free (filename); goto retry; } +#endif utf8_filename = mono_utf8_from_external (filename); if (utf8_filename == NULL) { @@ -2776,7 +2788,11 @@ retry: else create_time = buf.st_ctime; +#ifdef __native_client__ + find_data->dwFileAttributes = _wapi_stat_to_file_attributes (utf8_filename, &buf, NULL); +#else find_data->dwFileAttributes = _wapi_stat_to_file_attributes (utf8_filename, &buf, &linkbuf); +#endif _wapi_time_t_to_filetime (create_time, &find_data->ftCreationTime); _wapi_time_t_to_filetime (buf.st_atime, &find_data->ftLastAccessTime); @@ -2999,14 +3015,20 @@ guint32 GetFileAttributes (const gunichar2 *name) return (INVALID_FILE_ATTRIBUTES); } +#ifndef __native_client__ result = _wapi_lstat (utf8_name, &linkbuf); if (result != 0) { _wapi_set_last_path_error_from_errno (NULL, utf8_name); g_free (utf8_name); return (INVALID_FILE_ATTRIBUTES); } +#endif +#ifdef __native_client__ + ret = _wapi_stat_to_file_attributes (utf8_name, &buf, NULL); +#else ret = _wapi_stat_to_file_attributes (utf8_name, &buf, &linkbuf); +#endif g_free (utf8_name); @@ -3203,6 +3225,12 @@ extern guint32 GetCurrentDirectory (guint32 length, gunichar2 *buffer) glong count; gsize bytes; +#ifdef __native_client__ + gchar *path = g_get_current_dir (); + if (length < strlen(path) + 1 || path == NULL) + return 0; + memcpy (buffer, path, strlen(path) + 1); +#else if (getcwd ((char*)buffer, length) == NULL) { if (errno == ERANGE) { /*buffer length is not big enough */ gchar *path = g_get_current_dir (); /*FIXME g_get_current_dir doesn't work with broken paths and calling it just to know the path length is silly*/ @@ -3216,6 +3244,7 @@ extern guint32 GetCurrentDirectory (guint32 length, gunichar2 *buffer) _wapi_set_last_error_from_errno (); return 0; } +#endif utf16_path = mono_unicode_from_external ((gchar*)buffer, &bytes); count = (bytes/2)+1; diff --git a/mono/io-layer/shared.c b/mono/io-layer/shared.c index 9e70e8c5aec..ed9bb1fb211 100644 --- a/mono/io-layer/shared.c +++ b/mono/io-layer/shared.c @@ -18,7 +18,7 @@ #include #include -#ifdef HAVE_SYS_SEM_H +#if defined(HAVE_SYS_SEM_H) && !(defined(__native_client__) && defined(__GLIBC__)) # include #else # define DISABLE_SHARED_HANDLES diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c index 88d8267c865..31725457da0 100644 --- a/mono/metadata/appdomain.c +++ b/mono/metadata/appdomain.c @@ -2012,6 +2012,9 @@ ves_icall_System_AppDomain_InternalUnload (gint32 domain_id) */ if (g_getenv ("MONO_NO_UNLOAD")) return; +#ifdef __native_client__ + return; +#endif mono_domain_unload (domain); } diff --git a/mono/metadata/assembly.c b/mono/metadata/assembly.c index d43c107c09f..2d055726440 100644 --- a/mono/metadata/assembly.c +++ b/mono/metadata/assembly.c @@ -255,10 +255,10 @@ static void check_path_env (void) { const char* path; -#ifdef __native_client__ - path = nacl_mono_path; -#else path = g_getenv ("MONO_PATH"); +#ifdef __native_client__ + if (!path) + path = nacl_mono_path; #endif if (!path || assemblies_path != NULL) return; diff --git a/mono/metadata/boehm-gc.c b/mono/metadata/boehm-gc.c index d9d9b4e455d..9e5ab87ac9c 100644 --- a/mono/metadata/boehm-gc.c +++ b/mono/metadata/boehm-gc.c @@ -74,7 +74,7 @@ mono_gc_base_init (void) * we used to do this only when running on valgrind, * but it happens also in other setups. */ -#if defined(HAVE_PTHREAD_GETATTR_NP) && defined(HAVE_PTHREAD_ATTR_GETSTACK) +#if defined(HAVE_PTHREAD_GETATTR_NP) && defined(HAVE_PTHREAD_ATTR_GETSTACK) && !defined(__native_client__) { size_t size; void *sstart; diff --git a/mono/metadata/decimal.c b/mono/metadata/decimal.c index a923ff70eb7..0e6a7b3df1c 100644 --- a/mono/metadata/decimal.c +++ b/mono/metadata/decimal.c @@ -552,11 +552,15 @@ DECINLINE static void rshift192(guint64* pclo, guint64* pcmi, guint64* pchi) *pchi >>= 1; } +#if defined(__native_client__) && (defined(__i386__) || defined(__x86_64)) +#define USE_X86_32BIT_INSTRUCTIONS 1 +#endif + static inline gint my_g_bit_nth_msf (gsize mask) { /* Mask is expected to be != 0 */ -#if defined(__i386__) && defined(__GNUC__) +#if (defined(__i386__) && defined(__GNUC__)) || defined(USE_X86_32BIT_INSTRUCTIONS) int r; __asm__("bsrl %1,%0\n\t" @@ -1580,4 +1584,3 @@ gint32 mono_decimalSetExponent(/*[In, Out]*/decimal_repr* pA, gint32 texp) } #endif /* DISABLE_DECIMAL */ - diff --git a/mono/metadata/gc.c b/mono/metadata/gc.c index 5b036f43383..5d0584bb810 100644 --- a/mono/metadata/gc.c +++ b/mono/metadata/gc.c @@ -342,6 +342,10 @@ mono_domain_finalize (MonoDomain *domain, guint32 timeout) HANDLE done_event; MonoInternalThread *thread = mono_thread_internal_current (); +#if defined(__native_client__) + return FALSE; +#endif + if (mono_thread_internal_current () == gc_thread) /* We are called from inside a finalizer, not much we can do here */ return FALSE; diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index 72ff703939f..0bfe73bd4b7 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -6531,6 +6531,11 @@ ves_icall_System_Environment_Exit (int result) { MONO_ARCH_SAVE_REGS; +/* FIXME: There are some cleanup hangs that should be worked out, but + * if the program is going to exit, everything will be cleaned up when + * NaCl exits anyway. + */ +#ifndef __native_client__ mono_runtime_shutdown (); /* This will kill the tp threads which cannot be suspended */ @@ -6540,6 +6545,7 @@ ves_icall_System_Environment_Exit (int result) mono_thread_suspend_all_other_threads (); mono_runtime_quit (); +#endif /* we may need to do some cleanup here... */ exit (result); @@ -7214,6 +7220,12 @@ mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter) iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1)); #endif res.value = iter->args; +#if defined(__native_client__) && SIZEOF_REGISTER == 8 + /* Values are stored as 8 byte register sized objects, but 'value' + * is dereferenced as a pointer in other routines. + */ + res.value = (char*)res.value + 4; +#endif #if G_BYTE_ORDER != G_LITTLE_ENDIAN if (arg_size <= sizeof (gpointer)) { int dummy; diff --git a/mono/metadata/nacl-stub.c b/mono/metadata/nacl-stub.c index 83494def459..a1a3514f4fe 100644 --- a/mono/metadata/nacl-stub.c +++ b/mono/metadata/nacl-stub.c @@ -13,4 +13,35 @@ struct group *getgrgid(gid_t gid) { errno=EIO; return NULL; } int fsync(int fd) { errno=EINVAL; return -1; } dev_t makedev(guint32 maj, guint32 min) { return (maj)*256+(min); } +#ifdef USE_NEWLIB +int getdtablesize(void) { +#ifdef OPEN_MAX + return OPEN_MAX; +#else + return 256; +#endif +} + +size_t getpagesize(void) { +#ifdef PAGE_SIZE + return PAGE_SIZE; +#else + return 4096; +#endif +} + +#include + +int sem_trywait(sem_t *sem) { + g_assert_not_reached (); + return -1; +} + +int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout) { + g_assert_not_reached (); + return -1; +} + +#endif + #endif diff --git a/mono/metadata/null-gc.c b/mono/metadata/null-gc.c index 47d541594cf..4076d65d183 100644 --- a/mono/metadata/null-gc.c +++ b/mono/metadata/null-gc.c @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef HAVE_NULL_GC @@ -22,6 +23,8 @@ mono_gc_base_init (void) memset (&cb, 0, sizeof (cb)); cb.mono_method_is_critical = mono_runtime_is_critical_method; cb.mono_gc_pthread_create = (gpointer)mono_gc_pthread_create; + + mono_threads_init (&cb, sizeof (MonoThreadInfo)); } void diff --git a/mono/metadata/rand.c b/mono/metadata/rand.c index 97b264b6a31..4ed1203f85d 100644 --- a/mono/metadata/rand.c +++ b/mono/metadata/rand.c @@ -182,6 +182,8 @@ ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngClose (gpoint #elif defined (__native_client__) +#include + MonoBoolean ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngOpen (void) { diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index 6d582f15e85..ad6e0b2a310 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -3475,6 +3475,10 @@ collect_appdomain_thread (gpointer key, gpointer value, gpointer user_data) gboolean mono_threads_abort_appdomain_threads (MonoDomain *domain, int timeout) { +#ifdef __native_client__ + return FALSE; +#endif + abort_appdomain_data user_data; guint32 start_time; int orig_timeout = timeout; @@ -4450,6 +4454,10 @@ mono_runtime_has_tls_get (void) int mono_thread_kill (MonoInternalThread *thread, int signal) { +#ifdef __native_client__ + /* Workaround pthread_kill abort() in NaCl glibc. */ + return -1; +#endif #ifdef HOST_WIN32 /* Win32 uses QueueUserAPC and callers of this are guarded */ g_assert_not_reached (); diff --git a/mono/mini/Makefile.am.in b/mono/mini/Makefile.am.in index 21396bfb853..552f32cf297 100644 --- a/mono/mini/Makefile.am.in +++ b/mono/mini/Makefile.am.in @@ -414,6 +414,10 @@ test_sources = \ gshared.cs regtests=basic.exe basic-float.exe basic-long.exe basic-calls.exe objects.exe arrays.exe basic-math.exe exceptions.exe iltests.exe devirtualization.exe generics.exe basic-simd.exe +if NACL_CODEGEN +test_sources += nacl.cs +regtests += nacl.exe +endif if X86 if MONO_DEBUGGER_SUPPORTED @@ -553,10 +557,10 @@ libmonoinclude_HEADERS = jit.h CSFLAGS = -unsafe -nowarn:0219,0169,0414,0649 -basic-simd.exe: basic-simd.cs +basic-simd.exe: basic-simd.cs TestDriver.dll $(MCS) -out:$@ $(CSFLAGS) $< -r:TestDriver.dll -r:Mono.Simd.dll -nacl.exe: nacl.cs +nacl.exe: nacl.cs TestDriver.dll $(MCS) -out:$@ $(CSFLAGS) $< -r:TestDriver.dll -r:Mono.Simd.dll generics.exe: generics.cs TestDriver.dll generics-variant-types.dll @@ -591,7 +595,11 @@ endif !NACL_CODEGEN if CROSS_COMPILING GENMDESC_PRG=perl $(srcdir)/genmdesc.pl $(arch_define) $(srcdir) $(GENMDESC_OPTS) else !CROSS_COMPILING +if NACL_CODEGEN +GENMDESC_PRG=perl $(srcdir)/genmdesc.pl $(arch_define) $(srcdir) $(GENMDESC_OPTS) +else GENMDESC_PRG=./genmdesc $(GENMDESC_OPTS) +endif endif !CROSS_COMPILING cpu-x86.h: cpu-x86.md genmdesc$(EXEEXT) @@ -632,7 +640,11 @@ checktests: $(regtests) for i in $(regtests); do $(RUNTIME) $$i; done rcheck: mono $(regtests) +if NACL_CODEGEN + for i in $(regtests); do echo "running test $$i"; $(RUNTIME) $$i --exclude 'NaClDisable' || exit 1; done +else $(RUNTIME) --regression $(regtests) +endif gctest: mono gc-test.exe MONO_DEBUG_OPTIONS=clear-nursery-at-gc $(RUNTIME) --regression gc-test.exe diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index 2fce30e3781..ef06a3aac22 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -1840,7 +1840,9 @@ mono_aot_init (void) InitializeCriticalSection (&aot_page_mutex); aot_modules = g_hash_table_new (NULL, NULL); +#ifndef __native_client__ mono_install_assembly_load_hook (load_aot_module, NULL); +#endif if (g_getenv ("MONO_LASTAOT")) mono_last_aot_method = atoi (g_getenv ("MONO_LASTAOT")); diff --git a/mono/mini/arrays.cs b/mono/mini/arrays.cs index e52c2c70e9d..e65e30a203f 100644 --- a/mono/mini/arrays.cs +++ b/mono/mini/arrays.cs @@ -25,8 +25,8 @@ using System.Reflection; class Tests { - static int Main () { - return TestDriver.RunTests (typeof (Tests)); + public static int Main (string[] args) { + return TestDriver.RunTests (typeof (Tests), args); } public static int test_10_create () { diff --git a/mono/mini/basic-calls.cs b/mono/mini/basic-calls.cs index 5ad874b3dfa..d6bd503a954 100644 --- a/mono/mini/basic-calls.cs +++ b/mono/mini/basic-calls.cs @@ -25,8 +25,8 @@ using System.Reflection; class Tests { - static int Main () { - return TestDriver.RunTests (typeof (Tests)); + public static int Main (string[] args) { + return TestDriver.RunTests (typeof (Tests), args); } static void dummy () { diff --git a/mono/mini/basic-float.cs b/mono/mini/basic-float.cs index df8f6666f0d..bf8c50cb422 100644 --- a/mono/mini/basic-float.cs +++ b/mono/mini/basic-float.cs @@ -28,8 +28,8 @@ using System.Reflection; class Tests { - public static int Main () { - return TestDriver.RunTests (typeof (Tests)); + public static int Main (string[] args) { + return TestDriver.RunTests (typeof (Tests), args); } public static int test_0_beq () { diff --git a/mono/mini/basic-long.cs b/mono/mini/basic-long.cs index 19c33016558..45c67fe2c3a 100644 --- a/mono/mini/basic-long.cs +++ b/mono/mini/basic-long.cs @@ -25,8 +25,8 @@ using System.Reflection; class Tests { - public static int Main () { - return TestDriver.RunTests (typeof (Tests)); + public static int Main (string[] args) { + return TestDriver.RunTests (typeof (Tests), args); } public static int test_10_simple_cast () { diff --git a/mono/mini/basic-math.cs b/mono/mini/basic-math.cs index d2fa1ede9bc..4482c913af6 100644 --- a/mono/mini/basic-math.cs +++ b/mono/mini/basic-math.cs @@ -25,8 +25,8 @@ using System.Reflection; class Tests { - public static int Main () { - return TestDriver.RunTests (typeof (Tests)); + public static int Main (string[] args) { + return TestDriver.RunTests (typeof (Tests), args); } public static int test_0_sin_precision () { diff --git a/mono/mini/basic.cs b/mono/mini/basic.cs index b700efa87e3..b9cf91347b2 100644 --- a/mono/mini/basic.cs +++ b/mono/mini/basic.cs @@ -25,8 +25,8 @@ using System.Reflection; class Tests { - static int Main () { - return TestDriver.RunTests (typeof (Tests)); + public static int Main (string[] args) { + return TestDriver.RunTests (typeof (Tests), args); } public static int test_0_return () { @@ -1361,4 +1361,4 @@ class Tests { return k == -32768 ? 0 : 1; } -} \ No newline at end of file +} diff --git a/mono/mini/driver.c b/mono/mini/driver.c index 8c67f6db6d5..dc73ec4fbfe 100644 --- a/mono/mini/driver.c +++ b/mono/mini/driver.c @@ -1423,6 +1423,9 @@ mono_main (int argc, char* argv[]) #ifdef HOST_WIN32 int mixed_mode = FALSE; #endif +#ifdef __native_client__ + gboolean nacl_null_checks_off = FALSE; +#endif #ifdef MOONLIGHT #ifndef HOST_WIN32 @@ -1727,6 +1730,8 @@ mono_main (int argc, char* argv[]) #ifdef __native_client__ } else if (strcmp (argv [i], "--nacl-mono-path") == 0){ nacl_mono_path = g_strdup(argv[++i]); + } else if (strcmp (argv [i], "--nacl-null-checks-off") == 0){ + nacl_null_checks_off = TRUE; #endif } else { fprintf (stderr, "Unknown command line option: '%s'\n", argv [i]); @@ -1739,6 +1744,10 @@ mono_main (int argc, char* argv[]) { nacl_align_byte = -1; /* 0xff */ } + if (!nacl_null_checks_off) { + MonoDebugOptions *opt = mini_get_debug_options (); + opt->explicit_null_checks = TRUE; + } #endif if (!argv [i]) { @@ -1950,7 +1959,7 @@ mono_main (int argc, char* argv[]) * This used to be an amd64 only crash, but it looks like now most glibc targets do unwinding * that requires reading the target code. */ -#ifdef __linux__ +#if defined( __linux__ ) || defined( __native_client__ ) mono_dont_free_global_codeman = TRUE; #endif diff --git a/mono/mini/exceptions.cs b/mono/mini/exceptions.cs index b3319e56089..49dca8d1ba1 100644 --- a/mono/mini/exceptions.cs +++ b/mono/mini/exceptions.cs @@ -26,8 +26,8 @@ using System.Runtime.CompilerServices; class Tests { - public static int Main () { - return TestDriver.RunTests (typeof (Tests)); + public static int Main (string[] args) { + return TestDriver.RunTests (typeof (Tests), args); } public static int test_0_catch () { @@ -1455,6 +1455,7 @@ class Tests { return 0; } + [Category ("NaClDisable")] public static int test_0_div_zero () { int d = 1; int q = 0; @@ -1560,6 +1561,7 @@ class Tests { return 0; } + [Category ("NaClDisable")] public static int test_0_long_div_zero () { long d = 1; long q = 0; diff --git a/mono/mini/fsacheck.c b/mono/mini/fsacheck.c deleted file mode 100644 index 6ee66bb8c58..00000000000 --- a/mono/mini/fsacheck.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -extern void* mono_aot_module_mscorlib_info; -extern void* mono_aot_module_System_Core_info; -extern void* mono_aot_module_System_info; -extern void* mono_aot_module_Mono_Posix_info; -extern void* mono_aot_module_System_Configuration_info; -extern void* mono_aot_module_System_Security_info; -extern void* mono_aot_module_System_Xml_info; -/* extern void* mono_aot_module_System_Threading_info; */ -extern void* mono_aot_module_Mono_Security_info; -extern void* mono_aot_module_Mono_Simd_info; -extern void* mono_aot_module_TestDriver_info; - -extern void* mono_aot_module_basic_info; -extern void* mono_aot_module_basic_float_info; -extern void* mono_aot_module_basic_long_info; -extern void* mono_aot_module_basic_calls_info; -extern void* mono_aot_module_basic_simd_info; -extern void* mono_aot_module_objects_info; -extern void* mono_aot_module_arrays_info; -extern void* mono_aot_module_basic_math_info; -extern void* mono_aot_module_exceptions_info; -extern void* mono_aot_module_devirtualization_info; -extern void* mono_aot_module_generics_info; -extern void* mono_aot_module_generics_variant_types_info; -extern void* mono_aot_module_basic_simd_info; -extern void* mono_aot_module_gc_stress_info; -extern void* mono_aot_module_imt_big_iface_test_info; -extern void* mono_aot_module_make_imt_test_info; -/* extern void* mono_aot_module_thread_stress_info; */ -extern void* mono_aot_module_iltests_info; - -extern void mono_aot_register_module(void *aot_info); -extern void mono_aot_init(void); -extern void mono_jit_set_aot_only(mono_bool aot_only); -extern MonoDomain * mini_init (const char *filename, const char *runtime_version); - -int run_all_test_methods(MonoClass *klass) { - void * iter = NULL; - MonoMethod *mm = NULL; - int count = 0; - int passed = 0; - printf("Running test methods without reflection\n"); - while (NULL != (mm = mono_class_get_methods(klass, &iter))) { - long expected_result; - const char *name = mono_method_get_name(mm); - char *end = NULL; - if (strncmp(name, "test_", 5)) continue; - printf("=== Test %d, method %s\n", count, mono_method_get_name(mm)); - expected_result = strtol(name + 5, &end, 10); - if (name == end) { - printf(" warning: could not determine expected return value\n"); - expected_result = 0; - } - MonoObject *mo = mono_runtime_invoke(mm, NULL, NULL, NULL); - int *ret = mono_object_unbox(mo); - if (ret && *ret == expected_result) { - printf(" passed!\n"); - passed++; - } else { - printf(" FAILED, expected %d, returned %p, %d\n", expected_result, ret, - ret != NULL ? *ret : 0); - } - count++; - } - if (count > 0) { - printf("============================================\n"); - printf("Final count: %d tests, %d pass, %.2f%%\n", count, passed, - (double)passed / count * 100.0); - } else { - printf("no test methods found.\n"); - } - return count; -} - -#if defined(__native_client__) -extern void* mono_aot_module_nacl_info; -extern char* nacl_mono_path; -char *load_corlib_data() { - FILE *mscorlib; - static char *corlib_data = NULL; - if (corlib_data) return corlib_data; - - mscorlib = fopen("mscorlib.dll", "r"); - if (NULL != mscorlib) { - size_t size; - struct stat st; - if (0 == stat("mscorlib.dll", &st)) { - size = st.st_size; - printf("reading mscorlib.dll, size %ld\n", size); - corlib_data = malloc(size); - if (corlib_data != NULL) { - while (fread(corlib_data, 1, size, mscorlib) != 0) ; - if (!ferror(mscorlib)) { - mono_set_corlib_data(corlib_data, size); - } else { - perror("error reading mscorlib.dll"); - free(corlib_data); - corlib_data = NULL; - } - } else { - perror("Could not allocate memory"); - } - } else { - perror("stat error"); - } - fclose(mscorlib); - } - return corlib_data; -} -#endif - -/* Initialize Mono. Must run only once per process */ -MonoDomain *init_mono(char *mname) { - MonoDomain *domain = NULL; -#ifdef AOT_VERSION - mono_jit_set_aot_only(1); - mono_aot_register_module(mono_aot_module_mscorlib_info); - mono_aot_register_module(mono_aot_module_TestDriver_info); - mono_aot_register_module(mono_aot_module_System_Core_info); - mono_aot_register_module(mono_aot_module_System_info); - mono_aot_register_module(mono_aot_module_Mono_Posix_info); - mono_aot_register_module(mono_aot_module_System_Configuration_info); - mono_aot_register_module(mono_aot_module_System_Security_info); - mono_aot_register_module(mono_aot_module_System_Xml_info); - mono_aot_register_module(mono_aot_module_Mono_Security_info); - /* mono_aot_register_module(mono_aot_module_System_Threading_info); */ - mono_aot_register_module(mono_aot_module_Mono_Simd_info); - - mono_aot_register_module(mono_aot_module_basic_info); - mono_aot_register_module(mono_aot_module_basic_float_info); - mono_aot_register_module(mono_aot_module_basic_long_info); - mono_aot_register_module(mono_aot_module_basic_calls_info); - mono_aot_register_module(mono_aot_module_basic_simd_info); - mono_aot_register_module(mono_aot_module_objects_info); - mono_aot_register_module(mono_aot_module_arrays_info); - mono_aot_register_module(mono_aot_module_basic_math_info); - mono_aot_register_module(mono_aot_module_exceptions_info); - mono_aot_register_module(mono_aot_module_devirtualization_info); - mono_aot_register_module(mono_aot_module_generics_info); - mono_aot_register_module(mono_aot_module_generics_variant_types_info); - mono_aot_register_module(mono_aot_module_gc_stress_info); - mono_aot_register_module(mono_aot_module_imt_big_iface_test_info); - mono_aot_register_module(mono_aot_module_iltests_info); -#endif - /* mono_aot_register_module(mono_aot_module_make_imt_test_info); */ - /* mono_aot_register_module(mono_aot_module_thread_stress_info); */ -#if defined(__native_client__) -#ifdef AOT_VERSION - mono_aot_register_module(mono_aot_module_nacl_info); -#endif - - /* Test file-less shortcut for loading mscorlib metadata */ - load_corlib_data(); - nacl_mono_path = strdup("."); -#endif - /* Uncomment the following if something is going wrong */ - /* mono_trace_set_level_string("info"); */ - domain = mono_jit_init(mname); - if (NULL == domain) { - printf("ERROR: mono_jit_init failure\n"); - exit(-1); - } - return domain; -} - -/* Run all tests from one assembly file */ -int try_one(char *mname, MonoDomain *domain) { - MonoAssembly *ma; - MonoImage *mi; - MonoClass *mc; - MonoMethodDesc *mmd; - MonoMethod *mm; - MonoObject *mo; - MonoString *monostring_arg; - MonoArray *arg_array; - int *failures = NULL; - const int kUseTestDriver = 1; - int test_count = 0; - void *args [1]; - char *cstr_arg = "--timing"; - - ma = mono_domain_assembly_open(domain, mname); - if (NULL == ma) { - printf("ERROR: could not open mono assembly\n"); - exit(-1); - } - - mi = mono_assembly_get_image(ma); - if (NULL == mi) { - printf("ERROR: could not get assembly image\n"); - exit(-1); - } - - monostring_arg = mono_string_new(domain, cstr_arg); - mc = mono_class_from_name(mono_get_corlib(), "System", "String"); - if (0 == mc) { - printf("ERROR: could not mono string class\n"); - exit(-1); - } - - // to pass a string argument, change the 0 to a 1 and uncomment - // mono_array_setref below - arg_array = mono_array_new(domain, mc, 0); - //mono_array_setref(arg_array, 0, monostring_arg); - args[0] = arg_array; - - if (!kUseTestDriver) { - mc = mono_class_from_name(mi, "", "Tests"); - if (NULL == mc) { - printf("could not open Tests class\n"); - exit(-1); - } - test_count = run_all_test_methods(mc); - } - /* If run_all_test_methods didn't find any tests, try Main */ - if (kUseTestDriver || test_count == 0) { - mmd = mono_method_desc_new("Tests:Main()", 1); - mm = mono_method_desc_search_in_image(mmd, mi); - if (0 == mm) { - mmd = mono_method_desc_new("Tests:Main(string[])", 1); - mm = mono_method_desc_search_in_image(mmd, mi); - if (0 == mm) { - printf("Couldn't find Tests:Main() or Tests:Main(string[])\n"); - exit(-1); - } - } - - mo = mono_runtime_invoke(mm, NULL, args, NULL); - failures = mo != NULL ? mono_object_unbox(mo) : NULL; - if (NULL == failures || *failures != 0) { - printf("--------------------> Failed"); - } - } - return failures != NULL ? failures : 1; -} - -int main(int argc, char *argv[]) { - MonoDomain *domain; - int failures = 0; - - if (argc < 2) { - printf("no test specified; running basic.exe\n"); - printf("================================\n"); - domain = init_mono("basic.exe"); - try_one("basic.exe", domain); - } else { - domain = init_mono(argv[1]); - int i; - for (i = 1; i < argc; i++) { - printf("\nRunning tests from %s:\n", argv[i]); - printf("===============================\n\n"); - failures += try_one(argv[i], domain); - } - } - mono_jit_cleanup(domain); - return failures; -} diff --git a/mono/mini/genmdesc.c b/mono/mini/genmdesc.c index 0c942afabaf..d00a24b5455 100644 --- a/mono/mini/genmdesc.c +++ b/mono/mini/genmdesc.c @@ -11,6 +11,11 @@ #include #include +#if defined(__native_client__) || defined(__native_client_codegen__) +volatile int __nacl_thread_suspension_needed = 0; +void __nacl_suspend_thread_if_needed() {} +#endif + #define MINI_OP(a,b,dest,src1,src2) b, #define MINI_OP3(a,b,dest,src1,src2,src3) b, /* keep in sync with the enum in mini.h */ diff --git a/mono/mini/helpers.c b/mono/mini/helpers.c index 0e884e0c8e7..d945a39b8f2 100644 --- a/mono/mini/helpers.c +++ b/mono/mini/helpers.c @@ -130,6 +130,9 @@ mono_blockset_print (MonoCompile *cfg, MonoBitSet *set, const char *name, guint void mono_disassemble_code (MonoCompile *cfg, guint8 *code, int size, char *id) { +#if defined(__native_client__) + return; +#endif #ifndef DISABLE_LOGGING GHashTable *offset_to_bb_hash = NULL; int i, cindex, bb_num; diff --git a/mono/mini/ldscript b/mono/mini/ldscript index c1d5cc45e8c..dd2e8ea9083 100644 --- a/mono/mini/ldscript +++ b/mono/mini/ldscript @@ -5,6 +5,9 @@ VER_1 { GC_start_blocking; GC_end_blocking; gc_thread_vtable; + __nacl_suspend_thread_if_needed; + __nacl_thread_suspension_needed; + nacl_mono_path; local: *; }; diff --git a/mono/mini/mini-amd64.h b/mono/mini/mini-amd64.h index 84e6bfd0c99..6efc0c7b605 100644 --- a/mono/mini/mini-amd64.h +++ b/mono/mini/mini-amd64.h @@ -15,7 +15,15 @@ /* image-writer.c doesn't happen */ #define kNaClLengthOfCallImm kNaClAlignmentAMD64 -int is_nacl_call_reg_sequence(guint8* code); +int is_nacl_call_reg_sequence (guint8* code); +void amd64_nacl_clear_legacy_prefix_tag (); +void amd64_nacl_tag_legacy_prefix (guint8* code); +void amd64_nacl_tag_rex (guint8* code); +guint8* amd64_nacl_get_legacy_prefix_tag (); +guint8* amd64_nacl_get_rex_tag (); +void amd64_nacl_instruction_pre (); +void amd64_nacl_instruction_post (guint8 **start, guint8 **end); +void amd64_nacl_membase_handler (guint8** code, gint8 basereg, gint32 offset, gint8 dreg); #endif #ifdef HOST_WIN32 diff --git a/mono/mini/mini-gc.c b/mono/mini/mini-gc.c index 3d9bfee3bcc..4b9a010f453 100644 --- a/mono/mini/mini-gc.c +++ b/mono/mini/mini-gc.c @@ -603,8 +603,12 @@ thread_suspend_func (gpointer user_data, void *sigctx, MonoContext *ctx) } else { tls->unwind_state.unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf (); if (sigctx) { +#ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX mono_arch_sigctx_to_monoctx (sigctx, &tls->unwind_state.ctx); tls->unwind_state.valid = TRUE; +#else + tls->unwind_state.valid = FALSE; +#endif } else if (ctx) { memcpy (&tls->unwind_state.ctx, ctx, sizeof (MonoContext)); tls->unwind_state.valid = TRUE; diff --git a/mono/mini/mini-posix.c b/mono/mini/mini-posix.c index d03e1147d4f..d3e5c907294 100644 --- a/mono/mini/mini-posix.c +++ b/mono/mini/mini-posix.c @@ -100,7 +100,17 @@ mono_runtime_cleanup_handlers (void) { } +pid_t +mono_runtime_syscall_fork (void) +{ + g_assert_not_reached(); + return 0; +} +void +mono_gdb_render_native_backtraces (pid_t crashed_pid) +{ +} #else diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 8801957181b..8357ca931c9 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -5798,8 +5798,15 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in patch_info.data.method = method; g_hash_table_remove (domain_jit_info (target_domain)->jump_target_hash, method); +#if defined(__native_client_codegen__) && defined(__native_client__) + /* These patches are applied after a method has been installed, no target munging is needed. */ + nacl_allow_target_modification (FALSE); +#endif for (tmp = jlist->list; tmp; tmp = tmp->next) mono_arch_patch_code (NULL, target_domain, tmp->data, &patch_info, NULL, TRUE); +#if defined(__native_client_codegen__) && defined(__native_client__) + nacl_allow_target_modification (TRUE); +#endif } } diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 288d96efd87..5f64c2ef1b4 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -39,6 +39,11 @@ #include "mini-unwind.h" #include "jit.h" +#ifdef __native_client_codegen__ +#include +#endif + + /* * The mini code should not have any compile time dependencies on the GC being used, so the same object file from mini/ * can be linked into both mono and mono-sgen. @@ -1957,6 +1962,8 @@ extern const guint kNaClAlignmentMask; #endif #if defined(__native_client__) || defined(__native_client_codegen__) +extern volatile int __nacl_thread_suspension_needed; +extern void __nacl_suspend_thread_if_needed(); void mono_nacl_gc(); #endif diff --git a/mono/mini/nacl.cs b/mono/mini/nacl.cs index 24cd2c5cc82..d47645a1ef2 100644 --- a/mono/mini/nacl.cs +++ b/mono/mini/nacl.cs @@ -1,67 +1,145 @@ using System; using Mono.Simd; +using System.Threading; + +class A { + public void Print() { Console.WriteLine("A"); } +} + +class B : A { + public void Print() { Console.WriteLine("B"); } +} + +class ThreadRunner { + public Int32 Inc2(Int32 a) { return Inc1(a); } + public Int32 Inc1(Int32 a) { return a + 2; } + public void PrintA(A a) { a.Print(); ((B)a).Print(); } + public void Run() { + Console.WriteLine("Running thread" ); + B b = new B(); + Int32 a=0; + for(int i = 0; i < 1000000; i++) { + a = Inc2(a); + if(i % 100000 == 0) PrintA(b); + } + Console.WriteLine("Ending thread"); + } +} + + +class Extensions { public static string BogusProperty { get; set; } } + +class RuntimeServices { + public System.Reflection.MemberInfo[] members = typeof(Extensions).GetMembers(); + public void Run() { + foreach (var m in members) System.Console.WriteLine(m); + } +} class Tests { struct myvt { - public int X; - public int Y; + public int X; + public int Y; } static int test_0_vector4i_cmp_gt () { - Vector4i a = new Vector4i (10, 5, 12, -1); + Vector4i a = new Vector4i (10, 5, 12, -1); Vector4i b = new Vector4i (-1, 5, 10, 10); Vector4i c = a.CompareGreaterThan (b); - + if (c.X != -1) return 1; if (c.Y != 0) return 2; if (c.Z != -1) - return 3; + return 3; if (c.W != 0) - return 4; + return 4; return 0; } static myvt CompareGT(myvt a, myvt b) { - myvt r; - r.X = a.X > b.X ? -1 : 0; - r.Y = a.Y > b.Y ? -1 : 0; - return r; + myvt r; + r.X = a.X > b.X ? -1 : 0; + r.Y = a.Y > b.Y ? -1 : 0; + return r; } static int test_0_struct2i_cmp_gt() { - myvt a; - myvt b; - a.X = 10; - a.Y = 5; - b.X = -1; - b.Y = 5; - myvt c = CompareGT(a, b); - if (c.X != -1) - return 1; - if (c.Y != 0) - return 2; - return 0; + myvt a; + myvt b; + a.X = 10; + a.Y = 5; + b.X = -1; + b.Y = 5; + myvt c = CompareGT(a, b); + if (c.X != -1) + return 1; + if (c.Y != 0) + return 2; + return 0; } static int vararg_sum(params int[] args) { - int sum = 0; - foreach(int arg in args) { - sum += arg; - } - return sum; + int sum = 0; + foreach(int arg in args) { + sum += arg; + } + return sum; } static int test_21_vararg_test() { - int sum = 0; - sum += vararg_sum(); - sum += vararg_sum(1); - sum += vararg_sum(2, 3); - sum += vararg_sum(4, 5, 6); - return sum; + int sum = 0; + sum += vararg_sum(); + sum += vararg_sum(1); + sum += vararg_sum(2, 3); + sum += vararg_sum(4, 5, 6); + return sum; } + + static int test_0_threads() { + // Run a bunch of threads, make them JIT some code and + // do some casts + ThreadRunner runner = new ThreadRunner(); + Thread[] threads = new Thread[10]; + for (int i = 0; i < 10; i++) { + threads[i] = new Thread(new ThreadStart(runner.Run)); + threads[i].Start(); + } + for (int i = 0; i < 10; i++) { + threads[i].Join(); + } + return 0; + } + + + static int test_0_reflection() { + RuntimeServices r = new RuntimeServices(); + r.Run(); + return 0; + } + + public class BaseClass { + } + + public class LongClass : BaseClass { + public long Value; + public LongClass(long val) { Value = val; } + } + + static public long add_two_LongClass(BaseClass l1, BaseClass l2) { + long l = checked (((LongClass)l1).Value + ((LongClass)l2).Value); + return l; + } + + static int test_0_laddcc() { + long l = add_two_LongClass(new LongClass(System.Int64.MinValue), new LongClass(1234)); + if (l == 1234) + return 1; + return 0; + } + public static int Main(String[] args) { - return TestDriver.RunTests(typeof(Tests)); + return TestDriver.RunTests(typeof(Tests)); } } diff --git a/mono/mini/objects.cs b/mono/mini/objects.cs index b7a60134fad..a16871b226c 100644 --- a/mono/mini/objects.cs +++ b/mono/mini/objects.cs @@ -114,8 +114,8 @@ struct Gamma { class Tests { - static int Main () { - return TestDriver.RunTests (typeof (Tests)); + public static int Main (string[] args) { + return TestDriver.RunTests (typeof (Tests), args); } public static int test_0_return () { diff --git a/mono/mini/regalloc.h b/mono/mini/regalloc.h index f043ddd6d55..9e910dc362e 100644 --- a/mono/mini/regalloc.h +++ b/mono/mini/regalloc.h @@ -1,5 +1,8 @@ - +#if defined(__native_client__) && defined(__x86_64__) +typedef guint64 regmask_t; +#else typedef size_t regmask_t; +#endif enum { MONO_REG_INT, diff --git a/mono/mini/wapihandles.c b/mono/mini/wapihandles.c index c873a1d243b..c2a31ce1ea3 100644 --- a/mono/mini/wapihandles.c +++ b/mono/mini/wapihandles.c @@ -3,7 +3,7 @@ #include "mini.h" -#if defined(HOST_WIN32) || !defined(HAVE_SYS_IPC_H) || !defined(HAVE_SYS_SEM_H) +#if defined(HOST_WIN32) || !defined(HAVE_SYS_IPC_H) || !defined(HAVE_SYS_SEM_H) || (defined(__native_client__) && defined(__GLIBC__)) int mini_wapi_hps (int argc, char **argv) { diff --git a/mono/monograph/monograph.c b/mono/monograph/monograph.c index 7d103d3d5fc..27f1a5f3cf9 100644 --- a/mono/monograph/monograph.c +++ b/mono/monograph/monograph.c @@ -18,6 +18,11 @@ static int max_depth = 6; static int verbose = 0; static const char *graph_properties = "\tnode [fontsize=8.0]\n\tedge [len=2,color=red]\n"; +#if defined(__native_client__) || defined(__native_client_codegen__) +volatile int __nacl_thread_suspension_needed = 0; +void __nacl_suspend_thread_if_needed() {} +#endif + static void output_type_edge (MonoClass *first, MonoClass *second) { if (include_namespace) @@ -1200,5 +1205,3 @@ main (int argc, char *argv[]) { fclose (output); return 0; } - - diff --git a/mono/profiler/Makefile.am b/mono/profiler/Makefile.am index a6f029ab590..25bb9b51f70 100644 --- a/mono/profiler/Makefile.am +++ b/mono/profiler/Makefile.am @@ -82,7 +82,11 @@ MCS = $(RUNTIME) $(mcs_topdir)/class/lib/build/mcs.exe -unsafe -nowarn:0162 -now testlog: $(PLOG_TESTS) $(with_mono_path) perl $(srcdir)/ptestrunner.pl $(top_builddir) +if NACL_CODEGEN +check-local: +else check-local: testlog +endif EXTRA_DIST=utils.c utils.h proflog.h log-profiler.txt perf_event.h \ $(PLOG_TESTS_SRC) ptestrunner.pl diff --git a/mono/profiler/decode.c b/mono/profiler/decode.c index 1f893ce8128..1383ae90b27 100644 --- a/mono/profiler/decode.c +++ b/mono/profiler/decode.c @@ -27,6 +27,11 @@ #define HASH_SIZE 9371 #define SMALL_HASH_SIZE 31 +#if defined(__native_client__) || defined(__native_client_codegen__) +volatile int __nacl_thread_suspension_needed = 0; +void __nacl_suspend_thread_if_needed() {} +#endif + static int debug = 0; static int collect_traces = 0; static int show_traces = 0; diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index 455a4b15940..d6f4c317886 100644 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -446,6 +446,91 @@ PLATFORM_DISABLED_TESTS=dynamic-method-resurrection.exe #PLATFORM_DISABLED_TESTS=dynamic-method-resurrection.exe exception17.exe endif +if NACL_CODEGEN +# Tests that use Thread.Abort() +PLATFORM_DISABLED_TESTS= abort-stress-1.exe \ + abort-stress-2.exe \ + abort-stress-3.exe \ + appdomain-thread-abort.exe \ + async-exc-compilation.exe \ + bug-561239.exe \ + bug-70561.exe \ + finalizer-abort.exe \ + finally_guard.exe \ + main-returns-abort-resetabort.exe \ + main-returns-background-abort-resetabort.exe \ + thread6.exe \ + threadpool-exceptions5.exe \ + threadpool-exceptions6.exe + +# Tests that rely on AppDomain.Unload +PLATFORM_DISABLED_TESTS+= appdomain-async-invoke.exe \ + appdomain-exit.exe \ + appdomain-unload-callback.exe \ + appdomain-unload.exe \ + domain-stress.exe \ + generic-unloading.2.exe \ + monitor.exe \ + remoting4.exe \ + threadpool-exceptions7.exe \ + xdomain-threads.exe + +# pinvoke2 attaches a thread to the runtime, but +# doesn't 'unattach' it and it hangs in GC on exit +PLATFORM_DISABLED_TESTS+= pinvoke2.exe + +# Tests that currently hang waiting for non-main threads +# to exit in NaCl, need to investigate. Most are AppDomain +# creation and Delegate tests. +PLATFORM_DISABLED_TESTS+= appdomain1.exe \ + delegate9.exe \ + marshal-valuetypes.exe \ + cross-domain.exe \ + stackframes-async.2.exe \ + generic-marshalbyref.2.exe \ + generic-xdomain.2.exe \ + bug-415577.exe + +# Tests that fail trying to write files (appdomain create mostly) +PLATFORM_DISABLED_TESTS+= bug-335131.2.exe \ + bug-349190.2.exe \ + bug-80307.exe \ + bug-462592.exe + +# FIXME: don't know why delegate2.exe fails, it shouldn't +PLATFORM_DISABLED_TESTS+= delegate2.exe + +# These tests newly fail with the latest revision. pinvoke3 fails because +# of a thread attach, the others have not been investigated. TODO revisit. +PLATFORM_DISABLED_TESTS+= pinvoke3.exe \ + async_read.exe \ + async-with-cb-throws.exe \ + appdomain-unload-doesnot-raise-pending-events.exe \ + gsharing-valuetype-layout.exe + +if X86 +# FIXME: There are problems with async callbacks and results on NaCl 32-bit +PLATFORM_DISABLED_TESTS+= delegate1.exe \ + delegate3.exe \ + delegate5.exe \ + delegate8.exe \ + threadpool.exe \ + threadpool1.exe \ + threadpool-exceptions3.exe \ + bug-323114.exe \ + delegate-exit.exe \ + bug-80392.2.exe + +# FIXME: These tests hang/fail for unknown reasons, deal with exiting +PLATFORM_DISABLED_TESTS+= main-returns-background-resetabort.exe \ + main-returns-background.exe \ + main-returns-background-change.exe +endif + +endif + +# The two finalizer tests only work under sgen +# gc-altstack.exe fails under boehm because it has no support for altstack # bug-459094.exe creates an extremely deep directory tree # delegate-invoke.exe depends on 929c6bc9b6d76a273f251e6f5dfacac36e9c38bd which was # reverted. @@ -599,17 +684,25 @@ tests: $(TESTSI_CS) $(TESTSI_IL) $(TESTBS) libtest.la $(PREREQSI_IL) $(PREREQSI_ # Test that no symbols are missed in eglib-remap.h # OK_G_SYMBOLS='g_list\|g_slist\|g_concat_dir_and_file' +if NACL_CODEGEN +test-eglib-remap: +else test-eglib-remap: @echo "Testing eglib remap..." @if which nm > /dev/null; then if nm $(top_builddir)/mono/mini/mono | grep -v $(OK_G_SYMBOLS) | grep 't g_'; then exit 1; else exit 0; fi; fi +endif # # Tests that the internals in mono/io-layer/messages.c are ok by triggering the # code that checks that the table is properly sorted # +if NACL_CODEGEN +test-messages: +else test-messages: w32message.exe > test_messages.zero $(with_mono_path) $(JITTEST_PROG_RUN) w32message.exe >& w32message.allout && cmp test_messages.zero w32message.allout +endif if MOONLIGHT test_2_1 : test-coreclr-security @@ -1039,8 +1132,12 @@ test-generic-sharing-normal: $(GSHARED_TESTS) test-generic-sharing-managed: test-runner.exe $(GSHARED_TESTS) @$(RUNTIME) ./test-runner.exe -j a --opt-sets "gshared gshared,shared gshared,-inline gshared,-inline,shared" $(GSHARED_TESTS) +if NACL_CODEGEN +test-generic-sharing: +else test-generic-sharing: @if test x$(M) != x; then $(MAKE) test-generic-sharing-managed; else $(MAKE) test-generic-sharing-normal; fi +endif EXTRA_DIST += async-exceptions.cs async-exceptions.exe : async-exceptions.cs @@ -1062,6 +1159,10 @@ patch-libtool: sed -e 's,LIBTOOL =,LIBTOOL2 =,g' Makefile > 2 && echo "LIBTOOL = bash ./libtool" > 1 && cat 1 2 > Makefile touch libtest.c + +if NACL_CODEGEN +test-process-exit: +else EXTRA_DIST += bug-438454.cs bug-438454.exe.stdout.expected threadpool-in-processexit.cs threadpool-in-processexit.exe.stdout.expected test-process-exit: @$(MCS) $(srcdir)/bug-438454.cs -out:bug-438454.exe @@ -1072,6 +1173,7 @@ test-process-exit: @echo "Testing threadpool-in-processexit.exe..." @$(RUNTIME) threadpool-in-processexit.exe > threadpool-in-processexit.exe.stdout @diff -w threadpool-in-processexit.exe.stdout $(srcdir)/threadpool-in-processexit.exe.stdout.expected +endif OOM_TESTS = \ gc-oom-handling.exe \ diff --git a/mono/utils/mono-codeman.c b/mono/utils/mono-codeman.c index 4efcea0ae25..dcee2a99b3e 100644 --- a/mono/utils/mono-codeman.c +++ b/mono/utils/mono-codeman.c @@ -91,7 +91,7 @@ struct _MonoCodeManager { CodeChunk *current; CodeChunk *full; #if defined(__native_client_codegen__) && defined(__native_client__) - MonoGHashTable *hash; + GHashTable *hash; #endif }; @@ -228,14 +228,16 @@ mono_code_manager_new (void) if (next_dynamic_code_addr == NULL) { const guint kPageMask = 0xFFFF; /* 64K pages */ next_dynamic_code_addr = (uintptr_t)(etext + kPageMask) & ~kPageMask; +#if defined (__GLIBC__) + /* TODO: For now, just jump 64MB ahead to avoid dynamic libraries. */ + next_dynamic_code_addr += (uintptr_t)0x4000000; +#else /* Workaround bug in service runtime, unable to allocate */ /* from the first page in the dynamic code section. */ - /* TODO: remove */ next_dynamic_code_addr += (uintptr_t)0x10000; +#endif } - cman->hash = mono_g_hash_table_new (NULL, NULL); - /* Keep the hash table from being collected */ - mono_gc_register_root (&cman->hash, sizeof (void*), NULL); + cman->hash = g_hash_table_new (NULL, NULL); if (patch_source_base == NULL) { patch_source_base = g_malloc (kMaxPatchDepth * sizeof(unsigned char *)); patch_dest_base = g_malloc (kMaxPatchDepth * sizeof(unsigned char *)); @@ -546,7 +548,7 @@ mono_code_manager_reserve_align (MonoCodeManager *cman, int size, int alignment) /* Allocate code space from the service runtime */ code_ptr = allocate_code (size); /* Insert pointer to code space in hash, keyed by buffer ptr */ - mono_g_hash_table_insert (cman->hash, temp_ptr, code_ptr); + g_hash_table_insert (cman->hash, temp_ptr, code_ptr); nacl_jit_check_init (); @@ -598,7 +600,7 @@ mono_code_manager_commit (MonoCodeManager *cman, void *data, int size, int newsi unsigned char *code; int status; g_assert (newsize <= size); - code = mono_g_hash_table_lookup (cman->hash, data); + code = g_hash_table_lookup (cman->hash, data); g_assert (code != NULL); /* Pad space after code with HLTs */ /* TODO: this is x86/amd64 specific */ @@ -608,9 +610,15 @@ mono_code_manager_commit (MonoCodeManager *cman, void *data, int size, int newsi } status = nacl_dyncode_create (code, data, newsize); if (status != 0) { + unsigned char *codep; + fprintf(stderr, "Error creating Native Client dynamic code section attempted to be\n" + "emitted at %p (hex dissasembly of code follows):\n", code); + for (codep = data; codep < data + newsize; codep++) + fprintf(stderr, "%02x ", *codep); + fprintf(stderr, "\n"); g_assert_not_reached (); } - mono_g_hash_table_remove (cman->hash, data); + g_hash_table_remove (cman->hash, data); g_assert (data == patch_source_base[patch_current_depth]); g_assert (code == patch_dest_base[patch_current_depth]); patch_current_depth--; @@ -623,7 +631,7 @@ mono_code_manager_commit (MonoCodeManager *cman, void *data, int size, int newsi void * nacl_code_manager_get_code_dest (MonoCodeManager *cman, void *data) { - return mono_g_hash_table_lookup (cman->hash, data); + return g_hash_table_lookup (cman->hash, data); } #endif diff --git a/mono/utils/mono-context.c b/mono/utils/mono-context.c index 81e2fe69b35..81f3ca84ec3 100644 --- a/mono/utils/mono-context.c +++ b/mono/utils/mono-context.c @@ -252,6 +252,8 @@ mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx) { #ifdef MONO_CROSS_COMPILE g_assert_not_reached (); +#elif defined(__native_client__) + g_assert_not_reached (); #else arm_ucontext *my_uc = sigctx; @@ -270,6 +272,8 @@ mono_monoctx_to_sigctx (MonoContext *mctx, void *ctx) { #ifdef MONO_CROSS_COMPILE g_assert_not_reached (); +#elif defined(__native_client__) + g_assert_not_reached (); #else arm_ucontext *my_uc = ctx; diff --git a/mono/utils/mono-mmap.c b/mono/utils/mono-mmap.c index 412a23b3fff..087259fd151 100644 --- a/mono/utils/mono-mmap.c +++ b/mono/utils/mono-mmap.c @@ -405,6 +405,20 @@ mono_file_unmap (void *addr, void *handle) * * Returns: 0 on success. */ +#if defined(__native_client__) +int +mono_mprotect (void *addr, size_t length, int flags) +{ + int prot = prot_from_flags (flags); + void *new_addr; + + if (flags & MONO_MMAP_DISCARD) memset (addr, 0, length); + + new_addr = mmap(addr, length, prot, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0); + if (new_addr == addr) return 0; + return -1; +} +#else int mono_mprotect (void *addr, size_t length, int flags) { @@ -427,6 +441,7 @@ mono_mprotect (void *addr, size_t length, int flags) } return mprotect (addr, length, prot); } +#endif // __native_client__ #else diff --git a/mono/utils/mono-path.c b/mono/utils/mono-path.c index 88b5d25a719..0a443aa41f7 100644 --- a/mono/utils/mono-path.c +++ b/mono/utils/mono-path.c @@ -44,14 +44,9 @@ mono_path_canonicalize (const char *path) if (g_path_is_absolute (path)) { abspath = g_strdup (path); } else { -#ifdef __native_client__ - gchar *tmpdir = "."; - abspath = g_build_filename (tmpdir, path, NULL); -#else gchar *tmpdir = g_get_current_dir (); abspath = g_build_filename (tmpdir, path, NULL); g_free (tmpdir); -#endif } #ifdef HOST_WIN32 diff --git a/mono/utils/mono-threads-posix.c b/mono/utils/mono-threads-posix.c index cc8b61d9d9c..a1db7cb4165 100644 --- a/mono/utils/mono-threads-posix.c +++ b/mono/utils/mono-threads-posix.c @@ -169,6 +169,9 @@ mono_threads_pthread_kill (MonoThreadInfo *info, int signum) errno = old_errno; } return result; +#elif defined(__native_client__) + /* Workaround pthread_kill abort() in NaCl glibc. */ + return 0; #else return pthread_kill (mono_thread_info_get_tid (info), signum); #endif diff --git a/mono/utils/monobitset.c b/mono/utils/monobitset.c index c71da25ba5c..5ff68938f6d 100644 --- a/mono/utils/monobitset.c +++ b/mono/utils/monobitset.c @@ -285,7 +285,11 @@ my_g_bit_nth_lsf (gsize mask, gint nth_bit) if ((mask == 0) || (nth_bit == BITS_PER_CHUNK)) return -1; -#if defined(__i386__) && defined(__GNUC__) +#if defined(__native_client__) && (defined(__i386__) || defined(__x86_64)) +#define USE_X86_32BIT_INSTRUCTIONS 1 +#endif + +#if (defined(__i386__) && defined(__GNUC__)) || defined(USE_X86_32BIT_INSTRUCTIONS) { int r; /* This depends on mask != 0 */ @@ -315,7 +319,7 @@ static inline gint my_g_bit_nth_lsf_nomask (gsize mask) { /* Mask is expected to be != 0 */ -#if defined(__i386__) && defined(__GNUC__) +#if (defined(__i386__) && defined(__GNUC__)) || defined(USE_X86_32BIT_INSTRUCTIONS) int r; __asm__("bsfl %1,%0\n\t" @@ -817,4 +821,3 @@ main() { } #endif - diff --git a/runtime/Makefile.am b/runtime/Makefile.am index f8d500502a3..93b44b4bdc3 100644 --- a/runtime/Makefile.am +++ b/runtime/Makefile.am @@ -169,8 +169,12 @@ mcs-compileall: mono-wrapper etc/mono/config fi; done; done; \ $$ok +if NACL_CODEGEN +check-local: +else check-local: mcs-compileall mcs-do-test-profiles $(MAKE) $(test_select) mcs-do-run-test-profiles +endif # Compile all mcs tests test: mcs-do-test-profiles diff --git a/runtime/mono-wrapper.in b/runtime/mono-wrapper.in index eb6cd895921..18c8cb5e47b 100644 --- a/runtime/mono-wrapper.in +++ b/runtime/mono-wrapper.in @@ -4,4 +4,13 @@ MONO_CFG_DIR='@mono_cfg_dir@' PATH="$r/runtime/_tmpinst/bin:$PATH" MONO_SHARED_DIR=$r/runtime export MONO_CFG_DIR MONO_SHARED_DIR PATH +if [ -n "@nacl_self_host@" ]; then + case "$@" in + # gacutil.exe and mdoc.exe require filesystem functionality not + # exposed in NaCl. + # mcs.exe was added to the list recently because mcs under NaCl + # no longer produces equivalent output. TODO: investigate + */mcs.exe* | */gacutil.exe* | */mdoc.exe* ) exec /usr/local/bin/mono "$@";; + esac +fi exec "$r/libtool" --mode=execute "$r/@mono_runtime@" --config "@mono_cfg_dir@/mono/config" "$@" -- 2.25.1