Mercurial > hg > truffle
comparison src/cpu/x86/vm/templateTable_x86_64.cpp @ 113:ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
Summary: Compressed oops in instances, arrays, and headers. Code contributors are coleenp, phh, never, swamyv
Reviewed-by: jmasa, kamg, acorn, tbell, kvn, rasbold
author | coleenp |
---|---|
date | Sun, 13 Apr 2008 17:43:42 -0400 |
parents | a61af66fc99e |
children | feeb96a45707 37f87013dfd8 |
comparison
equal
deleted
inserted
replaced
110:a49a647afe9a | 113:ba764ed4b6f2 |
---|---|
555 transition(itos, atos); | 555 transition(itos, atos); |
556 __ pop_ptr(rdx); | 556 __ pop_ptr(rdx); |
557 // eax: index | 557 // eax: index |
558 // rdx: array | 558 // rdx: array |
559 index_check(rdx, rax); // kills rbx | 559 index_check(rdx, rax); // kills rbx |
560 __ movq(rax, Address(rdx, rax, | 560 __ load_heap_oop(rax, Address(rdx, rax, |
561 Address::times_8, | 561 UseCompressedOops ? Address::times_4 : Address::times_8, |
562 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); | 562 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); |
563 } | 563 } |
564 | 564 |
565 void TemplateTable::baload() { | 565 void TemplateTable::baload() { |
566 transition(itos, itos); | 566 transition(itos, itos); |
868 // do array store check - check for NULL value first | 868 // do array store check - check for NULL value first |
869 __ testq(rax, rax); | 869 __ testq(rax, rax); |
870 __ jcc(Assembler::zero, is_null); | 870 __ jcc(Assembler::zero, is_null); |
871 | 871 |
872 // Move subklass into rbx | 872 // Move subklass into rbx |
873 __ movq(rbx, Address(rax, oopDesc::klass_offset_in_bytes())); | 873 __ load_klass(rbx, rax); |
874 // Move superklass into rax | 874 // Move superklass into rax |
875 __ movq(rax, Address(rdx, oopDesc::klass_offset_in_bytes())); | 875 __ load_klass(rax, rdx); |
876 __ movq(rax, Address(rax, | 876 __ movq(rax, Address(rax, |
877 sizeof(oopDesc) + | 877 sizeof(oopDesc) + |
878 objArrayKlass::element_klass_offset_in_bytes())); | 878 objArrayKlass::element_klass_offset_in_bytes())); |
879 // Compress array + index*8 + 12 into a single register. Frees rcx. | 879 // Compress array + index*oopSize + 12 into a single register. Frees rcx. |
880 __ leaq(rdx, Address(rdx, rcx, | 880 __ leaq(rdx, Address(rdx, rcx, |
881 Address::times_8, | 881 UseCompressedOops ? Address::times_4 : Address::times_8, |
882 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); | 882 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); |
883 | 883 |
884 // Generate subtype check. Blows rcx, rdi | 884 // Generate subtype check. Blows rcx, rdi |
885 // Superklass in rax. Subklass in rbx. | 885 // Superklass in rax. Subklass in rbx. |
886 __ gen_subtype_check(rbx, ok_is_subtype); | 886 __ gen_subtype_check(rbx, ok_is_subtype); |
890 __ jump(ExternalAddress(Interpreter::_throw_ArrayStoreException_entry)); | 890 __ jump(ExternalAddress(Interpreter::_throw_ArrayStoreException_entry)); |
891 | 891 |
892 // Come here on success | 892 // Come here on success |
893 __ bind(ok_is_subtype); | 893 __ bind(ok_is_subtype); |
894 __ movq(rax, at_tos()); // Value | 894 __ movq(rax, at_tos()); // Value |
895 __ movq(Address(rdx, 0), rax); | 895 __ store_heap_oop(Address(rdx, 0), rax); |
896 __ store_check(rdx); | 896 __ store_check(rdx); |
897 __ jmp(done); | 897 __ jmp(done); |
898 | 898 |
899 // Have a NULL in rax, rdx=array, ecx=index. Store NULL at ary[idx] | 899 // Have a NULL in rax, rdx=array, ecx=index. Store NULL at ary[idx] |
900 __ bind(is_null); | 900 __ bind(is_null); |
901 __ profile_null_seen(rbx); | 901 __ profile_null_seen(rbx); |
902 __ movq(Address(rdx, rcx, | 902 __ store_heap_oop(Address(rdx, rcx, |
903 Address::times_8, | 903 UseCompressedOops ? Address::times_4 : Address::times_8, |
904 arrayOopDesc::base_offset_in_bytes(T_OBJECT)), | 904 arrayOopDesc::base_offset_in_bytes(T_OBJECT)), |
905 rax); | 905 rax); |
906 | 906 |
907 // Pop stack arguments | 907 // Pop stack arguments |
908 __ bind(done); | 908 __ bind(done); |
909 __ addq(rsp, 3 * Interpreter::stackElementSize()); | 909 __ addq(rsp, 3 * Interpreter::stackElementSize()); |
910 } | 910 } |
1932 "inconsistent calls_vm information"); // call in remove_activation | 1932 "inconsistent calls_vm information"); // call in remove_activation |
1933 | 1933 |
1934 if (_desc->bytecode() == Bytecodes::_return_register_finalizer) { | 1934 if (_desc->bytecode() == Bytecodes::_return_register_finalizer) { |
1935 assert(state == vtos, "only valid state"); | 1935 assert(state == vtos, "only valid state"); |
1936 __ movq(c_rarg1, aaddress(0)); | 1936 __ movq(c_rarg1, aaddress(0)); |
1937 __ movq(rdi, Address(c_rarg1, oopDesc::klass_offset_in_bytes())); | 1937 __ load_klass(rdi, c_rarg1); |
1938 __ movl(rdi, Address(rdi, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc))); | 1938 __ movl(rdi, Address(rdi, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc))); |
1939 __ testl(rdi, JVM_ACC_HAS_FINALIZER); | 1939 __ testl(rdi, JVM_ACC_HAS_FINALIZER); |
1940 Label skip_register_finalizer; | 1940 Label skip_register_finalizer; |
1941 __ jcc(Assembler::zero, skip_register_finalizer); | 1941 __ jcc(Assembler::zero, skip_register_finalizer); |
1942 | 1942 |
2182 | 2182 |
2183 __ bind(notByte); | 2183 __ bind(notByte); |
2184 __ cmpl(flags, atos); | 2184 __ cmpl(flags, atos); |
2185 __ jcc(Assembler::notEqual, notObj); | 2185 __ jcc(Assembler::notEqual, notObj); |
2186 // atos | 2186 // atos |
2187 __ movq(rax, field); | 2187 __ load_heap_oop(rax, field); |
2188 __ push(atos); | 2188 __ push(atos); |
2189 if (!is_static) { | 2189 if (!is_static) { |
2190 patch_bytecode(Bytecodes::_fast_agetfield, bc, rbx); | 2190 patch_bytecode(Bytecodes::_fast_agetfield, bc, rbx); |
2191 } | 2191 } |
2192 __ jmp(Done); | 2192 __ jmp(Done); |
2392 __ cmpl(flags, atos); | 2392 __ cmpl(flags, atos); |
2393 __ jcc(Assembler::notEqual, notObj); | 2393 __ jcc(Assembler::notEqual, notObj); |
2394 // atos | 2394 // atos |
2395 __ pop(atos); | 2395 __ pop(atos); |
2396 if (!is_static) pop_and_check_object(obj); | 2396 if (!is_static) pop_and_check_object(obj); |
2397 __ movq(field, rax); | 2397 __ store_heap_oop(field, rax); |
2398 __ store_check(obj, field); // Need to mark card | 2398 __ store_check(obj, field); // Need to mark card |
2399 if (!is_static) { | 2399 if (!is_static) { |
2400 patch_bytecode(Bytecodes::_fast_aputfield, bc, rbx); | 2400 patch_bytecode(Bytecodes::_fast_aputfield, bc, rbx); |
2401 } | 2401 } |
2402 __ jmp(Done); | 2402 __ jmp(Done); |
2513 __ subq(rsp, sizeof(jvalue)); // add space for a jvalue object | 2513 __ subq(rsp, sizeof(jvalue)); // add space for a jvalue object |
2514 __ movq(c_rarg3, rsp); | 2514 __ movq(c_rarg3, rsp); |
2515 const Address field(c_rarg3, 0); | 2515 const Address field(c_rarg3, 0); |
2516 | 2516 |
2517 switch (bytecode()) { // load values into the jvalue object | 2517 switch (bytecode()) { // load values into the jvalue object |
2518 case Bytecodes::_fast_aputfield: // fall through | 2518 case Bytecodes::_fast_aputfield: __ movq(field, rax); break; |
2519 case Bytecodes::_fast_lputfield: __ movq(field, rax); break; | 2519 case Bytecodes::_fast_lputfield: __ movq(field, rax); break; |
2520 case Bytecodes::_fast_iputfield: __ movl(field, rax); break; | 2520 case Bytecodes::_fast_iputfield: __ movl(field, rax); break; |
2521 case Bytecodes::_fast_bputfield: __ movb(field, rax); break; | 2521 case Bytecodes::_fast_bputfield: __ movb(field, rax); break; |
2522 case Bytecodes::_fast_sputfield: // fall through | 2522 case Bytecodes::_fast_sputfield: // fall through |
2523 case Bytecodes::_fast_cputfield: __ movw(field, rax); break; | 2523 case Bytecodes::_fast_cputfield: __ movw(field, rax); break; |
2580 const Address field(rcx, rbx, Address::times_1); | 2580 const Address field(rcx, rbx, Address::times_1); |
2581 | 2581 |
2582 // access field | 2582 // access field |
2583 switch (bytecode()) { | 2583 switch (bytecode()) { |
2584 case Bytecodes::_fast_aputfield: | 2584 case Bytecodes::_fast_aputfield: |
2585 __ movq(field, rax); | 2585 __ store_heap_oop(field, rax); |
2586 __ store_check(rcx, field); | 2586 __ store_check(rcx, field); |
2587 break; | 2587 break; |
2588 case Bytecodes::_fast_lputfield: | 2588 case Bytecodes::_fast_lputfield: |
2589 __ movq(field, rax); | 2589 __ movq(field, rax); |
2590 break; | 2590 break; |
2629 __ mov32(rcx, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); | 2629 __ mov32(rcx, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); |
2630 __ testl(rcx, rcx); | 2630 __ testl(rcx, rcx); |
2631 __ jcc(Assembler::zero, L1); | 2631 __ jcc(Assembler::zero, L1); |
2632 // access constant pool cache entry | 2632 // access constant pool cache entry |
2633 __ get_cache_entry_pointer_at_bcp(c_rarg2, rcx, 1); | 2633 __ get_cache_entry_pointer_at_bcp(c_rarg2, rcx, 1); |
2634 __ verify_oop(rax); | |
2634 __ movq(r12, rax); // save object pointer before call_VM() clobbers it | 2635 __ movq(r12, rax); // save object pointer before call_VM() clobbers it |
2635 __ verify_oop(rax); | |
2636 __ movq(c_rarg1, rax); | 2636 __ movq(c_rarg1, rax); |
2637 // c_rarg1: object pointer copied above | 2637 // c_rarg1: object pointer copied above |
2638 // c_rarg2: cache entry pointer | 2638 // c_rarg2: cache entry pointer |
2639 __ call_VM(noreg, | 2639 __ call_VM(noreg, |
2640 CAST_FROM_FN_PTR(address, | 2640 CAST_FROM_FN_PTR(address, |
2641 InterpreterRuntime::post_field_access), | 2641 InterpreterRuntime::post_field_access), |
2642 c_rarg1, c_rarg2); | 2642 c_rarg1, c_rarg2); |
2643 __ movq(rax, r12); // restore object pointer | 2643 __ movq(rax, r12); // restore object pointer |
2644 __ reinit_heapbase(); | |
2644 __ bind(L1); | 2645 __ bind(L1); |
2645 } | 2646 } |
2646 | 2647 |
2647 // access constant pool cache | 2648 // access constant pool cache |
2648 __ get_cache_and_index_at_bcp(rcx, rbx, 1); | 2649 __ get_cache_and_index_at_bcp(rcx, rbx, 1); |
2665 Address field(rax, rbx, Address::times_1); | 2666 Address field(rax, rbx, Address::times_1); |
2666 | 2667 |
2667 // access field | 2668 // access field |
2668 switch (bytecode()) { | 2669 switch (bytecode()) { |
2669 case Bytecodes::_fast_agetfield: | 2670 case Bytecodes::_fast_agetfield: |
2670 __ movq(rax, field); | 2671 __ load_heap_oop(rax, field); |
2671 __ verify_oop(rax); | 2672 __ verify_oop(rax); |
2672 break; | 2673 break; |
2673 case Bytecodes::_fast_lgetfield: | 2674 case Bytecodes::_fast_lgetfield: |
2674 __ movq(rax, field); | 2675 __ movq(rax, field); |
2675 break; | 2676 break; |
2723 switch (state) { | 2724 switch (state) { |
2724 case itos: | 2725 case itos: |
2725 __ movl(rax, Address(rax, rbx, Address::times_1)); | 2726 __ movl(rax, Address(rax, rbx, Address::times_1)); |
2726 break; | 2727 break; |
2727 case atos: | 2728 case atos: |
2728 __ movq(rax, Address(rax, rbx, Address::times_1)); | 2729 __ load_heap_oop(rax, Address(rax, rbx, Address::times_1)); |
2729 __ verify_oop(rax); | 2730 __ verify_oop(rax); |
2730 break; | 2731 break; |
2731 case ftos: | 2732 case ftos: |
2732 __ movflt(xmm0, Address(rax, rbx, Address::times_1)); | 2733 __ movflt(xmm0, Address(rax, rbx, Address::times_1)); |
2733 break; | 2734 break; |
2785 // load receiver if needed (note: no return address pushed yet) | 2786 // load receiver if needed (note: no return address pushed yet) |
2786 if (load_receiver) { | 2787 if (load_receiver) { |
2787 __ movl(recv, flags); | 2788 __ movl(recv, flags); |
2788 __ andl(recv, 0xFF); | 2789 __ andl(recv, 0xFF); |
2789 if (TaggedStackInterpreter) __ shll(recv, 1); // index*2 | 2790 if (TaggedStackInterpreter) __ shll(recv, 1); // index*2 |
2790 __ movq(recv, Address(rsp, recv, Address::times_8, -Interpreter::expr_offset_in_bytes(1))); | 2791 __ movq(recv, Address(rsp, recv, Address::times_8, |
2792 -Interpreter::expr_offset_in_bytes(1))); | |
2791 __ verify_oop(recv); | 2793 __ verify_oop(recv); |
2792 } | 2794 } |
2793 | 2795 |
2794 // do null check if needed | 2796 // do null check if needed |
2795 if (receiver_null_check) { | 2797 if (receiver_null_check) { |
2852 | 2854 |
2853 __ bind(notFinal); | 2855 __ bind(notFinal); |
2854 | 2856 |
2855 // get receiver klass | 2857 // get receiver klass |
2856 __ null_check(recv, oopDesc::klass_offset_in_bytes()); | 2858 __ null_check(recv, oopDesc::klass_offset_in_bytes()); |
2857 __ movq(rax, Address(recv, oopDesc::klass_offset_in_bytes())); | 2859 __ load_klass(rax, recv); |
2858 | 2860 |
2859 __ verify_oop(rax); | 2861 __ verify_oop(rax); |
2860 | 2862 |
2861 // profile this call | 2863 // profile this call |
2862 __ profile_virtual_call(rax, r14, rdx); | 2864 __ profile_virtual_call(rax, r14, rdx); |
2864 // get target methodOop & entry point | 2866 // get target methodOop & entry point |
2865 const int base = instanceKlass::vtable_start_offset() * wordSize; | 2867 const int base = instanceKlass::vtable_start_offset() * wordSize; |
2866 assert(vtableEntry::size() * wordSize == 8, | 2868 assert(vtableEntry::size() * wordSize == 8, |
2867 "adjust the scaling in the code below"); | 2869 "adjust the scaling in the code below"); |
2868 __ movq(method, Address(rax, index, | 2870 __ movq(method, Address(rax, index, |
2869 Address::times_8, | 2871 Address::times_8, |
2870 base + vtableEntry::method_offset_in_bytes())); | 2872 base + vtableEntry::method_offset_in_bytes())); |
2871 __ movq(rdx, Address(method, methodOopDesc::interpreter_entry_offset())); | 2873 __ movq(rdx, Address(method, methodOopDesc::interpreter_entry_offset())); |
2872 __ jump_from_interpreted(method, rdx); | 2874 __ jump_from_interpreted(method, rdx); |
2873 } | 2875 } |
2874 | 2876 |
2875 | 2877 |
2930 invokevirtual_helper(rbx, rcx, rdx); | 2932 invokevirtual_helper(rbx, rcx, rdx); |
2931 __ bind(notMethod); | 2933 __ bind(notMethod); |
2932 | 2934 |
2933 // Get receiver klass into rdx - also a null check | 2935 // Get receiver klass into rdx - also a null check |
2934 __ restore_locals(); // restore r14 | 2936 __ restore_locals(); // restore r14 |
2935 __ movq(rdx, Address(rcx, oopDesc::klass_offset_in_bytes())); | 2937 __ load_klass(rdx, rcx); |
2936 __ verify_oop(rdx); | 2938 __ verify_oop(rdx); |
2937 | 2939 |
2938 // profile this call | 2940 // profile this call |
2939 __ profile_virtual_call(rdx, r13, r14); | 2941 __ profile_virtual_call(rdx, r13, r14); |
2940 | 2942 |
3159 __ movq(Address(rax, oopDesc::mark_offset_in_bytes()), rscratch1); | 3161 __ movq(Address(rax, oopDesc::mark_offset_in_bytes()), rscratch1); |
3160 } else { | 3162 } else { |
3161 __ movptr(Address(rax, oopDesc::mark_offset_in_bytes()), | 3163 __ movptr(Address(rax, oopDesc::mark_offset_in_bytes()), |
3162 (intptr_t) markOopDesc::prototype()); // header (address 0x1) | 3164 (intptr_t) markOopDesc::prototype()); // header (address 0x1) |
3163 } | 3165 } |
3164 __ movq(Address(rax, oopDesc::klass_offset_in_bytes()), rsi); // klass | 3166 __ store_klass(rax, rsi); // klass |
3165 __ jmp(done); | 3167 __ jmp(done); |
3166 } | 3168 } |
3167 | 3169 |
3168 { | 3170 { |
3169 SkipIfEqual skip(_masm, &DTraceAllocProbes, false); | 3171 SkipIfEqual skip(_masm, &DTraceAllocProbes, false); |
3221 __ cmpb(Address(rdx, rbx, | 3223 __ cmpb(Address(rdx, rbx, |
3222 Address::times_1, | 3224 Address::times_1, |
3223 typeArrayOopDesc::header_size(T_BYTE) * wordSize), | 3225 typeArrayOopDesc::header_size(T_BYTE) * wordSize), |
3224 JVM_CONSTANT_Class); | 3226 JVM_CONSTANT_Class); |
3225 __ jcc(Assembler::equal, quicked); | 3227 __ jcc(Assembler::equal, quicked); |
3226 | 3228 __ push(atos); // save receiver for result, and for GC |
3227 __ movq(r12, rcx); // save rcx XXX | 3229 __ movq(r12, rcx); // save rcx XXX |
3228 __ push(atos); // save receiver for result, and for GC | |
3229 call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); | 3230 call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); |
3231 __ movq(rcx, r12); // restore rcx XXX | |
3232 __ reinit_heapbase(); | |
3230 __ pop_ptr(rdx); // restore receiver | 3233 __ pop_ptr(rdx); // restore receiver |
3231 __ movq(rcx, r12); // restore rcx XXX | |
3232 __ jmpb(resolved); | 3234 __ jmpb(resolved); |
3233 | 3235 |
3234 // Get superklass in rax and subklass in rbx | 3236 // Get superklass in rax and subklass in rbx |
3235 __ bind(quicked); | 3237 __ bind(quicked); |
3236 __ movq(rdx, rax); // Save object in rdx; rax needed for subtype check | 3238 __ movq(rdx, rax); // Save object in rdx; rax needed for subtype check |
3237 __ movq(rax, Address(rcx, rbx, | 3239 __ movq(rax, Address(rcx, rbx, |
3238 Address::times_8, sizeof(constantPoolOopDesc))); | 3240 Address::times_8, sizeof(constantPoolOopDesc))); |
3239 | 3241 |
3240 __ bind(resolved); | 3242 __ bind(resolved); |
3241 __ movq(rbx, Address(rdx, oopDesc::klass_offset_in_bytes())); | 3243 __ load_klass(rbx, rdx); |
3242 | 3244 |
3243 // Generate subtype check. Blows rcx, rdi. Object in rdx. | 3245 // Generate subtype check. Blows rcx, rdi. Object in rdx. |
3244 // Superklass in rax. Subklass in rbx. | 3246 // Superklass in rax. Subklass in rbx. |
3245 __ gen_subtype_check(rbx, ok_is_subtype); | 3247 __ gen_subtype_check(rbx, ok_is_subtype); |
3246 | 3248 |
3278 Address::times_1, | 3280 Address::times_1, |
3279 typeArrayOopDesc::header_size(T_BYTE) * wordSize), | 3281 typeArrayOopDesc::header_size(T_BYTE) * wordSize), |
3280 JVM_CONSTANT_Class); | 3282 JVM_CONSTANT_Class); |
3281 __ jcc(Assembler::equal, quicked); | 3283 __ jcc(Assembler::equal, quicked); |
3282 | 3284 |
3285 __ push(atos); // save receiver for result, and for GC | |
3283 __ movq(r12, rcx); // save rcx | 3286 __ movq(r12, rcx); // save rcx |
3284 __ push(atos); // save receiver for result, and for GC | |
3285 call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); | 3287 call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); |
3288 __ movq(rcx, r12); // restore rcx | |
3289 __ reinit_heapbase(); | |
3286 __ pop_ptr(rdx); // restore receiver | 3290 __ pop_ptr(rdx); // restore receiver |
3287 __ movq(rdx, Address(rdx, oopDesc::klass_offset_in_bytes())); | 3291 __ load_klass(rdx, rdx); |
3288 __ movq(rcx, r12); // restore rcx | |
3289 __ jmpb(resolved); | 3292 __ jmpb(resolved); |
3290 | 3293 |
3291 // Get superklass in rax and subklass in rdx | 3294 // Get superklass in rax and subklass in rdx |
3292 __ bind(quicked); | 3295 __ bind(quicked); |
3293 __ movq(rdx, Address(rax, oopDesc::klass_offset_in_bytes())); | 3296 __ load_klass(rdx, rax); |
3294 __ movq(rax, Address(rcx, rbx, | 3297 __ movq(rax, Address(rcx, rbx, |
3295 Address::times_8, sizeof(constantPoolOopDesc))); | 3298 Address::times_8, sizeof(constantPoolOopDesc))); |
3296 | 3299 |
3297 __ bind(resolved); | 3300 __ bind(resolved); |
3298 | 3301 |
3299 // Generate subtype check. Blows rcx, rdi | 3302 // Generate subtype check. Blows rcx, rdi |
3300 // Superklass in rax. Subklass in rdx. | 3303 // Superklass in rax. Subklass in rdx. |