Tue, 10 Mar 2009 08:52:16 -0700
Merge
src/cpu/x86/vm/interp_masm_x86_32.cpp | file | annotate | diff | comparison | revisions | |
src/cpu/x86/vm/interp_masm_x86_64.cpp | file | annotate | diff | comparison | revisions |
1.1 --- a/src/cpu/sparc/vm/assembler_sparc.cpp Mon Mar 09 11:32:57 2009 -0400 1.2 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp Tue Mar 10 08:52:16 2009 -0700 1.3 @@ -2615,6 +2615,158 @@ 1.4 } 1.5 } 1.6 1.7 +RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr, 1.8 + Register tmp, 1.9 + int offset) { 1.10 + intptr_t value = *delayed_value_addr; 1.11 + if (value != 0) 1.12 + return RegisterConstant(value + offset); 1.13 + 1.14 + // load indirectly to solve generation ordering problem 1.15 + Address a(tmp, (address) delayed_value_addr); 1.16 + load_ptr_contents(a, tmp); 1.17 + 1.18 +#ifdef ASSERT 1.19 + tst(tmp); 1.20 + breakpoint_trap(zero, xcc); 1.21 +#endif 1.22 + 1.23 + if (offset != 0) 1.24 + add(tmp, offset, tmp); 1.25 + 1.26 + return RegisterConstant(tmp); 1.27 +} 1.28 + 1.29 + 1.30 +void MacroAssembler::regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) { 1.31 + assert(dest.register_or_noreg() != G0, "lost side effect"); 1.32 + if ((src.is_constant() && src.as_constant() == 0) || 1.33 + (src.is_register() && src.as_register() == G0)) { 1.34 + // do nothing 1.35 + } else if (dest.is_register()) { 1.36 + add(dest.as_register(), ensure_rs2(src, temp), dest.as_register()); 1.37 + } else if (src.is_constant()) { 1.38 + intptr_t res = dest.as_constant() + src.as_constant(); 1.39 + dest = RegisterConstant(res); // side effect seen by caller 1.40 + } else { 1.41 + assert(temp != noreg, "cannot handle constant += register"); 1.42 + add(src.as_register(), ensure_rs2(dest, temp), temp); 1.43 + dest = RegisterConstant(temp); // side effect seen by caller 1.44 + } 1.45 +} 1.46 + 1.47 +void MacroAssembler::regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) { 1.48 + assert(dest.register_or_noreg() != G0, "lost side effect"); 1.49 + if (!is_simm13(src.constant_or_zero())) 1.50 + src = (src.as_constant() & 0xFF); 1.51 + if ((src.is_constant() && src.as_constant() == 0) || 1.52 + (src.is_register() && src.as_register() == G0)) { 1.53 + // do nothing 1.54 + } else if (dest.is_register()) { 1.55 + sll_ptr(dest.as_register(), src, dest.as_register()); 1.56 + } else if (src.is_constant()) { 1.57 + intptr_t res = dest.as_constant() << src.as_constant(); 1.58 + dest = RegisterConstant(res); // side effect seen by caller 1.59 + } else { 1.60 + assert(temp != noreg, "cannot handle constant <<= register"); 1.61 + set(dest.as_constant(), temp); 1.62 + sll_ptr(temp, src, temp); 1.63 + dest = RegisterConstant(temp); // side effect seen by caller 1.64 + } 1.65 +} 1.66 + 1.67 + 1.68 +// Look up the method for a megamorphic invokeinterface call. 1.69 +// The target method is determined by <intf_klass, itable_index>. 1.70 +// The receiver klass is in recv_klass. 1.71 +// On success, the result will be in method_result, and execution falls through. 1.72 +// On failure, execution transfers to the given label. 1.73 +void MacroAssembler::lookup_interface_method(Register recv_klass, 1.74 + Register intf_klass, 1.75 + RegisterConstant itable_index, 1.76 + Register method_result, 1.77 + Register scan_temp, 1.78 + Register sethi_temp, 1.79 + Label& L_no_such_interface) { 1.80 + assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); 1.81 + assert(itable_index.is_constant() || itable_index.as_register() == method_result, 1.82 + "caller must use same register for non-constant itable index as for method"); 1.83 + 1.84 + // Compute start of first itableOffsetEntry (which is at the end of the vtable) 1.85 + int vtable_base = instanceKlass::vtable_start_offset() * wordSize; 1.86 + int scan_step = itableOffsetEntry::size() * wordSize; 1.87 + int vte_size = vtableEntry::size() * wordSize; 1.88 + 1.89 + lduw(recv_klass, instanceKlass::vtable_length_offset() * wordSize, scan_temp); 1.90 + // %%% We should store the aligned, prescaled offset in the klassoop. 1.91 + // Then the next several instructions would fold away. 1.92 + 1.93 + int round_to_unit = ((HeapWordsPerLong > 1) ? BytesPerLong : 0); 1.94 + int itb_offset = vtable_base; 1.95 + if (round_to_unit != 0) { 1.96 + // hoist first instruction of round_to(scan_temp, BytesPerLong): 1.97 + itb_offset += round_to_unit - wordSize; 1.98 + } 1.99 + int itb_scale = exact_log2(vtableEntry::size() * wordSize); 1.100 + sll(scan_temp, itb_scale, scan_temp); 1.101 + add(scan_temp, itb_offset, scan_temp); 1.102 + if (round_to_unit != 0) { 1.103 + // Round up to align_object_offset boundary 1.104 + // see code for instanceKlass::start_of_itable! 1.105 + // Was: round_to(scan_temp, BytesPerLong); 1.106 + // Hoisted: add(scan_temp, BytesPerLong-1, scan_temp); 1.107 + and3(scan_temp, -round_to_unit, scan_temp); 1.108 + } 1.109 + add(recv_klass, scan_temp, scan_temp); 1.110 + 1.111 + // Adjust recv_klass by scaled itable_index, so we can free itable_index. 1.112 + RegisterConstant itable_offset = itable_index; 1.113 + regcon_sll_ptr(itable_offset, exact_log2(itableMethodEntry::size() * wordSize)); 1.114 + regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes()); 1.115 + add(recv_klass, ensure_rs2(itable_offset, sethi_temp), recv_klass); 1.116 + 1.117 + // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { 1.118 + // if (scan->interface() == intf) { 1.119 + // result = (klass + scan->offset() + itable_index); 1.120 + // } 1.121 + // } 1.122 + Label search, found_method; 1.123 + 1.124 + for (int peel = 1; peel >= 0; peel--) { 1.125 + // %%%% Could load both offset and interface in one ldx, if they were 1.126 + // in the opposite order. This would save a load. 1.127 + ld_ptr(scan_temp, itableOffsetEntry::interface_offset_in_bytes(), method_result); 1.128 + 1.129 + // Check that this entry is non-null. A null entry means that 1.130 + // the receiver class doesn't implement the interface, and wasn't the 1.131 + // same as when the caller was compiled. 1.132 + bpr(Assembler::rc_z, false, Assembler::pn, method_result, L_no_such_interface); 1.133 + delayed()->cmp(method_result, intf_klass); 1.134 + 1.135 + if (peel) { 1.136 + brx(Assembler::equal, false, Assembler::pt, found_method); 1.137 + } else { 1.138 + brx(Assembler::notEqual, false, Assembler::pn, search); 1.139 + // (invert the test to fall through to found_method...) 1.140 + } 1.141 + delayed()->add(scan_temp, scan_step, scan_temp); 1.142 + 1.143 + if (!peel) break; 1.144 + 1.145 + bind(search); 1.146 + } 1.147 + 1.148 + bind(found_method); 1.149 + 1.150 + // Got a hit. 1.151 + int ito_offset = itableOffsetEntry::offset_offset_in_bytes(); 1.152 + // scan_temp[-scan_step] points to the vtable offset we need 1.153 + ito_offset -= scan_step; 1.154 + lduw(scan_temp, ito_offset, scan_temp); 1.155 + ld_ptr(recv_klass, scan_temp, method_result); 1.156 +} 1.157 + 1.158 + 1.159 void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, 1.160 Register temp_reg, 1.161 Label& done, Label* slow_case, 1.162 @@ -4057,6 +4209,24 @@ 1.163 card_table_write(bs->byte_map_base, tmp, store_addr); 1.164 } 1.165 1.166 +// Loading values by size and signed-ness 1.167 +void MacroAssembler::load_sized_value(Register s1, RegisterConstant s2, Register d, 1.168 + int size_in_bytes, bool is_signed) { 1.169 + switch (size_in_bytes ^ (is_signed ? -1 : 0)) { 1.170 + case ~8: // fall through: 1.171 + case 8: ld_long( s1, s2, d ); break; 1.172 + case ~4: ldsw( s1, s2, d ); break; 1.173 + case 4: lduw( s1, s2, d ); break; 1.174 + case ~2: ldsh( s1, s2, d ); break; 1.175 + case 2: lduh( s1, s2, d ); break; 1.176 + case ~1: ldsb( s1, s2, d ); break; 1.177 + case 1: ldub( s1, s2, d ); break; 1.178 + default: ShouldNotReachHere(); 1.179 + } 1.180 +} 1.181 + 1.182 + 1.183 + 1.184 void MacroAssembler::load_klass(Register src_oop, Register klass) { 1.185 // The number of bytes in this code is used by 1.186 // MachCallDynamicJavaNode::ret_addr_offset()
2.1 --- a/src/cpu/sparc/vm/assembler_sparc.hpp Mon Mar 09 11:32:57 2009 -0400 2.2 +++ b/src/cpu/sparc/vm/assembler_sparc.hpp Tue Mar 10 08:52:16 2009 -0700 2.3 @@ -384,6 +384,12 @@ 2.4 2.5 inline bool is_simm13(int offset = 0); // check disp+offset for overflow 2.6 2.7 + Address plus_disp(int disp) const { // bump disp by a small amount 2.8 + Address a = (*this); 2.9 + a._disp += disp; 2.10 + return a; 2.11 + } 2.12 + 2.13 Address split_disp() const { // deal with disp overflow 2.14 Address a = (*this); 2.15 int hi_disp = _disp & ~0x3ff; 2.16 @@ -1082,6 +1088,7 @@ 2.17 inline void add( Register s1, Register s2, Register d ); 2.18 inline void add( Register s1, int simm13a, Register d, relocInfo::relocType rtype = relocInfo::none); 2.19 inline void add( Register s1, int simm13a, Register d, RelocationHolder const& rspec); 2.20 + inline void add( Register s1, RegisterConstant s2, Register d, int offset = 0); 2.21 inline void add( const Address& a, Register d, int offset = 0); 2.22 2.23 void addcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } 2.24 @@ -1298,6 +1305,16 @@ 2.25 inline void ld( const Address& a, Register d, int offset = 0 ); 2.26 inline void ldd( const Address& a, Register d, int offset = 0 ); 2.27 2.28 + inline void ldub( Register s1, RegisterConstant s2, Register d ); 2.29 + inline void ldsb( Register s1, RegisterConstant s2, Register d ); 2.30 + inline void lduh( Register s1, RegisterConstant s2, Register d ); 2.31 + inline void ldsh( Register s1, RegisterConstant s2, Register d ); 2.32 + inline void lduw( Register s1, RegisterConstant s2, Register d ); 2.33 + inline void ldsw( Register s1, RegisterConstant s2, Register d ); 2.34 + inline void ldx( Register s1, RegisterConstant s2, Register d ); 2.35 + inline void ld( Register s1, RegisterConstant s2, Register d ); 2.36 + inline void ldd( Register s1, RegisterConstant s2, Register d ); 2.37 + 2.38 // pp 177 2.39 2.40 void ldsba( Register s1, Register s2, int ia, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldsb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 2.41 @@ -1518,6 +1535,13 @@ 2.42 inline void st( Register d, const Address& a, int offset = 0 ); 2.43 inline void std( Register d, const Address& a, int offset = 0 ); 2.44 2.45 + inline void stb( Register d, Register s1, RegisterConstant s2 ); 2.46 + inline void sth( Register d, Register s1, RegisterConstant s2 ); 2.47 + inline void stw( Register d, Register s1, RegisterConstant s2 ); 2.48 + inline void stx( Register d, Register s1, RegisterConstant s2 ); 2.49 + inline void std( Register d, Register s1, RegisterConstant s2 ); 2.50 + inline void st( Register d, Register s1, RegisterConstant s2 ); 2.51 + 2.52 // pp 177 2.53 2.54 void stba( Register d, Register s1, Register s2, int ia ) { emit_long( op(ldst_op) | rd(d) | op3(stb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } 2.55 @@ -1835,6 +1859,7 @@ 2.56 // Functions for isolating 64 bit shifts for LP64 2.57 inline void sll_ptr( Register s1, Register s2, Register d ); 2.58 inline void sll_ptr( Register s1, int imm6a, Register d ); 2.59 + inline void sll_ptr( Register s1, RegisterConstant s2, Register d ); 2.60 inline void srl_ptr( Register s1, Register s2, Register d ); 2.61 inline void srl_ptr( Register s1, int imm6a, Register d ); 2.62 2.63 @@ -1940,20 +1965,47 @@ 2.64 // st_ptr will perform st for 32 bit VM's and stx for 64 bit VM's 2.65 inline void ld_ptr( Register s1, Register s2, Register d ); 2.66 inline void ld_ptr( Register s1, int simm13a, Register d); 2.67 + inline void ld_ptr( Register s1, RegisterConstant s2, Register d ); 2.68 inline void ld_ptr( const Address& a, Register d, int offset = 0 ); 2.69 inline void st_ptr( Register d, Register s1, Register s2 ); 2.70 inline void st_ptr( Register d, Register s1, int simm13a); 2.71 + inline void st_ptr( Register d, Register s1, RegisterConstant s2 ); 2.72 inline void st_ptr( Register d, const Address& a, int offset = 0 ); 2.73 2.74 // ld_long will perform ld for 32 bit VM's and ldx for 64 bit VM's 2.75 // st_long will perform st for 32 bit VM's and stx for 64 bit VM's 2.76 inline void ld_long( Register s1, Register s2, Register d ); 2.77 inline void ld_long( Register s1, int simm13a, Register d ); 2.78 + inline void ld_long( Register s1, RegisterConstant s2, Register d ); 2.79 inline void ld_long( const Address& a, Register d, int offset = 0 ); 2.80 inline void st_long( Register d, Register s1, Register s2 ); 2.81 inline void st_long( Register d, Register s1, int simm13a ); 2.82 + inline void st_long( Register d, Register s1, RegisterConstant s2 ); 2.83 inline void st_long( Register d, const Address& a, int offset = 0 ); 2.84 2.85 + // Loading values by size and signed-ness 2.86 + void load_sized_value(Register s1, RegisterConstant s2, Register d, 2.87 + int size_in_bytes, bool is_signed); 2.88 + 2.89 + // Helpers for address formation. 2.90 + // They update the dest in place, whether it is a register or constant. 2.91 + // They emit no code at all if src is a constant zero. 2.92 + // If dest is a constant and src is a register, the temp argument 2.93 + // is required, and becomes the result. 2.94 + // If dest is a register and src is a non-simm13 constant, 2.95 + // the temp argument is required, and is used to materialize the constant. 2.96 + void regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src, 2.97 + Register temp = noreg ); 2.98 + void regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src, 2.99 + Register temp = noreg ); 2.100 + RegisterConstant ensure_rs2(RegisterConstant rs2, Register sethi_temp) { 2.101 + guarantee(sethi_temp != noreg, "constant offset overflow"); 2.102 + if (is_simm13(rs2.constant_or_zero())) 2.103 + return rs2; // register or short constant 2.104 + set(rs2.as_constant(), sethi_temp); 2.105 + return sethi_temp; 2.106 + } 2.107 + 2.108 // -------------------------------------------------- 2.109 2.110 public: 2.111 @@ -2267,6 +2319,14 @@ 2.112 ); 2.113 void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); 2.114 2.115 + // interface method calling 2.116 + void lookup_interface_method(Register recv_klass, 2.117 + Register intf_klass, 2.118 + RegisterConstant itable_index, 2.119 + Register method_result, 2.120 + Register temp_reg, Register temp2_reg, 2.121 + Label& no_such_interface); 2.122 + 2.123 // Stack overflow checking 2.124 2.125 // Note: this clobbers G3_scratch 2.126 @@ -2281,6 +2341,8 @@ 2.127 // stack overflow + shadow pages. Clobbers tsp and scratch registers. 2.128 void bang_stack_size(Register Rsize, Register Rtsp, Register Rscratch); 2.129 2.130 + virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr, Register tmp, int offset); 2.131 + 2.132 void verify_tlab(); 2.133 2.134 Condition negate_condition(Condition cond);
3.1 --- a/src/cpu/sparc/vm/assembler_sparc.inline.hpp Mon Mar 09 11:32:57 2009 -0400 3.2 +++ b/src/cpu/sparc/vm/assembler_sparc.inline.hpp Tue Mar 10 08:52:16 2009 -0700 3.3 @@ -143,6 +143,49 @@ 3.4 inline void Assembler::ld( Register s1, int simm13a, Register d) { lduw( s1, simm13a, d); } 3.5 #endif 3.6 3.7 +inline void Assembler::ldub( Register s1, RegisterConstant s2, Register d) { 3.8 + if (s2.is_register()) ldsb(s1, s2.as_register(), d); 3.9 + else ldsb(s1, s2.as_constant(), d); 3.10 +} 3.11 +inline void Assembler::ldsb( Register s1, RegisterConstant s2, Register d) { 3.12 + if (s2.is_register()) ldsb(s1, s2.as_register(), d); 3.13 + else ldsb(s1, s2.as_constant(), d); 3.14 +} 3.15 +inline void Assembler::lduh( Register s1, RegisterConstant s2, Register d) { 3.16 + if (s2.is_register()) ldsh(s1, s2.as_register(), d); 3.17 + else ldsh(s1, s2.as_constant(), d); 3.18 +} 3.19 +inline void Assembler::ldsh( Register s1, RegisterConstant s2, Register d) { 3.20 + if (s2.is_register()) ldsh(s1, s2.as_register(), d); 3.21 + else ldsh(s1, s2.as_constant(), d); 3.22 +} 3.23 +inline void Assembler::lduw( Register s1, RegisterConstant s2, Register d) { 3.24 + if (s2.is_register()) ldsw(s1, s2.as_register(), d); 3.25 + else ldsw(s1, s2.as_constant(), d); 3.26 +} 3.27 +inline void Assembler::ldsw( Register s1, RegisterConstant s2, Register d) { 3.28 + if (s2.is_register()) ldsw(s1, s2.as_register(), d); 3.29 + else ldsw(s1, s2.as_constant(), d); 3.30 +} 3.31 +inline void Assembler::ldx( Register s1, RegisterConstant s2, Register d) { 3.32 + if (s2.is_register()) ldx(s1, s2.as_register(), d); 3.33 + else ldx(s1, s2.as_constant(), d); 3.34 +} 3.35 +inline void Assembler::ld( Register s1, RegisterConstant s2, Register d) { 3.36 + if (s2.is_register()) ld(s1, s2.as_register(), d); 3.37 + else ld(s1, s2.as_constant(), d); 3.38 +} 3.39 +inline void Assembler::ldd( Register s1, RegisterConstant s2, Register d) { 3.40 + if (s2.is_register()) ldd(s1, s2.as_register(), d); 3.41 + else ldd(s1, s2.as_constant(), d); 3.42 +} 3.43 + 3.44 +// form effective addresses this way: 3.45 +inline void Assembler::add( Register s1, RegisterConstant s2, Register d, int offset) { 3.46 + if (s2.is_register()) add(s1, s2.as_register(), d); 3.47 + else { add(s1, s2.as_constant() + offset, d); offset = 0; } 3.48 + if (offset != 0) add(d, offset, d); 3.49 +} 3.50 3.51 inline void Assembler::ld( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ld( a.base(), a.disp() + offset, d ); } 3.52 inline void Assembler::ldsb( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ldsb( a.base(), a.disp() + offset, d ); } 3.53 @@ -200,6 +243,27 @@ 3.54 inline void Assembler::st( Register d, Register s1, Register s2) { stw(d, s1, s2); } 3.55 inline void Assembler::st( Register d, Register s1, int simm13a) { stw(d, s1, simm13a); } 3.56 3.57 +inline void Assembler::stb( Register d, Register s1, RegisterConstant s2) { 3.58 + if (s2.is_register()) stb(d, s1, s2.as_register()); 3.59 + else stb(d, s1, s2.as_constant()); 3.60 +} 3.61 +inline void Assembler::sth( Register d, Register s1, RegisterConstant s2) { 3.62 + if (s2.is_register()) sth(d, s1, s2.as_register()); 3.63 + else sth(d, s1, s2.as_constant()); 3.64 +} 3.65 +inline void Assembler::stx( Register d, Register s1, RegisterConstant s2) { 3.66 + if (s2.is_register()) stx(d, s1, s2.as_register()); 3.67 + else stx(d, s1, s2.as_constant()); 3.68 +} 3.69 +inline void Assembler::std( Register d, Register s1, RegisterConstant s2) { 3.70 + if (s2.is_register()) std(d, s1, s2.as_register()); 3.71 + else std(d, s1, s2.as_constant()); 3.72 +} 3.73 +inline void Assembler::st( Register d, Register s1, RegisterConstant s2) { 3.74 + if (s2.is_register()) st(d, s1, s2.as_register()); 3.75 + else st(d, s1, s2.as_constant()); 3.76 +} 3.77 + 3.78 inline void Assembler::stb( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); stb( d, a.base(), a.disp() + offset); } 3.79 inline void Assembler::sth( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); sth( d, a.base(), a.disp() + offset); } 3.80 inline void Assembler::stw( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); stw( d, a.base(), a.disp() + offset); } 3.81 @@ -244,6 +308,14 @@ 3.82 #endif 3.83 } 3.84 3.85 +inline void MacroAssembler::ld_ptr( Register s1, RegisterConstant s2, Register d ) { 3.86 +#ifdef _LP64 3.87 + Assembler::ldx( s1, s2, d); 3.88 +#else 3.89 + Assembler::ld( s1, s2, d); 3.90 +#endif 3.91 +} 3.92 + 3.93 inline void MacroAssembler::ld_ptr( const Address& a, Register d, int offset ) { 3.94 #ifdef _LP64 3.95 Assembler::ldx( a, d, offset ); 3.96 @@ -268,6 +340,14 @@ 3.97 #endif 3.98 } 3.99 3.100 +inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterConstant s2 ) { 3.101 +#ifdef _LP64 3.102 + Assembler::stx( d, s1, s2); 3.103 +#else 3.104 + Assembler::st( d, s1, s2); 3.105 +#endif 3.106 +} 3.107 + 3.108 inline void MacroAssembler::st_ptr( Register d, const Address& a, int offset) { 3.109 #ifdef _LP64 3.110 Assembler::stx( d, a, offset); 3.111 @@ -293,6 +373,14 @@ 3.112 #endif 3.113 } 3.114 3.115 +inline void MacroAssembler::ld_long( Register s1, RegisterConstant s2, Register d ) { 3.116 +#ifdef _LP64 3.117 + Assembler::ldx(s1, s2, d); 3.118 +#else 3.119 + Assembler::ldd(s1, s2, d); 3.120 +#endif 3.121 +} 3.122 + 3.123 inline void MacroAssembler::ld_long( const Address& a, Register d, int offset ) { 3.124 #ifdef _LP64 3.125 Assembler::ldx(a, d, offset ); 3.126 @@ -317,6 +405,14 @@ 3.127 #endif 3.128 } 3.129 3.130 +inline void MacroAssembler::st_long( Register d, Register s1, RegisterConstant s2 ) { 3.131 +#ifdef _LP64 3.132 + Assembler::stx(d, s1, s2); 3.133 +#else 3.134 + Assembler::std(d, s1, s2); 3.135 +#endif 3.136 +} 3.137 + 3.138 inline void MacroAssembler::st_long( Register d, const Address& a, int offset ) { 3.139 #ifdef _LP64 3.140 Assembler::stx(d, a, offset); 3.141 @@ -359,6 +455,11 @@ 3.142 #endif 3.143 } 3.144 3.145 +inline void MacroAssembler::sll_ptr( Register s1, RegisterConstant s2, Register d ) { 3.146 + if (s2.is_register()) sll_ptr(s1, s2.as_register(), d); 3.147 + else sll_ptr(s1, s2.as_constant(), d); 3.148 +} 3.149 + 3.150 // Use the right branch for the platform 3.151 3.152 inline void MacroAssembler::br( Condition c, bool a, Predict p, address d, relocInfo::relocType rt ) {
4.1 --- a/src/cpu/sparc/vm/sparc.ad Mon Mar 09 11:32:57 2009 -0400 4.2 +++ b/src/cpu/sparc/vm/sparc.ad Tue Mar 10 08:52:16 2009 -0700 4.3 @@ -1,5 +1,5 @@ 4.4 // 4.5 -// Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved. 4.6 +// Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. 4.7 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.8 // 4.9 // This code is free software; you can redistribute it and/or modify it 4.10 @@ -5286,55 +5286,91 @@ 4.11 ins_cost(MEMORY_REF_COST); 4.12 4.13 size(4); 4.14 - format %{ "LDSB $mem,$dst" %} 4.15 + format %{ "LDSB $mem,$dst\t! byte" %} 4.16 opcode(Assembler::ldsb_op3); 4.17 ins_encode(simple_form3_mem_reg( mem, dst ) ); 4.18 ins_pipe(iload_mask_mem); 4.19 %} 4.20 4.21 -// Load Byte (8bit UNsigned) into an int reg 4.22 -instruct loadUB(iRegI dst, memory mem, immI_255 bytemask) %{ 4.23 - match(Set dst (AndI (LoadB mem) bytemask)); 4.24 +// Load Byte (8bit signed) into a Long Register 4.25 +instruct loadB2L(iRegL dst, memory mem) %{ 4.26 + match(Set dst (ConvI2L (LoadB mem))); 4.27 ins_cost(MEMORY_REF_COST); 4.28 4.29 size(4); 4.30 - format %{ "LDUB $mem,$dst" %} 4.31 + format %{ "LDSB $mem,$dst\t! byte -> long" %} 4.32 + opcode(Assembler::ldsb_op3); 4.33 + ins_encode(simple_form3_mem_reg( mem, dst ) ); 4.34 + ins_pipe(iload_mask_mem); 4.35 +%} 4.36 + 4.37 +// Load Unsigned Byte (8bit UNsigned) into an int reg 4.38 +instruct loadUB(iRegI dst, memory mem) %{ 4.39 + match(Set dst (LoadUB mem)); 4.40 + ins_cost(MEMORY_REF_COST); 4.41 + 4.42 + size(4); 4.43 + format %{ "LDUB $mem,$dst\t! ubyte" %} 4.44 opcode(Assembler::ldub_op3); 4.45 ins_encode(simple_form3_mem_reg( mem, dst ) ); 4.46 ins_pipe(iload_mask_mem); 4.47 %} 4.48 4.49 -// Load Byte (8bit UNsigned) into a Long Register 4.50 -instruct loadUBL(iRegL dst, memory mem, immL_FF bytemask) %{ 4.51 - match(Set dst (AndL (ConvI2L (LoadB mem)) bytemask)); 4.52 +// Load Unsigned Byte (8bit UNsigned) into a Long Register 4.53 +instruct loadUB2L(iRegL dst, memory mem) %{ 4.54 + match(Set dst (ConvI2L (LoadUB mem))); 4.55 ins_cost(MEMORY_REF_COST); 4.56 4.57 size(4); 4.58 - format %{ "LDUB $mem,$dst" %} 4.59 + format %{ "LDUB $mem,$dst\t! ubyte -> long" %} 4.60 opcode(Assembler::ldub_op3); 4.61 ins_encode(simple_form3_mem_reg( mem, dst ) ); 4.62 ins_pipe(iload_mask_mem); 4.63 %} 4.64 4.65 -// Load Unsigned Short/Char (16bit UNsigned) into a Long Register 4.66 -instruct loadUS2L(iRegL dst, memory mem, immL_FFFF bytemask) %{ 4.67 - match(Set dst (AndL (ConvI2L (LoadUS mem)) bytemask)); 4.68 +// Load Short (16bit signed) 4.69 +instruct loadS(iRegI dst, memory mem) %{ 4.70 + match(Set dst (LoadS mem)); 4.71 ins_cost(MEMORY_REF_COST); 4.72 4.73 size(4); 4.74 - format %{ "LDUH $mem,$dst" %} 4.75 + format %{ "LDSH $mem,$dst\t! short" %} 4.76 + opcode(Assembler::ldsh_op3); 4.77 + ins_encode(simple_form3_mem_reg( mem, dst ) ); 4.78 + ins_pipe(iload_mask_mem); 4.79 +%} 4.80 + 4.81 +// Load Short (16bit signed) into a Long Register 4.82 +instruct loadS2L(iRegL dst, memory mem) %{ 4.83 + match(Set dst (ConvI2L (LoadS mem))); 4.84 + ins_cost(MEMORY_REF_COST); 4.85 + 4.86 + size(4); 4.87 + format %{ "LDSH $mem,$dst\t! short -> long" %} 4.88 + opcode(Assembler::ldsh_op3); 4.89 + ins_encode(simple_form3_mem_reg( mem, dst ) ); 4.90 + ins_pipe(iload_mask_mem); 4.91 +%} 4.92 + 4.93 +// Load Unsigned Short/Char (16bit UNsigned) 4.94 +instruct loadUS(iRegI dst, memory mem) %{ 4.95 + match(Set dst (LoadUS mem)); 4.96 + ins_cost(MEMORY_REF_COST); 4.97 + 4.98 + size(4); 4.99 + format %{ "LDUH $mem,$dst\t! ushort/char" %} 4.100 opcode(Assembler::lduh_op3); 4.101 ins_encode(simple_form3_mem_reg( mem, dst ) ); 4.102 ins_pipe(iload_mask_mem); 4.103 %} 4.104 4.105 -// Load Unsigned Short/Char (16bit unsigned) 4.106 -instruct loadUS(iRegI dst, memory mem) %{ 4.107 - match(Set dst (LoadUS mem)); 4.108 +// Load Unsigned Short/Char (16bit UNsigned) into a Long Register 4.109 +instruct loadUS2L(iRegL dst, memory mem) %{ 4.110 + match(Set dst (ConvI2L (LoadUS mem))); 4.111 ins_cost(MEMORY_REF_COST); 4.112 4.113 size(4); 4.114 - format %{ "LDUH $mem,$dst" %} 4.115 + format %{ "LDUH $mem,$dst\t! ushort/char -> long" %} 4.116 opcode(Assembler::lduh_op3); 4.117 ins_encode(simple_form3_mem_reg( mem, dst ) ); 4.118 ins_pipe(iload_mask_mem); 4.119 @@ -5344,9 +5380,33 @@ 4.120 instruct loadI(iRegI dst, memory mem) %{ 4.121 match(Set dst (LoadI mem)); 4.122 ins_cost(MEMORY_REF_COST); 4.123 - size(4); 4.124 - 4.125 - format %{ "LDUW $mem,$dst" %} 4.126 + 4.127 + size(4); 4.128 + format %{ "LDUW $mem,$dst\t! int" %} 4.129 + opcode(Assembler::lduw_op3); 4.130 + ins_encode(simple_form3_mem_reg( mem, dst ) ); 4.131 + ins_pipe(iload_mem); 4.132 +%} 4.133 + 4.134 +// Load Integer into a Long Register 4.135 +instruct loadI2L(iRegL dst, memory mem) %{ 4.136 + match(Set dst (ConvI2L (LoadI mem))); 4.137 + ins_cost(MEMORY_REF_COST); 4.138 + 4.139 + size(4); 4.140 + format %{ "LDSW $mem,$dst\t! int -> long" %} 4.141 + opcode(Assembler::ldsw_op3); 4.142 + ins_encode(simple_form3_mem_reg( mem, dst ) ); 4.143 + ins_pipe(iload_mem); 4.144 +%} 4.145 + 4.146 +// Load Unsigned Integer into a Long Register 4.147 +instruct loadUI2L(iRegL dst, memory mem) %{ 4.148 + match(Set dst (LoadUI2L mem)); 4.149 + ins_cost(MEMORY_REF_COST); 4.150 + 4.151 + size(4); 4.152 + format %{ "LDUW $mem,$dst\t! uint -> long" %} 4.153 opcode(Assembler::lduw_op3); 4.154 ins_encode(simple_form3_mem_reg( mem, dst ) ); 4.155 ins_pipe(iload_mem); 4.156 @@ -5356,6 +5416,7 @@ 4.157 instruct loadL(iRegL dst, memory mem ) %{ 4.158 match(Set dst (LoadL mem)); 4.159 ins_cost(MEMORY_REF_COST); 4.160 + 4.161 size(4); 4.162 format %{ "LDX $mem,$dst\t! long" %} 4.163 opcode(Assembler::ldx_op3); 4.164 @@ -5471,13 +5532,11 @@ 4.165 4.166 format %{ "LDUW $mem,$dst\t! compressed ptr" %} 4.167 ins_encode %{ 4.168 - Register base = as_Register($mem$$base); 4.169 - Register index = as_Register($mem$$index); 4.170 - Register dst = $dst$$Register; 4.171 + Register index = $mem$$index$$Register; 4.172 if (index != G0) { 4.173 - __ lduw(base, index, dst); 4.174 + __ lduw($mem$$base$$Register, index, $dst$$Register); 4.175 } else { 4.176 - __ lduw(base, $mem$$disp, dst); 4.177 + __ lduw($mem$$base$$Register, $mem$$disp, $dst$$Register); 4.178 } 4.179 %} 4.180 ins_pipe(iload_mem); 4.181 @@ -5521,18 +5580,6 @@ 4.182 ins_pipe(iload_mem); 4.183 %} 4.184 4.185 -// Load Short (16bit signed) 4.186 -instruct loadS(iRegI dst, memory mem) %{ 4.187 - match(Set dst (LoadS mem)); 4.188 - ins_cost(MEMORY_REF_COST); 4.189 - 4.190 - size(4); 4.191 - format %{ "LDSH $mem,$dst" %} 4.192 - opcode(Assembler::ldsh_op3); 4.193 - ins_encode(simple_form3_mem_reg( mem, dst ) ); 4.194 - ins_pipe(iload_mask_mem); 4.195 -%} 4.196 - 4.197 // Load Double 4.198 instruct loadD(regD dst, memory mem) %{ 4.199 match(Set dst (LoadD mem));
5.1 --- a/src/cpu/sparc/vm/vtableStubs_sparc.cpp Mon Mar 09 11:32:57 2009 -0400 5.2 +++ b/src/cpu/sparc/vm/vtableStubs_sparc.cpp Tue Mar 10 08:52:16 2009 -0700 5.3 @@ -106,6 +106,15 @@ 5.4 __ delayed()->nop(); 5.5 5.6 masm->flush(); 5.7 + 5.8 + if (PrintMiscellaneous && (WizardMode || Verbose)) { 5.9 + tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d", 5.10 + vtable_index, s->entry_point(), 5.11 + (int)(s->code_end() - s->entry_point()), 5.12 + (int)(s->code_end() - __ pc())); 5.13 + } 5.14 + guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 5.15 + 5.16 s->set_exception_points(npe_addr, ame_addr); 5.17 return s; 5.18 } 5.19 @@ -113,9 +122,9 @@ 5.20 5.21 // NOTE: %%%% if any change is made to this stub make sure that the function 5.22 // pd_code_size_limit is changed to ensure the correct size for VtableStub 5.23 -VtableStub* VtableStubs::create_itable_stub(int vtable_index) { 5.24 +VtableStub* VtableStubs::create_itable_stub(int itable_index) { 5.25 const int sparc_code_length = VtableStub::pd_code_size_limit(false); 5.26 - VtableStub* s = new(sparc_code_length) VtableStub(false, vtable_index); 5.27 + VtableStub* s = new(sparc_code_length) VtableStub(false, itable_index); 5.28 ResourceMark rm; 5.29 CodeBuffer cb(s->entry_point(), sparc_code_length); 5.30 MacroAssembler* masm = new MacroAssembler(&cb); 5.31 @@ -139,7 +148,6 @@ 5.32 // are passed in the %o registers. Instead, longs are passed in G1 and G4 5.33 // and so those registers are not available here. 5.34 __ save(SP,-frame::register_save_words*wordSize,SP); 5.35 - Register I0_receiver = I0; // Location of receiver after save 5.36 5.37 #ifndef PRODUCT 5.38 if (CountCompiledCalls) { 5.39 @@ -151,63 +159,31 @@ 5.40 } 5.41 #endif /* PRODUCT */ 5.42 5.43 - // load start of itable entries into L0 register 5.44 - const int base = instanceKlass::vtable_start_offset() * wordSize; 5.45 - __ ld(Address(G3_klassOop, 0, instanceKlass::vtable_length_offset() * wordSize), L0); 5.46 + Label throw_icce; 5.47 5.48 - // %%% Could store the aligned, prescaled offset in the klassoop. 5.49 - __ sll(L0, exact_log2(vtableEntry::size() * wordSize), L0); 5.50 - // see code for instanceKlass::start_of_itable! 5.51 - const int vtable_alignment = align_object_offset(1); 5.52 - assert(vtable_alignment == 1 || vtable_alignment == 2, ""); 5.53 - const int odd_bit = vtableEntry::size() * wordSize; 5.54 - if (vtable_alignment == 2) { 5.55 - __ and3(L0, odd_bit, L1); // isolate the odd bit 5.56 - } 5.57 - __ add(G3_klassOop, L0, L0); 5.58 - if (vtable_alignment == 2) { 5.59 - __ add(L0, L1, L0); // double the odd bit, to align up 5.60 - } 5.61 - 5.62 - // Loop over all itable entries until desired interfaceOop (G5_interface) found 5.63 - __ bind(search); 5.64 - 5.65 - // %%%% Could load both offset and interface in one ldx, if they were 5.66 - // in the opposite order. This would save a load. 5.67 - __ ld_ptr(L0, base + itableOffsetEntry::interface_offset_in_bytes(), L1); 5.68 - 5.69 - // If the entry is NULL then we've reached the end of the table 5.70 - // without finding the expected interface, so throw an exception 5.71 - Label throw_icce; 5.72 - __ bpr(Assembler::rc_z, false, Assembler::pn, L1, throw_icce); 5.73 - __ delayed()->cmp(G5_interface, L1); 5.74 - __ brx(Assembler::notEqual, true, Assembler::pn, search); 5.75 - __ delayed()->add(L0, itableOffsetEntry::size() * wordSize, L0); 5.76 - 5.77 - // entry found and L0 points to it, move offset of vtable for interface into L0 5.78 - __ ld(L0, base + itableOffsetEntry::offset_offset_in_bytes(), L0); 5.79 - 5.80 - // Compute itableMethodEntry and get methodOop(G5_method) and entrypoint(L0) for compiler 5.81 - const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + itableMethodEntry::method_offset_in_bytes(); 5.82 - __ add(G3_klassOop, L0, L1); 5.83 - __ ld_ptr(L1, method_offset, G5_method); 5.84 + Register L5_method = L5; 5.85 + __ lookup_interface_method(// inputs: rec. class, interface, itable index 5.86 + G3_klassOop, G5_interface, itable_index, 5.87 + // outputs: method, scan temp. reg 5.88 + L5_method, L2, L3, 5.89 + throw_icce); 5.90 5.91 #ifndef PRODUCT 5.92 if (DebugVtables) { 5.93 Label L01; 5.94 - __ ld_ptr(L1, method_offset, G5_method); 5.95 - __ bpr(Assembler::rc_nz, false, Assembler::pt, G5_method, L01); 5.96 + __ bpr(Assembler::rc_nz, false, Assembler::pt, L5_method, L01); 5.97 __ delayed()->nop(); 5.98 __ stop("methodOop is null"); 5.99 __ bind(L01); 5.100 - __ verify_oop(G5_method); 5.101 + __ verify_oop(L5_method); 5.102 } 5.103 #endif 5.104 5.105 // If the following load is through a NULL pointer, we'll take an OS 5.106 // exception that should translate into an AbstractMethodError. We need the 5.107 // window count to be correct at that time. 5.108 - __ restore(); // Restore registers BEFORE the AME point 5.109 + __ restore(L5_method, 0, G5_method); 5.110 + // Restore registers *before* the AME point. 5.111 5.112 address ame_addr = __ pc(); // if the vtable entry is null, the method is abstract 5.113 __ ld_ptr(G5_method, in_bytes(methodOopDesc::from_compiled_offset()), G3_scratch); 5.114 @@ -225,6 +201,12 @@ 5.115 5.116 masm->flush(); 5.117 5.118 + if (PrintMiscellaneous && (WizardMode || Verbose)) { 5.119 + tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d", 5.120 + itable_index, s->entry_point(), 5.121 + (int)(s->code_end() - s->entry_point()), 5.122 + (int)(s->code_end() - __ pc())); 5.123 + } 5.124 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 5.125 5.126 s->set_exception_points(npe_addr, ame_addr); 5.127 @@ -243,8 +225,7 @@ 5.128 (UseCompressedOops ? 2*BytesPerInstWord : 0); 5.129 return basic + slop; 5.130 } else { 5.131 - // save, ld, ld, sll, and, add, add, ld, cmp, br, add, ld, add, ld, ld, jmp, restore, sethi, jmpl, restore 5.132 - const int basic = (20 LP64_ONLY(+ 6)) * BytesPerInstWord + 5.133 + const int basic = (28 LP64_ONLY(+ 6)) * BytesPerInstWord + 5.134 // shift;add for load_klass 5.135 (UseCompressedOops ? 2*BytesPerInstWord : 0); 5.136 return (basic + slop);
6.1 --- a/src/cpu/x86/vm/assembler_x86.cpp Mon Mar 09 11:32:57 2009 -0400 6.2 +++ b/src/cpu/x86/vm/assembler_x86.cpp Tue Mar 10 08:52:16 2009 -0700 6.3 @@ -1,5 +1,5 @@ 6.4 /* 6.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 6.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 6.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.8 * 6.9 * This code is free software; you can redistribute it and/or modify it 6.10 @@ -129,13 +129,19 @@ 6.11 // Convert the raw encoding form into the form expected by the constructor for 6.12 // Address. An index of 4 (rsp) corresponds to having no index, so convert 6.13 // that to noreg for the Address constructor. 6.14 -Address Address::make_raw(int base, int index, int scale, int disp) { 6.15 +Address Address::make_raw(int base, int index, int scale, int disp, bool disp_is_oop) { 6.16 + RelocationHolder rspec; 6.17 + if (disp_is_oop) { 6.18 + rspec = Relocation::spec_simple(relocInfo::oop_type); 6.19 + } 6.20 bool valid_index = index != rsp->encoding(); 6.21 if (valid_index) { 6.22 Address madr(as_Register(base), as_Register(index), (Address::ScaleFactor)scale, in_ByteSize(disp)); 6.23 + madr._rspec = rspec; 6.24 return madr; 6.25 } else { 6.26 Address madr(as_Register(base), noreg, Address::no_scale, in_ByteSize(disp)); 6.27 + madr._rspec = rspec; 6.28 return madr; 6.29 } 6.30 } 6.31 @@ -3892,6 +3898,21 @@ 6.32 emit_operand(src, dst); 6.33 } 6.34 6.35 +void Assembler::movsbq(Register dst, Address src) { 6.36 + InstructionMark im(this); 6.37 + prefixq(src, dst); 6.38 + emit_byte(0x0F); 6.39 + emit_byte(0xBE); 6.40 + emit_operand(dst, src); 6.41 +} 6.42 + 6.43 +void Assembler::movsbq(Register dst, Register src) { 6.44 + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); 6.45 + emit_byte(0x0F); 6.46 + emit_byte(0xBE); 6.47 + emit_byte(0xC0 | encode); 6.48 +} 6.49 + 6.50 void Assembler::movslq(Register dst, int32_t imm32) { 6.51 // dbx shows movslq(rcx, 3) as movq $0x0000000049000000,(%rbx) 6.52 // and movslq(r8, 3); as movl $0x0000000048000000,(%rbx) 6.53 @@ -3925,6 +3946,51 @@ 6.54 emit_byte(0xC0 | encode); 6.55 } 6.56 6.57 +void Assembler::movswq(Register dst, Address src) { 6.58 + InstructionMark im(this); 6.59 + prefixq(src, dst); 6.60 + emit_byte(0x0F); 6.61 + emit_byte(0xBF); 6.62 + emit_operand(dst, src); 6.63 +} 6.64 + 6.65 +void Assembler::movswq(Register dst, Register src) { 6.66 + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); 6.67 + emit_byte(0x0F); 6.68 + emit_byte(0xBF); 6.69 + emit_byte(0xC0 | encode); 6.70 +} 6.71 + 6.72 +void Assembler::movzbq(Register dst, Address src) { 6.73 + InstructionMark im(this); 6.74 + prefixq(src, dst); 6.75 + emit_byte(0x0F); 6.76 + emit_byte(0xB6); 6.77 + emit_operand(dst, src); 6.78 +} 6.79 + 6.80 +void Assembler::movzbq(Register dst, Register src) { 6.81 + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); 6.82 + emit_byte(0x0F); 6.83 + emit_byte(0xB6); 6.84 + emit_byte(0xC0 | encode); 6.85 +} 6.86 + 6.87 +void Assembler::movzwq(Register dst, Address src) { 6.88 + InstructionMark im(this); 6.89 + prefixq(src, dst); 6.90 + emit_byte(0x0F); 6.91 + emit_byte(0xB7); 6.92 + emit_operand(dst, src); 6.93 +} 6.94 + 6.95 +void Assembler::movzwq(Register dst, Register src) { 6.96 + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); 6.97 + emit_byte(0x0F); 6.98 + emit_byte(0xB7); 6.99 + emit_byte(0xC0 | encode); 6.100 +} 6.101 + 6.102 void Assembler::negq(Register dst) { 6.103 int encode = prefixq_and_encode(dst->encoding()); 6.104 emit_byte(0xF7); 6.105 @@ -6197,8 +6263,11 @@ 6.106 return off; 6.107 } 6.108 6.109 -// word => int32 which seems bad for 64bit 6.110 -int MacroAssembler::load_signed_word(Register dst, Address src) { 6.111 +// Note: load_signed_short used to be called load_signed_word. 6.112 +// Although the 'w' in x86 opcodes refers to the term "word" in the assembler 6.113 +// manual, which means 16 bits, that usage is found nowhere in HotSpot code. 6.114 +// The term "word" in HotSpot means a 32- or 64-bit machine word. 6.115 +int MacroAssembler::load_signed_short(Register dst, Address src) { 6.116 int off; 6.117 if (LP64_ONLY(true ||) VM_Version::is_P6()) { 6.118 // This is dubious to me since it seems safe to do a signed 16 => 64 bit 6.119 @@ -6207,7 +6276,7 @@ 6.120 off = offset(); 6.121 movswl(dst, src); // movsxw 6.122 } else { 6.123 - off = load_unsigned_word(dst, src); 6.124 + off = load_unsigned_short(dst, src); 6.125 shll(dst, 16); 6.126 sarl(dst, 16); 6.127 } 6.128 @@ -6229,7 +6298,8 @@ 6.129 return off; 6.130 } 6.131 6.132 -int MacroAssembler::load_unsigned_word(Register dst, Address src) { 6.133 +// Note: load_unsigned_short used to be called load_unsigned_word. 6.134 +int MacroAssembler::load_unsigned_short(Register dst, Address src) { 6.135 // According to Intel Doc. AP-526, "Zero-Extension of Short", p.16, 6.136 // and "3.9 Partial Register Penalties", p. 22). 6.137 int off; 6.138 @@ -6244,6 +6314,28 @@ 6.139 return off; 6.140 } 6.141 6.142 +void MacroAssembler::load_sized_value(Register dst, Address src, 6.143 + int size_in_bytes, bool is_signed) { 6.144 + switch (size_in_bytes ^ (is_signed ? -1 : 0)) { 6.145 +#ifndef _LP64 6.146 + // For case 8, caller is responsible for manually loading 6.147 + // the second word into another register. 6.148 + case ~8: // fall through: 6.149 + case 8: movl( dst, src ); break; 6.150 +#else 6.151 + case ~8: // fall through: 6.152 + case 8: movq( dst, src ); break; 6.153 +#endif 6.154 + case ~4: // fall through: 6.155 + case 4: movl( dst, src ); break; 6.156 + case ~2: load_signed_short( dst, src ); break; 6.157 + case 2: load_unsigned_short( dst, src ); break; 6.158 + case ~1: load_signed_byte( dst, src ); break; 6.159 + case 1: load_unsigned_byte( dst, src ); break; 6.160 + default: ShouldNotReachHere(); 6.161 + } 6.162 +} 6.163 + 6.164 void MacroAssembler::mov32(AddressLiteral dst, Register src) { 6.165 if (reachable(dst)) { 6.166 movl(as_Address(dst), src); 6.167 @@ -7050,6 +7142,81 @@ 6.168 } 6.169 6.170 6.171 +// Look up the method for a megamorphic invokeinterface call. 6.172 +// The target method is determined by <intf_klass, itable_index>. 6.173 +// The receiver klass is in recv_klass. 6.174 +// On success, the result will be in method_result, and execution falls through. 6.175 +// On failure, execution transfers to the given label. 6.176 +void MacroAssembler::lookup_interface_method(Register recv_klass, 6.177 + Register intf_klass, 6.178 + RegisterConstant itable_index, 6.179 + Register method_result, 6.180 + Register scan_temp, 6.181 + Label& L_no_such_interface) { 6.182 + assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); 6.183 + assert(itable_index.is_constant() || itable_index.as_register() == method_result, 6.184 + "caller must use same register for non-constant itable index as for method"); 6.185 + 6.186 + // Compute start of first itableOffsetEntry (which is at the end of the vtable) 6.187 + int vtable_base = instanceKlass::vtable_start_offset() * wordSize; 6.188 + int itentry_off = itableMethodEntry::method_offset_in_bytes(); 6.189 + int scan_step = itableOffsetEntry::size() * wordSize; 6.190 + int vte_size = vtableEntry::size() * wordSize; 6.191 + Address::ScaleFactor times_vte_scale = Address::times_ptr; 6.192 + assert(vte_size == wordSize, "else adjust times_vte_scale"); 6.193 + 6.194 + movl(scan_temp, Address(recv_klass, instanceKlass::vtable_length_offset() * wordSize)); 6.195 + 6.196 + // %%% Could store the aligned, prescaled offset in the klassoop. 6.197 + lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base)); 6.198 + if (HeapWordsPerLong > 1) { 6.199 + // Round up to align_object_offset boundary 6.200 + // see code for instanceKlass::start_of_itable! 6.201 + round_to(scan_temp, BytesPerLong); 6.202 + } 6.203 + 6.204 + // Adjust recv_klass by scaled itable_index, so we can free itable_index. 6.205 + assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); 6.206 + lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off)); 6.207 + 6.208 + // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { 6.209 + // if (scan->interface() == intf) { 6.210 + // result = (klass + scan->offset() + itable_index); 6.211 + // } 6.212 + // } 6.213 + Label search, found_method; 6.214 + 6.215 + for (int peel = 1; peel >= 0; peel--) { 6.216 + movptr(method_result, Address(scan_temp, itableOffsetEntry::interface_offset_in_bytes())); 6.217 + cmpptr(intf_klass, method_result); 6.218 + 6.219 + if (peel) { 6.220 + jccb(Assembler::equal, found_method); 6.221 + } else { 6.222 + jccb(Assembler::notEqual, search); 6.223 + // (invert the test to fall through to found_method...) 6.224 + } 6.225 + 6.226 + if (!peel) break; 6.227 + 6.228 + bind(search); 6.229 + 6.230 + // Check that the previous entry is non-null. A null entry means that 6.231 + // the receiver class doesn't implement the interface, and wasn't the 6.232 + // same as when the caller was compiled. 6.233 + testptr(method_result, method_result); 6.234 + jcc(Assembler::zero, L_no_such_interface); 6.235 + addptr(scan_temp, scan_step); 6.236 + } 6.237 + 6.238 + bind(found_method); 6.239 + 6.240 + // Got a hit. 6.241 + movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes())); 6.242 + movptr(method_result, Address(recv_klass, scan_temp, Address::times_1)); 6.243 +} 6.244 + 6.245 + 6.246 void MacroAssembler::ucomisd(XMMRegister dst, AddressLiteral src) { 6.247 ucomisd(dst, as_Address(src)); 6.248 } 6.249 @@ -7095,6 +7262,31 @@ 6.250 } 6.251 6.252 6.253 +RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr, 6.254 + Register tmp, 6.255 + int offset) { 6.256 + intptr_t value = *delayed_value_addr; 6.257 + if (value != 0) 6.258 + return RegisterConstant(value + offset); 6.259 + 6.260 + // load indirectly to solve generation ordering problem 6.261 + movptr(tmp, ExternalAddress((address) delayed_value_addr)); 6.262 + 6.263 +#ifdef ASSERT 6.264 + Label L; 6.265 + testl(tmp, tmp); 6.266 + jccb(Assembler::notZero, L); 6.267 + hlt(); 6.268 + bind(L); 6.269 +#endif 6.270 + 6.271 + if (offset != 0) 6.272 + addptr(tmp, offset); 6.273 + 6.274 + return RegisterConstant(tmp); 6.275 +} 6.276 + 6.277 + 6.278 void MacroAssembler::verify_oop_addr(Address addr, const char* s) { 6.279 if (!VerifyOops) return; 6.280
7.1 --- a/src/cpu/x86/vm/assembler_x86.hpp Mon Mar 09 11:32:57 2009 -0400 7.2 +++ b/src/cpu/x86/vm/assembler_x86.hpp Tue Mar 10 08:52:16 2009 -0700 7.3 @@ -1,5 +1,5 @@ 7.4 /* 7.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 7.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 7.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.8 * 7.9 * This code is free software; you can redistribute it and/or modify it 7.10 @@ -153,6 +153,21 @@ 7.11 times_8 = 3, 7.12 times_ptr = LP64_ONLY(times_8) NOT_LP64(times_4) 7.13 }; 7.14 + static ScaleFactor times(int size) { 7.15 + assert(size >= 1 && size <= 8 && is_power_of_2(size), "bad scale size"); 7.16 + if (size == 8) return times_8; 7.17 + if (size == 4) return times_4; 7.18 + if (size == 2) return times_2; 7.19 + return times_1; 7.20 + } 7.21 + static int scale_size(ScaleFactor scale) { 7.22 + assert(scale != no_scale, ""); 7.23 + assert(((1 << (int)times_1) == 1 && 7.24 + (1 << (int)times_2) == 2 && 7.25 + (1 << (int)times_4) == 4 && 7.26 + (1 << (int)times_8) == 8), ""); 7.27 + return (1 << (int)scale); 7.28 + } 7.29 7.30 private: 7.31 Register _base; 7.32 @@ -197,6 +212,22 @@ 7.33 "inconsistent address"); 7.34 } 7.35 7.36 + Address(Register base, RegisterConstant index, ScaleFactor scale = times_1, int disp = 0) 7.37 + : _base (base), 7.38 + _index(index.register_or_noreg()), 7.39 + _scale(scale), 7.40 + _disp (disp + (index.constant_or_zero() * scale_size(scale))) { 7.41 + if (!index.is_register()) scale = Address::no_scale; 7.42 + assert(!_index->is_valid() == (scale == Address::no_scale), 7.43 + "inconsistent address"); 7.44 + } 7.45 + 7.46 + Address plus_disp(int disp) const { 7.47 + Address a = (*this); 7.48 + a._disp += disp; 7.49 + return a; 7.50 + } 7.51 + 7.52 // The following two overloads are used in connection with the 7.53 // ByteSize type (see sizes.hpp). They simplify the use of 7.54 // ByteSize'd arguments in assembly code. Note that their equivalent 7.55 @@ -224,6 +255,17 @@ 7.56 assert(!index->is_valid() == (scale == Address::no_scale), 7.57 "inconsistent address"); 7.58 } 7.59 + 7.60 + Address(Register base, RegisterConstant index, ScaleFactor scale, ByteSize disp) 7.61 + : _base (base), 7.62 + _index(index.register_or_noreg()), 7.63 + _scale(scale), 7.64 + _disp (in_bytes(disp) + (index.constant_or_zero() * scale_size(scale))) { 7.65 + if (!index.is_register()) scale = Address::no_scale; 7.66 + assert(!_index->is_valid() == (scale == Address::no_scale), 7.67 + "inconsistent address"); 7.68 + } 7.69 + 7.70 #endif // ASSERT 7.71 7.72 // accessors 7.73 @@ -236,11 +278,10 @@ 7.74 // Convert the raw encoding form into the form expected by the constructor for 7.75 // Address. An index of 4 (rsp) corresponds to having no index, so convert 7.76 // that to noreg for the Address constructor. 7.77 - static Address make_raw(int base, int index, int scale, int disp); 7.78 + static Address make_raw(int base, int index, int scale, int disp, bool disp_is_oop); 7.79 7.80 static Address make_array(ArrayAddress); 7.81 7.82 - 7.83 private: 7.84 bool base_needs_rex() const { 7.85 return _base != noreg && _base->encoding() >= 8; 7.86 @@ -1097,6 +1138,9 @@ 7.87 void movsbl(Register dst, Register src); 7.88 7.89 #ifdef _LP64 7.90 + void movsbq(Register dst, Address src); 7.91 + void movsbq(Register dst, Register src); 7.92 + 7.93 // Move signed 32bit immediate to 64bit extending sign 7.94 void movslq(Address dst, int32_t imm64); 7.95 void movslq(Register dst, int32_t imm64); 7.96 @@ -1109,6 +1153,11 @@ 7.97 void movswl(Register dst, Address src); 7.98 void movswl(Register dst, Register src); 7.99 7.100 +#ifdef _LP64 7.101 + void movswq(Register dst, Address src); 7.102 + void movswq(Register dst, Register src); 7.103 +#endif 7.104 + 7.105 void movw(Address dst, int imm16); 7.106 void movw(Register dst, Address src); 7.107 void movw(Address dst, Register src); 7.108 @@ -1116,9 +1165,19 @@ 7.109 void movzbl(Register dst, Address src); 7.110 void movzbl(Register dst, Register src); 7.111 7.112 +#ifdef _LP64 7.113 + void movzbq(Register dst, Address src); 7.114 + void movzbq(Register dst, Register src); 7.115 +#endif 7.116 + 7.117 void movzwl(Register dst, Address src); 7.118 void movzwl(Register dst, Register src); 7.119 7.120 +#ifdef _LP64 7.121 + void movzwq(Register dst, Address src); 7.122 + void movzwq(Register dst, Register src); 7.123 +#endif 7.124 + 7.125 void mull(Address src); 7.126 void mull(Register src); 7.127 7.128 @@ -1393,17 +1452,20 @@ 7.129 7.130 // The following 4 methods return the offset of the appropriate move instruction 7.131 7.132 - // Support for fast byte/word loading with zero extension (depending on particular CPU) 7.133 + // Support for fast byte/short loading with zero extension (depending on particular CPU) 7.134 int load_unsigned_byte(Register dst, Address src); 7.135 - int load_unsigned_word(Register dst, Address src); 7.136 - 7.137 - // Support for fast byte/word loading with sign extension (depending on particular CPU) 7.138 + int load_unsigned_short(Register dst, Address src); 7.139 + 7.140 + // Support for fast byte/short loading with sign extension (depending on particular CPU) 7.141 int load_signed_byte(Register dst, Address src); 7.142 - int load_signed_word(Register dst, Address src); 7.143 + int load_signed_short(Register dst, Address src); 7.144 7.145 // Support for sign-extension (hi:lo = extend_sign(lo)) 7.146 void extend_sign(Register hi, Register lo); 7.147 7.148 + // Loading values by size and signed-ness 7.149 + void load_sized_value(Register dst, Address src, int size_in_bytes, bool is_signed); 7.150 + 7.151 // Support for inc/dec with optimal instruction selection depending on value 7.152 7.153 void increment(Register reg, int value = 1) { LP64_ONLY(incrementq(reg, value)) NOT_LP64(incrementl(reg, value)) ; } 7.154 @@ -1721,6 +1783,14 @@ 7.155 ); 7.156 void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); 7.157 7.158 + // interface method calling 7.159 + void lookup_interface_method(Register recv_klass, 7.160 + Register intf_klass, 7.161 + RegisterConstant itable_index, 7.162 + Register method_result, 7.163 + Register scan_temp, 7.164 + Label& no_such_interface); 7.165 + 7.166 //---- 7.167 void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0 7.168 7.169 @@ -1763,6 +1833,10 @@ 7.170 // stack overflow + shadow pages. Also, clobbers tmp 7.171 void bang_stack_size(Register size, Register tmp); 7.172 7.173 + virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr, 7.174 + Register tmp, 7.175 + int offset); 7.176 + 7.177 // Support for serializing memory accesses between threads 7.178 void serialize_memory(Register thread, Register tmp); 7.179
8.1 --- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Mon Mar 09 11:32:57 2009 -0400 8.2 +++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Tue Mar 10 08:52:16 2009 -0700 8.3 @@ -554,8 +554,8 @@ 8.4 __ jcc (Assembler::zero, noLoop); 8.5 8.6 // compare first characters 8.7 - __ load_unsigned_word(rcx, Address(rdi, 0)); 8.8 - __ load_unsigned_word(rbx, Address(rsi, 0)); 8.9 + __ load_unsigned_short(rcx, Address(rdi, 0)); 8.10 + __ load_unsigned_short(rbx, Address(rsi, 0)); 8.11 __ subl(rcx, rbx); 8.12 __ jcc(Assembler::notZero, haveResult); 8.13 // starting loop 8.14 @@ -574,8 +574,8 @@ 8.15 Label loop; 8.16 __ align(wordSize); 8.17 __ bind(loop); 8.18 - __ load_unsigned_word(rcx, Address(rdi, rax, Address::times_2, 0)); 8.19 - __ load_unsigned_word(rbx, Address(rsi, rax, Address::times_2, 0)); 8.20 + __ load_unsigned_short(rcx, Address(rdi, rax, Address::times_2, 0)); 8.21 + __ load_unsigned_short(rbx, Address(rsi, rax, Address::times_2, 0)); 8.22 __ subl(rcx, rbx); 8.23 __ jcc(Assembler::notZero, haveResult); 8.24 __ increment(rax);
9.1 --- a/src/cpu/x86/vm/cppInterpreter_x86.cpp Mon Mar 09 11:32:57 2009 -0400 9.2 +++ b/src/cpu/x86/vm/cppInterpreter_x86.cpp Tue Mar 10 08:52:16 2009 -0700 9.3 @@ -513,7 +513,7 @@ 9.4 // compute full expression stack limit 9.5 9.6 const Address size_of_stack (rbx, methodOopDesc::max_stack_offset()); 9.7 - __ load_unsigned_word(rdx, size_of_stack); // get size of expression stack in words 9.8 + __ load_unsigned_short(rdx, size_of_stack); // get size of expression stack in words 9.9 __ negptr(rdx); // so we can subtract in next step 9.10 // Allocate expression stack 9.11 __ lea(rsp, Address(rsp, rdx, Address::times_ptr)); 9.12 @@ -659,7 +659,7 @@ 9.13 // Always give one monitor to allow us to start interp if sync method. 9.14 // Any additional monitors need a check when moving the expression stack 9.15 const int one_monitor = frame::interpreter_frame_monitor_size() * wordSize; 9.16 - __ load_unsigned_word(rax, size_of_stack); // get size of expression stack in words 9.17 + __ load_unsigned_short(rax, size_of_stack); // get size of expression stack in words 9.18 __ lea(rax, Address(noreg, rax, Interpreter::stackElementScale(), one_monitor)); 9.19 __ lea(rax, Address(rax, rdx, Interpreter::stackElementScale(), overhead_size)); 9.20 9.21 @@ -863,13 +863,13 @@ 9.22 __ bind(notByte); 9.23 __ cmpl(rdx, stos); 9.24 __ jcc(Assembler::notEqual, notShort); 9.25 - __ load_signed_word(rax, field_address); 9.26 + __ load_signed_short(rax, field_address); 9.27 __ jmp(xreturn_path); 9.28 9.29 __ bind(notShort); 9.30 __ cmpl(rdx, ctos); 9.31 __ jcc(Assembler::notEqual, notChar); 9.32 - __ load_unsigned_word(rax, field_address); 9.33 + __ load_unsigned_short(rax, field_address); 9.34 __ jmp(xreturn_path); 9.35 9.36 __ bind(notChar); 9.37 @@ -937,7 +937,7 @@ 9.38 const Register locals = rdi; 9.39 9.40 // get parameter size (always needed) 9.41 - __ load_unsigned_word(rcx, size_of_parameters); 9.42 + __ load_unsigned_short(rcx, size_of_parameters); 9.43 9.44 // rbx: methodOop 9.45 // rcx: size of parameters 9.46 @@ -1062,7 +1062,7 @@ 9.47 // allocate space for parameters 9.48 __ movptr(method, STATE(_method)); 9.49 __ verify_oop(method); 9.50 - __ load_unsigned_word(t, Address(method, methodOopDesc::size_of_parameters_offset())); 9.51 + __ load_unsigned_short(t, Address(method, methodOopDesc::size_of_parameters_offset())); 9.52 __ shll(t, 2); 9.53 #ifdef _LP64 9.54 __ subptr(rsp, t); 9.55 @@ -1659,11 +1659,11 @@ 9.56 // const Address monitor(rbp, frame::interpreter_frame_initial_sp_offset * wordSize - (int)sizeof(BasicObjectLock)); 9.57 9.58 // get parameter size (always needed) 9.59 - __ load_unsigned_word(rcx, size_of_parameters); 9.60 + __ load_unsigned_short(rcx, size_of_parameters); 9.61 9.62 // rbx: methodOop 9.63 // rcx: size of parameters 9.64 - __ load_unsigned_word(rdx, size_of_locals); // get size of locals in words 9.65 + __ load_unsigned_short(rdx, size_of_locals); // get size of locals in words 9.66 9.67 __ subptr(rdx, rcx); // rdx = no. of additional locals 9.68 9.69 @@ -1949,7 +1949,7 @@ 9.70 __ movptr(rbx, STATE(_result._to_call._callee)); 9.71 9.72 // callee left args on top of expression stack, remove them 9.73 - __ load_unsigned_word(rcx, Address(rbx, methodOopDesc::size_of_parameters_offset())); 9.74 + __ load_unsigned_short(rcx, Address(rbx, methodOopDesc::size_of_parameters_offset())); 9.75 __ lea(rsp, Address(rsp, rcx, Address::times_ptr)); 9.76 9.77 __ movl(rcx, Address(rbx, methodOopDesc::result_index_offset())); 9.78 @@ -2119,7 +2119,7 @@ 9.79 // Make it look like call_stub calling conventions 9.80 9.81 // Get (potential) receiver 9.82 - __ load_unsigned_word(rcx, size_of_parameters); // get size of parameters in words 9.83 + __ load_unsigned_short(rcx, size_of_parameters); // get size of parameters in words 9.84 9.85 ExternalAddress recursive(CAST_FROM_FN_PTR(address, RecursiveInterpreterActivation)); 9.86 __ pushptr(recursive.addr()); // make it look good in the debugger
10.1 --- a/src/cpu/x86/vm/interp_masm_x86_32.cpp Mon Mar 09 11:32:57 2009 -0400 10.2 +++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp Tue Mar 10 08:52:16 2009 -0700 10.3 @@ -192,7 +192,7 @@ 10.4 void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset) { 10.5 assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); 10.6 assert(cache != index, "must use different registers"); 10.7 - load_unsigned_word(index, Address(rsi, bcp_offset)); 10.8 + load_unsigned_short(index, Address(rsi, bcp_offset)); 10.9 movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize)); 10.10 assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below"); 10.11 shlptr(index, 2); // convert from field index to ConstantPoolCacheEntry index 10.12 @@ -202,7 +202,7 @@ 10.13 void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset) { 10.14 assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); 10.15 assert(cache != tmp, "must use different register"); 10.16 - load_unsigned_word(tmp, Address(rsi, bcp_offset)); 10.17 + load_unsigned_short(tmp, Address(rsi, bcp_offset)); 10.18 assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below"); 10.19 // convert from field index to ConstantPoolCacheEntry index 10.20 // and from word offset to byte offset 10.21 @@ -1031,7 +1031,7 @@ 10.22 10.23 // If the mdp is valid, it will point to a DataLayout header which is 10.24 // consistent with the bcp. The converse is highly probable also. 10.25 - load_unsigned_word(rdx, Address(rcx, in_bytes(DataLayout::bci_offset()))); 10.26 + load_unsigned_short(rdx, Address(rcx, in_bytes(DataLayout::bci_offset()))); 10.27 addptr(rdx, Address(rbx, methodOopDesc::const_offset())); 10.28 lea(rdx, Address(rdx, constMethodOopDesc::codes_offset())); 10.29 cmpptr(rdx, rsi);
11.1 --- a/src/cpu/x86/vm/interp_masm_x86_64.cpp Mon Mar 09 11:32:57 2009 -0400 11.2 +++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp Tue Mar 10 08:52:16 2009 -0700 11.3 @@ -190,7 +190,7 @@ 11.4 int bcp_offset) { 11.5 assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); 11.6 assert(cache != index, "must use different registers"); 11.7 - load_unsigned_word(index, Address(r13, bcp_offset)); 11.8 + load_unsigned_short(index, Address(r13, bcp_offset)); 11.9 movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize)); 11.10 assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below"); 11.11 // convert from field index to ConstantPoolCacheEntry index 11.12 @@ -203,7 +203,7 @@ 11.13 int bcp_offset) { 11.14 assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); 11.15 assert(cache != tmp, "must use different register"); 11.16 - load_unsigned_word(tmp, Address(r13, bcp_offset)); 11.17 + load_unsigned_short(tmp, Address(r13, bcp_offset)); 11.18 assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below"); 11.19 // convert from field index to ConstantPoolCacheEntry index 11.20 // and from word offset to byte offset 11.21 @@ -1063,8 +1063,8 @@ 11.22 11.23 // If the mdp is valid, it will point to a DataLayout header which is 11.24 // consistent with the bcp. The converse is highly probable also. 11.25 - load_unsigned_word(c_rarg2, 11.26 - Address(c_rarg3, in_bytes(DataLayout::bci_offset()))); 11.27 + load_unsigned_short(c_rarg2, 11.28 + Address(c_rarg3, in_bytes(DataLayout::bci_offset()))); 11.29 addptr(c_rarg2, Address(rbx, methodOopDesc::const_offset())); 11.30 lea(c_rarg2, Address(c_rarg2, constMethodOopDesc::codes_offset())); 11.31 cmpptr(c_rarg2, r13);
12.1 --- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Mon Mar 09 11:32:57 2009 -0400 12.2 +++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Tue Mar 10 08:52:16 2009 -0700 12.3 @@ -662,13 +662,13 @@ 12.4 __ bind(notByte); 12.5 __ cmpl(rdx, stos); 12.6 __ jcc(Assembler::notEqual, notShort); 12.7 - __ load_signed_word(rax, field_address); 12.8 + __ load_signed_short(rax, field_address); 12.9 __ jmp(xreturn_path); 12.10 12.11 __ bind(notShort); 12.12 __ cmpl(rdx, ctos); 12.13 __ jcc(Assembler::notEqual, notChar); 12.14 - __ load_unsigned_word(rax, field_address); 12.15 + __ load_unsigned_short(rax, field_address); 12.16 __ jmp(xreturn_path); 12.17 12.18 __ bind(notChar); 12.19 @@ -723,7 +723,7 @@ 12.20 const Address access_flags (rbx, methodOopDesc::access_flags_offset()); 12.21 12.22 // get parameter size (always needed) 12.23 - __ load_unsigned_word(rcx, size_of_parameters); 12.24 + __ load_unsigned_short(rcx, size_of_parameters); 12.25 12.26 // native calls don't need the stack size check since they have no expression stack 12.27 // and the arguments are already on the stack and we only add a handful of words 12.28 @@ -838,7 +838,7 @@ 12.29 // allocate space for parameters 12.30 __ get_method(method); 12.31 __ verify_oop(method); 12.32 - __ load_unsigned_word(t, Address(method, methodOopDesc::size_of_parameters_offset())); 12.33 + __ load_unsigned_short(t, Address(method, methodOopDesc::size_of_parameters_offset())); 12.34 __ shlptr(t, Interpreter::logStackElementSize()); 12.35 __ addptr(t, 2*wordSize); // allocate two more slots for JNIEnv and possible mirror 12.36 __ subptr(rsp, t); 12.37 @@ -1155,14 +1155,14 @@ 12.38 const Address access_flags (rbx, methodOopDesc::access_flags_offset()); 12.39 12.40 // get parameter size (always needed) 12.41 - __ load_unsigned_word(rcx, size_of_parameters); 12.42 + __ load_unsigned_short(rcx, size_of_parameters); 12.43 12.44 // rbx,: methodOop 12.45 // rcx: size of parameters 12.46 12.47 // rsi: sender_sp (could differ from sp+wordSize if we were called via c2i ) 12.48 12.49 - __ load_unsigned_word(rdx, size_of_locals); // get size of locals in words 12.50 + __ load_unsigned_short(rdx, size_of_locals); // get size of locals in words 12.51 __ subl(rdx, rcx); // rdx = no. of additional locals 12.52 12.53 // see if we've got enough room on the stack for locals plus overhead. 12.54 @@ -1558,7 +1558,7 @@ 12.55 // Compute size of arguments for saving when returning to deoptimized caller 12.56 __ get_method(rax); 12.57 __ verify_oop(rax); 12.58 - __ load_unsigned_word(rax, Address(rax, in_bytes(methodOopDesc::size_of_parameters_offset()))); 12.59 + __ load_unsigned_short(rax, Address(rax, in_bytes(methodOopDesc::size_of_parameters_offset()))); 12.60 __ shlptr(rax, Interpreter::logStackElementSize()); 12.61 __ restore_locals(); 12.62 __ subptr(rdi, rax);
13.1 --- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Mon Mar 09 11:32:57 2009 -0400 13.2 +++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Tue Mar 10 08:52:16 2009 -0700 13.3 @@ -650,7 +650,7 @@ 13.4 __ cmpl(rdx, stos); 13.5 __ jcc(Assembler::notEqual, notShort); 13.6 // stos 13.7 - __ load_signed_word(rax, field_address); 13.8 + __ load_signed_short(rax, field_address); 13.9 __ jmp(xreturn_path); 13.10 13.11 __ bind(notShort); 13.12 @@ -662,7 +662,7 @@ 13.13 __ bind(okay); 13.14 #endif 13.15 // ctos 13.16 - __ load_unsigned_word(rax, field_address); 13.17 + __ load_unsigned_short(rax, field_address); 13.18 13.19 __ bind(xreturn_path); 13.20 13.21 @@ -702,7 +702,7 @@ 13.22 const Address access_flags (rbx, methodOopDesc::access_flags_offset()); 13.23 13.24 // get parameter size (always needed) 13.25 - __ load_unsigned_word(rcx, size_of_parameters); 13.26 + __ load_unsigned_short(rcx, size_of_parameters); 13.27 13.28 // native calls don't need the stack size check since they have no 13.29 // expression stack and the arguments are already on the stack and 13.30 @@ -819,9 +819,9 @@ 13.31 // allocate space for parameters 13.32 __ get_method(method); 13.33 __ verify_oop(method); 13.34 - __ load_unsigned_word(t, 13.35 - Address(method, 13.36 - methodOopDesc::size_of_parameters_offset())); 13.37 + __ load_unsigned_short(t, 13.38 + Address(method, 13.39 + methodOopDesc::size_of_parameters_offset())); 13.40 __ shll(t, Interpreter::logStackElementSize()); 13.41 13.42 __ subptr(rsp, t); 13.43 @@ -1165,13 +1165,13 @@ 13.44 const Address access_flags(rbx, methodOopDesc::access_flags_offset()); 13.45 13.46 // get parameter size (always needed) 13.47 - __ load_unsigned_word(rcx, size_of_parameters); 13.48 + __ load_unsigned_short(rcx, size_of_parameters); 13.49 13.50 // rbx: methodOop 13.51 // rcx: size of parameters 13.52 // r13: sender_sp (could differ from sp+wordSize if we were called via c2i ) 13.53 13.54 - __ load_unsigned_word(rdx, size_of_locals); // get size of locals in words 13.55 + __ load_unsigned_short(rdx, size_of_locals); // get size of locals in words 13.56 __ subl(rdx, rcx); // rdx = no. of additional locals 13.57 13.58 // YYY 13.59 @@ -1583,7 +1583,7 @@ 13.60 // Compute size of arguments for saving when returning to 13.61 // deoptimized caller 13.62 __ get_method(rax); 13.63 - __ load_unsigned_word(rax, Address(rax, in_bytes(methodOopDesc:: 13.64 + __ load_unsigned_short(rax, Address(rax, in_bytes(methodOopDesc:: 13.65 size_of_parameters_offset()))); 13.66 __ shll(rax, Interpreter::logStackElementSize()); 13.67 __ restore_locals(); // XXX do we need this?
14.1 --- a/src/cpu/x86/vm/templateTable_x86_32.cpp Mon Mar 09 11:32:57 2009 -0400 14.2 +++ b/src/cpu/x86/vm/templateTable_x86_32.cpp Tue Mar 10 08:52:16 2009 -0700 14.3 @@ -296,7 +296,7 @@ 14.4 14.5 void TemplateTable::sipush() { 14.6 transition(vtos, itos); 14.7 - __ load_unsigned_word(rax, at_bcp(1)); 14.8 + __ load_unsigned_short(rax, at_bcp(1)); 14.9 __ bswapl(rax); 14.10 __ sarl(rax, 16); 14.11 } 14.12 @@ -662,7 +662,7 @@ 14.13 index_check(rdx, rax); // kills rbx, 14.14 // rax,: index 14.15 // can do better code for P5 - may want to improve this at some point 14.16 - __ load_unsigned_word(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); 14.17 + __ load_unsigned_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); 14.18 __ mov(rax, rbx); 14.19 } 14.20 14.21 @@ -677,7 +677,7 @@ 14.22 // rdx: array 14.23 index_check(rdx, rax); 14.24 // rax,: index 14.25 - __ load_unsigned_word(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); 14.26 + __ load_unsigned_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); 14.27 __ mov(rax, rbx); 14.28 } 14.29 14.30 @@ -687,7 +687,7 @@ 14.31 index_check(rdx, rax); // kills rbx, 14.32 // rax,: index 14.33 // can do better code for P5 - may want to improve this at some point 14.34 - __ load_signed_word(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_SHORT))); 14.35 + __ load_signed_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_SHORT))); 14.36 __ mov(rax, rbx); 14.37 } 14.38 14.39 @@ -2310,7 +2310,7 @@ 14.40 __ cmpl(flags, ctos ); 14.41 __ jcc(Assembler::notEqual, notChar); 14.42 14.43 - __ load_unsigned_word(rax, lo ); 14.44 + __ load_unsigned_short(rax, lo ); 14.45 __ push(ctos); 14.46 if (!is_static) { 14.47 patch_bytecode(Bytecodes::_fast_cgetfield, rcx, rbx); 14.48 @@ -2322,7 +2322,7 @@ 14.49 __ cmpl(flags, stos ); 14.50 __ jcc(Assembler::notEqual, notShort); 14.51 14.52 - __ load_signed_word(rax, lo ); 14.53 + __ load_signed_short(rax, lo ); 14.54 __ push(stos); 14.55 if (!is_static) { 14.56 patch_bytecode(Bytecodes::_fast_sgetfield, rcx, rbx); 14.57 @@ -2830,8 +2830,8 @@ 14.58 // access field 14.59 switch (bytecode()) { 14.60 case Bytecodes::_fast_bgetfield: __ movsbl(rax, lo ); break; 14.61 - case Bytecodes::_fast_sgetfield: __ load_signed_word(rax, lo ); break; 14.62 - case Bytecodes::_fast_cgetfield: __ load_unsigned_word(rax, lo ); break; 14.63 + case Bytecodes::_fast_sgetfield: __ load_signed_short(rax, lo ); break; 14.64 + case Bytecodes::_fast_cgetfield: __ load_unsigned_short(rax, lo ); break; 14.65 case Bytecodes::_fast_igetfield: __ movl(rax, lo); break; 14.66 case Bytecodes::_fast_lgetfield: __ stop("should not be rewritten"); break; 14.67 case Bytecodes::_fast_fgetfield: __ fld_s(lo); break; 14.68 @@ -3055,35 +3055,44 @@ 14.69 // profile this call 14.70 __ profile_virtual_call(rdx, rsi, rdi); 14.71 14.72 - __ mov(rdi, rdx); // Save klassOop in rdi 14.73 - 14.74 - // Compute start of first itableOffsetEntry (which is at the end of the vtable) 14.75 - const int base = instanceKlass::vtable_start_offset() * wordSize; 14.76 - assert(vtableEntry::size() * wordSize == (1 << (int)Address::times_ptr), "adjust the scaling in the code below"); 14.77 - __ movl(rsi, Address(rdx, instanceKlass::vtable_length_offset() * wordSize)); // Get length of vtable 14.78 - __ lea(rdx, Address(rdx, rsi, Address::times_4, base)); 14.79 - if (HeapWordsPerLong > 1) { 14.80 - // Round up to align_object_offset boundary 14.81 - __ round_to(rdx, BytesPerLong); 14.82 - } 14.83 - 14.84 - Label entry, search, interface_ok; 14.85 - 14.86 - __ jmpb(entry); 14.87 - __ bind(search); 14.88 - __ addptr(rdx, itableOffsetEntry::size() * wordSize); 14.89 - 14.90 - __ bind(entry); 14.91 - 14.92 - // Check that the entry is non-null. A null entry means that the receiver 14.93 - // class doesn't implement the interface, and wasn't the same as the 14.94 - // receiver class checked when the interface was resolved. 14.95 - __ push(rdx); 14.96 - __ movptr(rdx, Address(rdx, itableOffsetEntry::interface_offset_in_bytes())); 14.97 - __ testptr(rdx, rdx); 14.98 - __ jcc(Assembler::notZero, interface_ok); 14.99 + Label no_such_interface, no_such_method; 14.100 + 14.101 + __ lookup_interface_method(// inputs: rec. class, interface, itable index 14.102 + rdx, rax, rbx, 14.103 + // outputs: method, scan temp. reg 14.104 + rbx, rsi, 14.105 + no_such_interface); 14.106 + 14.107 + // rbx,: methodOop to call 14.108 + // rcx: receiver 14.109 + // Check for abstract method error 14.110 + // Note: This should be done more efficiently via a throw_abstract_method_error 14.111 + // interpreter entry point and a conditional jump to it in case of a null 14.112 + // method. 14.113 + __ testptr(rbx, rbx); 14.114 + __ jcc(Assembler::zero, no_such_method); 14.115 + 14.116 + // do the call 14.117 + // rcx: receiver 14.118 + // rbx,: methodOop 14.119 + __ jump_from_interpreted(rbx, rdx); 14.120 + __ should_not_reach_here(); 14.121 + 14.122 + // exception handling code follows... 14.123 + // note: must restore interpreter registers to canonical 14.124 + // state for exception handling to work correctly! 14.125 + 14.126 + __ bind(no_such_method); 14.127 // throw exception 14.128 - __ pop(rdx); // pop saved register first. 14.129 + __ pop(rbx); // pop return address (pushed by prepare_invoke) 14.130 + __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) 14.131 + __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) 14.132 + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); 14.133 + // the call_VM checks for exception, so we should never return here. 14.134 + __ should_not_reach_here(); 14.135 + 14.136 + __ bind(no_such_interface); 14.137 + // throw exception 14.138 __ pop(rbx); // pop return address (pushed by prepare_invoke) 14.139 __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) 14.140 __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) 14.141 @@ -3091,42 +3100,6 @@ 14.142 InterpreterRuntime::throw_IncompatibleClassChangeError)); 14.143 // the call_VM checks for exception, so we should never return here. 14.144 __ should_not_reach_here(); 14.145 - __ bind(interface_ok); 14.146 - 14.147 - __ pop(rdx); 14.148 - 14.149 - __ cmpptr(rax, Address(rdx, itableOffsetEntry::interface_offset_in_bytes())); 14.150 - __ jcc(Assembler::notEqual, search); 14.151 - 14.152 - __ movl(rdx, Address(rdx, itableOffsetEntry::offset_offset_in_bytes())); 14.153 - __ addptr(rdx, rdi); // Add offset to klassOop 14.154 - assert(itableMethodEntry::size() * wordSize == (1 << (int)Address::times_ptr), "adjust the scaling in the code below"); 14.155 - __ movptr(rbx, Address(rdx, rbx, Address::times_ptr)); 14.156 - // rbx,: methodOop to call 14.157 - // rcx: receiver 14.158 - // Check for abstract method error 14.159 - // Note: This should be done more efficiently via a throw_abstract_method_error 14.160 - // interpreter entry point and a conditional jump to it in case of a null 14.161 - // method. 14.162 - { Label L; 14.163 - __ testptr(rbx, rbx); 14.164 - __ jcc(Assembler::notZero, L); 14.165 - // throw exception 14.166 - // note: must restore interpreter registers to canonical 14.167 - // state for exception handling to work correctly! 14.168 - __ pop(rbx); // pop return address (pushed by prepare_invoke) 14.169 - __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) 14.170 - __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) 14.171 - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); 14.172 - // the call_VM checks for exception, so we should never return here. 14.173 - __ should_not_reach_here(); 14.174 - __ bind(L); 14.175 - } 14.176 - 14.177 - // do the call 14.178 - // rcx: receiver 14.179 - // rbx,: methodOop 14.180 - __ jump_from_interpreted(rbx, rdx); 14.181 } 14.182 14.183 //----------------------------------------------------------------------------------------------------
15.1 --- a/src/cpu/x86/vm/templateTable_x86_64.cpp Mon Mar 09 11:32:57 2009 -0400 15.2 +++ b/src/cpu/x86/vm/templateTable_x86_64.cpp Tue Mar 10 08:52:16 2009 -0700 15.3 @@ -307,7 +307,7 @@ 15.4 15.5 void TemplateTable::sipush() { 15.6 transition(vtos, itos); 15.7 - __ load_unsigned_word(rax, at_bcp(1)); 15.8 + __ load_unsigned_short(rax, at_bcp(1)); 15.9 __ bswapl(rax); 15.10 __ sarl(rax, 16); 15.11 } 15.12 @@ -645,10 +645,10 @@ 15.13 // eax: index 15.14 // rdx: array 15.15 index_check(rdx, rax); // kills rbx 15.16 - __ load_unsigned_word(rax, 15.17 - Address(rdx, rax, 15.18 - Address::times_2, 15.19 - arrayOopDesc::base_offset_in_bytes(T_CHAR))); 15.20 + __ load_unsigned_short(rax, 15.21 + Address(rdx, rax, 15.22 + Address::times_2, 15.23 + arrayOopDesc::base_offset_in_bytes(T_CHAR))); 15.24 } 15.25 15.26 // iload followed by caload frequent pair 15.27 @@ -663,10 +663,10 @@ 15.28 // rdx: array 15.29 __ pop_ptr(rdx); 15.30 index_check(rdx, rax); // kills rbx 15.31 - __ load_unsigned_word(rax, 15.32 - Address(rdx, rax, 15.33 - Address::times_2, 15.34 - arrayOopDesc::base_offset_in_bytes(T_CHAR))); 15.35 + __ load_unsigned_short(rax, 15.36 + Address(rdx, rax, 15.37 + Address::times_2, 15.38 + arrayOopDesc::base_offset_in_bytes(T_CHAR))); 15.39 } 15.40 15.41 void TemplateTable::saload() { 15.42 @@ -675,10 +675,10 @@ 15.43 // eax: index 15.44 // rdx: array 15.45 index_check(rdx, rax); // kills rbx 15.46 - __ load_signed_word(rax, 15.47 - Address(rdx, rax, 15.48 - Address::times_2, 15.49 - arrayOopDesc::base_offset_in_bytes(T_SHORT))); 15.50 + __ load_signed_short(rax, 15.51 + Address(rdx, rax, 15.52 + Address::times_2, 15.53 + arrayOopDesc::base_offset_in_bytes(T_SHORT))); 15.54 } 15.55 15.56 void TemplateTable::iload(int n) { 15.57 @@ -2276,7 +2276,7 @@ 15.58 __ cmpl(flags, ctos); 15.59 __ jcc(Assembler::notEqual, notChar); 15.60 // ctos 15.61 - __ load_unsigned_word(rax, field); 15.62 + __ load_unsigned_short(rax, field); 15.63 __ push(ctos); 15.64 // Rewrite bytecode to be faster 15.65 if (!is_static) { 15.66 @@ -2288,7 +2288,7 @@ 15.67 __ cmpl(flags, stos); 15.68 __ jcc(Assembler::notEqual, notShort); 15.69 // stos 15.70 - __ load_signed_word(rax, field); 15.71 + __ load_signed_short(rax, field); 15.72 __ push(stos); 15.73 // Rewrite bytecode to be faster 15.74 if (!is_static) { 15.75 @@ -2751,10 +2751,10 @@ 15.76 __ movsbl(rax, field); 15.77 break; 15.78 case Bytecodes::_fast_sgetfield: 15.79 - __ load_signed_word(rax, field); 15.80 + __ load_signed_short(rax, field); 15.81 break; 15.82 case Bytecodes::_fast_cgetfield: 15.83 - __ load_unsigned_word(rax, field); 15.84 + __ load_unsigned_short(rax, field); 15.85 break; 15.86 case Bytecodes::_fast_fgetfield: 15.87 __ movflt(xmm0, field); 15.88 @@ -3010,97 +3010,55 @@ 15.89 // profile this call 15.90 __ profile_virtual_call(rdx, r13, r14); 15.91 15.92 - __ mov(r14, rdx); // Save klassOop in r14 15.93 - 15.94 - // Compute start of first itableOffsetEntry (which is at the end of 15.95 - // the vtable) 15.96 - const int base = instanceKlass::vtable_start_offset() * wordSize; 15.97 - // Get length of vtable 15.98 - assert(vtableEntry::size() * wordSize == 8, 15.99 - "adjust the scaling in the code below"); 15.100 - __ movl(r13, Address(rdx, 15.101 - instanceKlass::vtable_length_offset() * wordSize)); 15.102 - __ lea(rdx, Address(rdx, r13, Address::times_8, base)); 15.103 - 15.104 - if (HeapWordsPerLong > 1) { 15.105 - // Round up to align_object_offset boundary 15.106 - __ round_to(rdx, BytesPerLong); 15.107 - } 15.108 - 15.109 - Label entry, search, interface_ok; 15.110 - 15.111 - __ jmpb(entry); 15.112 - __ bind(search); 15.113 - __ addptr(rdx, itableOffsetEntry::size() * wordSize); 15.114 - 15.115 - __ bind(entry); 15.116 - 15.117 - // Check that the entry is non-null. A null entry means that the 15.118 - // receiver class doesn't implement the interface, and wasn't the 15.119 - // same as the receiver class checked when the interface was 15.120 - // resolved. 15.121 - __ push(rdx); 15.122 - __ movptr(rdx, Address(rdx, itableOffsetEntry::interface_offset_in_bytes())); 15.123 - __ testptr(rdx, rdx); 15.124 - __ jcc(Assembler::notZero, interface_ok); 15.125 + Label no_such_interface, no_such_method; 15.126 + 15.127 + __ lookup_interface_method(// inputs: rec. class, interface, itable index 15.128 + rdx, rax, rbx, 15.129 + // outputs: method, scan temp. reg 15.130 + rbx, r13, 15.131 + no_such_interface); 15.132 + 15.133 + // rbx,: methodOop to call 15.134 + // rcx: receiver 15.135 + // Check for abstract method error 15.136 + // Note: This should be done more efficiently via a throw_abstract_method_error 15.137 + // interpreter entry point and a conditional jump to it in case of a null 15.138 + // method. 15.139 + __ testptr(rbx, rbx); 15.140 + __ jcc(Assembler::zero, no_such_method); 15.141 + 15.142 + // do the call 15.143 + // rcx: receiver 15.144 + // rbx,: methodOop 15.145 + __ jump_from_interpreted(rbx, rdx); 15.146 + __ should_not_reach_here(); 15.147 + 15.148 + // exception handling code follows... 15.149 + // note: must restore interpreter registers to canonical 15.150 + // state for exception handling to work correctly! 15.151 + 15.152 + __ bind(no_such_method); 15.153 // throw exception 15.154 - __ pop(rdx); // pop saved register first. 15.155 - __ pop(rbx); // pop return address (pushed by prepare_invoke) 15.156 - __ restore_bcp(); // r13 must be correct for exception handler (was 15.157 - // destroyed) 15.158 - __ restore_locals(); // make sure locals pointer is correct as well 15.159 - // (was destroyed) 15.160 + __ pop(rbx); // pop return address (pushed by prepare_invoke) 15.161 + __ restore_bcp(); // r13 must be correct for exception handler (was destroyed) 15.162 + __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) 15.163 + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); 15.164 + // the call_VM checks for exception, so we should never return here. 15.165 + __ should_not_reach_here(); 15.166 + 15.167 + __ bind(no_such_interface); 15.168 + // throw exception 15.169 + __ pop(rbx); // pop return address (pushed by prepare_invoke) 15.170 + __ restore_bcp(); // r13 must be correct for exception handler (was destroyed) 15.171 + __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) 15.172 __ call_VM(noreg, CAST_FROM_FN_PTR(address, 15.173 InterpreterRuntime::throw_IncompatibleClassChangeError)); 15.174 // the call_VM checks for exception, so we should never return here. 15.175 __ should_not_reach_here(); 15.176 - __ bind(interface_ok); 15.177 - 15.178 - __ pop(rdx); 15.179 - 15.180 - __ cmpptr(rax, Address(rdx, itableOffsetEntry::interface_offset_in_bytes())); 15.181 - __ jcc(Assembler::notEqual, search); 15.182 - 15.183 - __ movl(rdx, Address(rdx, itableOffsetEntry::offset_offset_in_bytes())); 15.184 - 15.185 - __ addptr(rdx, r14); // Add offset to klassOop 15.186 - assert(itableMethodEntry::size() * wordSize == 8, 15.187 - "adjust the scaling in the code below"); 15.188 - __ movptr(rbx, Address(rdx, rbx, Address::times_8)); 15.189 - // rbx: methodOop to call 15.190 - // rcx: receiver 15.191 - // Check for abstract method error 15.192 - // Note: This should be done more efficiently via a 15.193 - // throw_abstract_method_error interpreter entry point and a 15.194 - // conditional jump to it in case of a null method. 15.195 - { 15.196 - Label L; 15.197 - __ testptr(rbx, rbx); 15.198 - __ jcc(Assembler::notZero, L); 15.199 - // throw exception 15.200 - // note: must restore interpreter registers to canonical 15.201 - // state for exception handling to work correctly! 15.202 - __ pop(rbx); // pop return address (pushed by prepare_invoke) 15.203 - __ restore_bcp(); // r13 must be correct for exception handler 15.204 - // (was destroyed) 15.205 - __ restore_locals(); // make sure locals pointer is correct as 15.206 - // well (was destroyed) 15.207 - __ call_VM(noreg, 15.208 - CAST_FROM_FN_PTR(address, 15.209 - InterpreterRuntime::throw_AbstractMethodError)); 15.210 - // the call_VM checks for exception, so we should never return here. 15.211 - __ should_not_reach_here(); 15.212 - __ bind(L); 15.213 - } 15.214 - 15.215 - __ movptr(rcx, Address(rbx, methodOopDesc::interpreter_entry_offset())); 15.216 - 15.217 - // do the call 15.218 - // rcx: receiver 15.219 - // rbx: methodOop 15.220 - __ jump_from_interpreted(rbx, rdx); 15.221 + return; 15.222 } 15.223 15.224 + 15.225 //----------------------------------------------------------------------------- 15.226 // Allocation 15.227
16.1 --- a/src/cpu/x86/vm/vtableStubs_x86_32.cpp Mon Mar 09 11:32:57 2009 -0400 16.2 +++ b/src/cpu/x86/vm/vtableStubs_x86_32.cpp Tue Mar 10 08:52:16 2009 -0700 16.3 @@ -34,10 +34,16 @@ 16.4 extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int index); 16.5 #endif 16.6 16.7 -// used by compiler only; may use only caller saved registers rax, rbx, rcx. 16.8 -// rdx holds first int arg, rsi, rdi, rbp are callee-save & must be preserved. 16.9 -// Leave receiver in rcx; required behavior when +OptoArgsInRegisters 16.10 -// is modifed to put first oop in rcx. 16.11 +// These stubs are used by the compiler only. 16.12 +// Argument registers, which must be preserved: 16.13 +// rcx - receiver (always first argument) 16.14 +// rdx - second argument (if any) 16.15 +// Other registers that might be usable: 16.16 +// rax - inline cache register (is interface for itable stub) 16.17 +// rbx - method (used when calling out to interpreter) 16.18 +// Available now, but may become callee-save at some point: 16.19 +// rsi, rdi 16.20 +// Note that rax and rdx are also used for return values. 16.21 // 16.22 VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { 16.23 const int i486_code_length = VtableStub::pd_code_size_limit(true); 16.24 @@ -94,16 +100,25 @@ 16.25 __ jmp( Address(method, methodOopDesc::from_compiled_offset())); 16.26 16.27 masm->flush(); 16.28 + 16.29 + if (PrintMiscellaneous && (WizardMode || Verbose)) { 16.30 + tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d", 16.31 + vtable_index, s->entry_point(), 16.32 + (int)(s->code_end() - s->entry_point()), 16.33 + (int)(s->code_end() - __ pc())); 16.34 + } 16.35 + guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 16.36 + 16.37 s->set_exception_points(npe_addr, ame_addr); 16.38 return s; 16.39 } 16.40 16.41 16.42 -VtableStub* VtableStubs::create_itable_stub(int vtable_index) { 16.43 +VtableStub* VtableStubs::create_itable_stub(int itable_index) { 16.44 // Note well: pd_code_size_limit is the absolute minimum we can get away with. If you 16.45 // add code here, bump the code stub size returned by pd_code_size_limit! 16.46 const int i486_code_length = VtableStub::pd_code_size_limit(false); 16.47 - VtableStub* s = new(i486_code_length) VtableStub(false, vtable_index); 16.48 + VtableStub* s = new(i486_code_length) VtableStub(false, itable_index); 16.49 ResourceMark rm; 16.50 CodeBuffer cb(s->entry_point(), i486_code_length); 16.51 MacroAssembler* masm = new MacroAssembler(&cb); 16.52 @@ -123,50 +138,19 @@ 16.53 16.54 // get receiver klass (also an implicit null-check) 16.55 address npe_addr = __ pc(); 16.56 - __ movptr(rbx, Address(rcx, oopDesc::klass_offset_in_bytes())); 16.57 + __ movptr(rsi, Address(rcx, oopDesc::klass_offset_in_bytes())); 16.58 16.59 - __ mov(rsi, rbx); // Save klass in free register 16.60 - // Most registers are in use, so save a few 16.61 - __ push(rdx); 16.62 - // compute itable entry offset (in words) 16.63 - const int base = instanceKlass::vtable_start_offset() * wordSize; 16.64 - assert(vtableEntry::size() * wordSize == 4, "adjust the scaling in the code below"); 16.65 - __ movl(rdx, Address(rbx, instanceKlass::vtable_length_offset() * wordSize)); // Get length of vtable 16.66 - __ lea(rbx, Address(rbx, rdx, Address::times_ptr, base)); 16.67 - if (HeapWordsPerLong > 1) { 16.68 - // Round up to align_object_offset boundary 16.69 - __ round_to(rbx, BytesPerLong); 16.70 - } 16.71 - 16.72 - Label hit, next, entry, throw_icce; 16.73 - 16.74 - __ jmpb(entry); 16.75 - 16.76 - __ bind(next); 16.77 - __ addptr(rbx, itableOffsetEntry::size() * wordSize); 16.78 - 16.79 - __ bind(entry); 16.80 - 16.81 - // If the entry is NULL then we've reached the end of the table 16.82 - // without finding the expected interface, so throw an exception 16.83 - __ movptr(rdx, Address(rbx, itableOffsetEntry::interface_offset_in_bytes())); 16.84 - __ testptr(rdx, rdx); 16.85 - __ jcc(Assembler::zero, throw_icce); 16.86 - __ cmpptr(rax, rdx); 16.87 - __ jcc(Assembler::notEqual, next); 16.88 - 16.89 - // We found a hit, move offset into rbx, 16.90 - __ movl(rdx, Address(rbx, itableOffsetEntry::offset_offset_in_bytes())); 16.91 - 16.92 - // Compute itableMethodEntry. 16.93 - const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + itableMethodEntry::method_offset_in_bytes(); 16.94 + // Most registers are in use; we'll use rax, rbx, rsi, rdi 16.95 + // (If we need to make rsi, rdi callee-save, do a push/pop here.) 16.96 + const Register method = rbx; 16.97 + Label throw_icce; 16.98 16.99 // Get methodOop and entrypoint for compiler 16.100 - const Register method = rbx; 16.101 - __ movptr(method, Address(rsi, rdx, Address::times_1, method_offset)); 16.102 - 16.103 - // Restore saved register, before possible trap. 16.104 - __ pop(rdx); 16.105 + __ lookup_interface_method(// inputs: rec. class, interface, itable index 16.106 + rsi, rax, itable_index, 16.107 + // outputs: method, scan temp. reg 16.108 + method, rdi, 16.109 + throw_icce); 16.110 16.111 // method (rbx): methodOop 16.112 // rcx: receiver 16.113 @@ -187,12 +171,15 @@ 16.114 __ jmp(Address(method, methodOopDesc::from_compiled_offset())); 16.115 16.116 __ bind(throw_icce); 16.117 - // Restore saved register 16.118 - __ pop(rdx); 16.119 __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); 16.120 - 16.121 masm->flush(); 16.122 16.123 + if (PrintMiscellaneous && (WizardMode || Verbose)) { 16.124 + tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d", 16.125 + itable_index, s->entry_point(), 16.126 + (int)(s->code_end() - s->entry_point()), 16.127 + (int)(s->code_end() - __ pc())); 16.128 + } 16.129 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 16.130 16.131 s->set_exception_points(npe_addr, ame_addr); 16.132 @@ -207,7 +194,7 @@ 16.133 return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0); 16.134 } else { 16.135 // Itable stub size 16.136 - return (DebugVtables ? 144 : 64) + (CountCompiledCalls ? 6 : 0); 16.137 + return (DebugVtables ? 256 : 66) + (CountCompiledCalls ? 6 : 0); 16.138 } 16.139 } 16.140
17.1 --- a/src/cpu/x86/vm/vtableStubs_x86_64.cpp Mon Mar 09 11:32:57 2009 -0400 17.2 +++ b/src/cpu/x86/vm/vtableStubs_x86_64.cpp Tue Mar 10 08:52:16 2009 -0700 17.3 @@ -98,17 +98,26 @@ 17.4 __ jmp( Address(rbx, methodOopDesc::from_compiled_offset())); 17.5 17.6 __ flush(); 17.7 + 17.8 + if (PrintMiscellaneous && (WizardMode || Verbose)) { 17.9 + tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d", 17.10 + vtable_index, s->entry_point(), 17.11 + (int)(s->code_end() - s->entry_point()), 17.12 + (int)(s->code_end() - __ pc())); 17.13 + } 17.14 + guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 17.15 + 17.16 s->set_exception_points(npe_addr, ame_addr); 17.17 return s; 17.18 } 17.19 17.20 17.21 -VtableStub* VtableStubs::create_itable_stub(int vtable_index) { 17.22 +VtableStub* VtableStubs::create_itable_stub(int itable_index) { 17.23 // Note well: pd_code_size_limit is the absolute minimum we can get 17.24 // away with. If you add code here, bump the code stub size 17.25 // returned by pd_code_size_limit! 17.26 const int amd64_code_length = VtableStub::pd_code_size_limit(false); 17.27 - VtableStub* s = new(amd64_code_length) VtableStub(false, vtable_index); 17.28 + VtableStub* s = new(amd64_code_length) VtableStub(false, itable_index); 17.29 ResourceMark rm; 17.30 CodeBuffer cb(s->entry_point(), amd64_code_length); 17.31 MacroAssembler* masm = new MacroAssembler(&cb); 17.32 @@ -131,68 +140,28 @@ 17.33 // get receiver klass (also an implicit null-check) 17.34 address npe_addr = __ pc(); 17.35 17.36 - __ load_klass(rbx, j_rarg0); 17.37 + // Most registers are in use; we'll use rax, rbx, r10, r11 17.38 + // (various calling sequences use r[cd]x, r[sd]i, r[89]; stay away from them) 17.39 + __ load_klass(r10, j_rarg0); 17.40 17.41 // If we take a trap while this arg is on the stack we will not 17.42 // be able to walk the stack properly. This is not an issue except 17.43 // when there are mistakes in this assembly code that could generate 17.44 // a spurious fault. Ask me how I know... 17.45 17.46 - __ push(j_rarg1); // Most registers are in use, so save one 17.47 - 17.48 - // compute itable entry offset (in words) 17.49 - const int base = instanceKlass::vtable_start_offset() * wordSize; 17.50 - assert(vtableEntry::size() * wordSize == 8, 17.51 - "adjust the scaling in the code below"); 17.52 - // Get length of vtable 17.53 - __ movl(j_rarg1, 17.54 - Address(rbx, instanceKlass::vtable_length_offset() * wordSize)); 17.55 - __ lea(rbx, Address(rbx, j_rarg1, Address::times_8, base)); 17.56 - 17.57 - if (HeapWordsPerLong > 1) { 17.58 - // Round up to align_object_offset boundary 17.59 - __ round_to(rbx, BytesPerLong); 17.60 - } 17.61 - Label hit, next, entry, throw_icce; 17.62 - 17.63 - __ jmpb(entry); 17.64 - 17.65 - __ bind(next); 17.66 - __ addptr(rbx, itableOffsetEntry::size() * wordSize); 17.67 - 17.68 - __ bind(entry); 17.69 - 17.70 - // If the entry is NULL then we've reached the end of the table 17.71 - // without finding the expected interface, so throw an exception 17.72 - __ movptr(j_rarg1, Address(rbx, itableOffsetEntry::interface_offset_in_bytes())); 17.73 - __ testptr(j_rarg1, j_rarg1); 17.74 - __ jcc(Assembler::zero, throw_icce); 17.75 - __ cmpptr(rax, j_rarg1); 17.76 - __ jccb(Assembler::notEqual, next); 17.77 - 17.78 - // We found a hit, move offset into j_rarg1 17.79 - __ movl(j_rarg1, Address(rbx, itableOffsetEntry::offset_offset_in_bytes())); 17.80 - 17.81 - // Compute itableMethodEntry 17.82 - const int method_offset = 17.83 - (itableMethodEntry::size() * wordSize * vtable_index) + 17.84 - itableMethodEntry::method_offset_in_bytes(); 17.85 + const Register method = rbx; 17.86 + Label throw_icce; 17.87 17.88 // Get methodOop and entrypoint for compiler 17.89 - 17.90 - // Get klass pointer again 17.91 - __ load_klass(rax, j_rarg0); 17.92 - 17.93 - const Register method = rbx; 17.94 - __ movptr(method, Address(rax, j_rarg1, Address::times_1, method_offset)); 17.95 - 17.96 - // Restore saved register, before possible trap. 17.97 - __ pop(j_rarg1); 17.98 + __ lookup_interface_method(// inputs: rec. class, interface, itable index 17.99 + r10, rax, itable_index, 17.100 + // outputs: method, scan temp. reg 17.101 + method, r11, 17.102 + throw_icce); 17.103 17.104 // method (rbx): methodOop 17.105 // j_rarg0: receiver 17.106 17.107 - 17.108 #ifdef ASSERT 17.109 if (DebugVtables) { 17.110 Label L2; 17.111 @@ -211,12 +180,16 @@ 17.112 __ jmp(Address(method, methodOopDesc::from_compiled_offset())); 17.113 17.114 __ bind(throw_icce); 17.115 - // Restore saved register 17.116 - __ pop(j_rarg1); 17.117 __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); 17.118 17.119 __ flush(); 17.120 17.121 + if (PrintMiscellaneous && (WizardMode || Verbose)) { 17.122 + tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d", 17.123 + itable_index, s->entry_point(), 17.124 + (int)(s->code_end() - s->entry_point()), 17.125 + (int)(s->code_end() - __ pc())); 17.126 + } 17.127 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 17.128 17.129 s->set_exception_points(npe_addr, ame_addr); 17.130 @@ -230,7 +203,7 @@ 17.131 (UseCompressedOops ? 16 : 0); // 1 leaq can be 3 bytes + 1 long 17.132 } else { 17.133 // Itable stub size 17.134 - return (DebugVtables ? 636 : 72) + (CountCompiledCalls ? 13 : 0) + 17.135 + return (DebugVtables ? 512 : 72) + (CountCompiledCalls ? 13 : 0) + 17.136 (UseCompressedOops ? 32 : 0); // 2 leaqs 17.137 } 17.138 }
18.1 --- a/src/cpu/x86/vm/x86_32.ad Mon Mar 09 11:32:57 2009 -0400 18.2 +++ b/src/cpu/x86/vm/x86_32.ad Tue Mar 10 08:52:16 2009 -0700 18.3 @@ -1,5 +1,5 @@ 18.4 // 18.5 -// Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 18.6 +// Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 18.7 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 18.8 // 18.9 // This code is free software; you can redistribute it and/or modify it 18.10 @@ -3126,14 +3126,12 @@ 18.11 18.12 enc_class movq_ld(regXD dst, memory mem) %{ 18.13 MacroAssembler _masm(&cbuf); 18.14 - Address madr = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); 18.15 - __ movq(as_XMMRegister($dst$$reg), madr); 18.16 + __ movq($dst$$XMMRegister, $mem$$Address); 18.17 %} 18.18 18.19 enc_class movq_st(memory mem, regXD src) %{ 18.20 MacroAssembler _masm(&cbuf); 18.21 - Address madr = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); 18.22 - __ movq(madr, as_XMMRegister($src$$reg)); 18.23 + __ movq($mem$$Address, $src$$XMMRegister); 18.24 %} 18.25 18.26 enc_class pshufd_8x8(regX dst, regX src) %{ 18.27 @@ -3751,8 +3749,8 @@ 18.28 masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL); 18.29 18.30 // Load first characters 18.31 - masm.load_unsigned_word(rcx, Address(rbx, 0)); 18.32 - masm.load_unsigned_word(rdi, Address(rax, 0)); 18.33 + masm.load_unsigned_short(rcx, Address(rbx, 0)); 18.34 + masm.load_unsigned_short(rdi, Address(rax, 0)); 18.35 18.36 // Compare first characters 18.37 masm.subl(rcx, rdi); 18.38 @@ -3782,8 +3780,8 @@ 18.39 18.40 // Compare the rest of the characters 18.41 masm.bind(WHILE_HEAD_LABEL); 18.42 - masm.load_unsigned_word(rcx, Address(rbx, rsi, Address::times_2, 0)); 18.43 - masm.load_unsigned_word(rdi, Address(rax, rsi, Address::times_2, 0)); 18.44 + masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0)); 18.45 + masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0)); 18.46 masm.subl(rcx, rdi); 18.47 masm.jcc(Assembler::notZero, POP_LABEL); 18.48 masm.incrementl(rsi); 18.49 @@ -3840,8 +3838,8 @@ 18.50 masm.jcc(Assembler::zero, COMPARE_LOOP_HDR); 18.51 18.52 // Compare 2-byte "tail" at end of arrays 18.53 - masm.load_unsigned_word(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset)); 18.54 - masm.load_unsigned_word(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset)); 18.55 + masm.load_unsigned_short(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset)); 18.56 + masm.load_unsigned_short(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset)); 18.57 masm.cmpl(tmp1Reg, tmp2Reg); 18.58 masm.jcc(Assembler::notEqual, FALSE_LABEL); 18.59 masm.testl(resultReg, resultReg); 18.60 @@ -6396,21 +6394,94 @@ 18.61 match(Set dst (LoadB mem)); 18.62 18.63 ins_cost(125); 18.64 - format %{ "MOVSX8 $dst,$mem" %} 18.65 - opcode(0xBE, 0x0F); 18.66 - ins_encode( OpcS, OpcP, RegMem(dst,mem)); 18.67 - ins_pipe( ialu_reg_mem ); 18.68 -%} 18.69 - 18.70 -// Load Byte (8bit UNsigned) 18.71 -instruct loadUB(xRegI dst, memory mem, immI_255 bytemask) %{ 18.72 - match(Set dst (AndI (LoadB mem) bytemask)); 18.73 + format %{ "MOVSX8 $dst,$mem\t# byte" %} 18.74 + 18.75 + ins_encode %{ 18.76 + __ movsbl($dst$$Register, $mem$$Address); 18.77 + %} 18.78 + 18.79 + ins_pipe(ialu_reg_mem); 18.80 +%} 18.81 + 18.82 +// Load Byte (8bit signed) into Long Register 18.83 +instruct loadB2L(eRegL dst, memory mem) %{ 18.84 + match(Set dst (ConvI2L (LoadB mem))); 18.85 + 18.86 + ins_cost(375); 18.87 + format %{ "MOVSX8 $dst.lo,$mem\t# byte -> long\n\t" 18.88 + "MOV $dst.hi,$dst.lo\n\t" 18.89 + "SAR $dst.hi,7" %} 18.90 + 18.91 + ins_encode %{ 18.92 + __ movsbl($dst$$Register, $mem$$Address); 18.93 + __ movl(HIGH_FROM_LOW($dst$$Register), $dst$$Register); // This is always a different register. 18.94 + __ sarl(HIGH_FROM_LOW($dst$$Register), 7); // 24+1 MSB are already signed extended. 18.95 + %} 18.96 + 18.97 + ins_pipe(ialu_reg_mem); 18.98 +%} 18.99 + 18.100 +// Load Unsigned Byte (8bit UNsigned) 18.101 +instruct loadUB(xRegI dst, memory mem) %{ 18.102 + match(Set dst (LoadUB mem)); 18.103 18.104 ins_cost(125); 18.105 - format %{ "MOVZX8 $dst,$mem" %} 18.106 - opcode(0xB6, 0x0F); 18.107 - ins_encode( OpcS, OpcP, RegMem(dst,mem)); 18.108 - ins_pipe( ialu_reg_mem ); 18.109 + format %{ "MOVZX8 $dst,$mem\t# ubyte -> int" %} 18.110 + 18.111 + ins_encode %{ 18.112 + __ movzbl($dst$$Register, $mem$$Address); 18.113 + %} 18.114 + 18.115 + ins_pipe(ialu_reg_mem); 18.116 +%} 18.117 + 18.118 +// Load Unsigned Byte (8 bit UNsigned) into Long Register 18.119 +instruct loadUB2L(eRegL dst, memory mem) 18.120 +%{ 18.121 + match(Set dst (ConvI2L (LoadUB mem))); 18.122 + 18.123 + ins_cost(250); 18.124 + format %{ "MOVZX8 $dst.lo,$mem\t# ubyte -> long\n\t" 18.125 + "XOR $dst.hi,$dst.hi" %} 18.126 + 18.127 + ins_encode %{ 18.128 + __ movzbl($dst$$Register, $mem$$Address); 18.129 + __ xorl(HIGH_FROM_LOW($dst$$Register), HIGH_FROM_LOW($dst$$Register)); 18.130 + %} 18.131 + 18.132 + ins_pipe(ialu_reg_mem); 18.133 +%} 18.134 + 18.135 +// Load Short (16bit signed) 18.136 +instruct loadS(eRegI dst, memory mem) %{ 18.137 + match(Set dst (LoadS mem)); 18.138 + 18.139 + ins_cost(125); 18.140 + format %{ "MOVSX $dst,$mem\t# short" %} 18.141 + 18.142 + ins_encode %{ 18.143 + __ movswl($dst$$Register, $mem$$Address); 18.144 + %} 18.145 + 18.146 + ins_pipe(ialu_reg_mem); 18.147 +%} 18.148 + 18.149 +// Load Short (16bit signed) into Long Register 18.150 +instruct loadS2L(eRegL dst, memory mem) %{ 18.151 + match(Set dst (ConvI2L (LoadS mem))); 18.152 + 18.153 + ins_cost(375); 18.154 + format %{ "MOVSX $dst.lo,$mem\t# short -> long\n\t" 18.155 + "MOV $dst.hi,$dst.lo\n\t" 18.156 + "SAR $dst.hi,15" %} 18.157 + 18.158 + ins_encode %{ 18.159 + __ movswl($dst$$Register, $mem$$Address); 18.160 + __ movl(HIGH_FROM_LOW($dst$$Register), $dst$$Register); // This is always a different register. 18.161 + __ sarl(HIGH_FROM_LOW($dst$$Register), 15); // 16+1 MSB are already signed extended. 18.162 + %} 18.163 + 18.164 + ins_pipe(ialu_reg_mem); 18.165 %} 18.166 18.167 // Load Unsigned Short/Char (16bit unsigned) 18.168 @@ -6418,10 +6489,30 @@ 18.169 match(Set dst (LoadUS mem)); 18.170 18.171 ins_cost(125); 18.172 - format %{ "MOVZX $dst,$mem" %} 18.173 - opcode(0xB7, 0x0F); 18.174 - ins_encode( OpcS, OpcP, RegMem(dst,mem)); 18.175 - ins_pipe( ialu_reg_mem ); 18.176 + format %{ "MOVZX $dst,$mem\t# ushort/char -> int" %} 18.177 + 18.178 + ins_encode %{ 18.179 + __ movzwl($dst$$Register, $mem$$Address); 18.180 + %} 18.181 + 18.182 + ins_pipe(ialu_reg_mem); 18.183 +%} 18.184 + 18.185 +// Load Unsigned Short/Char (16 bit UNsigned) into Long Register 18.186 +instruct loadUS2L(eRegL dst, memory mem) 18.187 +%{ 18.188 + match(Set dst (ConvI2L (LoadUS mem))); 18.189 + 18.190 + ins_cost(250); 18.191 + format %{ "MOVZX $dst.lo,$mem\t# ushort/char -> long\n\t" 18.192 + "XOR $dst.hi,$dst.hi" %} 18.193 + 18.194 + ins_encode %{ 18.195 + __ movzwl($dst$$Register, $mem$$Address); 18.196 + __ xorl(HIGH_FROM_LOW($dst$$Register), HIGH_FROM_LOW($dst$$Register)); 18.197 + %} 18.198 + 18.199 + ins_pipe(ialu_reg_mem); 18.200 %} 18.201 18.202 // Load Integer 18.203 @@ -6429,10 +6520,47 @@ 18.204 match(Set dst (LoadI mem)); 18.205 18.206 ins_cost(125); 18.207 - format %{ "MOV $dst,$mem" %} 18.208 - opcode(0x8B); 18.209 - ins_encode( OpcP, RegMem(dst,mem)); 18.210 - ins_pipe( ialu_reg_mem ); 18.211 + format %{ "MOV $dst,$mem\t# int" %} 18.212 + 18.213 + ins_encode %{ 18.214 + __ movl($dst$$Register, $mem$$Address); 18.215 + %} 18.216 + 18.217 + ins_pipe(ialu_reg_mem); 18.218 +%} 18.219 + 18.220 +// Load Integer into Long Register 18.221 +instruct loadI2L(eRegL dst, memory mem) %{ 18.222 + match(Set dst (ConvI2L (LoadI mem))); 18.223 + 18.224 + ins_cost(375); 18.225 + format %{ "MOV $dst.lo,$mem\t# int -> long\n\t" 18.226 + "MOV $dst.hi,$dst.lo\n\t" 18.227 + "SAR $dst.hi,31" %} 18.228 + 18.229 + ins_encode %{ 18.230 + __ movl($dst$$Register, $mem$$Address); 18.231 + __ movl(HIGH_FROM_LOW($dst$$Register), $dst$$Register); // This is always a different register. 18.232 + __ sarl(HIGH_FROM_LOW($dst$$Register), 31); 18.233 + %} 18.234 + 18.235 + ins_pipe(ialu_reg_mem); 18.236 +%} 18.237 + 18.238 +// Load Unsigned Integer into Long Register 18.239 +instruct loadUI2L(eRegL dst, memory mem) %{ 18.240 + match(Set dst (LoadUI2L mem)); 18.241 + 18.242 + ins_cost(250); 18.243 + format %{ "MOV $dst.lo,$mem\t# uint -> long\n\t" 18.244 + "XOR $dst.hi,$dst.hi" %} 18.245 + 18.246 + ins_encode %{ 18.247 + __ movl($dst$$Register, $mem$$Address); 18.248 + __ xorl(HIGH_FROM_LOW($dst$$Register), HIGH_FROM_LOW($dst$$Register)); 18.249 + %} 18.250 + 18.251 + ins_pipe(ialu_reg_mem); 18.252 %} 18.253 18.254 // Load Long. Cannot clobber address while loading, so restrict address 18.255 @@ -6442,11 +6570,17 @@ 18.256 match(Set dst (LoadL mem)); 18.257 18.258 ins_cost(250); 18.259 - format %{ "MOV $dst.lo,$mem\n\t" 18.260 + format %{ "MOV $dst.lo,$mem\t# long\n\t" 18.261 "MOV $dst.hi,$mem+4" %} 18.262 - opcode(0x8B, 0x8B); 18.263 - ins_encode( OpcP, RegMem(dst,mem), OpcS, RegMem_Hi(dst,mem)); 18.264 - ins_pipe( ialu_reg_long_mem ); 18.265 + 18.266 + ins_encode %{ 18.267 + Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, false); 18.268 + Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, false); 18.269 + __ movl($dst$$Register, Amemlo); 18.270 + __ movl(HIGH_FROM_LOW($dst$$Register), Amemhi); 18.271 + %} 18.272 + 18.273 + ins_pipe(ialu_reg_long_mem); 18.274 %} 18.275 18.276 // Volatile Load Long. Must be atomic, so do 64-bit FILD 18.277 @@ -6521,17 +6655,6 @@ 18.278 ins_pipe( ialu_reg_mem ); 18.279 %} 18.280 18.281 -// Load Short (16bit signed) 18.282 -instruct loadS(eRegI dst, memory mem) %{ 18.283 - match(Set dst (LoadS mem)); 18.284 - 18.285 - ins_cost(125); 18.286 - format %{ "MOVSX $dst,$mem" %} 18.287 - opcode(0xBF, 0x0F); 18.288 - ins_encode( OpcS, OpcP, RegMem(dst,mem)); 18.289 - ins_pipe( ialu_reg_mem ); 18.290 -%} 18.291 - 18.292 // Load Double 18.293 instruct loadD(regD dst, memory mem) %{ 18.294 predicate(UseSSE<=1); 18.295 @@ -7957,7 +8080,7 @@ 18.296 __ xchgl(as_Register(EBX_enc), as_Register(ECX_enc)); 18.297 if( os::is_MP() ) 18.298 __ lock(); 18.299 - __ cmpxchg8(Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp)); 18.300 + __ cmpxchg8($mem$$Address); 18.301 __ xchgl(as_Register(EBX_enc), as_Register(ECX_enc)); 18.302 %} 18.303 ins_pipe( pipe_cmpxchg ); 18.304 @@ -11467,6 +11590,7 @@ 18.305 instruct convI2L_reg( eRegL dst, eRegI src, eFlagsReg cr) %{ 18.306 match(Set dst (ConvI2L src)); 18.307 effect(KILL cr); 18.308 + ins_cost(375); 18.309 format %{ "MOV $dst.lo,$src\n\t" 18.310 "MOV $dst.hi,$src\n\t" 18.311 "SAR $dst.hi,31" %} 18.312 @@ -11478,6 +11602,7 @@ 18.313 instruct convI2L_reg_zex(eRegL dst, eRegI src, immL_32bits mask, eFlagsReg flags ) %{ 18.314 match(Set dst (AndL (ConvI2L src) mask) ); 18.315 effect( KILL flags ); 18.316 + ins_cost(250); 18.317 format %{ "MOV $dst.lo,$src\n\t" 18.318 "XOR $dst.hi,$dst.hi" %} 18.319 opcode(0x33); // XOR 18.320 @@ -11489,6 +11614,7 @@ 18.321 instruct zerox_long(eRegL dst, eRegL src, immL_32bits mask, eFlagsReg flags ) %{ 18.322 match(Set dst (AndL src mask) ); 18.323 effect( KILL flags ); 18.324 + ins_cost(250); 18.325 format %{ "MOV $dst.lo,$src.lo\n\t" 18.326 "XOR $dst.hi,$dst.hi\n\t" %} 18.327 opcode(0x33); // XOR
19.1 --- a/src/cpu/x86/vm/x86_64.ad Mon Mar 09 11:32:57 2009 -0400 19.2 +++ b/src/cpu/x86/vm/x86_64.ad Tue Mar 10 08:52:16 2009 -0700 19.3 @@ -1,5 +1,5 @@ 19.4 // 19.5 -// Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. 19.6 +// Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. 19.7 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 19.8 // 19.9 // This code is free software; you can redistribute it and/or modify it 19.10 @@ -3462,14 +3462,12 @@ 19.11 19.12 enc_class movq_ld(regD dst, memory mem) %{ 19.13 MacroAssembler _masm(&cbuf); 19.14 - Address madr = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); 19.15 - __ movq(as_XMMRegister($dst$$reg), madr); 19.16 + __ movq($dst$$XMMRegister, $mem$$Address); 19.17 %} 19.18 19.19 enc_class movq_st(memory mem, regD src) %{ 19.20 MacroAssembler _masm(&cbuf); 19.21 - Address madr = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); 19.22 - __ movq(madr, as_XMMRegister($src$$reg)); 19.23 + __ movq($mem$$Address, $src$$XMMRegister); 19.24 %} 19.25 19.26 enc_class pshufd_8x8(regF dst, regF src) %{ 19.27 @@ -3765,8 +3763,8 @@ 19.28 masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL); 19.29 19.30 // Load first characters 19.31 - masm.load_unsigned_word(rcx, Address(rbx, 0)); 19.32 - masm.load_unsigned_word(rdi, Address(rax, 0)); 19.33 + masm.load_unsigned_short(rcx, Address(rbx, 0)); 19.34 + masm.load_unsigned_short(rdi, Address(rax, 0)); 19.35 19.36 // Compare first characters 19.37 masm.subl(rcx, rdi); 19.38 @@ -3796,8 +3794,8 @@ 19.39 19.40 // Compare the rest of the characters 19.41 masm.bind(WHILE_HEAD_LABEL); 19.42 - masm.load_unsigned_word(rcx, Address(rbx, rsi, Address::times_2, 0)); 19.43 - masm.load_unsigned_word(rdi, Address(rax, rsi, Address::times_2, 0)); 19.44 + masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0)); 19.45 + masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0)); 19.46 masm.subl(rcx, rdi); 19.47 masm.jcc(Assembler::notZero, POP_LABEL); 19.48 masm.increment(rsi); 19.49 @@ -3854,8 +3852,8 @@ 19.50 masm.jcc(Assembler::zero, COMPARE_LOOP_HDR); 19.51 19.52 // Compare 2-byte "tail" at end of arrays 19.53 - masm.load_unsigned_word(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset)); 19.54 - masm.load_unsigned_word(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset)); 19.55 + masm.load_unsigned_short(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset)); 19.56 + masm.load_unsigned_short(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset)); 19.57 masm.cmpl(tmp1Reg, tmp2Reg); 19.58 masm.jcc(Assembler::notEqual, FALSE_LABEL); 19.59 masm.testl(resultReg, resultReg); 19.60 @@ -6031,70 +6029,88 @@ 19.61 19.62 ins_cost(125); 19.63 format %{ "movsbl $dst, $mem\t# byte" %} 19.64 - opcode(0x0F, 0xBE); 19.65 - ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem)); 19.66 + 19.67 + ins_encode %{ 19.68 + __ movsbl($dst$$Register, $mem$$Address); 19.69 + %} 19.70 + 19.71 ins_pipe(ialu_reg_mem); 19.72 %} 19.73 19.74 -// Load Byte (8 bit signed) into long 19.75 -// instruct loadB2L(rRegL dst, memory mem) 19.76 -// %{ 19.77 -// match(Set dst (ConvI2L (LoadB mem))); 19.78 - 19.79 -// ins_cost(125); 19.80 -// format %{ "movsbq $dst, $mem\t# byte -> long" %} 19.81 -// opcode(0x0F, 0xBE); 19.82 -// ins_encode(REX_reg_mem_wide(dst, mem), OpcP, OpcS, reg_mem(dst, mem)); 19.83 -// ins_pipe(ialu_reg_mem); 19.84 -// %} 19.85 - 19.86 -// Load Byte (8 bit UNsigned) 19.87 -instruct loadUB(rRegI dst, memory mem, immI_255 bytemask) 19.88 -%{ 19.89 - match(Set dst (AndI (LoadB mem) bytemask)); 19.90 +// Load Byte (8 bit signed) into Long Register 19.91 +instruct loadB2L(rRegL dst, memory mem) 19.92 +%{ 19.93 + match(Set dst (ConvI2L (LoadB mem))); 19.94 + 19.95 + ins_cost(125); 19.96 + format %{ "movsbq $dst, $mem\t# byte -> long" %} 19.97 + 19.98 + ins_encode %{ 19.99 + __ movsbq($dst$$Register, $mem$$Address); 19.100 + %} 19.101 + 19.102 + ins_pipe(ialu_reg_mem); 19.103 +%} 19.104 + 19.105 +// Load Unsigned Byte (8 bit UNsigned) 19.106 +instruct loadUB(rRegI dst, memory mem) 19.107 +%{ 19.108 + match(Set dst (LoadUB mem)); 19.109 19.110 ins_cost(125); 19.111 format %{ "movzbl $dst, $mem\t# ubyte" %} 19.112 - opcode(0x0F, 0xB6); 19.113 - ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem)); 19.114 + 19.115 + ins_encode %{ 19.116 + __ movzbl($dst$$Register, $mem$$Address); 19.117 + %} 19.118 + 19.119 ins_pipe(ialu_reg_mem); 19.120 %} 19.121 19.122 -// Load Byte (8 bit UNsigned) into long 19.123 -// instruct loadUB2L(rRegL dst, memory mem, immI_255 bytemask) 19.124 -// %{ 19.125 -// match(Set dst (ConvI2L (AndI (LoadB mem) bytemask))); 19.126 - 19.127 -// ins_cost(125); 19.128 -// format %{ "movzbl $dst, $mem\t# ubyte -> long" %} 19.129 -// opcode(0x0F, 0xB6); 19.130 -// ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem)); 19.131 -// ins_pipe(ialu_reg_mem); 19.132 -// %} 19.133 +// Load Unsigned Byte (8 bit UNsigned) into Long Register 19.134 +instruct loadUB2L(rRegL dst, memory mem) 19.135 +%{ 19.136 + match(Set dst (ConvI2L (LoadUB mem))); 19.137 + 19.138 + ins_cost(125); 19.139 + format %{ "movzbq $dst, $mem\t# ubyte -> long" %} 19.140 + 19.141 + ins_encode %{ 19.142 + __ movzbq($dst$$Register, $mem$$Address); 19.143 + %} 19.144 + 19.145 + ins_pipe(ialu_reg_mem); 19.146 +%} 19.147 19.148 // Load Short (16 bit signed) 19.149 instruct loadS(rRegI dst, memory mem) 19.150 %{ 19.151 match(Set dst (LoadS mem)); 19.152 19.153 - ins_cost(125); // XXX 19.154 + ins_cost(125); 19.155 format %{ "movswl $dst, $mem\t# short" %} 19.156 - opcode(0x0F, 0xBF); 19.157 - ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem)); 19.158 + 19.159 + ins_encode %{ 19.160 + __ movswl($dst$$Register, $mem$$Address); 19.161 + %} 19.162 + 19.163 ins_pipe(ialu_reg_mem); 19.164 %} 19.165 19.166 -// Load Short (16 bit signed) into long 19.167 -// instruct loadS2L(rRegL dst, memory mem) 19.168 -// %{ 19.169 -// match(Set dst (ConvI2L (LoadS mem))); 19.170 - 19.171 -// ins_cost(125); // XXX 19.172 -// format %{ "movswq $dst, $mem\t# short -> long" %} 19.173 -// opcode(0x0F, 0xBF); 19.174 -// ins_encode(REX_reg_mem_wide(dst, mem), OpcP, OpcS, reg_mem(dst, mem)); 19.175 -// ins_pipe(ialu_reg_mem); 19.176 -// %} 19.177 +// Load Short (16 bit signed) into Long Register 19.178 +instruct loadS2L(rRegL dst, memory mem) 19.179 +%{ 19.180 + match(Set dst (ConvI2L (LoadS mem))); 19.181 + 19.182 + ins_cost(125); 19.183 + format %{ "movswq $dst, $mem\t# short -> long" %} 19.184 + 19.185 + ins_encode %{ 19.186 + __ movswq($dst$$Register, $mem$$Address); 19.187 + %} 19.188 + 19.189 + ins_pipe(ialu_reg_mem); 19.190 +%} 19.191 19.192 // Load Unsigned Short/Char (16 bit UNsigned) 19.193 instruct loadUS(rRegI dst, memory mem) 19.194 @@ -6103,32 +6119,71 @@ 19.195 19.196 ins_cost(125); 19.197 format %{ "movzwl $dst, $mem\t# ushort/char" %} 19.198 - opcode(0x0F, 0xB7); 19.199 - ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem)); 19.200 + 19.201 + ins_encode %{ 19.202 + __ movzwl($dst$$Register, $mem$$Address); 19.203 + %} 19.204 + 19.205 ins_pipe(ialu_reg_mem); 19.206 %} 19.207 19.208 -// Load Unsigned Short/Char (16 bit UNsigned) into long 19.209 -// instruct loadUS2L(rRegL dst, memory mem) 19.210 -// %{ 19.211 -// match(Set dst (ConvI2L (LoadUS mem))); 19.212 - 19.213 -// ins_cost(125); 19.214 -// format %{ "movzwl $dst, $mem\t# ushort/char -> long" %} 19.215 -// opcode(0x0F, 0xB7); 19.216 -// ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem)); 19.217 -// ins_pipe(ialu_reg_mem); 19.218 -// %} 19.219 +// Load Unsigned Short/Char (16 bit UNsigned) into Long Register 19.220 +instruct loadUS2L(rRegL dst, memory mem) 19.221 +%{ 19.222 + match(Set dst (ConvI2L (LoadUS mem))); 19.223 + 19.224 + ins_cost(125); 19.225 + format %{ "movzwq $dst, $mem\t# ushort/char -> long" %} 19.226 + 19.227 + ins_encode %{ 19.228 + __ movzwq($dst$$Register, $mem$$Address); 19.229 + %} 19.230 + 19.231 + ins_pipe(ialu_reg_mem); 19.232 +%} 19.233 19.234 // Load Integer 19.235 instruct loadI(rRegI dst, memory mem) 19.236 %{ 19.237 match(Set dst (LoadI mem)); 19.238 19.239 - ins_cost(125); // XXX 19.240 + ins_cost(125); 19.241 format %{ "movl $dst, $mem\t# int" %} 19.242 - opcode(0x8B); 19.243 - ins_encode(REX_reg_mem(dst, mem), OpcP, reg_mem(dst, mem)); 19.244 + 19.245 + ins_encode %{ 19.246 + __ movl($dst$$Register, $mem$$Address); 19.247 + %} 19.248 + 19.249 + ins_pipe(ialu_reg_mem); 19.250 +%} 19.251 + 19.252 +// Load Integer into Long Register 19.253 +instruct loadI2L(rRegL dst, memory mem) 19.254 +%{ 19.255 + match(Set dst (ConvI2L (LoadI mem))); 19.256 + 19.257 + ins_cost(125); 19.258 + format %{ "movslq $dst, $mem\t# int -> long" %} 19.259 + 19.260 + ins_encode %{ 19.261 + __ movslq($dst$$Register, $mem$$Address); 19.262 + %} 19.263 + 19.264 + ins_pipe(ialu_reg_mem); 19.265 +%} 19.266 + 19.267 +// Load Unsigned Integer into Long Register 19.268 +instruct loadUI2L(rRegL dst, memory mem) 19.269 +%{ 19.270 + match(Set dst (LoadUI2L mem)); 19.271 + 19.272 + ins_cost(125); 19.273 + format %{ "movl $dst, $mem\t# uint -> long" %} 19.274 + 19.275 + ins_encode %{ 19.276 + __ movl($dst$$Register, $mem$$Address); 19.277 + %} 19.278 + 19.279 ins_pipe(ialu_reg_mem); 19.280 %} 19.281 19.282 @@ -6137,10 +6192,13 @@ 19.283 %{ 19.284 match(Set dst (LoadL mem)); 19.285 19.286 - ins_cost(125); // XXX 19.287 + ins_cost(125); 19.288 format %{ "movq $dst, $mem\t# long" %} 19.289 - opcode(0x8B); 19.290 - ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem)); 19.291 + 19.292 + ins_encode %{ 19.293 + __ movq($dst$$Register, $mem$$Address); 19.294 + %} 19.295 + 19.296 ins_pipe(ialu_reg_mem); // XXX 19.297 %} 19.298 19.299 @@ -10804,16 +10862,6 @@ 19.300 // ins_pipe(ialu_reg_reg); 19.301 // %} 19.302 19.303 -instruct convI2L_reg_mem(rRegL dst, memory src) 19.304 -%{ 19.305 - match(Set dst (ConvI2L (LoadI src))); 19.306 - 19.307 - format %{ "movslq $dst, $src\t# i2l" %} 19.308 - opcode(0x63); // needs REX.W 19.309 - ins_encode(REX_reg_mem_wide(dst, src), OpcP, reg_mem(dst,src)); 19.310 - ins_pipe(ialu_reg_mem); 19.311 -%} 19.312 - 19.313 // Zero-extend convert int to long 19.314 instruct convI2L_reg_reg_zex(rRegL dst, rRegI src, immL_32bits mask) 19.315 %{
20.1 --- a/src/share/vm/adlc/forms.cpp Mon Mar 09 11:32:57 2009 -0400 20.2 +++ b/src/share/vm/adlc/forms.cpp Tue Mar 10 08:52:16 2009 -0700 20.3 @@ -70,6 +70,7 @@ 20.4 else return (_iter <_cur-1 ? _names[++_iter] : NULL); 20.5 } 20.6 const char *NameList::current() { return (_iter < _cur ? _names[_iter] : NULL); } 20.7 +const char *NameList::peek(int skip) { return (_iter + skip < _cur ? _names[_iter + skip] : NULL); } 20.8 20.9 // Return 'true' if current entry is signal 20.10 bool NameList::current_is_signal() { 20.11 @@ -248,11 +249,13 @@ 20.12 // True if 'opType', an ideal name, loads or stores. 20.13 Form::DataType Form::is_load_from_memory(const char *opType) const { 20.14 if( strcmp(opType,"LoadB")==0 ) return Form::idealB; 20.15 + if( strcmp(opType,"LoadUB")==0 ) return Form::idealB; 20.16 if( strcmp(opType,"LoadUS")==0 ) return Form::idealC; 20.17 if( strcmp(opType,"LoadD")==0 ) return Form::idealD; 20.18 if( strcmp(opType,"LoadD_unaligned")==0 ) return Form::idealD; 20.19 if( strcmp(opType,"LoadF")==0 ) return Form::idealF; 20.20 if( strcmp(opType,"LoadI")==0 ) return Form::idealI; 20.21 + if( strcmp(opType,"LoadUI2L")==0 ) return Form::idealI; 20.22 if( strcmp(opType,"LoadKlass")==0 ) return Form::idealP; 20.23 if( strcmp(opType,"LoadNKlass")==0 ) return Form::idealN; 20.24 if( strcmp(opType,"LoadL")==0 ) return Form::idealL;
21.1 --- a/src/share/vm/adlc/forms.hpp Mon Mar 09 11:32:57 2009 -0400 21.2 +++ b/src/share/vm/adlc/forms.hpp Tue Mar 10 08:52:16 2009 -0700 21.3 @@ -342,6 +342,7 @@ 21.4 void reset(); // Reset iteration 21.5 const char *iter(); // after reset(), first element : else next 21.6 const char *current(); // return current element in iteration. 21.7 + const char *peek(int skip = 1); // returns element + skip in iteration if there is one 21.8 21.9 bool current_is_signal(); // Return 'true' if current entry is signal 21.10 bool is_signal(const char *entry); // Return true if entry is a signal
22.1 --- a/src/share/vm/adlc/formssel.cpp Mon Mar 09 11:32:57 2009 -0400 22.2 +++ b/src/share/vm/adlc/formssel.cpp Tue Mar 10 08:52:16 2009 -0700 22.3 @@ -3310,8 +3310,8 @@ 22.4 static const char *needs_ideal_memory_list[] = { 22.5 "StoreI","StoreL","StoreP","StoreN","StoreD","StoreF" , 22.6 "StoreB","StoreC","Store" ,"StoreFP", 22.7 - "LoadI" ,"LoadL", "LoadP" ,"LoadN", "LoadD" ,"LoadF" , 22.8 - "LoadB" ,"LoadUS" ,"LoadS" ,"Load" , 22.9 + "LoadI", "LoadUI2L", "LoadL", "LoadP" ,"LoadN", "LoadD" ,"LoadF" , 22.10 + "LoadB" , "LoadUB", "LoadUS" ,"LoadS" ,"Load" , 22.11 "Store4I","Store2I","Store2L","Store2D","Store4F","Store2F","Store16B", 22.12 "Store8B","Store4B","Store8C","Store4C","Store2C", 22.13 "Load4I" ,"Load2I" ,"Load2L" ,"Load2D" ,"Load4F" ,"Load2F" ,"Load16B" , 22.14 @@ -3431,10 +3431,16 @@ 22.15 const InstructForm *form2_inst = form2 ? form2->is_instruction() : NULL; 22.16 const char *name_left = mRule2->_lChild ? mRule2->_lChild->_opType : NULL; 22.17 const char *name_right = mRule2->_rChild ? mRule2->_rChild->_opType : NULL; 22.18 + DataType data_type = Form::none; 22.19 + if (form->is_operand()) { 22.20 + // Make sure the loadX matches the type of the reg 22.21 + data_type = form->ideal_to_Reg_type(form->is_operand()->ideal_type(globals)); 22.22 + } 22.23 // Detect reg vs (loadX memory) 22.24 if( form->is_cisc_reg(globals) 22.25 && form2_inst 22.26 - && (is_load_from_memory(mRule2->_opType) != Form::none) // reg vs. (load memory) 22.27 + && data_type != Form::none 22.28 + && (is_load_from_memory(mRule2->_opType) == data_type) // reg vs. (load memory) 22.29 && (name_left != NULL) // NOT (load) 22.30 && (name_right == NULL) ) { // NOT (load memory foo) 22.31 const Form *form2_left = name_left ? globals[name_left] : NULL;
23.1 --- a/src/share/vm/adlc/output_c.cpp Mon Mar 09 11:32:57 2009 -0400 23.2 +++ b/src/share/vm/adlc/output_c.cpp Tue Mar 10 08:52:16 2009 -0700 23.3 @@ -2139,8 +2139,59 @@ 23.4 // A subfield variable, '$$' prefix 23.5 emit_field( rep_var ); 23.6 } else { 23.7 - // A replacement variable, '$' prefix 23.8 - emit_rep_var( rep_var ); 23.9 + if (_strings_to_emit.peek() != NULL && 23.10 + strcmp(_strings_to_emit.peek(), "$Address") == 0) { 23.11 + fprintf(_fp, "Address::make_raw("); 23.12 + 23.13 + emit_rep_var( rep_var ); 23.14 + fprintf(_fp,"->base(ra_,this,idx%d), ", _operand_idx); 23.15 + 23.16 + _reg_status = LITERAL_ACCESSED; 23.17 + emit_rep_var( rep_var ); 23.18 + fprintf(_fp,"->index(ra_,this,idx%d), ", _operand_idx); 23.19 + 23.20 + _reg_status = LITERAL_ACCESSED; 23.21 + emit_rep_var( rep_var ); 23.22 + fprintf(_fp,"->scale(), "); 23.23 + 23.24 + _reg_status = LITERAL_ACCESSED; 23.25 + emit_rep_var( rep_var ); 23.26 + Form::DataType stack_type = _operand ? _operand->is_user_name_for_sReg() : Form::none; 23.27 + if( _operand && _operand_idx==0 && stack_type != Form::none ) { 23.28 + fprintf(_fp,"->disp(ra_,this,0), "); 23.29 + } else { 23.30 + fprintf(_fp,"->disp(ra_,this,idx%d), ", _operand_idx); 23.31 + } 23.32 + 23.33 + _reg_status = LITERAL_ACCESSED; 23.34 + emit_rep_var( rep_var ); 23.35 + fprintf(_fp,"->disp_is_oop())"); 23.36 + 23.37 + // skip trailing $Address 23.38 + _strings_to_emit.iter(); 23.39 + } else { 23.40 + // A replacement variable, '$' prefix 23.41 + const char* next = _strings_to_emit.peek(); 23.42 + const char* next2 = _strings_to_emit.peek(2); 23.43 + if (next != NULL && next2 != NULL && strcmp(next2, "$Register") == 0 && 23.44 + (strcmp(next, "$base") == 0 || strcmp(next, "$index") == 0)) { 23.45 + // handle $rev_var$$base$$Register and $rev_var$$index$$Register by 23.46 + // producing as_Register(opnd_array(#)->base(ra_,this,idx1)). 23.47 + fprintf(_fp, "as_Register("); 23.48 + // emit the operand reference 23.49 + emit_rep_var( rep_var ); 23.50 + rep_var = _strings_to_emit.iter(); 23.51 + assert(strcmp(rep_var, "$base") == 0 || strcmp(rep_var, "$index") == 0, "bad pattern"); 23.52 + // handle base or index 23.53 + emit_field(rep_var); 23.54 + rep_var = _strings_to_emit.iter(); 23.55 + assert(strcmp(rep_var, "$Register") == 0, "bad pattern"); 23.56 + // close up the parens 23.57 + fprintf(_fp, ")"); 23.58 + } else { 23.59 + emit_rep_var( rep_var ); 23.60 + } 23.61 + } 23.62 } // end replacement and/or subfield 23.63 } 23.64 }
24.1 --- a/src/share/vm/asm/assembler.cpp Mon Mar 09 11:32:57 2009 -0400 24.2 +++ b/src/share/vm/asm/assembler.cpp Tue Mar 10 08:52:16 2009 -0700 24.3 @@ -239,6 +239,78 @@ 24.4 } 24.5 } 24.6 24.7 +struct DelayedConstant { 24.8 + typedef void (*value_fn_t)(); 24.9 + BasicType type; 24.10 + intptr_t value; 24.11 + value_fn_t value_fn; 24.12 + // This limit of 20 is generous for initial uses. 24.13 + // The limit needs to be large enough to store the field offsets 24.14 + // into classes which do not have statically fixed layouts. 24.15 + // (Initial use is for method handle object offsets.) 24.16 + // Look for uses of "delayed_value" in the source code 24.17 + // and make sure this number is generous enough to handle all of them. 24.18 + enum { DC_LIMIT = 20 }; 24.19 + static DelayedConstant delayed_constants[DC_LIMIT]; 24.20 + static DelayedConstant* add(BasicType type, value_fn_t value_fn); 24.21 + bool match(BasicType t, value_fn_t cfn) { 24.22 + return type == t && value_fn == cfn; 24.23 + } 24.24 + static void update_all(); 24.25 +}; 24.26 + 24.27 +DelayedConstant DelayedConstant::delayed_constants[DC_LIMIT]; 24.28 +// Default C structure initialization rules have the following effect here: 24.29 +// = { { (BasicType)0, (intptr_t)NULL }, ... }; 24.30 + 24.31 +DelayedConstant* DelayedConstant::add(BasicType type, 24.32 + DelayedConstant::value_fn_t cfn) { 24.33 + for (int i = 0; i < DC_LIMIT; i++) { 24.34 + DelayedConstant* dcon = &delayed_constants[i]; 24.35 + if (dcon->match(type, cfn)) 24.36 + return dcon; 24.37 + if (dcon->value_fn == NULL) { 24.38 + // (cmpxchg not because this is multi-threaded but because I'm paranoid) 24.39 + if (Atomic::cmpxchg_ptr(CAST_FROM_FN_PTR(void*, cfn), &dcon->value_fn, NULL) == NULL) { 24.40 + dcon->type = type; 24.41 + return dcon; 24.42 + } 24.43 + } 24.44 + } 24.45 + // If this assert is hit (in pre-integration testing!) then re-evaluate 24.46 + // the comment on the definition of DC_LIMIT. 24.47 + guarantee(false, "too many delayed constants"); 24.48 + return NULL; 24.49 +} 24.50 + 24.51 +void DelayedConstant::update_all() { 24.52 + for (int i = 0; i < DC_LIMIT; i++) { 24.53 + DelayedConstant* dcon = &delayed_constants[i]; 24.54 + if (dcon->value_fn != NULL && dcon->value == 0) { 24.55 + typedef int (*int_fn_t)(); 24.56 + typedef address (*address_fn_t)(); 24.57 + switch (dcon->type) { 24.58 + case T_INT: dcon->value = (intptr_t) ((int_fn_t) dcon->value_fn)(); break; 24.59 + case T_ADDRESS: dcon->value = (intptr_t) ((address_fn_t)dcon->value_fn)(); break; 24.60 + } 24.61 + } 24.62 + } 24.63 +} 24.64 + 24.65 +intptr_t* AbstractAssembler::delayed_value_addr(int(*value_fn)()) { 24.66 + DelayedConstant* dcon = DelayedConstant::add(T_INT, (DelayedConstant::value_fn_t) value_fn); 24.67 + return &dcon->value; 24.68 +} 24.69 +intptr_t* AbstractAssembler::delayed_value_addr(address(*value_fn)()) { 24.70 + DelayedConstant* dcon = DelayedConstant::add(T_ADDRESS, (DelayedConstant::value_fn_t) value_fn); 24.71 + return &dcon->value; 24.72 +} 24.73 +void AbstractAssembler::update_delayed_values() { 24.74 + DelayedConstant::update_all(); 24.75 +} 24.76 + 24.77 + 24.78 + 24.79 24.80 void AbstractAssembler::block_comment(const char* comment) { 24.81 if (sect() == CodeBuffer::SECT_INSTS) {
25.1 --- a/src/share/vm/asm/assembler.hpp Mon Mar 09 11:32:57 2009 -0400 25.2 +++ b/src/share/vm/asm/assembler.hpp Tue Mar 10 08:52:16 2009 -0700 25.3 @@ -140,6 +140,28 @@ 25.4 } 25.5 }; 25.6 25.7 +// A union type for code which has to assemble both constant and 25.8 +// non-constant operands, when the distinction cannot be made 25.9 +// statically. 25.10 +class RegisterConstant VALUE_OBJ_CLASS_SPEC { 25.11 + private: 25.12 + Register _r; 25.13 + intptr_t _c; 25.14 + 25.15 + public: 25.16 + RegisterConstant(): _r(noreg), _c(0) {} 25.17 + RegisterConstant(Register r): _r(r), _c(0) {} 25.18 + RegisterConstant(intptr_t c): _r(noreg), _c(c) {} 25.19 + 25.20 + Register as_register() const { assert(is_register(),""); return _r; } 25.21 + intptr_t as_constant() const { assert(is_constant(),""); return _c; } 25.22 + 25.23 + Register register_or_noreg() const { return _r; } 25.24 + intptr_t constant_or_zero() const { return _c; } 25.25 + 25.26 + bool is_register() const { return _r != noreg; } 25.27 + bool is_constant() const { return _r == noreg; } 25.28 +}; 25.29 25.30 // The Abstract Assembler: Pure assembler doing NO optimizations on the 25.31 // instruction level; i.e., what you write is what you get. 25.32 @@ -280,6 +302,26 @@ 25.33 inline address address_constant(Label& L); 25.34 inline address address_table_constant(GrowableArray<Label*> label); 25.35 25.36 + // Bootstrapping aid to cope with delayed determination of constants. 25.37 + // Returns a static address which will eventually contain the constant. 25.38 + // The value zero (NULL) stands instead of a constant which is still uncomputed. 25.39 + // Thus, the eventual value of the constant must not be zero. 25.40 + // This is fine, since this is designed for embedding object field 25.41 + // offsets in code which must be generated before the object class is loaded. 25.42 + // Field offsets are never zero, since an object's header (mark word) 25.43 + // is located at offset zero. 25.44 + RegisterConstant delayed_value(int(*value_fn)(), Register tmp, int offset = 0) { 25.45 + return delayed_value(delayed_value_addr(value_fn), tmp, offset); 25.46 + } 25.47 + RegisterConstant delayed_value(address(*value_fn)(), Register tmp, int offset = 0) { 25.48 + return delayed_value(delayed_value_addr(value_fn), tmp, offset); 25.49 + } 25.50 + virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr, Register tmp, int offset) = 0; 25.51 + // Last overloading is platform-dependent; look in assembler_<arch>.cpp. 25.52 + static intptr_t* delayed_value_addr(int(*constant_fn)()); 25.53 + static intptr_t* delayed_value_addr(address(*constant_fn)()); 25.54 + static void update_delayed_values(); 25.55 + 25.56 // Bang stack to trigger StackOverflowError at a safe location 25.57 // implementation delegates to machine-specific bang_stack_with_offset 25.58 void generate_stack_overflow_check( int frame_size_in_bytes );
26.1 --- a/src/share/vm/opto/classes.hpp Mon Mar 09 11:32:57 2009 -0400 26.2 +++ b/src/share/vm/opto/classes.hpp Tue Mar 10 08:52:16 2009 -0700 26.3 @@ -1,5 +1,5 @@ 26.4 /* 26.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 26.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 26.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 26.8 * 26.9 * This code is free software; you can redistribute it and/or modify it 26.10 @@ -129,11 +129,13 @@ 26.11 macro(LShiftI) 26.12 macro(LShiftL) 26.13 macro(LoadB) 26.14 +macro(LoadUB) 26.15 macro(LoadUS) 26.16 macro(LoadD) 26.17 macro(LoadD_unaligned) 26.18 macro(LoadF) 26.19 macro(LoadI) 26.20 +macro(LoadUI2L) 26.21 macro(LoadKlass) 26.22 macro(LoadNKlass) 26.23 macro(LoadL)
27.1 --- a/src/share/vm/opto/compile.cpp Mon Mar 09 11:32:57 2009 -0400 27.2 +++ b/src/share/vm/opto/compile.cpp Tue Mar 10 08:52:16 2009 -0700 27.3 @@ -1,5 +1,5 @@ 27.4 /* 27.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 27.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 27.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 27.8 * 27.9 * This code is free software; you can redistribute it and/or modify it 27.10 @@ -2005,8 +2005,10 @@ 27.11 case Op_StoreP: 27.12 case Op_StoreN: 27.13 case Op_LoadB: 27.14 + case Op_LoadUB: 27.15 case Op_LoadUS: 27.16 case Op_LoadI: 27.17 + case Op_LoadUI2L: 27.18 case Op_LoadKlass: 27.19 case Op_LoadNKlass: 27.20 case Op_LoadL:
28.1 --- a/src/share/vm/opto/gcm.cpp Mon Mar 09 11:32:57 2009 -0400 28.2 +++ b/src/share/vm/opto/gcm.cpp Tue Mar 10 08:52:16 2009 -0700 28.3 @@ -1901,7 +1901,8 @@ 28.4 for (int i = 0; i < _members.length(); i++) { 28.5 CFGElement* s = _members.at(i); 28.6 float block_freq = s->_freq * loop_freq; 28.7 - if (block_freq < MIN_BLOCK_FREQUENCY) block_freq = MIN_BLOCK_FREQUENCY; 28.8 + if (g_isnan(block_freq) || block_freq < MIN_BLOCK_FREQUENCY) 28.9 + block_freq = MIN_BLOCK_FREQUENCY; 28.10 s->_freq = block_freq; 28.11 } 28.12 CFGLoop* ch = _child;
29.1 --- a/src/share/vm/opto/memnode.cpp Mon Mar 09 11:32:57 2009 -0400 29.2 +++ b/src/share/vm/opto/memnode.cpp Tue Mar 10 08:52:16 2009 -0700 29.3 @@ -1,5 +1,5 @@ 29.4 /* 29.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 29.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 29.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 29.8 * 29.9 * This code is free software; you can redistribute it and/or modify it 29.10 @@ -778,7 +778,7 @@ 29.11 adr_type->offset() == arrayOopDesc::length_offset_in_bytes()), 29.12 "use LoadRangeNode instead"); 29.13 switch (bt) { 29.14 - case T_BOOLEAN: 29.15 + case T_BOOLEAN: return new (C, 3) LoadUBNode(ctl, mem, adr, adr_type, rt->is_int() ); 29.16 case T_BYTE: return new (C, 3) LoadBNode (ctl, mem, adr, adr_type, rt->is_int() ); 29.17 case T_INT: return new (C, 3) LoadINode (ctl, mem, adr, adr_type, rt->is_int() ); 29.18 case T_CHAR: return new (C, 3) LoadUSNode(ctl, mem, adr, adr_type, rt->is_int() ); 29.19 @@ -1616,6 +1616,22 @@ 29.20 return LoadNode::Ideal(phase, can_reshape); 29.21 } 29.22 29.23 +//--------------------------LoadUBNode::Ideal------------------------------------- 29.24 +// 29.25 +// If the previous store is to the same address as this load, 29.26 +// and the value stored was larger than a byte, replace this load 29.27 +// with the value stored truncated to a byte. If no truncation is 29.28 +// needed, the replacement is done in LoadNode::Identity(). 29.29 +// 29.30 +Node* LoadUBNode::Ideal(PhaseGVN* phase, bool can_reshape) { 29.31 + Node* mem = in(MemNode::Memory); 29.32 + Node* value = can_see_stored_value(mem, phase); 29.33 + if (value && !phase->type(value)->higher_equal(_type)) 29.34 + return new (phase->C, 3) AndINode(value, phase->intcon(0xFF)); 29.35 + // Identity call will handle the case where truncation is not needed. 29.36 + return LoadNode::Ideal(phase, can_reshape); 29.37 +} 29.38 + 29.39 //--------------------------LoadUSNode::Ideal------------------------------------- 29.40 // 29.41 // If the previous store is to the same address as this load,
30.1 --- a/src/share/vm/opto/memnode.hpp Mon Mar 09 11:32:57 2009 -0400 30.2 +++ b/src/share/vm/opto/memnode.hpp Tue Mar 10 08:52:16 2009 -0700 30.3 @@ -1,5 +1,5 @@ 30.4 /* 30.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 30.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 30.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 30.8 * 30.9 * This code is free software; you can redistribute it and/or modify it 30.10 @@ -207,6 +207,19 @@ 30.11 virtual BasicType memory_type() const { return T_BYTE; } 30.12 }; 30.13 30.14 +//------------------------------LoadUBNode------------------------------------- 30.15 +// Load a unsigned byte (8bits unsigned) from memory 30.16 +class LoadUBNode : public LoadNode { 30.17 +public: 30.18 + LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti = TypeInt::UBYTE ) 30.19 + : LoadNode(c, mem, adr, at, ti) {} 30.20 + virtual int Opcode() const; 30.21 + virtual uint ideal_reg() const { return Op_RegI; } 30.22 + virtual Node* Ideal(PhaseGVN *phase, bool can_reshape); 30.23 + virtual int store_Opcode() const { return Op_StoreB; } 30.24 + virtual BasicType memory_type() const { return T_BYTE; } 30.25 +}; 30.26 + 30.27 //------------------------------LoadUSNode------------------------------------- 30.28 // Load an unsigned short/char (16bits unsigned) from memory 30.29 class LoadUSNode : public LoadNode { 30.30 @@ -232,6 +245,18 @@ 30.31 virtual BasicType memory_type() const { return T_INT; } 30.32 }; 30.33 30.34 +//------------------------------LoadUI2LNode----------------------------------- 30.35 +// Load an unsigned integer into long from memory 30.36 +class LoadUI2LNode : public LoadNode { 30.37 +public: 30.38 + LoadUI2LNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeLong* t = TypeLong::UINT) 30.39 + : LoadNode(c, mem, adr, at, t) {} 30.40 + virtual int Opcode() const; 30.41 + virtual uint ideal_reg() const { return Op_RegL; } 30.42 + virtual int store_Opcode() const { return Op_StoreL; } 30.43 + virtual BasicType memory_type() const { return T_LONG; } 30.44 +}; 30.45 + 30.46 //------------------------------LoadRangeNode---------------------------------- 30.47 // Load an array length from the array 30.48 class LoadRangeNode : public LoadINode {
31.1 --- a/src/share/vm/opto/mulnode.cpp Mon Mar 09 11:32:57 2009 -0400 31.2 +++ b/src/share/vm/opto/mulnode.cpp Tue Mar 10 08:52:16 2009 -0700 31.3 @@ -486,20 +486,23 @@ 31.4 return new (phase->C, 3) AndINode(ldus, phase->intcon(mask&0xFFFF)); 31.5 } 31.6 31.7 - // Masking sign bits off of a Byte? Let the matcher use an unsigned load 31.8 - if( lop == Op_LoadB && 31.9 - (!in(0) && load->in(0)) && 31.10 - (mask == 0x000000FF) ) { 31.11 - // Associate this node with the LoadB, so the matcher can see them together. 31.12 - // If we don't do this, it is common for the LoadB to have one control 31.13 - // edge, and the store or call containing this AndI to have a different 31.14 - // control edge. This will cause Label_Root to group the AndI with 31.15 - // the encoding store or call, so the matcher has no chance to match 31.16 - // this AndI together with the LoadB. Setting the control edge here 31.17 - // prevents Label_Root from grouping the AndI with the store or call, 31.18 - // if it has a control edge that is inconsistent with the LoadB. 31.19 - set_req(0, load->in(0)); 31.20 - return this; 31.21 + // Masking sign bits off of a Byte? Do an unsigned byte load. 31.22 + if (lop == Op_LoadB && mask == 0x000000FF) { 31.23 + return new (phase->C, 3) LoadUBNode(load->in(MemNode::Control), 31.24 + load->in(MemNode::Memory), 31.25 + load->in(MemNode::Address), 31.26 + load->adr_type()); 31.27 + } 31.28 + 31.29 + // Masking sign bits off of a Byte plus additional lower bits? Do 31.30 + // an unsigned byte load plus an and. 31.31 + if (lop == Op_LoadB && (mask & 0xFFFFFF00) == 0) { 31.32 + Node* ldub = new (phase->C, 3) LoadUBNode(load->in(MemNode::Control), 31.33 + load->in(MemNode::Memory), 31.34 + load->in(MemNode::Address), 31.35 + load->adr_type()); 31.36 + ldub = phase->transform(ldub); 31.37 + return new (phase->C, 3) AndINode(ldub, phase->intcon(mask)); 31.38 } 31.39 31.40 // Masking off sign bits? Dont make them! 31.41 @@ -599,12 +602,21 @@ 31.42 if( !t2 || !t2->is_con() ) return MulNode::Ideal(phase, can_reshape); 31.43 const jlong mask = t2->get_con(); 31.44 31.45 - Node *rsh = in(1); 31.46 - uint rop = rsh->Opcode(); 31.47 + Node* in1 = in(1); 31.48 + uint op = in1->Opcode(); 31.49 + 31.50 + // Masking sign bits off of an integer? Do an unsigned integer to long load. 31.51 + if (op == Op_ConvI2L && in1->in(1)->Opcode() == Op_LoadI && mask == 0x00000000FFFFFFFFL) { 31.52 + Node* load = in1->in(1); 31.53 + return new (phase->C, 3) LoadUI2LNode(load->in(MemNode::Control), 31.54 + load->in(MemNode::Memory), 31.55 + load->in(MemNode::Address), 31.56 + load->adr_type()); 31.57 + } 31.58 31.59 // Masking off sign bits? Dont make them! 31.60 - if( rop == Op_RShiftL ) { 31.61 - const TypeInt *t12 = phase->type(rsh->in(2))->isa_int(); 31.62 + if (op == Op_RShiftL) { 31.63 + const TypeInt *t12 = phase->type(in1->in(2))->isa_int(); 31.64 if( t12 && t12->is_con() ) { // Shift is by a constant 31.65 int shift = t12->get_con(); 31.66 shift &= BitsPerJavaLong - 1; // semantics of Java shifts 31.67 @@ -613,7 +625,7 @@ 31.68 // bits survive. NO sign-extension bits survive the maskings. 31.69 if( (sign_bits_mask & mask) == 0 ) { 31.70 // Use zero-fill shift instead 31.71 - Node *zshift = phase->transform(new (phase->C, 3) URShiftLNode(rsh->in(1),rsh->in(2))); 31.72 + Node *zshift = phase->transform(new (phase->C, 3) URShiftLNode(in1->in(1), in1->in(2))); 31.73 return new (phase->C, 3) AndLNode( zshift, in(2) ); 31.74 } 31.75 }
32.1 --- a/src/share/vm/opto/type.cpp Mon Mar 09 11:32:57 2009 -0400 32.2 +++ b/src/share/vm/opto/type.cpp Tue Mar 10 08:52:16 2009 -0700 32.3 @@ -1,5 +1,5 @@ 32.4 /* 32.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 32.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 32.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 32.8 * 32.9 * This code is free software; you can redistribute it and/or modify it 32.10 @@ -226,6 +226,7 @@ 32.11 TypeInt::CC_LE = TypeInt::make(-1, 0, WidenMin); 32.12 TypeInt::CC_GE = TypeInt::make( 0, 1, WidenMin); // == TypeInt::BOOL 32.13 TypeInt::BYTE = TypeInt::make(-128,127, WidenMin); // Bytes 32.14 + TypeInt::UBYTE = TypeInt::make(0, 255, WidenMin); // Unsigned Bytes 32.15 TypeInt::CHAR = TypeInt::make(0,65535, WidenMin); // Java chars 32.16 TypeInt::SHORT = TypeInt::make(-32768,32767, WidenMin); // Java shorts 32.17 TypeInt::POS = TypeInt::make(0,max_jint, WidenMin); // Non-neg values 32.18 @@ -1022,6 +1023,7 @@ 32.19 const TypeInt *TypeInt::CC_LE; // [-1,0] 32.20 const TypeInt *TypeInt::CC_GE; // [0,1] == BOOL (!) 32.21 const TypeInt *TypeInt::BYTE; // Bytes, -128 to 127 32.22 +const TypeInt *TypeInt::UBYTE; // Unsigned Bytes, 0 to 255 32.23 const TypeInt *TypeInt::CHAR; // Java chars, 0-65535 32.24 const TypeInt *TypeInt::SHORT; // Java shorts, -32768-32767 32.25 const TypeInt *TypeInt::POS; // Positive 32-bit integers or zero
33.1 --- a/src/share/vm/opto/type.hpp Mon Mar 09 11:32:57 2009 -0400 33.2 +++ b/src/share/vm/opto/type.hpp Tue Mar 10 08:52:16 2009 -0700 33.3 @@ -1,5 +1,5 @@ 33.4 /* 33.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 33.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 33.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 33.8 * 33.9 * This code is free software; you can redistribute it and/or modify it 33.10 @@ -415,6 +415,7 @@ 33.11 static const TypeInt *CC_LE; // [-1,0] 33.12 static const TypeInt *CC_GE; // [0,1] == BOOL (!) 33.13 static const TypeInt *BYTE; 33.14 + static const TypeInt *UBYTE; 33.15 static const TypeInt *CHAR; 33.16 static const TypeInt *SHORT; 33.17 static const TypeInt *POS;
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/test/compiler/6797305/Test6797305.java Tue Mar 10 08:52:16 2009 -0700 34.3 @@ -0,0 +1,114 @@ 34.4 +/* 34.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 34.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 34.7 + * 34.8 + * This code is free software; you can redistribute it and/or modify it 34.9 + * under the terms of the GNU General Public License version 2 only, as 34.10 + * published by the Free Software Foundation. 34.11 + * 34.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 34.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 34.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 34.15 + * version 2 for more details (a copy is included in the LICENSE file that 34.16 + * accompanied this code). 34.17 + * 34.18 + * You should have received a copy of the GNU General Public License version 34.19 + * 2 along with this work; if not, write to the Free Software Foundation, 34.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 34.21 + * 34.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 34.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 34.24 + * have any questions. 34.25 + */ 34.26 + 34.27 +/** 34.28 + * @test 34.29 + * @bug 6797305 34.30 + * @summary Add LoadUB and LoadUI opcode class 34.31 + * 34.32 + * @run main/othervm -Xcomp -XX:CompileOnly=Test6797305.loadB,Test6797305.loadB2L,Test6797305.loadUB,Test6797305.loadUBmask,Test6797305.loadUB2L,Test6797305.loadS,Test6797305.loadS2L,Test6797305.loadUS,Test6797305.loadUSmask,Test6797305.loadUS2L,Test6797305.loadI,Test6797305.loadI2L,Test6797305.loadUI2L,Test6797305.loadL Test6797305 34.33 + */ 34.34 + 34.35 +public class Test6797305 { 34.36 + static final byte[] ba = new byte[] { -1 }; 34.37 + static final short[] sa = new short[] { -1 }; 34.38 + static final int[] ia = new int[] { -1 }; 34.39 + static final long[] la = new long[] { -1 }; 34.40 + 34.41 + public static void main(String[] args) 34.42 + { 34.43 + long b = loadB(ba); 34.44 + if (b != -1) 34.45 + throw new InternalError("loadB failed: " + b + " != " + -1); 34.46 + 34.47 + long b2l = loadB2L(ba); 34.48 + if (b2l != -1L) 34.49 + throw new InternalError("loadB2L failed: " + b2l + " != " + -1L); 34.50 + 34.51 + int ub = loadUB(ba); 34.52 + if (ub != 0xFF) 34.53 + throw new InternalError("loadUB failed: " + ub + " != " + 0xFF); 34.54 + 34.55 + int ubmask = loadUBmask(ba); 34.56 + if (ubmask != 0xFE) 34.57 + throw new InternalError("loadUBmask failed: " + ubmask + " != " + 0xFE); 34.58 + 34.59 + long ub2l = loadUB2L(ba); 34.60 + if (ub2l != 0xFFL) 34.61 + throw new InternalError("loadUB2L failed: " + ub2l + " != " + 0xFFL); 34.62 + 34.63 + int s = loadS(sa); 34.64 + if (s != -1) 34.65 + throw new InternalError("loadS failed: " + s + " != " + -1); 34.66 + 34.67 + long s2l = loadS2L(sa); 34.68 + if (s2l != -1L) 34.69 + throw new InternalError("loadS2L failed: " + s2l + " != " + -1L); 34.70 + 34.71 + int us = loadUS(sa); 34.72 + if (us != 0xFFFF) 34.73 + throw new InternalError("loadUS failed: " + us + " != " + 0xFFFF); 34.74 + 34.75 + int usmask = loadUSmask(sa); 34.76 + if (usmask != 0xFFFE) 34.77 + throw new InternalError("loadUBmask failed: " + ubmask + " != " + 0xFFFE); 34.78 + 34.79 + long us2l = loadUS2L(sa); 34.80 + if (us2l != 0xFFFFL) 34.81 + throw new InternalError("loadUS2L failed: " + us2l + " != " + 0xFFFFL); 34.82 + 34.83 + int i = loadI(ia); 34.84 + if (i != -1) 34.85 + throw new InternalError("loadI failed: " + i + " != " + -1); 34.86 + 34.87 + long i2l = loadI2L(ia); 34.88 + if (i2l != -1L) 34.89 + throw new InternalError("loadI2L failed: " + i2l + " != " + -1L); 34.90 + 34.91 + long ui2l = loadUI2L(ia); 34.92 + if (ui2l != 0xFFFFFFFFL) 34.93 + throw new InternalError("loadUI2L failed: " + ui2l + " != " + 0xFFFFFFFFL); 34.94 + 34.95 + long l = loadL(la); 34.96 + if (l != -1L) 34.97 + throw new InternalError("loadL failed: " + l + " != " + -1L); 34.98 + } 34.99 + 34.100 + static int loadB (byte[] ba) { return ba[0]; } 34.101 + static long loadB2L (byte[] ba) { return ba[0]; } 34.102 + static int loadUB (byte[] ba) { return ba[0] & 0xFF; } 34.103 + static int loadUBmask(byte[] ba) { return ba[0] & 0xFE; } 34.104 + static long loadUB2L (byte[] ba) { return ba[0] & 0xFF; } 34.105 + 34.106 + static int loadS (short[] sa) { return sa[0]; } 34.107 + static long loadS2L (short[] sa) { return sa[0]; } 34.108 + static int loadUS (short[] sa) { return sa[0] & 0xFFFF; } 34.109 + static int loadUSmask(short[] sa) { return sa[0] & 0xFFFE; } 34.110 + static long loadUS2L (short[] sa) { return sa[0] & 0xFFFF; } 34.111 + 34.112 + static int loadI (int[] ia) { return ia[0]; } 34.113 + static long loadI2L (int[] ia) { return ia[0]; } 34.114 + static long loadUI2L (int[] ia) { return ia[0] & 0xFFFFFFFFL; } 34.115 + 34.116 + static long loadL (long[] la) { return la[0]; } 34.117 +}