It is needed to get rid of a branch instruction in throwing code which
omits pushing exception object reference on stack if it's supposed to
jump to exit block. Doing always 'leave' will assure that we can safely
always push exception object reference because it will be automatically
discarded.

Signed-off-by: Tomek Grabiec <[email protected]>
---
 arch/x86/emit-code_32.c           |   25 ++++++++++++++++---------
 arch/x86/include/arch/emit-code.h |    4 ++--
 jit/emit.c                        |    4 ++--
 test/arch-x86/emit-code-test_32.c |   15 ++-------------
 4 files changed, 22 insertions(+), 26 deletions(-)

diff --git a/arch/x86/emit-code_32.c b/arch/x86/emit-code_32.c
index fed4374..f031556 100644
--- a/arch/x86/emit-code_32.c
+++ b/arch/x86/emit-code_32.c
@@ -472,16 +472,23 @@ static void emit_ret(struct buffer *buf)
        emit(buf, 0xc3);
 }
 
+static void emit_leave(struct buffer *buf)
+{
+       emit(buf, 0xc9);
+}
+
 /*
  * Emitted code must not write to ECX register because it may hold
  * exception object reference when in unwind block
  */
-static void __emit_epilog(struct buffer *buf, unsigned long nr_locals)
+static void __emit_epilog(struct buffer *buf)
 {
-       if (nr_locals)
-               emit(buf, 0xc9);
-       else
-               __emit_pop_reg(buf, REG_EBP);
+       /*
+        * Always emit 'leave' even if method has no local variables
+        * becasue exception object reference might have been pushed
+        * on stack.
+        */
+       emit_leave(buf);
 
        /* Restore callee saved registers */
        __emit_pop_reg(buf, REG_EBX);
@@ -489,9 +496,9 @@ static void __emit_epilog(struct buffer *buf, unsigned long 
nr_locals)
        __emit_pop_reg(buf, REG_EDI);
 }
 
-void emit_epilog(struct buffer *buf, unsigned long nr_locals)
+void emit_epilog(struct buffer *buf)
 {
-       __emit_epilog(buf, nr_locals);
+       __emit_epilog(buf);
        emit_ret(buf);
 }
 
@@ -502,12 +509,12 @@ static void __emit_jmp(struct buffer *buf, unsigned long 
addr)
        emit_imm32(buf, addr - current - BRANCH_INSN_SIZE);
 }
 
-void emit_unwind(struct buffer *buf, unsigned long nr_locals)
+void emit_unwind(struct buffer *buf)
 {
        /* save exception object in ECX */
        __emit_pop_reg(buf, REG_ECX);
 
-       __emit_epilog(buf, nr_locals);
+       __emit_epilog(buf);
        __emit_jmp(buf, (unsigned long)&unwind);
 }
 
diff --git a/arch/x86/include/arch/emit-code.h 
b/arch/x86/include/arch/emit-code.h
index 5ae5d93..ee12875 100644
--- a/arch/x86/include/arch/emit-code.h
+++ b/arch/x86/include/arch/emit-code.h
@@ -7,9 +7,9 @@ struct basic_block;
 struct buffer;
 
 void emit_prolog(struct buffer *, unsigned long);
-void emit_epilog(struct buffer *, unsigned long);
+void emit_epilog(struct buffer *);
 void emit_body(struct basic_block *, struct buffer *);
 void emit_trampoline(struct compilation_unit *, void *, struct 
jit_trampoline*);
-void emit_unwind(struct buffer *, unsigned long);
+void emit_unwind(struct buffer *);
 
 #endif /* __X86_EMIT_CODE */
diff --git a/jit/emit.c b/jit/emit.c
index 22ab463..93d21e9 100644
--- a/jit/emit.c
+++ b/jit/emit.c
@@ -42,10 +42,10 @@ int emit_machine_code(struct compilation_unit *cu)
                emit_body(bb, cu->objcode);
 
        emit_body(cu->exit_bb, cu->objcode);
-       emit_epilog(cu->objcode, frame_size);
+       emit_epilog(cu->objcode);
 
        emit_body(cu->unwind_bb, cu->objcode);
-       emit_unwind(cu->objcode, frame_size);
+       emit_unwind(cu->objcode);
 
        return 0;
 }
diff --git a/test/arch-x86/emit-code-test_32.c 
b/test/arch-x86/emit-code-test_32.c
index a793713..0c2629d 100644
--- a/test/arch-x86/emit-code-test_32.c
+++ b/test/arch-x86/emit-code-test_32.c
@@ -153,24 +153,13 @@ void test_emit_prolog_has_locals(void)
        free_buffer(buf);
 }
 
-void test_emit_epilog_no_locals(void)
-{
-       unsigned char expected[] = { 0x5d, 0x5b, 0x5e, 0x5f, 0xc3 };
-       struct buffer *buf;
-
-       buf = alloc_buffer();
-       emit_epilog(buf, 0);
-       assert_mem_equals(expected, buffer_ptr(buf), ARRAY_SIZE(expected));
-       free_buffer(buf);
-}
-
-void test_emit_epilog_has_locals(void)
+void test_emit_epilog(void)
 {
        unsigned char expected[] = { 0xc9, 0x5b, 0x5e, 0x5f, 0xc3 };
        struct buffer *buf;
 
        buf = alloc_buffer();
-       emit_epilog(buf, 0x20);
+       emit_epilog(buf);
        assert_mem_equals(expected, buffer_ptr(buf), ARRAY_SIZE(expected));
        free_buffer(buf);
 }
-- 
1.6.0.6


------------------------------------------------------------------------------
Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT 
is a gathering of tech-side developers & brand creativity professionals. Meet
the minds behind Google Creative Lab, Visual Complexity, Processing, & 
iPhoneDevCamp as they present alongside digital heavyweights like Barbarian 
Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com 
_______________________________________________
Jatovm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to