? patch-stack-align-darwin-v2 Index: assembler_i486.cpp =================================================================== RCS file: /home/Java/CVS/JDK2/javasrc_1_6_jrl/hotspot/src/cpu/i486/vm/assembler_i486.cpp,v retrieving revision 1.1.1.4 diff -u -r1.1.1.4 assembler_i486.cpp --- assembler_i486.cpp 13 Aug 2007 20:54:12 -0000 1.1.1.4 +++ assembler_i486.cpp 11 Nov 2007 02:15:22 -0000 @@ -2623,16 +2623,88 @@ } +#ifdef __APPLE__ +// Darwin requires 16-byte stack alignment on IA32. We save +// esp to edi, align to 16-bytes to get a known alignment, and then +// pad esp to ensure alignment once the arguments are on the stack +void MacroAssembler::fixup_call_align(int number_of_arguments) { + int argument_size = number_of_arguments * wordSize; + // Save esi, we'll use it to store the current sp + pushl(esi); + movl(esi, esp); + + // Align our stack + andl(esp, -16); + + // If arg_size isn't a multiple of 16, pad the stack to ensure alignment + if (argument_size & 15) + subl(esp, ((argument_size + 15) & -16) - argument_size); +} + +void MacroAssembler::push_call_args(int number_of_arguments, Register args[]) { + // push args. they are passed in left-to-right + int argc = number_of_arguments - 1; + while (argc >= 0) { + if (args[argc] == esi) { + // We saved esi earlier, and used esi to + // record the stack pointer, so let's + // get the argument value back + pushl(Address(esi)); + } else { + pushl(args[argc]); + } + argc--; + } +} + +void MacroAssembler::discard_call_args(int number_of_arguments) { + // sp was saved in esi + movl(esp, esi); + popl(esi); +} + +#else + +void MacroAssembler::fixup_call_align(int number_of_arguments) { + // nop, 4-byte aligned stack +} + +void MacroAssembler::push_call_args(int number_of_arguments, Register args[]) { + // push args. they are passed in left-to-right + int argc = number_of_arguments - 1; + while (argc >= 0) { + pushl(args[argc]); + argc--; + } +} + +void MacroAssembler::discard_call_args(int number_of_arguments) { + int argument_size = number_of_arguments * wordSize; + + // discard thread and arguments + if (argument_size > 0) + addl(esp, argument_size); +} + +#endif // Implementation of call_VM versions void MacroAssembler::call_VM_leaf_base( - address entry_point, - int number_of_arguments + address entry_point, + int number_of_arguments, + Register args[] ) { + if (args != NULL) { + fixup_call_align(number_of_arguments); + push_call_args(number_of_arguments, args); + } + call(entry_point, relocInfo::runtime_call_type); - increment(esp, number_of_arguments * wordSize); + if (args != NULL) { + discard_call_args(number_of_arguments); + } } @@ -2642,6 +2714,7 @@ Register last_java_sp, address entry_point, int number_of_arguments, + Register args[], bool check_exceptions ) { // determine java_thread register @@ -2649,10 +2722,25 @@ java_thread = edi; get_thread(java_thread); } + + fixup_call_align(1 + number_of_arguments); + push_call_args(number_of_arguments, args); + +#ifdef __APPLE__ + // determine last_java_sp register + if (!last_java_sp->is_valid()) { + // esp (-1) saved in esi + leal(eax, Address(esi, 2 * wordSize)); + last_java_sp = eax; + } +#else // determine last_java_sp register if (!last_java_sp->is_valid()) { - last_java_sp = esp; + leal(eax, Address(esp, (1 + number_of_arguments) * wordSize)); + last_java_sp = eax; } +#endif + // debugging support assert(number_of_arguments >= 0 , "cannot have negative number of arguments"); assert(java_thread != oop_result , "cannot use the same register for java_thread & oop_result"); @@ -2688,8 +2776,8 @@ // reset last Java frame // Only interpreter should have to clear fp reset_last_Java_frame(java_thread, true, false); - // discard thread and arguments - addl(esp, (1 + number_of_arguments)*wordSize); + + discard_call_args(1 + number_of_arguments); check_and_handle_popframe(java_thread); check_and_handle_earlyret(java_thread); @@ -2715,9 +2803,8 @@ void MacroAssembler::check_and_handle_earlyret(Register java_thread) { } -void MacroAssembler::call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions) { - leal(eax, Address(esp, (1 + number_of_arguments) * wordSize)); - call_VM_base(oop_result, noreg, eax, entry_point, number_of_arguments, check_exceptions); +void MacroAssembler::call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, Register args[], bool check_exceptions) { + call_VM_base(oop_result, noreg, noreg, entry_point, number_of_arguments, args, check_exceptions); } @@ -2727,7 +2814,7 @@ jmp(E); bind(C); - call_VM_helper(oop_result, entry_point, 0, check_exceptions); + call_VM_helper(oop_result, entry_point, 0, NULL, check_exceptions); ret(0); bind(E); @@ -2735,13 +2822,13 @@ void MacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, bool check_exceptions) { + Register args[] = { arg_1 }; Label C, E; call(C, relocInfo::none); jmp(E); bind(C); - pushl(arg_1); - call_VM_helper(oop_result, entry_point, 1, check_exceptions); + call_VM_helper(oop_result, entry_point, 1, args, check_exceptions); ret(0); bind(E); @@ -2749,14 +2836,13 @@ void MacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, bool check_exceptions) { + Register args[] = { arg_1, arg_2 }; Label C, E; call(C, relocInfo::none); jmp(E); bind(C); - pushl(arg_2); - pushl(arg_1); - call_VM_helper(oop_result, entry_point, 2, check_exceptions); + call_VM_helper(oop_result, entry_point, 2, args, check_exceptions); ret(0); bind(E); @@ -2764,70 +2850,61 @@ void MacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions) { + Register args[] = { arg_1, arg_2, arg_3 }; Label C, E; call(C, relocInfo::none); jmp(E); bind(C); - pushl(arg_3); - pushl(arg_2); - pushl(arg_1); - call_VM_helper(oop_result, entry_point, 3, check_exceptions); + call_VM_helper(oop_result, entry_point, 3, args, check_exceptions); ret(0); bind(E); } - -void MacroAssembler::call_VM(Register oop_result, Register last_java_sp, address entry_point, int number_of_arguments, bool check_exceptions) { - call_VM_base(oop_result, noreg, last_java_sp, entry_point, number_of_arguments, check_exceptions); +void MacroAssembler::call_VM(Register oop_result, Register last_java_sp, address entry_point, int number_of_arguments, Register args[], bool check_exceptions) { + call_VM_base(oop_result, noreg, last_java_sp, entry_point, number_of_arguments, args, check_exceptions); } void MacroAssembler::call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, bool check_exceptions) { - pushl(arg_1); - call_VM(oop_result, last_java_sp, entry_point, 1, check_exceptions); + Register args[] = { arg_1 }; + call_VM(oop_result, last_java_sp, entry_point, 1, args, check_exceptions); } void MacroAssembler::call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, bool check_exceptions) { - pushl(arg_2); - pushl(arg_1); - call_VM(oop_result, last_java_sp, entry_point, 2, check_exceptions); + Register args[] = { arg_1, arg_2 }; + call_VM(oop_result, last_java_sp, entry_point, 2, args, check_exceptions); } void MacroAssembler::call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions) { - pushl(arg_3); - pushl(arg_2); - pushl(arg_1); - call_VM(oop_result, last_java_sp, entry_point, 3, check_exceptions); + Register args[] = { arg_1, arg_2, arg_3 }; + call_VM(oop_result, last_java_sp, entry_point, 3, args, check_exceptions); } -void MacroAssembler::call_VM_leaf(address entry_point, int number_of_arguments) { - call_VM_leaf_base(entry_point, number_of_arguments); +void MacroAssembler::call_VM_leaf(address entry_point, int number_of_arguments, Register args[]) { + call_VM_leaf_base(entry_point, number_of_arguments, args); } void MacroAssembler::call_VM_leaf(address entry_point, Register arg_1) { - pushl(arg_1); - call_VM_leaf(entry_point, 1); + Register args[] = { arg_1 }; + call_VM_leaf(entry_point, 1, args); } void MacroAssembler::call_VM_leaf(address entry_point, Register arg_1, Register arg_2) { - pushl(arg_2); - pushl(arg_1); - call_VM_leaf(entry_point, 2); + Register args[] = { arg_1, arg_2 }; + call_VM_leaf(entry_point, 2, args); } void MacroAssembler::call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3) { - pushl(arg_3); - pushl(arg_2); - pushl(arg_1); - call_VM_leaf(entry_point, 3); + Register args[] = { arg_1, arg_2, arg_3 }; + call_VM_leaf(entry_point, 3, args); } Index: assembler_i486.hpp =================================================================== RCS file: /home/Java/CVS/JDK2/javasrc_1_6_jrl/hotspot/src/cpu/i486/vm/assembler_i486.hpp,v retrieving revision 1.1.1.3 diff -u -r1.1.1.3 assembler_i486.hpp --- assembler_i486.hpp 13 Aug 2007 20:54:12 -0000 1.1.1.3 +++ assembler_i486.hpp 11 Nov 2007 02:15:22 -0000 @@ -677,8 +677,10 @@ // additional registers when doing a VM call). virtual void call_VM_leaf_base( - address entry_point, // the entry point - int number_of_arguments // the number of arguments to pop after the call + address entry_point, // the entry point + int number_of_arguments, // the number of arguments to pop after the call + Register args[] // call argument array (stack ordered, right to left); + // NULL if caller pushed the args directly. ); // This is the base routine called by the different versions of call_VM. The interpreter @@ -695,6 +697,7 @@ Register last_java_sp, // to set up last_Java_frame in stubs; use noreg otherwise address entry_point, // the entry point int number_of_arguments, // the number of arguments (w/o thread) to pop after the call + Register args[], // call argument array (stack ordered, right to left) bool check_exceptions // whether to check for pending exceptions after return ); @@ -704,7 +707,7 @@ virtual void check_and_handle_popframe(Register java_thread); virtual void check_and_handle_earlyret(Register java_thread); - void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true); + void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, Register args[], bool check_exceptions = true); // helpers for FPU flag access // tmp is a temporary register, if none is available use noreg @@ -773,16 +776,21 @@ void call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, bool check_exceptions = true); void call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true); - void call_VM(Register oop_result, Register last_java_sp, address entry_point, int number_of_arguments = 0, bool check_exceptions = true); + void call_VM(Register oop_result, Register last_java_sp, address entry_point, int number_of_arguments = 0, Register args[] = NULL, bool check_exceptions = true); void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, bool check_exceptions = true); void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, bool check_exceptions = true); void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true); - void call_VM_leaf(address entry_point, int number_of_arguments = 0); + void call_VM_leaf(address entry_point, int number_of_arguments = 0, Register args[] = NULL); void call_VM_leaf(address entry_point, Register arg_1); void call_VM_leaf(address entry_point, Register arg_1, Register arg_2); void call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3); + // Stack alignment + void MacroAssembler::fixup_call_align(int number_of_arguments); + void MacroAssembler::push_call_args(int number_of_arguments, Register args[]); + void MacroAssembler::discard_call_args(int number_of_arguments); + // last Java Frame (fills frame anchor) void set_last_Java_frame(Register thread, Register last_java_sp, Register last_java_fp, address last_java_pc); void reset_last_Java_frame(Register thread, bool clear_fp, bool clear_pc); Index: c1_LIRAssembler_i486.cpp =================================================================== RCS file: /home/Java/CVS/JDK2/javasrc_1_6_jrl/hotspot/src/cpu/i486/vm/c1_LIRAssembler_i486.cpp,v retrieving revision 1.1.1.5 diff -u -r1.1.1.5 c1_LIRAssembler_i486.cpp --- c1_LIRAssembler_i486.cpp 13 Aug 2007 20:54:12 -0000 1.1.1.5 +++ c1_LIRAssembler_i486.cpp 11 Nov 2007 02:15:23 -0000 @@ -2684,13 +2684,11 @@ assert(src == ecx && src_pos == edx, "mismatch in calling convention"); // pass arguments: may push as this is not a safepoint; SP must be fix at each safepoint - __ pushl(length); - __ pushl(dst_pos); - __ pushl(dst); - __ pushl(src_pos); - __ pushl(src); - address entry = CAST_FROM_FN_PTR(address, Runtime1::arraycopy); - __ call_VM_leaf(entry, 5); // removes pushed parameter from the stack + { + Register args[] = { src, src_pos, dst, dst_pos, length }; + address entry = CAST_FROM_FN_PTR(address, Runtime1::arraycopy); + __ call_VM_leaf(entry, 5, args); + } __ cmpl(eax, 0); __ jcc(Assembler::equal, *stub->continuation()); @@ -2803,6 +2801,7 @@ } #endif + // XXXDARWIN This code is not aligned. __ leal(tmp, Address(src, src_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); store_parameter(tmp, 0); __ leal(tmp, Address(dst, dst_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); Index: interp_masm_i486.cpp =================================================================== RCS file: /home/Java/CVS/JDK2/javasrc_1_6_jrl/hotspot/src/cpu/i486/vm/interp_masm_i486.cpp,v retrieving revision 1.1.1.2 diff -u -r1.1.1.2 interp_masm_i486.cpp --- interp_masm_i486.cpp 21 Jul 2006 17:22:22 -0000 1.1.1.2 +++ interp_masm_i486.cpp 11 Nov 2007 02:15:23 -0000 @@ -13,8 +13,9 @@ // Implementation of InterpreterMacroAssembler void InterpreterMacroAssembler::call_VM_leaf_base( - address entry_point, - int number_of_arguments + address entry_point, + int number_of_arguments, + Register args[] ) { // interpreter specific // @@ -31,7 +32,7 @@ } #endif // super call - MacroAssembler::call_VM_leaf_base(entry_point, number_of_arguments); + MacroAssembler::call_VM_leaf_base(entry_point, number_of_arguments, args); // interpreter specific #ifdef ASSERT { Label L; @@ -56,6 +57,7 @@ Register last_java_sp, address entry_point, int number_of_arguments, + Register args[], bool check_exceptions ) { #ifdef ASSERT @@ -75,7 +77,7 @@ assert(java_thread == noreg , "not expecting a precomputed java thread"); save_bcp(); // super call - MacroAssembler::call_VM_base(oop_result, java_thread, last_java_sp, entry_point, number_of_arguments, check_exceptions); + MacroAssembler::call_VM_base(oop_result, java_thread, last_java_sp, entry_point, number_of_arguments, args, check_exceptions); // interpreter specific restore_bcp(); restore_locals(); @@ -534,28 +536,25 @@ #endif // ASSERT void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point) { - MacroAssembler::call_VM_leaf_base(entry_point, 0); + MacroAssembler::call_VM_leaf_base(entry_point, 0, NULL); } void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register arg_1) { - pushl(arg_1); - MacroAssembler::call_VM_leaf_base(entry_point, 1); + Register args[] = { arg_1 }; + MacroAssembler::call_VM_leaf_base(entry_point, 1, args); } void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2) { - pushl(arg_2); - pushl(arg_1); - MacroAssembler::call_VM_leaf_base(entry_point, 2); + Register args[] = { arg_1, arg_2 }; + MacroAssembler::call_VM_leaf_base(entry_point, 2, args); } void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3) { - pushl(arg_3); - pushl(arg_2); - pushl(arg_1); - MacroAssembler::call_VM_leaf_base(entry_point, 3); + Register args[] = { arg_1, arg_2, arg_3 }; + MacroAssembler::call_VM_leaf_base(entry_point, 3, args); } Index: interp_masm_i486.hpp =================================================================== RCS file: /home/Java/CVS/JDK2/javasrc_1_6_jrl/hotspot/src/cpu/i486/vm/interp_masm_i486.hpp,v retrieving revision 1.1.1.2 diff -u -r1.1.1.2 interp_masm_i486.hpp --- interp_masm_i486.hpp 21 Jul 2006 17:22:22 -0000 1.1.1.2 +++ interp_masm_i486.hpp 11 Nov 2007 02:15:23 -0000 @@ -13,8 +13,9 @@ protected: // Interpreter specific version of call_VM_base virtual void call_VM_leaf_base( - address entry_point, - int number_of_arguments + address entry_point, + int number_of_arguments, + Register args[] ); virtual void call_VM_base( @@ -23,6 +24,7 @@ Register last_java_sp, address entry_point, int number_of_arguments, + Register args[], bool check_exceptions ); Index: interpreter_i486.cpp =================================================================== RCS file: /home/Java/CVS/JDK2/javasrc_1_6_jrl/hotspot/src/cpu/i486/vm/interpreter_i486.cpp,v retrieving revision 1.2 diff -u -r1.2 interpreter_i486.cpp --- interpreter_i486.cpp 28 Mar 2007 05:06:07 -0000 1.2 +++ interpreter_i486.cpp 11 Nov 2007 02:15:23 -0000 @@ -1160,9 +1160,10 @@ // preserved and correspond to the bcp/locals pointers. So we do a runtime call // by hand. // + __ fixup_call_align(1); __ pushl(thread); __ call(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans), relocInfo::runtime_call_type); - __ increment(esp, wordSize); + __ discard_call_args(1); __ get_thread(thread); __ bind(Continue); Index: stubGenerator_i486.cpp =================================================================== RCS file: /home/Java/CVS/JDK2/javasrc_1_6_jrl/hotspot/src/cpu/i486/vm/stubGenerator_i486.cpp,v retrieving revision 1.1.1.5 diff -u -r1.1.1.5 stubGenerator_i486.cpp --- stubGenerator_i486.cpp 31 Oct 2007 12:36:40 -0000 1.1.1.5 +++ stubGenerator_i486.cpp 11 Nov 2007 02:15:23 -0000 @@ -541,6 +541,7 @@ // push_FPU_state() resets the FP top of stack // Load original double into FP top of stack __ fld_d(Address(esp, saved_argument_off * wordSize)); + __ fixup_call_align(2); // Store double into stack as outgoing argument __ subl(esp, wordSize*2); __ fst_d(Address(esp)); @@ -549,6 +550,7 @@ __ empty_FPU_stack(); // Call the C code to massage the double. Result in EAX __ call_VM_leaf( fcn, 2 ); + __ discard_call_args(2); // Restore CPU & FPU state __ pop_FPU_state(); Index: templateTable_i486.cpp =================================================================== RCS file: /home/Java/CVS/JDK2/javasrc_1_6_jrl/hotspot/src/cpu/i486/vm/templateTable_i486.cpp,v retrieving revision 1.1.1.2 diff -u -r1.1.1.2 templateTable_i486.cpp --- templateTable_i486.cpp 21 Jul 2006 17:22:23 -0000 1.1.1.2 +++ templateTable_i486.cpp 11 Nov 2007 02:15:23 -0000 @@ -1149,26 +1149,32 @@ void TemplateTable::ldiv() { transition(ltos, ltos); __ pop_l(ebx, ecx); - __ pushl(ecx); __ pushl(ebx); - __ pushl(edx); __ pushl(eax); + // check if y = 0 __ orl(eax, edx); __ jcc(Assembler::zero, Interpreter::_throw_ArithmeticException_entry, relocInfo::none); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::ldiv)); - __ addl(esp, 4 * wordSize); // take off temporaries + + __ fixup_call_align(4); + __ pushl(ecx); __ pushl(ebx); + __ pushl(edx); __ pushl(eax); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::ldiv), 4); + __ discard_call_args(4); } void TemplateTable::lrem() { transition(ltos, ltos); __ pop_l(ebx, ecx); - __ pushl(ecx); __ pushl(ebx); - __ pushl(edx); __ pushl(eax); + // check if y = 0 __ orl(eax, edx); __ jcc(Assembler::zero, Interpreter::_throw_ArithmeticException_entry, relocInfo::none); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::lrem)); - __ addl(esp, 4 * wordSize); + + __ fixup_call_align(4); + __ pushl(ecx); __ pushl(ebx); + __ pushl(edx); __ pushl(eax); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::lrem), 4); + __ discard_call_args(4); } @@ -1407,29 +1413,37 @@ __ popl(ecx); break; case Bytecodes::_f2i: + __ fixup_call_align(1); __ pushl(ecx); // reserve space for argument __ fstp_s(at_esp()); // pass float argument on stack __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2i), 1); + __ discard_call_args(1); break; case Bytecodes::_f2l: + __ fixup_call_align(1); __ pushl(ecx); // reserve space for argument __ fstp_s(at_esp()); // pass float argument on stack __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2l), 1); + __ discard_call_args(1); break; case Bytecodes::_f2d: /* nothing to do */ break; case Bytecodes::_d2i: + __ fixup_call_align(2); __ pushl(ecx); // reserve space for argument __ pushl(ecx); __ fstp_d(at_esp()); // pass double argument on stack __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2i), 2); + __ discard_call_args(2); break; case Bytecodes::_d2l: + __ fixup_call_align(2); __ pushl(ecx); // reserve space for argument __ pushl(ecx); __ fstp_d(at_esp()); // pass double argument on stack __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2l), 2); + __ discard_call_args(2); break; case Bytecodes::_d2f: __ pushl(ecx); // reserve space for f2ieee()