From 5353e3ecae0f579f58170a58cdbc5df32fe4edc0 Mon Sep 17 00:00:00 2001 From: Alexander Astapchuk Date: Sat, 13 Jan 2007 17:07:25 +0600 Subject: [PATCH 3/6] [drlvm][fastcc]Fast calling convention for IA-32; part vm/vmcore --- vm/vmcore/include/dump.h | 12 +- vm/vmcore/include/environment.h | 5 + vm/vmcore/include/jit_export_rt.h | 5 +- vm/vmcore/include/vm_core_types.h | 2 + vm/vmcore/src/class_support/C_Interface.cpp | 10 +- vm/vmcore/src/class_support/Environment.cpp | 2 + vm/vmcore/src/exception/exceptions_jit.cpp | 23 +- vm/vmcore/src/init/parse_arguments.cpp | 32 ++- vm/vmcore/src/init/vm_init.cpp | 13 +- vm/vmcore/src/jit/compile.cpp | 102 +++--- vm/vmcore/src/jit/dump.cpp | 14 +- vm/vmcore/src/jit/jit_runtime_support.cpp | 8 +- vm/vmcore/src/object/object_handles.cpp | 4 +- vm/vmcore/src/util/ia32/base/compile_IA32.cpp | 262 ++++++++------- vm/vmcore/src/util/ia32/base/ini_iA32.cpp | 354 +++++++++++++------ .../src/util/ia32/base/invoke_native_stub_ia32.asm | 46 --- .../util/ia32/base/jit_lock_rt_support_ia32.cpp | 92 +++--- .../util/ia32/base/jit_runtime_support_ia32.cpp | 143 ++------- 18 files changed, 608 insertions(+), 521 deletions(-) diff --git a/vm/vmcore/include/dump.h b/vm/vmcore/include/dump.h index 1195004..cc01d84 100644 --- a/vm/vmcore/include/dump.h +++ b/vm/vmcore/include/dump.h @@ -14,17 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** -* @author Evgueni Brevnov -* @version $Revision: 1.1.2.1.4.3 $ -*/ +/** + * @author Evgueni Brevnov + */ #ifndef _DUMP_H_ #define _DUMP_H_ -#ifndef NDEBUG - extern bool dump_stubs; - +extern bool dump_stubs; +#ifdef _DEBUG #define DUMP_STUB(addr, name, len) \ if (dump_stubs) \ dump(((char *)addr), (name), (len)); diff --git a/vm/vmcore/include/environment.h b/vm/vmcore/include/environment.h index a843424..00785ea 100644 --- a/vm/vmcore/include/environment.h +++ b/vm/vmcore/include/environment.h @@ -76,6 +76,11 @@ struct Global_Env { bool verify_all; // Verify all classes including loaded by bootstrap class loader bool verify_strict; // Do strict verification size_t system_page_size; // system page size according to use_large_pages value + /** + * Calling convention for managed code. + * Normally, only on IA-32 it differs from default platform convention. + */ + CallingConvention managed_calling_convention; Lock_Manager *p_jit_a_method_lock; Lock_Manager *p_vtable_patch_lock; diff --git a/vm/vmcore/include/jit_export_rt.h b/vm/vmcore/include/jit_export_rt.h index 5ad2ac6..90f9dc5 100644 --- a/vm/vmcore/include/jit_export_rt.h +++ b/vm/vmcore/include/jit_export_rt.h @@ -104,11 +104,14 @@ struct JitFrameContext { uint32 *p_esi; uint32 *p_ebx; - // The scratch registers are currently only valid during GC enumeration. + // Scratch registers uint32 *p_eax; uint32 *p_ecx; uint32 *p_edx; + // XMM registers + double* p_xmms[8]; + // To restore processor flags during transfer uint32 eflags; diff --git a/vm/vmcore/include/vm_core_types.h b/vm/vmcore/include/vm_core_types.h index 2cfa3c6..029f6e8 100644 --- a/vm/vmcore/include/vm_core_types.h +++ b/vm/vmcore/include/vm_core_types.h @@ -118,6 +118,8 @@ struct Registers { uint32 eip; uint32 eflags; + double xmms[8]; + void reset_ip() { eip = 0; } void* get_ip() { return (void*)eip; } void set_ip(void* src_ip) { eip = (uint32)src_ip; } diff --git a/vm/vmcore/src/class_support/C_Interface.cpp b/vm/vmcore/src/class_support/C_Interface.cpp index 24b1deb..7ea0a83 100644 --- a/vm/vmcore/src/class_support/C_Interface.cpp +++ b/vm/vmcore/src/class_support/C_Interface.cpp @@ -16,7 +16,6 @@ */ /** * @author Intel, Alexei Fedotov - * @version $Revision: 1.1.2.6.2.1.2.4 $ */ #define LOG_DOMAIN "vm.core" @@ -37,6 +36,10 @@ #include "class_interface.h" #include "Package.h" +#ifdef _IA32_ +#include "callconv.h" +#endif + Boolean class_property_is_final(Class_Handle cl) { assert(cl); return cl->is_final(); @@ -2586,6 +2589,11 @@ void method_iterator_advance(ChaMethodIt CallingConvention vm_managed_calling_convention() { +#ifdef _IA32_ + if (vm_cc_is_drlfast_enabled()) { + return CC_DRLFast; + } +#endif return CC_Vm; } //vm_managed_calling_convention diff --git a/vm/vmcore/src/class_support/Environment.cpp b/vm/vmcore/src/class_support/Environment.cpp index c310843..759d218 100644 --- a/vm/vmcore/src/class_support/Environment.cpp +++ b/vm/vmcore/src/class_support/Environment.cpp @@ -122,6 +122,8 @@ ready_for_exceptions(false) else { system_page_size = ps[0]; } + + managed_calling_convention = CC_Vm; GlobalCodeMemoryManager = new PoolManager(DEFAULT_COMMOT_JIT_CODE_POOL_SIZE, system_page_size, use_large_pages, true/*is_code*/, true/*is_resize_allowed*/); diff --git a/vm/vmcore/src/exception/exceptions_jit.cpp b/vm/vmcore/src/exception/exceptions_jit.cpp index 4813637..73a4bdf 100644 --- a/vm/vmcore/src/exception/exceptions_jit.cpp +++ b/vm/vmcore/src/exception/exceptions_jit.cpp @@ -443,7 +443,7 @@ void exn_throw_for_JIT(ManagedObject* ex // Exception defined as in previous function. // Does not return. -// function can be safe point & should be called with disable reqursion = 1 +// function can be safe point & should be called with disable recursion = 1 void exn_athrow(ManagedObject* exn_obj, Class_Handle exn_class, Method_Handle exn_constr, uint8* exn_constr_args) { @@ -566,7 +566,7 @@ NativeCodePtr exn_get_rth_throw() assert(lil_is_valid(cs)); addr = LilCodeGenerator::get_platform()->compile(cs); - DUMP_STUB(addr, "rth_throw", lil_cs_get_code_size(cs)); + DUMP_STUB(addr, "rth_throw_with_args", lil_cs_get_code_size(cs)); lil_free_code_stub(cs); return addr; @@ -601,7 +601,7 @@ NativeCodePtr exn_get_rth_throw_lazy() assert(lil_is_valid(cs)); addr = LilCodeGenerator::get_platform()->compile(cs); - DUMP_STUB(addr, "rth_throw_lazy", lil_cs_get_code_size(cs)); + DUMP_STUB(addr, "rth_throw_lazy_with_args", lil_cs_get_code_size(cs)); lil_free_code_stub(cs); return addr; @@ -617,7 +617,8 @@ NativeCodePtr exn_get_rth_throw_lazy_tra return addr; } - LilCodeStub *cs = lil_parse_code_stub("entry 1:managed::void;" + LilCodeStub *cs = lil_parse_code_stub( + "entry 1:managed::void;" "push_m2n 0, 0;" "m2n_save_all;" "out platform:ref,pint,pint,pint:void;" @@ -644,8 +645,11 @@ NativeCodePtr exn_get_rth_throw_null_poi Class *exn_clss = VM_Global_State::loader_env->java_lang_NullPointerException_Class; LilCodeStub *cs = - lil_parse_code_stub("entry 0:managed::void;" "std_places 1;" - "sp0=%0i;" "tailcall %1i;", + lil_parse_code_stub( + "entry 0:managed::void;" + "std_places 1;" + "sp0=%0i;" + "tailcall %1i;", exn_clss, lil_npc_to_fp(exn_get_rth_throw_lazy_trampoline())); assert(lil_is_valid(cs)); @@ -792,8 +796,11 @@ NativeCodePtr exn_get_rth_throw_illegal_ return addr; } - LilCodeStub *cs = lil_parse_code_stub("entry 0:managed::void;" - "std_places 1;" "sp0=%0i;" "tailcall %1i;", + LilCodeStub *cs = lil_parse_code_stub( + "entry 0:managed::void;" + "std_places 1;" + "sp0=%0i;" + "tailcall %1i;", exn_get_illegal_state_exception_type(), lil_npc_to_fp(exn_get_rth_throw_lazy_trampoline())); assert(lil_is_valid(cs)); diff --git a/vm/vmcore/src/init/parse_arguments.cpp b/vm/vmcore/src/init/parse_arguments.cpp index 713b1d6..a2f359c 100644 --- a/vm/vmcore/src/init/parse_arguments.cpp +++ b/vm/vmcore/src/init/parse_arguments.cpp @@ -149,6 +149,27 @@ static void print_help_on_nonstandard_op # define STATS_OPTIONS_HELP #endif // VM_STATS +#ifdef _IA32_ + #define CALLING_CONVENTION_OPTIONS_HELP \ + " -Xcc:\n" \ + " Specifies calling convention for managed code\n" \ + " (same as -XDvm.cc=)\n" \ + " The possible values are:\n" \ + " default - default DRLVM calling convention\n" \ + " fast - IA-32 fastcall\n" \ + " stdcall - IA-32 stdcall\n" \ + " cdecl - IA-32 cdecl\n" \ + " drlfast - DRLVM-specific variant of fastcall\n" \ + " drlfast has the following properties (* means defaul):\n" \ + " -XDvm.drlfast.gp_reg_args={0*,1,2,3}\n" \ + " -XDvm.drlfast.use_fpu_ret={true*,false}\n" \ + " -XDvm.drlfast.xmm_reg_args={0*,1,2,3,4,5,6,7,8}\n" \ + " -XDvm.drlfast.xmm_callee_save_regs={0*,1,2,3,4,5,6,7,8}\n" +#else + #define CALLING_CONVENTION_OPTIONS_HELP +#endif + + ECHO(" -Xbootclasspath:\n" " Set bootclasspath to the specified value\n" " -Xbootclasspath/a:\n" @@ -208,7 +229,9 @@ static void print_help_on_nonstandard_op " -Xdumpfile:\n" " Specifies a file name for the dump\n" " -XD=\n" - " set an internal system property\n"); + " set an internal system property\n" + CALLING_CONVENTION_OPTIONS_HELP + ); } //print_help_on_nonstandard_options void print_vm_standard_properties() @@ -531,7 +554,12 @@ void parse_vm_arguments(Global_Env *p_en p_env->assert_reg->enable_system = false; } } - +#ifdef _IA32_ + else if (begins_with(option, "-Xcc:")) { + const char* cname = option+5; // 5= strlen("-Xcc:") + set_property("vm.cc", cname, VM_PROPERTIES); + } +#endif else { ECHO("Unknown option " << option << USE_JAVA_HELP); LOGGER_EXIT(1); diff --git a/vm/vmcore/src/init/vm_init.cpp b/vm/vmcore/src/init/vm_init.cpp index ed2fc9a..0234a9d 100644 --- a/vm/vmcore/src/init/vm_init.cpp +++ b/vm/vmcore/src/init/vm_init.cpp @@ -54,6 +54,11 @@ #include #endif +#ifdef _IA32_ +#include "callconv.h" +#endif + + #define LOG_DOMAIN "vm.core.init" #include "cxxlog.h" @@ -645,10 +650,14 @@ int vm_init1(JavaVM_Internal * java_vm, status = process_properties_dlls(vm_env); if (status != JNI_OK) return status; - + parse_jit_arguments(&vm_env->vm_arguments); - vm_env->pin_interned_strings = +#ifdef _IA32_ + vm_cc_init_from_properties(vm_env); +#endif + + vm_env->pin_interned_strings = (bool)get_boolean_property("vm.pin_interned_strings", FALSE, VM_PROPERTIES); if (!get_boolean_property("vm.assert_dialog", TRUE, VM_PROPERTIES)) { diff --git a/vm/vmcore/src/jit/compile.cpp b/vm/vmcore/src/jit/compile.cpp index 2426625..b9277f0 100644 --- a/vm/vmcore/src/jit/compile.cpp +++ b/vm/vmcore/src/jit/compile.cpp @@ -119,7 +119,6 @@ Target_Exception_Handler_Ptr CodeChunkIn } } - void CodeChunkInfo::print_name() const { Method *meth = get_method(); @@ -149,6 +148,7 @@ void CodeChunkInfo::print_info(bool prin printf(", %d bytes%s\n", (unsigned)code_size, (print_ellipses? "..." : "")); } //CodeChunkInfo::print_info + // end CodeChunkInfo //////////////////////////////////////////////////////////////////////// @@ -219,17 +219,18 @@ NativeCodePtr compile_create_lil_jni_stu bool is_synchronised = (method_is_synchronized(method) ? true : false); Method_Signature_Handle msh = method_get_signature(method); unsigned num_args = method_args_get_number(msh); - Type_Info_Handle ret_tih = method_ret_type_get_type_info(msh); - VM_Data_Type ret_type = type_info_get_type(ret_tih); + VM_Data_Type ret_type = type_info_get_type(method_ret_type_get_type_info(msh)); unsigned i; + unsigned num_ref_args = 0; // among original args, does not include jclass for static methods for(i=0; iget_class_handle(); @@ -298,31 +299,30 @@ NativeCodePtr compile_create_lil_jni_stu "call %1i;", clss, lil_npc_to_fp(vm_get_rt_support_addr(VM_RT_MONITOR_ENTER_STATIC))); - assert(cs); } else { cs = lil_parse_onto_end(cs, "out managed:ref:void;" "o0=i0;" "call %0i;", lil_npc_to_fp(vm_get_rt_support_addr(VM_RT_MONITOR_ENTER))); - assert(cs); } - } - - //***** Call JVMTI MethodEntry - DebugUtilsTI* ti = VM_Global_State::loader_env->TI; - if (ti->isEnabled() && - ti->get_global_capability(DebugUtilsTI::TI_GC_ENABLE_METHOD_ENTRY)) - { - cs = lil_parse_onto_end(cs, - "out platform:pint:void;" - "o0=%0i:pint;" - "call %1i;", - (jmethodID)method, - jvmti_process_method_entry_event); assert(cs); } + //***** Call JVMTI MethodEntry + DebugUtilsTI* ti = VM_Global_State::loader_env->TI; + if (ti->isEnabled() && + ti->get_global_capability(DebugUtilsTI::TI_GC_ENABLE_METHOD_ENTRY)) + { + cs = lil_parse_onto_end(cs, + "out platform:pint:void;" + "o0=%0i:pint;" + "call %1i;", + (jmethodID)method, + jvmti_process_method_entry_event); + assert(cs); + } + //***** Part 4: Enable GC cs = lil_parse_onto_end(cs, "out platform::void;" @@ -344,34 +344,28 @@ NativeCodePtr compile_create_lil_jni_stu // Loop over arguments proper, setting rest of outputs unsigned arg_base = 1 + (is_static ? 1 : 0); hn = 1; + // In case of compressed refs, it's heap_base. Ordinary NULL otherwise. + const Byte* nullValue = VM_Global_State::loader_env->managed_null; for(i=(is_static?0:1); icompress_references) { - cs = lil_parse_onto_end(cs, - "jc i%0i=%1i:ref,%n;" - "o%2i=l0+%3i;" - "j %o;" - ":%g;" - "o%4i=0;" - ":%g;", - i, VM_Global_State::loader_env->managed_null, - arg_base+i, handle_offset, arg_base+i); - } else { - cs = lil_parse_onto_end(cs, - "jc i%0i=0:ref,%n;" - "o%1i=l0+%2i;" - "j %o;" - ":%g;" - "o%3i=0;" - ":%g;", - i, arg_base+i, handle_offset, - arg_base+i); - } - hn++; - } else { + if (!is_reference(method_args_get_type_info(msh, i))) { cs = lil_parse_onto_end(cs, "o%0i=i%1i;", arg_base+i, i); + assert(cs); + continue; } + unsigned handle_offset = oh_get_handle_offset(hn); + cs = lil_parse_onto_end(cs, + "jc i%0i=%1i:ref,%n;" + "o%2i=l0+%3i;" + "j %o;" + ":%g;" + "o%4i=0;" + ":%g;", + i, // %0 + nullValue, // %1 + arg_base+i, // %2 + handle_offset, // %3 + arg_base+i); // %4 + hn++; assert(cs); } @@ -413,9 +407,8 @@ NativeCodePtr compile_create_lil_jni_stu hythread_suspend_disable); assert(cs); - // Exception offsets - unsigned eoo = (unsigned)(POINTER_SIZE_INT)&((VM_thread*)0)->thread_exception.exc_object; - unsigned eco = (unsigned)(POINTER_SIZE_INT)&((VM_thread*)0)->thread_exception.exc_class; + unsigned eoo = offsetof(VM_thread, thread_exception.exc_object); + unsigned eco = offsetof(VM_thread, thread_exception.exc_class); //***** Call JVMTI MethodExit if (ti->isEnabled() && @@ -446,7 +439,8 @@ NativeCodePtr compile_create_lil_jni_stu assert(cs); } - //***** Part 9: Synchronise + + //***** Part 9: Synchronize if (is_synchronised) { if (is_static) { cs = lil_parse_onto_end(cs, @@ -466,7 +460,7 @@ NativeCodePtr compile_create_lil_jni_stu } //***** Part 10: Unhandle the return if it is a reference - if (is_reference(ret_tih)) { + if (is_reference(method_ret_type_get_type_info(msh))) { cs = lil_parse_onto_end(cs, "jc l1=0,ret_done;" "ld l1,[l1+0:ref];" @@ -511,7 +505,7 @@ NativeCodePtr compile_create_lil_jni_stu assert(lil_is_valid(cs)); NativeCodePtr addr = LilCodeGenerator::get_platform()->compile(cs, clss->get_class_loader()->GetCodePool()); -#ifndef NDEBUG +#ifdef _DEBUG char buf[100]; apr_snprintf(buf, sizeof(buf)-1, "jni_stub.%s::%s", class_get_name(clss), method_get_name(method)); DUMP_STUB(addr, buf, lil_cs_get_code_size(cs)); @@ -782,7 +776,7 @@ NativeCodePtr compile_me(Method* method) NativeCodePtr entry_point = method->get_code_addr(); INFO2("compile.code", "Compiled method " << method - << ", entry " << entry_point); + << ", entry " << entry_point); if (method->get_pending_breakpoints() != 0) jvmti_set_pending_breakpoints(method); @@ -826,3 +820,5 @@ void compile_clear_dynamic_code_list(Dyn list = next; } } + +////////////////////////////////////////////////////////////////////////// diff --git a/vm/vmcore/src/jit/dump.cpp b/vm/vmcore/src/jit/dump.cpp index 6f9f5c3..820e616 100644 --- a/vm/vmcore/src/jit/dump.cpp +++ b/vm/vmcore/src/jit/dump.cpp @@ -25,13 +25,17 @@ #include #include #include "port_disasm.h" - +#include "lil.h" // FIXME: this should not be a global variable // this variable is filled in by parse_args() const char * dump_file_name = "file.dump"; int dump(const char * code, const char * name, unsigned int length) { + +// Temporarily disabling port usage, until it gets functional. +// For now, using LIL's machinery +#if 0 static apr_pool_t * pool = NULL; static port_disassembler_t * disassembler; static apr_file_t * file = NULL; @@ -56,9 +60,13 @@ int dump(const char * code, const char * apr_file_printf(file, "Function dump begin: %s\n", name); port_disasm_to_file(disassembler, code, length, file); apr_file_printf(file, "Function dump end: %s\n", name); - -// apr_pool_destroy(pool); + // apr_pool_destroy(pool); return APR_SUCCESS; +#endif + lil_dbg_dump_start(name); + lil_dbg_dump(code, length, true); + lil_dbg_dump_finish(name); + return length; } diff --git a/vm/vmcore/src/jit/jit_runtime_support.cpp b/vm/vmcore/src/jit/jit_runtime_support.cpp index df0ede1..994bc0a 100644 --- a/vm/vmcore/src/jit/jit_runtime_support.cpp +++ b/vm/vmcore/src/jit/jit_runtime_support.cpp @@ -270,7 +270,7 @@ static LilCodeStub* rth_gen_lil_type_tes Class* dummy = NULL; const size_t is_fast_off = Class::get_offset_of_fast_instanceof_flag(dummy); const size_t depth_off = Class::get_offset_of_depth(dummy); - const POINTER_SIZE_INT supertable_off = (POINTER_SIZE_INT)&((VTable*)NULL)->superclasses; + const POINTER_SIZE_INT supertable_off = offsetof(VTable, superclasses); bool do_slow = true; if (type) { if(type->get_fast_instanceof_flag()) { @@ -308,7 +308,7 @@ static LilCodeStub* rth_gen_lil_type_tes assert(cs); //*** Slow sequence - const POINTER_SIZE_INT clss_off = (POINTER_SIZE_INT)&((VTable*)NULL)->clss; + const POINTER_SIZE_INT clss_off = offsetof(VTable, clss); Boolean (*p_subclass)(Class_Handle, Class_Handle) = class_is_subtype; if (do_slow) { cs = lil_parse_onto_end(cs, @@ -580,8 +580,8 @@ static NativeCodePtr rth_get_lil_aastore if (!addr) { bool (*p_aastore_test)(ManagedObject*, Vector_Handle) = rth_aastore_test; - // The args are the element ref to store and the array to store into\n - LilCodeStub* cs = lil_parse_code_stub("entry 0:rth:ref,ref:void;"); + // The args are the element ref to store and the array to store into + LilCodeStub* cs = lil_parse_code_stub("entry 0:rth:ref,ref:pint;"); assert(cs); #ifdef VM_STATS assert(dyn_count); diff --git a/vm/vmcore/src/object/object_handles.cpp b/vm/vmcore/src/object/object_handles.cpp index 462e71b..10384de 100644 --- a/vm/vmcore/src/object/object_handles.cpp +++ b/vm/vmcore/src/object/object_handles.cpp @@ -458,7 +458,9 @@ VMEXPORT // temporary solution for inter void free_local_object_handles2(ObjectHandles* head) { ObjectHandlesNew* h = (ObjectHandlesNew*)head; - assert(h); + if (h == NULL) { + return; + } #ifdef VM_STATS VM_Statistics::get_vm_stats().num_free_local_called++; if(h->next != NULL) diff --git a/vm/vmcore/src/util/ia32/base/compile_IA32.cpp b/vm/vmcore/src/util/ia32/base/compile_IA32.cpp index dbabe2a..006e9fa 100644 --- a/vm/vmcore/src/util/ia32/base/compile_IA32.cpp +++ b/vm/vmcore/src/util/ia32/base/compile_IA32.cpp @@ -14,21 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** +/** * @author Intel, Evgueni Brevnov - * @version $Revision: 1.1.2.2.4.4 $ - */ + */ #define LOG_DOMAIN "vm.helpers" #include "cxxlog.h" #include "platform.h" -//MVM -#include - -using namespace std; - #include #include #include @@ -65,6 +59,7 @@ using namespace std; #include "compile.h" #include "lil.h" #include "lil_code_generator.h" +#include "lil_code_generator_ia32.h" #include "vm_stats.h" #include "dump.h" @@ -77,76 +72,78 @@ void compile_flush_generated_code() { // Nothing to do on IA32 } -static uint32* get_arg_word(unsigned num_arg_words, unsigned word) { - return m2n_get_args(m2n_get_last_frame())+num_arg_words-word-1; +static bool is_magic_type(const char* fullyqClassName) +{ + if (NULL == fullyqClassName) return false; + bool is_magic = false; + if (strcmp(fullyqClassName, "org/vmmagic/unboxed/Address") == 0) { + is_magic = true; + } + else if (strcmp(fullyqClassName, "org/vmmagic/unboxed/Extent") == 0) { + is_magic = true; + } + else if (strcmp(fullyqClassName, "org/vmmagic/unboxed/Offset") == 0) { + is_magic = true; + } + else if (strcmp(fullyqClassName, "org/vmmagic/unboxed/Word") == 0) { + is_magic = true; + } + else if (strcmp(fullyqClassName, "org/vmmagic/unboxed/ObjectReference") == 0) { + is_magic = true; + } + return is_magic; +} + +static bool is_magic_argument(Method_Signature_Handle msh, unsigned arg) +{ + if (arg>=method_args_get_number(msh)) { + assert(false); + return false; + } + Type_Info_Handle tih = method_args_get_type_info(msh, arg); + const String *str = tih->get_type_name(); + return str != NULL && is_magic_type(str->bytes); } -void compile_protect_arguments(Method_Handle method, GcFrame* gc) { + +void compile_protect_arguments(Method_Handle method, GcFrame* gc) +{ assert(!hythread_is_suspend_enabled()); Method_Signature_Handle msh = method_get_signature(method); - unsigned num_args = method_args_get_number(msh); - unsigned num_arg_words = ((Method*)method)->get_num_arg_slots(); - - unsigned cur_word = 0; - for(unsigned i=0; iget_type_name(); - - switch (type_info_get_type(tih)) { - case VM_DATA_TYPE_INT64: - case VM_DATA_TYPE_UINT64: - case VM_DATA_TYPE_F8: - cur_word += 2; - break; - case VM_DATA_TYPE_INT8: - case VM_DATA_TYPE_UINT8: - case VM_DATA_TYPE_INT16: - case VM_DATA_TYPE_UINT16: - case VM_DATA_TYPE_INT32: - case VM_DATA_TYPE_UINT32: - case VM_DATA_TYPE_INTPTR: - case VM_DATA_TYPE_UINTPTR: - case VM_DATA_TYPE_F4: - case VM_DATA_TYPE_BOOLEAN: - case VM_DATA_TYPE_CHAR: - case VM_DATA_TYPE_UP: - cur_word++; - break; - case VM_DATA_TYPE_CLASS: - case VM_DATA_TYPE_ARRAY: - if (str) { //wjw MMTk support - if (strncmp(str->bytes, "org/vmmagic/unboxed/Address", str->len) == 0 ) - is_magic = true; - if (strncmp(str->bytes, "org/vmmagic/unboxed/Extent", str->len) == 0 ) - is_magic = true; - if (strncmp(str->bytes, "org/vmmagic/unboxed/Offset", str->len) == 0 ) - is_magic = true; - if (strncmp(str->bytes, "org/vmmagic/unboxed/Word", str->len) == 0 ) - is_magic = true; - if (strncmp(str->bytes, "org/vmmagic/unboxed/ObjectReference", str->len) == 0 ) - is_magic = true; - } - if (is_magic == false) - gc->add_object((ManagedObject**)get_arg_word(num_arg_words, cur_word)); - cur_word++; - break; - case VM_DATA_TYPE_MP: - gc->add_managed_pointer((ManagedPointer*)get_arg_word(num_arg_words, cur_word)); - break; - case VM_DATA_TYPE_VALUE: - { - // This should never cause loading - Class_Handle UNUSED c = type_info_get_class(tih); - assert(c); - DIE("This functionality is not currently supported"); - break; - } - default: - ASSERT(0, "Unexpected data type: " << type_info_get_type(tih)); + + CallSig csig(msh); + + M2nFrame* lastM2N = m2n_get_last_frame(); + LilStackFrameLayout stackFrameLayout; + + const int m2n_offset = stackFrameLayout.adjust(stackFrameLayout.get_m2n()); + char* retIP = (char*)lastM2N - m2n_offset + stackFrameLayout.size(); + char* lastArgSlot = retIP + sizeof(void*); + + for(unsigned i=0; iadd_object((ManagedObject**)parg); + } + else { + // argument passed on a register + // double check - we currently do not pass Objects on XMMs + assert(getRegKind(reg) == OpndKind_GPReg); + int offset = m2n_get_reg_offset(to_Reg_No(reg)); + void* preg = (void*)(offset + (char*)lastM2N); + gc->add_object((ManagedObject**)preg); } } -} +} // compile_protect_arguments void patch_code_with_threads_suspended(Byte * UNREF code_block, Byte * UNREF new_code, size_t UNREF size) { ABORT("Not supported on IA32 currently"); @@ -185,49 +182,56 @@ static NativeCodePtr compile_get_compile #ifndef NDEBUG memset(stub, 0xcc /*int 3*/, STUB_SIZE); #endif + LilStackFrameLayout stackLayout; + // Std places are already on the top of the stack. Prepare the rest + // stack frame + const unsigned totalFrameSize = stackLayout.size(); + const unsigned allocateSize = totalFrameSize + stackLayout.get_std_places(); + stub = alu(stub, sub_opc, stack_opnd, Imm_Opnd(allocateSize)); // push m2n to the stack - stub = m2n_gen_push_m2n(stub, NULL, FRAME_COMPILATION, false, 0); - // ecx register should contain correct Mehod_Handle - stub = push(stub, ecx_opnd); + const int m2n_offset = stackLayout.adjust(stackLayout.get_m2n()); + const int retAddr_offset = stackLayout.adjust_input_or_ret(stackLayout.get_ret_addr()); + const M_Base_Opnd retAddr(stack_reg, retAddr_offset); + stub = m2n_gen_fill_m2n(stub, m2n_offset, NULL, FRAME_COMPILATION, true, retAddr); + // std0 must contain correct Mehod_Handle + M_Base_Opnd std0(stack_reg, stackLayout.adjust(stackLayout.get_std_place(0))); + stub = push(stub, std0); // compile the method - stub = call(stub, (char *)&compile_me); - // remove ecx from the stack - stub = pop(stub, ecx_opnd); - // pop m2n from the stack - stub = m2n_gen_pop_m2n(stub, false, 0, 0, 1); - // transfer control to the compiled code - stub = jump(stub, eax_opnd); - - assert(stub - (char *)addr <= STUB_SIZE); - - compile_add_dynamic_generated_code_chunk("compile_me_generic", addr, STUB_SIZE); + stub = call(stub, (char*)&compile_me); + // it's cdecl-like, restore stack + stub = alu(stub, add_opc, stack_opnd, Imm_Opnd(sizeof(void*))); + // re-throw exception if it pending + M_Base_Opnd eaxSpill(stack_reg, stackLayout.adjust(stackLayout.get_scratch())); + // preserve EAX across the call + stub = mov(stub, eaxSpill, eax_opnd); + // throw if something terrible happened during compilation + stub = call(stub, (char *)&exn_rethrow_if_pending); + // restore thing from M2N + stub = m2n_gen_clear_m2n(stub, m2n_offset, false, true); + + stub = push(stub, eaxSpill); // put method address on stack + // return + destroy stack frame + stub = ret(stub, Imm_Opnd(totalFrameSize)); + + unsigned realSize = stub - (char *)addr; + assert(realSize <= (unsigned)STUB_SIZE); + + compile_add_dynamic_generated_code_chunk("compile_me_generic", addr, realSize); if (VM_Global_State::loader_env->TI->isEnabled()) - jvmti_send_dynamic_code_generated_event("compile_me_generic", addr, STUB_SIZE); + jvmti_send_dynamic_code_generated_event("compile_me_generic", addr, realSize); - DUMP_STUB(addr, "compileme_generic", stub - (char *)addr); + DUMP_STUB(addr, "compileme_generic", realSize); return addr; } NativeCodePtr compile_gen_compile_me(Method_Handle method) { - const int STUB_SIZE = 16; + const int STUB_SIZE = 0x20; #ifdef VM_STATS ++VM_Statistics::get_vm_stats().num_compileme_generated; #endif - char * stub = (char *) method_get_class(method)->code_alloc(STUB_SIZE, DEFAULT_CODE_ALIGNMENT, CAA_Allocate); - NativeCodePtr addr = stub; -#ifndef NDEBUG - memset(stub, 0xcc /*int 3*/, STUB_SIZE); -#endif - -#ifdef VM_STATS - stub = inc(stub, M_Base_Opnd(n_reg, (int32)&VM_Statistics::get_vm_stats().num_compileme_used)); -#endif - stub = mov(stub, ecx_opnd, Imm_Opnd((int32)method)); - stub = jump(stub, (char *)compile_get_compile_me_generic()); - assert(stub - (char *)addr <= STUB_SIZE); char * name; const char * c = class_get_name(method_get_class(method)); @@ -235,32 +239,48 @@ NativeCodePtr compile_gen_compile_me(Met const char * d = method_get_descriptor(method); size_t sz = strlen(c)+strlen(m)+strlen(d)+12; name = (char *)STD_MALLOC(sz); - sprintf(name, "compileme.%s.%s%s", c, m, d); - compile_add_dynamic_generated_code_chunk(name, addr, STUB_SIZE); + apr_snprintf(name, sz, "compileme.%s.%s%s", c, m, d); - if (VM_Global_State::loader_env->TI->isEnabled()) - jvmti_send_dynamic_code_generated_event(name, addr, STUB_SIZE); + char * stub = (char *) malloc_fixed_code_for_jit(STUB_SIZE, + DEFAULT_CODE_ALIGNMENT, CODE_BLOCK_HEAT_DEFAULT, CAA_Allocate); + NativeCodePtr addr = stub; +#ifdef _DEBUG + memset(stub, 0xcc /*int 3*/, STUB_SIZE); +#endif +#ifdef VM_STATS + stub = inc(stub, M_Base_Opnd(n_reg, (int32)&VM_Statistics::get_vm_stats().num_compileme_used)); +#endif + // + // The compile_me_generic() uses std places for args - prepare both + // std places + // + /* + stub = alu(stub, sub_opc, stack_opnd, Imm_Opnd(STACK_SLOT_SIZE*2)); + stub = mov(stub, stack_slot_1, Imm_Opnd((void*)method)); + stub = mov(stub, stack_slot_0, Imm_Opnd(0xBAADF00D)); + */ + stub = push(stub, Imm_Opnd((void*)method)); + stub = push(stub, Imm_Opnd(0xBAADF00D)); -#ifndef NDEBUG - static unsigned done = 0; - // dump first 10 compileme stubs - if (dump_stubs && ++done <= 10) { - char * buf; - const char * c = class_get_name(method_get_class(method)); - const char * m = method_get_name(method); - const char * d = method_get_descriptor(method); - size_t sz = strlen(c)+strlen(m)+strlen(d)+12; - buf = (char *)STD_MALLOC(sz); - sprintf(buf, "compileme.%s.%s%s", c, m, d); - assert(strlen(buf) < sz); - DUMP_STUB(addr, buf, stub - (char *)addr); - STD_FREE(buf); + stub = jump(stub, (char *)compile_get_compile_me_generic()); + unsigned realSize = stub - (char *)addr; + assert(realSize <= STUB_SIZE); + + compile_add_dynamic_generated_code_chunk(name, addr, realSize); + + if (VM_Global_State::loader_env->TI->isEnabled()) { + jvmti_send_dynamic_code_generated_event(name, addr, realSize); } -#endif + + DUMP_STUB(addr, name, realSize); + // + // NOTE: name is not STD_FREE()-d here. It's intentional, as the name + // pointer is stored (and not copied) in compile_add_dynamic_generated_code_chunk(). + // return addr; } //compile_gen_compile_me - + /* END COMPILE-ME STUBS */ void gen_native_hashcode(Emitter_Handle h, Method *m); diff --git a/vm/vmcore/src/util/ia32/base/ini_iA32.cpp b/vm/vmcore/src/util/ia32/base/ini_iA32.cpp index 986b053..0602a51 100644 --- a/vm/vmcore/src/util/ia32/base/ini_iA32.cpp +++ b/vm/vmcore/src/util/ia32/base/ini_iA32.cpp @@ -14,17 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** +/** * @author Intel, Evgueni Brevnov - * @version $Revision: 1.1.2.1.4.3 $ - */ - - - -//MVM -#include + */ -using namespace std; #include @@ -45,165 +38,307 @@ using namespace std; #include "interpreter.h" #include "port_malloc.h" +#include "callsig.h" +#include "dump.h" #define LOG_DOMAIN "invoke" #include "cxxlog.h" -#ifdef _WIN32 -static int64 __declspec(naked) __stdcall -vm_invoke_native_array_stub(uint32 *args, - int sz, - void* f) +#include + +typedef double (*DoubleFuncPtr)( +void* addr, double* p_fr_args, unsigned stack_bytes, void* p_stack_args, +void* eax, void* ebx, void* ecx, void* edx); + +typedef ManagedObject* (*RefFuncPtr)( +void* addr, double* p_fr_args, unsigned stack_bytes, void* p_stack_args, +void* eax, void* ebx, void* ecx, void* edx); + +typedef float (*FloatFuncPtr)( +void* addr, double* p_fr_args, unsigned stack_bytes, void* p_stack_args, +void* eax, void* ebx, void* ecx, void* edx); + +typedef int32 (*IntFuncPtr)( +void* addr, double* p_fr_args, unsigned stack_bytes, void* p_stack_args, +void* eax, void* ebx, void* ecx, void* edx); + +typedef int64 (*Int64FuncPtr)( +void* addr, double* p_fr_args, unsigned stack_bytes, void* p_stack_args, +void* eax, void* ebx, void* ecx, void* edx); + + +#define ADDR_offset (4+16) // retIP + push(ebx,esi,edi,ebp) + +#define P_FR_ARGS_offset (ADDR_offset+4) + +#define STACK_BYTES_offset (P_FR_ARGS_offset+4) +#define P_STACK_ARGS_offset (STACK_BYTES_offset+4) + +#define EAX_offset (P_STACK_ARGS_offset+4) +#define EBX_offset (EAX_offset+4) +#define ECX_offset (EBX_offset+4) +#define EDX_offset (ECX_offset+4) + +/* +invoke_managed has the following signature: + +invoke_managed( + void* addr, + double* p_fr_args, + unsigned stack_bytes, + void* p_stack_args, + void* eax, void* ebx, void* ecx, void* edx + ); + +*/ +static NativeCodePtr gen_invoke_managed_code_stub(void) { - __asm { - push ebp - mov ebp, esp - push ebx // FIXME: check jit calling conventions, - push esi // is it necessary to save the registers here - push edi - - mov eax, [ebp+8] - mov ecx, [ebp+12] - lea eax, [eax+ecx*4-4] - sub eax, esp - or ecx, ecx - je e - l: - push [esp+eax] - loop l - e: - mov eax, [ebp+16] - call eax - lea esp, [ebp-12] - pop edi - pop esi - pop ebx - leave - ret + static NativeCodePtr staticAddr = NULL; + + if (NULL != staticAddr) { + return staticAddr; } + + const unsigned STUB_SIZE = 0x80; + char* buf = (char*)malloc_fixed_code_for_jit(STUB_SIZE, + DEFAULT_CODE_ALIGNMENT, CODE_BLOCK_HEAT_DEFAULT, CAA_Allocate); + staticAddr = buf; + // + buf = push(buf, ebx_opnd); + buf = push(buf, esi_opnd); + buf = push(buf, edi_opnd); + buf = push(buf, ebp_opnd); + // + buf = mov(buf, ebp_opnd, esp_opnd); + const Reg_No localBaseReg = ebp_reg; + // + + // + // 1. Load XMMs + // + // mov eax, [ebp+P_FR_ARGS_offset] + // for i in 0..7 do + // movq xmm#i, [eax+sizeof(double)*i] + + M_Base_Opnd pFrArgs(localBaseReg, P_FR_ARGS_offset); + Reg_No tmpBase = eax_reg; + + buf = mov(buf, eax_opnd, pFrArgs); + for (unsigned i=0; ilastFrame; p_TLS_vmthread->lastFrame = (void*)&lastFrame; - //printf("execute: push: prev = 0x%p, curr=0x%p\n", lastFrame, &lastFrame); -// fprintf(stderr, "Not implemented\n"); + assert(!hythread_is_suspend_enabled()); Method *method = (Method*) methodID; TRACE("enter method " << method->get_class()->get_name()->bytes << " " << method->get_name()->bytes << " " << method->get_descriptor()->bytes); - int sz = method->get_num_arg_slots(); - void *meth_addr = method->get_code_addr(); - uint32 *arg_words = (uint32*) STD_ALLOCA(sz * sizeof(uint32)); - - int argId = sz; - int pos = 0; - - assert(!hythread_is_suspend_enabled()); - if (!method->is_static()) { - ObjectHandle handle = (ObjectHandle) args[pos++].l; - assert(handle); - arg_words[--argId] = (unsigned) handle->object; - } - - const char *mtype = method->get_descriptor()->bytes + 1; - assert(mtype != 0); - for(; *mtype != ')'; mtype++) { - switch(*mtype) { + Method_Signature_Handle msh = method_get_signature((Method_Handle)method); + CallSig csig(msh); + + void* regs[n_gp_regs] = {NULL}; + double xmms[n_xmm_regs] = {0.}; + void* stackArgs = STD_ALLOCA(csig.get_stack_size()); + unsigned stackWords = 0; + + for (unsigned argIdx=0; argIdxobject : 0); - - while(*mtype == '[') mtype++; - if (*mtype == 'L') - while(*mtype != ';') mtype++; + ObjectHandle handle = (ObjectHandle) args[argIdx].l; + *(void**)whereToPut = (void*) (handle ? handle->object : 0); } break; - case JAVA_TYPE_SHORT: // sign extend - arg_words[--argId] = (uint32)(int32) args[pos++].s; + *(int32*)whereToPut = (int32) args[argIdx].s; break; case JAVA_TYPE_BYTE: // sign extend - arg_words[--argId] = (uint32)(int32) args[pos++].b; + *(int32*)whereToPut = (int32) args[argIdx].b; break; case JAVA_TYPE_INT: // sign extend - arg_words[--argId] = (uint32)(int32) args[pos++].i; + *(int32*)whereToPut = (int32) args[argIdx].i; break; - case JAVA_TYPE_FLOAT: - arg_words[--argId] = (int32) args[pos++].i; + *(int32*)whereToPut = (int32) args[argIdx].i; break; case JAVA_TYPE_BOOLEAN: - arg_words[--argId] = (int32) args[pos++].z; + *(int32*)whereToPut = (int32) args[argIdx].z; break; case JAVA_TYPE_CHAR: // zero extend - arg_words[--argId] = (int32) args[pos++].c; + *(int32*)whereToPut = (int32) args[argIdx].c; break; - case JAVA_TYPE_LONG: case JAVA_TYPE_DOUBLE: - *(jlong*)&arg_words[argId-2] = args[pos++].j; - argId -= 2; + *(jlong*)whereToPut = args[argIdx].j; +// *(jlong*)&arg_words[argId-2] = args[argIdx].j; +// argId -= 2; break; default: ABORT("Unexpected java type"); } } - assert(argId >= 0); jvalue *resultPtr = (jvalue*) return_value; Java_Type ret_type = method->get_return_java_type(); - arg_words += argId; - argId = sz - argId; + unsigned stack_bytes = csig.get_stack_size(); //stackWords*sizeof(void*); + void *meth_addr = method->get_code_addr(); switch(ret_type) { case JAVA_TYPE_VOID: - vm_invoke_native_array_stub(arg_words, argId, meth_addr); + get_int_func_ptr()(meth_addr, xmms, stack_bytes, stackArgs, regs[0], regs[1], regs[2], regs[3]); break; case JAVA_TYPE_CLASS: case JAVA_TYPE_ARRAY: case JAVA_TYPE_STRING: { - ManagedObject *ref = vm_invoke_native_array_stub_ref(arg_words, argId, meth_addr); + ManagedObject *ref = get_ref_func_ptr()(meth_addr, xmms, stack_bytes, stackArgs, regs[0], regs[1], regs[2], regs[3]); ObjectHandle h = oh_allocate_local_handle(); if (ref != NULL) { @@ -220,19 +355,19 @@ JIT_execute_method_default(JIT_Handle ji case JAVA_TYPE_CHAR: case JAVA_TYPE_SHORT: case JAVA_TYPE_INT: - resultPtr->i = vm_invoke_native_array_stub_int(arg_words, argId, meth_addr); + resultPtr->i = get_int_func_ptr()(meth_addr, xmms, stack_bytes, stackArgs, regs[0], regs[1], regs[2], regs[3]); break; case JAVA_TYPE_FLOAT: - resultPtr->f = vm_invoke_native_array_stub_float(arg_words, argId, meth_addr); + resultPtr->f = get_float_func_ptr()(meth_addr, xmms, stack_bytes, stackArgs, regs[0], regs[1], regs[2], regs[3]); break; case JAVA_TYPE_LONG: - resultPtr->j = vm_invoke_native_array_stub(arg_words, argId, meth_addr); + resultPtr->j = get_int64_func_ptr()(meth_addr, xmms, stack_bytes, stackArgs, regs[0], regs[1], regs[2], regs[3]); break; case JAVA_TYPE_DOUBLE: - resultPtr->d = vm_invoke_native_array_stub_double(arg_words, argId, meth_addr); + resultPtr->d = get_double_func_ptr()(meth_addr, xmms, stack_bytes, stackArgs, regs[0], regs[1], regs[2], regs[3]); break; default: @@ -240,8 +375,7 @@ JIT_execute_method_default(JIT_Handle ji } if (exn_raised()) { - TRACE("Exception occured: " << exn_get_name()); - if ((resultPtr != NULL) && (ret_type != JAVA_TYPE_VOID)) { + if ((resultPtr != NULL) && (ret_type != JAVA_TYPE_VOID)) { resultPtr->l = 0; //clear result } } @@ -256,7 +390,3 @@ JIT_execute_method_default(JIT_Handle ji //printf("execute: pop: prev = 0x%p, curr=0x%p\n", &lastFrame, lastFrame); p_TLS_vmthread->lastFrame = lastFrame; } - - - - diff --git a/vm/vmcore/src/util/ia32/base/invoke_native_stub_ia32.asm b/vm/vmcore/src/util/ia32/base/invoke_native_stub_ia32.asm deleted file mode 100644 index bc86d5f..0000000 --- a/vm/vmcore/src/util/ia32/base/invoke_native_stub_ia32.asm +++ /dev/null @@ -1,46 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one or more -// contributor license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright ownership. -// The ASF licenses this file to You under the Apache License, Version 2.0 -// (the "License"); you may not use this file except in compliance with -// the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Intel, Evgueni Brevnov -// - .text - .align 2 -.globl vm_invoke_native_array_stub - .type vm_invoke_native_array_stub, @function -vm_invoke_native_array_stub: - - push %ebp - movl %esp, %ebp - push %ebx - push %esi - push %edi - movl 8(%ebp), %eax - movl 12(%ebp), %ecx - leal -4(%eax,%ecx,4), %eax - subl %esp, %eax - or %ecx, %ecx - je 2f -1: - push 0(%esp,%eax) - loop 1b -2: - movl 16(%ebp), %eax - call *%eax - leal -12(%ebp), %esp - pop %edi - pop %esi - pop %ebx - leave - ret diff --git a/vm/vmcore/src/util/ia32/base/jit_lock_rt_support_ia32.cpp b/vm/vmcore/src/util/ia32/base/jit_lock_rt_support_ia32.cpp index 4cb8462..0a7b892 100644 --- a/vm/vmcore/src/util/ia32/base/jit_lock_rt_support_ia32.cpp +++ b/vm/vmcore/src/util/ia32/base/jit_lock_rt_support_ia32.cpp @@ -14,21 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** +/** * @author Intel, Evgueni Brevnov - * @version $Revision: 1.1.2.2.4.3 $ - */ + */ #include #include #include "platform_lowlevel.h" - -//MVM -#include - -using namespace std; - #include #include "open/vm_util.h" @@ -113,8 +106,8 @@ static char * gen_restore_monitor_enter( } ss = gen_setup_j2n_frame(ss); - ss = push(ss, M_Base_Opnd(esp_reg, m2n_sizeof_m2n_frame)); - + ss = push(ss, M_Base_Opnd(esp_reg, m2n_sizeof_m2n_frame+INPUT_ARG_OFFSET)); + ss = call(ss, (char *)oh_convert_to_local_handle); ss = alu(ss, add_opc, esp_opnd, Imm_Opnd(4)); // pop parameters @@ -186,7 +179,6 @@ static char * gen_restore_monitor_exit(c #ifdef VM_STATS ss = inc(ss, M_Opnd((unsigned)&(VM_Statistics::get_vm_stats().num_monitor_enter))); #endif - ss = mov(ss, ecx_opnd, M_Base_Opnd(esp_reg, INPUT_ARG_OFFSET)); ss = test(ss, ecx_opnd, ecx_opnd); ss = branch8(ss, Condition_Z, Imm_Opnd(size_8, 0)); @@ -199,11 +191,15 @@ static char * gen_restore_monitor_exit(c ss = gen_monitor_exit_helper(ss, ecx_opnd); } else { ss = gen_setup_j2n_frame(ss); - ss = push(ss, M_Base_Opnd(esp_reg, m2n_sizeof_m2n_frame)); - + ss = push(ss, M_Base_Opnd(esp_reg, m2n_sizeof_m2n_frame+INPUT_ARG_OFFSET)); + // oh_convert_to_local_handle returns handle in EAX ss = call(ss, (char *)oh_convert_to_local_handle); - ss = alu(ss, add_opc, esp_opnd, Imm_Opnd(4)); // pop parameters + // it's cdecl - restore stack + ss = alu(ss, add_opc, esp_opnd, Imm_Opnd(4)); + // EAX still holds the handle ss = gen_monitorexit_slow_path_helper(ss, eax_opnd); + // Store EAX into M2n frame, so it's not get lost when restored during pop_j2n + ss = m2n_gen_store_reg(ss, 0, eax_opnd); ss = gen_pop_j2n_frame(ss); } ss = test(ss, eax_opnd, eax_opnd); @@ -213,7 +209,7 @@ static char * gen_restore_monitor_exit(c signed offset = (signed)ss - (signed)backpatch_address__fast_monitor_failed - 1; *backpatch_address__fast_monitor_failed = (char)offset; - // illegal state happend + // illegal state happened ss = jump(ss, (char*)exn_get_rth_throw_illegal_state_exception()); offset = (signed)ss - (signed)backpatch_address__null_pointer - 1; @@ -242,11 +238,12 @@ void * restore__vm_monitor_exit_naked(vo ss = gen_restore_monitor_exit(ss, /*patch_addr_null_arg*/ NULL); - assert((ss - stub) < stub_size); + const unsigned realSize = ss - stub; + assert(realSize < stub_size); - DUMP_STUB(stub, "getaddress__vm_monitor_exit_naked_mt", ss - stub); + DUMP_STUB(stub, "getaddress__vm_monitor_exit_naked_mt", realSize); - return code_addr; + return code_addr; } //restore__vm_monitor_exit_naked @@ -264,11 +261,12 @@ void * restore__vm_monitor_exit_static_n ss = gen_convert_struct_class_to_object(ss, &patch_addr_null_arg); ss = gen_restore_monitor_exit(ss, patch_addr_null_arg); - assert((ss - stub) < stub_size); + const unsigned realSize = ss - stub; + assert(realSize < stub_size); - DUMP_STUB(stub, "getaddress__vm_monitor_exit_static_naked_mt", ss - stub); + DUMP_STUB(stub, "getaddress__vm_monitor_exit_static_naked_mt", realSize); - return code_addr; + return code_addr; } //restore__vm_monitor_exit_static_naked @@ -279,7 +277,7 @@ void * getaddress__vm_monitor_enter_nake return addr; } - const int stub_size = 226; + const int stub_size = 0x200; char *stub = (char *)malloc_fixed_code_for_jit(stub_size, DEFAULT_CODE_ALIGNMENT, CODE_BLOCK_HEAT_MAX/2, CAA_Allocate); #ifdef _DEBUG memset(stub, 0xcc /*int 3*/, stub_size); @@ -294,14 +292,15 @@ void * getaddress__vm_monitor_enter_nake ss = gen_restore_monitor_enter(ss, /*patch_addr_null_arg*/ NULL); addr = stub; - assert((ss - stub) < stub_size); + const unsigned realSize = ss - stub; + assert(realSize < stub_size); - compile_add_dynamic_generated_code_chunk("vm_monitor_enter_naked", stub, stub_size); + compile_add_dynamic_generated_code_chunk("vm_monitor_enter_naked", stub, realSize); if (VM_Global_State::loader_env->TI->isEnabled()) - jvmti_send_dynamic_code_generated_event("vm_monitor_enter_naked", stub, stub_size); + jvmti_send_dynamic_code_generated_event("vm_monitor_enter_naked", stub, realSize); - DUMP_STUB(stub, "getaddress__vm_monitor_enter_naked", ss - stub); + DUMP_STUB(stub, "getaddress__vm_monitor_enter_naked", realSize); return addr; } @@ -314,7 +313,7 @@ void * getaddress__vm_monitor_enter_stat return addr; } - const int stub_size = 250; + const int stub_size = 0x200; char *stub = (char *)malloc_fixed_code_for_jit(stub_size, DEFAULT_CODE_ALIGNMENT, CODE_BLOCK_HEAT_MAX/2, CAA_Allocate); #ifdef _DEBUG memset(stub, 0xcc /*int 3*/, stub_size); @@ -328,17 +327,18 @@ void * getaddress__vm_monitor_enter_stat char *patch_addr_null_arg; ss = gen_convert_struct_class_to_object(ss, &patch_addr_null_arg); - ss = gen_restore_monitor_enter(ss, patch_addr_null_arg); + ss = gen_restore_monitor_enter(ss, patch_addr_null_arg); addr = stub; - assert((ss - stub) < stub_size); + const unsigned realSize = ss - stub; + assert(realSize < stub_size); - compile_add_dynamic_generated_code_chunk("vm_monitor_enter_static_naked", stub, stub_size); + compile_add_dynamic_generated_code_chunk("vm_monitor_enter_static_naked", stub, realSize); if (VM_Global_State::loader_env->TI->isEnabled()) - jvmti_send_dynamic_code_generated_event("vm_monitor_enter_static_naked", stub, stub_size); + jvmti_send_dynamic_code_generated_event("vm_monitor_enter_static_naked", stub, realSize); - DUMP_STUB(stub, "getaddress__vm_monitor_enter_static_naked", ss - stub); + DUMP_STUB(stub, "getaddress__vm_monitor_enter_static_naked", realSize); return addr; } //getaddress__vm_monitor_enter_static_naked @@ -353,7 +353,7 @@ void * getaddress__vm_monitor_exit_naked return addr; } - const int stub_size = /*126*/210; + const int stub_size = 0x200; char *stub = (char *)malloc_fixed_code_for_jit(stub_size, DEFAULT_CODE_ALIGNMENT, CODE_BLOCK_HEAT_MAX/2, CAA_Allocate); char *ss = stub; @@ -366,14 +366,15 @@ void * getaddress__vm_monitor_exit_naked ss = gen_restore_monitor_exit(ss, /*patch_addr_null_arg*/ NULL); addr = stub; - assert((ss - stub) < stub_size); + const unsigned realSize = ss - stub; + assert(realSize < stub_size); - compile_add_dynamic_generated_code_chunk("vm_monitor_exit_naked", stub, stub_size); + compile_add_dynamic_generated_code_chunk("vm_monitor_exit_naked", stub, realSize); if (VM_Global_State::loader_env->TI->isEnabled()) - jvmti_send_dynamic_code_generated_event("vm_monitor_exit_naked", stub, stub_size); + jvmti_send_dynamic_code_generated_event("vm_monitor_exit_naked", stub, realSize); - DUMP_STUB(stub, "getaddress__vm_monitor_exit_naked", ss - stub); + DUMP_STUB(stub, "getaddress__vm_monitor_exit_naked", realSize); return addr; } //getaddress__vm_monitor_exit_naked @@ -386,7 +387,7 @@ void * getaddress__vm_monitor_exit_stati return addr; } - const int stub_size = /*126*/210; + const int stub_size = 0x200; char *stub = (char *)malloc_fixed_code_for_jit(stub_size, DEFAULT_CODE_ALIGNMENT, CODE_BLOCK_HEAT_MAX/2, CAA_Allocate); char *ss = stub; @@ -395,19 +396,20 @@ void * getaddress__vm_monitor_exit_stati ss = inc(ss, M_Opnd((unsigned)value)); #endif - char *patch_addr_null_arg; + char *patch_addr_null_arg = NULL; ss = gen_convert_struct_class_to_object(ss, &patch_addr_null_arg); - ss = gen_restore_monitor_exit(ss, patch_addr_null_arg); + ss = gen_restore_monitor_exit(ss, patch_addr_null_arg); addr = stub; - assert((ss - stub) < stub_size); + const unsigned realSize = ss - stub; + assert(realSize < stub_size); - compile_add_dynamic_generated_code_chunk("vm_monitor_exit_static_naked", stub, stub_size); + compile_add_dynamic_generated_code_chunk("vm_monitor_exit_static_naked", stub, realSize); if (VM_Global_State::loader_env->TI->isEnabled()) - jvmti_send_dynamic_code_generated_event("vm_monitor_exit_static_naked", stub, stub_size); + jvmti_send_dynamic_code_generated_event("vm_monitor_exit_static_naked", stub, realSize); - DUMP_STUB(stub, "getaddress__vm_monitor_exit_static_naked", ss - stub); + DUMP_STUB(stub, "getaddress__vm_monitor_exit_static_naked", realSize); return addr; } //getaddress__vm_monitor_exit_static_naked diff --git a/vm/vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp b/vm/vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp index 2231af7..0ee7130 100644 --- a/vm/vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp +++ b/vm/vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp @@ -14,16 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** +/** * @author Intel, Evgueni Brevnov, Ivan Volosyuk - * @version $Revision: 1.1.2.2.4.5 $ - */ - - -//MVM -#include - -using namespace std; + */ #include @@ -311,25 +304,14 @@ static void *generate_object_allocation_ char *slow_obj_alloc_proc, char *stub_name) { - const int stub_size = 52+26; + const int stub_size = 0x200; //52+26; char *stub = (char *)malloc_fixed_code_for_jit(stub_size, DEFAULT_CODE_ALIGNMENT, CODE_BLOCK_HEAT_MAX/2, CAA_Allocate); + char *ss = stub; #ifdef _DEBUG memset(stub, 0xcc /*int 3*/, stub_size); #endif - char *ss = stub; -// openTM integration -//#ifdef PLATFORM_POSIX ss = call(ss, (char *)vm_get_gc_thread_local); -/*#else // !PLATFORM_POSIX - *ss++ = (char)0x64; - *ss++ = (char)0xa1; - *ss++ = (char)0x14; - *ss++ = (char)0x00; - *ss++ = (char)0x00; - *ss++ = (char)0x00; - ss = alu(ss, add_opc, eax_opnd, Imm_Opnd((uint32)&((VM_thread *)0)->_gc_private_information)); -#endif // !PLATFORM_POSIX -*/ + ss = push(ss, eax_opnd); ss = push(ss, M_Base_Opnd(esp_reg, 12)); @@ -346,39 +328,34 @@ static void *generate_object_allocation_ signed offset = (signed)ss - (signed)backpatch_address__fast_alloc_failed - 1; *backpatch_address__fast_alloc_failed = (char)offset; - + ss = gen_setup_j2n_frame(ss); -// openTM integration -//#ifdef PLATFORM_POSIX ss = call(ss, (char *)vm_get_gc_thread_local); -/*#else // !PLATFORM_POSIX - *ss++ = (char)0x64; - *ss++ = (char)0xa1; - *ss++ = (char)0x14; - *ss++ = (char)0x00; - *ss++ = (char)0x00; - *ss++ = (char)0x00; - ss = alu(ss, add_opc, eax_opnd, Imm_Opnd((uint32)&((VM_thread *)0)->_gc_private_information)); -#endif // !PLATFORM_POSIX -*/ ss = push(ss, eax_opnd); - ss = push(ss, M_Base_Opnd(esp_reg, 8+m2n_sizeof_m2n_frame)); - ss = push(ss, M_Base_Opnd(esp_reg, 8+m2n_sizeof_m2n_frame)); + + const int stackSlotSize = sizeof(void*); + int in_arg_offset = m2n_sizeof_m2n_frame + 12; + ss = push(ss, M_Base_Opnd(esp_reg, in_arg_offset)); + ss = push(ss, M_Base_Opnd(esp_reg, in_arg_offset)); // + stackSlotSize)); ss = call(ss, (char *)slow_obj_alloc_proc); ss = alu(ss, add_opc, esp_opnd, Imm_Opnd(12)); + // Store EAX into M2n frame, so it's not get lost when restored during pop_j2n + ss = m2n_gen_store_reg(ss, 0, eax_opnd); + ss = gen_pop_j2n_frame(ss); ss = ret(ss, Imm_Opnd(8)); - assert((ss - stub) <= stub_size); + unsigned realSize = (ss - stub); + assert(realSize <= stub_size); - compile_add_dynamic_generated_code_chunk("object_allocation_stub_with_thread_pointer", stub, stub_size); + compile_add_dynamic_generated_code_chunk("object_allocation_stub_with_thread_pointer", stub, realSize); if (VM_Global_State::loader_env->TI->isEnabled()) - jvmti_send_dynamic_code_generated_event("object_allocation_stub_with_thread_pointer", stub, stub_size); + jvmti_send_dynamic_code_generated_event("object_allocation_stub_with_thread_pointer", stub, realSize); - DUMP_STUB(stub, stub_name, ss - stub); + DUMP_STUB(stub, stub_name, realSize); return (void *)stub; } //generate_object_allocation_stub_with_thread_pointer @@ -857,83 +834,19 @@ static void vm_throw_java_lang_Arithmeti } //vm_throw_java_lang_ArithmeticException -static void* getaddress__setup_java_to_native_frame() +VMEXPORT char *gen_setup_j2n_frame(char *ss) { - static void *addr = 0; - if (addr) { - return addr; - } - - const int stub_size = 3+m2n_push_m2n_size(false, 1)+1+1; - char *stub = (char *)malloc_fixed_code_for_jit(stub_size, DEFAULT_CODE_ALIGNMENT, CODE_BLOCK_HEAT_MAX/2, CAA_Allocate); -#ifdef _DEBUG - memset(stub, 0xcc /*int 3*/, stub_size); -#endif - char *ss = stub; - - ss = xchg(ss, M_Base_Opnd(esp_reg, 0), ebp_opnd, size_32); - ss = m2n_gen_push_m2n(ss, NULL, FRAME_UNKNOWN, false, 1); - ss = push(ss, ebp_opnd); - ss = ret(ss); - - assert((ss - stub) <= stub_size); - addr = stub; - - compile_add_dynamic_generated_code_chunk("setup_java_to_native_frame", stub, stub_size); - - if (VM_Global_State::loader_env->TI->isEnabled()) - jvmti_send_dynamic_code_generated_event("setup_java_to_native_frame", stub, stub_size); - - DUMP_STUB(stub, "getaddress__setup_java_to_native_frame", ss - stub); - - return addr; -} //getaddress__setup_java_to_native_frame - - -VMEXPORT char *gen_setup_j2n_frame(char *s) -{ - s = call(s, (char *)getaddress__setup_java_to_native_frame() ); - return s; + //NOTE: the function presumes that 'return address' is immediately on + // the top of the stack + M_Base_Opnd retAddr(stack_reg, 0); + ss = m2n_gen_push_m2n(ss, NULL, FRAME_UNKNOWN, retAddr); + return ss; } //setup_j2n_frame - -static void* getaddress__pop_java_to_native_frame() -{ - static void *addr = 0; - if (addr) { - return addr; - } - - const int stub_size = 1+m2n_pop_m2n_size(false, 0, 0, 2)+1+1; - char *stub = (char *)malloc_fixed_code_for_jit(stub_size, DEFAULT_CODE_ALIGNMENT, CODE_BLOCK_HEAT_MAX/2, CAA_Allocate); -#ifdef _DEBUG - memset(stub, 0xcc /*int 3*/, stub_size); -#endif - char *ss = stub; - - ss = pop(ss, edx_opnd); - ss = m2n_gen_pop_m2n(ss, false, 0, 0, 2); - ss = push(ss, edx_opnd); - ss = ret(ss); - - assert((ss - stub) <= stub_size); - addr = stub; - - compile_add_dynamic_generated_code_chunk("pop_java_to_native_frame", stub, stub_size); - - if (VM_Global_State::loader_env->TI->isEnabled()) - jvmti_send_dynamic_code_generated_event("pop_java_to_native_frame", stub, stub_size); - - DUMP_STUB(stub, "getaddress__pop_java_to_native_frame", ss - stub); - - return addr; -} //getaddress__pop_java_to_native_frame - - -VMEXPORT char *gen_pop_j2n_frame(char *s) +VMEXPORT char *gen_pop_j2n_frame(char *ss) { - s = call(s, (char *)getaddress__pop_java_to_native_frame() ); - return s; + ss = m2n_gen_pop_m2n(ss, false); + return ss; } //setup_j2n_frame -- 1.4.4