1.1 --- a/src/cpu/sparc/vm/assembler_sparc.cpp Mon May 10 14:58:38 2010 -0700 1.2 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp Tue May 11 15:19:19 2010 -0700 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -2333,6 +2333,18 @@ 1.11 #endif 1.12 1.13 1.14 +void MacroAssembler::load_sized_value(Address src, Register dst, 1.15 + size_t size_in_bytes, bool is_signed) { 1.16 + switch (size_in_bytes) { 1.17 + case 8: ldx(src, dst); break; 1.18 + case 4: ld( src, dst); break; 1.19 + case 2: is_signed ? ldsh(src, dst) : lduh(src, dst); break; 1.20 + case 1: is_signed ? ldsb(src, dst) : ldub(src, dst); break; 1.21 + default: ShouldNotReachHere(); 1.22 + } 1.23 +} 1.24 + 1.25 + 1.26 void MacroAssembler::float_cmp( bool is_float, int unordered_result, 1.27 FloatRegister Fa, FloatRegister Fb, 1.28 Register Rresult) { 1.29 @@ -2625,40 +2637,103 @@ 1.30 } 1.31 1.32 1.33 -void MacroAssembler::regcon_inc_ptr( RegisterOrConstant& dest, RegisterOrConstant src, Register temp ) { 1.34 - assert(dest.register_or_noreg() != G0, "lost side effect"); 1.35 - if ((src.is_constant() && src.as_constant() == 0) || 1.36 - (src.is_register() && src.as_register() == G0)) { 1.37 - // do nothing 1.38 - } else if (dest.is_register()) { 1.39 - add(dest.as_register(), ensure_simm13_or_reg(src, temp), dest.as_register()); 1.40 - } else if (src.is_constant()) { 1.41 - intptr_t res = dest.as_constant() + src.as_constant(); 1.42 - dest = RegisterOrConstant(res); // side effect seen by caller 1.43 +RegisterOrConstant MacroAssembler::regcon_andn_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { 1.44 + assert(d.register_or_noreg() != G0, "lost side effect"); 1.45 + if ((s2.is_constant() && s2.as_constant() == 0) || 1.46 + (s2.is_register() && s2.as_register() == G0)) { 1.47 + // Do nothing, just move value. 1.48 + if (s1.is_register()) { 1.49 + if (d.is_constant()) d = temp; 1.50 + mov(s1.as_register(), d.as_register()); 1.51 + return d; 1.52 + } else { 1.53 + return s1; 1.54 + } 1.55 + } 1.56 + 1.57 + if (s1.is_register()) { 1.58 + assert_different_registers(s1.as_register(), temp); 1.59 + if (d.is_constant()) d = temp; 1.60 + andn(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); 1.61 + return d; 1.62 } else { 1.63 - assert(temp != noreg, "cannot handle constant += register"); 1.64 - add(src.as_register(), ensure_simm13_or_reg(dest, temp), temp); 1.65 - dest = RegisterOrConstant(temp); // side effect seen by caller 1.66 + if (s2.is_register()) { 1.67 + assert_different_registers(s2.as_register(), temp); 1.68 + if (d.is_constant()) d = temp; 1.69 + set(s1.as_constant(), temp); 1.70 + andn(temp, s2.as_register(), d.as_register()); 1.71 + return d; 1.72 + } else { 1.73 + intptr_t res = s1.as_constant() & ~s2.as_constant(); 1.74 + return res; 1.75 + } 1.76 } 1.77 } 1.78 1.79 -void MacroAssembler::regcon_sll_ptr( RegisterOrConstant& dest, RegisterOrConstant src, Register temp ) { 1.80 - assert(dest.register_or_noreg() != G0, "lost side effect"); 1.81 - if (!is_simm13(src.constant_or_zero())) 1.82 - src = (src.as_constant() & 0xFF); 1.83 - if ((src.is_constant() && src.as_constant() == 0) || 1.84 - (src.is_register() && src.as_register() == G0)) { 1.85 - // do nothing 1.86 - } else if (dest.is_register()) { 1.87 - sll_ptr(dest.as_register(), src, dest.as_register()); 1.88 - } else if (src.is_constant()) { 1.89 - intptr_t res = dest.as_constant() << src.as_constant(); 1.90 - dest = RegisterOrConstant(res); // side effect seen by caller 1.91 +RegisterOrConstant MacroAssembler::regcon_inc_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { 1.92 + assert(d.register_or_noreg() != G0, "lost side effect"); 1.93 + if ((s2.is_constant() && s2.as_constant() == 0) || 1.94 + (s2.is_register() && s2.as_register() == G0)) { 1.95 + // Do nothing, just move value. 1.96 + if (s1.is_register()) { 1.97 + if (d.is_constant()) d = temp; 1.98 + mov(s1.as_register(), d.as_register()); 1.99 + return d; 1.100 + } else { 1.101 + return s1; 1.102 + } 1.103 + } 1.104 + 1.105 + if (s1.is_register()) { 1.106 + assert_different_registers(s1.as_register(), temp); 1.107 + if (d.is_constant()) d = temp; 1.108 + add(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); 1.109 + return d; 1.110 } else { 1.111 - assert(temp != noreg, "cannot handle constant <<= register"); 1.112 - set(dest.as_constant(), temp); 1.113 - sll_ptr(temp, src, temp); 1.114 - dest = RegisterOrConstant(temp); // side effect seen by caller 1.115 + if (s2.is_register()) { 1.116 + assert_different_registers(s2.as_register(), temp); 1.117 + if (d.is_constant()) d = temp; 1.118 + add(s2.as_register(), ensure_simm13_or_reg(s1, temp), d.as_register()); 1.119 + return d; 1.120 + } else { 1.121 + intptr_t res = s1.as_constant() + s2.as_constant(); 1.122 + return res; 1.123 + } 1.124 + } 1.125 +} 1.126 + 1.127 +RegisterOrConstant MacroAssembler::regcon_sll_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { 1.128 + assert(d.register_or_noreg() != G0, "lost side effect"); 1.129 + if (!is_simm13(s2.constant_or_zero())) 1.130 + s2 = (s2.as_constant() & 0xFF); 1.131 + if ((s2.is_constant() && s2.as_constant() == 0) || 1.132 + (s2.is_register() && s2.as_register() == G0)) { 1.133 + // Do nothing, just move value. 1.134 + if (s1.is_register()) { 1.135 + if (d.is_constant()) d = temp; 1.136 + mov(s1.as_register(), d.as_register()); 1.137 + return d; 1.138 + } else { 1.139 + return s1; 1.140 + } 1.141 + } 1.142 + 1.143 + if (s1.is_register()) { 1.144 + assert_different_registers(s1.as_register(), temp); 1.145 + if (d.is_constant()) d = temp; 1.146 + sll_ptr(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); 1.147 + return d; 1.148 + } else { 1.149 + if (s2.is_register()) { 1.150 + assert_different_registers(s2.as_register(), temp); 1.151 + if (d.is_constant()) d = temp; 1.152 + set(s1.as_constant(), temp); 1.153 + sll_ptr(temp, s2.as_register(), d.as_register()); 1.154 + return d; 1.155 + } else { 1.156 + intptr_t res = s1.as_constant() << s2.as_constant(); 1.157 + return res; 1.158 + } 1.159 } 1.160 } 1.161 1.162 @@ -2708,8 +2783,8 @@ 1.163 1.164 // Adjust recv_klass by scaled itable_index, so we can free itable_index. 1.165 RegisterOrConstant itable_offset = itable_index; 1.166 - regcon_sll_ptr(itable_offset, exact_log2(itableMethodEntry::size() * wordSize)); 1.167 - regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes()); 1.168 + itable_offset = regcon_sll_ptr(itable_index, exact_log2(itableMethodEntry::size() * wordSize), itable_offset); 1.169 + itable_offset = regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes(), itable_offset); 1.170 add(recv_klass, ensure_simm13_or_reg(itable_offset, sethi_temp), recv_klass); 1.171 1.172 // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { 1.173 @@ -2805,7 +2880,7 @@ 1.174 1.175 assert_different_registers(sub_klass, super_klass, temp_reg); 1.176 if (super_check_offset.is_register()) { 1.177 - assert_different_registers(sub_klass, super_klass, 1.178 + assert_different_registers(sub_klass, super_klass, temp_reg, 1.179 super_check_offset.as_register()); 1.180 } else if (must_load_sco) { 1.181 assert(temp2_reg != noreg, "supply either a temp or a register offset"); 1.182 @@ -2855,6 +2930,8 @@ 1.183 // The super check offset is always positive... 1.184 lduw(super_klass, sco_offset, temp2_reg); 1.185 super_check_offset = RegisterOrConstant(temp2_reg); 1.186 + // super_check_offset is register. 1.187 + assert_different_registers(sub_klass, super_klass, temp_reg, super_check_offset.as_register()); 1.188 } 1.189 ld_ptr(sub_klass, super_check_offset, temp_reg); 1.190 cmp(super_klass, temp_reg); 1.191 @@ -3014,11 +3091,10 @@ 1.192 } 1.193 1.194 1.195 - 1.196 - 1.197 void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg, 1.198 Register temp_reg, 1.199 Label& wrong_method_type) { 1.200 + if (UseCompressedOops) unimplemented("coop"); // field accesses must decode 1.201 assert_different_registers(mtype_reg, mh_reg, temp_reg); 1.202 // compare method type against that of the receiver 1.203 RegisterOrConstant mhtype_offset = delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg); 1.204 @@ -3029,10 +3105,33 @@ 1.205 } 1.206 1.207 1.208 -void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) { 1.209 +// A method handle has a "vmslots" field which gives the size of its 1.210 +// argument list in JVM stack slots. This field is either located directly 1.211 +// in every method handle, or else is indirectly accessed through the 1.212 +// method handle's MethodType. This macro hides the distinction. 1.213 +void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register mh_reg, 1.214 + Register temp_reg) { 1.215 + assert_different_registers(vmslots_reg, mh_reg, temp_reg); 1.216 + if (UseCompressedOops) unimplemented("coop"); // field accesses must decode 1.217 + // load mh.type.form.vmslots 1.218 + if (java_dyn_MethodHandle::vmslots_offset_in_bytes() != 0) { 1.219 + // hoist vmslots into every mh to avoid dependent load chain 1.220 + ld( Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); 1.221 + } else { 1.222 + Register temp2_reg = vmslots_reg; 1.223 + ld_ptr(Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)), temp2_reg); 1.224 + ld_ptr(Address(temp2_reg, delayed_value(java_dyn_MethodType::form_offset_in_bytes, temp_reg)), temp2_reg); 1.225 + ld( Address(temp2_reg, delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); 1.226 + } 1.227 +} 1.228 + 1.229 + 1.230 +void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg, bool emit_delayed_nop) { 1.231 assert(mh_reg == G3_method_handle, "caller must put MH object in G3"); 1.232 assert_different_registers(mh_reg, temp_reg); 1.233 1.234 + if (UseCompressedOops) unimplemented("coop"); // field accesses must decode 1.235 + 1.236 // pick out the interpreted side of the handler 1.237 ld_ptr(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg), temp_reg); 1.238 1.239 @@ -3043,17 +3142,18 @@ 1.240 // for the various stubs which take control at this point, 1.241 // see MethodHandles::generate_method_handle_stub 1.242 1.243 - // (Can any caller use this delay slot? If so, add an option for supression.) 1.244 - delayed()->nop(); 1.245 + // Some callers can fill the delay slot. 1.246 + if (emit_delayed_nop) { 1.247 + delayed()->nop(); 1.248 + } 1.249 } 1.250 1.251 + 1.252 RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot, 1.253 int extra_slot_offset) { 1.254 // cf. TemplateTable::prepare_invoke(), if (load_receiver). 1.255 - int stackElementSize = Interpreter::stackElementWords() * wordSize; 1.256 - int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0); 1.257 - int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1); 1.258 - assert(offset1 - offset == stackElementSize, "correct arithmetic"); 1.259 + int stackElementSize = Interpreter::stackElementSize; 1.260 + int offset = extra_slot_offset * stackElementSize; 1.261 if (arg_slot.is_constant()) { 1.262 offset += arg_slot.as_constant() * stackElementSize; 1.263 return offset; 1.264 @@ -3067,6 +3167,11 @@ 1.265 } 1.266 1.267 1.268 +Address MacroAssembler::argument_address(RegisterOrConstant arg_slot, 1.269 + int extra_slot_offset) { 1.270 + return Address(Gargs, argument_offset(arg_slot, extra_slot_offset)); 1.271 +} 1.272 + 1.273 1.274 void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, 1.275 Register temp_reg,