Signed-off-by: Tomek Grabiec <tgrab...@gmail.com>
---
 include/vm/bytecodes.h |    7 +++--
 jit/subroutine.c       |   49 ++++++++++++++++++++++++++---------------------
 vm/bytecodes.c         |   29 ++++++++++++++++++++++-----
 3 files changed, 54 insertions(+), 31 deletions(-)

diff --git a/include/vm/bytecodes.h b/include/vm/bytecodes.h
index f83a80d..e4c2482 100644
--- a/include/vm/bytecodes.h
+++ b/include/vm/bytecodes.h
@@ -11,9 +11,10 @@ long bc_target_off(const unsigned char *);
 bool bc_is_athrow(unsigned char);
 bool bc_is_return(unsigned char);
 bool bc_is_jsr(unsigned char);
-bool bc_is_ret(unsigned char);
-bool bc_is_astore(unsigned char);
-unsigned char bc_get_astore_index(const unsigned char *);
+bool bc_is_ret(const unsigned char *);
+bool bc_is_astore(const unsigned char *);
+unsigned long bc_get_astore_index(const unsigned char *);
+unsigned long bc_get_ret_index(const unsigned char *);
 void bc_set_target_off(unsigned char *, long);
 
 void bytecode_disassemble(const unsigned char *, unsigned long);
diff --git a/jit/subroutine.c b/jit/subroutine.c
index c734c5b..bbfad16 100644
--- a/jit/subroutine.c
+++ b/jit/subroutine.c
@@ -47,7 +47,6 @@
 #include "cafebabe/line_number_table_attribute.h"
 #include "cafebabe/code_attribute.h"
 
