Signed-off-by: Tomek Grabiec <[email protected]>
---
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/jatovm-devel