1.1 --- a/src/cpu/sparc/vm/assembler_sparc.cpp Wed Mar 04 09:58:39 2009 -0800 1.2 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp Fri Mar 06 21:36:50 2009 -0800 1.3 @@ -2638,6 +2638,135 @@ 1.4 } 1.5 1.6 1.7 +void MacroAssembler::regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) { 1.8 + assert(dest.register_or_noreg() != G0, "lost side effect"); 1.9 + if ((src.is_constant() && src.as_constant() == 0) || 1.10 + (src.is_register() && src.as_register() == G0)) { 1.11 + // do nothing 1.12 + } else if (dest.is_register()) { 1.13 + add(dest.as_register(), ensure_rs2(src, temp), dest.as_register()); 1.14 + } else if (src.is_constant()) { 1.15 + intptr_t res = dest.as_constant() + src.as_constant(); 1.16 + dest = RegisterConstant(res); // side effect seen by caller 1.17 + } else { 1.18 + assert(temp != noreg, "cannot handle constant += register"); 1.19 + add(src.as_register(), ensure_rs2(dest, temp), temp); 1.20 + dest = RegisterConstant(temp); // side effect seen by caller 1.21 + } 1.22 +} 1.23 + 1.24 +void MacroAssembler::regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) { 1.25 + assert(dest.register_or_noreg() != G0, "lost side effect"); 1.26 + if (!is_simm13(src.constant_or_zero())) 1.27 + src = (src.as_constant() & 0xFF); 1.28 + if ((src.is_constant() && src.as_constant() == 0) || 1.29 + (src.is_register() && src.as_register() == G0)) { 1.30 + // do nothing 1.31 + } else if (dest.is_register()) { 1.32 + sll_ptr(dest.as_register(), src, dest.as_register()); 1.33 + } else if (src.is_constant()) { 1.34 + intptr_t res = dest.as_constant() << src.as_constant(); 1.35 + dest = RegisterConstant(res); // side effect seen by caller 1.36 + } else { 1.37 + assert(temp != noreg, "cannot handle constant <<= register"); 1.38 + set(dest.as_constant(), temp); 1.39 + sll_ptr(temp, src, temp); 1.40 + dest = RegisterConstant(temp); // side effect seen by caller 1.41 + } 1.42 +} 1.43 + 1.44 + 1.45 +// Look up the method for a megamorphic invokeinterface call. 1.46 +// The target method is determined by <intf_klass, itable_index>. 1.47 +// The receiver klass is in recv_klass. 1.48 +// On success, the result will be in method_result, and execution falls through. 1.49 +// On failure, execution transfers to the given label. 1.50 +void MacroAssembler::lookup_interface_method(Register recv_klass, 1.51 + Register intf_klass, 1.52 + RegisterConstant itable_index, 1.53 + Register method_result, 1.54 + Register scan_temp, 1.55 + Register sethi_temp, 1.56 + Label& L_no_such_interface) { 1.57 + assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); 1.58 + assert(itable_index.is_constant() || itable_index.as_register() == method_result, 1.59 + "caller must use same register for non-constant itable index as for method"); 1.60 + 1.61 + // Compute start of first itableOffsetEntry (which is at the end of the vtable) 1.62 + int vtable_base = instanceKlass::vtable_start_offset() * wordSize; 1.63 + int scan_step = itableOffsetEntry::size() * wordSize; 1.64 + int vte_size = vtableEntry::size() * wordSize; 1.65 + 1.66 + lduw(recv_klass, instanceKlass::vtable_length_offset() * wordSize, scan_temp); 1.67 + // %%% We should store the aligned, prescaled offset in the klassoop. 1.68 + // Then the next several instructions would fold away. 1.69 + 1.70 + int round_to_unit = ((HeapWordsPerLong > 1) ? BytesPerLong : 0); 1.71 + int itb_offset = vtable_base; 1.72 + if (round_to_unit != 0) { 1.73 + // hoist first instruction of round_to(scan_temp, BytesPerLong): 1.74 + itb_offset += round_to_unit - wordSize; 1.75 + } 1.76 + int itb_scale = exact_log2(vtableEntry::size() * wordSize); 1.77 + sll(scan_temp, itb_scale, scan_temp); 1.78 + add(scan_temp, itb_offset, scan_temp); 1.79 + if (round_to_unit != 0) { 1.80 + // Round up to align_object_offset boundary 1.81 + // see code for instanceKlass::start_of_itable! 1.82 + // Was: round_to(scan_temp, BytesPerLong); 1.83 + // Hoisted: add(scan_temp, BytesPerLong-1, scan_temp); 1.84 + and3(scan_temp, -round_to_unit, scan_temp); 1.85 + } 1.86 + add(recv_klass, scan_temp, scan_temp); 1.87 + 1.88 + // Adjust recv_klass by scaled itable_index, so we can free itable_index. 1.89 + RegisterConstant itable_offset = itable_index; 1.90 + regcon_sll_ptr(itable_offset, exact_log2(itableMethodEntry::size() * wordSize)); 1.91 + regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes()); 1.92 + add(recv_klass, ensure_rs2(itable_offset, sethi_temp), recv_klass); 1.93 + 1.94 + // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { 1.95 + // if (scan->interface() == intf) { 1.96 + // result = (klass + scan->offset() + itable_index); 1.97 + // } 1.98 + // } 1.99 + Label search, found_method; 1.100 + 1.101 + for (int peel = 1; peel >= 0; peel--) { 1.102 + // %%%% Could load both offset and interface in one ldx, if they were 1.103 + // in the opposite order. This would save a load. 1.104 + ld_ptr(scan_temp, itableOffsetEntry::interface_offset_in_bytes(), method_result); 1.105 + 1.106 + // Check that this entry is non-null. A null entry means that 1.107 + // the receiver class doesn't implement the interface, and wasn't the 1.108 + // same as when the caller was compiled. 1.109 + bpr(Assembler::rc_z, false, Assembler::pn, method_result, L_no_such_interface); 1.110 + delayed()->cmp(method_result, intf_klass); 1.111 + 1.112 + if (peel) { 1.113 + brx(Assembler::equal, false, Assembler::pt, found_method); 1.114 + } else { 1.115 + brx(Assembler::notEqual, false, Assembler::pn, search); 1.116 + // (invert the test to fall through to found_method...) 1.117 + } 1.118 + delayed()->add(scan_temp, scan_step, scan_temp); 1.119 + 1.120 + if (!peel) break; 1.121 + 1.122 + bind(search); 1.123 + } 1.124 + 1.125 + bind(found_method); 1.126 + 1.127 + // Got a hit. 1.128 + int ito_offset = itableOffsetEntry::offset_offset_in_bytes(); 1.129 + // scan_temp[-scan_step] points to the vtable offset we need 1.130 + ito_offset -= scan_step; 1.131 + lduw(scan_temp, ito_offset, scan_temp); 1.132 + ld_ptr(recv_klass, scan_temp, method_result); 1.133 +} 1.134 + 1.135 + 1.136 void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, 1.137 Register temp_reg, 1.138 Label& done, Label* slow_case,