Mercurial > hg > truffle
comparison src/cpu/x86/vm/x86_64.ad @ 4947:fd8114661503
7125136: SIGILL on linux amd64 in gc/ArrayJuggle/Juggle29
Summary: For C2 moved saving EBP after ESP adjustment. For C1 generated 5 byte nop instruction first if needed.
Reviewed-by: never, twisti, azeemj
author | kvn |
---|---|
date | Wed, 15 Feb 2012 21:37:49 -0800 |
parents | e9a5e0a812c8 |
children | 9b8ce46870df |
comparison
equal
deleted
inserted
replaced
4946:69333a2fbae2 | 4947:fd8114661503 |
---|---|
851 #endif | 851 #endif |
852 | 852 |
853 | 853 |
854 //============================================================================= | 854 //============================================================================= |
855 #ifndef PRODUCT | 855 #ifndef PRODUCT |
856 void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const | 856 void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const { |
857 { | |
858 Compile* C = ra_->C; | 857 Compile* C = ra_->C; |
859 | 858 |
860 int framesize = C->frame_slots() << LogBytesPerInt; | 859 int framesize = C->frame_slots() << LogBytesPerInt; |
861 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); | 860 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); |
862 // Remove wordSize for return adr already pushed | 861 // Remove wordSize for return addr which is already pushed. |
863 // and another for the RBP we are going to save | 862 framesize -= wordSize; |
864 framesize -= 2*wordSize; | 863 |
865 bool need_nop = true; | |
866 | |
867 // Calls to C2R adapters often do not accept exceptional returns. | |
868 // We require that their callers must bang for them. But be | |
869 // careful, because some VM calls (such as call site linkage) can | |
870 // use several kilobytes of stack. But the stack safety zone should | |
871 // account for that. See bugs 4446381, 4468289, 4497237. | |
872 if (C->need_stack_bang(framesize)) { | 864 if (C->need_stack_bang(framesize)) { |
873 st->print_cr("# stack bang"); st->print("\t"); | 865 framesize -= wordSize; |
874 need_nop = false; | 866 st->print("# stack bang"); |
867 st->print("\n\t"); | |
868 st->print("pushq rbp\t# Save rbp"); | |
869 if (framesize) { | |
870 st->print("\n\t"); | |
871 st->print("subq rsp, #%d\t# Create frame",framesize); | |
872 } | |
873 } else { | |
874 st->print("subq rsp, #%d\t# Create frame",framesize); | |
875 st->print("\n\t"); | |
876 framesize -= wordSize; | |
877 st->print("movq [rsp + #%d], rbp\t# Save rbp",framesize); | |
875 } | 878 } |
876 st->print_cr("pushq rbp"); st->print("\t"); | |
877 | 879 |
878 if (VerifyStackAtCalls) { | 880 if (VerifyStackAtCalls) { |
879 // Majik cookie to verify stack depth | 881 st->print("\n\t"); |
880 st->print_cr("pushq 0xffffffffbadb100d" | 882 framesize -= wordSize; |
881 "\t# Majik cookie for stack depth check"); | 883 st->print("movq [rsp + #%d], 0xbadb100d\t# Majik cookie for stack depth check",framesize); |
882 st->print("\t"); | 884 #ifdef ASSERT |
883 framesize -= wordSize; // Remove 2 for cookie | 885 st->print("\n\t"); |
884 need_nop = false; | 886 st->print("# stack alignment check"); |
887 #endif | |
885 } | 888 } |
886 | 889 st->cr(); |
887 if (framesize) { | |
888 st->print("subq rsp, #%d\t# Create frame", framesize); | |
889 if (framesize < 0x80 && need_nop) { | |
890 st->print("\n\tnop\t# nop for patch_verified_entry"); | |
891 } | |
892 } | |
893 } | 890 } |
894 #endif | 891 #endif |
895 | 892 |
896 void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const | 893 void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { |
897 { | |
898 Compile* C = ra_->C; | 894 Compile* C = ra_->C; |
899 | 895 MacroAssembler _masm(&cbuf); |
900 // WARNING: Initial instruction MUST be 5 bytes or longer so that | |
901 // NativeJump::patch_verified_entry will be able to patch out the entry | |
902 // code safely. The fldcw is ok at 6 bytes, the push to verify stack | |
903 // depth is ok at 5 bytes, the frame allocation can be either 3 or | |
904 // 6 bytes. So if we don't do the fldcw or the push then we must | |
905 // use the 6 byte frame allocation even if we have no frame. :-( | |
906 // If method sets FPU control word do it now | |
907 | 896 |
908 int framesize = C->frame_slots() << LogBytesPerInt; | 897 int framesize = C->frame_slots() << LogBytesPerInt; |
909 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); | 898 |
910 // Remove wordSize for return adr already pushed | 899 __ verified_entry(framesize, C->need_stack_bang(framesize), false); |
911 // and another for the RBP we are going to save | |
912 framesize -= 2*wordSize; | |
913 bool need_nop = true; | |
914 | |
915 // Calls to C2R adapters often do not accept exceptional returns. | |
916 // We require that their callers must bang for them. But be | |
917 // careful, because some VM calls (such as call site linkage) can | |
918 // use several kilobytes of stack. But the stack safety zone should | |
919 // account for that. See bugs 4446381, 4468289, 4497237. | |
920 if (C->need_stack_bang(framesize)) { | |
921 MacroAssembler masm(&cbuf); | |
922 masm.generate_stack_overflow_check(framesize); | |
923 need_nop = false; | |
924 } | |
925 | |
926 // We always push rbp so that on return to interpreter rbp will be | |
927 // restored correctly and we can correct the stack. | |
928 emit_opcode(cbuf, 0x50 | RBP_enc); | |
929 | |
930 if (VerifyStackAtCalls) { | |
931 // Majik cookie to verify stack depth | |
932 emit_opcode(cbuf, 0x68); // pushq (sign-extended) 0xbadb100d | |
933 emit_d32(cbuf, 0xbadb100d); | |
934 framesize -= wordSize; // Remove 2 for cookie | |
935 need_nop = false; | |
936 } | |
937 | |
938 if (framesize) { | |
939 emit_opcode(cbuf, Assembler::REX_W); | |
940 if (framesize < 0x80) { | |
941 emit_opcode(cbuf, 0x83); // sub SP,#framesize | |
942 emit_rm(cbuf, 0x3, 0x05, RSP_enc); | |
943 emit_d8(cbuf, framesize); | |
944 if (need_nop) { | |
945 emit_opcode(cbuf, 0x90); // nop | |
946 } | |
947 } else { | |
948 emit_opcode(cbuf, 0x81); // sub SP,#framesize | |
949 emit_rm(cbuf, 0x3, 0x05, RSP_enc); | |
950 emit_d32(cbuf, framesize); | |
951 } | |
952 } | |
953 | 900 |
954 C->set_frame_complete(cbuf.insts_size()); | 901 C->set_frame_complete(cbuf.insts_size()); |
955 | |
956 #ifdef ASSERT | |
957 if (VerifyStackAtCalls) { | |
958 Label L; | |
959 MacroAssembler masm(&cbuf); | |
960 masm.push(rax); | |
961 masm.mov(rax, rsp); | |
962 masm.andptr(rax, StackAlignmentInBytes-1); | |
963 masm.cmpptr(rax, StackAlignmentInBytes-wordSize); | |
964 masm.pop(rax); | |
965 masm.jcc(Assembler::equal, L); | |
966 masm.stop("Stack is not properly aligned!"); | |
967 masm.bind(L); | |
968 } | |
969 #endif | |
970 | 902 |
971 if (C->has_mach_constant_base_node()) { | 903 if (C->has_mach_constant_base_node()) { |
972 // NOTE: We set the table base offset here because users might be | 904 // NOTE: We set the table base offset here because users might be |
973 // emitted before MachConstantBaseNode. | 905 // emitted before MachConstantBaseNode. |
974 Compile::ConstantTable& constant_table = C->constant_table(); | 906 Compile::ConstantTable& constant_table = C->constant_table(); |