Skip to content

Commit 916c691

Browse files
authored
[wasm] optimize out 'is this method MulticastDelegate.Invoke' checks in aot->interp transitions (#80181)
* When creating an InterpMethod, identify whether it is MulticastDelegate.Invoke and store that in a flag to optimize interp_entry * Always inline some jiterpreter APIs
1 parent 436277f commit 916c691

File tree

5 files changed

+20
-26
lines changed

5 files changed

+20
-26
lines changed

src/mono/mono/mini/interp/interp-internals.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ struct InterpMethod {
169169
unsigned int vararg : 1;
170170
unsigned int optimized : 1;
171171
unsigned int needs_thread_attach : 1;
172+
// If set, this method is MulticastDelegate.Invoke
173+
unsigned int is_invoke : 1;
172174
#if PROFILE_INTERP
173175
long calls;
174176
long opcounts;
@@ -298,9 +300,6 @@ mono_interp_jit_call_supported (MonoMethod *method, MonoMethodSignature *sig);
298300
void
299301
mono_interp_error_cleanup (MonoError *error);
300302

301-
gboolean
302-
mono_interp_is_method_multicastdelegate_invoke (MonoMethod *method);
303-
304303
#if HOST_BROWSER
305304

306305
gboolean

src/mono/mono/mini/interp/interp.c

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,8 @@ mono_interp_get_imethod (MonoMethod *method)
488488
imethod->hasthis = sig->hasthis;
489489
imethod->vararg = sig->call_convention == MONO_CALL_VARARG;
490490
imethod->code_type = IMETHOD_CODE_UNKNOWN;
491+
// This flag allows us to optimize out the interp_entry 'is this a delegate invoke' checks
492+
imethod->is_invoke = (m_class_get_parent (method->klass) == mono_defaults.multicastdelegate_class) && !strcmp(method->name, "Invoke");
491493
// always optimize code if tiering is disabled
492494
// always optimize wrappers
493495
if (!mono_interp_tiering_enabled () || method->wrapper_type != MONO_WRAPPER_NONE)
@@ -2161,12 +2163,6 @@ typedef struct {
21612163
gpointer *many_args;
21622164
} InterpEntryData;
21632165

2164-
static MONO_ALWAYS_INLINE gboolean
2165-
is_method_multicastdelegate_invoke (MonoMethod *method)
2166-
{
2167-
return m_class_get_parent (method->klass) == mono_defaults.multicastdelegate_class && !strcmp (method->name, "Invoke");
2168-
}
2169-
21702166
/* Main function for entering the interpreter from compiled code */
21712167
// Do not inline in case order of frame addresses matters.
21722168
static MONO_NEVER_INLINE void
@@ -2196,7 +2192,7 @@ interp_entry (InterpEntryData *data)
21962192

21972193
method = rmethod->method;
21982194

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

8594-
void
8590+
MONO_ALWAYS_INLINE void
85958591
mono_jiterp_check_pending_unwind (ThreadContext *context)
85968592
{
85978593
return check_pending_unwind (context);
85988594
}
85998595

8600-
void *
8596+
MONO_ALWAYS_INLINE void *
86018597
mono_jiterp_get_context (void)
86028598
{
86038599
return get_context ();
86048600
}
86058601

8606-
gpointer
8602+
MONO_ALWAYS_INLINE gpointer
86078603
mono_jiterp_frame_data_allocator_alloc (FrameDataAllocator *stack, InterpFrame *frame, int size)
86088604
{
86098605
return frame_data_allocator_alloc(stack, frame, size);
86108606
}
86118607

8612-
gboolean
8608+
MONO_ALWAYS_INLINE gboolean
86138609
mono_jiterp_isinst (MonoObject* object, MonoClass* klass)
86148610
{
86158611
return mono_interp_isinst (object, klass);
86168612
}
86178613

8618-
gboolean
8619-
mono_interp_is_method_multicastdelegate_invoke (MonoMethod *method)
8620-
{
8621-
return is_method_multicastdelegate_invoke (method);
8622-
}
8623-
86248614
// after interp_entry_prologue the wrapper will set up all the argument values
86258615
// in the correct place and compute the stack offset, then it passes that in to this
86268616
// function in order to actually enter the interpreter and process the return value

src/mono/mono/mini/interp/jiterpreter.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,6 @@ EMSCRIPTEN_KEEPALIVE stackval *
563563
mono_jiterp_interp_entry_prologue (JiterpEntryData *data, void *this_arg)
564564
{
565565
stackval *sp_args;
566-
MonoMethod *method;
567566
InterpMethod *rmethod;
568567
ThreadContext *context;
569568

@@ -572,23 +571,21 @@ mono_jiterp_interp_entry_prologue (JiterpEntryData *data, void *this_arg)
572571
jiterp_assert(data);
573572
rmethod = data->header.rmethod;
574573
jiterp_assert(rmethod);
575-
method = rmethod->method;
576-
jiterp_assert(method);
577574

578-
if (mono_interp_is_method_multicastdelegate_invoke(method)) {
575+
// Is this method MulticastDelegate.Invoke?
576+
if (rmethod->is_invoke) {
579577
// Copy the current state of the cache before using it
580578
JiterpEntryDataCache cache = data->cache;
581579
if (this_arg && (cache.delegate_invoke_is_for == (MonoDelegate*)this_arg)) {
582580
// We previously cached the invoke for this delegate
583-
method = cache.delegate_invoke;
584581
data->header.rmethod = rmethod = cache.delegate_invoke_rmethod;
585582
} else {
586583
/*
587584
* This happens when AOT code for the invoke wrapper is not found.
588585
* Have to replace the method with the wrapper here, since the wrapper depends on the delegate.
589586
*/
590587
MonoDelegate *del = (MonoDelegate*)this_arg;
591-
method = mono_marshal_get_delegate_invoke (method, del);
588+
MonoMethod *method = mono_marshal_get_delegate_invoke (rmethod->method, del);
592589
data->header.rmethod = rmethod = mono_interp_get_imethod (method);
593590

594591
// Cache the delegate invoke. This works because data was allocated statically

src/mono/mono/mini/interp/tiering.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ get_tier_up_imethod (InterpMethod *imethod)
3232
new_imethod->code_type = imethod->code_type;
3333
new_imethod->rtype = imethod->rtype;
3434
new_imethod->param_types = imethod->param_types;
35+
new_imethod->is_invoke = imethod->is_invoke;
3536
new_imethod->optimized = TRUE;
3637
new_imethod->prof_flags = imethod->prof_flags;
3738

src/mono/wasm/runtime/jiterpreter-interp-entry.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ typedef struct {
3030
gpointer args [16];
3131
gpointer *many_args;
3232
} InterpEntryData;
33+
34+
typedef struct {
35+
InterpMethod *rmethod; // 0
36+
ThreadContext *context; // 4
37+
gpointer orig_domain; // 8
38+
gpointer attach_cookie; // 12
39+
} JiterpEntryDataHeader;
3340
*/
3441

3542
const // offsetOfStack = 12,

0 commit comments

Comments
 (0)