Stack unwinding will need a way to get the compilation_unit of
the caller. This will be also needed by printStackTrace to work.

Signed-off-by: Tomek Grabiec <[email protected]>
---
 arch/x86/emit-code_32.c               |   12 ++++++++-
 arch/x86/include/arch/emit-code.h     |    2 +-
 arch/x86/include/arch/stack-frame.h   |   15 ++++++++++
 arch/x86/stack-frame.c                |   46 +++++++++++++++++++++++++++++---
 jit/emit.c                            |    2 +-
 test/arch-mmix/stack-frame.c          |   41 +++++++++++++++++++++++++++++
 test/arch-x86/emit-code-test_32.c     |   24 +++++++++++-----
 test/arch-x86/insn-selector-test_32.c |   17 ++++++-----
 test/arch-x86/stack-frame-test_32.c   |   11 ++++---
 test/arch-x86/stack-frame-utils.h     |    7 +++++
 test/include/arch/stack-frame.h       |    9 ++++++
 11 files changed, 157 insertions(+), 29 deletions(-)
 create mode 100644 test/arch-mmix/stack-frame.c
 create mode 100644 test/arch-x86/stack-frame-utils.h

diff --git a/arch/x86/emit-code_32.c b/arch/x86/emit-code_32.c
index 3be09f1..62f2a1c 100644
--- a/arch/x86/emit-code_32.c
+++ b/arch/x86/emit-code_32.c
@@ -27,6 +27,9 @@
 #include <stdbool.h>
 #include <string.h>
 
+static void __emit_add_imm_reg(struct buffer *buf, long imm, enum machine_reg 
reg);
+static void __emit_push_imm(struct buffer *buf, long imm);
+
 /*
  *     __encode_reg:   Encode register to be used in IA-32 instruction.
  *     @reg: Register to encode.
@@ -394,8 +397,12 @@ static void emit_sbb_reg_reg(struct buffer *buf, struct 
operand *src,
        emit_reg_reg(buf, 0x1B, src, dest);
 }
 
-void emit_prolog(struct buffer *buf, unsigned long nr_locals)
+void emit_prolog(struct compilation_unit *cu, struct buffer *buf,
+                unsigned long nr_locals)
 {
+       /* push pointer to method's compilation unit */
+       __emit_push_imm(buf, (long)cu);
+
        /* Unconditionally push callee-saved registers */
        __emit_push_reg(buf, REG_EDI);
        __emit_push_reg(buf, REG_ESI);
@@ -474,6 +481,9 @@ void emit_epilog(struct buffer *buf, unsigned long 
nr_locals)
        __emit_pop_reg(buf, REG_ESI);
        __emit_pop_reg(buf, REG_EDI);
 
+       /* Discard compilation unit pointer */
+       __emit_add_imm_reg(buf, 0x04, REG_ESP);
+
        emit_ret(buf);
 }
 
diff --git a/arch/x86/include/arch/emit-code.h 
b/arch/x86/include/arch/emit-code.h
index 52d1ef4..1e8eb16 100644
--- a/arch/x86/include/arch/emit-code.h
+++ b/arch/x86/include/arch/emit-code.h
@@ -6,7 +6,7 @@ struct compilation_unit;
 struct basic_block;
 struct buffer;
 
-void emit_prolog(struct buffer *, unsigned long);
+void emit_prolog(struct compilation_unit *, 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 
jit_trampoline*);
diff --git a/arch/x86/include/arch/stack-frame.h 
b/arch/x86/include/arch/stack-frame.h
index ec1338a..d048375 100644
--- a/arch/x86/include/arch/stack-frame.h
+++ b/arch/x86/include/arch/stack-frame.h
@@ -6,8 +6,23 @@
 struct methodblock;
 struct expression;
 
+struct compilation_unit;
+
+struct jit_stack_frame {
+       struct jit_stack_frame *prev;
+       unsigned long old_ebx;
+       unsigned long old_esi;
+       unsigned long old_edi;
+       struct compilation_unit *cu;
+       unsigned long return_address;
+       unsigned long args[0];
+} __attribute__((packed));
+
 unsigned long frame_local_offset(struct methodblock *, struct expression *);
 unsigned long slot_offset(struct stack_slot *slot);
 unsigned long frame_locals_size(struct stack_frame *frame);
