The code didn't handle the case where exception handler range covers
the whole subroutine and more.

Signed-off-by: Tomek Grabiec <tgrab...@gmail.com>
---
 jit/subroutine.c |  180 ++++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 127 insertions(+), 53 deletions(-)

diff --git a/jit/subroutine.c b/jit/subroutine.c
index 5ac8633..8a5181a 100644
--- a/jit/subroutine.c
+++ b/jit/subroutine.c
@@ -768,6 +768,42 @@ eh_split(struct inlining_context *ctx, int i)
        return &new_table[i + 1];
 }
 
+static inline bool
+eh_outside_subroutine(struct cafebabe_code_attribute_exception *eh,
+                     struct subroutine *s)
+{
+       return eh->start_pc >= s->end_pc + s->epilog_size ||
+               eh->end_pc <= s->start_pc;
+}
+
+static inline bool
+eh_inside_subroutine(struct cafebabe_code_attribute_exception *eh,
+                    struct subroutine *s)
+{
+       return eh->start_pc >= s->start_pc &&
+               eh->end_pc <= s->end_pc + s->epilog_size;
+}
+
+static inline bool
+eh_covers_subroutine(struct cafebabe_code_attribute_exception *eh,
+                    struct subroutine *s)
+{
+       return eh->start_pc <= s->start_pc &&
+               eh->end_pc >= s->end_pc + s->epilog_size;
+}
+
+static inline bool
+eh_target_inside_subroutine(struct cafebabe_code_attribute_exception *eh,
+                           struct subroutine *s)
+{
+       return eh->handler_pc >= s->start_pc &&
+               eh->handler_pc < s->end_pc + s->epilog_size;
+}
+
+/**
+ * Duplicates exception handler entry so that it covers all instances
+ * of inlined subroutines it belongs to.
+ */
 static int
 copy_exception_handler(struct inlining_context *ctx, struct subroutine *s,
                       int *eh_index, struct pc_map *pc_map)
@@ -775,12 +811,14 @@ copy_exception_handler(struct inlining_context *ctx, 
struct subroutine *s,
        struct cafebabe_code_attribute_exception *eh;
        unsigned long eh_start_pc_offset;
        unsigned long eh_end_pc_offset;
-       unsigned long eh_handler_pc_offset;
+       unsigned long eh_handler_pc;
        unsigned long body_start_pc;
        unsigned long body_size;
 
        eh = &ctx->exception_table[*eh_index];
 
+       eh_handler_pc = eh->handler_pc;
+
        body_start_pc = s->start_pc + s->prolog_size;
        body_size = subroutine_get_body_size(s);
 
@@ -794,8 +832,6 @@ copy_exception_handler(struct inlining_context *ctx, struct 
subroutine *s,
        else
                eh_end_pc_offset = eh->end_pc - body_start_pc;
 
-       eh_handler_pc_offset = eh->handler_pc - body_start_pc;
-
        for (int i = 0; i < s->nr_call_sites; i++) {
                struct cafebabe_code_attribute_exception *new_eh;
                unsigned long sub_start;
@@ -804,26 +840,84 @@ copy_exception_handler(struct inlining_context *ctx, 
struct subroutine *s,
                if (pc_map_get_unique(pc_map, &sub_start))
                        return warn("no or ambiguous mapping"), -EINVAL;
 
-               if (i == s->nr_call_sites - 1)
-                       new_eh = &ctx->exception_table[*eh_index];
-               else {
-                       new_eh = eh_split(ctx, *eh_index);
-                       if (!new_eh)
-                               return warn("out of memory"), -ENOMEM;
-               }
+               new_eh = eh_split(ctx, *eh_index);
+               if (!new_eh)
+                       return warn("out of memory"), -ENOMEM;
 
                new_eh->start_pc = sub_start + eh_start_pc_offset;
                new_eh->end_pc = sub_start + eh_end_pc_offset;
-               new_eh->handler_pc = sub_start + eh_handler_pc_offset;
                new_eh->catch_type = ctx->exception_table[*eh_index].catch_type;
+
+               if (eh_target_inside_subroutine(eh, s)) {
+                       new_eh->handler_pc = sub_start + eh_handler_pc - 
body_start_pc;
+               } else {
+                       unsigned long pc = eh_handler_pc;
+                       if (pc_map_get_unique(pc_map, &pc))
+                               return -EINVAL;
+
+                       new_eh->handler_pc = pc;
+               }
        }
 
-       *eh_index = *eh_index + s->nr_call_sites - 1;
+       *eh_index = *eh_index + s->nr_call_sites;
 
        return 0;
 }
 
 static int
+update_exception_handler(struct cafebabe_code_attribute_exception *eh,
+                        struct pc_map *pc_map)
+{
+       unsigned long start_pc, end_pc, handler_pc;
+       int err;
+
+       start_pc = eh->start_pc;
+       end_pc = eh->end_pc;
+       handler_pc = eh->handler_pc;
+
+       err = pc_map_get_unique(pc_map, &start_pc);
+       if (err)
+               return warn("no or ambiguous mapping"), -EINVAL;
+
+       err = pc_map_get_unique(pc_map, &end_pc);
+       if (err)
+               return warn("no or ambiguous mapping"), -EINVAL;
+
+       err = pc_map_get_unique(pc_map, &handler_pc);
+       if (err) {
+               /*
+                * If handler_pc is in realation with more than one
+                * address it means that the handler is within
+                * subroutine which have been previously inlined. We
+                * don't handle this.
+                */
+               if (pc_map_has_value_for(pc_map, handler_pc))
+                       return warn("invalid handler"), -EINVAL;
+
+               return warn("no mapping for handler"), -EINVAL;
+       }
+
+       eh->start_pc = start_pc;
+       eh->end_pc = end_pc;
+       eh->handler_pc = handler_pc;
+       return 0;
+}
+
+static void eh_remove(struct inlining_context *ctx, int i)
+{
+       unsigned long size;
+
+       size = (ctx->exception_table_length - i - 1) *
+               sizeof(struct cafebabe_code_attribute_exception);
+
+       memmove(ctx->exception_table + i,
+               ctx->exception_table + i + 1,
+               size);
+
+       ctx->exception_table_length--;
+}
+
+static int
 update_and_copy_exception_handlers(struct inlining_context *ctx,
                                   struct subroutine *s,
                                   struct pc_map *pc_map)
@@ -834,55 +928,35 @@ 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 + s->epilog_size ||
-                   eh->end_pc <= s->start_pc) {
-                       unsigned long start_pc, end_pc, handler_pc;
+               if (eh_outside_subroutine(eh, s)) {
+                       if (update_exception_handler(eh, pc_map))
+                               return -EINVAL;
+               } else if (eh_inside_subroutine(eh, s)) {
+                       int old_i = i;
 
-                       start_pc = eh->start_pc;
-                       end_pc = eh->end_pc;
-                       handler_pc = eh->handler_pc;
-
-                       err = pc_map_get_unique(pc_map, &start_pc);
+                       err = copy_exception_handler(ctx, s, &i, pc_map);
                        if (err)
-                               return warn("no or ambiguous mapping"), -EINVAL;
+                               return err;
 
-                       err = pc_map_get_unique(pc_map, &end_pc);
-                       if (err)
-                               return warn("no or ambiguous mapping"), -EINVAL;
-
-                       err = pc_map_get_unique(pc_map, &handler_pc);
-                       if (err) {
-                               /*
-                                * If handler_pc is in realation with more
-                                * than one address it means that the handler
-                                * is within subroutine which have been
-                                * previously inlined. We don't handle this.
-                                */
-                               if (pc_map_has_value_for(pc_map, handler_pc))
-                                       return warn("invalid handler"), -EINVAL;
-
-                               return warn("no mapping for handler"), -EINVAL;
-                       }
+                       eh_remove(ctx, old_i);
+                       i--;
+               } else if (eh_covers_subroutine(eh, s)) {
+                       int old_i = i;
 
-                       eh->start_pc = start_pc;
-                       eh->end_pc = end_pc;
-                       eh->handler_pc = handler_pc;
+                       if (eh_target_inside_subroutine(eh, s))
+                               return warn("exception handler jumps into 
subroutine"),
+                                       -EINVAL;
 
-                       continue;
-               }
+                       err = copy_exception_handler(ctx, s, &i, pc_map);
+                       if (err)
+                               return err;
 
-               if (eh->start_pc < s->start_pc ||
-                   eh->end_pc > s->end_pc + s->epilog_size)
+                       eh = &ctx->exception_table[old_i];
+                       if (update_exception_handler(eh, pc_map))
+                               return -EINVAL;
+               } else
                        return warn("handler range spans subroutine boundary"),
                                -EINVAL;
-
-               if (eh->handler_pc < s->start_pc ||
-                   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);
-               if (err)
-                       return err;
        }
 
        return 0;
-- 
1.6.0.4


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to