When method is prepared in vm_method_prepare_jit() it is checked whether native method is one of VM native methods and the address of it is stored in the ->vm_native_ptr field. This field is used to perform a quick check for a JNI method in vm_method_is_jni_method() and to omit vm_native_lookup() in jit_native_trampoline().
When converting method invocation it is checked whether method is a JNI native method. If this is the case then JNI environment pointer is appended to call arguments. When static JNI method is called the class->object pointer is also appended according to the JNI specification. Signed-off-by: Tomek Grabiec <[email protected]> --- arch/x86/emit-code.c | 23 ----------------------- include/jit/compiler.h | 8 -------- include/vm/method.h | 9 ++++++++- jit/emit.c | 27 --------------------------- jit/invoke-bc.c | 39 +++++++++++++++++++++++++++++++++++++++ jit/trace-jit.c | 3 +++ jit/trampoline.c | 30 ++++++------------------------ vm/method.c | 21 ++++++++++++++++++++- 8 files changed, 76 insertions(+), 84 deletions(-) diff --git a/arch/x86/emit-code.c b/arch/x86/emit-code.c index 6020bac..0ed73d4 100644 --- a/arch/x86/emit-code.c +++ b/arch/x86/emit-code.c @@ -21,7 +21,6 @@ #include "lib/list.h" #include "lib/buffer.h" -#include "vm/jni.h" #include "vm/method.h" #include "vm/object.h" @@ -1388,28 +1387,6 @@ void emit_trampoline(struct compilation_unit *cu, jit_text_unlock(); } -void emit_jni_trampoline(struct buffer *buf, struct vm_jni_env *jni_env, - void *target) -{ - jit_text_lock(); - - buf->buf = jit_text_ptr(); - - /* save return address into caller-saved register */ - __emit_pop_reg(buf, REG_ESI); - - __emit_push_imm(buf, (unsigned long) jni_env); - __emit_call(buf, target); - __emit_add_imm_reg(buf, 4, REG_ESP); - - /* return to caller*/ - __emit_push_reg(buf, REG_ESI); - emit_ret(buf); - - jit_text_reserve(buffer_offset(buf)); - jit_text_unlock(); -} - /* Note: a < b, always */ static void emit_itable_bsearch(struct buffer *buf, struct itable_entry **table, unsigned int a, unsigned int b) diff --git a/include/jit/compiler.h b/include/jit/compiler.h index 8584954..11df1be 100644 --- a/include/jit/compiler.h +++ b/include/jit/compiler.h @@ -31,10 +31,6 @@ struct jit_trampoline { pthread_mutex_t mutex; }; -struct jni_trampoline { - struct buffer *objcode; -}; - struct parse_context { struct compilation_unit *cu; struct basic_block *bb; @@ -60,12 +56,8 @@ int emit_machine_code(struct compilation_unit *); void *jit_magic_trampoline(struct compilation_unit *); struct jit_trampoline *alloc_jit_trampoline(void); -struct jni_trampoline *alloc_jni_trampoline(void); struct jit_trampoline *build_jit_trampoline(struct compilation_unit *); -struct jni_trampoline *build_jni_trampoline(void *); void free_jit_trampoline(struct jit_trampoline *); -void free_jni_trampoline(struct jni_trampoline *); - struct fixup_site *alloc_fixup_site(void); void free_fixup_site(struct fixup_site *); void trampoline_add_fixup_site(struct jit_trampoline *, struct fixup_site *); diff --git a/include/vm/method.h b/include/vm/method.h index fd19c16..e86df11 100644 --- a/include/vm/method.h +++ b/include/vm/method.h @@ -35,7 +35,8 @@ struct vm_method { struct compilation_unit *compilation_unit; struct jit_trampoline *trampoline; - struct jni_trampoline *jni_trampoline; + + void *vm_native_ptr; }; int vm_method_init(struct vm_method *vmm, @@ -80,6 +81,12 @@ static inline bool method_is_virtual(struct vm_method *vmm) | CAFEBABE_METHOD_ACC_PRIVATE)) == 0; } +static inline bool vm_method_is_jni_method(struct vm_method *vmm) +{ + return vmm->method->access_flags & CAFEBABE_METHOD_ACC_NATIVE + && !vmm->vm_native_ptr; +} + static inline enum vm_type method_return_type(struct vm_method *method) { char *return_type = method->type + (strlen(method->type) - 1); diff --git a/jit/emit.c b/jit/emit.c index ec79c3e..9d5c46a 100644 --- a/jit/emit.c +++ b/jit/emit.c @@ -205,35 +205,8 @@ struct jit_trampoline *alloc_jit_trampoline(void) return NULL; } -struct jni_trampoline *alloc_jni_trampoline(void) -{ - struct jni_trampoline *trampoline; - - trampoline = malloc(sizeof(*trampoline)); - if (!trampoline) - return NULL; - - memset(trampoline, 0, sizeof(*trampoline)); - - trampoline->objcode = __alloc_buffer(&exec_buf_ops); - if (!trampoline->objcode) - goto failed; - - return trampoline; - - failed: - free_jni_trampoline(trampoline); - return NULL; -} - void free_jit_trampoline(struct jit_trampoline *trampoline) { free_buffer(trampoline->objcode); free(trampoline); } - -void free_jni_trampoline(struct jni_trampoline *trampoline) -{ - free_buffer(trampoline->objcode); - free(trampoline); -} diff --git a/jit/invoke-bc.c b/jit/invoke-bc.c index e5e0ff4..3a4b2da 100644 --- a/jit/invoke-bc.c +++ b/jit/invoke-bc.c @@ -19,6 +19,7 @@ #include "vm/method.h" #include "vm/stack.h" #include "vm/die.h" +#include "vm/jni.h" #include <string.h> #include <errno.h> @@ -204,6 +205,14 @@ int convert_invokevirtual(struct parse_context *ctx) return err; } +static void append_arg(struct expression *expr, struct expression *arg) +{ + struct expression *args_list; + + args_list = insert_arg(to_expr(expr->args_list), arg); + expr->args_list = &args_list->node; +} + int convert_invokespecial(struct parse_context *ctx) { struct vm_method *invoke_target; @@ -228,6 +237,17 @@ int convert_invokespecial(struct parse_context *ctx) null_check_first_arg(to_expr(expr->args_list)); + if (vm_method_is_jni_method(invoke_target)) { + struct expression *jni_env_expr; + + jni_env_expr = value_expr(J_REFERENCE, + (unsigned long)vm_jni_get_jni_env()); + if (!jni_env_expr) + goto failed; + + append_arg(expr, jni_env_expr); + } + err = insert_invoke_expr(ctx, expr); if (err) goto failed; @@ -260,6 +280,25 @@ int convert_invokestatic(struct parse_context *ctx) if (err) goto failed; + if (vm_method_is_jni_method(invoke_target)) { + struct expression *jni_env_expr; + struct expression *class_expr; + + class_expr = value_expr(J_REFERENCE, + (unsigned long)invoke_target->class->object); + if (!class_expr) + goto failed; + + append_arg(expr, class_expr); + + jni_env_expr = value_expr(J_REFERENCE, + (unsigned long)vm_jni_get_jni_env()); + if (!jni_env_expr) + goto failed; + + append_arg(expr, jni_env_expr); + } + err = insert_invoke_expr(ctx, expr); if (err) goto failed; diff --git a/jit/trace-jit.c b/jit/trace-jit.c index 7f41006..a7b4d3a 100644 --- a/jit/trace-jit.c +++ b/jit/trace-jit.c @@ -324,6 +324,9 @@ static void trace_invoke_args(struct vm_method *vmm, const char *type_str; int arg_index; + if (vm_method_is_jni_method(vmm)) + arg_index += 2; + arg_index = 0; if (!vm_method_is_static(vmm)) { diff --git a/jit/trampoline.c b/jit/trampoline.c index 0de2db5..dd9658a 100644 --- a/jit/trampoline.c +++ b/jit/trampoline.c @@ -46,31 +46,24 @@ static void *jit_native_trampoline(struct compilation_unit *cu) { const char *method_name, *class_name, *method_type; struct vm_method *method; - struct string *msg; void *ret; method = cu->method; + + if (method->vm_native_ptr) + return method->vm_native_ptr; + class_name = method->class->name; method_name = method->name; method_type = method->type; - ret = vm_lookup_native(class_name, method_name); - if (ret) { - add_cu_mapping((unsigned long)ret, cu); - return ret; - } - ret = vm_jni_lookup_method(class_name, method_name, method_type); if (ret) { add_cu_mapping((unsigned long)ret, cu); - - if (!method->jni_trampoline) - method->jni_trampoline = build_jni_trampoline(ret); - - return buffer_ptr(method->jni_trampoline->objcode); + return ret; } - msg = alloc_str(); + struct string *msg = alloc_str(); if (!msg) /* TODO: signal OutOfMemoryError */ die("out of memory"); @@ -150,14 +143,3 @@ struct jit_trampoline *build_jit_trampoline(struct compilation_unit *cu) emit_trampoline(cu, jit_magic_trampoline, trampoline); return trampoline; } - -struct jni_trampoline *build_jni_trampoline(void *target) -{ - struct jni_trampoline *trampoline; - - trampoline = alloc_jni_trampoline(); - if (trampoline) - emit_jni_trampoline(trampoline->objcode, vm_jni_get_jni_env(), - target); - return trampoline; -} diff --git a/vm/method.c b/vm/method.c index c4a7eb2..5a8b688 100644 --- a/vm/method.c +++ b/vm/method.c @@ -12,6 +12,9 @@ #include "vm/class.h" #include "vm/method.h" +#include "vm/natives.h" + +#include "jit/cu-mapping.h" int vm_method_init(struct vm_method *vmm, struct vm_class *vmc, unsigned int method_index) @@ -129,8 +132,24 @@ int vm_method_prepare_jit(struct vm_method *vmm) return -1; } - vmm->jni_trampoline = NULL; + if (!vm_method_is_native(vmm)) + goto link_later; + + vmm->vm_native_ptr = NULL; + + void *native_ptr = vm_lookup_native(vmm->class->name, vmm->name); + if (native_ptr) { + vmm->vm_native_ptr = native_ptr; + + if (add_cu_mapping((unsigned long)native_ptr, + vmm->compilation_unit)) + { + NOT_IMPLEMENTED; + return -1; + } + } +link_later: vmm->trampoline = build_jit_trampoline(vmm->compilation_unit); if (!vmm->trampoline) { NOT_IMPLEMENTED; -- 1.6.0.6 ------------------------------------------------------------------------------ _______________________________________________ Jatovm-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/jatovm-devel
