1.1 --- a/src/cpu/sparc/vm/assembler_sparc.cpp Fri Mar 13 11:35:17 2009 -0700 1.2 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp Fri Mar 13 18:39:22 2009 -0700 1.3 @@ -2767,6 +2767,268 @@ 1.4 } 1.5 1.6 1.7 +void MacroAssembler::check_klass_subtype(Register sub_klass, 1.8 + Register super_klass, 1.9 + Register temp_reg, 1.10 + Register temp2_reg, 1.11 + Label& L_success) { 1.12 + Label L_failure, L_pop_to_failure; 1.13 + check_klass_subtype_fast_path(sub_klass, super_klass, 1.14 + temp_reg, temp2_reg, 1.15 + &L_success, &L_failure, NULL); 1.16 + Register sub_2 = sub_klass; 1.17 + Register sup_2 = super_klass; 1.18 + if (!sub_2->is_global()) sub_2 = L0; 1.19 + if (!sup_2->is_global()) sup_2 = L1; 1.20 + 1.21 + save_frame_and_mov(0, sub_klass, sub_2, super_klass, sup_2); 1.22 + check_klass_subtype_slow_path(sub_2, sup_2, 1.23 + L2, L3, L4, L5, 1.24 + NULL, &L_pop_to_failure); 1.25 + 1.26 + // on success: 1.27 + restore(); 1.28 + ba(false, L_success); 1.29 + delayed()->nop(); 1.30 + 1.31 + // on failure: 1.32 + bind(L_pop_to_failure); 1.33 + restore(); 1.34 + bind(L_failure); 1.35 +} 1.36 + 1.37 + 1.38 +void MacroAssembler::check_klass_subtype_fast_path(Register sub_klass, 1.39 + Register super_klass, 1.40 + Register temp_reg, 1.41 + Register temp2_reg, 1.42 + Label* L_success, 1.43 + Label* L_failure, 1.44 + Label* L_slow_path, 1.45 + RegisterConstant super_check_offset, 1.46 + Register instanceof_hack) { 1.47 + int sc_offset = (klassOopDesc::header_size() * HeapWordSize + 1.48 + Klass::secondary_super_cache_offset_in_bytes()); 1.49 + int sco_offset = (klassOopDesc::header_size() * HeapWordSize + 1.50 + Klass::super_check_offset_offset_in_bytes()); 1.51 + 1.52 + bool must_load_sco = (super_check_offset.constant_or_zero() == -1); 1.53 + bool need_slow_path = (must_load_sco || 1.54 + super_check_offset.constant_or_zero() == sco_offset); 1.55 + 1.56 + assert_different_registers(sub_klass, super_klass, temp_reg); 1.57 + if (super_check_offset.is_register()) { 1.58 + assert_different_registers(sub_klass, super_klass, 1.59 + super_check_offset.as_register()); 1.60 + } else if (must_load_sco) { 1.61 + assert(temp2_reg != noreg, "supply either a temp or a register offset"); 1.62 + } 1.63 + 1.64 + Label L_fallthrough; 1.65 + int label_nulls = 0; 1.66 + if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } 1.67 + if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } 1.68 + if (L_slow_path == NULL) { L_slow_path = &L_fallthrough; label_nulls++; } 1.69 + assert(label_nulls <= 1 || instanceof_hack != noreg || 1.70 + (L_slow_path == &L_fallthrough && label_nulls <= 2 && !need_slow_path), 1.71 + "at most one NULL in the batch, usually"); 1.72 + 1.73 + // Support for the instanceof hack, which uses delay slots to 1.74 + // set a destination register to zero or one. 1.75 + bool do_bool_sets = (instanceof_hack != noreg); 1.76 +#define BOOL_SET(bool_value) \ 1.77 + if (do_bool_sets && bool_value >= 0) \ 1.78 + set(bool_value, instanceof_hack) 1.79 +#define DELAYED_BOOL_SET(bool_value) \ 1.80 + if (do_bool_sets && bool_value >= 0) \ 1.81 + delayed()->set(bool_value, instanceof_hack); \ 1.82 + else delayed()->nop() 1.83 + // Hacked ba(), which may only be used just before L_fallthrough. 1.84 +#define FINAL_JUMP(label, bool_value) \ 1.85 + if (&(label) == &L_fallthrough) { \ 1.86 + BOOL_SET(bool_value); \ 1.87 + } else { \ 1.88 + ba((do_bool_sets && bool_value >= 0), label); \ 1.89 + DELAYED_BOOL_SET(bool_value); \ 1.90 + } 1.91 + 1.92 + // If the pointers are equal, we are done (e.g., String[] elements). 1.93 + // This self-check enables sharing of secondary supertype arrays among 1.94 + // non-primary types such as array-of-interface. Otherwise, each such 1.95 + // type would need its own customized SSA. 1.96 + // We move this check to the front of the fast path because many 1.97 + // type checks are in fact trivially successful in this manner, 1.98 + // so we get a nicely predicted branch right at the start of the check. 1.99 + cmp(super_klass, sub_klass); 1.100 + brx(Assembler::equal, do_bool_sets, Assembler::pn, *L_success); 1.101 + DELAYED_BOOL_SET(1); 1.102 + 1.103 + // Check the supertype display: 1.104 + if (must_load_sco) { 1.105 + // The super check offset is always positive... 1.106 + lduw(super_klass, sco_offset, temp2_reg); 1.107 + super_check_offset = RegisterConstant(temp2_reg); 1.108 + } 1.109 + ld_ptr(sub_klass, super_check_offset, temp_reg); 1.110 + cmp(super_klass, temp_reg); 1.111 + 1.112 + // This check has worked decisively for primary supers. 1.113 + // Secondary supers are sought in the super_cache ('super_cache_addr'). 1.114 + // (Secondary supers are interfaces and very deeply nested subtypes.) 1.115 + // This works in the same check above because of a tricky aliasing 1.116 + // between the super_cache and the primary super display elements. 1.117 + // (The 'super_check_addr' can address either, as the case requires.) 1.118 + // Note that the cache is updated below if it does not help us find 1.119 + // what we need immediately. 1.120 + // So if it was a primary super, we can just fail immediately. 1.121 + // Otherwise, it's the slow path for us (no success at this point). 1.122 + 1.123 + if (super_check_offset.is_register()) { 1.124 + brx(Assembler::equal, do_bool_sets, Assembler::pn, *L_success); 1.125 + delayed(); if (do_bool_sets) BOOL_SET(1); 1.126 + // if !do_bool_sets, sneak the next cmp into the delay slot: 1.127 + cmp(super_check_offset.as_register(), sc_offset); 1.128 + 1.129 + if (L_failure == &L_fallthrough) { 1.130 + brx(Assembler::equal, do_bool_sets, Assembler::pt, *L_slow_path); 1.131 + delayed()->nop(); 1.132 + BOOL_SET(0); // fallthrough on failure 1.133 + } else { 1.134 + brx(Assembler::notEqual, do_bool_sets, Assembler::pn, *L_failure); 1.135 + DELAYED_BOOL_SET(0); 1.136 + FINAL_JUMP(*L_slow_path, -1); // -1 => vanilla delay slot 1.137 + } 1.138 + } else if (super_check_offset.as_constant() == sc_offset) { 1.139 + // Need a slow path; fast failure is impossible. 1.140 + if (L_slow_path == &L_fallthrough) { 1.141 + brx(Assembler::equal, do_bool_sets, Assembler::pt, *L_success); 1.142 + DELAYED_BOOL_SET(1); 1.143 + } else { 1.144 + brx(Assembler::notEqual, false, Assembler::pn, *L_slow_path); 1.145 + delayed()->nop(); 1.146 + FINAL_JUMP(*L_success, 1); 1.147 + } 1.148 + } else { 1.149 + // No slow path; it's a fast decision. 1.150 + if (L_failure == &L_fallthrough) { 1.151 + brx(Assembler::equal, do_bool_sets, Assembler::pt, *L_success); 1.152 + DELAYED_BOOL_SET(1); 1.153 + BOOL_SET(0); 1.154 + } else { 1.155 + brx(Assembler::notEqual, do_bool_sets, Assembler::pn, *L_failure); 1.156 + DELAYED_BOOL_SET(0); 1.157 + FINAL_JUMP(*L_success, 1); 1.158 + } 1.159 + } 1.160 + 1.161 + bind(L_fallthrough); 1.162 + 1.163 +#undef final_jump 1.164 +#undef bool_set 1.165 +#undef DELAYED_BOOL_SET 1.166 +#undef final_jump 1.167 +} 1.168 + 1.169 + 1.170 +void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, 1.171 + Register super_klass, 1.172 + Register count_temp, 1.173 + Register scan_temp, 1.174 + Register scratch_reg, 1.175 + Register coop_reg, 1.176 + Label* L_success, 1.177 + Label* L_failure) { 1.178 + assert_different_registers(sub_klass, super_klass, 1.179 + count_temp, scan_temp, scratch_reg, coop_reg); 1.180 + 1.181 + Label L_fallthrough, L_loop; 1.182 + int label_nulls = 0; 1.183 + if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } 1.184 + if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } 1.185 + assert(label_nulls <= 1, "at most one NULL in the batch"); 1.186 + 1.187 + // a couple of useful fields in sub_klass: 1.188 + int ss_offset = (klassOopDesc::header_size() * HeapWordSize + 1.189 + Klass::secondary_supers_offset_in_bytes()); 1.190 + int sc_offset = (klassOopDesc::header_size() * HeapWordSize + 1.191 + Klass::secondary_super_cache_offset_in_bytes()); 1.192 + 1.193 + // Do a linear scan of the secondary super-klass chain. 1.194 + // This code is rarely used, so simplicity is a virtue here. 1.195 + 1.196 +#ifndef PRODUCT 1.197 + int* pst_counter = &SharedRuntime::_partial_subtype_ctr; 1.198 + inc_counter((address) pst_counter, count_temp, scan_temp); 1.199 +#endif 1.200 + 1.201 + // We will consult the secondary-super array. 1.202 + ld_ptr(sub_klass, ss_offset, scan_temp); 1.203 + 1.204 + // Compress superclass if necessary. 1.205 + Register search_key = super_klass; 1.206 + bool decode_super_klass = false; 1.207 + if (UseCompressedOops) { 1.208 + if (coop_reg != noreg) { 1.209 + encode_heap_oop_not_null(super_klass, coop_reg); 1.210 + search_key = coop_reg; 1.211 + } else { 1.212 + encode_heap_oop_not_null(super_klass); 1.213 + decode_super_klass = true; // scarce temps! 1.214 + } 1.215 + // The superclass is never null; it would be a basic system error if a null 1.216 + // pointer were to sneak in here. Note that we have already loaded the 1.217 + // Klass::super_check_offset from the super_klass in the fast path, 1.218 + // so if there is a null in that register, we are already in the afterlife. 1.219 + } 1.220 + 1.221 + // Load the array length. (Positive movl does right thing on LP64.) 1.222 + lduw(scan_temp, arrayOopDesc::length_offset_in_bytes(), count_temp); 1.223 + 1.224 + // Check for empty secondary super list 1.225 + tst(count_temp); 1.226 + 1.227 + // Top of search loop 1.228 + bind(L_loop); 1.229 + br(Assembler::equal, false, Assembler::pn, *L_failure); 1.230 + delayed()->add(scan_temp, heapOopSize, scan_temp); 1.231 + assert(heapOopSize != 0, "heapOopSize should be initialized"); 1.232 + 1.233 + // Skip the array header in all array accesses. 1.234 + int elem_offset = arrayOopDesc::base_offset_in_bytes(T_OBJECT); 1.235 + elem_offset -= heapOopSize; // the scan pointer was pre-incremented also 1.236 + 1.237 + // Load next super to check 1.238 + if (UseCompressedOops) { 1.239 + // Don't use load_heap_oop; we don't want to decode the element. 1.240 + lduw( scan_temp, elem_offset, scratch_reg ); 1.241 + } else { 1.242 + ld_ptr( scan_temp, elem_offset, scratch_reg ); 1.243 + } 1.244 + 1.245 + // Look for Rsuper_klass on Rsub_klass's secondary super-class-overflow list 1.246 + cmp(scratch_reg, search_key); 1.247 + 1.248 + // A miss means we are NOT a subtype and need to keep looping 1.249 + brx(Assembler::notEqual, false, Assembler::pn, L_loop); 1.250 + delayed()->deccc(count_temp); // decrement trip counter in delay slot 1.251 + 1.252 + // Falling out the bottom means we found a hit; we ARE a subtype 1.253 + if (decode_super_klass) decode_heap_oop(super_klass); 1.254 + 1.255 + // Success. Cache the super we found and proceed in triumph. 1.256 + st_ptr(super_klass, sub_klass, sc_offset); 1.257 + 1.258 + if (L_success != &L_fallthrough) { 1.259 + ba(false, *L_success); 1.260 + delayed()->nop(); 1.261 + } 1.262 + 1.263 + bind(L_fallthrough); 1.264 +} 1.265 + 1.266 + 1.267 + 1.268 + 1.269 void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, 1.270 Register temp_reg, 1.271 Label& done, Label* slow_case,