Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/libraries/tests.proj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
<ItemGroup Condition="'$(TargetOS)' == 'Browser' and '$(BuildAOTTestsOnHelix)' == 'true' and '$(RunDisabledWasmTests)' != 'true' and '$(RunAOTCompilation)' == 'true' and '$(BrowserHost)' != 'Windows'">
<!-- Exceeds VM resources in CI on compilation: https://github.com/dotnet/runtime/issues/61339 -->
<ProjectExclusions Include="$(MSBuildThisFileDirectory)Microsoft.Extensions.Logging.Abstractions\tests\Microsoft.Extensions.Logging.Generators.Tests\Microsoft.Extensions.Logging.Generators.Roslyn3.11.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)Microsoft.Extensions.Logging.Abstractions\tests\Microsoft.Extensions.Logging.Generators.Tests\Microsoft.Extensions.Logging.Generators.Roslyn4.0.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Text.Json\tests\System.Text.Json.SourceGeneration.Tests\System.Text.Json.SourceGeneration.
Roslyn4.0.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Text.Json\tests\System.Text.Json.SourceGeneration.Unit.Tests\System.Text.Json.SourceGeneration.Roslyn4.0.Unit.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Text.RegularExpressions\tests\System.Text.RegularExpressions.Generators.Tests\System.Text.RegularExpressions.Generators.Tests.csproj" />

<!-- https://github.com/dotnet/runtime/issues/61756 -->
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Text.RegularExpressions\tests\System.Text.RegularExpressions.Tests.csproj" />
Expand Down
7 changes: 7 additions & 0 deletions src/mono/mono/metadata/object-offsets.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,18 @@ DECL_OFFSET(SgenThreadInfo, tlab_temp_end)
#ifndef DISABLE_JIT_OFFSETS
DECL_SIZE(MonoMethodRuntimeGenericContext)
DECL_SIZE(MonoLMF)
DECL_SIZE(MonoLMFExt)
DECL_SIZE(MonoTypedRef)
DECL_SIZE(CallContext)
DECL_SIZE(MonoContext)

DECL_OFFSET(MonoLMF, previous_lmf)
DECL_OFFSET(MonoLMFExt, kind)
DECL_OFFSET(MonoLMFExt, il_state)

DECL_OFFSET(MonoMethodILState, method)
DECL_OFFSET(MonoMethodILState, il_offset)
DECL_OFFSET(MonoMethodILState, data)

DECL_OFFSET(MonoMethodRuntimeGenericContext, class_vtable)

Expand Down
4 changes: 3 additions & 1 deletion src/mono/mono/mini/ee.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#ifndef __MONO_EE_H__
#define __MONO_EE_H__

#define MONO_EE_API_VERSION 0x14
#define MONO_EE_API_VERSION 0x15

typedef struct _MonoInterpStackIter MonoInterpStackIter;

Expand All @@ -38,6 +38,7 @@ typedef gpointer MonoInterpFrameHandle;
MONO_EE_CALLBACK (void, get_resume_state, (const MonoJitTlsData *jit_tls, gboolean *has_resume_state, MonoInterpFrameHandle *interp_frame, gpointer *handler_ip)) \
MONO_EE_CALLBACK (gboolean, run_finally, (StackFrameInfo *frame, int clause_index, gpointer handler_ip, gpointer handler_ip_end)) \
MONO_EE_CALLBACK (gboolean, run_filter, (StackFrameInfo *frame, MonoException *ex, int clause_index, gpointer handler_ip, gpointer handler_ip_end)) \
MONO_EE_CALLBACK (gboolean, run_finally_with_il_state, (gpointer il_state, int clause_index, gpointer handler_ip, gpointer handler_ip_end)) \
MONO_EE_CALLBACK (void, frame_iter_init, (MonoInterpStackIter *iter, gpointer interp_exit_data)) \
MONO_EE_CALLBACK (gboolean, frame_iter_next, (MonoInterpStackIter *iter, StackFrameInfo *frame)) \
MONO_EE_CALLBACK (MonoJitInfo*, find_jit_info, (MonoMethod *method)) \
Expand All @@ -63,6 +64,7 @@ typedef gpointer MonoInterpFrameHandle;
MONO_EE_CALLBACK (gboolean, sufficient_stack, (gsize size)) \
MONO_EE_CALLBACK (void, entry_llvmonly, (gpointer res, gpointer *args, gpointer imethod)) \
MONO_EE_CALLBACK (gpointer, get_interp_method, (MonoMethod *method, MonoError *error)) \
MONO_EE_CALLBACK (MonoJitInfo*, compile_interp_method, (MonoMethod *method, MonoError *error)) \

