Save 64 bytes from most Linux/amd64 interpreter frames. (mono/mono#15926)
authorJay Krell <jaykrell@microsoft.com>
Wed, 31 Jul 2019 12:20:03 +0000 (05:20 -0700)
committerAlexander Köplinger <alex.koeplinger@outlook.com>
Wed, 31 Jul 2019 12:20:03 +0000 (14:20 +0200)
 Probably same on all 64bit architectures. half on 32bit.

before:
```
0000000000003ce0 <interp_exec_method_full>:
    3ce0: 55                    push   %rbp
    3ce1: 48 89 e5              mov    %rsp,%rbp
    3ce4: 41 57                 push   %r15
    3ce6: 41 56                 push   %r14
    3ce8: 41 55                 push   %r13
    3cea: 41 54                 push   %r12
    3cec: 49 89 f4              mov    %rsi,%r12
    3cef: 53                    push   %rbx
    3cf0: 48 89 fb              mov    %rdi,%rbx
    3cf3: 48 81 ec 78 01 00 00  sub    $0x178,%rsp
```

after:
```
0000000000003ce0 <interp_exec_method_full>:
    3ce0: 55                    push   %rbp
    3ce1: 48 89 e5              mov    %rsp,%rbp
    3ce4: 41 57                 push   %r15
    3ce6: 41 56                 push   %r14
    3ce8: 41 55                 push   %r13
    3cea: 41 54                 push   %r12
    3cec: 49 89 f4              mov    %rsi,%r12
    3cef: 53                    push   %rbx
    3cf0: 48 89 fb              mov    %rdi,%rbx
    3cf3: 48 81 ec 38 01 00 00  sub    $0x138,%rsp
```

It was 0x158 recently.

Some frames will be larger, i.e. dynamic + pinvoke.

Classic technique:
 pointer instead of struct
 initialized to null
 alloca it when needed and not null

A more detailed analysis might enable better, such as making
the parameter optional, and/or having the callee default it to its
local storage.

Commit migrated from https://github.com/mono/mono/commit/e0335d357056f9017f7c170ed41f5cb7e3e32399

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

index d3f5450..02a728b 100644 (file)
@@ -235,7 +235,7 @@ static void debug_enter (InterpFrame *frame, int *tracing)
 static void
 set_resume_state (ThreadContext *context, InterpFrame *frame)
 {
-       /* We have thrown an exception from a finally block. Some of the leave targets were unwinded already */ \
+       /* We have thrown an exception from a finally block. Some of the leave targets were unwinded already */
        while (frame->finally_ips &&
                   frame->finally_ips->data >= context->handler_ei->try_start &&
                   frame->finally_ips->data < context->handler_ei->try_end)
@@ -942,13 +942,9 @@ interp_throw (ThreadContext *context, MonoException *ex, InterpFrame *frame, gco
 
 #define THROW_EX(exception,ex_ip) THROW_EX_GENERAL ((exception), (ex_ip), FALSE)
 
-#define THROW_EX_OVF(ip) do { \
-       THROW_EX (mono_get_exception_overflow (), ip); \
-       } while (0)
+#define THROW_EX_OVF(ip) THROW_EX (mono_get_exception_overflow (), ip)
 
-#define THROW_EX_DIV_ZERO(ip) do { \
-       THROW_EX (mono_get_exception_divide_by_zero (), ip);    \
-       } while (0)
+#define THROW_EX_DIV_ZERO(ip) THROW_EX (mono_get_exception_divide_by_zero (), ip)
 
 #define NULL_CHECK(o) do { \
        if (G_UNLIKELY (!(o))) \
@@ -2945,6 +2941,8 @@ interp_exec_method_full (InterpFrame *frame, ThreadContext *context, FrameClause
        0 };
 #endif
 
+       MonoMethodPInvoke* piinfo = NULL;
+
        frame->ex = NULL;
        frame->finally_ips = NULL;
        frame->endfinally_ip = NULL;
@@ -3259,14 +3257,15 @@ interp_exec_method_full (InterpFrame *frame, ThreadContext *context, FrameClause
                        child_frame.stack_args = sp;
                        if (imethod->method->dynamic && csignature->pinvoke) {
                                MonoMarshalSpec **mspecs;
-                               MonoMethodPInvoke piinfo;
                                MonoMethod *m;
 
                                /* Pinvoke call is missing the wrapper. See mono_get_native_calli_wrapper */
                                mspecs = g_new0 (MonoMarshalSpec*, csignature->param_count + 1);
-                               memset (&piinfo, 0, sizeof (piinfo));
 
-                               m = mono_marshal_get_native_func_wrapper (m_class_get_image (imethod->method->klass), csignature, &piinfo, mspecs, code);
+                               piinfo = piinfo ? piinfo : g_newa (MonoMethodPInvoke, 1);
+                               memset (piinfo, 0, sizeof (*piinfo));
+
+                               m = mono_marshal_get_native_func_wrapper (m_class_get_image (imethod->method->klass), csignature, piinfo, mspecs, code);
 
                                for (int i = csignature->param_count; i >= 0; i--)
                                        if (mspecs [i])