When method is synchronized JIT compiler is responsible for generating code which acquires lock in prologue and releases it in epilogue and in unwind block.
Signed-off-by: Tomek Grabiec <tgrab...@gmail.com> --- arch/x86/emit-code_32.c | 39 +++++++++++++++++++++++++++++++++++++ arch/x86/include/arch/emit-code.h | 4 +++ include/vm/method.h | 11 ++++++++++ jit/emit.c | 24 ++++++++++++++++++++++ 4 files changed, 78 insertions(+), 0 deletions(-) diff --git a/arch/x86/emit-code_32.c b/arch/x86/emit-code_32.c index d0234ec..fc374e4 100644 --- a/arch/x86/emit-code_32.c +++ b/arch/x86/emit-code_32.c @@ -22,6 +22,7 @@ #include <arch/instruction.h> #include <arch/memory.h> #include <arch/exception.h> +#include <arch/stack-frame.h> #include <assert.h> #include <errno.h> @@ -30,6 +31,8 @@ #include <stdbool.h> #include <string.h> +#include <../jamvm/lock.h> + #define PREFIX_SIZE 1 #define BRANCH_INSN_SIZE 5 #define BRANCH_TARGET_OFFSET 1 @@ -831,6 +834,42 @@ static void emit_test_membase_reg(struct buffer *buf, struct operand *src, emit_membase_reg(buf, 0x85, src, dest); } +void emit_lock(struct buffer *buf, struct object *obj) +{ + __emit_push_imm(buf, (unsigned long)obj); + __emit_call(buf, objectLock); + __emit_add_imm_reg(buf, 0x04, REG_ESP); +} + +void emit_unlock(struct buffer *buf, struct object *obj) +{ + __emit_push_imm(buf, (unsigned long)obj); + __emit_call(buf, objectUnlock); + __emit_add_imm_reg(buf, 0x04, REG_ESP); +} + +void emit_lock_this(struct buffer *buf) +{ + unsigned long this_arg_offset; + + this_arg_offset = offsetof(struct jit_stack_frame, args); + + __emit_push_membase(buf, REG_EBP, this_arg_offset); + __emit_call(buf, objectLock); + __emit_add_imm_reg(buf, 0x04, REG_ESP); +} + +void emit_unlock_this(struct buffer *buf) +{ + unsigned long this_arg_offset; + + this_arg_offset = offsetof(struct jit_stack_frame, args); + + __emit_push_membase(buf, REG_EBP, this_arg_offset); + __emit_call(buf, objectUnlock); + __emit_add_imm_reg(buf, 0x04, REG_ESP); +} + enum emitter_type { NO_OPERANDS = 1, SINGLE_OPERAND, diff --git a/arch/x86/include/arch/emit-code.h b/arch/x86/include/arch/emit-code.h index ee12875..13912e8 100644 --- a/arch/x86/include/arch/emit-code.h +++ b/arch/x86/include/arch/emit-code.h @@ -11,5 +11,9 @@ void emit_epilog(struct buffer *); void emit_body(struct basic_block *, struct buffer *); void emit_trampoline(struct compilation_unit *, void *, struct jit_trampoline*); void emit_unwind(struct buffer *); +void emit_lock(struct buffer *, struct object *); +void emit_lock_this(struct buffer *); +void emit_unlock(struct buffer *, struct object *); +void emit_unlock_this(struct buffer *); #endif /* __X86_EMIT_CODE */ diff --git a/include/vm/method.h b/include/vm/method.h index 142a8c9..5bf94b6 100644 --- a/include/vm/method.h +++ b/include/vm/method.h @@ -4,6 +4,7 @@ #include <vm/vm.h> #include <vm/types.h> +#include <stdbool.h> #include <string.h> static inline enum vm_type method_return_type(struct methodblock *method) @@ -17,4 +18,14 @@ static inline bool method_is_constructor(struct methodblock *method) return strcmp(method->name,"<init>") == 0; } +static inline bool method_is_synchronized(struct methodblock *method) +{ + return method->access_flags & ACC_SYNCHRONIZED; +} + +static inline bool method_is_static(struct methodblock *method) +{ + return method->access_flags & ACC_STATIC; +} + #endif diff --git a/jit/emit.c b/jit/emit.c index 93d21e9..5ffce24 100644 --- a/jit/emit.c +++ b/jit/emit.c @@ -9,6 +9,7 @@ #include <vm/alloc.h> #include <vm/buffer.h> +#include <vm/method.h> #include <vm/vm.h> #include <jit/basic-block.h> @@ -21,6 +22,22 @@ #include <stdlib.h> #include <string.h> +static void emit_monitor_enter(struct compilation_unit *cu) +{ + if (method_is_static(cu->method)) + emit_lock(cu->objcode, cu->method->class); + else + emit_lock_this(cu->objcode); +} + +static void emit_monitor_exit(struct compilation_unit *cu) +{ + if (method_is_static(cu->method)) + emit_unlock(cu->objcode, cu->method->class); + else + emit_unlock_this(cu->objcode); +} + static struct buffer_operations exec_buf_ops = { .expand = expand_buffer_exec, .free = generic_buffer_free, @@ -38,13 +55,20 @@ int emit_machine_code(struct compilation_unit *cu) frame_size = frame_locals_size(cu->stack_frame); emit_prolog(cu->objcode, frame_size); + if (method_is_synchronized(cu->method)) + emit_monitor_enter(cu); + for_each_basic_block(bb, &cu->bb_list) emit_body(bb, cu->objcode); emit_body(cu->exit_bb, cu->objcode); + if (method_is_synchronized(cu->method)) + emit_monitor_exit(cu); emit_epilog(cu->objcode); emit_body(cu->unwind_bb, cu->objcode); + if (method_is_synchronized(cu->method)) + emit_monitor_exit(cu); emit_unwind(cu->objcode); return 0; -- 1.6.0.6 ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp as they present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel