Mercurial > hg > graal-compiler
comparison src/cpu/sparc/vm/assembler_sparc.cpp @ 644:c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
Summary: Code in interp_masm, stubGenerator, c1_LIRAssembler, and AD files moved into MacroAssembler.
Reviewed-by: kvn
author | jrose |
---|---|
date | Fri, 13 Mar 2009 18:39:22 -0700 |
parents | 660978a2a31a |
children | c89f86385056 96b229c54d1e |
comparison
equal
deleted
inserted
replaced
643:c771b7f43bbf | 644:c517646eef23 |
---|---|
2763 // scan_temp[-scan_step] points to the vtable offset we need | 2763 // scan_temp[-scan_step] points to the vtable offset we need |
2764 ito_offset -= scan_step; | 2764 ito_offset -= scan_step; |
2765 lduw(scan_temp, ito_offset, scan_temp); | 2765 lduw(scan_temp, ito_offset, scan_temp); |
2766 ld_ptr(recv_klass, scan_temp, method_result); | 2766 ld_ptr(recv_klass, scan_temp, method_result); |
2767 } | 2767 } |
2768 | |
2769 | |
2770 void MacroAssembler::check_klass_subtype(Register sub_klass, | |
2771 Register super_klass, | |
2772 Register temp_reg, | |
2773 Register temp2_reg, | |
2774 Label& L_success) { | |
2775 Label L_failure, L_pop_to_failure; | |
2776 check_klass_subtype_fast_path(sub_klass, super_klass, | |
2777 temp_reg, temp2_reg, | |
2778 &L_success, &L_failure, NULL); | |
2779 Register sub_2 = sub_klass; | |
2780 Register sup_2 = super_klass; | |
2781 if (!sub_2->is_global()) sub_2 = L0; | |
2782 if (!sup_2->is_global()) sup_2 = L1; | |
2783 | |
2784 save_frame_and_mov(0, sub_klass, sub_2, super_klass, sup_2); | |
2785 check_klass_subtype_slow_path(sub_2, sup_2, | |
2786 L2, L3, L4, L5, | |
2787 NULL, &L_pop_to_failure); | |
2788 | |
2789 // on success: | |
2790 restore(); | |
2791 ba(false, L_success); | |
2792 delayed()->nop(); | |
2793 | |
2794 // on failure: | |
2795 bind(L_pop_to_failure); | |
2796 restore(); | |
2797 bind(L_failure); | |
2798 } | |
2799 | |
2800 | |
2801 void MacroAssembler::check_klass_subtype_fast_path(Register sub_klass, | |
2802 Register super_klass, | |
2803 Register temp_reg, | |
2804 Register temp2_reg, | |
2805 Label* L_success, | |
2806 Label* L_failure, | |
2807 Label* L_slow_path, | |
2808 RegisterConstant super_check_offset, | |
2809 Register instanceof_hack) { | |
2810 int sc_offset = (klassOopDesc::header_size() * HeapWordSize + | |
2811 Klass::secondary_super_cache_offset_in_bytes()); | |
2812 int sco_offset = (klassOopDesc::header_size() * HeapWordSize + | |
2813 Klass::super_check_offset_offset_in_bytes()); | |
2814 | |
2815 bool must_load_sco = (super_check_offset.constant_or_zero() == -1); | |
2816 bool need_slow_path = (must_load_sco || | |
2817 super_check_offset.constant_or_zero() == sco_offset); | |
2818 | |
2819 assert_different_registers(sub_klass, super_klass, temp_reg); | |
2820 if (super_check_offset.is_register()) { | |
2821 assert_different_registers(sub_klass, super_klass, | |
2822 super_check_offset.as_register()); | |
2823 } else if (must_load_sco) { | |
2824 assert(temp2_reg != noreg, "supply either a temp or a register offset"); | |
2825 } | |
2826 | |
2827 Label L_fallthrough; | |
2828 int label_nulls = 0; | |
2829 if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } | |
2830 if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } | |
2831 if (L_slow_path == NULL) { L_slow_path = &L_fallthrough; label_nulls++; } | |
2832 assert(label_nulls <= 1 || instanceof_hack != noreg || | |
2833 (L_slow_path == &L_fallthrough && label_nulls <= 2 && !need_slow_path), | |
2834 "at most one NULL in the batch, usually"); | |
2835 | |
2836 // Support for the instanceof hack, which uses delay slots to | |
2837 // set a destination register to zero or one. | |
2838 bool do_bool_sets = (instanceof_hack != noreg); | |
2839 #define BOOL_SET(bool_value) \ | |
2840 if (do_bool_sets && bool_value >= 0) \ | |
2841 set(bool_value, instanceof_hack) | |
2842 #define DELAYED_BOOL_SET(bool_value) \ | |
2843 if (do_bool_sets && bool_value >= 0) \ | |
2844 delayed()->set(bool_value, instanceof_hack); \ | |
2845 else delayed()->nop() | |
2846 // Hacked ba(), which may only be used just before L_fallthrough. | |
2847 #define FINAL_JUMP(label, bool_value) \ | |
2848 if (&(label) == &L_fallthrough) { \ | |
2849 BOOL_SET(bool_value); \ | |
2850 } else { \ | |
2851 ba((do_bool_sets && bool_value >= 0), label); \ | |
2852 DELAYED_BOOL_SET(bool_value); \ | |
2853 } | |
2854 | |
2855 // If the pointers are equal, we are done (e.g., String[] elements). | |
2856 // This self-check enables sharing of secondary supertype arrays among | |
2857 // non-primary types such as array-of-interface. Otherwise, each such | |
2858 // type would need its own customized SSA. | |
2859 // We move this check to the front of the fast path because many | |
2860 // type checks are in fact trivially successful in this manner, | |
2861 // so we get a nicely predicted branch right at the start of the check. | |
2862 cmp(super_klass, sub_klass); | |
2863 brx(Assembler::equal, do_bool_sets, Assembler::pn, *L_success); | |
2864 DELAYED_BOOL_SET(1); | |
2865 | |
2866 // Check the supertype display: | |
2867 if (must_load_sco) { | |
2868 // The super check offset is always positive... | |
2869 lduw(super_klass, sco_offset, temp2_reg); | |
2870 super_check_offset = RegisterConstant(temp2_reg); | |
2871 } | |
2872 ld_ptr(sub_klass, super_check_offset, temp_reg); | |
2873 cmp(super_klass, temp_reg); | |
2874 | |
2875 // This check has worked decisively for primary supers. | |
2876 // Secondary supers are sought in the super_cache ('super_cache_addr'). | |
2877 // (Secondary supers are interfaces and very deeply nested subtypes.) | |
2878 // This works in the same check above because of a tricky aliasing | |
2879 // between the super_cache and the primary super display elements. | |
2880 // (The 'super_check_addr' can address either, as the case requires.) | |
2881 // Note that the cache is updated below if it does not help us find | |
2882 // what we need immediately. | |
2883 // So if it was a primary super, we can just fail immediately. | |
2884 // Otherwise, it's the slow path for us (no success at this point). | |
2885 | |
2886 if (super_check_offset.is_register()) { | |
2887 brx(Assembler::equal, do_bool_sets, Assembler::pn, *L_success); | |
2888 delayed(); if (do_bool_sets) BOOL_SET(1); | |
2889 // if !do_bool_sets, sneak the next cmp into the delay slot: | |
2890 cmp(super_check_offset.as_register(), sc_offset); | |
2891 | |
2892 if (L_failure == &L_fallthrough) { | |
2893 brx(Assembler::equal, do_bool_sets, Assembler::pt, *L_slow_path); | |
2894 delayed()->nop(); | |
2895 BOOL_SET(0); // fallthrough on failure | |
2896 } else { | |
2897 brx(Assembler::notEqual, do_bool_sets, Assembler::pn, *L_failure); | |
2898 DELAYED_BOOL_SET(0); | |
2899 FINAL_JUMP(*L_slow_path, -1); // -1 => vanilla delay slot | |
2900 } | |
2901 } else if (super_check_offset.as_constant() == sc_offset) { | |
2902 // Need a slow path; fast failure is impossible. | |
2903 if (L_slow_path == &L_fallthrough) { | |
2904 brx(Assembler::equal, do_bool_sets, Assembler::pt, *L_success); | |
2905 DELAYED_BOOL_SET(1); | |
2906 } else { | |
2907 brx(Assembler::notEqual, false, Assembler::pn, *L_slow_path); | |
2908 delayed()->nop(); | |
2909 FINAL_JUMP(*L_success, 1); | |
2910 } | |
2911 } else { | |
2912 // No slow path; it's a fast decision. | |
2913 if (L_failure == &L_fallthrough) { | |
2914 brx(Assembler::equal, do_bool_sets, Assembler::pt, *L_success); | |
2915 DELAYED_BOOL_SET(1); | |
2916 BOOL_SET(0); | |
2917 } else { | |
2918 brx(Assembler::notEqual, do_bool_sets, Assembler::pn, *L_failure); | |
2919 DELAYED_BOOL_SET(0); | |
2920 FINAL_JUMP(*L_success, 1); | |
2921 } | |
2922 } | |
2923 | |
2924 bind(L_fallthrough); | |
2925 | |
2926 #undef final_jump | |
2927 #undef bool_set | |
2928 #undef DELAYED_BOOL_SET | |
2929 #undef final_jump | |
2930 } | |
2931 | |
2932 | |
2933 void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, | |
2934 Register super_klass, | |
2935 Register count_temp, | |
2936 Register scan_temp, | |
2937 Register scratch_reg, | |
2938 Register coop_reg, | |
2939 Label* L_success, | |
2940 Label* L_failure) { | |
2941 assert_different_registers(sub_klass, super_klass, | |
2942 count_temp, scan_temp, scratch_reg, coop_reg); | |
2943 | |
2944 Label L_fallthrough, L_loop; | |
2945 int label_nulls = 0; | |
2946 if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } | |
2947 if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } | |
2948 assert(label_nulls <= 1, "at most one NULL in the batch"); | |
2949 | |
2950 // a couple of useful fields in sub_klass: | |
2951 int ss_offset = (klassOopDesc::header_size() * HeapWordSize + | |
2952 Klass::secondary_supers_offset_in_bytes()); | |
2953 int sc_offset = (klassOopDesc::header_size() * HeapWordSize + | |
2954 Klass::secondary_super_cache_offset_in_bytes()); | |
2955 | |
2956 // Do a linear scan of the secondary super-klass chain. | |
2957 // This code is rarely used, so simplicity is a virtue here. | |
2958 | |
2959 #ifndef PRODUCT | |
2960 int* pst_counter = &SharedRuntime::_partial_subtype_ctr; | |
2961 inc_counter((address) pst_counter, count_temp, scan_temp); | |
2962 #endif | |
2963 | |
2964 // We will consult the secondary-super array. | |
2965 ld_ptr(sub_klass, ss_offset, scan_temp); | |
2966 | |
2967 // Compress superclass if necessary. | |
2968 Register search_key = super_klass; | |
2969 bool decode_super_klass = false; | |
2970 if (UseCompressedOops) { | |
2971 if (coop_reg != noreg) { | |
2972 encode_heap_oop_not_null(super_klass, coop_reg); | |
2973 search_key = coop_reg; | |
2974 } else { | |
2975 encode_heap_oop_not_null(super_klass); | |
2976 decode_super_klass = true; // scarce temps! | |
2977 } | |
2978 // The superclass is never null; it would be a basic system error if a null | |
2979 // pointer were to sneak in here. Note that we have already loaded the | |
2980 // Klass::super_check_offset from the super_klass in the fast path, | |
2981 // so if there is a null in that register, we are already in the afterlife. | |
2982 } | |
2983 | |
2984 // Load the array length. (Positive movl does right thing on LP64.) | |
2985 lduw(scan_temp, arrayOopDesc::length_offset_in_bytes(), count_temp); | |
2986 | |
2987 // Check for empty secondary super list | |
2988 tst(count_temp); | |
2989 | |
2990 // Top of search loop | |
2991 bind(L_loop); | |
2992 br(Assembler::equal, false, Assembler::pn, *L_failure); | |
2993 delayed()->add(scan_temp, heapOopSize, scan_temp); | |
2994 assert(heapOopSize != 0, "heapOopSize should be initialized"); | |
2995 | |
2996 // Skip the array header in all array accesses. | |
2997 int elem_offset = arrayOopDesc::base_offset_in_bytes(T_OBJECT); | |
2998 elem_offset -= heapOopSize; // the scan pointer was pre-incremented also | |
2999 | |
3000 // Load next super to check | |
3001 if (UseCompressedOops) { | |
3002 // Don't use load_heap_oop; we don't want to decode the element. | |
3003 lduw( scan_temp, elem_offset, scratch_reg ); | |
3004 } else { | |
3005 ld_ptr( scan_temp, elem_offset, scratch_reg ); | |
3006 } | |
3007 | |
3008 // Look for Rsuper_klass on Rsub_klass's secondary super-class-overflow list | |
3009 cmp(scratch_reg, search_key); | |
3010 | |
3011 // A miss means we are NOT a subtype and need to keep looping | |
3012 brx(Assembler::notEqual, false, Assembler::pn, L_loop); | |
3013 delayed()->deccc(count_temp); // decrement trip counter in delay slot | |
3014 | |
3015 // Falling out the bottom means we found a hit; we ARE a subtype | |
3016 if (decode_super_klass) decode_heap_oop(super_klass); | |
3017 | |
3018 // Success. Cache the super we found and proceed in triumph. | |
3019 st_ptr(super_klass, sub_klass, sc_offset); | |
3020 | |
3021 if (L_success != &L_fallthrough) { | |
3022 ba(false, *L_success); | |
3023 delayed()->nop(); | |
3024 } | |
3025 | |
3026 bind(L_fallthrough); | |
3027 } | |
3028 | |
3029 | |
2768 | 3030 |
2769 | 3031 |
2770 void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, | 3032 void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, |
2771 Register temp_reg, | 3033 Register temp_reg, |
2772 Label& done, Label* slow_case, | 3034 Label& done, Label* slow_case, |