typedef struct _MonoEECallbacks {

Expand Down
70 changes: 70 additions & 0 deletions src/mono/mono/mini/exceptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3029,6 +3029,76 @@ public static int test_0_unsigned_ct_div () {

return 0;
}

struct AStruct {
public int i1, i2, i3, i4;
}

// Running finally clauses with the interpreter in llvmonly-interp mode
public static int test_0_finally_deopt () {
int arg_i = 2;
var o = new ExceptionTests ();
try {
o.finally_deopt (1, 0, ref arg_i, new AStruct () { i1 = 1, i2 = 2, i3 = 3, i4 = 4 });
} catch (Exception) {
}
return finally_deopt_res;
}

static int dummy_static = 5;

[MethodImplAttribute (MethodImplOptions.NoInlining)]
static void throw_inner () {
// Avoid warnings/errors
if (dummy_static == 5)
throw new Exception ();
// Run with the interpreter
try {
throw new Exception ();
} catch (Exception) {
}
}

static int finally_deopt_res;

void finally_deopt (int arg_i, int unused_arg_i, ref int ref_arg_i, AStruct s) {
int i = 3;

try {
try {
i = 5;
throw_inner ();
} finally {
// Check that arguments/locals are copied correctly to the interpreter
object o = this;
if (!(o is ExceptionTests))
finally_deopt_res = 1;
if (arg_i != 1)
finally_deopt_res = 2;
arg_i ++;
if (i != 5)
finally_deopt_res = 3;
i ++;
if (ref_arg_i != 2)
finally_deopt_res = 4;
ref_arg_i ++;
if (s.i1 != 1 || s.i2 != 2)
finally_deopt_res = 5;
s.i1 ++;
s.i2 ++;
}
} finally {
// Check that arguments/locals were copied back after the first call to the interpreter
if (arg_i != 2)
finally_deopt_res = 10;
if (ref_arg_i != 3)
finally_deopt_res = 11;
if (i != 6)
finally_deopt_res = 12;
if (s.i1 != 2 || s.i2 != 3)
finally_deopt_res = 13;
}
}
}

#if !__MOBILE__
Expand Down
13 changes: 13 additions & 0 deletions src/mono/mono/mini/interp-stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ stub_run_filter (StackFrameInfo *frame, MonoException *ex, int clause_index, gpo
return FALSE;
}

static gboolean
stub_run_finally_with_il_state (gpointer il_state, int clause_index, gpointer handler_ip, gpointer handler_ip_end)
{
g_assert_not_reached ();
}

static void
stub_frame_iter_init (MonoInterpStackIter *iter, gpointer interp_exit_data)
{
Expand Down Expand Up @@ -239,6 +245,13 @@ stub_get_interp_method (MonoMethod *method, MonoError *error)
return NULL;
}

static MonoJitInfo*
stub_compile_interp_method (MonoMethod *method, MonoError *error)
{
g_assert_not_reached ();
return NULL;
}

#undef MONO_EE_CALLBACK
#define MONO_EE_CALLBACK(ret, name, sig) stub_ ## name,

Expand Down
182 changes: 182 additions & 0 deletions src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,70 @@ get_virtual_method_fast (InterpMethod *imethod, MonoVTable *vtable, int offset)
}
}

// Returns the size it uses on the interpreter stack
static int
stackval_size (MonoType *type, gboolean pinvoke)
{
type = mini_native_type_replace_type (type);
if (m_type_is_byref (type))
return MINT_STACK_SLOT_SIZE;
switch (type->type) {
case MONO_TYPE_VOID:
return 0;
case MONO_TYPE_I1:
case MONO_TYPE_U1:
case MONO_TYPE_BOOLEAN:
case MONO_TYPE_I2:
case MONO_TYPE_U2:
case MONO_TYPE_CHAR:
case MONO_TYPE_I4:
case MONO_TYPE_U:
case MONO_TYPE_I:
case MONO_TYPE_PTR:
case MONO_TYPE_FNPTR:
case MONO_TYPE_U4:
return MINT_STACK_SLOT_SIZE;
case MONO_TYPE_R4:
return MINT_STACK_SLOT_SIZE;
case MONO_TYPE_I8:
case MONO_TYPE_U8:
return MINT_STACK_SLOT_SIZE;
case MONO_TYPE_R8:
return MINT_STACK_SLOT_SIZE;
case MONO_TYPE_STRING:
case MONO_TYPE_SZARRAY:
case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
case MONO_TYPE_ARRAY:
return MINT_STACK_SLOT_SIZE;
case MONO_TYPE_VALUETYPE:
if (m_class_is_enumtype (type->data.klass)) {
return stackval_size (mono_class_enum_basetype_internal (type->data.klass), pinvoke);
} else {
int size;
if (pinvoke)
size = mono_class_native_size (type->data.klass, NULL);
else
size = mono_class_value_size (type->data.klass, NULL);
return ALIGN_TO (size, MINT_STACK_SLOT_SIZE);
}
case MONO_TYPE_GENERICINST: {
if (mono_type_generic_inst_is_valuetype (type)) {
MonoClass *klass = mono_class_from_mono_type_internal (type);
int size;
if (pinvoke)
size = mono_class_native_size (klass, NULL);
else
size = mono_class_value_size (klass, NULL);
return ALIGN_TO (size, MINT_STACK_SLOT_SIZE);
}
return stackval_size (m_class_get_byval_arg (type->data.generic_class->container_class), pinvoke);
}
default:
g_error ("got type 0x%02x", type->type);
}
}

