Mercurial > hg > truffle
comparison src/cpu/x86/vm/methodHandles_x86.cpp @ 1135:e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
Summary: During the work for 6829187 we have fixed a number of basic bugs which are logically grouped with 6815692 and 6858164 but which must be reviewed and pushed separately.
Reviewed-by: kvn, never
author | twisti |
---|---|
date | Mon, 04 Jan 2010 18:38:08 +0100 |
parents | aa62b9388fce |
children | 855c5171834c |
comparison
equal
deleted
inserted
replaced
1134:0910903272e5 | 1135:e66fd840cb6b |
---|---|
63 static void verify_argslot(MacroAssembler* _masm, Register rax_argslot, | 63 static void verify_argslot(MacroAssembler* _masm, Register rax_argslot, |
64 const char* error_message) { | 64 const char* error_message) { |
65 // Verify that argslot lies within (rsp, rbp]. | 65 // Verify that argslot lies within (rsp, rbp]. |
66 Label L_ok, L_bad; | 66 Label L_ok, L_bad; |
67 __ cmpptr(rax_argslot, rbp); | 67 __ cmpptr(rax_argslot, rbp); |
68 __ jcc(Assembler::above, L_bad); | 68 __ jccb(Assembler::above, L_bad); |
69 __ cmpptr(rsp, rax_argslot); | 69 __ cmpptr(rsp, rax_argslot); |
70 __ jcc(Assembler::below, L_ok); | 70 __ jccb(Assembler::below, L_ok); |
71 __ bind(L_bad); | 71 __ bind(L_bad); |
72 __ stop(error_message); | 72 __ stop(error_message); |
73 __ bind(L_ok); | 73 __ bind(L_ok); |
74 } | 74 } |
75 #endif | 75 #endif |
134 #ifdef ASSERT | 134 #ifdef ASSERT |
135 verify_argslot(_masm, rax_argslot, "insertion point must fall within current frame"); | 135 verify_argslot(_masm, rax_argslot, "insertion point must fall within current frame"); |
136 if (arg_slots.is_register()) { | 136 if (arg_slots.is_register()) { |
137 Label L_ok, L_bad; | 137 Label L_ok, L_bad; |
138 __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD); | 138 __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD); |
139 __ jcc(Assembler::greater, L_bad); | 139 __ jccb(Assembler::greater, L_bad); |
140 __ testl(arg_slots.as_register(), -stack_move_unit() - 1); | 140 __ testl(arg_slots.as_register(), -stack_move_unit() - 1); |
141 __ jcc(Assembler::zero, L_ok); | 141 __ jccb(Assembler::zero, L_ok); |
142 __ bind(L_bad); | 142 __ bind(L_bad); |
143 __ stop("assert arg_slots <= 0 and clear low bits"); | 143 __ stop("assert arg_slots <= 0 and clear low bits"); |
144 __ bind(L_ok); | 144 __ bind(L_ok); |
145 } else { | 145 } else { |
146 assert(arg_slots.as_constant() <= 0, ""); | 146 assert(arg_slots.as_constant() <= 0, ""); |
171 // pull one word down each time through the loop | 171 // pull one word down each time through the loop |
172 __ movptr(rbx_temp, Address(rdx_temp, 0)); | 172 __ movptr(rbx_temp, Address(rdx_temp, 0)); |
173 __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp); | 173 __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp); |
174 __ addptr(rdx_temp, wordSize); | 174 __ addptr(rdx_temp, wordSize); |
175 __ cmpptr(rdx_temp, rax_argslot); | 175 __ cmpptr(rdx_temp, rax_argslot); |
176 __ jcc(Assembler::less, loop); | 176 __ jccb(Assembler::less, loop); |
177 } | 177 } |
178 | 178 |
179 // Now move the argslot down, to point to the opened-up space. | 179 // Now move the argslot down, to point to the opened-up space. |
180 __ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr)); | 180 __ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr)); |
181 | 181 |
209 { | 209 { |
210 // Verify that [argslot..argslot+size) lies within (rsp, rbp). | 210 // Verify that [argslot..argslot+size) lies within (rsp, rbp). |
211 Label L_ok, L_bad; | 211 Label L_ok, L_bad; |
212 __ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr)); | 212 __ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr)); |
213 __ cmpptr(rbx_temp, rbp); | 213 __ cmpptr(rbx_temp, rbp); |
214 __ jcc(Assembler::above, L_bad); | 214 __ jccb(Assembler::above, L_bad); |
215 __ cmpptr(rsp, rax_argslot); | 215 __ cmpptr(rsp, rax_argslot); |
216 __ jcc(Assembler::below, L_ok); | 216 __ jccb(Assembler::below, L_ok); |
217 __ bind(L_bad); | 217 __ bind(L_bad); |
218 __ stop("deleted argument(s) must fall within current frame"); | 218 __ stop("deleted argument(s) must fall within current frame"); |
219 __ bind(L_ok); | 219 __ bind(L_ok); |
220 } | 220 } |
221 if (arg_slots.is_register()) { | 221 if (arg_slots.is_register()) { |
222 Label L_ok, L_bad; | 222 Label L_ok, L_bad; |
223 __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD); | 223 __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD); |
224 __ jcc(Assembler::less, L_bad); | 224 __ jccb(Assembler::less, L_bad); |
225 __ testl(arg_slots.as_register(), -stack_move_unit() - 1); | 225 __ testl(arg_slots.as_register(), -stack_move_unit() - 1); |
226 __ jcc(Assembler::zero, L_ok); | 226 __ jccb(Assembler::zero, L_ok); |
227 __ bind(L_bad); | 227 __ bind(L_bad); |
228 __ stop("assert arg_slots >= 0 and clear low bits"); | 228 __ stop("assert arg_slots >= 0 and clear low bits"); |
229 __ bind(L_ok); | 229 __ bind(L_ok); |
230 } else { | 230 } else { |
231 assert(arg_slots.as_constant() >= 0, ""); | 231 assert(arg_slots.as_constant() >= 0, ""); |
256 // pull one word up each time through the loop | 256 // pull one word up each time through the loop |
257 __ movptr(rbx_temp, Address(rdx_temp, 0)); | 257 __ movptr(rbx_temp, Address(rdx_temp, 0)); |
258 __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp); | 258 __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp); |
259 __ addptr(rdx_temp, -wordSize); | 259 __ addptr(rdx_temp, -wordSize); |
260 __ cmpptr(rdx_temp, rsp); | 260 __ cmpptr(rdx_temp, rsp); |
261 __ jcc(Assembler::greaterEqual, loop); | 261 __ jccb(Assembler::greaterEqual, loop); |
262 } | 262 } |
263 | 263 |
264 // Now move the argslot up, to point to the just-copied block. | 264 // Now move the argslot up, to point to the just-copied block. |
265 __ lea(rsp, Address(rsp, arg_slots, Address::times_ptr)); | 265 __ lea(rsp, Address(rsp, arg_slots, Address::times_ptr)); |
266 // And adjust the argslot address to point at the deletion point. | 266 // And adjust the argslot address to point at the deletion point. |
382 Register rbx_method = rbx_temp; | 382 Register rbx_method = rbx_temp; |
383 Label no_method; | 383 Label no_method; |
384 // FIXME: fill in _raise_exception_method with a suitable sun.dyn method | 384 // FIXME: fill in _raise_exception_method with a suitable sun.dyn method |
385 __ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method)); | 385 __ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method)); |
386 __ testptr(rbx_method, rbx_method); | 386 __ testptr(rbx_method, rbx_method); |
387 __ jcc(Assembler::zero, no_method); | 387 __ jccb(Assembler::zero, no_method); |
388 int jobject_oop_offset = 0; | 388 int jobject_oop_offset = 0; |
389 __ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject | 389 __ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject |
390 __ testptr(rbx_method, rbx_method); | 390 __ testptr(rbx_method, rbx_method); |
391 __ jcc(Assembler::zero, no_method); | 391 __ jccb(Assembler::zero, no_method); |
392 __ verify_oop(rbx_method); | 392 __ verify_oop(rbx_method); |
393 __ push(rdi_pc); // and restore caller PC | 393 __ push(rdi_pc); // and restore caller PC |
394 __ jmp(rbx_method_fie); | 394 __ jmp(rbx_method_fie); |
395 | 395 |
396 // If we get here, the Java runtime did not do its job of creating the exception. | 396 // If we get here, the Java runtime did not do its job of creating the exception. |
533 __ movptr(rbx_temp, rcx_bmh_argument); | 533 __ movptr(rbx_temp, rcx_bmh_argument); |
534 Address prim_value_addr(rbx_temp, java_lang_boxing_object::value_offset_in_bytes(arg_type)); | 534 Address prim_value_addr(rbx_temp, java_lang_boxing_object::value_offset_in_bytes(arg_type)); |
535 if (arg_type == T_OBJECT) { | 535 if (arg_type == T_OBJECT) { |
536 __ movptr(Address(rax_argslot, 0), rbx_temp); | 536 __ movptr(Address(rax_argslot, 0), rbx_temp); |
537 } else { | 537 } else { |
538 __ load_sized_value(rbx_temp, prim_value_addr, | 538 __ load_sized_value(rdx_temp, prim_value_addr, |
539 type2aelembytes(arg_type), is_signed_subword_type(arg_type)); | 539 type2aelembytes(arg_type), is_signed_subword_type(arg_type)); |
540 __ movptr(Address(rax_argslot, 0), rbx_temp); | 540 __ movptr(Address(rax_argslot, 0), rdx_temp); |
541 #ifndef _LP64 | 541 #ifndef _LP64 |
542 if (arg_slots == 2) { | 542 if (arg_slots == 2) { |
543 __ movl(rbx_temp, prim_value_addr.plus_disp(wordSize)); | 543 __ movl(rdx_temp, prim_value_addr.plus_disp(wordSize)); |
544 __ movl(Address(rax_argslot, Interpreter::stackElementSize()), rbx_temp); | 544 __ movl(Address(rax_argslot, Interpreter::stackElementSize()), rdx_temp); |
545 } | 545 } |
546 #endif //_LP64 | 546 #endif //_LP64 |
547 break; | |
548 } | 547 } |
549 | 548 |
550 if (direct_to_method) { | 549 if (direct_to_method) { |
551 Register rbx_method = rbx_temp; | 550 Register rbx_method = rbx_temp; |
552 __ movptr(rbx_method, rcx_mh_vmtarget); | 551 __ movptr(rbx_method, rcx_mh_vmtarget); |
584 __ movptr(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes())); | 583 __ movptr(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes())); |
585 | 584 |
586 Label done; | 585 Label done; |
587 __ movptr(rdx_temp, vmarg); | 586 __ movptr(rdx_temp, vmarg); |
588 __ testl(rdx_temp, rdx_temp); | 587 __ testl(rdx_temp, rdx_temp); |
589 __ jcc(Assembler::zero, done); // no cast if null | 588 __ jccb(Assembler::zero, done); // no cast if null |
590 __ load_klass(rdx_temp, rdx_temp); | 589 __ load_klass(rdx_temp, rdx_temp); |
591 | 590 |
592 // live at this point: | 591 // live at this point: |
593 // - rbx_klass: klass required by the target method | 592 // - rbx_klass: klass required by the target method |
594 // - rdx_temp: argument klass to test | 593 // - rdx_temp: argument klass to test |
675 // get the new MH: | 674 // get the new MH: |
676 __ movptr(rcx_recv, rcx_mh_vmtarget); | 675 __ movptr(rcx_recv, rcx_mh_vmtarget); |
677 // (now we are done with the old MH) | 676 // (now we are done with the old MH) |
678 | 677 |
679 // original 32-bit vmdata word must be of this form: | 678 // original 32-bit vmdata word must be of this form: |
680 // | MBZ:16 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 | | 679 // | MBZ:6 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 | |
681 __ xchgl(rcx, rbx_vminfo); // free rcx for shifts | 680 __ xchgptr(rcx, rbx_vminfo); // free rcx for shifts |
682 __ shll(rdx_temp /*, rcx*/); | 681 __ shll(rdx_temp /*, rcx*/); |
683 Label zero_extend, done; | 682 Label zero_extend, done; |
684 __ testl(rcx, CONV_VMINFO_SIGN_FLAG); | 683 __ testl(rcx, CONV_VMINFO_SIGN_FLAG); |
685 __ jcc(Assembler::zero, zero_extend); | 684 __ jccb(Assembler::zero, zero_extend); |
686 | 685 |
687 // this path is taken for int->byte, int->short | 686 // this path is taken for int->byte, int->short |
688 __ sarl(rdx_temp /*, rcx*/); | 687 __ sarl(rdx_temp /*, rcx*/); |
689 __ jmp(done); | 688 __ jmpb(done); |
690 | 689 |
691 __ bind(zero_extend); | 690 __ bind(zero_extend); |
692 // this is taken for int->char | 691 // this is taken for int->char |
693 __ shrl(rdx_temp /*, rcx*/); | 692 __ shrl(rdx_temp /*, rcx*/); |
694 | 693 |
695 __ bind(done); | 694 __ bind(done); |
696 __ movptr(vmarg, rdx_temp); | 695 __ movl(vmarg, rdx_temp); |
697 __ xchgl(rcx, rbx_vminfo); // restore rcx_recv | 696 __ xchgptr(rcx, rbx_vminfo); // restore rcx_recv |
698 | 697 |
699 __ jump_to_method_handle_entry(rcx_recv, rdx_temp); | 698 __ jump_to_method_handle_entry(rcx_recv, rdx_temp); |
700 } | 699 } |
701 break; | 700 break; |
702 | 701 |
861 #ifdef ASSERT | 860 #ifdef ASSERT |
862 { | 861 { |
863 // Verify that argslot > destslot, by at least swap_bytes. | 862 // Verify that argslot > destslot, by at least swap_bytes. |
864 Label L_ok; | 863 Label L_ok; |
865 __ cmpptr(rax_argslot, rbx_destslot); | 864 __ cmpptr(rax_argslot, rbx_destslot); |
866 __ jcc(Assembler::aboveEqual, L_ok); | 865 __ jccb(Assembler::aboveEqual, L_ok); |
867 __ stop("source must be above destination (upward rotation)"); | 866 __ stop("source must be above destination (upward rotation)"); |
868 __ bind(L_ok); | 867 __ bind(L_ok); |
869 } | 868 } |
870 #endif | 869 #endif |
871 // work argslot down to destslot, copying contiguous data upwards | 870 // work argslot down to destslot, copying contiguous data upwards |
877 __ bind(loop); | 876 __ bind(loop); |
878 __ movptr(rdx_temp, Address(rax_argslot, 0)); | 877 __ movptr(rdx_temp, Address(rax_argslot, 0)); |
879 __ movptr(Address(rax_argslot, swap_bytes), rdx_temp); | 878 __ movptr(Address(rax_argslot, swap_bytes), rdx_temp); |
880 __ addptr(rax_argslot, -wordSize); | 879 __ addptr(rax_argslot, -wordSize); |
881 __ cmpptr(rax_argslot, rbx_destslot); | 880 __ cmpptr(rax_argslot, rbx_destslot); |
882 __ jcc(Assembler::aboveEqual, loop); | 881 __ jccb(Assembler::aboveEqual, loop); |
883 } else { | 882 } else { |
884 __ addptr(rax_argslot, swap_bytes); | 883 __ addptr(rax_argslot, swap_bytes); |
885 #ifdef ASSERT | 884 #ifdef ASSERT |
886 { | 885 { |
887 // Verify that argslot < destslot, by at least swap_bytes. | 886 // Verify that argslot < destslot, by at least swap_bytes. |
888 Label L_ok; | 887 Label L_ok; |
889 __ cmpptr(rax_argslot, rbx_destslot); | 888 __ cmpptr(rax_argslot, rbx_destslot); |
890 __ jcc(Assembler::belowEqual, L_ok); | 889 __ jccb(Assembler::belowEqual, L_ok); |
891 __ stop("source must be below destination (downward rotation)"); | 890 __ stop("source must be below destination (downward rotation)"); |
892 __ bind(L_ok); | 891 __ bind(L_ok); |
893 } | 892 } |
894 #endif | 893 #endif |
895 // work argslot up to destslot, copying contiguous data downwards | 894 // work argslot up to destslot, copying contiguous data downwards |
901 __ bind(loop); | 900 __ bind(loop); |
902 __ movptr(rdx_temp, Address(rax_argslot, 0)); | 901 __ movptr(rdx_temp, Address(rax_argslot, 0)); |
903 __ movptr(Address(rax_argslot, -swap_bytes), rdx_temp); | 902 __ movptr(Address(rax_argslot, -swap_bytes), rdx_temp); |
904 __ addptr(rax_argslot, wordSize); | 903 __ addptr(rax_argslot, wordSize); |
905 __ cmpptr(rax_argslot, rbx_destslot); | 904 __ cmpptr(rax_argslot, rbx_destslot); |
906 __ jcc(Assembler::belowEqual, loop); | 905 __ jccb(Assembler::belowEqual, loop); |
907 } | 906 } |
908 | 907 |
909 // pop the original first chunk into the destination slot, now free | 908 // pop the original first chunk into the destination slot, now free |
910 for (int i = 0; i < swap_bytes; i += wordSize) { | 909 for (int i = 0; i < swap_bytes; i += wordSize) { |
911 __ pop(rdx_temp); | 910 __ pop(rdx_temp); |
967 __ movptr(rdi, Address(rax_argslot, 0)); | 966 __ movptr(rdi, Address(rax_argslot, 0)); |
968 __ movptr(Address(rdx_newarg, 0), rdi); | 967 __ movptr(Address(rdx_newarg, 0), rdi); |
969 __ addptr(rax_argslot, wordSize); | 968 __ addptr(rax_argslot, wordSize); |
970 __ addptr(rdx_newarg, wordSize); | 969 __ addptr(rdx_newarg, wordSize); |
971 __ cmpptr(rdx_newarg, rbx_oldarg); | 970 __ cmpptr(rdx_newarg, rbx_oldarg); |
972 __ jcc(Assembler::less, loop); | 971 __ jccb(Assembler::less, loop); |
973 | 972 |
974 __ pop(rdi); // restore temp | 973 __ pop(rdi); // restore temp |
975 | 974 |
976 __ movptr(rcx_recv, rcx_mh_vmtarget); | 975 __ movptr(rcx_recv, rcx_mh_vmtarget); |
977 __ jump_to_method_handle_entry(rcx_recv, rdx_temp); | 976 __ jump_to_method_handle_entry(rcx_recv, rdx_temp); |
1119 __ movptr(Address(rax_argslot, tag_offset), | 1118 __ movptr(Address(rax_argslot, tag_offset), |
1120 frame::tag_for_basic_type(elem_type)); | 1119 frame::tag_for_basic_type(elem_type)); |
1121 } | 1120 } |
1122 __ addptr(rax_argslot, Interpreter::stackElementSize()); | 1121 __ addptr(rax_argslot, Interpreter::stackElementSize()); |
1123 __ cmpptr(rax_argslot, rdx_argslot_limit); | 1122 __ cmpptr(rax_argslot, rdx_argslot_limit); |
1124 __ jcc(Assembler::less, loop); | 1123 __ jccb(Assembler::less, loop); |
1125 } else if (length_constant == 0) { | 1124 } else if (length_constant == 0) { |
1126 __ bind(skip_array_check); | 1125 __ bind(skip_array_check); |
1127 // nothing to copy | 1126 // nothing to copy |
1128 } else { | 1127 } else { |
1129 int elem_offset = elem0_offset; | 1128 int elem_offset = elem0_offset; |