+unsigned long jit_frame_locals_offset(struct jit_stack_frame *frame);
+struct compilation_unit *get_cu_from_stack_frame(struct jit_stack_frame 
*frame);
+bool called_from_jitted(struct jit_stack_frame *frame);
 
 #endif
diff --git a/arch/x86/stack-frame.c b/arch/x86/stack-frame.c
index cf1a612..384ad43 100644
--- a/arch/x86/stack-frame.c
+++ b/arch/x86/stack-frame.c
@@ -25,15 +25,17 @@
  */
 
 #include <jit/expression.h>
+#include <jit/compilation-unit.h>
 #include <vm/vm.h>
 #include <arch/stack-frame.h>
 #include <stdlib.h>
 
 /*
- * The three callee-saved registers are unconditionally stored on the stack
- * after EIP and EBP (see emit_prolog() for details). Therefore, there are five
- * 32-bit stack slots before the first argument to a function as illustrated by
- * the following diagram:
+ * The three callee-saved registers are unconditionally stored on the
+ * stack after EIP and pointer to struct compilation_unit (see
+ * emit_prolog() for details). Therefore, there are five 32-bit stack
+ * slots before the first argument to a function as illustrated by the
+ * following diagram:
  *
  *     :              :  ^
  *     :              :  |  Higher memory addresses
@@ -42,6 +44,7 @@
  *     :     ...      :
  *     |    Arg 1     | <-- Start offset of arguments
  *     |   Old EIP    |
+ *     |     cu       | <-- pointer to struct compilation_unit
  *     |     EDI      |
  *     |     ESI      |
  *     |     EBX      |
@@ -51,7 +54,7 @@
  *     |   Local m    :
  *     +--------------+
  */
-#define ARGS_START_OFFSET (sizeof(unsigned long) * 5)
+#define ARGS_START_OFFSET offsetof(struct jit_stack_frame,args)
 
 static unsigned long __index_to_offset(unsigned long index)
 {
@@ -90,3 +93,36 @@ unsigned long frame_locals_size(struct stack_frame *frame)
        unsigned long nr_locals = frame->nr_local_slots - frame->nr_args;
        return __index_to_offset(nr_locals + frame->nr_spill_slots);
 }
+
+struct compilation_unit *get_cu_from_stack_frame(struct jit_stack_frame *frame)
+{
+       return frame->cu;
+}
+
+/* Points to the first address past text segment */
+extern char etext;
+
+/*
+ * Checks whether return address belongs to jitted or JATO method.
+ * This is used in deciding when to stop the unwind process upon
+ * exception throwing.
+ *
+ * It utilises the fact, that jitted code is allocated on heap. So by
+ * comparing return address with text segment end we can tell whether
+ * the caller is on heap or in text.
+ */
+bool called_from_jitted(struct jit_stack_frame *frame)
+{
+       return frame->return_address >= (unsigned long)&etext;
+}
+
+/*
+ * Returns total offset to subtract from ESP to reserve space for locals.
+ */
+unsigned long jit_frame_locals_offset(struct jit_stack_frame *frame)
+{
+       struct compilation_unit *cu = get_cu_from_stack_frame(frame);
+       unsigned long frame_size = frame_locals_size(cu->stack_frame);
+
+       return sizeof(unsigned long) * frame_size;
+}
diff --git a/jit/emit.c b/jit/emit.c
index 1c8af96..b36df07 100644
--- a/jit/emit.c
+++ b/jit/emit.c
@@ -37,7 +37,7 @@ int emit_machine_code(struct compilation_unit *cu)
 
        frame_size = frame_locals_size(cu->stack_frame);
 
-       emit_prolog(cu->objcode, frame_size);
+       emit_prolog(cu, cu->objcode, frame_size);
        for_each_basic_block(bb, &cu->bb_list)
                emit_body(bb, cu->objcode);
 