// Returns the size it uses on the interpreter stack
static int
stackval_from_data (MonoType *type, stackval *result, const void *data, gboolean pinvoke)
Expand Down Expand Up @@ -2859,6 +2923,18 @@ interp_get_interp_method (MonoMethod *method, MonoError *error)
return mono_interp_get_imethod (method, error);
}

static MonoJitInfo*
interp_compile_interp_method (MonoMethod *method, MonoError *error)
{
InterpMethod *imethod = mono_interp_get_imethod (method, error);
return_val_if_nok (error, NULL);

mono_interp_transform_method (imethod, get_context (), error);
return_val_if_nok (error, NULL);

return imethod->jinfo;
}

static InterpMethod*
lookup_method_pointer (gpointer addr)
{
Expand Down Expand Up @@ -7187,6 +7263,112 @@ interp_run_filter (StackFrameInfo *frame, MonoException *ex, int clause_index, g
return retval.data.i ? TRUE : FALSE;
}

static gboolean
interp_run_finally_with_il_state (gpointer il_state_ptr, int clause_index, gpointer handler_ip, gpointer handler_ip_end)
{
MonoMethodILState *il_state = (MonoMethodILState*)il_state_ptr;
MonoMethodSignature *sig;
ThreadContext *context = get_context ();
stackval *sp, *sp_args;
InterpMethod *imethod;
FrameClauseArgs clause_args;
ERROR_DECL (error);

// FIXME: Optimize this ? Its only used during EH

sig = mono_method_signature_internal (il_state->method);
g_assert (sig);

imethod = mono_interp_get_imethod (il_state->method, error);
mono_error_assert_ok (error);

sp_args = sp = (stackval*)context->stack_pointer;

int findex = 0;
if (sig->hasthis) {
if (il_state->data [findex])
sp_args->data.p = *(gpointer*)il_state->data [findex];
sp_args++;
findex ++;
}

for (int i = 0; i < sig->param_count; ++i) {
if (il_state->data [findex]) {
int size = stackval_from_data (sig->params [i], sp_args, il_state->data [findex], FALSE);
sp_args = STACK_ADD_BYTES (sp_args, size);
} else {
int size = stackval_size (sig->params [i], FALSE);
sp_args = STACK_ADD_BYTES (sp_args, size);
}
findex ++;
}

/* Allocate frame */
InterpFrame frame = {0};
frame.imethod = imethod;
frame.stack = sp;
frame.retval = sp;

context->stack_pointer = (guchar*)sp_args;
context->stack_pointer += imethod->alloca_size;

MonoMethodHeader *header = mono_method_get_header_internal (il_state->method, error);
mono_error_assert_ok (error);

/* Init locals */
if (header->num_locals)
memset (frame_locals (&frame) + imethod->local_offsets [0], 0, imethod->locals_size);
/* Copy locals from il_state */
int locals_start = sig->hasthis + sig->param_count;
for (int i = 0; i < header->num_locals; ++i) {
if (il_state->data [locals_start + i])
stackval_from_data (header->locals [i], (stackval*)(frame_locals (&frame) + imethod->local_offsets [i]), il_state->data [locals_start + i], FALSE);
}

memset (&clause_args, 0, sizeof (FrameClauseArgs));
clause_args.start_with_ip = (const guint16*)handler_ip;
clause_args.end_at_ip = (const guint16*)handler_ip_end;
clause_args.exit_clause = clause_index;
clause_args.exec_frame = &frame;

// this informs MINT_ENDFINALLY to return to EH
*(guint16**)(frame_locals (&frame) + imethod->clause_data_offsets [clause_index]) = NULL;

interp_exec_method (&frame, context, &clause_args);

/* Write back args */
sp_args = sp;
findex = 0;
if (sig->hasthis) {
// FIXME: This
sp_args++;
findex ++;
}
findex = sig->hasthis ? 1 : 0;
for (int i = 0; i < sig->param_count; ++i) {
if (il_state->data [findex]) {
int size = stackval_to_data (sig->params [i], sp_args, il_state->data [findex], FALSE);
sp_args = STACK_ADD_BYTES (sp_args, size);
} else {
int size = stackval_size (sig->params [i], FALSE);
sp_args = STACK_ADD_BYTES (sp_args, size);
}
findex ++;
}
/* Write back locals */
for (int i = 0; i < header->num_locals; ++i) {
if (il_state->data [locals_start + i])
stackval_to_data (header->locals [i], (stackval*)(frame_locals (&frame) + imethod->local_offsets [i]), il_state->data [locals_start + i], FALSE);
}
mono_metadata_free_mh (header);

// FIXME: Restore stack ?
if (context->has_resume_state)
return TRUE;
else
return FALSE;
}

typedef struct {
InterpFrame *current;
} StackIter;
Expand Down
Loading