On Mon, 2009-07-06 at 01:16 +0200, Tomek Grabiec wrote:
> We cannot overwrite a register which is not saved (ESI) because this
> will lead to a corruption in JIT code. The proper solution is
> to copy the call arguments.
>
> Signed-off-by: Tomek Grabiec <[email protected]>
I'm confused. What exactly is the problem here and why do we need to
copy arguments?
> ---
> arch/x86/emit-code.c | 37 +++++++++++++++++++++++++++++++------
> include/jit/compiler.h | 3 ++-
> include/jit/emit-code.h | 3 ++-
> jit/trampoline.c | 7 ++++---
> 4 files changed, 39 insertions(+), 11 deletions(-)
>
> diff --git a/arch/x86/emit-code.c b/arch/x86/emit-code.c
> index 236ba0e..c4ba179 100644
> --- a/arch/x86/emit-code.c
> +++ b/arch/x86/emit-code.c
> @@ -1389,21 +1389,46 @@ void emit_trampoline(struct compilation_unit *cu,
> }
>
> void emit_jni_trampoline(struct buffer *buf, struct vm_jni_env *jni_env,
> - void *target)
> + void *target, struct vm_method *method)
> {
> + unsigned long args_size;
> +
> jit_text_lock();
>
> buf->buf = jit_text_ptr();
>
> - /* save return address into caller-saved register */
> - __emit_pop_reg(buf, REG_ESI);
> + __emit_push_reg(buf, REG_ESI);
> + __emit_push_reg(buf, REG_EDI);
> + __emit_push_reg(buf, REG_ECX);
> +
> + /*
> + * Make a copy of call arguments
> + */
> + __emit_mov_reg_reg(buf, REG_ESP, REG_ESI);
> + __emit_add_imm_reg(buf, (3 + 1) * sizeof(unsigned long), REG_ESI);
> +
> + args_size = sizeof(unsigned long) + (method->args_count + 1);
> +
> + __emit_add_imm_reg(buf, -args_size, REG_ESP);
> + __emit_mov_reg_reg(buf, REG_ESP, REG_EDI);
> +
> + __emit_mov_imm_reg(buf, method->args_count + 1, REG_ECX);
> +
> + /* CLD */
> + emit(buf, 0xfc);
> +
> + /* REP MOVSD */
> + emit(buf, 0xf3);
> + emit(buf, 0xa5);
>
> __emit_push_imm(buf, (unsigned long) jni_env);
> __emit_call(buf, target);
> - __emit_add_imm_reg(buf, 4, REG_ESP);
> + __emit_add_imm_reg(buf, args_size + sizeof(unsigned long), REG_ESP);
> +
> + __emit_pop_reg(buf, REG_ECX);
> + __emit_pop_reg(buf, REG_EDI);
> + __emit_pop_reg(buf, REG_ESI);
>
> - /* return to caller*/
> - __emit_push_reg(buf, REG_ESI);
> emit_ret(buf);
>
> jit_text_reserve(buffer_offset(buf));
> diff --git a/include/jit/compiler.h b/include/jit/compiler.h
> index 8584954..e2609ef 100644
> --- a/include/jit/compiler.h
> +++ b/include/jit/compiler.h
> @@ -14,6 +14,7 @@ struct compilation_unit;
> struct expression;
> struct statement;
> struct buffer;
> +struct vm_method;
>
> struct fixup_site {
> /* Compilation unit to which relcall_insn belongs */
> @@ -62,7 +63,7 @@ void *jit_magic_trampoline(struct compilation_unit *);
> struct jit_trampoline *alloc_jit_trampoline(void);
> struct jni_trampoline *alloc_jni_trampoline(void);
> struct jit_trampoline *build_jit_trampoline(struct compilation_unit *);
> -struct jni_trampoline *build_jni_trampoline(void *);
> +struct jni_trampoline *build_jni_trampoline(struct vm_method *, void *);
> void free_jit_trampoline(struct jit_trampoline *);
> void free_jni_trampoline(struct jni_trampoline *);
>
> diff --git a/include/jit/emit-code.h b/include/jit/emit-code.h
> index 07c41bf..291955f 100644
> --- a/include/jit/emit-code.h
> +++ b/include/jit/emit-code.h
> @@ -8,6 +8,7 @@ struct buffer;
> struct insn;
> struct vm_object;
> struct vm_jni_env;
> +struct vm_method;
>
> enum emitter_type {
> NO_OPERANDS = 1,
> @@ -39,6 +40,6 @@ extern void emit_body(struct basic_block *, struct buffer
> *);
> extern void backpatch_branch_target(struct buffer *buf, struct insn *insn,
> unsigned long target_offset);
> extern void emit_jni_trampoline(struct buffer *buf, struct vm_jni_env
> *jni_env,
> - void *target);
> + void *target, struct vm_method *method);
>
> #endif /* JATO_EMIT_CODE_H */
> diff --git a/jit/trampoline.c b/jit/trampoline.c
> index 0de2db5..42f3afa 100644
> --- a/jit/trampoline.c
> +++ b/jit/trampoline.c
> @@ -65,7 +65,8 @@ static void *jit_native_trampoline(struct compilation_unit
> *cu)
> add_cu_mapping((unsigned long)ret, cu);
>
> if (!method->jni_trampoline)
> - method->jni_trampoline = build_jni_trampoline(ret);
> + method->jni_trampoline =
> + build_jni_trampoline(method, ret);
>
> return buffer_ptr(method->jni_trampoline->objcode);
> }
> @@ -151,13 +152,13 @@ struct jit_trampoline *build_jit_trampoline(struct
> compilation_unit *cu)
> return trampoline;
> }
>
> -struct jni_trampoline *build_jni_trampoline(void *target)
> +struct jni_trampoline *build_jni_trampoline(struct vm_method *vmm, void
> *target)
> {
> struct jni_trampoline *trampoline;
>
> trampoline = alloc_jni_trampoline();
> if (trampoline)
> emit_jni_trampoline(trampoline->objcode, vm_jni_get_jni_env(),
> - target);
> + target, vmm);
> return trampoline;
> }
------------------------------------------------------------------------------
_______________________________________________
Jatovm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jatovm-devel