// public static OpenMode FileAttr(int FileNumber){ throw null; }
[Fact]
+ [ActiveIssue("https://github.com/dotnet/runtime/issues/53815", typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser), nameof(PlatformDetection.IsMonoAOT))]
public void FileClose()
{
int fileNumber = FileSystem.FreeFile();
}
[Fact]
+ [ActiveIssue("https://github.com/dotnet/runtime/issues/53815", typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser), nameof(PlatformDetection.IsMonoAOT))]
public void FileOpen()
{
// OpenMode.Append:
// public static void WriteLine(int FileNumber, params object[] Output) { }
[Fact]
+ [ActiveIssue("https://github.com/dotnet/runtime/issues/53815", typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser), nameof(PlatformDetection.IsMonoAOT))]
public void Write_ArgumentException()
{
int fileNumber = FileSystem.FreeFile();
flags |= MONO_AOT_METHOD_FLAG_HAS_PATCHES;
if (needs_ctx && ctx)
flags |= MONO_AOT_METHOD_FLAG_HAS_CTX;
+ if (cfg->interp_entry_only)
+ flags |= MONO_AOT_METHOD_FLAG_INTERP_ENTRY_ONLY;
/* Saved into another table so it can be accessed without having access to this data */
cfg->aot_method_flags = flags;
if (mono_llvm_only) {
guint8 flags = amodule->method_flags_table [method_index];
/* The caller needs to looks this up, but its hard to do without constructing the full MonoJitInfo, so save it here */
- if (flags & MONO_AOT_METHOD_FLAG_GSHAREDVT_VARIABLE) {
+ if (flags & (MONO_AOT_METHOD_FLAG_GSHAREDVT_VARIABLE | MONO_AOT_METHOD_FLAG_INTERP_ENTRY_ONLY)) {
mono_aot_lock ();
if (!code_to_method_flags)
code_to_method_flags = g_hash_table_new (NULL, NULL);
MONO_AOT_METHOD_FLAG_HAS_CCTOR = 1,
MONO_AOT_METHOD_FLAG_GSHAREDVT_VARIABLE = 2,
MONO_AOT_METHOD_FLAG_HAS_PATCHES = 4,
- MONO_AOT_METHOD_FLAG_HAS_CTX = 8
+ MONO_AOT_METHOD_FLAG_HAS_CTX = 8,
+ MONO_AOT_METHOD_FLAG_INTERP_ENTRY_ONLY = 16,
} MonoAotMethodFlags;
typedef enum {
ERROR_DECL (error);
MonoLMFExt ext;
- interp_push_lmf (&ext, frame);
/*
* When explicitly throwing exception we pass the ip of the instruction that throws the exception.
* Offset the subtraction from interp_frame_get_ip, so we don't end up in prev instruction.
* Since ctx.ip is 0, this will start unwinding from the LMF frame
* pushed above, which points to our frames.
*/
- HandleExceptionCbData cb_data = { ex, &ctx };
- if (mono_aot_mode == MONO_AOT_MODE_LLVMONLY_INTERP) {
- gboolean thrown = FALSE;
- /*
- * If the exception is uncaught in interpreter code, mono_handle_exception_internal () will rethrow it.
- * Catch and rethrow it here again so we can pop the LMF.
- */
- mono_llvm_cpp_catch_exception (handle_exception_cb, &cb_data, &thrown);
- if (thrown) {
- interp_pop_lmf (&ext);
- mono_llvm_rethrow_exception ((MonoObject*)ex);
- }
- } else {
- handle_exception_cb (&cb_data);
- }
+ interp_push_lmf (&ext, frame);
+
+ mono_handle_exception (&ctx, (MonoObject*)ex);
+
+ interp_pop_lmf (&ext);
if (MONO_CONTEXT_GET_IP (&ctx) != 0) {
/* We need to unwind into non-interpreter code */
g_assert_not_reached ();
}
- interp_pop_lmf (&ext);
-
g_assert (context->has_resume_state);
}
context->stack_pointer = (guchar*)sp;
- g_assert (!context->has_resume_state);
g_assert (!context->safepoint_frame);
if (rmethod->needs_thread_attach)
if (mono_llvm_only) {
if (context->has_resume_state)
+ /* The exception will be handled in a frame above us */
mono_llvm_reraise_exception ((MonoException*)mono_gchandle_get_target_internal (context->exc_gchandle));
} else {
g_assert (!context->has_resume_state);
}
static MONO_NEVER_INLINE void
-do_jit_call (stackval *ret_sp, stackval *sp, InterpFrame *frame, InterpMethod *rmethod, MonoError *error)
+do_jit_call (ThreadContext *context, stackval *ret_sp, stackval *sp, InterpFrame *frame, InterpMethod *rmethod, MonoError *error)
{
MonoLMFExt ext;
JitCallInfo *cinfo;
}
interp_pop_lmf (&ext);
if (thrown) {
+ if (context->has_resume_state)
+ /*
+ * This happens when interp_entry calls mono_llvm_reraise_exception ().
+ */
+ return;
MonoObject *obj = mono_llvm_load_exception ();
g_assert (obj);
+ mono_llvm_clear_exception ();
mono_error_set_exception_instance (error, (MonoException*)obj);
return;
}
} else if (code_type == IMETHOD_CODE_COMPILED) {
frame->state.ip = ip;
error_init_reuse (error);
- do_jit_call ((stackval*)(locals + return_offset), (stackval*)(locals + call_args_offset), frame, cmethod, error);
+ do_jit_call (context, (stackval*)(locals + return_offset), (stackval*)(locals + call_args_offset), frame, cmethod, error);
if (!is_ok (error)) {
MonoException *ex = mono_error_convert_to_exception (error);
THROW_EX (ex, ip);
error_init_reuse (error);
/* for calls, have ip pointing at the start of next instruction */
frame->state.ip = ip + 4;
- do_jit_call ((stackval*)(locals + ip [1]), (stackval*)(locals + ip [2]), frame, rmethod, error);
+ do_jit_call (context, (stackval*)(locals + ip [1]), (stackval*)(locals + ip [2]), frame, rmethod, error);
if (!is_ok (error)) {
MonoException *ex = mono_error_convert_to_exception (error);
THROW_EX (ex, ip);
error_init_reuse (error);
frame->state.ip = ip + 6;
- do_jit_call ((stackval*)(locals + ip [1]), frame, rmethod, error);
+ do_jit_call (context, (stackval*)(locals + ip [1]), frame, rmethod, error);
if (!is_ok (error)) {
MonoException *ex = mono_error_convert_to_exception (error);
THROW_EX (ex, ip);
#include <mono/mini/mini.h>
#include <mono/mini/mini-runtime.h>
+#include <mono/mini/aot-runtime.h>
#include "mintops.h"
#include "interp-internals.h"
if (method->wrapper_type != MONO_WRAPPER_NONE)
return FALSE;
+ if (method->flags & METHOD_ATTRIBUTE_REQSECOBJ)
+ /* Used to mark methods containing StackCrawlMark locals */
+ return FALSE;
+
if (mono_aot_only && m_class_get_image (method->klass)->aot_module && !(method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) {
ERROR_DECL (error);
- gpointer addr = mono_jit_compile_method_jit_only (method, error);
- if (addr && is_ok (error))
- return TRUE;
+ gpointer addr = mono_aot_get_method (method, error);
+ if (addr && is_ok (error)) {
+ MonoAotMethodFlags flags = mono_aot_get_method_flags (addr);
+ if (!(flags & MONO_AOT_METHOD_FLAG_INTERP_ENTRY_ONLY))
+ return TRUE;
+ }
}
for (l = mono_interp_jit_classes; l; l = l->next) {
}
if (cfg->llvm_only && cfg->interp && cfg->method == method) {
- for (int i = 0; i < header->num_clauses; ++i) {
- MonoExceptionClause *clause = &header->clauses [i];
- if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY && clause->flags != MONO_EXCEPTION_CLAUSE_FAULT && clause->flags != MONO_EXCEPTION_CLAUSE_NONE)
- cfg->interp_entry_only = TRUE;
- }
+ if (!cfg->method->wrapper_type && header->num_clauses)
+ cfg->interp_entry_only = TRUE;
if (cfg->interp_entry_only)
emit_llvmonly_interp_entry (cfg, header);
* return \c MONO_FIRST_PASS_CALLBACK_TO_NATIVE).
*/
static MonoFirstPassResult
-handle_exception_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filter_idx, MonoJitInfo **out_ji, MonoJitInfo **out_prev_ji, MonoObject *non_exception, StackFrameInfo *catch_frame, gboolean *last_mono_wrapper_runtime_invoke)
+handle_exception_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filter_idx, MonoJitInfo **out_ji, MonoJitInfo **out_prev_ji,
+ MonoObject *non_exception, StackFrameInfo *catch_frame, gboolean *last_mono_wrapper_runtime_invoke, gboolean enable_trace)
{
ERROR_DECL (error);
MonoDomain *domain = mono_domain_get ();
*ctx = new_ctx;
continue;
case FRAME_TYPE_INTERP_ENTRY:
- if (mono_aot_mode == MONO_AOT_MODE_LLVMONLY_INTERP)
- /*
- * There might be AOTed frames above the intepreted frames which can handle the exception,
- * so stop first pass, the caller will rethrow the exception, starting the process again.
- */
- return MONO_FIRST_PASS_UNHANDLED;
*ctx = new_ctx;
continue;
case FRAME_TYPE_INTERP:
jit_tls->orig_ex_ctx_set = FALSE;
}
+ if (enable_trace) {
+ char *name = mono_method_get_full_name (method);
+ g_print ("[%p:] EXCEPTION running filter clause %d in '%s'.\n", (void*)(gsize)mono_native_thread_id_get (), i, name);
+ g_free (name);
+ }
+
if (ji->is_interp) {
/* The filter ends where the exception handler starts */
filtered = mini_get_interp_callbacks ()->run_filter (&frame, (MonoException*)ex_obj, i, ei->data.filter, ei->handler_start);
} else {
filtered = call_filter (ctx, ei->data.filter);
}
+
+ if (enable_trace)
+ g_print ("[%p:] EXCEPTION filter result: %d\n", (void*)(gsize)mono_native_thread_id_get (), filtered);
+
mini_get_dbg_callbacks ()->end_exception_filter (mono_ex, ctx, &initial_ctx);
if (filtered && out_filter_idx)
*out_filter_idx = filter_idx;
*/
memcpy (&jit_tls->orig_ex_ctx, ctx, sizeof (MonoContext));
+ gboolean enable_trace = FALSE;
+
if (!resume) {
MonoContext ctx_cp = *ctx;
if (mono_trace_is_enabled ()) {
}
g_print ("[%p:] EXCEPTION handling: %s.%s: %s\n", (void*)(gsize)mono_native_thread_id_get (), m_class_get_name_space (mono_object_class (obj)), m_class_get_name (mono_object_class (obj)), msg);
g_free (msg);
- if (mono_ex && mono_trace_eval_exception (mono_object_class (mono_ex)))
+ if (mono_ex && mono_trace_eval_exception (mono_object_class (mono_ex))) {
+ enable_trace = TRUE;
mono_print_thread_dump_from_ctx (ctx);
+ }
}
+
jit_tls->orig_ex_ctx_set = TRUE;
MONO_PROFILER_RAISE (exception_throw, (obj));
jit_tls->orig_ex_ctx_set = FALSE;
StackFrameInfo catch_frame;
MonoFirstPassResult res;
- res = handle_exception_first_pass (&ctx_cp, obj, &first_filter_idx, &ji, &prev_ji, non_exception, &catch_frame, &last_mono_wrapper_runtime_invoke);
+ res = handle_exception_first_pass (&ctx_cp, obj, &first_filter_idx, &ji, &prev_ji, non_exception, &catch_frame, &last_mono_wrapper_runtime_invoke, enable_trace);
if (res == MONO_FIRST_PASS_UNHANDLED) {
- if (mono_aot_mode == MONO_AOT_MODE_LLVMONLY_INTERP) {
- /* Reached the top interpreted frames, but there might be native frames above us */
- throw_exception (obj, TRUE);
- g_assert_not_reached ();
- }
if (mini_debug_options.break_on_exc)
G_BREAKPOINT ();
mini_get_dbg_callbacks ()->handle_exception ((MonoException *)obj, ctx, NULL, NULL);
gboolean use_interp = FALSE;
+ if (mono_aot_mode == MONO_AOT_MODE_LLVMONLY_INTERP)
+ /* The runtime invoke wrappers contain clauses so they are not AOTed */
+ use_interp = TRUE;
+
if (callee) {
compiled_method = mono_jit_compile_method_jit_only (callee, error);
if (!compiled_method) {