-#define RET_INSN_SIZE 2
 #define PC_UNKNOWN ULONG_MAX
 
 struct code_state {
@@ -58,8 +57,9 @@ struct code_state {
 struct subroutine {
        unsigned long start_pc;
        unsigned long end_pc;
-       uint8_t ret_index;
-       unsigned long body_offset;
+       unsigned long ret_index;
+       unsigned long prolog_size;
+       unsigned long epilog_size;
 
        int nr_dependencies;
 
@@ -247,12 +247,12 @@ static void free_subroutine_scan_context(struct 
subroutine_scan_context *ctx)
 
 static inline unsigned long subroutine_get_body_size(struct subroutine *sub)
 {
-       return sub->end_pc - sub->start_pc - sub->body_offset;
+       return sub->end_pc - sub->start_pc - sub->prolog_size;
 }
 
 static inline unsigned long subroutine_get_size(struct subroutine *sub)
 {
-       return sub->end_pc + RET_INSN_SIZE - sub->start_pc;
+       return sub->end_pc + sub->epilog_size - sub->start_pc;
 }
 
 static struct subroutine *lookup_subroutine(struct inlining_context *ctx,
@@ -333,14 +333,15 @@ static int do_subroutine_scan(struct 
subroutine_scan_context *ctx,
 
                ctx->visited_code[pc]++;
 
-               if (bc_is_ret(c[pc]) && c[pc + 1] == ctx->sub->ret_index) {
+               if (bc_is_ret(&c[pc]) &&
+                   bc_get_ret_index(&c[pc]) == ctx->sub->ret_index) {
                        if (ctx->sub->end_pc == PC_UNKNOWN ||
                            pc > ctx->sub->end_pc)
                                ctx->sub->end_pc = pc;
                        return 0;
                }
 
-               if (bc_is_astore(c[pc]) &&
+               if (bc_is_astore(&c[pc]) &&
                    bc_get_astore_index(&c[pc]) == ctx->sub->ret_index)
                        return warn("return address override"), -EINVAL;
 
@@ -393,12 +394,12 @@ static int subroutine_scan(struct inlining_context *ctx, 
struct subroutine *sub)
        if (sub->start_pc >= ctx->code.code_length)
                return warn("invalid branch offset"), -EINVAL;
 
-       if (!bc_is_astore(ctx->code.code[sub->start_pc]))
+       if (!bc_is_astore(&ctx->code.code[sub->start_pc]))
                return warn("invalid subroutine start"), -EINVAL;
 
        sub->ret_index = bc_get_astore_index(&ctx->code.code[sub->start_pc]);
        target = next_pc(ctx->code.code, sub->start_pc);
-       sub->body_offset = target - sub->start_pc;
+       sub->prolog_size = target - sub->start_pc;
 
        struct subroutine_scan_context *sub_ctx =
                alloc_subroutine_scan_context(ctx, sub);
@@ -413,7 +414,7 @@ static int subroutine_scan(struct inlining_context *ctx, 
struct subroutine *sub)
                return err;
 
        if (sub->end_pc != PC_UNKNOWN)
-               return 0;
+               goto out;
 
        /*
         * In some situations ECJ compiler generates subroutines which
@@ -431,14 +432,18 @@ static int subroutine_scan(struct inlining_context *ctx, 
struct subroutine *sub)
        for (unsigned long pc = sub->start_pc; pc < ctx->code.code_length;
             pc = next_pc(ctx->code.code, pc))
        {
-               if (bc_is_ret(ctx->code.code[pc]) &&
-                   ctx->code.code[pc + 1] == sub->ret_index) {
+               if (bc_is_ret(&ctx->code.code[pc]) &&
+                   bc_get_ret_index(&ctx->code.code[pc]) == sub->ret_index) {
                        sub->end_pc = pc;
-                       return 0;
+                       goto out;
                }
        }
 
        return warn("subroutine end not found"), -EINVAL;
+
+ out:
+       sub->epilog_size = bc_insn_size(&ctx->code.code[sub->end_pc]);
+       return 0;
 }
 
 static int scan_subroutines(struct inlining_context *ctx)
@@ -619,9 +624,9 @@ static int bytecode_copy(struct code_state *dest, unsigned 
long *dest_pc,
                *dest_pc += count_1;
                src_pc += count_1;
 
-               src_pc += sub->end_pc + RET_INSN_SIZE - sub->start_pc;
+               src_pc += sub->end_pc + sub->epilog_size - sub->start_pc;
 
-               count_2 = upto - (sub->end_pc + RET_INSN_SIZE);
+               count_2 = upto - (sub->end_pc + sub->epilog_size);
                err = do_bytecode_copy(dest, *dest_pc, src, src_pc, count_2,
                                       pc_map);
                *dest_pc += count_2;
@@ -666,7 +671,7 @@ static int build_line_number_table(struct inlining_context 
*ctx)
        index = 0;
 
        bytecode_for_each_insn(code, code_length, pc) {
-               if (bc_is_jsr(code[pc]) || bc_is_ret(code[pc]))
+               if (bc_is_jsr(code[pc]) || bc_is_ret(&code[pc]))
                        continue;
 
                unsigned long line_no
@@ -730,7 +735,7 @@ copy_exception_handler(struct inlining_context *ctx, struct 
subroutine *s,
 
        eh = &ctx->exception_table[*eh_index];
 
-       body_start_pc = s->start_pc + s->body_offset;
+       body_start_pc = s->start_pc + s->prolog_size;
        body_size = subroutine_get_body_size(s);
 
        if (eh->start_pc < body_start_pc)
@@ -783,7 +788,7 @@ update_and_copy_exception_handlers(struct inlining_context 
*ctx,
                struct cafebabe_code_attribute_exception *eh
                        = &ctx->exception_table[i];
 
-               if (eh->start_pc >= s->end_pc + RET_INSN_SIZE ||
+               if (eh->start_pc >= s->end_pc + s->epilog_size ||
                    eh->end_pc <= s->start_pc) {
                        unsigned long start_pc, end_pc, handler_pc;
 
@@ -821,12 +826,12 @@ update_and_copy_exception_handlers(struct 
inlining_context *ctx,
                }
 
                if (eh->start_pc < s->start_pc ||
-                   eh->end_pc > s->end_pc + RET_INSN_SIZE)
+                   eh->end_pc > s->end_pc + s->epilog_size)
                        return warn("handler range spans subroutine boundary"),
                                -EINVAL;
 
                if (eh->handler_pc < s->start_pc ||
-                   eh->handler_pc >= s->end_pc + RET_INSN_SIZE)
+                   eh->handler_pc >= s->end_pc + s->epilog_size)
                        return warn("handler not inside subroutine"), -EINVAL;
 
                err = copy_exception_handler(ctx, s, &i, pc_map);
@@ -897,7 +902,7 @@ static int do_inline_subroutine(struct inlining_context 
*ctx,
 
                /* Inline subroutine */
                err = do_bytecode_copy(&new_code, new_code_pc, &ctx->code,
-                                      sub->body_offset + sub->start_pc,
+                                      sub->prolog_size + sub->start_pc,
                                       body_size, &pc_map);
                if (err)
                        goto error;
@@ -1066,7 +1071,7 @@ static int split_exception_handlers(struct 
inlining_context *ctx)
                for (int i = 0; i < this->nr_call_sites; i++) {
                        err = do_split_exception_handlers(ctx,
                                        this->call_sites[i], this->start_pc,
-                                       this->end_pc + RET_INSN_SIZE);
+                                       this->end_pc + this->epilog_size);
                        if (err)
                                return err;
                }
diff --git a/vm/bytecodes.c b/vm/bytecodes.c
index 10a39a0..8c6a5fa 100644
--- a/vm/bytecodes.c
+++ b/vm/bytecodes.c
@@ -92,14 +92,20 @@ bool bc_is_jsr(unsigned char opc)
        return opc == OPC_JSR || opc == OPC_JSR_W;
 }
 
-bool bc_is_ret(unsigned char opc)
+bool bc_is_ret(const unsigned char *code)
 {
-       return opc == OPC_RET;
+       if (*code == OPC_WIDE)
+               code++;
+
+       return *code == OPC_RET;
 }
 
-bool bc_is_astore(unsigned char opc)
+bool bc_is_astore(const unsigned char *code)
 {
-       switch (opc) {
+       if (*code == OPC_WIDE)
+               code++;
+
+       switch (*code) {
        case OPC_ASTORE:
        case OPC_ASTORE_0:
        case OPC_ASTORE_1:
@@ -111,8 +117,11 @@ bool bc_is_astore(unsigned char opc)
        }
 }
 
-unsigned char bc_get_astore_index(const unsigned char *code)
+unsigned long bc_get_astore_index(const unsigned char *code)
 {
+       if (*code == OPC_WIDE)
+               return read_u16(code + 2);
+
        switch (*code) {
        case OPC_ASTORE:
                return read_u8(code + 1);
@@ -125,10 +134,18 @@ unsigned char bc_get_astore_index(const unsigned char 
*code)
        case OPC_ASTORE_3:
                return 3;
        default:
-               error("not an astore bytecode");
+               assert(!"not an astore instruction");
        }
 }
 
+unsigned long bc_get_ret_index(const unsigned char *code)
+{
+       if (*code == OPC_WIDE)
+               return read_u16(code + 2);
+
+       return read_u8(code + 1);
+}
+
 /**
  *     bc_target_off - Return branch opcode target offset.
  *     @code: start of branch bytecode.
-- 
1.6.0.6


------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge  
This is your chance to win up to $100,000 in prizes! For a limited time, 
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize  
details at: http://p.sf.net/sfu/Challenge
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to