Mercurial > hg > truffle
diff src/cpu/sparc/vm/sparc.ad @ 113:ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
Summary: Compressed oops in instances, arrays, and headers. Code contributors are coleenp, phh, never, swamyv
Reviewed-by: jmasa, kamg, acorn, tbell, kvn, rasbold
author | coleenp |
---|---|
date | Sun, 13 Apr 2008 17:43:42 -0400 |
parents | dee7a3f3dc9d |
children | b130b98db9cf |
line wrap: on
line diff
--- a/src/cpu/sparc/vm/sparc.ad Fri Apr 11 09:56:35 2008 -0400 +++ b/src/cpu/sparc/vm/sparc.ad Sun Apr 13 17:43:42 2008 -0400 @@ -544,11 +544,19 @@ assert(!UseInlineCaches, "expect vtable calls only if not using ICs"); int entry_offset = instanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size(); int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes(); + int klass_load_size; + if (UseCompressedOops) { + klass_load_size = 3*BytesPerInstWord; // see MacroAssembler::load_klass() + } else { + klass_load_size = 1*BytesPerInstWord; + } if( Assembler::is_simm13(v_off) ) { - return (3*BytesPerInstWord + // ld_ptr, ld_ptr, ld_ptr + return klass_load_size + + (2*BytesPerInstWord + // ld_ptr, ld_ptr NativeCall::instruction_size); // call; delay slot } else { - return (5*BytesPerInstWord + // ld_ptr, set_hi, set, ld_ptr, ld_ptr + return klass_load_size + + (4*BytesPerInstWord + // set_hi, set, ld_ptr, ld_ptr NativeCall::instruction_size); // call; delay slot } } @@ -1591,7 +1599,13 @@ void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { st->print_cr("\nUEP:"); #ifdef _LP64 - st->print_cr("\tLDX [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check"); + if (UseCompressedOops) { + st->print_cr("\tLDUW [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check - compressed klass"); + st->print_cr("\tSLL R_G5,3,R_G5"); + st->print_cr("\tADD R_G5,R_G6_heap_base,R_G5"); + } else { + st->print_cr("\tLDX [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check"); + } st->print_cr("\tCMP R_G5,R_G3" ); st->print ("\tTne xcc,R_G0+ST_RESERVED_FOR_USER_0+2"); #else // _LP64 @@ -1610,7 +1624,7 @@ assert( G5_ic_reg != temp_reg, "conflicting registers" ); // Load klass from reciever - __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), temp_reg); + __ load_klass(O0, temp_reg); // Compare against expected klass __ cmp(temp_reg, G5_ic_reg); // Branch to miss code, checks xcc or icc depending @@ -1811,6 +1825,11 @@ reg == R_I3H_num || reg == R_I4H_num || reg == R_I5H_num ) return true; + + if ((UseCompressedOops) && (reg == R_G6_num || reg == R_G6H_num)) { + return true; + } + #else // 32-bit builds with longs-in-one-entry pass longs in G1 & G4. // Longs cannot be passed in O regs, because O regs become I regs @@ -2474,7 +2493,13 @@ // get receiver klass (receiver already checked for non-null) // If we end up going thru a c2i adapter interpreter expects method in G5 int off = __ offset(); - __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), G3_scratch); + __ load_klass(O0, G3_scratch); + int klass_load_size; + if (UseCompressedOops) { + klass_load_size = 3*BytesPerInstWord; + } else { + klass_load_size = 1*BytesPerInstWord; + } int entry_offset = instanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size(); int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes(); if( __ is_simm13(v_off) ) { @@ -2484,7 +2509,8 @@ __ Assembler::sethi(v_off & ~0x3ff, G5_method); __ or3(G5_method, v_off & 0x3ff, G5_method); // ld_ptr, set_hi, set - assert(__ offset() - off == 3*BytesPerInstWord, "Unexpected instruction size(s)"); + assert(__ offset() - off == klass_load_size + 2*BytesPerInstWord, + "Unexpected instruction size(s)"); __ ld_ptr(G3, G5_method, G5_method); } // NOTE: for vtable dispatches, the vtable entry will never be null. @@ -2860,12 +2886,12 @@ int count_offset = java_lang_String:: count_offset_in_bytes(); // load str1 (jchar*) base address into tmp1_reg - __ ld_ptr(Address(str1_reg, 0, value_offset), tmp1_reg); + __ load_heap_oop(Address(str1_reg, 0, value_offset), tmp1_reg); __ ld(Address(str1_reg, 0, offset_offset), result_reg); __ add(tmp1_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1_reg); __ ld(Address(str1_reg, 0, count_offset), str1_reg); // hoisted __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg); - __ ld_ptr(Address(str2_reg, 0, value_offset), tmp2_reg); // hoisted + __ load_heap_oop(Address(str2_reg, 0, value_offset), tmp2_reg); // hoisted __ add(result_reg, tmp1_reg, tmp1_reg); // load str2 (jchar*) base address into tmp2_reg @@ -3016,6 +3042,7 @@ MacroAssembler _masm(&cbuf); __ membar( Assembler::Membar_mask_bits(Assembler::StoreLoad) ); %} + enc_class enc_repl8b( iRegI src, iRegL dst ) %{ MacroAssembler _masm(&cbuf); Register src_reg = reg_to_register_object($src$$reg); @@ -3189,15 +3216,15 @@ c_return_value %{ assert( ideal_reg >= Op_RegI && ideal_reg <= Op_RegL, "only return normal values" ); #ifdef _LP64 - static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_O0_num }; - static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_O0H_num, OptoReg::Bad, R_F1_num, R_O0H_num}; - static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_I0_num }; - static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_I0H_num, OptoReg::Bad, R_F1_num, R_I0H_num}; + static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_O0_num }; + static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_O0H_num, OptoReg::Bad, R_F1_num, R_O0H_num}; + static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_I0_num }; + static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_I0H_num, OptoReg::Bad, R_F1_num, R_I0H_num}; #else // !_LP64 - static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_G1_num }; - static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num }; - static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_G1_num }; - static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num }; + static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_G1_num }; + static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num }; + static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_G1_num }; + static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num }; #endif return OptoRegPair( (is_outgoing?hi_out:hi_in)[ideal_reg], (is_outgoing?lo_out:lo_in)[ideal_reg] ); @@ -3207,15 +3234,15 @@ return_value %{ assert( ideal_reg >= Op_RegI && ideal_reg <= Op_RegL, "only return normal values" ); #ifdef _LP64 - static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_O0_num }; - static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_O0H_num, OptoReg::Bad, R_F1_num, R_O0H_num}; - static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_I0_num }; - static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_I0H_num, OptoReg::Bad, R_F1_num, R_I0H_num}; + static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_O0_num }; + static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_O0H_num, OptoReg::Bad, R_F1_num, R_O0H_num}; + static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_I0_num }; + static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_I0H_num, OptoReg::Bad, R_F1_num, R_I0H_num}; #else // !_LP64 - static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_G1_num }; - static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num}; - static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_G1_num }; - static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num}; + static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_G1_num }; + static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num}; + static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_G1_num }; + static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num}; #endif return OptoRegPair( (is_outgoing?hi_out:hi_in)[ideal_reg], (is_outgoing?lo_out:lo_in)[ideal_reg] ); @@ -3408,6 +3435,27 @@ interface(CONST_INTER); %} +// Pointer Immediate +operand immN() +%{ + match(ConN); + + op_cost(10); + format %{ %} + interface(CONST_INTER); +%} + +// NULL Pointer Immediate +operand immN0() +%{ + predicate(n->get_narrowcon() == 0); + match(ConN); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + operand immL() %{ match(ConL); op_cost(40); @@ -3672,6 +3720,14 @@ interface(REG_INTER); %} +operand iRegN() %{ + constraint(ALLOC_IN_RC(int_reg)); + match(RegN); + + format %{ %} + interface(REG_INTER); +%} + // Long Register operand iRegL() %{ constraint(ALLOC_IN_RC(long_reg)); @@ -5392,9 +5448,30 @@ ins_pipe(iload_mem); %} +// Load Compressed Pointer +instruct loadN(iRegN dst, memory mem) %{ + match(Set dst (LoadN mem)); + ins_cost(MEMORY_REF_COST); + size(4); + + format %{ "LDUW $mem,$dst\t! compressed ptr" %} + ins_encode %{ + Register base = as_Register($mem$$base); + Register index = as_Register($mem$$index); + Register dst = $dst$$Register; + if (index != G0) { + __ lduw(base, index, dst); + } else { + __ lduw(base, $mem$$disp, dst); + } + %} + ins_pipe(iload_mem); +%} + // Load Klass Pointer instruct loadKlass(iRegP dst, memory mem) %{ match(Set dst (LoadKlass mem)); + predicate(!n->in(MemNode::Address)->bottom_type()->is_narrow()); ins_cost(MEMORY_REF_COST); size(4); @@ -5409,6 +5486,30 @@ ins_pipe(iload_mem); %} +// Load Klass Pointer +instruct loadKlassComp(iRegP dst, memory mem) %{ + match(Set dst (LoadKlass mem)); + predicate(n->in(MemNode::Address)->bottom_type()->is_narrow()); + ins_cost(MEMORY_REF_COST); + + format %{ "LDUW $mem,$dst\t! compressed klass ptr" %} + + ins_encode %{ + Register base = as_Register($mem$$base); + Register index = as_Register($mem$$index); + Register dst = $dst$$Register; + if (index != G0) { + __ lduw(base, index, dst); + } else { + __ lduw(base, $mem$$disp, dst); + } + // klass oop never null but this is generated for nonheader klass loads + // too which can be null. + __ decode_heap_oop(dst); + %} + ins_pipe(iload_mem); +%} + // Load Short (16bit signed) instruct loadS(iRegI dst, memory mem) %{ match(Set dst (LoadS mem)); @@ -5508,6 +5609,24 @@ ins_pipe(loadConP_poll); %} +instruct loadConN(iRegN dst, immN src) %{ + match(Set dst src); + ins_cost(DEFAULT_COST * 2); + format %{ "SET $src,$dst\t!ptr" %} + ins_encode %{ + address con = (address)$src$$constant; + Register dst = $dst$$Register; + if (con == NULL) { + __ mov(G0, dst); + } else { + __ set_oop((jobject)$src$$constant, dst); + __ encode_heap_oop(dst); + } + %} + ins_pipe(loadConP); + +%} + instruct loadConL(iRegL dst, immL src, o7RegL tmp) %{ // %%% maybe this should work like loadConD match(Set dst src); @@ -5741,6 +5860,44 @@ ins_pipe(istore_mem_zero); %} +// Store Compressed Pointer +instruct storeN(memory dst, iRegN src) %{ + match(Set dst (StoreN dst src)); + ins_cost(MEMORY_REF_COST); + size(4); + + format %{ "STW $src,$dst\t! compressed ptr" %} + ins_encode %{ + Register base = as_Register($dst$$base); + Register index = as_Register($dst$$index); + Register src = $src$$Register; + if (index != G0) { + __ stw(src, base, index); + } else { + __ stw(src, base, $dst$$disp); + } + %} + ins_pipe(istore_mem_spORreg); +%} + +instruct storeN0(memory dst, immN0 src) %{ + match(Set dst (StoreN dst src)); + ins_cost(MEMORY_REF_COST); + size(4); + + format %{ "STW $src,$dst\t! compressed ptr" %} + ins_encode %{ + Register base = as_Register($dst$$base); + Register index = as_Register($dst$$index); + if (index != G0) { + __ stw(0, base, index); + } else { + __ stw(0, base, $dst$$disp); + } + %} + ins_pipe(istore_mem_zero); +%} + // Store Double instruct storeD( memory mem, regD src) %{ match(Set mem (StoreD mem src)); @@ -5798,6 +5955,26 @@ ins_pipe(fstoreD_mem_reg); %} +// Convert oop pointer into compressed form +instruct encodeHeapOop(iRegN dst, iRegP src) %{ + match(Set dst (EncodeP src)); + format %{ "SRL $src,3,$dst\t encodeHeapOop" %} + ins_encode %{ + __ encode_heap_oop($src$$Register, $dst$$Register); + %} + ins_pipe(ialu_reg); +%} + +instruct decodeHeapOop(iRegP dst, iRegN src) %{ + match(Set dst (DecodeN src)); + format %{ "decode_heap_oop $src, $dst" %} + ins_encode %{ + __ decode_heap_oop($src$$Register, $dst$$Register); + %} + ins_pipe(ialu_reg); +%} + + // Store Zero into Aligned Packed Bytes instruct storeA8B0(memory mem, immI0 zero) %{ match(Set mem (Store8B mem zero)); @@ -6434,17 +6611,27 @@ instruct compareAndSwapP_bool(iRegP mem_ptr, iRegP oldval, iRegP newval, iRegI res, o7RegI tmp1, flagsReg ccr ) %{ match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval))); effect( USE mem_ptr, KILL ccr, KILL tmp1); -#ifdef _LP64 format %{ "MOV $newval,O7\n\t" - "CASXA [$mem_ptr],$oldval,O7\t! If $oldval==[$mem_ptr] Then store O7 into [$mem_ptr], set O7=[$mem_ptr] in any case\n\t" + "CASA_PTR [$mem_ptr],$oldval,O7\t! If $oldval==[$mem_ptr] Then store O7 into [$mem_ptr], set O7=[$mem_ptr] in any case\n\t" "CMP $oldval,O7\t\t! See if we made progress\n\t" "MOV 1,$res\n\t" "MOVne xcc,R_G0,$res" %} +#ifdef _LP64 ins_encode( enc_casx(mem_ptr, oldval, newval), enc_lflags_ne_to_boolean(res) ); #else + ins_encode( enc_casi(mem_ptr, oldval, newval), + enc_iflags_ne_to_boolean(res) ); +#endif + ins_pipe( long_memory_op ); +%} + +instruct compareAndSwapN_bool_comp(iRegP mem_ptr, iRegN oldval, iRegN newval, iRegI res, o7RegI tmp, flagsReg ccr ) %{ + match(Set res (CompareAndSwapN mem_ptr (Binary oldval newval))); + effect( USE mem_ptr, KILL ccr, KILL tmp); + format %{ "MOV $newval,O7\n\t" "CASA [$mem_ptr],$oldval,O7\t! If $oldval==[$mem_ptr] Then store O7 into [$mem_ptr], set O7=[$mem_ptr] in any case\n\t" @@ -6452,9 +6639,18 @@ "MOV 1,$res\n\t" "MOVne icc,R_G0,$res" %} - ins_encode( enc_casi(mem_ptr, oldval, newval), - enc_iflags_ne_to_boolean(res) ); -#endif + ins_encode %{ + Register Rmem = reg_to_register_object($mem_ptr$$reg); + Register Rold = reg_to_register_object($oldval$$reg); + Register Rnew = reg_to_register_object($newval$$reg); + Register Rres = reg_to_register_object($res$$reg); + + __ cas(Rmem, Rold, Rnew); + __ cmp( Rold, Rnew ); + __ mov(1, Rres); + __ movcc( Assembler::notEqual, false, Assembler::icc, G0, Rres ); + %} + ins_pipe( long_memory_op ); %} @@ -8607,6 +8803,17 @@ ins_pipe(partial_subtype_check_pipe); %} + +instruct compP_iRegN_immN0(flagsRegP pcc, iRegN op1, immN0 op2 ) %{ + match(Set pcc (CmpN op1 op2)); + + size(4); + format %{ "CMP $op1,$op2\t! ptr" %} + opcode(Assembler::subcc_op3, Assembler::arith_op); + ins_encode( form3_rs1_simm13_rd( op1, op2, R_G0 ) ); + ins_pipe(ialu_cconly_reg_imm); +%} + // ============================================================================ // inlined locking and unlocking @@ -8648,9 +8855,10 @@ ins_pipe(long_memory_op); %} -instruct string_compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result, flagsReg ccr) %{ +instruct string_compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result, + o7RegI tmp3, flagsReg ccr) %{ match(Set result (StrComp str1 str2)); - effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr); + effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3); ins_cost(300); format %{ "String Compare $str1,$str2 -> $result" %} ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, result) );