On Tue, 2009-04-14 at 23:05 +0200, Tomek Grabiec wrote:
> Signed-off-by: Tomek Grabiec <[email protected]>

Applied, thanks! Please cc the mailing list for future patches.

>  Makefile                                       |    6 +-
>  arch/x86/emit-code_32.c                        |   95 
> +++++++++++++++++++++++-
>  arch/x86/include/arch/emit-code.h              |    3 +-
>  arch/x86/include/arch/memory.h                 |   11 +++
>  arch/x86/insn-selector_32.brg                  |   26 ++++++-
>  include/jit/compiler.h                         |   26 ++++++-
>  include/vm/method.h                            |    5 +
>  jamvm/class.c                                  |    2 +-
>  jit/emit.c                                     |    3 +
>  jit/fixup-site.c                               |   57 ++++++++++++++
>  jit/trace-jit.c                                |   11 +++
>  jit/trampoline.c                               |    5 +-
>  regression/jvm/TrampolineBackpatchingTest.java |   62 +++++++++++++++
>  regression/run-suite.sh                        |    1 +
>  test/arch-x86/Makefile                         |    1 +
>  test/arch-x86/insn-selector-test_32.c          |    8 +-
>  vm/jato.c                                      |    6 +-
>  17 files changed, 313 insertions(+), 15 deletions(-)
>  create mode 100644 arch/x86/include/arch/memory.h
>  create mode 100644 jit/fixup-site.c
>  create mode 100644 regression/jvm/TrampolineBackpatchingTest.java
> 
> diff --git a/Makefile b/Makefile
> index 84adf3a..9d4445e 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -64,7 +64,8 @@ JIT_OBJS = \
>       jit/trampoline.o        \
>       jit/tree-printer.o      \
>       jit/typeconv-bc.o       \
> -     jit/vtable.o
> +     jit/vtable.o            \
> +     jit/fixup-site.o
>  
>  VM_OBJS = \
>       vm/bitset.o             \
> @@ -195,7 +196,8 @@ REGRESSION_TEST_SUITE_CLASSES = \
>       regression/jamvm/SynchronizationTest.class \
>       regression/jamvm/MethodInvocationAndReturnTest.class \
>       regression/jamvm/ConversionTest.class \
> -     regression/jvm/PutstaticTest.class
> +     regression/jvm/PutstaticTest.class \
> +     regression/jvm/TrampolineBackpatchingTest.class \
>  
>  lib: $(CLASSPATH_CONFIG)
>       make -C lib/ JAVAC=$(JAVAC) GLIBJ=$(GLIBJ)
> diff --git a/arch/x86/emit-code_32.c b/arch/x86/emit-code_32.c
> index e3f6230..a838b05 100644
> --- a/arch/x86/emit-code_32.c
> +++ b/arch/x86/emit-code_32.c
> @@ -9,17 +9,23 @@
>  
>  #include <jit/basic-block.h>
>  #include <jit/statement.h>
> +#include <jit/compilation-unit.h>
> +#include <jit/compiler.h>
>  
> +#include <vm/list.h>
>  #include <vm/buffer.h>
> +#include <vm/method.h>
>  
>  #include <arch/emit-code.h>
>  #include <arch/instruction.h>
> +#include <arch/memory.h>
>  
>  #include <assert.h>
>  #include <errno.h>
>  #include <stdio.h>
>  #include <stdlib.h>
>  #include <stdbool.h>
> +#include <string.h>
>  
>  /*
>   *   __encode_reg:   Encode register to be used in IA-32 instruction.
> @@ -214,6 +220,17 @@ static void __emit_push_reg(struct buffer *buf, enum 
> machine_reg reg)
>       emit(buf, 0x50 + __encode_reg(reg));
>  }
>  
> +static void __emit_push_membase(struct buffer *buf, enum machine_reg src_reg,
> +                             unsigned long disp)
> +{
> +     __emit_membase_reg(buf, 0xff, src_reg, disp, REG_ESI);
> +}
> +
> +static void __emit_pop_reg(struct buffer *buf, enum machine_reg reg)
> +{
> +     emit(buf, 0x58 + __encode_reg(reg));
> +}
> +
>  static void emit_push_reg(struct buffer *buf, struct operand *operand)
>  {
>       __emit_push_reg(buf, mach_reg(&operand->reg));
> @@ -870,11 +887,85 @@ void emit_body(struct basic_block *bb, struct buffer 
> *buf)
>       bb->is_emitted = true;
>  }
>  
> -void emit_trampoline(struct compilation_unit *cu, void *call_target,
> -                  struct buffer *buf)
> +/*
> + * This fixes relative calls generated by EXPR_INVOKE.
> + *
> + * Please note, that this code does not care about icache flushing in
> + * MP environment. This may lead to a GPF when one CPU modifies code
> + * already prefetched by another CPU on some bogus Intel CPUs (see
> + * section 7.1.3 of "Intel 64 and IA-32 Architectures Software
> + * Developers Manual Volume 3A"). It is required for other CPUs to
> + * execute a serializing instruction (to flush instruction cache)
> + * between modification and execution of new instruction. To achieve
> + * this, we could suspend all threads before patching, and force them
> + * to execute flush_icache() on resume.
> + */
> +static void fixup_invoke(struct jit_trampoline *t, unsigned long target)
>  {
> +     struct fixup_site *this, *next;
> +
> +     pthread_mutex_lock(&t->mutex);
> +
> +     list_for_each_entry_safe(this, next, &t->fixup_site_list,
> +                              fixup_list_node) {
> +             unsigned char *site_addr;
> +             uint32_t new_target;
> +
> +             site_addr = fixup_site_addr(this);
> +             new_target = target - ((uint32_t)site_addr + CALL_INSN_SIZE);
> +             cpu_write_u32(site_addr+1, new_target);
> +
> +             list_del(&this->fixup_list_node);
> +             free_fixup_site(this);
> +     }
> +
> +     pthread_mutex_unlock(&t->mutex);
> +}
> +
> +/*
> + * This function replaces pointers in vtable so that they point
> + * directly to compiled code instead of trampoline code.
> + */
> +static void fixup_invokevirtual(struct compilation_unit *cu,
> +                             struct object *objref,
> +                             void *target)
> +{
> +     struct classblock *cb = CLASS_CB(objref->class);
> +
> +     cb->vtable.native_ptr[cu->method->method_table_index] = target;
> +}
> +
> +void emit_trampoline(struct compilation_unit *cu,
> +                  void *call_target,
> +                  struct jit_trampoline *trampoline)
> +{
> +     struct buffer *buf = trampoline->objcode;
> +
> +     /* This is for __builtin_return_address() to work and to access
> +        call arguments in correct manner. */
> +     __emit_push_reg(buf, REG_EBP);
> +     __emit_mov_reg_reg(buf, REG_ESP, REG_EBP);
> +
>       __emit_push_imm(buf, (unsigned long)cu);
>       __emit_call(buf, call_target);
> +
> +     __emit_push_reg(buf, REG_EAX);
> +
> +     if ((cu->method->access_flags & ACC_STATIC) ||
> +          method_is_constructor(cu->method)) {
> +             __emit_push_imm(buf, (unsigned long)trampoline);
> +             __emit_call(buf, fixup_invoke);
> +             __emit_add_imm_reg(buf, 0x4, REG_ESP);
> +     } else {
> +             __emit_push_membase(buf, REG_EBP, 0x08);
> +             __emit_push_imm(buf, (unsigned long)cu);
> +             __emit_call(buf, fixup_invokevirtual);
> +             __emit_add_imm_reg(buf, 0x08, REG_ESP);
> +     }
> +
> +     __emit_pop_reg(buf, REG_EAX);
> +
>       __emit_add_imm_reg(buf, 0x04, REG_ESP);
> +     __emit_pop_reg(buf, REG_EBP);
>       emit_indirect_jump_reg(buf, REG_EAX);
>  }
> diff --git a/arch/x86/include/arch/emit-code.h 
> b/arch/x86/include/arch/emit-code.h
> index c7ebb43..52d1ef4 100644
> --- a/arch/x86/include/arch/emit-code.h
> +++ b/arch/x86/include/arch/emit-code.h
> @@ -1,6 +1,7 @@
>  #ifndef __X86_EMIT_CODE_H
>  #define __X86_EMIT_CODE_H
>  
> +struct jit_trampoline;
>  struct compilation_unit;
>  struct basic_block;
>  struct buffer;
> @@ -8,6 +9,6 @@ struct buffer;
>  void emit_prolog(struct buffer *, unsigned long);
>  void emit_epilog(struct buffer *, unsigned long);
>  void emit_body(struct basic_block *, struct buffer *);
> -void emit_trampoline(struct compilation_unit *, void *, struct buffer *);
> +void emit_trampoline(struct compilation_unit *, void *, struct 
> jit_trampoline*);
>      
>  #endif /* __X86_EMIT_CODE */
> diff --git a/arch/x86/include/arch/memory.h b/arch/x86/include/arch/memory.h
> new file mode 100644
> index 0000000..e27c31b
> --- /dev/null
> +++ b/arch/x86/include/arch/memory.h
> @@ -0,0 +1,11 @@
> +#ifndef _MEMORY_H_
> +#define _MEMORY_H_
> +
> +#include <stdint.h>
> +
> +static inline void cpu_write_u32(unsigned char *p, uint32_t val)
> +{
> +     *((uint32_t*)p) = val;
> +}
> +
> +#endif
> diff --git a/arch/x86/insn-selector_32.brg b/arch/x86/insn-selector_32.brg
> index c11ec6a..c31cd99 100644
> --- a/arch/x86/insn-selector_32.brg
> +++ b/arch/x86/insn-selector_32.brg
> @@ -361,10 +361,21 @@ reg:    EXPR_INVOKE(arg) 1
>       struct expression *expr;
>       struct var_info *var;
>       void *target;
> +     struct insn *call_insn;
> +     bool is_compiled;
>  
>       expr   = to_expr(tree);
>       method = expr->target_method;
> -     target = trampoline_ptr(method);
> +
> +     pthread_mutex_lock(&method->compilation_unit->mutex);
> +     is_compiled = method->compilation_unit->is_compiled;
> +
> +     if (is_compiled)
> +             target = method_native_ptr(method);
> +     else
> +             target = method_trampoline_ptr(method);
> +
> +     pthread_mutex_unlock(&method->compilation_unit->mutex);
>  
>       var = get_fixed_var(s->b_parent, REG_EAX);
>       state->reg1 = var;
> @@ -374,7 +385,18 @@ reg:     EXPR_INVOKE(arg) 1
>               state->reg2 = var;
>       }
>  
> -     bb_add_insn(s, rel_insn(INSN_CALL_REL, (unsigned long) target));
> +     call_insn = rel_insn(INSN_CALL_REL, (unsigned long) target);
> +     bb_add_insn(s, call_insn);
> +
> +     if (!is_compiled) {
> +             struct fixup_site *fixup;
> +
> +             fixup = alloc_fixup_site();
> +             fixup->cu = s->b_parent;
> +             fixup->relcall_insn = call_insn;
> +
> +             trampoline_add_fixup_site(method->trampoline, fixup);
> +     }
>  
>       if (method->args_count)
>               method_args_cleanup(s, method->args_count);
> diff --git a/include/jit/compiler.h b/include/jit/compiler.h
> index 89f2f29..8fadc29 100644
> --- a/include/jit/compiler.h
> +++ b/include/jit/compiler.h
> @@ -6,12 +6,25 @@
>  #include <vm/buffer.h>
>  #include <vm/stack.h>
>  #include <vm/vm.h>
> +#include <pthread.h>
>  
>  struct buffer;
>  struct compilation_unit;
>  
> +struct fixup_site {
> +     /* Compilation unit to which relcall_insn belongs */
> +     struct compilation_unit *cu;
> +     /* We need this, because we don't have native pointer at
> +        instruction selection */
> +     struct insn *relcall_insn;
> +     struct list_head fixup_list_node;
> +};
> +
>  struct jit_trampoline {
>       struct buffer *objcode;
> +     struct list_head fixup_site_list;
> +     /* This mutex is protecting operations on fixup_site_list */
> +     pthread_mutex_t mutex;
>  };
>  
>  struct parse_context {
> @@ -41,7 +54,17 @@ void free_jit_trampoline(struct jit_trampoline *);
>  
>  int jit_prepare_method(struct methodblock *);
>  
> -static inline void *trampoline_ptr(struct methodblock *method)
> +struct fixup_site *alloc_fixup_site(void);
> +void free_fixup_site(struct fixup_site *);
> +void trampoline_add_fixup_site(struct jit_trampoline *, struct fixup_site *);
> +unsigned char *fixup_site_addr(struct fixup_site *);
> +
> +static inline void *method_native_ptr(struct methodblock *method)
> +{
> +     return buffer_ptr(method->compilation_unit->objcode);
> +}
> +
> +static inline void *method_trampoline_ptr(struct methodblock *method)
>  {
>       return buffer_ptr(method->trampoline->objcode);
>  }
> @@ -52,6 +75,7 @@ extern bool opt_trace_tree_ir;
>  extern bool opt_trace_liveness;
>  extern bool opt_trace_regalloc;
>  extern bool opt_trace_machine_code;
> +extern bool opt_trace_magic_trampoline;
>  
>  void trace_method(struct compilation_unit *);
>  void trace_cfg(struct compilation_unit *);
> diff --git a/include/vm/method.h b/include/vm/method.h
> index 6c0af65..142a8c9 100644
> --- a/include/vm/method.h
> +++ b/include/vm/method.h
> @@ -12,4 +12,9 @@ static inline enum vm_type method_return_type(struct 
> methodblock *method)
>       return str_to_type(return_type);
>  }
>  
> +static inline bool method_is_constructor(struct methodblock *method)
> +{
> +     return strcmp(method->name,"<init>") == 0;
> +}
> +
>  #endif
> diff --git a/jamvm/class.c b/jamvm/class.c
> index 1e09908..b546f5a 100644
> --- a/jamvm/class.c
> +++ b/jamvm/class.c
> @@ -984,7 +984,7 @@ void linkClass(Class *class) {
>         vtable_init(&cb->vtable, method_table_size);
>         for (i = 0; i < method_table_size; i++) {
>             mb = method_table[i];
> -           vtable_setup_method(&cb->vtable, mb->method_table_index, 
> trampoline_ptr(mb));
> +           vtable_setup_method(&cb->vtable, mb->method_table_index, 
> method_trampoline_ptr(mb));
>         }
>     }
>  
> diff --git a/jit/emit.c b/jit/emit.c
> index 0e7c990..1c8af96 100644
> --- a/jit/emit.c
> +++ b/jit/emit.c
> @@ -61,6 +61,9 @@ struct jit_trampoline *alloc_jit_trampoline(void)
>       if (!trampoline->objcode)
>               goto failed;
>  
> +     INIT_LIST_HEAD(&trampoline->fixup_site_list);
> +     pthread_mutex_init(&trampoline->mutex, NULL);
> +
>       return trampoline;
>  
>    failed:
> diff --git a/jit/fixup-site.c b/jit/fixup-site.c
> new file mode 100644
> index 0000000..9a63f28
> --- /dev/null
> +++ b/jit/fixup-site.c
> @@ -0,0 +1,57 @@
> +/*
> + * Copyright (c) 2009 Tomasz Grabiec
> + *
> + * This file is released under the GPL version 2 with the following
> + * clarification and special exception:
> + *
> + *     Linking this library statically or dynamically with other modules is
> + *     making a combined work based on this library. Thus, the terms and
> + *     conditions of the GNU General Public License cover the whole
> + *     combination.
> + *
> + *     As a special exception, the copyright holders of this library give you
> + *     permission to link this library with independent modules to produce an
> + *     executable, regardless of the license terms of these independent
> + *     modules, and to copy and distribute the resulting executable under 
> terms
> + *     of your choice, provided that you also meet, for each linked 
> independent
> + *     module, the terms and conditions of the license of that module. An
> + *     independent module is a module which is not derived from or based on
> + *     this library. If you modify this library, you may extend this 
> exception
> + *     to your version of the library, but you are not obligated to do so. If
> + *     you do not wish to do so, delete this exception statement from your
> + *     version.
> + *
> + * Please refer to the file LICENSE for details.
> + */
> +
> +#include <jit/compiler.h>
> +#include <memory.h>
> +#include <malloc.h>
> +
> +struct fixup_site *alloc_fixup_site(void)
> +{
> +     struct fixup_site *site;
> +
> +     site = malloc(sizeof(*site));
> +     memset(site, 0, sizeof(*site));
> +
> +     return site;
> +}
> +
> +void free_fixup_site(struct fixup_site *site)
> +{
> +     free(site);
> +}
> +
> +void trampoline_add_fixup_site(struct jit_trampoline *trampoline,
> +                            struct fixup_site *site)
> +{
> +     pthread_mutex_lock(&trampoline->mutex);
> +     list_add_tail(&site->fixup_list_node, &trampoline->fixup_site_list);
> +     pthread_mutex_unlock(&trampoline->mutex);
> +}
> +
> +unsigned char *fixup_site_addr(struct fixup_site *site)
> +{
> +     return buffer_ptr(site->cu->objcode) + site->relcall_insn->mach_offset;
> +}
> diff --git a/jit/trace-jit.c b/jit/trace-jit.c
> index c678ffc..5bdd36e 100644
> --- a/jit/trace-jit.c
> +++ b/jit/trace-jit.c
> @@ -27,6 +27,7 @@ bool opt_trace_tree_ir;
>  bool opt_trace_liveness;
>  bool opt_trace_regalloc;
>  bool opt_trace_machine_code;
> +bool opt_trace_magic_trampoline;
>  
>  void trace_method(struct compilation_unit *cu)
>  {
> @@ -159,3 +160,13 @@ void trace_machine_code(struct compilation_unit *cu)
>       disassemble(start, end);
>       printf("\n");
>  }
> +
> +void trace_magic_trampoline(struct compilation_unit *cu)
> +{
> +     printf("jit_magic_trampoline: ret0=%p, ret1=%p: %s.%s #%d\n",
> +            __builtin_return_address(1),
> +            __builtin_return_address(2),
> +            CLASS_CB(cu->method->class)->name,
> +            cu->method->name,
> +            cu->method->method_table_index);
> +}
> diff --git a/jit/trampoline.c b/jit/trampoline.c
> index 73c4438..cab6c09 100644
> --- a/jit/trampoline.c
> +++ b/jit/trampoline.c
> @@ -61,6 +61,9 @@ void *jit_magic_trampoline(struct compilation_unit *cu)
>  
>       pthread_mutex_lock(&cu->mutex);
>  
> +     if (opt_trace_magic_trampoline)
> +             trace_magic_trampoline(cu);
> +
>       if (cu->method->access_flags & ACC_NATIVE)
>               ret = jit_native_trampoline(cu);
>       else
> @@ -77,6 +80,6 @@ struct jit_trampoline *build_jit_trampoline(struct 
> compilation_unit *cu)
>       
>       trampoline = alloc_jit_trampoline();
>       if (trampoline)
> -             emit_trampoline(cu, jit_magic_trampoline, trampoline->objcode);
> +             emit_trampoline(cu, jit_magic_trampoline, trampoline);
>       return trampoline;
>  }
> diff --git a/regression/jvm/TrampolineBackpatchingTest.java 
> b/regression/jvm/TrampolineBackpatchingTest.java
> new file mode 100644
> index 0000000..cc6aecb
> --- /dev/null
> +++ b/regression/jvm/TrampolineBackpatchingTest.java
> @@ -0,0 +1,62 @@
> +/*
> + * Copyright (C) 2009 Tomasz Grabiec
> + *
> + * This file is released under the GPL version 2. Please refer to the file
> + * LICENSE for details.
> + */
> +package jvm;
> +
> +import jamvm.TestCase;
> +
> +/**
> + * @author Tomasz Grabiec
> + */
> +public class TrampolineBackpatchingTest extends TestCase {
> +
> +    public static int test(int x) {
> +        return x+x;
> +    }
> +
> +    public static int testBackpatchingOnTheFly(int x) {
> +        /* No trampoline call should be generated for this,
> +           because method test() is already compiled */
> +        return test(x);
> +    }
> +
> +    static void testVTableBackpatching() {
> +        /* Instantiating RuntimeException calls virtual method
> +           Throwable.fillInStackTrace.  This tests proper functioning
> +           of vtable back-patching */
> +        new RuntimeException("foo");
> +    }
> +
> +    public int testArg(int a) {
> +        return a+1;
> +    }
> +
> +    public static void main(String [] args) {
> +        int x;
> +        TrampolineBackpatchingTest t = new TrampolineBackpatchingTest();
> +
> +        /* Test backpatching of multiple call sites
> +           at once */
> +        x = 1;
> +        x = test(x);
> +        x = test(x);
> +        x = test(x);
> +        assertEquals(x, 8);
> +
> +        x = testBackpatchingOnTheFly(8);
> +        assertEquals(x, 16);
> +
> +        testVTableBackpatching();
> +
> +        /* Another invokevirtual backpatching test */
> +        x = 1;
> +        x = t.testArg(x);
> +        x = t.testArg(x);
> +        assertEquals(x, 3);
> +
> +        Runtime.getRuntime().halt(retval);
> +    }
> +}
> diff --git a/regression/run-suite.sh b/regression/run-suite.sh
> index 31a6740..af8b14d 100755
> --- a/regression/run-suite.sh
> +++ b/regression/run-suite.sh
> @@ -61,6 +61,7 @@ if [ -z "$CLASS_LIST" ]; then
>      run_java jamvm.MethodInvocationAndReturnTest 0
>      run_java jamvm.ControlTransferTest 0
>      run_java jvm.PutstaticTest 0
> +    run_java jvm.TrampolineBackpatchingTest 0
>  else 
>      for i in $CLASS_LIST; do
>       run_java $i 0
> diff --git a/test/arch-x86/Makefile b/test/arch-x86/Makefile
> index aba1a3b..11a30e3 100644
> --- a/test/arch-x86/Makefile
> +++ b/test/arch-x86/Makefile
> @@ -41,6 +41,7 @@ OBJS = \
>       ../../jit/stack-slot.o \
>       ../../jit/statement.o \
>       ../../jit/tree-printer.o \
> +     ../../jit/fixup-site.o \
>       ../../arch/x86/emit-code$(ARCH_POSTFIX).o \
>       ../../arch/x86/instruction.o \
>       ../../arch/x86/insn-selector$(ARCH_POSTFIX).o \
> diff --git a/test/arch-x86/insn-selector-test_32.c 
> b/test/arch-x86/insn-selector-test_32.c
> index fac248d..accb81f 100644
> --- a/test/arch-x86/insn-selector-test_32.c
> +++ b/test/arch-x86/insn-selector-test_32.c
> @@ -535,7 +535,7 @@ void test_select_invoke_without_arguments(void)
>       select_instructions(bb->b_parent);
>  
>       insn = list_first_entry(&bb->insn_list, struct insn, insn_list_node);
> -     assert_rel_insn(INSN_CALL_REL, (unsigned long) trampoline_ptr(&mb), 
> insn);
> +     assert_rel_insn(INSN_CALL_REL, (unsigned long) 
> method_trampoline_ptr(&mb), insn);
>  
>       free_jit_trampoline(mb.trampoline);
>       free_compilation_unit(mb.compilation_unit);
> @@ -575,7 +575,7 @@ void test_select_invoke_with_arguments(void)
>       assert_imm_insn(INSN_PUSH_IMM, 0x01, insn);
>  
>       insn = list_next_entry(&insn->insn_list_node, struct insn, 
> insn_list_node);
> -     assert_rel_insn(INSN_CALL_REL, (unsigned long) trampoline_ptr(&mb), 
> insn);
> +     assert_rel_insn(INSN_CALL_REL, (unsigned long) 
> method_trampoline_ptr(&mb), insn);
>  
>       insn = list_next_entry(&insn->insn_list_node, struct insn, 
> insn_list_node);
>       assert_imm_reg_insn(INSN_ADD_IMM_REG, 8, REG_ESP, insn);
> @@ -621,13 +621,13 @@ void 
> test_select_method_return_value_passed_as_argument(void)
>       select_instructions(bb->b_parent);
>  
>       insn = list_first_entry(&bb->insn_list, struct insn, insn_list_node);
> -     assert_rel_insn(INSN_CALL_REL, (unsigned long) 
> trampoline_ptr(&nested_mb), insn);
> +     assert_rel_insn(INSN_CALL_REL, (unsigned long) 
> method_trampoline_ptr(&nested_mb), insn);
>  
>       insn = list_next_entry(&insn->insn_list_node, struct insn, 
> insn_list_node);
>       assert_reg_insn(INSN_PUSH_REG, REG_EAX, insn);
>  
>       insn = list_next_entry(&insn->insn_list_node, struct insn, 
> insn_list_node);
> -     assert_rel_insn(INSN_CALL_REL, (unsigned long) trampoline_ptr(&mb), 
> insn);
> +     assert_rel_insn(INSN_CALL_REL, (unsigned long) 
> method_trampoline_ptr(&mb), insn);
>  
>       free_jit_trampoline(mb.trampoline);
>       free_compilation_unit(mb.compilation_unit);
> diff --git a/vm/jato.c b/vm/jato.c
> index eb361c0..5db42bc 100644
> --- a/vm/jato.c
> +++ b/vm/jato.c
> @@ -233,6 +233,10 @@ int parseCommandLine(int argc, char *argv[], InitArgs 
> *args) {
>              opt_trace_liveness = true;
>              opt_trace_regalloc = true;
>              opt_trace_machine_code = true;
> +            opt_trace_magic_trampoline = true;
> +
> +        } else if (strcmp(argv[i], "-Xtrace:trampoline") == 0) {
> +            opt_trace_magic_trampoline = true;
>  
>          } else if(strcmp(argv[i], "-Xtrace:asm") == 0) {
>              opt_trace_method = true;
> @@ -348,7 +352,7 @@ int main(int argc, char *argv[]) {
>              if (run_with_interpreter)
>                  executeStaticMethod(main_class, mb, array);
>           else {
> -             java_main_fn java_main = trampoline_ptr(mb);
> +             java_main_fn java_main = method_trampoline_ptr(mb);
>               java_main();
>           }
>       }


------------------------------------------------------------------------------
This SF.net email is sponsored by:
High Quality Requirements in a Collaborative Environment.
Download a free trial of Rational Requirements Composer Now!
http://p.sf.net/sfu/www-ibm-com
_______________________________________________
Jatovm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to