diff --git a/test/arch-mmix/stack-frame.c b/test/arch-mmix/stack-frame.c
new file mode 100644
index 0000000..c1da03b
--- /dev/null
+++ b/test/arch-mmix/stack-frame.c
@@ -0,0 +1,41 @@
+/*
+ * 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 <arch/stack-frame.h>
+
+struct jit_stack_frame {
+       unsigned long dummy;
+};
+
+struct compilation_unit *get_cu_from_stack_frame(struct jit_stack_frame *frame)
+{
+       return NULL;
+}
+
+bool called_from_jitted(struct jit_stack_frame *frame)
+{
+       return false;
+}
diff --git a/test/arch-x86/emit-code-test_32.c 
b/test/arch-x86/emit-code-test_32.c
index a793713..4cd81a7 100644
--- a/test/arch-x86/emit-code-test_32.c
+++ b/test/arch-x86/emit-code-test_32.c
@@ -16,6 +16,7 @@
 
 #include <test/vars.h>
 #include <libharness.h>
+#include <stack-frame-utils.h>
 
 static struct methodblock method;
 
@@ -133,29 +134,35 @@ static void assert_emit_insn_7(unsigned char opcode, 
unsigned char modrm,
 
 void test_emit_prolog_no_locals(void)
 {
-       unsigned char expected[] = { 0x57, 0x56, 0x53, 0x55, 0x89, 0xe5};
+       struct compilation_unit *cu = (struct compilation_unit*)0xcafebabe;
+       unsigned char expected[] = { 0x68, 0xbe, 0xba, 0xfe, 0xca, 0x57, 0x56,
+                                    0x53, 0x55, 0x89, 0xe5};
        struct buffer *buf;
 
        buf = alloc_buffer();
-       emit_prolog(buf, 0);
+       emit_prolog(cu, buf, 0);
        assert_mem_equals(expected, buffer_ptr(buf), ARRAY_SIZE(expected));
        free_buffer(buf);
 }
 
 void test_emit_prolog_has_locals(void)
 {
-       unsigned char expected[] = { 0x57, 0x56, 0x53, 0x55, 0x89, 0xe5, 0x81, 
0xec, 0x80, 0x00, 0x00, 0x00 };
+       struct compilation_unit *cu = (struct compilation_unit*)0xcafebabe;
+       unsigned char expected[] = { 0x68, 0xbe, 0xba, 0xfe, 0xca, 0x57, 0x56,
+                                    0x53, 0x55, 0x89, 0xe5, 0x81, 0xec, 0x80,
+                                    0x00, 0x00, 0x00 };
        struct buffer *buf;
 
        buf = alloc_buffer();
-       emit_prolog(buf, 0x20);
+       emit_prolog(cu, buf, 0x20);
        assert_mem_equals(expected, buffer_ptr(buf), ARRAY_SIZE(expected));
        free_buffer(buf);
 }
 
 void test_emit_epilog_no_locals(void)
 {
-       unsigned char expected[] = { 0x5d, 0x5b, 0x5e, 0x5f, 0xc3 };
+       unsigned char expected[] = { 0x5d, 0x5b, 0x5e, 0x5f, 0x83, 0xc4, 0x04,
+                                    0xc3 };
        struct buffer *buf;
 
        buf = alloc_buffer();
@@ -166,7 +173,8 @@ void test_emit_epilog_no_locals(void)
 
 void test_emit_epilog_has_locals(void)
 {
-       unsigned char expected[] = { 0xc9, 0x5b, 0x5e, 0x5f, 0xc3 };
+       unsigned char expected[] = { 0xc9, 0x5b, 0x5e, 0x5f, 0x83, 0xc4, 0x04,
+                                    0xc3 };
        struct buffer *buf;
 
        buf = alloc_buffer();
@@ -281,8 +289,8 @@ void test_emit_mov_reg_memlocal(void)
        slot = get_local_slot(frame, 0);
        wide_slot = get_local_slot(frame, 31);
 
-       assert_emit_insn_3(0x89, 0x45, 0x14, 
reg_memlocal_insn(INSN_MOV_REG_MEMLOCAL, &VAR_EAX, slot));
-       assert_emit_insn_6(0x89, 0x9d, 0x90, 0x00, 0x00, 0x00, 
reg_memlocal_insn(INSN_MOV_REG_MEMLOCAL, &VAR_EBX, wide_slot));
+       assert_emit_insn_3(0x89, 0x45, ARG_OFFSET(0), 
reg_memlocal_insn(INSN_MOV_REG_MEMLOCAL, &VAR_EAX, slot));
+       assert_emit_insn_6(0x89, 0x9d, ARG_OFFSET(31), 0x00, 0x00, 0x00, 
reg_memlocal_insn(INSN_MOV_REG_MEMLOCAL, &VAR_EBX, wide_slot));
 
        free_stack_frame(frame);
 }
diff --git a/test/arch-x86/insn-selector-test_32.c 
b/test/arch-x86/insn-selector-test_32.c
index b573ed4..eb33799 100644
--- a/test/arch-x86/insn-selector-test_32.c
+++ b/test/arch-x86/insn-selector-test_32.c
@@ -10,6 +10,7 @@
 #include <vm/vm.h>
 #include <vm/class.h>
 #include <arch/instruction.h>
+#include <stack-frame-utils.h>
 
 #include <test/vars.h>
 #include <test/vm.h>
@@ -177,14 +178,14 @@ void test_should_select_insn_for_every_statement(void)
        assert_memlocal_reg_insn(INSN_MOV_MEMLOCAL_REG, 0, dreg, insn);
 
        insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       assert_membase_reg_insn(INSN_ADD_MEMBASE_REG, REG_EBP, 24, dreg, insn);
+       assert_membase_reg_insn(INSN_ADD_MEMBASE_REG, REG_EBP, ARG_OFFSET(1), 
dreg, insn);
 
        insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
        dreg = mach_reg(&insn->dest.reg);
        assert_memlocal_reg_insn(INSN_MOV_MEMLOCAL_REG, 2, dreg, insn);
 
        insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       assert_membase_reg_insn(INSN_ADD_MEMBASE_REG, REG_EBP, 32, dreg, insn);
+       assert_membase_reg_insn(INSN_ADD_MEMBASE_REG, REG_EBP, ARG_OFFSET(3), 
dreg, insn);
 
        insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
        assert_reg_reg_insn(INSN_MOV_REG_REG, dreg, REG_EAX, insn);
@@ -235,7 +236,7 @@ static void assert_select_local_local_binop(enum 
binary_operator expr_op, enum i
 
        insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
        dreg = mach_reg(&insn->dest.reg);
-       assert_membase_reg_insn(insn_type, REG_EBP, 24, dreg, insn);
+       assert_membase_reg_insn(insn_type, REG_EBP, ARG_OFFSET(1), dreg, insn);
 
        free_compilation_unit(bb->b_parent);
 }
@@ -292,7 +293,7 @@ void test_select_local_local_mul(void)
        assert_reg_reg_insn(INSN_MOV_REG_REG, dreg, REG_EAX, insn);
 
        insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       assert_membase_reg_insn(INSN_MUL_MEMBASE_EAX, REG_EBP, 24, REG_EAX, 
insn);
+       assert_membase_reg_insn(INSN_MUL_MEMBASE_EAX, REG_EBP, ARG_OFFSET(1), 
REG_EAX, insn);
 
        free_compilation_unit(bb->b_parent);
 }
@@ -317,7 +318,7 @@ void test_select_local_local_div(void)
        assert_reg_reg_insn(INSN_CLTD_REG_REG, REG_EAX, REG_EDX, insn);
 
        insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       assert_membase_reg_insn(INSN_DIV_MEMBASE_REG, REG_EBP, 24, REG_EAX, 
insn);
+       assert_membase_reg_insn(INSN_DIV_MEMBASE_REG, REG_EBP, ARG_OFFSET(1), 
REG_EAX, insn);
 
        free_compilation_unit(bb->b_parent);
 }
@@ -342,7 +343,7 @@ void test_select_local_local_rem(void)
        assert_reg_reg_insn(INSN_CLTD_REG_REG, REG_EAX, REG_EDX, insn);
 
        insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       assert_membase_reg_insn(INSN_DIV_MEMBASE_REG, REG_EBP, 24, REG_EAX, 
insn);
+       assert_membase_reg_insn(INSN_DIV_MEMBASE_REG, REG_EBP, ARG_OFFSET(1), 
REG_EAX, insn);
 
        insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
        assert_reg_reg_insn(INSN_MOV_REG_REG, REG_EDX, REG_EAX, insn);
@@ -409,7 +410,7 @@ static void assert_select_local_local_shift(enum 
binary_operator expr_op, enum i
        assert_memlocal_reg_insn(INSN_MOV_MEMLOCAL_REG, 0, dreg, insn);
 
        insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       assert_membase_reg_insn(INSN_MOV_MEMBASE_REG, REG_EBP, 24, REG_ECX, 
insn);
+       assert_membase_reg_insn(INSN_MOV_MEMBASE_REG, REG_EBP, ARG_OFFSET(1), 
REG_ECX, insn);
 
        insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
        assert_reg_reg_insn(insn_type, REG_ECX, dreg, insn);
@@ -736,7 +737,7 @@ static void assert_select_if_statement_local_local(enum 
insn_type expected,
        assert_memlocal_reg_insn(INSN_MOV_MEMLOCAL_REG, 0, dreg, insn);
 
        insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       assert_membase_reg_insn(INSN_CMP_MEMBASE_REG, REG_EBP, 24, dreg, insn);
+       assert_membase_reg_insn(INSN_CMP_MEMBASE_REG, REG_EBP, ARG_OFFSET(1), 
dreg, insn);
 
        insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
        assert_branch_insn(expected, stmt->if_true, insn);
diff --git a/test/arch-x86/stack-frame-test_32.c 
b/test/arch-x86/stack-frame-test_32.c
index db53f06..0b03584 100644
--- a/test/arch-x86/stack-frame-test_32.c
+++ b/test/arch-x86/stack-frame-test_32.c
@@ -5,6 +5,7 @@
 #include <jit/expression.h>
 #include <vm/vm.h>
 #include <arch/stack-frame.h>
+#include <stack-frame-utils.h>
 #include <stdlib.h>
 #include <libharness.h>
 
@@ -19,13 +20,13 @@ static void assert_local_offset(unsigned long expected, 
struct expression *local
 
 void test_should_map_local_index_to_frame_offset(void)
 {
-       assert_local_offset(20, local_expr(J_INT, 0), 2);
-       assert_local_offset(24, local_expr(J_INT, 1), 2);
+       assert_local_offset(ARG_OFFSET(0), local_expr(J_INT, 0), 2);
+       assert_local_offset(ARG_OFFSET(1), local_expr(J_INT, 1), 2);
 }
 
 void test_should_map_local_variables_after_last_arg_at_negative_offsets(void)
 {
-       assert_local_offset(20, local_expr(J_INT, 0), 1);
+       assert_local_offset(ARG_OFFSET(0), local_expr(J_INT, 0), 1);
        assert_local_offset(-4, local_expr(J_INT, 1), 1);
        assert_local_offset(-8, local_expr(J_INT, 2), 1);
 }
@@ -43,8 +44,8 @@ void test_arguments_are_at_successive_positive_offsets(void)
        param1 = get_local_slot(frame, 0);
        param2 = get_local_slot(frame, 1);
 
-       assert_int_equals(0x14, slot_offset(param1));
-       assert_int_equals(0x18, slot_offset(param2));
+       assert_int_equals(ARG_OFFSET(0), slot_offset(param1));
+       assert_int_equals(ARG_OFFSET(1), slot_offset(param2));
 
        free_stack_frame(frame);
 }
diff --git a/test/arch-x86/stack-frame-utils.h 
b/test/arch-x86/stack-frame-utils.h
new file mode 100644
index 0000000..68836f3
--- /dev/null
+++ b/test/arch-x86/stack-frame-utils.h
@@ -0,0 +1,7 @@
+#ifndef _STACK_FRAME_UTILS_
+#define _STACK_FRAME_UTILS_
+
+#define ARGS_START_OFFSET (sizeof(unsigned long) * 6)
+#define ARG_OFFSET(x) (ARGS_START_OFFSET + (x) * sizeof(unsigned long))
+
+#endif
diff --git a/test/include/arch/stack-frame.h b/test/include/arch/stack-frame.h
index 946ac33..d8e5188 100644
--- a/test/include/arch/stack-frame.h
+++ b/test/include/arch/stack-frame.h
@@ -1,4 +1,13 @@
 #ifndef MMIX_STACK_FRAME_H
 #define MMIX_STACK_FRAME_H
 
+#include <stdlib.h>
+#include <stdbool.h>
+
+struct jit_stack_frame;
+struct compilation_unit;
+
+struct compilation_unit *get_cu_from_stack_frame(struct jit_stack_frame 
*frame);
+bool called_from_jitted(struct jit_stack_frame *frame);
+
 #endif /* MMIX_STACK_FRAME_H */
-- 
1.6.0.6


------------------------------------------------------------------------------
The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your
production scanning environment may not be a perfect world - but thanks to
Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700
Series Scanner you'll get full speed at 300 dpi even with all image 
processing features enabled. http://p.sf.net/sfu/kodak-com
_______________________________________________
Jatovm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to