-Subproject commit df1c00441047e7cc439608aa1aa083f585f5ace0
+Subproject commit 6c6e36218c4a0b6dfb85bd27fa6746467761e8a0
rm -f $outfile.inc
-if test -n "$excfile"; then
+if test -n "$excfile" -a -f "$excfile"; then
process_includes $excfile $outfile.exc
fi
if (!hashAlg.CanReuseTransform) {
canReuseHashAlg = false;
hashAlg = null;
+ return null;
}
+ hashAlg.Key = MachineKeySectionUtils.GetValidationKey (mks);
}
if (hashAlg != null)
WritePrefix ();
}
- WriteDebugString (message);
-
if (Debugger.IsLogging())
Debugger.Log (0, null, message);
+ else
+ WriteDebugString (message);
WriteLogFile (message, LogFileName);
}
static Console ()
{
-#if NET_2_1
- Encoding inputEncoding;
- Encoding outputEncoding;
-#endif
-
if (Environment.IsRunningOnWindows) {
//
// On Windows, follow the Windows tradition
#endif
-#if !NET_2_1
// FIXME: Console should use these encodings when changed
static Encoding inputEncoding;
static Encoding outputEncoding;
}
}
+#if !NET_2_1
public static ConsoleColor BackgroundColor {
get { return ConsoleDriver.BackgroundColor; }
set { ConsoleDriver.BackgroundColor = value; }
mono_install_assembly_postload_search_hook ((MonoAssemblySearchFunc)mono_domain_assembly_postload_search, GUINT_TO_POINTER (FALSE));
mono_install_assembly_postload_refonly_search_hook ((MonoAssemblySearchFunc)mono_domain_assembly_postload_search, GUINT_TO_POINTER (TRUE));
mono_install_assembly_load_hook (mono_domain_fire_assembly_load, NULL);
- mono_install_lookup_dynamic_token (mono_reflection_lookup_dynamic_token);
mono_thread_init (start_cb, attach_cb);
typedef gpointer (*MonoRemotingTrampoline) (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target);
typedef gpointer (*MonoDelegateTrampoline) (MonoDomain *domain, MonoClass *klass);
-typedef gpointer (*MonoLookupDynamicToken) (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context);
-
typedef gboolean (*MonoGetCachedClassInfo) (MonoClass *klass, MonoCachedClassInfo *res);
typedef gboolean (*MonoGetClassFromName) (MonoImage *image, const char *name_space, const char *name, MonoClass **res);
mono_install_delegate_trampoline (MonoDelegateTrampoline func);
gpointer
-mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context);
+mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error);
gpointer
-mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean check_token, MonoClass **handle_class, MonoGenericContext *context);
-
-void
-mono_install_lookup_dynamic_token (MonoLookupDynamicToken func);
+mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean check_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
gpointer
mono_runtime_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean add_sync_wrapper);
mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
return NULL;
}
- klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
+ klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
goto done;
}
mono_error_init (error);
//FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
- if (image_is_dynamic (image))
- return mono_class_get_type ((MonoClass *)mono_lookup_dynamic_token (image, type_token, context));
+ if (image_is_dynamic (image)) {
+ MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
+ return_val_if_nok (error, NULL);
+ return mono_class_get_type (klass);
+ }
if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
MonoClass *klass = mono_class_get_checked (image, type_token, error);
if (image_is_dynamic (image)) {
MonoClass *tmp_handle_class;
- gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
+ gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
+ mono_error_assert_ok (error);
g_assert (tmp_handle_class);
if (handle_class)
*handle_class = tmp_handle_class;
return NULL;
}
-/**
- * This function might need to call runtime functions so it can't be part
- * of the metadata library.
- */
-static MonoLookupDynamicToken lookup_dynamic = NULL;
-
-void
-mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
-{
- lookup_dynamic = func;
-}
-
gpointer
-mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
+mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
{
MonoClass *handle_class;
-
- return lookup_dynamic (image, token, TRUE, &handle_class, context);
+ mono_error_init (error);
+ return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
}
gpointer
-mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
+mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
{
- return lookup_dynamic (image, token, valid_token, handle_class, context);
+ return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
}
static MonoGetCachedClassInfo get_cached_class_info = NULL;
mono_metadata_decode_blob_size (sig, &sig);
return (*sig != 0x6);
} else {
+ MonoError error;
MonoClass *handle_class;
- if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
+ if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
+ mono_error_cleanup (&error); /* just probing, ignore error */
return FALSE;
+ }
return mono_defaults.methodhandle_class == handle_class;
}
if (image_is_dynamic (image)) {
if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
- klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
+ klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
+ mono_error_cleanup (&error);
return klass ? &klass->byval_arg : NULL;
}
init_generic_context_from_args (&context, type_args, method_args);
- klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
+ klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
+ mono_error_cleanup (&error);
return klass ? &klass->byval_arg : NULL;
}
}
if (image_is_dynamic (image)) {
- if (table == MONO_TABLE_METHOD)
- return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
+ if (table == MONO_TABLE_METHOD) {
+ method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
+ mono_error_cleanup (&error);
+ return method;
+ }
if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
*resolve_error = ResolveTokenError_BadTable;
}
init_generic_context_from_args (&context, type_args, method_args);
- return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
+ method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
+ mono_error_cleanup (&error);
+ return method;
}
if ((index <= 0) || (index > image->tables [table].rows)) {
}
ICALL_EXPORT MonoString*
-ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
+ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
{
+ MonoError error;
int index = mono_metadata_token_index (token);
- *error = ResolveTokenError_Other;
+ *resolve_error = ResolveTokenError_Other;
/* Validate token */
if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
- *error = ResolveTokenError_BadTable;
+ *resolve_error = ResolveTokenError_BadTable;
return NULL;
}
- if (image_is_dynamic (image))
- return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
+ if (image_is_dynamic (image)) {
+ MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
+ mono_error_cleanup (&error);
+ return result;
+ }
if ((index <= 0) || (index >= image->heap_us.size)) {
- *error = ResolveTokenError_OutOfRange;
+ *resolve_error = ResolveTokenError_OutOfRange;
return NULL;
}
}
if (image_is_dynamic (image)) {
- if (table == MONO_TABLE_FIELD)
- return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
+ if (table == MONO_TABLE_FIELD) {
+ field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
+ mono_error_cleanup (&error);
+ return field;
+ }
if (mono_memberref_is_method (image, token)) {
*resolve_error = ResolveTokenError_BadTable;
}
init_generic_context_from_args (&context, type_args, method_args);
- return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
+ field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
+ mono_error_cleanup (&error);
+ return field;
}
if ((index <= 0) || (index > image->tables [table].rows)) {
MonoClass *handle_class;
*retklass = NULL;
- result = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context);
+ MonoError inner_error;
+ result = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context, &inner_error);
+ mono_error_cleanup (&inner_error);
// This checks the memberref type as well
if (!result || handle_class != mono_defaults.fieldhandle_class) {
mono_error_set_bad_image (error, image, "Bad field token 0x%08x", token);
if (image_is_dynamic (image)) {
MonoClass *handle_class;
- result = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context);
+ result = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context, error);
+ mono_error_assert_ok (error);
mono_loader_assert_no_error ();
// This checks the memberref type as well
}
static void
-register_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
+register_icall (gpointer func, const char *name, const char *sigstr, gboolean no_wrapper)
{
MonoMethodSignature *sig = mono_create_icall_signature (sigstr);
- mono_register_jit_icall (func, name, sig, save);
+ mono_register_jit_icall (func, name, sig, no_wrapper);
}
MonoMethodSignature*
guint32 sig;
const char *ptr;
- if (image_is_dynamic (image))
- return (MonoMethodSignature *)mono_lookup_dynamic_token (image, token, NULL);
+ if (image_is_dynamic (image)) {
+ ret = (MonoMethodSignature *)mono_lookup_dynamic_token (image, token, NULL, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ return ret;
+ }
g_assert (mono_metadata_token_table(token) == MONO_TABLE_STANDALONESIG);
MonoReflectionMarshalAsAttribute* mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass, MonoMarshalSpec *spec, MonoError *error);
gpointer
-mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context);
+mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
gboolean
mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error);
mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
{
MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
if (image->dynamic) {
- MonoString *str = (MonoString *)mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx, NULL);
+ MonoString *str = (MonoString *)mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx, NULL, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
return str;
} else {
if (!mono_verifier_verify_string_signature (image, idx, NULL))
* LOCKING: Take the loader lock
*/
gpointer
-mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
+mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
{
- MonoError error;
MonoDynamicImage *assembly = (MonoDynamicImage*)image;
MonoObject *obj;
MonoClass *klass;
+ mono_error_init (error);
+
obj = lookup_dyn_token (assembly, token);
if (!obj) {
if (valid_token)
g_error ("Could not find required dynamic token 0x%08x", token);
- else
+ else {
+ mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
return NULL;
+ }
}
if (!handle_class)
handle_class = &klass;
- gpointer result = resolve_object (image, obj, handle_class, context, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ gpointer result = resolve_object (image, obj, handle_class, context, error);
return result;
}
#define SGEN_TV_DECLARE(name) gint64 name
#define SGEN_TV_GETTIME(tv) tv = mono_100ns_ticks ()
-#define SGEN_TV_ELAPSED(start,end) ((long)(end-start))
+#define SGEN_TV_ELAPSED(start,end) ((gint64)(end-start))
typedef MonoSemType SgenSemaphore;
DEF_QSORT_INLINE(hash_entries, HashEntry*, compare_hash_entries)
-static unsigned long step_1, step_2, step_3, step_4, step_5, step_6;
+static gint64 step_1, step_2, step_3, step_4, step_5, step_6;
static int fist_pass_links, second_pass_links, sccs_links;
static int max_sccs_links = 0;
DEF_QSORT_INLINE(hash_entries, HashEntry*, compare_hash_entries)
-static unsigned long step_1, step_2, step_3, step_4, step_5, step_6;
+static gint64 step_1, step_2, step_3, step_4, step_5, step_6;
static int fist_pass_links, second_pass_links, sccs_links;
static int max_sccs_links = 0;
fullaotcheck: $(mono) $(fullaot_regtests)
rm -rf fullaot-tmp
mkdir fullaot-tmp
- $(MAKE) fullaot-libs AOT_FLAGS=full GSHAREDVT=$(GSHAREDVT)
+ $(MAKE) fullaot-libs AOT_FLAGS="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)" GSHAREDVT=$(GSHAREDVT)
cp $(regtests) $(fullaot_regtests) generics-variant-types.dll TestDriver.dll fullaot-tmp/
- MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper $(LLVM_AOT_RUNTIME_OPTS) $(GSHAREDVT_RUNTIME_OPTS) --aot=full fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1
+ MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper $(LLVM_AOT_RUNTIME_OPTS) $(GSHAREDVT_RUNTIME_OPTS) --aot="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)" fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1
ln -s $(if $(MONO_EXECUTABLE),$(MONO_EXECUTABLE),$$PWD/mono) fullaot-tmp/
for i in $(fullaot_regtests); do echo $$i; MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper --full-aot fullaot-tmp/$$i --exclude '!FULLAOT' $(ARCH_FULLAOT_EXCLUDE) || exit 1; done
llvmonlycheck: mono $(llvmonly_regtests)
rm -rf fullaot-tmp
mkdir fullaot-tmp
- $(MAKE) fullaot-libs AOT_FLAGS=llvmonly
+ $(MAKE) fullaot-libs AOT_FLAGS="llvmonly,$(MONO_FULLAOT_ADDITIONAL_ARGS)"
cp $(llvmonly_regtests) generics-variant-types.dll TestDriver.dll fullaot-tmp/
MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper --aot=llvmonly fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1
ln -s $$PWD/mono fullaot-tmp/
return clean;
}
+// Duplicate a char range and add it to a ptrarray, but only if it is nonempty
+static void
+ptr_array_add_range_if_nonempty(GPtrArray *args, gchar const *start, gchar const *end)
+{
+ ptrdiff_t len = end-start;
+ if (len > 0)
+ g_ptr_array_add (args, g_strndup (start, len));
+}
+
static GPtrArray *
mono_aot_split_options (const char *aot_options)
{
next:
aot_options++;
+ restart:
// If the next character is end of string, then process the last option.
if (*(aot_options) == '\0') {
end_of_string = TRUE;
continue;
new_opt:
- g_ptr_array_add (args, g_strndup (opt_start, aot_options - opt_start));
+ ptr_array_add_range_if_nonempty (args, opt_start, aot_options);
opt_start = ++aot_options;
if (end_of_string)
break;
- goto next;
+ goto restart; // Check for null and continue loop
}
return args;
#define AS_OPTIONS "--64"
#elif defined(TARGET_POWERPC64)
#define AS_OPTIONS "-a64 -mppc64"
-#define LD_OPTIONS "-m elf64ppc"
#elif defined(sparc) && SIZEOF_VOID_P == 8
#define AS_OPTIONS "-xarch=v9"
#elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
#define AS_NAME "as"
#endif
-#ifndef LD_OPTIONS
-#define LD_OPTIONS ""
-#endif
-
#if defined(sparc)
-#define LD_NAME "ld -shared -G"
+#define LD_NAME "ld"
+#define LD_OPTIONS "-shared -G"
#elif defined(__ppc__) && defined(TARGET_MACH)
-#define LD_NAME "gcc -dynamiclib"
+#define LD_NAME "gcc"
+#define LD_OPTIONS "-dynamiclib"
#elif defined(TARGET_AMD64) && defined(TARGET_MACH)
-#define LD_NAME "clang --shared"
+#define LD_NAME "clang"
+#define LD_OPTIONS "--shared"
#elif defined(TARGET_WIN32) && !defined(TARGET_ANDROID)
-#define LD_NAME "gcc -shared --dll"
+#define LD_NAME "gcc"
+#define LD_OPTIONS "-shared"
#elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
-#define LD_NAME "clang -m32 -dynamiclib"
+#define LD_NAME "clang"
+#define LD_OPTIONS "-m32 -dynamiclib"
#elif defined(TARGET_ARM) && !defined(TARGET_ANDROID)
-#define LD_NAME "gcc --shared"
+#define LD_NAME "gcc"
+#define LD_OPTIONS "--shared"
+#elif defined(TARGET_POWERPC64)
+#define LD_OPTIONS "-m elf64ppc"
+#endif
+
+#ifndef LD_OPTIONS
+#define LD_OPTIONS ""
#endif
if (acfg->aot_opts.asm_only) {
ld_flags = g_strdup_printf ("%s %s", ld_flags, "-lstdc++");
#ifdef LD_NAME
- command = g_strdup_printf ("%s -o %s %s %s %s", LD_NAME,
+ command = g_strdup_printf ("%s%s %s -o %s %s %s %s", tool_prefix, LD_NAME, LD_OPTIONS,
wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
#else
+ // Default (linux)
command = g_strdup_printf ("\"%sld\" %s -shared -o %s %s %s %s", tool_prefix, LD_OPTIONS,
wrap_path (tmp_outfile_name), wrap_path (llvm_ofile),
wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags);
amd64_lea_membase (code, AMD64_RAX, AMD64_RSP, stack_size + sizeof(mgreg_t));
amd64_mov_membase_reg (code, AMD64_RSP, regs_offset + (AMD64_RSP * sizeof(mgreg_t)), X86_EAX, sizeof(mgreg_t));
/* Save IP */
- if (llvm_abs)
- amd64_alu_reg_reg (code, X86_XOR, AMD64_RAX, AMD64_RAX);
- else
- amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RSP, stack_size, sizeof(mgreg_t));
+ amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RSP, stack_size, sizeof(mgreg_t));
amd64_mov_membase_reg (code, AMD64_RSP, regs_offset + (AMD64_RIP * sizeof(mgreg_t)), AMD64_RAX, sizeof(mgreg_t));
/* Set arg1 == ctx */
amd64_lea_membase (code, AMD64_RAX, AMD64_RSP, ctx_offset);
if (resume_unwind) {
amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [2], 0, sizeof(mgreg_t));
} else if (corlib) {
- amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [2], AMD64_ARG_REG2, sizeof(mgreg_t));
if (llvm_abs)
- /*
- * The caller is LLVM code which passes the absolute address not a pc offset,
- * so compensate by passing 0 as 'rip' and passing the negated abs address as
- * the pc offset.
+ /*
+ * The caller doesn't pass in a pc/pc offset, instead we simply use the
+ * caller ip. Negate the pc adjustment done in mono_amd64_throw_corlib_exception ().
*/
- amd64_neg_membase (code, AMD64_RSP, arg_offsets [2]);
+ amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [2], 1, sizeof(mgreg_t));
+ else
+ amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [2], AMD64_ARG_REG2, sizeof(mgreg_t));
} else {
amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [2], rethrow, sizeof(mgreg_t));
}
}
void
-mono_arm_throw_exception_by_token (guint32 type_token, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
+mono_arm_throw_exception_by_token (guint32 ex_token_index, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
{
+ guint32 ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index;
/* Clear thumb bit */
pc &= ~1;
- mono_arm_throw_exception ((MonoObject*)mono_exception_from_token (mono_defaults.corlib, type_token), pc, sp, int_regs, fp_regs);
+ mono_arm_throw_exception ((MonoObject*)mono_exception_from_token (mono_defaults.corlib, ex_token), pc, sp, int_regs, fp_regs);
}
void
/* exc is already in place in r0 */
if (corlib) {
/* The caller ip is already in R1 */
- if (llvm)
- /* Negate the ip adjustment done in mono_arm_throw_exception */
- ARM_ADD_REG_IMM8 (code, ARMREG_R1, ARMREG_R1, 4);
+ if (llvm) {
+ /*
+ * The address passed by llvm might point to before the call,
+ * thus outside the eh range recorded by llvm. Use the return
+ * address instead.
+ * FIXME: Do this on more platforms.
+ */
+ ARM_MOV_REG_REG (code, ARMREG_R1, ARMREG_LR); /* caller ip */
+ }
} else {
ARM_MOV_REG_REG (code, ARMREG_R1, ARMREG_LR); /* caller ip */
}
unw_word_t ip, sp;
int res;
- if (mono_object_isinst (exc, mono_defaults.exception_class, &error)) {
+ if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
MonoException *mono_ex = (MonoException*)exc;
if (!rethrow) {
mono_ex->stack_trace = NULL;
memcpy (&ctx.regs, int_regs, sizeof (mgreg_t) * MONO_SAVED_GREGS);
memcpy (&ctx.fregs, fp_regs, sizeof (double) * MONO_SAVED_FREGS);
- if (mono_object_isinst (exc, mono_defaults.exception_class, &error)) {
+ if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
MonoException *mono_ex = (MonoException*)exc;
if (!rethrow) {
mono_ex->stack_trace = NULL;
#define eat_whitespace(s) while (*(s) && isspace (*(s))) s++;
+// Per spec isalnum() expects input in the range 0-255
+// and can misbehave if you pass in a signed char.
+static int
+isalnum_char(char c)
+{
+ return isalnum ((unsigned char)c);
+}
+
static int
load_file (const char *name) {
FILE *f;
OpDesc *tdesc;
p += 9;
tname = p;
- while (*p && isalnum (*p)) ++p;
+ while (*p && isalnum_char (*p)) ++p;
*p++ = 0;
tdesc = (OpDesc *)g_hash_table_lookup (template_table, tname);
if (!tdesc)
g_error ("Duplicated name tag in template %s at '%s' at line %d in %s\n", desc->name, p, line, name);
p += 5;
tname = p;
- while (*p && isalnum (*p)) ++p;
+ while (*p && isalnum_char (*p)) ++p;
*p++ = 0;
if (g_hash_table_lookup (template_table, tname))
g_error ("Duplicated template %s at line %d in %s\n", tname, line, name);
static void
output_char (FILE *f, char c) {
- if (isalnum (c))
+ if (isalnum_char (c))
fprintf (f, "%c", c);
else
fprintf (f, "\\x%x\" \"", (guint8)c);
stype = "object";
asm_writer_emit_unset_mode (acfg);
+
#if defined(TARGET_ASM_APPLE)
+#elif defined(TARGET_WIN32)
+ if (func)
+ fprintf (acfg->fp, "\t.def %s; .scl 2; .type 32; .endef\n", name);
+ else
+ fprintf (acfg->fp, "\t.data\n");
#elif defined(TARGET_ARM)
fprintf (acfg->fp, "\t.type %s,#%s\n", name, stype);
#else
{
asm_writer_emit_unset_mode (acfg);
-#ifndef TARGET_ASM_APPLE
+#if !defined(TARGET_ASM_APPLE) && !defined(TARGET_WIN32)
fprintf (acfg->fp, "\t.local %s\n", name);
#endif
{
asm_writer_emit_unset_mode (acfg);
-#ifndef TARGET_ASM_APPLE
+
+#if !defined(TARGET_ASM_APPLE) && !defined(TARGET_WIN32)
fprintf (acfg->fp, "\t.size %s,%s-%s\n", name, end_label, name);
#endif
}
patch_info->ip.i = code - cfg->native_code;
ARM_BL (code, 0);
cfg->thunk_area += THUNK_SIZE;
- *(guint32*)(gpointer)code = exc_class->type_token;
+ *(guint32*)(gpointer)code = exc_class->type_token - MONO_TOKEN_TYPE_DEF;
code += 4;
#endif
break;
MonoClass *exc_class;
LLVMValueRef args [2];
LLVMValueRef callee;
+ gboolean no_pc = FALSE;
+
+ if (IS_TARGET_AMD64)
+ /* Some platforms don't require the pc argument */
+ no_pc = TRUE;
ex_bb = gen_bb (ctx, "EX_BB");
if (ctx->llvm_only)
LLVMTypeRef sig;
const char *icall_name;
- sig = LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), LLVMPointerType (LLVMInt8Type (), 0), FALSE);
+ if (no_pc)
+ sig = LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE);
+ else
+ sig = LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), LLVMPointerType (LLVMInt8Type (), 0), FALSE);
icall_name = "llvm_throw_corlib_exception_abs_trampoline";
if (ctx->cfg->compile_aot) {
}
}
- if (IS_TARGET_X86 || IS_TARGET_AMD64)
- args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token - MONO_TOKEN_TYPE_DEF, FALSE);
- else
- args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token, FALSE);
+ args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token - MONO_TOKEN_TYPE_DEF, FALSE);
/*
* The LLVM mono branch contains changes so a block address can be passed as an
* argument to a call.
*/
- args [1] = LLVMBlockAddress (ctx->lmethod, ex_bb);
- emit_call (ctx, bb, &builder, callee, args, 2);
+ if (no_pc) {
+ emit_call (ctx, bb, &builder, callee, args, 1);
+ } else {
+ args [1] = LLVMBlockAddress (ctx->lmethod, ex_bb);
+ emit_call (ctx, bb, &builder, callee, args, 2);
+ }
LLVMBuildUnreachable (builder);
mono_runtime_install_handlers (void)
{
#ifndef MONO_CROSS_COMPILE
- win32_seh_init();
- win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
- win32_seh_set_handler(SIGILL, mono_sigill_signal_handler);
- win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
- if (mini_get_debug_options ()->handle_sigint)
- win32_seh_set_handler(SIGINT, mono_sigint_signal_handler);
+ if (!mono_aot_only) {
+ win32_seh_init();
+ win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
+ win32_seh_set_handler(SIGILL, mono_sigill_signal_handler);
+ win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
+ if (mini_get_debug_options ()->handle_sigint)
+ win32_seh_set_handler(SIGINT, mono_sigint_signal_handler);
+ }
#endif
}
mono_runtime_cleanup_handlers (void)
{
#ifndef MONO_CROSS_COMPILE
- win32_seh_cleanup();
+ if (!mono_aot_only) {
+ win32_seh_cleanup();
+ }
#endif
}
g_free (cached);
}
-
g_free (cached_info);
+
+ for (GSList *cursor = cached_info_list; cursor != NULL; cursor = cursor->next)
+ g_free (cursor->data);
+
+ g_slist_free (cached_info_list);
}
/*
mono_memory_barrier ();
- cached_info = new_table;
-
cached_info_list = g_slist_prepend (cached_info_list, cached_info);
+ cached_info = new_table;
+
cached_info_size *= 2;
}
sgen_client_clear_togglerefs (start_addr, end_addr, ctx);
TV_GETTIME (btv);
- SGEN_LOG (2, "Finalize queue handling scan for %s generation: %ld usecs %d ephemeron rounds", generation_name (generation), TV_ELAPSED (atv, btv), ephemeron_rounds);
+ SGEN_LOG (2, "Finalize queue handling scan for %s generation: %lld usecs %d ephemeron rounds", generation_name (generation), TV_ELAPSED (atv, btv), ephemeron_rounds);
/*
* handle disappearing links
TV_GETTIME (atv);
time_minor_pinning += TV_ELAPSED (btv, atv);
- SGEN_LOG (2, "Finding pinned pointers: %zd in %ld usecs", sgen_get_pinned_count (), TV_ELAPSED (btv, atv));
+ SGEN_LOG (2, "Finding pinned pointers: %zd in %lld usecs", sgen_get_pinned_count (), 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));
/* we don't have complete write barrier yet, so we scan all the old generation sections */
TV_GETTIME (btv);
time_minor_scan_remsets += TV_ELAPSED (atv, btv);
- SGEN_LOG (2, "Old generation scan: %ld usecs", TV_ELAPSED (atv, btv));
+ SGEN_LOG (2, "Old generation scan: %lld usecs", TV_ELAPSED (atv, btv));
sgen_pin_stats_print_class_stats ();
sgen_client_binary_protocol_reclaim_end (GENERATION_NURSERY);
TV_GETTIME (btv);
time_minor_fragment_creation += TV_ELAPSED (atv, btv);
- SGEN_LOG (2, "Fragment creation: %ld usecs, %lu bytes available", TV_ELAPSED (atv, btv), (unsigned long)fragment_total);
+ SGEN_LOG (2, "Fragment creation: %lld usecs, %lu bytes available", TV_ELAPSED (atv, btv), (unsigned long)fragment_total);
if (consistency_check_at_minor_collection)
sgen_check_major_refs ();
TV_GETTIME (btv);
time_major_pinning += TV_ELAPSED (atv, btv);
- SGEN_LOG (2, "Finding pinned pointers: %zd in %ld usecs", sgen_get_pinned_count (), TV_ELAPSED (atv, btv));
+ SGEN_LOG (2, "Finding pinned pointers: %zd in %lld usecs", sgen_get_pinned_count (), TV_ELAPSED (atv, btv));
SGEN_LOG (4, "Start scan with %zd pinned objects", sgen_get_pinned_count ());
major_collector.init_to_space ();
#include "config.h"
-#ifdef ENABLE_EXTENSION_MODULE
-#include "../../../mono-extensions/mono/utils/mono-signal-handler.h"
+/*
+ * When a signal is delivered to a thread on a Krait Android device
+ * that's in the middle of skipping over an "IT" block, such as this
+ * one:
+ *
+ * 0x40184ef0 <dlfree+1308>: ldr r1, [r3, #0]
+ * 0x40184ef2 <dlfree+1310>: add.w r5, r12, r2, lsl #3
+ * 0x40184ef6 <dlfree+1314>: lsls.w r2, r0, r2
+ * 0x40184efa <dlfree+1318>: tst r2, r1
+ * ### this is the IT instruction
+ * 0x40184efc <dlfree+1320>: itt eq
+ * 0x40184efe <dlfree+1322>: orreq r2, r1
+ * ### signal arrives here
+ * 0x40184f00 <dlfree+1324>: streq r2, [r3, #0]
+ * 0x40184f02 <dlfree+1326>: beq.n 0x40184f1a <dlfree+1350>
+ * 0x40184f04 <dlfree+1328>: ldr r2, [r5, #8]
+ * 0x40184f06 <dlfree+1330>: ldr r3, [r3, #16]
+ *
+ * then the first few (at most four, one would assume) instructions of
+ * the signal handler (!) might be skipped. They happen to be the
+ * push of the frame pointer and return address, so once the signal
+ * handler has done its work, it returns into a SIGSEGV.
+ */
+
+#if defined (TARGET_ARM) && defined (HAVE_ARMV7) && defined (TARGET_ANDROID)
+#define KRAIT_IT_BUG_WORKAROUND 1
+#endif
+
+#ifdef KRAIT_IT_BUG_WORKAROUND
+#define MONO_SIGNAL_HANDLER_FUNC(access, name, arglist) \
+ static void __krait_ ## name arglist; \
+ __attribute__ ((naked)) access void \
+ name arglist \
+ { \
+ asm volatile ( \
+ "mov r0, r0\n\t" \
+ "mov r0, r0\n\t" \
+ "mov r0, r0\n\t" \
+ "mov r0, r0\n\t"); \
+ asm volatile ( \
+ "bx %0" \
+ : : "r" (__krait_ ## name)); \
+ } \
+ static void __krait_ ## name arglist
#endif
+
/* Don't use this */
#ifndef MONO_SIGNAL_HANDLER_FUNC
#define MONO_SIGNAL_HANDLER_FUNC(access, name, arglist) access void name arglist