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: 2 additions & 3 deletions src/mono/mono/mini/interp/interp-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ struct InterpMethod {
unsigned int vararg : 1;
unsigned int optimized : 1;
unsigned int needs_thread_attach : 1;
// If set, this method is MulticastDelegate.Invoke
unsigned int is_invoke : 1;
#if PROFILE_INTERP
long calls;
long opcounts;
Expand Down Expand Up @@ -298,9 +300,6 @@ mono_interp_jit_call_supported (MonoMethod *method, MonoMethodSignature *sig);
void
mono_interp_error_cleanup (MonoError *error);

gboolean
mono_interp_is_method_multicastdelegate_invoke (MonoMethod *method);

#if HOST_BROWSER

gboolean
Expand Down
24 changes: 7 additions & 17 deletions src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,8 @@ mono_interp_get_imethod (MonoMethod *method)
imethod->hasthis = sig->hasthis;
imethod->vararg = sig->call_convention == MONO_CALL_VARARG;
imethod->code_type = IMETHOD_CODE_UNKNOWN;
// This flag allows us to optimize out the interp_entry 'is this a delegate invoke' checks
imethod->is_invoke = (m_class_get_parent (method->klass) == mono_defaults.multicastdelegate_class) && !strcmp(method->name, "Invoke");
// always optimize code if tiering is disabled
// always optimize wrappers
if (!mono_interp_tiering_enabled () || method->wrapper_type != MONO_WRAPPER_NONE)
Expand Down Expand Up @@ -2161,12 +2163,6 @@ typedef struct {
gpointer *many_args;
} InterpEntryData;

static MONO_ALWAYS_INLINE gboolean
is_method_multicastdelegate_invoke (MonoMethod *method)
{
return m_class_get_parent (method->klass) == mono_defaults.multicastdelegate_class && !strcmp (method->name, "Invoke");
}

/* Main function for entering the interpreter from compiled code */
// Do not inline in case order of frame addresses matters.
static MONO_NEVER_INLINE void
Expand Down Expand Up @@ -2196,7 +2192,7 @@ interp_entry (InterpEntryData *data)

method = rmethod->method;

if (is_method_multicastdelegate_invoke(method)) {
if (rmethod->is_invoke) {
/*
* This happens when AOT code for the invoke wrapper is not found.
* Have to replace the method with the wrapper here, since the wrapper depends on the delegate.
Expand Down Expand Up @@ -8591,36 +8587,30 @@ mono_jiterp_ld_delegate_method_ptr (gpointer *destination, MonoDelegate **source
*destination = imethod_to_ftnptr (del->interp_method, FALSE);
}

void
MONO_ALWAYS_INLINE void
mono_jiterp_check_pending_unwind (ThreadContext *context)
{
return check_pending_unwind (context);
}

void *
MONO_ALWAYS_INLINE void *
mono_jiterp_get_context (void)
{
return get_context ();
}

gpointer
MONO_ALWAYS_INLINE gpointer
mono_jiterp_frame_data_allocator_alloc (FrameDataAllocator *stack, InterpFrame *frame, int size)
{
return frame_data_allocator_alloc(stack, frame, size);
}

gboolean
MONO_ALWAYS_INLINE gboolean
mono_jiterp_isinst (MonoObject* object, MonoClass* klass)
{
return mono_interp_isinst (object, klass);
}

gboolean
mono_interp_is_method_multicastdelegate_invoke (MonoMethod *method)
{
return is_method_multicastdelegate_invoke (method);
}

// after interp_entry_prologue the wrapper will set up all the argument values
// in the correct place and compute the stack offset, then it passes that in to this
// function in order to actually enter the interpreter and process the return value
Expand Down
9 changes: 3 additions & 6 deletions src/mono/mono/mini/interp/jiterpreter.c
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,6 @@ EMSCRIPTEN_KEEPALIVE stackval *
mono_jiterp_interp_entry_prologue (JiterpEntryData *data, void *this_arg)
{
stackval *sp_args;
MonoMethod *method;
InterpMethod *rmethod;
ThreadContext *context;

Expand All @@ -572,23 +571,21 @@ mono_jiterp_interp_entry_prologue (JiterpEntryData *data, void *this_arg)
jiterp_assert(data);
rmethod = data->header.rmethod;
jiterp_assert(rmethod);
method = rmethod->method;
jiterp_assert(method);

if (mono_interp_is_method_multicastdelegate_invoke(method)) {
// Is this method MulticastDelegate.Invoke?
if (rmethod->is_invoke) {
// Copy the current state of the cache before using it
JiterpEntryDataCache cache = data->cache;
if (this_arg && (cache.delegate_invoke_is_for == (MonoDelegate*)this_arg)) {
// We previously cached the invoke for this delegate
method = cache.delegate_invoke;
data->header.rmethod = rmethod = cache.delegate_invoke_rmethod;
} else {
/*
* This happens when AOT code for the invoke wrapper is not found.
* Have to replace the method with the wrapper here, since the wrapper depends on the delegate.
*/
MonoDelegate *del = (MonoDelegate*)this_arg;
method = mono_marshal_get_delegate_invoke (method, del);
MonoMethod *method = mono_marshal_get_delegate_invoke (rmethod->method, del);
data->header.rmethod = rmethod = mono_interp_get_imethod (method);

// Cache the delegate invoke. This works because data was allocated statically
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/interp/tiering.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ get_tier_up_imethod (InterpMethod *imethod)
new_imethod->code_type = imethod->code_type;
new_imethod->rtype = imethod->rtype;
new_imethod->param_types = imethod->param_types;
new_imethod->is_invoke = imethod->is_invoke;
new_imethod->optimized = TRUE;
new_imethod->prof_flags = imethod->prof_flags;

Expand Down
7 changes: 7 additions & 0 deletions src/mono/wasm/runtime/jiterpreter-interp-entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ typedef struct {
gpointer args [16];
gpointer *many_args;
} InterpEntryData;

typedef struct {
InterpMethod *rmethod; // 0
ThreadContext *context; // 4
gpointer orig_domain; // 8
gpointer attach_cookie; // 12
} JiterpEntryDataHeader;
*/

const // offsetOfStack = 12,
Expand Down