2 * trampoline.c: JIT trampoline code
5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Carlos Valiente <yo@virutass.net>
9 * (C) 2001 Ximian, Inc.
15 #include <mono/metadata/appdomain.h>
16 #include <mono/metadata/tabledefs.h>
17 #include <mono/arch/ppc/ppc-codegen.h>
18 #include <mono/metadata/mono-debug-debugger.h>
23 /* adapt to mini later... */
24 #define mono_jit_share_code (1)
27 * Address of the x86 trampoline code. This is used by the debugger to check
28 * whether a method is a trampoline.
30 guint8 *mono_generic_trampoline_code = NULL;
33 * get_unbox_trampoline:
35 * @addr: pointer to native code for @m
37 * when value type methods are called through the vtable we need to unbox the
38 * this argument. This method returns a pointer to a trampoline which does
39 * unboxing before calling the method
42 get_unbox_trampoline (MonoMethod *m, gpointer addr)
47 if (!m->signature->ret->byref && MONO_TYPE_ISSTRUCT (m->signature->ret))
50 start = code = g_malloc (20);
52 ppc_load (code, ppc_r11, addr);
53 ppc_mtctr (code, ppc_r11);
54 ppc_addi (code, this_pos, this_pos, sizeof (MonoObject));
55 ppc_bcctr (code, 20, 0);
56 g_assert ((code - start) <= 20);
61 /* Stack size for trampoline function */
64 /* Method-specific trampoline code framgment size */
65 #define METHOD_TRAMPOLINE_SIZE 64
68 * ppc_magic_trampoline:
69 * @code: pointer into caller code
70 * @method: the method to translate
73 * This method is called by the function 'arch_create_jit_trampoline', which in
74 * turn is called by the trampoline functions for virtual methods.
75 * After having called the JIT compiler to compile the method, it inspects the
76 * caller code to find the address of the method-specific part of the
77 * trampoline vtable slot for this method, updates it with a fragment that calls
78 * the newly compiled code and returns this address of the compiled code to
79 * 'arch_create_jit_trampoline'
82 ppc_magic_trampoline (MonoMethod *method, guint32 *code, char *sp)
88 EnterCriticalSection(metadata_section);
89 addr = mono_compile_method(method);
90 LeaveCriticalSection(metadata_section);
93 /* Locate the address of the method-specific trampoline. The call using
94 the vtable slot that took the processing flow to 'arch_create_jit_trampoline'
95 looks something like this:
97 mtlr rA ; Move rA (a register containing the
98 ; target address) to LR
99 blrl ; Call function at LR
101 PowerPC instructions are 32-bit long, which means that a 32-bit target
102 address cannot be encoded as an immediate value (because we already
103 have spent some bits to encode the branch instruction!). That's why a
104 'b'ranch to the contents of the 'l'ink 'r'egister (with 'l'ink register
105 update) is needed, instead of a simpler 'branch immediate'. This
106 complicates our purpose here, because 'blrl' overwrites LR, which holds
107 the value we're interested in.
109 Therefore, we need to locate the 'mtlr rA' instruction to know which
110 register LR was loaded from, and then retrieve the value from that
113 /* This is the 'blrl' instruction */
117 * Note that methods are called also with the bl opcode.
119 if (((*code) >> 26) == 18) {
120 ppc_patch (code, addr);
121 mono_arch_flush_icache (code, 4);
125 /* Sanity check: instruction must be 'blrl' */
126 g_assert(*code == 0x4e800021);
128 /* OK, we're now at the 'blrl' instruction. Now walk backwards
129 till we get to a 'mtlr rA' */
131 if((*code & 0x7c0803a6) == 0x7c0803a6) {
132 /* Here we are: we reached the 'mtlr rA'.
133 Extract the register from the instruction */
134 reg = (*code & 0x03e00000) >> 21;
136 case 0 : o = *((int *) (sp + STACK - 8)); break;
137 case 11: o = *((int *) (sp + STACK - 24)); break;
138 case 12: o = *((int *) (sp + STACK - 28)); break;
139 case 13: o = *((int *) (sp + STACK - 32)); break;
140 case 14: o = *((int *) (sp + STACK - 36)); break;
141 case 15: o = *((int *) (sp + STACK - 40)); break;
142 case 16: o = *((int *) (sp + STACK - 44)); break;
143 case 17: o = *((int *) (sp + STACK - 48)); break;
144 case 18: o = *((int *) (sp + STACK - 52)); break;
145 case 19: o = *((int *) (sp + STACK - 56)); break;
146 case 20: o = *((int *) (sp + STACK - 60)); break;
147 case 21: o = *((int *) (sp + STACK - 64)); break;
148 case 22: o = *((int *) (sp + STACK - 68)); break;
149 case 23: o = *((int *) (sp + STACK - 72)); break;
150 case 24: o = *((int *) (sp + STACK - 76)); break;
151 case 25: o = *((int *) (sp + STACK - 80)); break;
152 case 26: o = *((int *) (sp + STACK - 84)); break;
153 case 27: o = *((int *) (sp + STACK - 88)); break;
154 case 28: o = *((int *) (sp + STACK - 92)); break;
155 case 29: o = *((int *) (sp + STACK - 96)); break;
156 case 30: o = *((int *) (sp + STACK - 100)); break;
157 case 31: o = *((int *) (sp + STACK - 4)); break;
159 printf("%s: Unexpected register %d\n",
161 g_assert_not_reached();
167 /* this is not done for non-virtual calls, because in that case
168 we won't have an object, but the actual pointer to the
169 valuetype as the this argument
171 if (method->klass->valuetype)
172 addr = get_unbox_trampoline (method, addr);
174 /* Finally, replace the method-specific trampoline code (which called
175 the generic trampoline code) with a fragment that calls directly the
179 ppc_stwu (o, ppc_r1, -16, ppc_r1);
180 ppc_mflr (o, ppc_r0);
181 ppc_stw (o, ppc_r31, 12, ppc_r1);
182 ppc_stw (o, ppc_r0, 20, ppc_r1);
183 ppc_mr (o, ppc_r31, ppc_r1);
185 ppc_lis (o, ppc_r0, (guint32) addr >> 16);
186 ppc_ori (o, ppc_r0, ppc_r0, (guint32) addr & 0xffff);
187 ppc_mtlr (o, ppc_r0);
190 ppc_lwz (o, ppc_r11, 0, ppc_r1);
191 ppc_lwz (o, ppc_r0, 4, ppc_r11);
192 ppc_mtlr (o, ppc_r0);
193 ppc_lwz (o, ppc_r31, -4, ppc_r11);
194 ppc_mr (o, ppc_r1, ppc_r11);
197 mono_arch_flush_icache (start, o - start);
198 g_assert(o - start < METHOD_TRAMPOLINE_SIZE);
204 * arch_create_jit_trampoline:
205 * @method: pointer to the method info
207 * Creates a trampoline function for virtual methods. If the created
208 * code is called it first starts JIT compilation of method,
209 * and then calls the newly created method. It also replaces the
210 * corresponding vtable entry (see ppc_magic_trampoline).
212 * A trampoline consists of two parts: a main fragment, shared by all method
213 * trampolines, and some code specific to each method, which hard-codes a
214 * reference to that method and then calls the main fragment.
216 * The main fragment contains a call to 'ppc_magic_trampoline', which performs
217 * call to the JIT compiler and substitutes the method-specific fragment with
218 * some code that directly calls the JIT-compiled method.
220 * Returns: a pointer to the newly created code
223 mono_arch_create_jit_trampoline (MonoMethod *method)
226 static guint8 *vc = NULL;
228 /* previously created trampoline code */
232 /* we immediately compile runtime provided functions */
233 if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
234 method->info = mono_compile_method (method);
238 /* icalls use method->addr */
239 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
240 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
243 nm = mono_marshal_get_native_wrapper (method);
244 method->info = mono_compile_method (nm);
248 if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
249 return mono_arch_create_jit_trampoline (mono_marshal_get_synchronized_wrapper (method));
252 /* Now we'll create in 'buf' the PowerPC trampoline code. This
253 is the trampoline code common to all methods */
255 vc = buf = g_malloc(512);
257 /*-----------------------------------------------------------
258 STEP 0: First create a non-standard function prologue with a
259 stack size big enough to save our registers:
261 lr (We'll be calling functions here, so we
263 r0 (See ppc_magic_trampoline)
264 r1 (sp) (Stack pointer - must save)
265 r3-r10 Function arguments.
266 r11-r31 (See ppc_magic_trampoline)
267 method in r11 (See ppc_magic_trampoline)
269 This prologue is non-standard because r0 is not saved here - it
270 was saved in the method-specific trampoline code
271 -----------------------------------------------------------*/
273 ppc_stwu (buf, ppc_r1, -STACK, ppc_r1);
275 /* Save r0 before modifying it - we will need its contents in
276 'ppc_magic_trampoline' */
277 ppc_stw (buf, ppc_r0, STACK - 8, ppc_r1);
279 ppc_stw (buf, ppc_r31, STACK - 4, ppc_r1);
280 ppc_mr (buf, ppc_r31, ppc_r1);
282 /* Now save our registers. */
283 ppc_stw (buf, ppc_r3, STACK - 12, ppc_r1);
284 ppc_stw (buf, ppc_r4, STACK - 16, ppc_r1);
285 ppc_stw (buf, ppc_r5, STACK - 20, ppc_r1);
286 ppc_stw (buf, ppc_r6, STACK - 24, ppc_r1);
287 ppc_stw (buf, ppc_r7, STACK - 28, ppc_r1);
288 ppc_stw (buf, ppc_r8, STACK - 32, ppc_r1);
289 ppc_stw (buf, ppc_r9, STACK - 36, ppc_r1);
290 ppc_stw (buf, ppc_r10, STACK - 40, ppc_r1);
291 /* STACK - 44 contains r11, which is set in the method-specific
292 part of the trampoline (see bellow this 'if' block) */
293 ppc_stw (buf, ppc_r12, STACK - 48, ppc_r1);
294 ppc_stw (buf, ppc_r13, STACK - 52, ppc_r1);
295 ppc_stw (buf, ppc_r14, STACK - 56, ppc_r1);
296 ppc_stw (buf, ppc_r15, STACK - 60, ppc_r1);
297 ppc_stw (buf, ppc_r16, STACK - 64, ppc_r1);
298 ppc_stw (buf, ppc_r17, STACK - 68, ppc_r1);
299 ppc_stw (buf, ppc_r18, STACK - 72, ppc_r1);
300 ppc_stw (buf, ppc_r19, STACK - 76, ppc_r1);
301 ppc_stw (buf, ppc_r20, STACK - 80, ppc_r1);
302 ppc_stw (buf, ppc_r21, STACK - 84, ppc_r1);
303 ppc_stw (buf, ppc_r22, STACK - 88, ppc_r1);
304 ppc_stw (buf, ppc_r23, STACK - 92, ppc_r1);
305 ppc_stw (buf, ppc_r24, STACK - 96, ppc_r1);
306 ppc_stw (buf, ppc_r25, STACK - 100, ppc_r1);
307 ppc_stw (buf, ppc_r26, STACK - 104, ppc_r1);
308 ppc_stw (buf, ppc_r27, STACK - 108, ppc_r1);
309 ppc_stw (buf, ppc_r28, STACK - 112, ppc_r1);
310 ppc_stw (buf, ppc_r29, STACK - 116, ppc_r1);
311 ppc_stw (buf, ppc_r30, STACK - 120, ppc_r1);
312 /* Save 'method' pseudo-parameter - the one passed in r11 */
313 ppc_stw (buf, ppc_r11, STACK - 124, ppc_r1);
315 /*----------------------------------------------------------
316 STEP 1: call 'mono_get_lmf_addr()' to get the address of our
317 LMF. We'll need to restore it after the call to
318 'ppc_magic_trampoline' and before the call to the native
320 ----------------------------------------------------------*/
322 /* Calculate the address and make the call. Keep in mind that
323 we're using r0, so we'll have to restore it before calling
324 'ppc_magic_trampoline' */
325 ppc_lis (buf, ppc_r0, (guint32) mono_get_lmf_addr >> 16);
326 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) mono_get_lmf_addr & 0xffff);
327 ppc_mtlr (buf, ppc_r0);
330 /* XXX Update LMF !!! */
332 /*----------------------------------------------------------
333 STEP 2: call 'ppc_magic_trampoline()', who will compile the
334 code and fix the method vtable entry for us
335 ----------------------------------------------------------*/
339 /* Arg 1: MonoMethod *method. It was put in r11 by the
340 method-specific trampoline code, and then saved before the call
341 to mono_get_lmf_addr()'. Restore r11, by the way :-) */
342 ppc_lwz (buf, ppc_r3, STACK - 124, ppc_r1);
343 ppc_lwz (buf, ppc_r11, STACK - 44, ppc_r1);
345 /* Arg 2: code (next address to the instruction that called us) */
346 ppc_lwz (buf, ppc_r4, STACK + 4, ppc_r1);
348 /* Arg 3: stack pointer */
349 ppc_mr (buf, ppc_r5, ppc_r1);
351 /* Calculate call address, restore r0 and call
352 'ppc_magic_trampoline'. Return value will be in r3 */
353 ppc_lis (buf, ppc_r0, (guint32) ppc_magic_trampoline >> 16);
354 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_magic_trampoline & 0xffff);
355 ppc_mtlr (buf, ppc_r0);
356 ppc_lwz (buf, ppc_r0, STACK - 8, ppc_r1);
359 /* OK, code address is now on r3. Move it to r0, so that we
360 can restore r3 and use it from r0 later */
361 ppc_mr (buf, ppc_r0, ppc_r3);
364 /*----------------------------------------------------------
365 STEP 3: Restore the LMF
366 ----------------------------------------------------------*/
370 /*----------------------------------------------------------
371 STEP 4: call the compiled method
372 ----------------------------------------------------------*/
374 /* Restore registers */
376 ppc_lwz (buf, ppc_r3, STACK - 12, ppc_r1);
377 ppc_lwz (buf, ppc_r4, STACK - 16, ppc_r1);
378 ppc_lwz (buf, ppc_r5, STACK - 20, ppc_r1);
379 ppc_lwz (buf, ppc_r6, STACK - 24, ppc_r1);
380 ppc_lwz (buf, ppc_r7, STACK - 28, ppc_r1);
381 ppc_lwz (buf, ppc_r8, STACK - 32, ppc_r1);
382 ppc_lwz (buf, ppc_r9, STACK - 36, ppc_r1);
383 ppc_lwz (buf, ppc_r10, STACK - 40, ppc_r1);
385 /* We haven't touched any of these, so there's no need to
388 ppc_lwz (buf, ppc_r14, STACK - 56, ppc_r1);
389 ppc_lwz (buf, ppc_r15, STACK - 60, ppc_r1);
390 ppc_lwz (buf, ppc_r16, STACK - 64, ppc_r1);
391 ppc_lwz (buf, ppc_r17, STACK - 68, ppc_r1);
392 ppc_lwz (buf, ppc_r18, STACK - 72, ppc_r1);
393 ppc_lwz (buf, ppc_r19, STACK - 76, ppc_r1);
394 ppc_lwz (buf, ppc_r20, STACK - 80, ppc_r1);
395 ppc_lwz (buf, ppc_r21, STACK - 84, ppc_r1);
396 ppc_lwz (buf, ppc_r22, STACK - 88, ppc_r1);
397 ppc_lwz (buf, ppc_r23, STACK - 92, ppc_r1);
398 ppc_lwz (buf, ppc_r24, STACK - 96, ppc_r1);
399 ppc_lwz (buf, ppc_r25, STACK - 100, ppc_r1);
400 ppc_lwz (buf, ppc_r26, STACK - 104, ppc_r1);
401 ppc_lwz (buf, ppc_r27, STACK - 108, ppc_r1);
402 ppc_lwz (buf, ppc_r28, STACK - 112, ppc_r1);
403 ppc_lwz (buf, ppc_r29, STACK - 116, ppc_r1);
404 ppc_lwz (buf, ppc_r30, STACK - 120, ppc_r1);
407 /* Non-standard function epilogue. Instead of doing a proper
408 return, we just call the compiled code, so
409 that, when it finishes, the method returns here. */
411 ppc_mtlr (buf, ppc_r0);
414 /* Restore stack pointer, r31, LR and return to caller */
415 ppc_lwz (buf, ppc_r11, 0, ppc_r1);
416 ppc_lwz (buf, ppc_r31, -4, ppc_r11);
417 ppc_mr (buf, ppc_r1, ppc_r11);
418 ppc_lwz (buf, ppc_r0, 4, ppc_r1);
419 ppc_mtlr (buf, ppc_r0);
422 /* Flush instruction cache, since we've generated code */
423 mono_arch_flush_icache (vc, buf - vc);
426 g_assert ((buf - vc) <= 512);
429 /* This is the method-specific part of the trampoline. Its purpose is
430 to provide the generic part with the MonoMethod *method pointer. We'll
431 use r11 to keep that value, for instance. However, the generic part of
432 the trampoline relies on r11 having the same value it had before coming
433 here, so we must save it before. */
434 code = buf = g_malloc(METHOD_TRAMPOLINE_SIZE);
436 /* Save r11. There's nothing magic in the '44', its just an arbitrary
437 position - see above */
438 ppc_stw (buf, ppc_r11, -44, ppc_r1);
440 /* Now save LR - we'll overwrite it now */
441 ppc_mflr (buf, ppc_r11);
442 ppc_stw (buf, ppc_r11, 4, ppc_r1);
444 /* Prepare the jump to the generic trampoline code.*/
445 ppc_lis (buf, ppc_r11, (guint32) vc >> 16);
446 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) vc & 0xffff);
447 ppc_mtlr (buf, ppc_r11);
449 /* And finally put 'method' in r11 and fly! */
450 ppc_lis (buf, ppc_r11, (guint32) method >> 16);
451 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) method & 0xffff);
454 /* Flush instruction cache, since we've generated code */
455 mono_arch_flush_icache (code, buf - code);
458 g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
460 /* Store trampoline address */
463 mono_jit_stats.method_trampolines++;
471 * x86_magic_trampoline:
472 * @eax: saved x86 register
473 * @ecx: saved x86 register
474 * @edx: saved x86 register
475 * @esi: saved x86 register
476 * @edi: saved x86 register
477 * @ebx: saved x86 register
478 * @code: pointer into caller code
479 * @method: the method to translate
481 * This method is called by the trampoline functions for virtual
482 * methods. It inspects the caller code to find the address of the
483 * vtable slot, then calls the JIT compiler and writes the address
484 * of the compiled method back to the vtable. All virtual methods
485 * are called with: x86_call_membase (inst, basereg, disp). We always
486 * use 32 bit displacement to ensure that the length of the call
487 * instruction is 6 bytes. We need to get the value of the basereg
488 * and the constant displacement.
491 x86_magic_trampoline (int eax, int ecx, int edx, int esi, int edi,
492 int ebx, guint8 *code, MonoMethod *m)
499 EnterCriticalSection (metadata_section);
500 addr = mono_compile_method (m);
501 LeaveCriticalSection (metadata_section);
504 /* go to the start of the call instruction
506 * address_byte = (m << 6) | (o << 3) | reg
507 * call opcode: 0xff address_byte displacement
512 if ((code [1] != 0xe8) && (code [3] == 0xff) && ((code [4] & 0x18) == 0x10) && ((code [4] >> 6) == 1)) {
513 reg = code [4] & 0x07;
514 disp = (signed char)code [5];
516 if ((code [0] == 0xff) && ((code [1] & 0x18) == 0x10) && ((code [1] >> 6) == 2)) {
517 reg = code [1] & 0x07;
518 disp = *((gint32*)(code + 2));
519 } else if ((code [1] == 0xe8)) {
520 *((guint32*)(code + 2)) = (guint)addr - ((guint)code + 1) - 5;
522 } else if ((code [4] == 0xff) && (((code [5] >> 6) & 0x3) == 0) && (((code [5] >> 3) & 0x7) == 2)) {
524 * This is a interface call: should check the above code can't catch it earlier
525 * 8b 40 30 mov 0x30(%eax),%eax
529 reg = code [5] & 0x07;
531 printf ("Invalid trampoline sequence: %x %x %x %x %x %x %x\n", code [0], code [1], code [2], code [3],
532 code [4], code [5], code [6]);
533 g_assert_not_reached ();
557 g_assert_not_reached ();
562 if (m->klass->valuetype) {
563 return *((gpointer *)o) = get_unbox_trampoline (m, addr);
565 return *((gpointer *)o) = addr;
570 * mono_arch_create_jit_trampoline:
571 * @method: pointer to the method info
573 * Creates a trampoline function for virtual methods. If the created
574 * code is called it first starts JIT compilation of method,
575 * and then calls the newly created method. I also replaces the
576 * corresponding vtable entry (see x86_magic_trampoline).
578 * Returns: a pointer to the newly created code
581 mono_arch_create_jit_trampoline (MonoMethod *method)
585 /* previously created trampoline code */
589 /* we immediately compile runtime provided functions */
590 if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
591 method->info = mono_compile_method (method);
595 /* icalls use method->addr */
596 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
597 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
600 nm = mono_marshal_get_native_wrapper (method);
601 method->info = mono_compile_method (nm);
605 if (!mono_generic_trampoline_code) {
606 mono_generic_trampoline_code = buf = g_malloc (256);
607 /* save caller save regs because we need to do a call */
608 x86_push_reg (buf, X86_EDX);
609 x86_push_reg (buf, X86_EAX);
610 x86_push_reg (buf, X86_ECX);
614 /* save the IP (caller ip) */
615 x86_push_membase (buf, X86_ESP, 16);
617 x86_push_reg (buf, X86_EBX);
618 x86_push_reg (buf, X86_EDI);
619 x86_push_reg (buf, X86_ESI);
620 x86_push_reg (buf, X86_EBP);
622 /* save method info */
623 x86_push_membase (buf, X86_ESP, 32);
624 /* get the address of lmf for the current thread */
625 x86_call_code (buf, mono_get_lmf_addr);
627 x86_push_reg (buf, X86_EAX);
628 /* push *lfm (previous_lmf) */
629 x86_push_membase (buf, X86_EAX, 0);
631 x86_mov_membase_reg (buf, X86_EAX, 0, X86_ESP, 4);
634 /* push the method info */
635 x86_push_membase (buf, X86_ESP, 44);
636 /* push the return address onto the stack */
637 x86_push_membase (buf, X86_ESP, 52);
639 /* save all register values */
640 x86_push_reg (buf, X86_EBX);
641 x86_push_reg (buf, X86_EDI);
642 x86_push_reg (buf, X86_ESI);
643 x86_push_membase (buf, X86_ESP, 64); /* EDX */
644 x86_push_membase (buf, X86_ESP, 64); /* ECX */
645 x86_push_membase (buf, X86_ESP, 64); /* EAX */
647 x86_call_code (buf, x86_magic_trampoline);
648 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 8*4);
650 /* restore LMF start */
651 /* ebx = previous_lmf */
652 x86_pop_reg (buf, X86_EBX);
654 x86_pop_reg (buf, X86_EDI);
655 /* *(lmf) = previous_lmf */
656 x86_mov_membase_reg (buf, X86_EDI, 0, X86_EBX, 4);
657 /* discard method info */
658 x86_pop_reg (buf, X86_ESI);
659 /* restore caller saved regs */
660 x86_pop_reg (buf, X86_EBP);
661 x86_pop_reg (buf, X86_ESI);
662 x86_pop_reg (buf, X86_EDI);
663 x86_pop_reg (buf, X86_EBX);
664 /* discard save IP */
665 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 4);
666 /* restore LMF end */
668 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 16);
670 /* call the compiled method */
671 x86_jump_reg (buf, X86_EAX);
673 g_assert ((buf - mono_generic_trampoline_code) <= 256);
676 code = buf = g_malloc (16);
677 x86_push_imm (buf, method);
678 x86_jump_code (buf, mono_generic_trampoline_code);
679 g_assert ((buf - code) <= 16);
681 /* store trampoline address */
684 //mono_jit_stats.method_trampolines++;
692 * This method is only called when running in the Mono Debugger.
695 mono_debugger_create_notification_function (gpointer *notification_address)
699 ptr = buf = g_malloc0 (16);
701 if (notification_address)
702 *notification_address = buf;