Thu, 02 Apr 2009 17:01:00 -0700
Merge
1.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/StubRoutines.java Wed Apr 01 22:31:26 2009 -0700 1.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/StubRoutines.java Thu Apr 02 17:01:00 2009 -0700 1.3 @@ -46,12 +46,18 @@ 1.4 Type type = db.lookupType("StubRoutines"); 1.5 1.6 callStubReturnAddressField = type.getAddressField("_call_stub_return_address"); 1.7 - // Only some platforms have specif return from compiled to call_stub 1.8 + // Only some platforms have specific return from compiled to call_stub 1.9 try { 1.10 - callStubCompiledReturnAddressField = type.getAddressField("_call_stub_compiled_return"); 1.11 + type = db.lookupType("StubRoutines::x86"); 1.12 + if (type != null) { 1.13 + callStubCompiledReturnAddressField = type.getAddressField("_call_stub_compiled_return"); 1.14 + } 1.15 } catch (RuntimeException re) { 1.16 callStubCompiledReturnAddressField = null; 1.17 } 1.18 + if (callStubCompiledReturnAddressField == null && VM.getVM().getCPU().equals("x86")) { 1.19 + throw new InternalError("Missing definition for _call_stub_compiled_return"); 1.20 + } 1.21 } 1.22 1.23 public StubRoutines() {
2.1 --- a/src/cpu/sparc/vm/assembler_sparc.cpp Wed Apr 01 22:31:26 2009 -0700 2.2 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp Thu Apr 02 17:01:00 2009 -0700 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 2.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 2.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.8 * 2.9 * This code is free software; you can redistribute it and/or modify it 2.10 @@ -2615,12 +2615,12 @@ 2.11 } 2.12 } 2.13 2.14 -RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr, 2.15 - Register tmp, 2.16 - int offset) { 2.17 +RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr, 2.18 + Register tmp, 2.19 + int offset) { 2.20 intptr_t value = *delayed_value_addr; 2.21 if (value != 0) 2.22 - return RegisterConstant(value + offset); 2.23 + return RegisterOrConstant(value + offset); 2.24 2.25 // load indirectly to solve generation ordering problem 2.26 Address a(tmp, (address) delayed_value_addr); 2.27 @@ -2634,11 +2634,11 @@ 2.28 if (offset != 0) 2.29 add(tmp, offset, tmp); 2.30 2.31 - return RegisterConstant(tmp); 2.32 + return RegisterOrConstant(tmp); 2.33 } 2.34 2.35 2.36 -void MacroAssembler::regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) { 2.37 +void MacroAssembler::regcon_inc_ptr( RegisterOrConstant& dest, RegisterOrConstant src, Register temp ) { 2.38 assert(dest.register_or_noreg() != G0, "lost side effect"); 2.39 if ((src.is_constant() && src.as_constant() == 0) || 2.40 (src.is_register() && src.as_register() == G0)) { 2.41 @@ -2647,15 +2647,15 @@ 2.42 add(dest.as_register(), ensure_rs2(src, temp), dest.as_register()); 2.43 } else if (src.is_constant()) { 2.44 intptr_t res = dest.as_constant() + src.as_constant(); 2.45 - dest = RegisterConstant(res); // side effect seen by caller 2.46 + dest = RegisterOrConstant(res); // side effect seen by caller 2.47 } else { 2.48 assert(temp != noreg, "cannot handle constant += register"); 2.49 add(src.as_register(), ensure_rs2(dest, temp), temp); 2.50 - dest = RegisterConstant(temp); // side effect seen by caller 2.51 + dest = RegisterOrConstant(temp); // side effect seen by caller 2.52 } 2.53 } 2.54 2.55 -void MacroAssembler::regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) { 2.56 +void MacroAssembler::regcon_sll_ptr( RegisterOrConstant& dest, RegisterOrConstant src, Register temp ) { 2.57 assert(dest.register_or_noreg() != G0, "lost side effect"); 2.58 if (!is_simm13(src.constant_or_zero())) 2.59 src = (src.as_constant() & 0xFF); 2.60 @@ -2666,12 +2666,12 @@ 2.61 sll_ptr(dest.as_register(), src, dest.as_register()); 2.62 } else if (src.is_constant()) { 2.63 intptr_t res = dest.as_constant() << src.as_constant(); 2.64 - dest = RegisterConstant(res); // side effect seen by caller 2.65 + dest = RegisterOrConstant(res); // side effect seen by caller 2.66 } else { 2.67 assert(temp != noreg, "cannot handle constant <<= register"); 2.68 set(dest.as_constant(), temp); 2.69 sll_ptr(temp, src, temp); 2.70 - dest = RegisterConstant(temp); // side effect seen by caller 2.71 + dest = RegisterOrConstant(temp); // side effect seen by caller 2.72 } 2.73 } 2.74 2.75 @@ -2683,7 +2683,7 @@ 2.76 // On failure, execution transfers to the given label. 2.77 void MacroAssembler::lookup_interface_method(Register recv_klass, 2.78 Register intf_klass, 2.79 - RegisterConstant itable_index, 2.80 + RegisterOrConstant itable_index, 2.81 Register method_result, 2.82 Register scan_temp, 2.83 Register sethi_temp, 2.84 @@ -2720,7 +2720,7 @@ 2.85 add(recv_klass, scan_temp, scan_temp); 2.86 2.87 // Adjust recv_klass by scaled itable_index, so we can free itable_index. 2.88 - RegisterConstant itable_offset = itable_index; 2.89 + RegisterOrConstant itable_offset = itable_index; 2.90 regcon_sll_ptr(itable_offset, exact_log2(itableMethodEntry::size() * wordSize)); 2.91 regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes()); 2.92 add(recv_klass, ensure_rs2(itable_offset, sethi_temp), recv_klass); 2.93 @@ -2805,7 +2805,7 @@ 2.94 Label* L_success, 2.95 Label* L_failure, 2.96 Label* L_slow_path, 2.97 - RegisterConstant super_check_offset, 2.98 + RegisterOrConstant super_check_offset, 2.99 Register instanceof_hack) { 2.100 int sc_offset = (klassOopDesc::header_size() * HeapWordSize + 2.101 Klass::secondary_super_cache_offset_in_bytes()); 2.102 @@ -2867,7 +2867,7 @@ 2.103 if (must_load_sco) { 2.104 // The super check offset is always positive... 2.105 lduw(super_klass, sco_offset, temp2_reg); 2.106 - super_check_offset = RegisterConstant(temp2_reg); 2.107 + super_check_offset = RegisterOrConstant(temp2_reg); 2.108 } 2.109 ld_ptr(sub_klass, super_check_offset, temp_reg); 2.110 cmp(super_klass, temp_reg); 2.111 @@ -4234,7 +4234,6 @@ 2.112 static jint num_ct_writes = 0; 2.113 static jint num_ct_writes_filtered_in_hr = 0; 2.114 static jint num_ct_writes_filtered_null = 0; 2.115 -static jint num_ct_writes_filtered_pop = 0; 2.116 static G1CollectedHeap* g1 = NULL; 2.117 2.118 static Thread* count_ct_writes(void* filter_val, void* new_val) { 2.119 @@ -4247,25 +4246,19 @@ 2.120 if (g1 == NULL) { 2.121 g1 = G1CollectedHeap::heap(); 2.122 } 2.123 - if ((HeapWord*)new_val < g1->popular_object_boundary()) { 2.124 - Atomic::inc(&num_ct_writes_filtered_pop); 2.125 - } 2.126 } 2.127 if ((num_ct_writes % 1000000) == 0) { 2.128 jint num_ct_writes_filtered = 2.129 num_ct_writes_filtered_in_hr + 2.130 - num_ct_writes_filtered_null + 2.131 - num_ct_writes_filtered_pop; 2.132 + num_ct_writes_filtered_null; 2.133 2.134 tty->print_cr("%d potential CT writes: %5.2f%% filtered\n" 2.135 - " (%5.2f%% intra-HR, %5.2f%% null, %5.2f%% popular).", 2.136 + " (%5.2f%% intra-HR, %5.2f%% null).", 2.137 num_ct_writes, 2.138 100.0*(float)num_ct_writes_filtered/(float)num_ct_writes, 2.139 100.0*(float)num_ct_writes_filtered_in_hr/ 2.140 (float)num_ct_writes, 2.141 100.0*(float)num_ct_writes_filtered_null/ 2.142 - (float)num_ct_writes, 2.143 - 100.0*(float)num_ct_writes_filtered_pop/ 2.144 (float)num_ct_writes); 2.145 } 2.146 return Thread::current(); 2.147 @@ -4472,7 +4465,7 @@ 2.148 } 2.149 2.150 // Loading values by size and signed-ness 2.151 -void MacroAssembler::load_sized_value(Register s1, RegisterConstant s2, Register d, 2.152 +void MacroAssembler::load_sized_value(Register s1, RegisterOrConstant s2, Register d, 2.153 int size_in_bytes, bool is_signed) { 2.154 switch (size_in_bytes ^ (is_signed ? -1 : 0)) { 2.155 case ~8: // fall through:
3.1 --- a/src/cpu/sparc/vm/assembler_sparc.hpp Wed Apr 01 22:31:26 2009 -0700 3.2 +++ b/src/cpu/sparc/vm/assembler_sparc.hpp Thu Apr 02 17:01:00 2009 -0700 3.3 @@ -1,5 +1,5 @@ 3.4 /* 3.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 3.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 3.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.8 * 3.9 * This code is free software; you can redistribute it and/or modify it 3.10 @@ -1088,8 +1088,8 @@ 3.11 inline void add( Register s1, Register s2, Register d ); 3.12 inline void add( Register s1, int simm13a, Register d, relocInfo::relocType rtype = relocInfo::none); 3.13 inline void add( Register s1, int simm13a, Register d, RelocationHolder const& rspec); 3.14 - inline void add( Register s1, RegisterConstant s2, Register d, int offset = 0); 3.15 - inline void add( const Address& a, Register d, int offset = 0); 3.16 + inline void add( Register s1, RegisterOrConstant s2, Register d, int offset = 0); 3.17 + inline void add( const Address& a, Register d, int offset = 0); 3.18 3.19 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) ); } 3.20 void addcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } 3.21 @@ -1305,15 +1305,15 @@ 3.22 inline void ld( const Address& a, Register d, int offset = 0 ); 3.23 inline void ldd( const Address& a, Register d, int offset = 0 ); 3.24 3.25 - inline void ldub( Register s1, RegisterConstant s2, Register d ); 3.26 - inline void ldsb( Register s1, RegisterConstant s2, Register d ); 3.27 - inline void lduh( Register s1, RegisterConstant s2, Register d ); 3.28 - inline void ldsh( Register s1, RegisterConstant s2, Register d ); 3.29 - inline void lduw( Register s1, RegisterConstant s2, Register d ); 3.30 - inline void ldsw( Register s1, RegisterConstant s2, Register d ); 3.31 - inline void ldx( Register s1, RegisterConstant s2, Register d ); 3.32 - inline void ld( Register s1, RegisterConstant s2, Register d ); 3.33 - inline void ldd( Register s1, RegisterConstant s2, Register d ); 3.34 + inline void ldub( Register s1, RegisterOrConstant s2, Register d ); 3.35 + inline void ldsb( Register s1, RegisterOrConstant s2, Register d ); 3.36 + inline void lduh( Register s1, RegisterOrConstant s2, Register d ); 3.37 + inline void ldsh( Register s1, RegisterOrConstant s2, Register d ); 3.38 + inline void lduw( Register s1, RegisterOrConstant s2, Register d ); 3.39 + inline void ldsw( Register s1, RegisterOrConstant s2, Register d ); 3.40 + inline void ldx( Register s1, RegisterOrConstant s2, Register d ); 3.41 + inline void ld( Register s1, RegisterOrConstant s2, Register d ); 3.42 + inline void ldd( Register s1, RegisterOrConstant s2, Register d ); 3.43 3.44 // pp 177 3.45 3.46 @@ -1535,12 +1535,12 @@ 3.47 inline void st( Register d, const Address& a, int offset = 0 ); 3.48 inline void std( Register d, const Address& a, int offset = 0 ); 3.49 3.50 - inline void stb( Register d, Register s1, RegisterConstant s2 ); 3.51 - inline void sth( Register d, Register s1, RegisterConstant s2 ); 3.52 - inline void stw( Register d, Register s1, RegisterConstant s2 ); 3.53 - inline void stx( Register d, Register s1, RegisterConstant s2 ); 3.54 - inline void std( Register d, Register s1, RegisterConstant s2 ); 3.55 - inline void st( Register d, Register s1, RegisterConstant s2 ); 3.56 + inline void stb( Register d, Register s1, RegisterOrConstant s2 ); 3.57 + inline void sth( Register d, Register s1, RegisterOrConstant s2 ); 3.58 + inline void stw( Register d, Register s1, RegisterOrConstant s2 ); 3.59 + inline void stx( Register d, Register s1, RegisterOrConstant s2 ); 3.60 + inline void std( Register d, Register s1, RegisterOrConstant s2 ); 3.61 + inline void st( Register d, Register s1, RegisterOrConstant s2 ); 3.62 3.63 // pp 177 3.64 3.65 @@ -1859,7 +1859,7 @@ 3.66 // Functions for isolating 64 bit shifts for LP64 3.67 inline void sll_ptr( Register s1, Register s2, Register d ); 3.68 inline void sll_ptr( Register s1, int imm6a, Register d ); 3.69 - inline void sll_ptr( Register s1, RegisterConstant s2, Register d ); 3.70 + inline void sll_ptr( Register s1, RegisterOrConstant s2, Register d ); 3.71 inline void srl_ptr( Register s1, Register s2, Register d ); 3.72 inline void srl_ptr( Register s1, int imm6a, Register d ); 3.73 3.74 @@ -1965,26 +1965,26 @@ 3.75 // st_ptr will perform st for 32 bit VM's and stx for 64 bit VM's 3.76 inline void ld_ptr( Register s1, Register s2, Register d ); 3.77 inline void ld_ptr( Register s1, int simm13a, Register d); 3.78 - inline void ld_ptr( Register s1, RegisterConstant s2, Register d ); 3.79 + inline void ld_ptr( Register s1, RegisterOrConstant s2, Register d ); 3.80 inline void ld_ptr( const Address& a, Register d, int offset = 0 ); 3.81 inline void st_ptr( Register d, Register s1, Register s2 ); 3.82 inline void st_ptr( Register d, Register s1, int simm13a); 3.83 - inline void st_ptr( Register d, Register s1, RegisterConstant s2 ); 3.84 + inline void st_ptr( Register d, Register s1, RegisterOrConstant s2 ); 3.85 inline void st_ptr( Register d, const Address& a, int offset = 0 ); 3.86 3.87 // ld_long will perform ld for 32 bit VM's and ldx for 64 bit VM's 3.88 // st_long will perform st for 32 bit VM's and stx for 64 bit VM's 3.89 inline void ld_long( Register s1, Register s2, Register d ); 3.90 inline void ld_long( Register s1, int simm13a, Register d ); 3.91 - inline void ld_long( Register s1, RegisterConstant s2, Register d ); 3.92 + inline void ld_long( Register s1, RegisterOrConstant s2, Register d ); 3.93 inline void ld_long( const Address& a, Register d, int offset = 0 ); 3.94 inline void st_long( Register d, Register s1, Register s2 ); 3.95 inline void st_long( Register d, Register s1, int simm13a ); 3.96 - inline void st_long( Register d, Register s1, RegisterConstant s2 ); 3.97 + inline void st_long( Register d, Register s1, RegisterOrConstant s2 ); 3.98 inline void st_long( Register d, const Address& a, int offset = 0 ); 3.99 3.100 // Loading values by size and signed-ness 3.101 - void load_sized_value(Register s1, RegisterConstant s2, Register d, 3.102 + void load_sized_value(Register s1, RegisterOrConstant s2, Register d, 3.103 int size_in_bytes, bool is_signed); 3.104 3.105 // Helpers for address formation. 3.106 @@ -1994,11 +1994,11 @@ 3.107 // is required, and becomes the result. 3.108 // If dest is a register and src is a non-simm13 constant, 3.109 // the temp argument is required, and is used to materialize the constant. 3.110 - void regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src, 3.111 + void regcon_inc_ptr( RegisterOrConstant& dest, RegisterOrConstant src, 3.112 Register temp = noreg ); 3.113 - void regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src, 3.114 + void regcon_sll_ptr( RegisterOrConstant& dest, RegisterOrConstant src, 3.115 Register temp = noreg ); 3.116 - RegisterConstant ensure_rs2(RegisterConstant rs2, Register sethi_temp) { 3.117 + RegisterOrConstant ensure_rs2(RegisterOrConstant rs2, Register sethi_temp) { 3.118 guarantee(sethi_temp != noreg, "constant offset overflow"); 3.119 if (is_simm13(rs2.constant_or_zero())) 3.120 return rs2; // register or short constant 3.121 @@ -2322,7 +2322,7 @@ 3.122 // interface method calling 3.123 void lookup_interface_method(Register recv_klass, 3.124 Register intf_klass, 3.125 - RegisterConstant itable_index, 3.126 + RegisterOrConstant itable_index, 3.127 Register method_result, 3.128 Register temp_reg, Register temp2_reg, 3.129 Label& no_such_interface); 3.130 @@ -2341,7 +2341,7 @@ 3.131 Label* L_success, 3.132 Label* L_failure, 3.133 Label* L_slow_path, 3.134 - RegisterConstant super_check_offset = RegisterConstant(-1), 3.135 + RegisterOrConstant super_check_offset = RegisterOrConstant(-1), 3.136 Register instanceof_hack = noreg); 3.137 3.138 // The rest of the type check; must be wired to a corresponding fast path. 3.139 @@ -2381,7 +2381,7 @@ 3.140 // stack overflow + shadow pages. Clobbers tsp and scratch registers. 3.141 void bang_stack_size(Register Rsize, Register Rtsp, Register Rscratch); 3.142 3.143 - virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr, Register tmp, int offset); 3.144 + virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, Register tmp, int offset); 3.145 3.146 void verify_tlab(); 3.147
4.1 --- a/src/cpu/sparc/vm/assembler_sparc.inline.hpp Wed Apr 01 22:31:26 2009 -0700 4.2 +++ b/src/cpu/sparc/vm/assembler_sparc.inline.hpp Thu Apr 02 17:01:00 2009 -0700 4.3 @@ -1,5 +1,5 @@ 4.4 /* 4.5 - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. 4.6 + * Copyright 1997-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 @@ -143,45 +143,45 @@ 4.11 inline void Assembler::ld( Register s1, int simm13a, Register d) { lduw( s1, simm13a, d); } 4.12 #endif 4.13 4.14 -inline void Assembler::ldub( Register s1, RegisterConstant s2, Register d) { 4.15 +inline void Assembler::ldub( Register s1, RegisterOrConstant s2, Register d) { 4.16 if (s2.is_register()) ldsb(s1, s2.as_register(), d); 4.17 else ldsb(s1, s2.as_constant(), d); 4.18 } 4.19 -inline void Assembler::ldsb( Register s1, RegisterConstant s2, Register d) { 4.20 +inline void Assembler::ldsb( Register s1, RegisterOrConstant s2, Register d) { 4.21 if (s2.is_register()) ldsb(s1, s2.as_register(), d); 4.22 else ldsb(s1, s2.as_constant(), d); 4.23 } 4.24 -inline void Assembler::lduh( Register s1, RegisterConstant s2, Register d) { 4.25 +inline void Assembler::lduh( Register s1, RegisterOrConstant s2, Register d) { 4.26 if (s2.is_register()) ldsh(s1, s2.as_register(), d); 4.27 else ldsh(s1, s2.as_constant(), d); 4.28 } 4.29 -inline void Assembler::ldsh( Register s1, RegisterConstant s2, Register d) { 4.30 +inline void Assembler::ldsh( Register s1, RegisterOrConstant s2, Register d) { 4.31 if (s2.is_register()) ldsh(s1, s2.as_register(), d); 4.32 else ldsh(s1, s2.as_constant(), d); 4.33 } 4.34 -inline void Assembler::lduw( Register s1, RegisterConstant s2, Register d) { 4.35 +inline void Assembler::lduw( Register s1, RegisterOrConstant s2, Register d) { 4.36 if (s2.is_register()) ldsw(s1, s2.as_register(), d); 4.37 else ldsw(s1, s2.as_constant(), d); 4.38 } 4.39 -inline void Assembler::ldsw( Register s1, RegisterConstant s2, Register d) { 4.40 +inline void Assembler::ldsw( Register s1, RegisterOrConstant s2, Register d) { 4.41 if (s2.is_register()) ldsw(s1, s2.as_register(), d); 4.42 else ldsw(s1, s2.as_constant(), d); 4.43 } 4.44 -inline void Assembler::ldx( Register s1, RegisterConstant s2, Register d) { 4.45 +inline void Assembler::ldx( Register s1, RegisterOrConstant s2, Register d) { 4.46 if (s2.is_register()) ldx(s1, s2.as_register(), d); 4.47 else ldx(s1, s2.as_constant(), d); 4.48 } 4.49 -inline void Assembler::ld( Register s1, RegisterConstant s2, Register d) { 4.50 +inline void Assembler::ld( Register s1, RegisterOrConstant s2, Register d) { 4.51 if (s2.is_register()) ld(s1, s2.as_register(), d); 4.52 else ld(s1, s2.as_constant(), d); 4.53 } 4.54 -inline void Assembler::ldd( Register s1, RegisterConstant s2, Register d) { 4.55 +inline void Assembler::ldd( Register s1, RegisterOrConstant s2, Register d) { 4.56 if (s2.is_register()) ldd(s1, s2.as_register(), d); 4.57 else ldd(s1, s2.as_constant(), d); 4.58 } 4.59 4.60 // form effective addresses this way: 4.61 -inline void Assembler::add( Register s1, RegisterConstant s2, Register d, int offset) { 4.62 +inline void Assembler::add( Register s1, RegisterOrConstant s2, Register d, int offset) { 4.63 if (s2.is_register()) add(s1, s2.as_register(), d); 4.64 else { add(s1, s2.as_constant() + offset, d); offset = 0; } 4.65 if (offset != 0) add(d, offset, d); 4.66 @@ -243,23 +243,23 @@ 4.67 inline void Assembler::st( Register d, Register s1, Register s2) { stw(d, s1, s2); } 4.68 inline void Assembler::st( Register d, Register s1, int simm13a) { stw(d, s1, simm13a); } 4.69 4.70 -inline void Assembler::stb( Register d, Register s1, RegisterConstant s2) { 4.71 +inline void Assembler::stb( Register d, Register s1, RegisterOrConstant s2) { 4.72 if (s2.is_register()) stb(d, s1, s2.as_register()); 4.73 else stb(d, s1, s2.as_constant()); 4.74 } 4.75 -inline void Assembler::sth( Register d, Register s1, RegisterConstant s2) { 4.76 +inline void Assembler::sth( Register d, Register s1, RegisterOrConstant s2) { 4.77 if (s2.is_register()) sth(d, s1, s2.as_register()); 4.78 else sth(d, s1, s2.as_constant()); 4.79 } 4.80 -inline void Assembler::stx( Register d, Register s1, RegisterConstant s2) { 4.81 +inline void Assembler::stx( Register d, Register s1, RegisterOrConstant s2) { 4.82 if (s2.is_register()) stx(d, s1, s2.as_register()); 4.83 else stx(d, s1, s2.as_constant()); 4.84 } 4.85 -inline void Assembler::std( Register d, Register s1, RegisterConstant s2) { 4.86 +inline void Assembler::std( Register d, Register s1, RegisterOrConstant s2) { 4.87 if (s2.is_register()) std(d, s1, s2.as_register()); 4.88 else std(d, s1, s2.as_constant()); 4.89 } 4.90 -inline void Assembler::st( Register d, Register s1, RegisterConstant s2) { 4.91 +inline void Assembler::st( Register d, Register s1, RegisterOrConstant s2) { 4.92 if (s2.is_register()) st(d, s1, s2.as_register()); 4.93 else st(d, s1, s2.as_constant()); 4.94 } 4.95 @@ -308,7 +308,7 @@ 4.96 #endif 4.97 } 4.98 4.99 -inline void MacroAssembler::ld_ptr( Register s1, RegisterConstant s2, Register d ) { 4.100 +inline void MacroAssembler::ld_ptr( Register s1, RegisterOrConstant s2, Register d ) { 4.101 #ifdef _LP64 4.102 Assembler::ldx( s1, s2, d); 4.103 #else 4.104 @@ -340,7 +340,7 @@ 4.105 #endif 4.106 } 4.107 4.108 -inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterConstant s2 ) { 4.109 +inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterOrConstant s2 ) { 4.110 #ifdef _LP64 4.111 Assembler::stx( d, s1, s2); 4.112 #else 4.113 @@ -373,7 +373,7 @@ 4.114 #endif 4.115 } 4.116 4.117 -inline void MacroAssembler::ld_long( Register s1, RegisterConstant s2, Register d ) { 4.118 +inline void MacroAssembler::ld_long( Register s1, RegisterOrConstant s2, Register d ) { 4.119 #ifdef _LP64 4.120 Assembler::ldx(s1, s2, d); 4.121 #else 4.122 @@ -405,7 +405,7 @@ 4.123 #endif 4.124 } 4.125 4.126 -inline void MacroAssembler::st_long( Register d, Register s1, RegisterConstant s2 ) { 4.127 +inline void MacroAssembler::st_long( Register d, Register s1, RegisterOrConstant s2 ) { 4.128 #ifdef _LP64 4.129 Assembler::stx(d, s1, s2); 4.130 #else 4.131 @@ -455,7 +455,7 @@ 4.132 #endif 4.133 } 4.134 4.135 -inline void MacroAssembler::sll_ptr( Register s1, RegisterConstant s2, Register d ) { 4.136 +inline void MacroAssembler::sll_ptr( Register s1, RegisterOrConstant s2, Register d ) { 4.137 if (s2.is_register()) sll_ptr(s1, s2.as_register(), d); 4.138 else sll_ptr(s1, s2.as_constant(), d); 4.139 }
5.1 --- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Wed Apr 01 22:31:26 2009 -0700 5.2 +++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Apr 02 17:01:00 2009 -0700 5.3 @@ -1,5 +1,5 @@ 5.4 /* 5.5 - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. 5.6 + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. 5.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.8 * 5.9 * This code is free software; you can redistribute it and/or modify it 5.10 @@ -2489,7 +2489,7 @@ 5.11 __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, noreg, 5.12 (need_slow_path ? &done : NULL), 5.13 stub->entry(), NULL, 5.14 - RegisterConstant(k->super_check_offset())); 5.15 + RegisterOrConstant(k->super_check_offset())); 5.16 } else { 5.17 // perform the fast part of the checking logic 5.18 __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7, 5.19 @@ -2550,14 +2550,14 @@ 5.20 __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, O7, noreg, 5.21 (need_slow_path ? &done : NULL), 5.22 (need_slow_path ? &done : NULL), NULL, 5.23 - RegisterConstant(k->super_check_offset()), 5.24 + RegisterOrConstant(k->super_check_offset()), 5.25 dst); 5.26 } else { 5.27 assert(dst != klass_RInfo && dst != k_RInfo, "need 3 registers"); 5.28 // perform the fast part of the checking logic 5.29 __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, O7, dst, 5.30 &done, &done, NULL, 5.31 - RegisterConstant(-1), 5.32 + RegisterOrConstant(-1), 5.33 dst); 5.34 } 5.35 if (need_slow_path) {
6.1 --- a/src/cpu/sparc/vm/globals_sparc.hpp Wed Apr 01 22:31:26 2009 -0700 6.2 +++ b/src/cpu/sparc/vm/globals_sparc.hpp Thu Apr 02 17:01:00 2009 -0700 6.3 @@ -46,6 +46,7 @@ 6.4 define_pd_global(uintx, NewSize, ScaleForWordSize((2048 * K) + (2 * (64 * K)))); 6.5 define_pd_global(intx, SurvivorRatio, 8); 6.6 define_pd_global(intx, InlineFrequencyCount, 50); // we can use more inlining on the SPARC 6.7 +define_pd_global(intx, InlineSmallCode, 1500); 6.8 #ifdef _LP64 6.9 // Stack slots are 2X larger in LP64 than in the 32 bit VM. 6.10 define_pd_global(intx, ThreadStackSize, 1024);
7.1 --- a/src/cpu/sparc/vm/sparc.ad Wed Apr 01 22:31:26 2009 -0700 7.2 +++ b/src/cpu/sparc/vm/sparc.ad Thu Apr 02 17:01:00 2009 -0700 7.3 @@ -3003,6 +3003,202 @@ 7.4 __ bind(Ldone); 7.5 %} 7.6 7.7 +enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{ 7.8 + Label Lword, Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone; 7.9 + MacroAssembler _masm(&cbuf); 7.10 + 7.11 + Register str1_reg = reg_to_register_object($str1$$reg); 7.12 + Register str2_reg = reg_to_register_object($str2$$reg); 7.13 + Register tmp1_reg = reg_to_register_object($tmp1$$reg); 7.14 + Register tmp2_reg = reg_to_register_object($tmp2$$reg); 7.15 + Register result_reg = reg_to_register_object($result$$reg); 7.16 + 7.17 + // Get the first character position in both strings 7.18 + // [8] char array, [12] offset, [16] count 7.19 + int value_offset = java_lang_String:: value_offset_in_bytes(); 7.20 + int offset_offset = java_lang_String::offset_offset_in_bytes(); 7.21 + int count_offset = java_lang_String:: count_offset_in_bytes(); 7.22 + 7.23 + // load str1 (jchar*) base address into tmp1_reg 7.24 + __ load_heap_oop(Address(str1_reg, 0, value_offset), tmp1_reg); 7.25 + __ ld(Address(str1_reg, 0, offset_offset), result_reg); 7.26 + __ add(tmp1_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1_reg); 7.27 + __ ld(Address(str1_reg, 0, count_offset), str1_reg); // hoisted 7.28 + __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg); 7.29 + __ load_heap_oop(Address(str2_reg, 0, value_offset), tmp2_reg); // hoisted 7.30 + __ add(result_reg, tmp1_reg, tmp1_reg); 7.31 + 7.32 + // load str2 (jchar*) base address into tmp2_reg 7.33 + // __ ld_ptr(Address(str2_reg, 0, value_offset), tmp2_reg); // hoisted 7.34 + __ ld(Address(str2_reg, 0, offset_offset), result_reg); 7.35 + __ add(tmp2_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp2_reg); 7.36 + __ ld(Address(str2_reg, 0, count_offset), str2_reg); // hoisted 7.37 + __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg); 7.38 + __ cmp(str1_reg, str2_reg); // hoisted 7.39 + __ add(result_reg, tmp2_reg, tmp2_reg); 7.40 + 7.41 + __ sll(str1_reg, exact_log2(sizeof(jchar)), str1_reg); 7.42 + __ br(Assembler::notEqual, true, Assembler::pt, Ldone); 7.43 + __ delayed()->mov(G0, result_reg); // not equal 7.44 + 7.45 + __ br_zero(Assembler::equal, true, Assembler::pn, str1_reg, Ldone); 7.46 + __ delayed()->add(G0, 1, result_reg); //equals 7.47 + 7.48 + __ cmp(tmp1_reg, tmp2_reg); //same string ? 7.49 + __ brx(Assembler::equal, true, Assembler::pn, Ldone); 7.50 + __ delayed()->add(G0, 1, result_reg); 7.51 + 7.52 + //rename registers 7.53 + Register limit_reg = str1_reg; 7.54 + Register chr2_reg = str2_reg; 7.55 + Register chr1_reg = result_reg; 7.56 + // tmp{12} are the base pointers 7.57 + 7.58 + //check for alignment and position the pointers to the ends 7.59 + __ or3(tmp1_reg, tmp2_reg, chr1_reg); 7.60 + __ andcc(chr1_reg, 0x3, chr1_reg); // notZero means at least one not 4-byte aligned 7.61 + __ br(Assembler::notZero, false, Assembler::pn, Lchar); 7.62 + __ delayed()->nop(); 7.63 + 7.64 + __ bind(Lword); 7.65 + __ and3(limit_reg, 0x2, O7); //remember the remainder (either 0 or 2) 7.66 + __ andn(limit_reg, 0x3, limit_reg); 7.67 + __ br_zero(Assembler::zero, false, Assembler::pn, limit_reg, Lpost_word); 7.68 + __ delayed()->nop(); 7.69 + 7.70 + __ add(tmp1_reg, limit_reg, tmp1_reg); 7.71 + __ add(tmp2_reg, limit_reg, tmp2_reg); 7.72 + __ neg(limit_reg); 7.73 + 7.74 + __ lduw(tmp1_reg, limit_reg, chr1_reg); 7.75 + __ bind(Lword_loop); 7.76 + __ lduw(tmp2_reg, limit_reg, chr2_reg); 7.77 + __ cmp(chr1_reg, chr2_reg); 7.78 + __ br(Assembler::notEqual, true, Assembler::pt, Ldone); 7.79 + __ delayed()->mov(G0, result_reg); 7.80 + __ inccc(limit_reg, 2*sizeof(jchar)); 7.81 + // annul LDUW if branch i s not taken to prevent access past end of string 7.82 + __ br(Assembler::notZero, true, Assembler::pt, Lword_loop); //annul on taken 7.83 + __ delayed()->lduw(tmp1_reg, limit_reg, chr1_reg); // hoisted 7.84 + 7.85 + __ bind(Lpost_word); 7.86 + __ br_zero(Assembler::zero, true, Assembler::pt, O7, Ldone); 7.87 + __ delayed()->add(G0, 1, result_reg); 7.88 + 7.89 + __ lduh(tmp1_reg, 0, chr1_reg); 7.90 + __ lduh(tmp2_reg, 0, chr2_reg); 7.91 + __ cmp (chr1_reg, chr2_reg); 7.92 + __ br(Assembler::notEqual, true, Assembler::pt, Ldone); 7.93 + __ delayed()->mov(G0, result_reg); 7.94 + __ ba(false,Ldone); 7.95 + __ delayed()->add(G0, 1, result_reg); 7.96 + 7.97 + __ bind(Lchar); 7.98 + __ add(tmp1_reg, limit_reg, tmp1_reg); 7.99 + __ add(tmp2_reg, limit_reg, tmp2_reg); 7.100 + __ neg(limit_reg); //negate count 7.101 + 7.102 + __ lduh(tmp1_reg, limit_reg, chr1_reg); 7.103 + __ bind(Lchar_loop); 7.104 + __ lduh(tmp2_reg, limit_reg, chr2_reg); 7.105 + __ cmp(chr1_reg, chr2_reg); 7.106 + __ br(Assembler::notEqual, true, Assembler::pt, Ldone); 7.107 + __ delayed()->mov(G0, result_reg); //not equal 7.108 + __ inccc(limit_reg, sizeof(jchar)); 7.109 + // annul LDUH if branch is not taken to prevent access past end of string 7.110 + __ br(Assembler::notZero, true, Assembler::pt, Lchar_loop); //annul on taken 7.111 + __ delayed()->lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted 7.112 + 7.113 + __ add(G0, 1, result_reg); //equal 7.114 + 7.115 + __ bind(Ldone); 7.116 + %} 7.117 + 7.118 +enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{ 7.119 + Label Lvector, Ldone, Lloop; 7.120 + MacroAssembler _masm(&cbuf); 7.121 + 7.122 + Register ary1_reg = reg_to_register_object($ary1$$reg); 7.123 + Register ary2_reg = reg_to_register_object($ary2$$reg); 7.124 + Register tmp1_reg = reg_to_register_object($tmp1$$reg); 7.125 + Register tmp2_reg = reg_to_register_object($tmp2$$reg); 7.126 + Register result_reg = reg_to_register_object($result$$reg); 7.127 + 7.128 + int length_offset = arrayOopDesc::length_offset_in_bytes(); 7.129 + int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 7.130 + 7.131 + // return true if the same array 7.132 + __ cmp(ary1_reg, ary2_reg); 7.133 + __ br(Assembler::equal, true, Assembler::pn, Ldone); 7.134 + __ delayed()->add(G0, 1, result_reg); // equal 7.135 + 7.136 + __ br_null(ary1_reg, true, Assembler::pn, Ldone); 7.137 + __ delayed()->mov(G0, result_reg); // not equal 7.138 + 7.139 + __ br_null(ary2_reg, true, Assembler::pn, Ldone); 7.140 + __ delayed()->mov(G0, result_reg); // not equal 7.141 + 7.142 + //load the lengths of arrays 7.143 + __ ld(Address(ary1_reg, 0, length_offset), tmp1_reg); 7.144 + __ ld(Address(ary2_reg, 0, length_offset), tmp2_reg); 7.145 + 7.146 + // return false if the two arrays are not equal length 7.147 + __ cmp(tmp1_reg, tmp2_reg); 7.148 + __ br(Assembler::notEqual, true, Assembler::pn, Ldone); 7.149 + __ delayed()->mov(G0, result_reg); // not equal 7.150 + 7.151 + __ br_zero(Assembler::zero, true, Assembler::pn, tmp1_reg, Ldone); 7.152 + __ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal 7.153 + 7.154 + // load array addresses 7.155 + __ add(ary1_reg, base_offset, ary1_reg); 7.156 + __ add(ary2_reg, base_offset, ary2_reg); 7.157 + 7.158 + // renaming registers 7.159 + Register chr1_reg = tmp2_reg; // for characters in ary1 7.160 + Register chr2_reg = result_reg; // for characters in ary2 7.161 + Register limit_reg = tmp1_reg; // length 7.162 + 7.163 + // set byte count 7.164 + __ sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg); 7.165 + __ andcc(limit_reg, 0x2, chr1_reg); //trailing character ? 7.166 + __ br(Assembler::zero, false, Assembler::pt, Lvector); 7.167 + __ delayed()->nop(); 7.168 + 7.169 + //compare the trailing char 7.170 + __ sub(limit_reg, sizeof(jchar), limit_reg); 7.171 + __ lduh(ary1_reg, limit_reg, chr1_reg); 7.172 + __ lduh(ary2_reg, limit_reg, chr2_reg); 7.173 + __ cmp(chr1_reg, chr2_reg); 7.174 + __ br(Assembler::notEqual, true, Assembler::pt, Ldone); 7.175 + __ delayed()->mov(G0, result_reg); // not equal 7.176 + 7.177 + // only one char ? 7.178 + __ br_zero(Assembler::zero, true, Assembler::pn, limit_reg, Ldone); 7.179 + __ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal 7.180 + 7.181 + __ bind(Lvector); 7.182 + // Shift ary1_reg and ary2_reg to the end of the arrays, negate limit 7.183 + __ add(ary1_reg, limit_reg, ary1_reg); 7.184 + __ add(ary2_reg, limit_reg, ary2_reg); 7.185 + __ neg(limit_reg, limit_reg); 7.186 + 7.187 + __ lduw(ary1_reg, limit_reg, chr1_reg); 7.188 + __ bind(Lloop); 7.189 + __ lduw(ary2_reg, limit_reg, chr2_reg); 7.190 + __ cmp(chr1_reg, chr2_reg); 7.191 + __ br(Assembler::notEqual, false, Assembler::pt, Ldone); 7.192 + __ delayed()->mov(G0, result_reg); // not equal 7.193 + __ inccc(limit_reg, 2*sizeof(jchar)); 7.194 + // annul LDUW if branch is not taken to prevent access past end of string 7.195 + __ br(Assembler::notZero, true, Assembler::pt, Lloop); //annul on taken 7.196 + __ delayed()->lduw(ary1_reg, limit_reg, chr1_reg); // hoisted 7.197 + 7.198 + __ add(G0, 1, result_reg); // equals 7.199 + 7.200 + __ bind(Ldone); 7.201 + %} 7.202 + 7.203 enc_class enc_rethrow() %{ 7.204 cbuf.set_inst_mark(); 7.205 Register temp_reg = G3; 7.206 @@ -9015,6 +9211,25 @@ 7.207 ins_pipe(long_memory_op); 7.208 %} 7.209 7.210 +instruct string_equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result, 7.211 + o7RegI tmp3, flagsReg ccr) %{ 7.212 + match(Set result (StrEquals str1 str2)); 7.213 + effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3); 7.214 + ins_cost(300); 7.215 + format %{ "String Equals $str1,$str2 -> $result" %} 7.216 + ins_encode( enc_String_Equals(str1, str2, tmp1, tmp2, result) ); 7.217 + ins_pipe(long_memory_op); 7.218 +%} 7.219 + 7.220 +instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result, 7.221 + flagsReg ccr) %{ 7.222 + match(Set result (AryEq ary1 ary2)); 7.223 + effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr); 7.224 + ins_cost(300); 7.225 + format %{ "Array Equals $ary1,$ary2 -> $result" %} 7.226 + ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result)); 7.227 + ins_pipe(long_memory_op); 7.228 +%} 7.229 7.230 //---------- Population Count Instructions ------------------------------------- 7.231
8.1 --- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp Wed Apr 01 22:31:26 2009 -0700 8.2 +++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp Thu Apr 02 17:01:00 2009 -0700 8.3 @@ -817,21 +817,6 @@ 8.4 Label _atomic_add_stub; // called from other stubs 8.5 8.6 8.7 - // Support for void OrderAccess::fence(). 8.8 - // 8.9 - address generate_fence() { 8.10 - StubCodeMark mark(this, "StubRoutines", "fence"); 8.11 - address start = __ pc(); 8.12 - 8.13 - __ membar(Assembler::Membar_mask_bits(Assembler::LoadLoad | Assembler::LoadStore | 8.14 - Assembler::StoreLoad | Assembler::StoreStore)); 8.15 - __ retl(false); 8.16 - __ delayed()->nop(); 8.17 - 8.18 - return start; 8.19 - } 8.20 - 8.21 - 8.22 //------------------------------------------------------------------------------------------------------------------------ 8.23 // The following routine generates a subroutine to throw an asynchronous 8.24 // UnknownError when an unsafe access gets a fault that could not be 8.25 @@ -2861,7 +2846,6 @@ 8.26 StubRoutines::_atomic_cmpxchg_ptr_entry = StubRoutines::_atomic_cmpxchg_entry; 8.27 StubRoutines::_atomic_cmpxchg_long_entry = generate_atomic_cmpxchg_long(); 8.28 StubRoutines::_atomic_add_ptr_entry = StubRoutines::_atomic_add_entry; 8.29 - StubRoutines::_fence_entry = generate_fence(); 8.30 #endif // COMPILER2 !=> _LP64 8.31 } 8.32
9.1 --- a/src/cpu/sparc/vm/vm_version_sparc.cpp Wed Apr 01 22:31:26 2009 -0700 9.2 +++ b/src/cpu/sparc/vm/vm_version_sparc.cpp Thu Apr 02 17:01:00 2009 -0700 9.3 @@ -62,7 +62,7 @@ 9.4 if (is_niagara1()) { 9.5 // Indirect branch is the same cost as direct 9.6 if (FLAG_IS_DEFAULT(UseInlineCaches)) { 9.7 - UseInlineCaches = false; 9.8 + FLAG_SET_DEFAULT(UseInlineCaches, false); 9.9 } 9.10 #ifdef _LP64 9.11 // Single issue niagara1 is slower for CompressedOops 9.12 @@ -79,15 +79,19 @@ 9.13 #ifdef COMPILER2 9.14 // Indirect branch is the same cost as direct 9.15 if (FLAG_IS_DEFAULT(UseJumpTables)) { 9.16 - UseJumpTables = true; 9.17 + FLAG_SET_DEFAULT(UseJumpTables, true); 9.18 } 9.19 // Single-issue, so entry and loop tops are 9.20 // aligned on a single instruction boundary 9.21 if (FLAG_IS_DEFAULT(InteriorEntryAlignment)) { 9.22 - InteriorEntryAlignment = 4; 9.23 + FLAG_SET_DEFAULT(InteriorEntryAlignment, 4); 9.24 } 9.25 if (FLAG_IS_DEFAULT(OptoLoopAlignment)) { 9.26 - OptoLoopAlignment = 4; 9.27 + FLAG_SET_DEFAULT(OptoLoopAlignment, 4); 9.28 + } 9.29 + if (is_niagara1_plus() && FLAG_IS_DEFAULT(AllocatePrefetchDistance)) { 9.30 + // Use smaller prefetch distance on N2 9.31 + FLAG_SET_DEFAULT(AllocatePrefetchDistance, 256); 9.32 } 9.33 #endif 9.34 } 9.35 @@ -95,7 +99,7 @@ 9.36 // Use hardware population count instruction if available. 9.37 if (has_hardware_popc()) { 9.38 if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { 9.39 - UsePopCountInstruction = true; 9.40 + FLAG_SET_DEFAULT(UsePopCountInstruction, true); 9.41 } 9.42 } 9.43
10.1 --- a/src/cpu/x86/vm/assembler_x86.cpp Wed Apr 01 22:31:26 2009 -0700 10.2 +++ b/src/cpu/x86/vm/assembler_x86.cpp Thu Apr 02 17:01:00 2009 -0700 10.3 @@ -1438,26 +1438,12 @@ 10.4 } 10.5 } 10.6 10.7 -// Serializes memory. 10.8 +// Emit mfence instruction 10.9 void Assembler::mfence() { 10.10 - // Memory barriers are only needed on multiprocessors 10.11 - if (os::is_MP()) { 10.12 - if( LP64_ONLY(true ||) VM_Version::supports_sse2() ) { 10.13 - emit_byte( 0x0F ); // MFENCE; faster blows no regs 10.14 - emit_byte( 0xAE ); 10.15 - emit_byte( 0xF0 ); 10.16 - } else { 10.17 - // All usable chips support "locked" instructions which suffice 10.18 - // as barriers, and are much faster than the alternative of 10.19 - // using cpuid instruction. We use here a locked add [esp],0. 10.20 - // This is conveniently otherwise a no-op except for blowing 10.21 - // flags (which we save and restore.) 10.22 - pushf(); // Save eflags register 10.23 - lock(); 10.24 - addl(Address(rsp, 0), 0);// Assert the lock# signal here 10.25 - popf(); // Restore eflags register 10.26 - } 10.27 - } 10.28 + NOT_LP64(assert(VM_Version::supports_sse2(), "unsupported");) 10.29 + emit_byte( 0x0F ); 10.30 + emit_byte( 0xAE ); 10.31 + emit_byte( 0xF0 ); 10.32 } 10.33 10.34 void Assembler::mov(Register dst, Register src) { 10.35 @@ -2187,6 +2173,31 @@ 10.36 emit_arith(0x0B, 0xC0, dst, src); 10.37 } 10.38 10.39 +void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) { 10.40 + assert(VM_Version::supports_sse4_2(), ""); 10.41 + 10.42 + InstructionMark im(this); 10.43 + emit_byte(0x66); 10.44 + prefix(src, dst); 10.45 + emit_byte(0x0F); 10.46 + emit_byte(0x3A); 10.47 + emit_byte(0x61); 10.48 + emit_operand(dst, src); 10.49 + emit_byte(imm8); 10.50 +} 10.51 + 10.52 +void Assembler::pcmpestri(XMMRegister dst, XMMRegister src, int imm8) { 10.53 + assert(VM_Version::supports_sse4_2(), ""); 10.54 + 10.55 + emit_byte(0x66); 10.56 + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); 10.57 + emit_byte(0x0F); 10.58 + emit_byte(0x3A); 10.59 + emit_byte(0x61); 10.60 + emit_byte(0xC0 | encode); 10.61 + emit_byte(imm8); 10.62 +} 10.63 + 10.64 // generic 10.65 void Assembler::pop(Register dst) { 10.66 int encode = prefix_and_encode(dst->encoding()); 10.67 @@ -2344,6 +2355,29 @@ 10.68 emit_byte(shift); 10.69 } 10.70 10.71 +void Assembler::ptest(XMMRegister dst, Address src) { 10.72 + assert(VM_Version::supports_sse4_1(), ""); 10.73 + 10.74 + InstructionMark im(this); 10.75 + emit_byte(0x66); 10.76 + prefix(src, dst); 10.77 + emit_byte(0x0F); 10.78 + emit_byte(0x38); 10.79 + emit_byte(0x17); 10.80 + emit_operand(dst, src); 10.81 +} 10.82 + 10.83 +void Assembler::ptest(XMMRegister dst, XMMRegister src) { 10.84 + assert(VM_Version::supports_sse4_1(), ""); 10.85 + 10.86 + emit_byte(0x66); 10.87 + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); 10.88 + emit_byte(0x0F); 10.89 + emit_byte(0x38); 10.90 + emit_byte(0x17); 10.91 + emit_byte(0xC0 | encode); 10.92 +} 10.93 + 10.94 void Assembler::punpcklbw(XMMRegister dst, XMMRegister src) { 10.95 NOT_LP64(assert(VM_Version::supports_sse2(), "")); 10.96 emit_byte(0x66); 10.97 @@ -7218,7 +7252,7 @@ 10.98 // On failure, execution transfers to the given label. 10.99 void MacroAssembler::lookup_interface_method(Register recv_klass, 10.100 Register intf_klass, 10.101 - RegisterConstant itable_index, 10.102 + RegisterOrConstant itable_index, 10.103 Register method_result, 10.104 Register scan_temp, 10.105 Label& L_no_such_interface) { 10.106 @@ -7303,7 +7337,7 @@ 10.107 Label* L_success, 10.108 Label* L_failure, 10.109 Label* L_slow_path, 10.110 - RegisterConstant super_check_offset) { 10.111 + RegisterOrConstant super_check_offset) { 10.112 assert_different_registers(sub_klass, super_klass, temp_reg); 10.113 bool must_load_sco = (super_check_offset.constant_or_zero() == -1); 10.114 if (super_check_offset.is_register()) { 10.115 @@ -7352,7 +7386,7 @@ 10.116 if (must_load_sco) { 10.117 // Positive movl does right thing on LP64. 10.118 movl(temp_reg, super_check_offset_addr); 10.119 - super_check_offset = RegisterConstant(temp_reg); 10.120 + super_check_offset = RegisterOrConstant(temp_reg); 10.121 } 10.122 Address super_check_addr(sub_klass, super_check_offset, Address::times_1, 0); 10.123 cmpptr(super_klass, super_check_addr); // load displayed supertype 10.124 @@ -7550,12 +7584,12 @@ 10.125 } 10.126 10.127 10.128 -RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr, 10.129 - Register tmp, 10.130 - int offset) { 10.131 +RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr, 10.132 + Register tmp, 10.133 + int offset) { 10.134 intptr_t value = *delayed_value_addr; 10.135 if (value != 0) 10.136 - return RegisterConstant(value + offset); 10.137 + return RegisterOrConstant(value + offset); 10.138 10.139 // load indirectly to solve generation ordering problem 10.140 movptr(tmp, ExternalAddress((address) delayed_value_addr)); 10.141 @@ -7571,7 +7605,7 @@ 10.142 if (offset != 0) 10.143 addptr(tmp, offset); 10.144 10.145 - return RegisterConstant(tmp); 10.146 + return RegisterOrConstant(tmp); 10.147 } 10.148 10.149
11.1 --- a/src/cpu/x86/vm/assembler_x86.hpp Wed Apr 01 22:31:26 2009 -0700 11.2 +++ b/src/cpu/x86/vm/assembler_x86.hpp Thu Apr 02 17:01:00 2009 -0700 11.3 @@ -212,7 +212,7 @@ 11.4 "inconsistent address"); 11.5 } 11.6 11.7 - Address(Register base, RegisterConstant index, ScaleFactor scale = times_1, int disp = 0) 11.8 + Address(Register base, RegisterOrConstant index, ScaleFactor scale = times_1, int disp = 0) 11.9 : _base (base), 11.10 _index(index.register_or_noreg()), 11.11 _scale(scale), 11.12 @@ -256,7 +256,7 @@ 11.13 "inconsistent address"); 11.14 } 11.15 11.16 - Address(Register base, RegisterConstant index, ScaleFactor scale, ByteSize disp) 11.17 + Address(Register base, RegisterOrConstant index, ScaleFactor scale, ByteSize disp) 11.18 : _base (base), 11.19 _index(index.register_or_noreg()), 11.20 _scale(scale), 11.21 @@ -1068,15 +1068,23 @@ 11.22 LoadLoad = 1 << 0 11.23 }; 11.24 11.25 - // Serializes memory. 11.26 + // Serializes memory and blows flags 11.27 void membar(Membar_mask_bits order_constraint) { 11.28 - // We only have to handle StoreLoad and LoadLoad 11.29 - if (order_constraint & StoreLoad) { 11.30 - // MFENCE subsumes LFENCE 11.31 - mfence(); 11.32 - } /* [jk] not needed currently: else if (order_constraint & LoadLoad) { 11.33 - lfence(); 11.34 - } */ 11.35 + if (os::is_MP()) { 11.36 + // We only have to handle StoreLoad 11.37 + if (order_constraint & StoreLoad) { 11.38 + // All usable chips support "locked" instructions which suffice 11.39 + // as barriers, and are much faster than the alternative of 11.40 + // using cpuid instruction. We use here a locked add [esp],0. 11.41 + // This is conveniently otherwise a no-op except for blowing 11.42 + // flags. 11.43 + // Any change to this code may need to revisit other places in 11.44 + // the code where this idiom is used, in particular the 11.45 + // orderAccess code. 11.46 + lock(); 11.47 + addl(Address(rsp, 0), 0);// Assert the lock# signal here 11.48 + } 11.49 + } 11.50 } 11.51 11.52 void mfence(); 11.53 @@ -1218,6 +1226,10 @@ 11.54 void orq(Register dst, Address src); 11.55 void orq(Register dst, Register src); 11.56 11.57 + // SSE4.2 string instructions 11.58 + void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8); 11.59 + void pcmpestri(XMMRegister xmm1, Address src, int imm8); 11.60 + 11.61 void popl(Address dst); 11.62 11.63 #ifdef _LP64 11.64 @@ -1252,6 +1264,10 @@ 11.65 // Shift Right Logical Quadword Immediate 11.66 void psrlq(XMMRegister dst, int shift); 11.67 11.68 + // Logical Compare Double Quadword 11.69 + void ptest(XMMRegister dst, XMMRegister src); 11.70 + void ptest(XMMRegister dst, Address src); 11.71 + 11.72 // Interleave Low Bytes 11.73 void punpcklbw(XMMRegister dst, XMMRegister src); 11.74 11.75 @@ -1802,7 +1818,7 @@ 11.76 // interface method calling 11.77 void lookup_interface_method(Register recv_klass, 11.78 Register intf_klass, 11.79 - RegisterConstant itable_index, 11.80 + RegisterOrConstant itable_index, 11.81 Register method_result, 11.82 Register scan_temp, 11.83 Label& no_such_interface); 11.84 @@ -1819,7 +1835,7 @@ 11.85 Label* L_success, 11.86 Label* L_failure, 11.87 Label* L_slow_path, 11.88 - RegisterConstant super_check_offset = RegisterConstant(-1)); 11.89 + RegisterOrConstant super_check_offset = RegisterOrConstant(-1)); 11.90 11.91 // The rest of the type check; must be wired to a corresponding fast path. 11.92 // It does not repeat the fast path logic, so don't use it standalone. 11.93 @@ -1883,9 +1899,9 @@ 11.94 // stack overflow + shadow pages. Also, clobbers tmp 11.95 void bang_stack_size(Register size, Register tmp); 11.96 11.97 - virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr, 11.98 - Register tmp, 11.99 - int offset); 11.100 + virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, 11.101 + Register tmp, 11.102 + int offset); 11.103 11.104 // Support for serializing memory accesses between threads 11.105 void serialize_memory(Register thread, Register tmp);
12.1 --- a/src/cpu/x86/vm/globals_x86.hpp Wed Apr 01 22:31:26 2009 -0700 12.2 +++ b/src/cpu/x86/vm/globals_x86.hpp Thu Apr 02 17:01:00 2009 -0700 12.3 @@ -60,6 +60,7 @@ 12.4 define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+1)); 12.5 #endif // AMD64 12.6 define_pd_global(intx, InlineFrequencyCount, 100); 12.7 +define_pd_global(intx, InlineSmallCode, 1000); 12.8 define_pd_global(intx, PreInflateSpin, 10); 12.9 12.10 define_pd_global(intx, StackYellowPages, 2);
13.1 --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed Apr 01 22:31:26 2009 -0700 13.2 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Thu Apr 02 17:01:00 2009 -0700 13.3 @@ -2691,7 +2691,7 @@ 13.4 __ mov(rdi, rax); 13.5 13.6 Label noException; 13.7 - __ cmpl(r12, Deoptimization::Unpack_exception); // Was exception pending? 13.8 + __ cmpl(r14, Deoptimization::Unpack_exception); // Was exception pending? 13.9 __ jcc(Assembler::notEqual, noException); 13.10 __ movptr(rax, Address(r15_thread, JavaThread::exception_oop_offset())); 13.11 // QQQ this is useless it was NULL above
14.1 --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed Apr 01 22:31:26 2009 -0700 14.2 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp Thu Apr 02 17:01:00 2009 -0700 14.3 @@ -637,7 +637,7 @@ 14.4 address generate_orderaccess_fence() { 14.5 StubCodeMark mark(this, "StubRoutines", "orderaccess_fence"); 14.6 address start = __ pc(); 14.7 - __ mfence(); 14.8 + __ membar(Assembler::StoreLoad); 14.9 __ ret(0); 14.10 14.11 return start;
15.1 --- a/src/cpu/x86/vm/vm_version_x86.cpp Wed Apr 01 22:31:26 2009 -0700 15.2 +++ b/src/cpu/x86/vm/vm_version_x86.cpp Thu Apr 02 17:01:00 2009 -0700 15.3 @@ -408,6 +408,11 @@ 15.4 UseUnalignedLoadStores = true; // use movdqu on newest Intel cpus 15.5 } 15.6 } 15.7 + if( supports_sse4_2() && UseSSE >= 4 ) { 15.8 + if( FLAG_IS_DEFAULT(UseSSE42Intrinsics)) { 15.9 + UseSSE42Intrinsics = true; 15.10 + } 15.11 + } 15.12 } 15.13 } 15.14
16.1 --- a/src/cpu/x86/vm/x86_32.ad Wed Apr 01 22:31:26 2009 -0700 16.2 +++ b/src/cpu/x86/vm/x86_32.ad Thu Apr 02 17:01:00 2009 -0700 16.3 @@ -3694,12 +3694,16 @@ 16.4 } 16.5 %} 16.6 16.7 - enc_class enc_String_Compare() %{ 16.8 + enc_class enc_String_Compare(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2, 16.9 + eAXRegI tmp3, eBXRegI tmp4, eCXRegI result) %{ 16.10 Label ECX_GOOD_LABEL, LENGTH_DIFF_LABEL, 16.11 POP_LABEL, DONE_LABEL, CONT_LABEL, 16.12 WHILE_HEAD_LABEL; 16.13 MacroAssembler masm(&cbuf); 16.14 16.15 + XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 16.16 + XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 16.17 + 16.18 // Get the first character position in both strings 16.19 // [8] char array, [12] offset, [16] count 16.20 int value_offset = java_lang_String::value_offset_in_bytes(); 16.21 @@ -3717,7 +3721,6 @@ 16.22 // Compute the minimum of the string lengths(rsi) and the 16.23 // difference of the string lengths (stack) 16.24 16.25 - 16.26 if (VM_Version::supports_cmov()) { 16.27 masm.movl(rdi, Address(rdi, count_offset)); 16.28 masm.movl(rsi, Address(rsi, count_offset)); 16.29 @@ -3731,7 +3734,7 @@ 16.30 masm.movl(rsi, rdi); 16.31 masm.subl(rdi, rcx); 16.32 masm.push(rdi); 16.33 - masm.jcc(Assembler::lessEqual, ECX_GOOD_LABEL); 16.34 + masm.jccb(Assembler::lessEqual, ECX_GOOD_LABEL); 16.35 masm.movl(rsi, rcx); 16.36 // rsi holds min, rcx is unused 16.37 } 16.38 @@ -3756,7 +3759,7 @@ 16.39 Label LSkip2; 16.40 // Check if the strings start at same location 16.41 masm.cmpptr(rbx,rax); 16.42 - masm.jcc(Assembler::notEqual, LSkip2); 16.43 + masm.jccb(Assembler::notEqual, LSkip2); 16.44 16.45 // Check if the length difference is zero (from stack) 16.46 masm.cmpl(Address(rsp, 0), 0x0); 16.47 @@ -3766,9 +3769,52 @@ 16.48 masm.bind(LSkip2); 16.49 } 16.50 16.51 - // Shift rax, and rbx, to the end of the arrays, negate min 16.52 - masm.lea(rax, Address(rax, rsi, Address::times_2, 2)); 16.53 - masm.lea(rbx, Address(rbx, rsi, Address::times_2, 2)); 16.54 + // Advance to next character 16.55 + masm.addptr(rax, 2); 16.56 + masm.addptr(rbx, 2); 16.57 + 16.58 + if (UseSSE42Intrinsics) { 16.59 + // With SSE4.2, use double quad vector compare 16.60 + Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL; 16.61 + // Setup to compare 16-byte vectors 16.62 + masm.movl(rdi, rsi); 16.63 + masm.andl(rsi, 0xfffffff8); // rsi holds the vector count 16.64 + masm.andl(rdi, 0x00000007); // rdi holds the tail count 16.65 + masm.testl(rsi, rsi); 16.66 + masm.jccb(Assembler::zero, COMPARE_TAIL); 16.67 + 16.68 + masm.lea(rax, Address(rax, rsi, Address::times_2)); 16.69 + masm.lea(rbx, Address(rbx, rsi, Address::times_2)); 16.70 + masm.negl(rsi); 16.71 + 16.72 + masm.bind(COMPARE_VECTORS); 16.73 + masm.movdqu(tmp1Reg, Address(rax, rsi, Address::times_2)); 16.74 + masm.movdqu(tmp2Reg, Address(rbx, rsi, Address::times_2)); 16.75 + masm.pxor(tmp1Reg, tmp2Reg); 16.76 + masm.ptest(tmp1Reg, tmp1Reg); 16.77 + masm.jccb(Assembler::notZero, VECTOR_NOT_EQUAL); 16.78 + masm.addl(rsi, 8); 16.79 + masm.jcc(Assembler::notZero, COMPARE_VECTORS); 16.80 + masm.jmpb(COMPARE_TAIL); 16.81 + 16.82 + // Mismatched characters in the vectors 16.83 + masm.bind(VECTOR_NOT_EQUAL); 16.84 + masm.lea(rax, Address(rax, rsi, Address::times_2)); 16.85 + masm.lea(rbx, Address(rbx, rsi, Address::times_2)); 16.86 + masm.movl(rdi, 8); 16.87 + 16.88 + // Compare tail (< 8 chars), or rescan last vectors to 16.89 + // find 1st mismatched characters 16.90 + masm.bind(COMPARE_TAIL); 16.91 + masm.testl(rdi, rdi); 16.92 + masm.jccb(Assembler::zero, LENGTH_DIFF_LABEL); 16.93 + masm.movl(rsi, rdi); 16.94 + // Fallthru to tail compare 16.95 + } 16.96 + 16.97 + //Shift rax, and rbx, to the end of the arrays, negate min 16.98 + masm.lea(rax, Address(rax, rsi, Address::times_2, 0)); 16.99 + masm.lea(rbx, Address(rbx, rsi, Address::times_2, 0)); 16.100 masm.negl(rsi); 16.101 16.102 // Compare the rest of the characters 16.103 @@ -3776,93 +3822,329 @@ 16.104 masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0)); 16.105 masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0)); 16.106 masm.subl(rcx, rdi); 16.107 - masm.jcc(Assembler::notZero, POP_LABEL); 16.108 + masm.jccb(Assembler::notZero, POP_LABEL); 16.109 masm.incrementl(rsi); 16.110 masm.jcc(Assembler::notZero, WHILE_HEAD_LABEL); 16.111 16.112 // Strings are equal up to min length. Return the length difference. 16.113 masm.bind(LENGTH_DIFF_LABEL); 16.114 masm.pop(rcx); 16.115 - masm.jmp(DONE_LABEL); 16.116 + masm.jmpb(DONE_LABEL); 16.117 16.118 // Discard the stored length difference 16.119 masm.bind(POP_LABEL); 16.120 masm.addptr(rsp, 4); 16.121 - 16.122 + 16.123 // That's it 16.124 masm.bind(DONE_LABEL); 16.125 %} 16.126 16.127 - enc_class enc_Array_Equals(eDIRegP ary1, eSIRegP ary2, eAXRegI tmp1, eBXRegI tmp2, eCXRegI result) %{ 16.128 - Label TRUE_LABEL, FALSE_LABEL, DONE_LABEL, COMPARE_LOOP_HDR, COMPARE_LOOP; 16.129 + enc_class enc_String_Equals(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2, 16.130 + eBXRegI tmp3, eCXRegI tmp4, eAXRegI result) %{ 16.131 + Label RET_TRUE, RET_FALSE, DONE, COMPARE_VECTORS, COMPARE_CHAR; 16.132 MacroAssembler masm(&cbuf); 16.133 16.134 - Register ary1Reg = as_Register($ary1$$reg); 16.135 - Register ary2Reg = as_Register($ary2$$reg); 16.136 - Register tmp1Reg = as_Register($tmp1$$reg); 16.137 - Register tmp2Reg = as_Register($tmp2$$reg); 16.138 - Register resultReg = as_Register($result$$reg); 16.139 + XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 16.140 + XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 16.141 + 16.142 + int value_offset = java_lang_String::value_offset_in_bytes(); 16.143 + int offset_offset = java_lang_String::offset_offset_in_bytes(); 16.144 + int count_offset = java_lang_String::count_offset_in_bytes(); 16.145 + int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 16.146 + 16.147 + // does source == target string? 16.148 + masm.cmpptr(rdi, rsi); 16.149 + masm.jcc(Assembler::equal, RET_TRUE); 16.150 + 16.151 + // get and compare counts 16.152 + masm.movl(rcx, Address(rdi, count_offset)); 16.153 + masm.movl(rax, Address(rsi, count_offset)); 16.154 + masm.cmpl(rcx, rax); 16.155 + masm.jcc(Assembler::notEqual, RET_FALSE); 16.156 + masm.testl(rax, rax); 16.157 + masm.jcc(Assembler::zero, RET_TRUE); 16.158 + 16.159 + // get source string offset and value 16.160 + masm.movptr(rbx, Address(rsi, value_offset)); 16.161 + masm.movl(rax, Address(rsi, offset_offset)); 16.162 + masm.leal(rsi, Address(rbx, rax, Address::times_2, base_offset)); 16.163 + 16.164 + // get compare string offset and value 16.165 + masm.movptr(rbx, Address(rdi, value_offset)); 16.166 + masm.movl(rax, Address(rdi, offset_offset)); 16.167 + masm.leal(rdi, Address(rbx, rax, Address::times_2, base_offset)); 16.168 + 16.169 + // Set byte count 16.170 + masm.shll(rcx, 1); 16.171 + masm.movl(rax, rcx); 16.172 + 16.173 + if (UseSSE42Intrinsics) { 16.174 + // With SSE4.2, use double quad vector compare 16.175 + Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; 16.176 + // Compare 16-byte vectors 16.177 + masm.andl(rcx, 0xfffffff0); // vector count (in bytes) 16.178 + masm.andl(rax, 0x0000000e); // tail count (in bytes) 16.179 + masm.testl(rcx, rcx); 16.180 + masm.jccb(Assembler::zero, COMPARE_TAIL); 16.181 + masm.lea(rdi, Address(rdi, rcx, Address::times_1)); 16.182 + masm.lea(rsi, Address(rsi, rcx, Address::times_1)); 16.183 + masm.negl(rcx); 16.184 + 16.185 + masm.bind(COMPARE_WIDE_VECTORS); 16.186 + masm.movdqu(tmp1Reg, Address(rdi, rcx, Address::times_1)); 16.187 + masm.movdqu(tmp2Reg, Address(rsi, rcx, Address::times_1)); 16.188 + masm.pxor(tmp1Reg, tmp2Reg); 16.189 + masm.ptest(tmp1Reg, tmp1Reg); 16.190 + masm.jccb(Assembler::notZero, RET_FALSE); 16.191 + masm.addl(rcx, 16); 16.192 + masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); 16.193 + masm.bind(COMPARE_TAIL); 16.194 + masm.movl(rcx, rax); 16.195 + // Fallthru to tail compare 16.196 + } 16.197 + 16.198 + // Compare 4-byte vectors 16.199 + masm.andl(rcx, 0xfffffffc); // vector count (in bytes) 16.200 + masm.andl(rax, 0x00000002); // tail char (in bytes) 16.201 + masm.testl(rcx, rcx); 16.202 + masm.jccb(Assembler::zero, COMPARE_CHAR); 16.203 + masm.lea(rdi, Address(rdi, rcx, Address::times_1)); 16.204 + masm.lea(rsi, Address(rsi, rcx, Address::times_1)); 16.205 + masm.negl(rcx); 16.206 + 16.207 + masm.bind(COMPARE_VECTORS); 16.208 + masm.movl(rbx, Address(rdi, rcx, Address::times_1)); 16.209 + masm.cmpl(rbx, Address(rsi, rcx, Address::times_1)); 16.210 + masm.jccb(Assembler::notEqual, RET_FALSE); 16.211 + masm.addl(rcx, 4); 16.212 + masm.jcc(Assembler::notZero, COMPARE_VECTORS); 16.213 + 16.214 + // Compare trailing char (final 2 bytes), if any 16.215 + masm.bind(COMPARE_CHAR); 16.216 + masm.testl(rax, rax); 16.217 + masm.jccb(Assembler::zero, RET_TRUE); 16.218 + masm.load_unsigned_short(rbx, Address(rdi, 0)); 16.219 + masm.load_unsigned_short(rcx, Address(rsi, 0)); 16.220 + masm.cmpl(rbx, rcx); 16.221 + masm.jccb(Assembler::notEqual, RET_FALSE); 16.222 + 16.223 + masm.bind(RET_TRUE); 16.224 + masm.movl(rax, 1); // return true 16.225 + masm.jmpb(DONE); 16.226 + 16.227 + masm.bind(RET_FALSE); 16.228 + masm.xorl(rax, rax); // return false 16.229 + 16.230 + masm.bind(DONE); 16.231 + %} 16.232 + 16.233 + enc_class enc_String_IndexOf(eSIRegP str1, eDIRegP str2, regXD tmp1, eAXRegI tmp2, 16.234 + eCXRegI tmp3, eDXRegI tmp4, eBXRegI result) %{ 16.235 + // SSE4.2 version 16.236 + Label LOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR, 16.237 + SCAN_SUBSTR, RET_NEG_ONE, RET_NOT_FOUND, CLEANUP, DONE; 16.238 + MacroAssembler masm(&cbuf); 16.239 + 16.240 + XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 16.241 + 16.242 + // Get the first character position in both strings 16.243 + // [8] char array, [12] offset, [16] count 16.244 + int value_offset = java_lang_String::value_offset_in_bytes(); 16.245 + int offset_offset = java_lang_String::offset_offset_in_bytes(); 16.246 + int count_offset = java_lang_String::count_offset_in_bytes(); 16.247 + int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 16.248 + 16.249 + // Get counts for string and substr 16.250 + masm.movl(rdx, Address(rsi, count_offset)); 16.251 + masm.movl(rax, Address(rdi, count_offset)); 16.252 + // Check for substr count > string count 16.253 + masm.cmpl(rax, rdx); 16.254 + masm.jcc(Assembler::greater, RET_NEG_ONE); 16.255 + 16.256 + // Start the indexOf operation 16.257 + // Get start addr of string 16.258 + masm.movptr(rbx, Address(rsi, value_offset)); 16.259 + masm.movl(rcx, Address(rsi, offset_offset)); 16.260 + masm.lea(rsi, Address(rbx, rcx, Address::times_2, base_offset)); 16.261 + masm.push(rsi); 16.262 + 16.263 + // Get start addr of substr 16.264 + masm.movptr(rbx, Address(rdi, value_offset)); 16.265 + masm.movl(rcx, Address(rdi, offset_offset)); 16.266 + masm.lea(rdi, Address(rbx, rcx, Address::times_2, base_offset)); 16.267 + masm.push(rdi); 16.268 + masm.push(rax); 16.269 + masm.jmpb(PREP_FOR_SCAN); 16.270 + 16.271 + // Substr count saved at sp 16.272 + // Substr saved at sp+4 16.273 + // String saved at sp+8 16.274 + 16.275 + // Prep to load substr for scan 16.276 + masm.bind(LOAD_SUBSTR); 16.277 + masm.movptr(rdi, Address(rsp, 4)); 16.278 + masm.movl(rax, Address(rsp, 0)); 16.279 + 16.280 + // Load substr 16.281 + masm.bind(PREP_FOR_SCAN); 16.282 + masm.movdqu(tmp1Reg, Address(rdi, 0)); 16.283 + masm.addl(rdx, 8); // prime the loop 16.284 + masm.subptr(rsi, 16); 16.285 + 16.286 + // Scan string for substr in 16-byte vectors 16.287 + masm.bind(SCAN_TO_SUBSTR); 16.288 + masm.subl(rdx, 8); 16.289 + masm.addptr(rsi, 16); 16.290 + masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d); 16.291 + masm.jcc(Assembler::above, SCAN_TO_SUBSTR); // CF == 0 && ZF == 0 16.292 + masm.jccb(Assembler::aboveEqual, RET_NOT_FOUND); // CF == 0 16.293 + 16.294 + // Fallthru: found a potential substr 16.295 + 16.296 + // Make sure string is still long enough 16.297 + masm.subl(rdx, rcx); 16.298 + masm.cmpl(rdx, rax); 16.299 + masm.jccb(Assembler::negative, RET_NOT_FOUND); 16.300 + // Compute start addr of substr 16.301 + masm.lea(rsi, Address(rsi, rcx, Address::times_2)); 16.302 + masm.movptr(rbx, rsi); 16.303 + 16.304 + // Compare potential substr 16.305 + masm.addl(rdx, 8); // prime the loop 16.306 + masm.addl(rax, 8); 16.307 + masm.subptr(rsi, 16); 16.308 + masm.subptr(rdi, 16); 16.309 + 16.310 + // Scan 16-byte vectors of string and substr 16.311 + masm.bind(SCAN_SUBSTR); 16.312 + masm.subl(rax, 8); 16.313 + masm.subl(rdx, 8); 16.314 + masm.addptr(rsi, 16); 16.315 + masm.addptr(rdi, 16); 16.316 + masm.movdqu(tmp1Reg, Address(rdi, 0)); 16.317 + masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d); 16.318 + masm.jcc(Assembler::noOverflow, LOAD_SUBSTR); // OF == 0 16.319 + masm.jcc(Assembler::positive, SCAN_SUBSTR); // SF == 0 16.320 + 16.321 + // Compute substr offset 16.322 + masm.movptr(rsi, Address(rsp, 8)); 16.323 + masm.subptr(rbx, rsi); 16.324 + masm.shrl(rbx, 1); 16.325 + masm.jmpb(CLEANUP); 16.326 + 16.327 + masm.bind(RET_NEG_ONE); 16.328 + masm.movl(rbx, -1); 16.329 + masm.jmpb(DONE); 16.330 + 16.331 + masm.bind(RET_NOT_FOUND); 16.332 + masm.movl(rbx, -1); 16.333 + 16.334 + masm.bind(CLEANUP); 16.335 + masm.addptr(rsp, 12); 16.336 + 16.337 + masm.bind(DONE); 16.338 + %} 16.339 + 16.340 + enc_class enc_Array_Equals(eDIRegP ary1, eSIRegP ary2, regXD tmp1, regXD tmp2, 16.341 + eBXRegI tmp3, eDXRegI tmp4, eAXRegI result) %{ 16.342 + Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR; 16.343 + MacroAssembler masm(&cbuf); 16.344 + 16.345 + XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 16.346 + XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 16.347 + Register ary1Reg = as_Register($ary1$$reg); 16.348 + Register ary2Reg = as_Register($ary2$$reg); 16.349 + Register tmp3Reg = as_Register($tmp3$$reg); 16.350 + Register tmp4Reg = as_Register($tmp4$$reg); 16.351 + Register resultReg = as_Register($result$$reg); 16.352 16.353 int length_offset = arrayOopDesc::length_offset_in_bytes(); 16.354 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 16.355 16.356 // Check the input args 16.357 - masm.cmpl(ary1Reg, ary2Reg); 16.358 + masm.cmpptr(ary1Reg, ary2Reg); 16.359 masm.jcc(Assembler::equal, TRUE_LABEL); 16.360 - masm.testl(ary1Reg, ary1Reg); 16.361 + masm.testptr(ary1Reg, ary1Reg); 16.362 masm.jcc(Assembler::zero, FALSE_LABEL); 16.363 - masm.testl(ary2Reg, ary2Reg); 16.364 + masm.testptr(ary2Reg, ary2Reg); 16.365 masm.jcc(Assembler::zero, FALSE_LABEL); 16.366 16.367 // Check the lengths 16.368 - masm.movl(tmp2Reg, Address(ary1Reg, length_offset)); 16.369 + masm.movl(tmp4Reg, Address(ary1Reg, length_offset)); 16.370 masm.movl(resultReg, Address(ary2Reg, length_offset)); 16.371 - masm.cmpl(tmp2Reg, resultReg); 16.372 + masm.cmpl(tmp4Reg, resultReg); 16.373 masm.jcc(Assembler::notEqual, FALSE_LABEL); 16.374 masm.testl(resultReg, resultReg); 16.375 masm.jcc(Assembler::zero, TRUE_LABEL); 16.376 16.377 - // Get the number of 4 byte vectors to compare 16.378 - masm.shrl(resultReg, 1); 16.379 - 16.380 - // Check for odd-length arrays 16.381 - masm.andl(tmp2Reg, 1); 16.382 - masm.testl(tmp2Reg, tmp2Reg); 16.383 - masm.jcc(Assembler::zero, COMPARE_LOOP_HDR); 16.384 - 16.385 - // Compare 2-byte "tail" at end of arrays 16.386 - masm.load_unsigned_short(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset)); 16.387 - masm.load_unsigned_short(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset)); 16.388 - masm.cmpl(tmp1Reg, tmp2Reg); 16.389 - masm.jcc(Assembler::notEqual, FALSE_LABEL); 16.390 + // Load array addrs 16.391 + masm.lea(ary1Reg, Address(ary1Reg, base_offset)); 16.392 + masm.lea(ary2Reg, Address(ary2Reg, base_offset)); 16.393 + 16.394 + // Set byte count 16.395 + masm.shll(tmp4Reg, 1); 16.396 + masm.movl(resultReg, tmp4Reg); 16.397 + 16.398 + if (UseSSE42Intrinsics) { 16.399 + // With SSE4.2, use double quad vector compare 16.400 + Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; 16.401 + // Compare 16-byte vectors 16.402 + masm.andl(tmp4Reg, 0xfffffff0); // vector count (in bytes) 16.403 + masm.andl(resultReg, 0x0000000e); // tail count (in bytes) 16.404 + masm.testl(tmp4Reg, tmp4Reg); 16.405 + masm.jccb(Assembler::zero, COMPARE_TAIL); 16.406 + masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 16.407 + masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 16.408 + masm.negl(tmp4Reg); 16.409 + 16.410 + masm.bind(COMPARE_WIDE_VECTORS); 16.411 + masm.movdqu(tmp1Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 16.412 + masm.movdqu(tmp2Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 16.413 + masm.pxor(tmp1Reg, tmp2Reg); 16.414 + masm.ptest(tmp1Reg, tmp1Reg); 16.415 + 16.416 + masm.jccb(Assembler::notZero, FALSE_LABEL); 16.417 + masm.addl(tmp4Reg, 16); 16.418 + masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); 16.419 + masm.bind(COMPARE_TAIL); 16.420 + masm.movl(tmp4Reg, resultReg); 16.421 + // Fallthru to tail compare 16.422 + } 16.423 + 16.424 + // Compare 4-byte vectors 16.425 + masm.andl(tmp4Reg, 0xfffffffc); // vector count (in bytes) 16.426 + masm.andl(resultReg, 0x00000002); // tail char (in bytes) 16.427 + masm.testl(tmp4Reg, tmp4Reg); 16.428 + masm.jccb(Assembler::zero, COMPARE_CHAR); 16.429 + masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 16.430 + masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 16.431 + masm.negl(tmp4Reg); 16.432 + 16.433 + masm.bind(COMPARE_VECTORS); 16.434 + masm.movl(tmp3Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 16.435 + masm.cmpl(tmp3Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 16.436 + masm.jccb(Assembler::notEqual, FALSE_LABEL); 16.437 + masm.addl(tmp4Reg, 4); 16.438 + masm.jcc(Assembler::notZero, COMPARE_VECTORS); 16.439 + 16.440 + // Compare trailing char (final 2 bytes), if any 16.441 + masm.bind(COMPARE_CHAR); 16.442 masm.testl(resultReg, resultReg); 16.443 - masm.jcc(Assembler::zero, TRUE_LABEL); 16.444 - 16.445 - // Setup compare loop 16.446 - masm.bind(COMPARE_LOOP_HDR); 16.447 - // Shift tmp1Reg and tmp2Reg to the last 4-byte boundary of the arrays 16.448 - masm.leal(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset)); 16.449 - masm.leal(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset)); 16.450 - masm.negl(resultReg); 16.451 - 16.452 - // 4-byte-wide compare loop 16.453 - masm.bind(COMPARE_LOOP); 16.454 - masm.movl(ary1Reg, Address(tmp1Reg, resultReg, Address::times_4, 0)); 16.455 - masm.movl(ary2Reg, Address(tmp2Reg, resultReg, Address::times_4, 0)); 16.456 - masm.cmpl(ary1Reg, ary2Reg); 16.457 - masm.jcc(Assembler::notEqual, FALSE_LABEL); 16.458 - masm.increment(resultReg); 16.459 - masm.jcc(Assembler::notZero, COMPARE_LOOP); 16.460 + masm.jccb(Assembler::zero, TRUE_LABEL); 16.461 + masm.load_unsigned_short(tmp3Reg, Address(ary1Reg, 0)); 16.462 + masm.load_unsigned_short(tmp4Reg, Address(ary2Reg, 0)); 16.463 + masm.cmpl(tmp3Reg, tmp4Reg); 16.464 + masm.jccb(Assembler::notEqual, FALSE_LABEL); 16.465 16.466 masm.bind(TRUE_LABEL); 16.467 masm.movl(resultReg, 1); // return true 16.468 - masm.jmp(DONE_LABEL); 16.469 + masm.jmpb(DONE); 16.470 16.471 masm.bind(FALSE_LABEL); 16.472 masm.xorl(resultReg, resultReg); // return false 16.473 16.474 // That's it 16.475 - masm.bind(DONE_LABEL); 16.476 + masm.bind(DONE); 16.477 %} 16.478 16.479 enc_class enc_pop_rdx() %{ 16.480 @@ -4288,24 +4570,6 @@ 16.481 emit_opcode(cbuf, 0xC8 + $src2$$reg); 16.482 %} 16.483 16.484 - enc_class enc_membar_acquire %{ 16.485 - // Doug Lea believes this is not needed with current Sparcs and TSO. 16.486 - // MacroAssembler masm(&cbuf); 16.487 - // masm.membar(); 16.488 - %} 16.489 - 16.490 - enc_class enc_membar_release %{ 16.491 - // Doug Lea believes this is not needed with current Sparcs and TSO. 16.492 - // MacroAssembler masm(&cbuf); 16.493 - // masm.membar(); 16.494 - %} 16.495 - 16.496 - enc_class enc_membar_volatile %{ 16.497 - MacroAssembler masm(&cbuf); 16.498 - masm.membar(Assembler::Membar_mask_bits(Assembler::StoreLoad | 16.499 - Assembler::StoreStore)); 16.500 - %} 16.501 - 16.502 // Atomically load the volatile long 16.503 enc_class enc_loadL_volatile( memory mem, stackSlotL dst ) %{ 16.504 emit_opcode(cbuf,0xDF); 16.505 @@ -7498,9 +7762,9 @@ 16.506 ins_cost(400); 16.507 16.508 size(0); 16.509 - format %{ "MEMBAR-acquire" %} 16.510 - ins_encode( enc_membar_acquire ); 16.511 - ins_pipe(pipe_slow); 16.512 + format %{ "MEMBAR-acquire ! (empty encoding)" %} 16.513 + ins_encode(); 16.514 + ins_pipe(empty); 16.515 %} 16.516 16.517 instruct membar_acquire_lock() %{ 16.518 @@ -7519,9 +7783,9 @@ 16.519 ins_cost(400); 16.520 16.521 size(0); 16.522 - format %{ "MEMBAR-release" %} 16.523 - ins_encode( enc_membar_release ); 16.524 - ins_pipe(pipe_slow); 16.525 + format %{ "MEMBAR-release ! (empty encoding)" %} 16.526 + ins_encode( ); 16.527 + ins_pipe(empty); 16.528 %} 16.529 16.530 instruct membar_release_lock() %{ 16.531 @@ -7535,12 +7799,22 @@ 16.532 ins_pipe(empty); 16.533 %} 16.534 16.535 -instruct membar_volatile() %{ 16.536 +instruct membar_volatile(eFlagsReg cr) %{ 16.537 match(MemBarVolatile); 16.538 + effect(KILL cr); 16.539 ins_cost(400); 16.540 16.541 - format %{ "MEMBAR-volatile" %} 16.542 - ins_encode( enc_membar_volatile ); 16.543 + format %{ 16.544 + $$template 16.545 + if (os::is_MP()) { 16.546 + $$emit$$"LOCK ADDL [ESP + #0], 0\t! membar_volatile" 16.547 + } else { 16.548 + $$emit$$"MEMBAR-volatile ! (empty encoding)" 16.549 + } 16.550 + %} 16.551 + ins_encode %{ 16.552 + __ membar(Assembler::StoreLoad); 16.553 + %} 16.554 ins_pipe(pipe_slow); 16.555 %} 16.556 16.557 @@ -12082,11 +12356,8 @@ 16.558 ins_pipe( fpu_reg_reg ); 16.559 %} 16.560 16.561 - 16.562 - 16.563 // ======================================================================= 16.564 // fast clearing of an array 16.565 - 16.566 instruct rep_stos(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlagsReg cr) %{ 16.567 match(Set dummy (ClearArray cnt base)); 16.568 effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr); 16.569 @@ -12100,24 +12371,48 @@ 16.570 ins_pipe( pipe_slow ); 16.571 %} 16.572 16.573 -instruct string_compare(eDIRegP str1, eSIRegP str2, eAXRegI tmp1, eBXRegI tmp2, eCXRegI result, eFlagsReg cr) %{ 16.574 +instruct string_compare(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2, 16.575 + eAXRegI tmp3, eBXRegI tmp4, eCXRegI result, eFlagsReg cr) %{ 16.576 match(Set result (StrComp str1 str2)); 16.577 - effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL cr); 16.578 + effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr); 16.579 //ins_cost(300); 16.580 16.581 format %{ "String Compare $str1,$str2 -> $result // KILL EAX, EBX" %} 16.582 - ins_encode( enc_String_Compare() ); 16.583 + ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, tmp3, tmp4, result) ); 16.584 + ins_pipe( pipe_slow ); 16.585 +%} 16.586 + 16.587 +// fast string equals 16.588 +instruct string_equals(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2, 16.589 + eBXRegI tmp3, eCXRegI tmp4, eAXRegI result, eFlagsReg cr) %{ 16.590 + match(Set result (StrEquals str1 str2)); 16.591 + effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr); 16.592 + 16.593 + format %{ "String Equals $str1,$str2 -> $result // KILL EBX, ECX" %} 16.594 + ins_encode( enc_String_Equals(tmp1, tmp2, str1, str2, tmp3, tmp4, result) ); 16.595 + ins_pipe( pipe_slow ); 16.596 +%} 16.597 + 16.598 +instruct string_indexof(eSIRegP str1, eDIRegP str2, regXD tmp1, eAXRegI tmp2, 16.599 + eCXRegI tmp3, eDXRegI tmp4, eBXRegI result, eFlagsReg cr) %{ 16.600 + predicate(UseSSE42Intrinsics); 16.601 + match(Set result (StrIndexOf str1 str2)); 16.602 + effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, KILL tmp2, KILL tmp3, KILL tmp4, KILL cr); 16.603 + 16.604 + format %{ "String IndexOf $str1,$str2 -> $result // KILL EAX, ECX, EDX" %} 16.605 + ins_encode( enc_String_IndexOf(str1, str2, tmp1, tmp2, tmp3, tmp4, result) ); 16.606 ins_pipe( pipe_slow ); 16.607 %} 16.608 16.609 // fast array equals 16.610 -instruct array_equals(eDIRegP ary1, eSIRegP ary2, eAXRegI tmp1, eBXRegI tmp2, eCXRegI result, eFlagsReg cr) %{ 16.611 +instruct array_equals(eDIRegP ary1, eSIRegP ary2, regXD tmp1, regXD tmp2, eBXRegI tmp3, 16.612 + eDXRegI tmp4, eAXRegI result, eFlagsReg cr) %{ 16.613 match(Set result (AryEq ary1 ary2)); 16.614 - effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL cr); 16.615 + effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr); 16.616 //ins_cost(300); 16.617 16.618 - format %{ "Array Equals $ary1,$ary2 -> $result // KILL EAX, EBX" %} 16.619 - ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result) ); 16.620 + format %{ "Array Equals $ary1,$ary2 -> $result // KILL EBX, EDX" %} 16.621 + ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, tmp4, result) ); 16.622 ins_pipe( pipe_slow ); 16.623 %} 16.624
17.1 --- a/src/cpu/x86/vm/x86_64.ad Wed Apr 01 22:31:26 2009 -0700 17.2 +++ b/src/cpu/x86/vm/x86_64.ad Thu Apr 02 17:01:00 2009 -0700 17.3 @@ -3694,13 +3694,16 @@ 17.4 } 17.5 %} 17.6 17.7 - enc_class enc_String_Compare() 17.8 - %{ 17.9 + enc_class enc_String_Compare(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2, 17.10 + rax_RegI tmp3, rbx_RegI tmp4, rcx_RegI result) %{ 17.11 Label RCX_GOOD_LABEL, LENGTH_DIFF_LABEL, 17.12 POP_LABEL, DONE_LABEL, CONT_LABEL, 17.13 WHILE_HEAD_LABEL; 17.14 MacroAssembler masm(&cbuf); 17.15 17.16 + XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 17.17 + XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 17.18 + 17.19 // Get the first character position in both strings 17.20 // [8] char array, [12] offset, [16] count 17.21 int value_offset = java_lang_String::value_offset_in_bytes(); 17.22 @@ -3718,6 +3721,7 @@ 17.23 // Compute the minimum of the string lengths(rsi) and the 17.24 // difference of the string lengths (stack) 17.25 17.26 + // do the conditional move stuff 17.27 masm.movl(rdi, Address(rdi, count_offset)); 17.28 masm.movl(rsi, Address(rsi, count_offset)); 17.29 masm.movl(rcx, rdi); 17.30 @@ -3745,7 +3749,7 @@ 17.31 Label LSkip2; 17.32 // Check if the strings start at same location 17.33 masm.cmpptr(rbx, rax); 17.34 - masm.jcc(Assembler::notEqual, LSkip2); 17.35 + masm.jccb(Assembler::notEqual, LSkip2); 17.36 17.37 // Check if the length difference is zero (from stack) 17.38 masm.cmpl(Address(rsp, 0), 0x0); 17.39 @@ -3755,9 +3759,52 @@ 17.40 masm.bind(LSkip2); 17.41 } 17.42 17.43 + // Advance to next character 17.44 + masm.addptr(rax, 2); 17.45 + masm.addptr(rbx, 2); 17.46 + 17.47 + if (UseSSE42Intrinsics) { 17.48 + // With SSE4.2, use double quad vector compare 17.49 + Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL; 17.50 + // Setup to compare 16-byte vectors 17.51 + masm.movl(rdi, rsi); 17.52 + masm.andl(rsi, 0xfffffff8); // rsi holds the vector count 17.53 + masm.andl(rdi, 0x00000007); // rdi holds the tail count 17.54 + masm.testl(rsi, rsi); 17.55 + masm.jccb(Assembler::zero, COMPARE_TAIL); 17.56 + 17.57 + masm.lea(rax, Address(rax, rsi, Address::times_2)); 17.58 + masm.lea(rbx, Address(rbx, rsi, Address::times_2)); 17.59 + masm.negptr(rsi); 17.60 + 17.61 + masm.bind(COMPARE_VECTORS); 17.62 + masm.movdqu(tmp1Reg, Address(rax, rsi, Address::times_2)); 17.63 + masm.movdqu(tmp2Reg, Address(rbx, rsi, Address::times_2)); 17.64 + masm.pxor(tmp1Reg, tmp2Reg); 17.65 + masm.ptest(tmp1Reg, tmp1Reg); 17.66 + masm.jccb(Assembler::notZero, VECTOR_NOT_EQUAL); 17.67 + masm.addptr(rsi, 8); 17.68 + masm.jcc(Assembler::notZero, COMPARE_VECTORS); 17.69 + masm.jmpb(COMPARE_TAIL); 17.70 + 17.71 + // Mismatched characters in the vectors 17.72 + masm.bind(VECTOR_NOT_EQUAL); 17.73 + masm.lea(rax, Address(rax, rsi, Address::times_2)); 17.74 + masm.lea(rbx, Address(rbx, rsi, Address::times_2)); 17.75 + masm.movl(rdi, 8); 17.76 + 17.77 + // Compare tail (< 8 chars), or rescan last vectors to 17.78 + // find 1st mismatched characters 17.79 + masm.bind(COMPARE_TAIL); 17.80 + masm.testl(rdi, rdi); 17.81 + masm.jccb(Assembler::zero, LENGTH_DIFF_LABEL); 17.82 + masm.movl(rsi, rdi); 17.83 + // Fallthru to tail compare 17.84 + } 17.85 + 17.86 // Shift RAX and RBX to the end of the arrays, negate min 17.87 - masm.lea(rax, Address(rax, rsi, Address::times_2, 2)); 17.88 - masm.lea(rbx, Address(rbx, rsi, Address::times_2, 2)); 17.89 + masm.lea(rax, Address(rax, rsi, Address::times_2, 0)); 17.90 + masm.lea(rbx, Address(rbx, rsi, Address::times_2, 0)); 17.91 masm.negptr(rsi); 17.92 17.93 // Compare the rest of the characters 17.94 @@ -3765,93 +3812,329 @@ 17.95 masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0)); 17.96 masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0)); 17.97 masm.subl(rcx, rdi); 17.98 - masm.jcc(Assembler::notZero, POP_LABEL); 17.99 + masm.jccb(Assembler::notZero, POP_LABEL); 17.100 masm.increment(rsi); 17.101 masm.jcc(Assembler::notZero, WHILE_HEAD_LABEL); 17.102 17.103 // Strings are equal up to min length. Return the length difference. 17.104 masm.bind(LENGTH_DIFF_LABEL); 17.105 masm.pop(rcx); 17.106 - masm.jmp(DONE_LABEL); 17.107 + masm.jmpb(DONE_LABEL); 17.108 17.109 // Discard the stored length difference 17.110 masm.bind(POP_LABEL); 17.111 masm.addptr(rsp, 8); 17.112 - 17.113 + 17.114 // That's it 17.115 masm.bind(DONE_LABEL); 17.116 %} 17.117 17.118 - enc_class enc_Array_Equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI tmp1, rbx_RegI tmp2, rcx_RegI result) %{ 17.119 - Label TRUE_LABEL, FALSE_LABEL, DONE_LABEL, COMPARE_LOOP_HDR, COMPARE_LOOP; 17.120 + enc_class enc_String_IndexOf(rsi_RegP str1, rdi_RegP str2, regD tmp1, rax_RegI tmp2, 17.121 + rcx_RegI tmp3, rdx_RegI tmp4, rbx_RegI result) %{ 17.122 + // SSE4.2 version 17.123 + Label LOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR, 17.124 + SCAN_SUBSTR, RET_NEG_ONE, RET_NOT_FOUND, CLEANUP, DONE; 17.125 MacroAssembler masm(&cbuf); 17.126 17.127 - Register ary1Reg = as_Register($ary1$$reg); 17.128 - Register ary2Reg = as_Register($ary2$$reg); 17.129 - Register tmp1Reg = as_Register($tmp1$$reg); 17.130 - Register tmp2Reg = as_Register($tmp2$$reg); 17.131 - Register resultReg = as_Register($result$$reg); 17.132 + XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 17.133 + 17.134 + // Get the first character position in both strings 17.135 + // [8] char array, [12] offset, [16] count 17.136 + int value_offset = java_lang_String::value_offset_in_bytes(); 17.137 + int offset_offset = java_lang_String::offset_offset_in_bytes(); 17.138 + int count_offset = java_lang_String::count_offset_in_bytes(); 17.139 + int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 17.140 + 17.141 + // Get counts for string and substr 17.142 + masm.movl(rdx, Address(rsi, count_offset)); 17.143 + masm.movl(rax, Address(rdi, count_offset)); 17.144 + // Check for substr count > string count 17.145 + masm.cmpl(rax, rdx); 17.146 + masm.jcc(Assembler::greater, RET_NEG_ONE); 17.147 + 17.148 + // Start the indexOf operation 17.149 + // Get start addr of string 17.150 + masm.load_heap_oop(rbx, Address(rsi, value_offset)); 17.151 + masm.movl(rcx, Address(rsi, offset_offset)); 17.152 + masm.lea(rsi, Address(rbx, rcx, Address::times_2, base_offset)); 17.153 + masm.push(rsi); 17.154 + 17.155 + // Get start addr of substr 17.156 + masm.load_heap_oop(rbx, Address(rdi, value_offset)); 17.157 + masm.movl(rcx, Address(rdi, offset_offset)); 17.158 + masm.lea(rdi, Address(rbx, rcx, Address::times_2, base_offset)); 17.159 + masm.push(rdi); 17.160 + masm.push(rax); 17.161 + masm.jmpb(PREP_FOR_SCAN); 17.162 + 17.163 + // Substr count saved at sp 17.164 + // Substr saved at sp+8 17.165 + // String saved at sp+16 17.166 + 17.167 + // Prep to load substr for scan 17.168 + masm.bind(LOAD_SUBSTR); 17.169 + masm.movptr(rdi, Address(rsp, 8)); 17.170 + masm.movl(rax, Address(rsp, 0)); 17.171 + 17.172 + // Load substr 17.173 + masm.bind(PREP_FOR_SCAN); 17.174 + masm.movdqu(tmp1Reg, Address(rdi, 0)); 17.175 + masm.addq(rdx, 8); // prime the loop 17.176 + masm.subptr(rsi, 16); 17.177 + 17.178 + // Scan string for substr in 16-byte vectors 17.179 + masm.bind(SCAN_TO_SUBSTR); 17.180 + masm.subq(rdx, 8); 17.181 + masm.addptr(rsi, 16); 17.182 + masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d); 17.183 + masm.jcc(Assembler::above, SCAN_TO_SUBSTR); 17.184 + masm.jccb(Assembler::aboveEqual, RET_NOT_FOUND); 17.185 + 17.186 + // Fallthru: found a potential substr 17.187 + 17.188 + //Make sure string is still long enough 17.189 + masm.subl(rdx, rcx); 17.190 + masm.cmpl(rdx, rax); 17.191 + masm.jccb(Assembler::negative, RET_NOT_FOUND); 17.192 + // Compute start addr of substr 17.193 + masm.lea(rsi, Address(rsi, rcx, Address::times_2)); 17.194 + masm.movptr(rbx, rsi); 17.195 + 17.196 + // Compare potential substr 17.197 + masm.addq(rdx, 8); // prime the loop 17.198 + masm.addq(rax, 8); 17.199 + masm.subptr(rsi, 16); 17.200 + masm.subptr(rdi, 16); 17.201 + 17.202 + // Scan 16-byte vectors of string and substr 17.203 + masm.bind(SCAN_SUBSTR); 17.204 + masm.subq(rax, 8); 17.205 + masm.subq(rdx, 8); 17.206 + masm.addptr(rsi, 16); 17.207 + masm.addptr(rdi, 16); 17.208 + masm.movdqu(tmp1Reg, Address(rdi, 0)); 17.209 + masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d); 17.210 + masm.jcc(Assembler::noOverflow, LOAD_SUBSTR); // OF == 0 17.211 + masm.jcc(Assembler::positive, SCAN_SUBSTR); // SF == 0 17.212 + 17.213 + // Compute substr offset 17.214 + masm.movptr(rsi, Address(rsp, 16)); 17.215 + masm.subptr(rbx, rsi); 17.216 + masm.shrl(rbx, 1); 17.217 + masm.jmpb(CLEANUP); 17.218 + 17.219 + masm.bind(RET_NEG_ONE); 17.220 + masm.movl(rbx, -1); 17.221 + masm.jmpb(DONE); 17.222 + 17.223 + masm.bind(RET_NOT_FOUND); 17.224 + masm.movl(rbx, -1); 17.225 + 17.226 + masm.bind(CLEANUP); 17.227 + masm.addptr(rsp, 24); 17.228 + 17.229 + masm.bind(DONE); 17.230 + %} 17.231 + 17.232 + enc_class enc_String_Equals(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2, 17.233 + rbx_RegI tmp3, rcx_RegI tmp2, rax_RegI result) %{ 17.234 + Label RET_TRUE, RET_FALSE, DONE, COMPARE_VECTORS, COMPARE_CHAR; 17.235 + MacroAssembler masm(&cbuf); 17.236 + 17.237 + XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 17.238 + XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 17.239 + 17.240 + int value_offset = java_lang_String::value_offset_in_bytes(); 17.241 + int offset_offset = java_lang_String::offset_offset_in_bytes(); 17.242 + int count_offset = java_lang_String::count_offset_in_bytes(); 17.243 + int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 17.244 + 17.245 + // does source == target string? 17.246 + masm.cmpptr(rdi, rsi); 17.247 + masm.jcc(Assembler::equal, RET_TRUE); 17.248 + 17.249 + // get and compare counts 17.250 + masm.movl(rcx, Address(rdi, count_offset)); 17.251 + masm.movl(rax, Address(rsi, count_offset)); 17.252 + masm.cmpl(rcx, rax); 17.253 + masm.jcc(Assembler::notEqual, RET_FALSE); 17.254 + masm.testl(rax, rax); 17.255 + masm.jcc(Assembler::zero, RET_TRUE); 17.256 + 17.257 + // get source string offset and value 17.258 + masm.load_heap_oop(rbx, Address(rsi, value_offset)); 17.259 + masm.movl(rax, Address(rsi, offset_offset)); 17.260 + masm.lea(rsi, Address(rbx, rax, Address::times_2, base_offset)); 17.261 + 17.262 + // get compare string offset and value 17.263 + masm.load_heap_oop(rbx, Address(rdi, value_offset)); 17.264 + masm.movl(rax, Address(rdi, offset_offset)); 17.265 + masm.lea(rdi, Address(rbx, rax, Address::times_2, base_offset)); 17.266 + 17.267 + // Set byte count 17.268 + masm.shll(rcx, 1); 17.269 + masm.movl(rax, rcx); 17.270 + 17.271 + if (UseSSE42Intrinsics) { 17.272 + // With SSE4.2, use double quad vector compare 17.273 + Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; 17.274 + // Compare 16-byte vectors 17.275 + masm.andl(rcx, 0xfffffff0); // vector count (in bytes) 17.276 + masm.andl(rax, 0x0000000e); // tail count (in bytes) 17.277 + masm.testl(rcx, rcx); 17.278 + masm.jccb(Assembler::zero, COMPARE_TAIL); 17.279 + masm.lea(rdi, Address(rdi, rcx, Address::times_1)); 17.280 + masm.lea(rsi, Address(rsi, rcx, Address::times_1)); 17.281 + masm.negptr(rcx); 17.282 + 17.283 + masm.bind(COMPARE_WIDE_VECTORS); 17.284 + masm.movdqu(tmp1Reg, Address(rdi, rcx, Address::times_1)); 17.285 + masm.movdqu(tmp2Reg, Address(rsi, rcx, Address::times_1)); 17.286 + masm.pxor(tmp1Reg, tmp2Reg); 17.287 + masm.ptest(tmp1Reg, tmp1Reg); 17.288 + masm.jccb(Assembler::notZero, RET_FALSE); 17.289 + masm.addptr(rcx, 16); 17.290 + masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); 17.291 + masm.bind(COMPARE_TAIL); 17.292 + masm.movl(rcx, rax); 17.293 + // Fallthru to tail compare 17.294 + } 17.295 + 17.296 + // Compare 4-byte vectors 17.297 + masm.andl(rcx, 0xfffffffc); // vector count (in bytes) 17.298 + masm.andl(rax, 0x00000002); // tail char (in bytes) 17.299 + masm.testl(rcx, rcx); 17.300 + masm.jccb(Assembler::zero, COMPARE_CHAR); 17.301 + masm.lea(rdi, Address(rdi, rcx, Address::times_1)); 17.302 + masm.lea(rsi, Address(rsi, rcx, Address::times_1)); 17.303 + masm.negptr(rcx); 17.304 + 17.305 + masm.bind(COMPARE_VECTORS); 17.306 + masm.movl(rbx, Address(rdi, rcx, Address::times_1)); 17.307 + masm.cmpl(rbx, Address(rsi, rcx, Address::times_1)); 17.308 + masm.jccb(Assembler::notEqual, RET_FALSE); 17.309 + masm.addptr(rcx, 4); 17.310 + masm.jcc(Assembler::notZero, COMPARE_VECTORS); 17.311 + 17.312 + // Compare trailing char (final 2 bytes), if any 17.313 + masm.bind(COMPARE_CHAR); 17.314 + masm.testl(rax, rax); 17.315 + masm.jccb(Assembler::zero, RET_TRUE); 17.316 + masm.load_unsigned_short(rbx, Address(rdi, 0)); 17.317 + masm.load_unsigned_short(rcx, Address(rsi, 0)); 17.318 + masm.cmpl(rbx, rcx); 17.319 + masm.jccb(Assembler::notEqual, RET_FALSE); 17.320 + 17.321 + masm.bind(RET_TRUE); 17.322 + masm.movl(rax, 1); // return true 17.323 + masm.jmpb(DONE); 17.324 + 17.325 + masm.bind(RET_FALSE); 17.326 + masm.xorl(rax, rax); // return false 17.327 + 17.328 + masm.bind(DONE); 17.329 + %} 17.330 + 17.331 + enc_class enc_Array_Equals(rdi_RegP ary1, rsi_RegP ary2, regD tmp1, regD tmp2, 17.332 + rax_RegI tmp3, rbx_RegI tmp4, rcx_RegI result) %{ 17.333 + Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR; 17.334 + MacroAssembler masm(&cbuf); 17.335 + 17.336 + XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 17.337 + XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 17.338 + Register ary1Reg = as_Register($ary1$$reg); 17.339 + Register ary2Reg = as_Register($ary2$$reg); 17.340 + Register tmp3Reg = as_Register($tmp3$$reg); 17.341 + Register tmp4Reg = as_Register($tmp4$$reg); 17.342 + Register resultReg = as_Register($result$$reg); 17.343 17.344 int length_offset = arrayOopDesc::length_offset_in_bytes(); 17.345 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 17.346 17.347 // Check the input args 17.348 - masm.cmpq(ary1Reg, ary2Reg); 17.349 + masm.cmpq(ary1Reg, ary2Reg); 17.350 masm.jcc(Assembler::equal, TRUE_LABEL); 17.351 - masm.testq(ary1Reg, ary1Reg); 17.352 + masm.testq(ary1Reg, ary1Reg); 17.353 masm.jcc(Assembler::zero, FALSE_LABEL); 17.354 - masm.testq(ary2Reg, ary2Reg); 17.355 + masm.testq(ary2Reg, ary2Reg); 17.356 masm.jcc(Assembler::zero, FALSE_LABEL); 17.357 17.358 // Check the lengths 17.359 - masm.movl(tmp2Reg, Address(ary1Reg, length_offset)); 17.360 + masm.movl(tmp4Reg, Address(ary1Reg, length_offset)); 17.361 masm.movl(resultReg, Address(ary2Reg, length_offset)); 17.362 - masm.cmpl(tmp2Reg, resultReg); 17.363 + masm.cmpl(tmp4Reg, resultReg); 17.364 masm.jcc(Assembler::notEqual, FALSE_LABEL); 17.365 masm.testl(resultReg, resultReg); 17.366 masm.jcc(Assembler::zero, TRUE_LABEL); 17.367 17.368 - // Get the number of 4 byte vectors to compare 17.369 - masm.shrl(resultReg, 1); 17.370 - 17.371 - // Check for odd-length arrays 17.372 - masm.andl(tmp2Reg, 1); 17.373 - masm.testl(tmp2Reg, tmp2Reg); 17.374 - masm.jcc(Assembler::zero, COMPARE_LOOP_HDR); 17.375 - 17.376 - // Compare 2-byte "tail" at end of arrays 17.377 - masm.load_unsigned_short(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset)); 17.378 - masm.load_unsigned_short(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset)); 17.379 - masm.cmpl(tmp1Reg, tmp2Reg); 17.380 - masm.jcc(Assembler::notEqual, FALSE_LABEL); 17.381 + //load array address 17.382 + masm.lea(ary1Reg, Address(ary1Reg, base_offset)); 17.383 + masm.lea(ary2Reg, Address(ary2Reg, base_offset)); 17.384 + 17.385 + //set byte count 17.386 + masm.shll(tmp4Reg, 1); 17.387 + masm.movl(resultReg,tmp4Reg); 17.388 + 17.389 + if (UseSSE42Intrinsics){ 17.390 + // With SSE4.2, use double quad vector compare 17.391 + Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; 17.392 + // Compare 16-byte vectors 17.393 + masm.andl(tmp4Reg, 0xfffffff0); // vector count (in bytes) 17.394 + masm.andl(resultReg, 0x0000000e); // tail count (in bytes) 17.395 + masm.testl(tmp4Reg, tmp4Reg); 17.396 + masm.jccb(Assembler::zero, COMPARE_TAIL); 17.397 + masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 17.398 + masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 17.399 + masm.negptr(tmp4Reg); 17.400 + 17.401 + masm.bind(COMPARE_WIDE_VECTORS); 17.402 + masm.movdqu(tmp1Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 17.403 + masm.movdqu(tmp2Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 17.404 + masm.pxor(tmp1Reg, tmp2Reg); 17.405 + masm.ptest(tmp1Reg, tmp1Reg); 17.406 + 17.407 + masm.jccb(Assembler::notZero, FALSE_LABEL); 17.408 + masm.addptr(tmp4Reg, 16); 17.409 + masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); 17.410 + masm.bind(COMPARE_TAIL); 17.411 + masm.movl(tmp4Reg, resultReg); 17.412 + // Fallthru to tail compare 17.413 + } 17.414 + 17.415 + // Compare 4-byte vectors 17.416 + masm.andl(tmp4Reg, 0xfffffffc); // vector count (in bytes) 17.417 + masm.andl(resultReg, 0x00000002); // tail char (in bytes) 17.418 + masm.testl(tmp4Reg, tmp4Reg); //if tmp2 == 0, only compare char 17.419 + masm.jccb(Assembler::zero, COMPARE_CHAR); 17.420 + masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 17.421 + masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 17.422 + masm.negptr(tmp4Reg); 17.423 + 17.424 + masm.bind(COMPARE_VECTORS); 17.425 + masm.movl(tmp3Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 17.426 + masm.cmpl(tmp3Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 17.427 + masm.jccb(Assembler::notEqual, FALSE_LABEL); 17.428 + masm.addptr(tmp4Reg, 4); 17.429 + masm.jcc(Assembler::notZero, COMPARE_VECTORS); 17.430 + 17.431 + // Compare trailing char (final 2 bytes), if any 17.432 + masm.bind(COMPARE_CHAR); 17.433 masm.testl(resultReg, resultReg); 17.434 - masm.jcc(Assembler::zero, TRUE_LABEL); 17.435 - 17.436 - // Setup compare loop 17.437 - masm.bind(COMPARE_LOOP_HDR); 17.438 - // Shift tmp1Reg and tmp2Reg to the last 4-byte boundary of the arrays 17.439 - masm.leaq(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset)); 17.440 - masm.leaq(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset)); 17.441 - masm.negq(resultReg); 17.442 - 17.443 - // 4-byte-wide compare loop 17.444 - masm.bind(COMPARE_LOOP); 17.445 - masm.movl(ary1Reg, Address(tmp1Reg, resultReg, Address::times_4, 0)); 17.446 - masm.movl(ary2Reg, Address(tmp2Reg, resultReg, Address::times_4, 0)); 17.447 - masm.cmpl(ary1Reg, ary2Reg); 17.448 - masm.jcc(Assembler::notEqual, FALSE_LABEL); 17.449 - masm.incrementq(resultReg); 17.450 - masm.jcc(Assembler::notZero, COMPARE_LOOP); 17.451 + masm.jccb(Assembler::zero, TRUE_LABEL); 17.452 + masm.load_unsigned_short(tmp3Reg, Address(ary1Reg, 0)); 17.453 + masm.load_unsigned_short(tmp4Reg, Address(ary2Reg, 0)); 17.454 + masm.cmpl(tmp3Reg, tmp4Reg); 17.455 + masm.jccb(Assembler::notEqual, FALSE_LABEL); 17.456 17.457 masm.bind(TRUE_LABEL); 17.458 masm.movl(resultReg, 1); // return true 17.459 - masm.jmp(DONE_LABEL); 17.460 + masm.jmpb(DONE); 17.461 17.462 masm.bind(FALSE_LABEL); 17.463 masm.xorl(resultReg, resultReg); // return false 17.464 17.465 // That's it 17.466 - masm.bind(DONE_LABEL); 17.467 + masm.bind(DONE); 17.468 %} 17.469 17.470 enc_class enc_rethrow() 17.471 @@ -4162,33 +4445,6 @@ 17.472 // done: 17.473 %} 17.474 17.475 - enc_class enc_membar_acquire 17.476 - %{ 17.477 - // [jk] not needed currently, if you enable this and it really 17.478 - // emits code don't forget to the remove the "size(0)" line in 17.479 - // membar_acquire() 17.480 - // MacroAssembler masm(&cbuf); 17.481 - // masm.membar(Assembler::Membar_mask_bits(Assembler::LoadStore | 17.482 - // Assembler::LoadLoad)); 17.483 - %} 17.484 - 17.485 - enc_class enc_membar_release 17.486 - %{ 17.487 - // [jk] not needed currently, if you enable this and it really 17.488 - // emits code don't forget to the remove the "size(0)" line in 17.489 - // membar_release() 17.490 - // MacroAssembler masm(&cbuf); 17.491 - // masm.membar(Assembler::Membar_mask_bits(Assembler::LoadStore | 17.492 - // Assembler::StoreStore)); 17.493 - %} 17.494 - 17.495 - enc_class enc_membar_volatile 17.496 - %{ 17.497 - MacroAssembler masm(&cbuf); 17.498 - masm.membar(Assembler::Membar_mask_bits(Assembler::StoreLoad | 17.499 - Assembler::StoreStore)); 17.500 - %} 17.501 - 17.502 // Safepoint Poll. This polls the safepoint page, and causes an 17.503 // exception if it is not readable. Unfortunately, it kills 17.504 // RFLAGS in the process. 17.505 @@ -5114,7 +5370,7 @@ 17.506 %} 17.507 17.508 // Double register operands 17.509 -operand regD() 17.510 +operand regD() 17.511 %{ 17.512 constraint(ALLOC_IN_RC(double_reg)); 17.513 match(RegD); 17.514 @@ -7458,7 +7714,7 @@ 17.515 ins_cost(0); 17.516 17.517 size(0); 17.518 - format %{ "MEMBAR-acquire" %} 17.519 + format %{ "MEMBAR-acquire ! (empty encoding)" %} 17.520 ins_encode(); 17.521 ins_pipe(empty); 17.522 %} 17.523 @@ -7481,7 +7737,7 @@ 17.524 ins_cost(0); 17.525 17.526 size(0); 17.527 - format %{ "MEMBAR-release" %} 17.528 + format %{ "MEMBAR-release ! (empty encoding)" %} 17.529 ins_encode(); 17.530 ins_pipe(empty); 17.531 %} 17.532 @@ -7498,13 +7754,22 @@ 17.533 ins_pipe(empty); 17.534 %} 17.535 17.536 -instruct membar_volatile() 17.537 -%{ 17.538 +instruct membar_volatile(rFlagsReg cr) %{ 17.539 match(MemBarVolatile); 17.540 + effect(KILL cr); 17.541 ins_cost(400); 17.542 17.543 - format %{ "MEMBAR-volatile" %} 17.544 - ins_encode(enc_membar_volatile); 17.545 + format %{ 17.546 + $$template 17.547 + if (os::is_MP()) { 17.548 + $$emit$$"lock addl [rsp + #0], 0\t! membar_volatile" 17.549 + } else { 17.550 + $$emit$$"MEMBAR-volatile ! (empty encoding)" 17.551 + } 17.552 + %} 17.553 + ins_encode %{ 17.554 + __ membar(Assembler::StoreLoad); 17.555 + %} 17.556 ins_pipe(pipe_slow); 17.557 %} 17.558 17.559 @@ -11558,27 +11823,52 @@ 17.560 ins_pipe(pipe_slow); 17.561 %} 17.562 17.563 -instruct string_compare(rdi_RegP str1, rsi_RegP str2, rax_RegI tmp1, 17.564 - rbx_RegI tmp2, rcx_RegI result, rFlagsReg cr) 17.565 +instruct string_compare(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2, 17.566 + rax_RegI tmp3, rbx_RegI tmp4, rcx_RegI result, rFlagsReg cr) 17.567 %{ 17.568 match(Set result (StrComp str1 str2)); 17.569 - effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL cr); 17.570 + effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr); 17.571 //ins_cost(300); 17.572 17.573 format %{ "String Compare $str1, $str2 -> $result // XXX KILL RAX, RBX" %} 17.574 - ins_encode( enc_String_Compare() ); 17.575 + ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, tmp3, tmp4, result) ); 17.576 ins_pipe( pipe_slow ); 17.577 %} 17.578 17.579 +instruct string_indexof(rsi_RegP str1, rdi_RegP str2, regD tmp1, rax_RegI tmp2, 17.580 + rcx_RegI tmp3, rdx_RegI tmp4, rbx_RegI result, rFlagsReg cr) 17.581 +%{ 17.582 + predicate(UseSSE42Intrinsics); 17.583 + match(Set result (StrIndexOf str1 str2)); 17.584 + effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, KILL tmp2, KILL tmp3, KILL tmp4, KILL cr); 17.585 + 17.586 + format %{ "String IndexOf $str1,$str2 -> $result // KILL RAX, RCX, RDX" %} 17.587 + ins_encode( enc_String_IndexOf(str1, str2, tmp1, tmp2, tmp3, tmp4, result) ); 17.588 + ins_pipe( pipe_slow ); 17.589 +%} 17.590 + 17.591 +// fast string equals 17.592 +instruct string_equals(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2, rbx_RegI tmp3, 17.593 + rcx_RegI tmp4, rax_RegI result, rFlagsReg cr) 17.594 +%{ 17.595 + match(Set result (StrEquals str1 str2)); 17.596 + effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr); 17.597 + 17.598 + format %{ "String Equals $str1,$str2 -> $result // KILL RBX, RCX" %} 17.599 + ins_encode( enc_String_Equals(str1, str2, tmp1, tmp2, tmp3, tmp4, result) ); 17.600 + ins_pipe( pipe_slow ); 17.601 +%} 17.602 + 17.603 // fast array equals 17.604 -instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI tmp1, 17.605 - rbx_RegI tmp2, rcx_RegI result, rFlagsReg cr) %{ 17.606 +instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, regD tmp1, regD tmp2, rax_RegI tmp3, 17.607 + rbx_RegI tmp4, rcx_RegI result, rFlagsReg cr) 17.608 +%{ 17.609 match(Set result (AryEq ary1 ary2)); 17.610 - effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL cr); 17.611 + effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr); 17.612 //ins_cost(300); 17.613 17.614 - format %{ "Array Equals $ary1,$ary2 -> $result // KILL RAX, RBX" %} 17.615 - ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result) ); 17.616 + format %{ "Array Equals $ary1,$ary2 -> $result // KILL RAX, RBX" %} 17.617 + ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, tmp4, result) ); 17.618 ins_pipe( pipe_slow ); 17.619 %} 17.620
18.1 --- a/src/os_cpu/linux_sparc/vm/os_linux_sparc.hpp Wed Apr 01 22:31:26 2009 -0700 18.2 +++ b/src/os_cpu/linux_sparc/vm/os_linux_sparc.hpp Thu Apr 02 17:01:00 2009 -0700 18.3 @@ -29,13 +29,11 @@ 18.4 static jint (*atomic_cmpxchg_func) (jint, volatile jint*, jint); 18.5 static jlong (*atomic_cmpxchg_long_func)(jlong, volatile jlong*, jlong); 18.6 static jint (*atomic_add_func) (jint, volatile jint*); 18.7 - static void (*fence_func) (); 18.8 18.9 static jint atomic_xchg_bootstrap (jint, volatile jint*); 18.10 static jint atomic_cmpxchg_bootstrap (jint, volatile jint*, jint); 18.11 static jlong atomic_cmpxchg_long_bootstrap(jlong, volatile jlong*, jlong); 18.12 static jint atomic_add_bootstrap (jint, volatile jint*); 18.13 - static void fence_bootstrap (); 18.14 18.15 static void setup_fpu() {} 18.16
19.1 --- a/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp Wed Apr 01 22:31:26 2009 -0700 19.2 +++ b/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp Thu Apr 02 17:01:00 2009 -0700 19.3 @@ -44,11 +44,12 @@ 19.4 19.5 inline void OrderAccess::fence() { 19.6 if (os::is_MP()) { 19.7 + // always use locked addl since mfence is sometimes expensive 19.8 #ifdef AMD64 19.9 - __asm__ __volatile__ ("mfence":::"memory"); 19.10 + __asm__ volatile ("lock; addl $0,0(%%rsp)" : : : "cc", "memory"); 19.11 #else 19.12 __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory"); 19.13 -#endif // AMD64 19.14 +#endif 19.15 } 19.16 } 19.17
20.1 --- a/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp Wed Apr 01 22:31:26 2009 -0700 20.2 +++ b/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp Thu Apr 02 17:01:00 2009 -0700 20.3 @@ -60,22 +60,10 @@ 20.4 dummy = 0; 20.5 } 20.6 20.7 -#if defined(COMPILER2) || defined(_LP64) 20.8 - 20.9 inline void OrderAccess::fence() { 20.10 _OrderAccess_fence(); 20.11 } 20.12 20.13 -#else // defined(COMPILER2) || defined(_LP64) 20.14 - 20.15 -inline void OrderAccess::fence() { 20.16 - if (os::is_MP()) { 20.17 - (*os::fence_func)(); 20.18 - } 20.19 -} 20.20 - 20.21 -#endif // defined(COMPILER2) || defined(_LP64) 20.22 - 20.23 #endif // _GNU_SOURCE 20.24 20.25 inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; }
21.1 --- a/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Wed Apr 01 22:31:26 2009 -0700 21.2 +++ b/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Thu Apr 02 17:01:00 2009 -0700 21.3 @@ -619,7 +619,6 @@ 21.4 typedef jint cmpxchg_func_t (jint, volatile jint*, jint); 21.5 typedef jlong cmpxchg_long_func_t(jlong, volatile jlong*, jlong); 21.6 typedef jint add_func_t (jint, volatile jint*); 21.7 -typedef void fence_func_t (); 21.8 21.9 jint os::atomic_xchg_bootstrap(jint exchange_value, volatile jint* dest) { 21.10 // try to use the stub: 21.11 @@ -681,25 +680,10 @@ 21.12 return (*dest) += add_value; 21.13 } 21.14 21.15 -void os::fence_bootstrap() { 21.16 - // try to use the stub: 21.17 - fence_func_t* func = CAST_TO_FN_PTR(fence_func_t*, StubRoutines::fence_entry()); 21.18 - 21.19 - if (func != NULL) { 21.20 - os::fence_func = func; 21.21 - (*func)(); 21.22 - return; 21.23 - } 21.24 - assert(Threads::number_of_threads() == 0, "for bootstrap only"); 21.25 - 21.26 - // don't have to do anything for a single thread 21.27 -} 21.28 - 21.29 xchg_func_t* os::atomic_xchg_func = os::atomic_xchg_bootstrap; 21.30 cmpxchg_func_t* os::atomic_cmpxchg_func = os::atomic_cmpxchg_bootstrap; 21.31 cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap; 21.32 add_func_t* os::atomic_add_func = os::atomic_add_bootstrap; 21.33 -fence_func_t* os::fence_func = os::fence_bootstrap; 21.34 21.35 #endif // !_LP64 && !COMPILER2 21.36
22.1 --- a/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.hpp Wed Apr 01 22:31:26 2009 -0700 22.2 +++ b/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.hpp Thu Apr 02 17:01:00 2009 -0700 22.3 @@ -29,13 +29,11 @@ 22.4 static jint (*atomic_cmpxchg_func) (jint, volatile jint*, jint); 22.5 static jlong (*atomic_cmpxchg_long_func)(jlong, volatile jlong*, jlong); 22.6 static jint (*atomic_add_func) (jint, volatile jint*); 22.7 - static void (*fence_func) (); 22.8 22.9 static jint atomic_xchg_bootstrap (jint, volatile jint*); 22.10 static jint atomic_cmpxchg_bootstrap (jint, volatile jint*, jint); 22.11 static jlong atomic_cmpxchg_long_bootstrap(jlong, volatile jlong*, jlong); 22.12 static jint atomic_add_bootstrap (jint, volatile jint*); 22.13 - static void fence_bootstrap (); 22.14 22.15 static void setup_fpu() {} 22.16
23.1 --- a/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp Wed Apr 01 22:31:26 2009 -0700 23.2 +++ b/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp Thu Apr 02 17:01:00 2009 -0700 23.3 @@ -61,11 +61,8 @@ 23.4 #endif // AMD64 23.5 } 23.6 inline void _OrderAccess_fence() { 23.7 -#ifdef AMD64 23.8 - __asm__ __volatile__ ("mfence":::"memory"); 23.9 -#else 23.10 + // Always use locked addl since mfence is sometimes expensive 23.11 __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory"); 23.12 -#endif // AMD64 23.13 } 23.14 23.15 }
24.1 --- a/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Wed Apr 01 22:31:26 2009 -0700 24.2 +++ b/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Thu Apr 02 17:01:00 2009 -0700 24.3 @@ -794,7 +794,6 @@ 24.4 typedef jint cmpxchg_func_t (jint, volatile jint*, jint); 24.5 typedef jlong cmpxchg_long_func_t(jlong, volatile jlong*, jlong); 24.6 typedef jint add_func_t (jint, volatile jint*); 24.7 -typedef void fence_func_t (); 24.8 24.9 jint os::atomic_xchg_bootstrap(jint exchange_value, volatile jint* dest) { 24.10 // try to use the stub: 24.11 @@ -856,25 +855,10 @@ 24.12 return (*dest) += add_value; 24.13 } 24.14 24.15 -void os::fence_bootstrap() { 24.16 - // try to use the stub: 24.17 - fence_func_t* func = CAST_TO_FN_PTR(fence_func_t*, StubRoutines::fence_entry()); 24.18 - 24.19 - if (func != NULL) { 24.20 - os::fence_func = func; 24.21 - (*func)(); 24.22 - return; 24.23 - } 24.24 - assert(Threads::number_of_threads() == 0, "for bootstrap only"); 24.25 - 24.26 - // don't have to do anything for a single thread 24.27 -} 24.28 - 24.29 xchg_func_t* os::atomic_xchg_func = os::atomic_xchg_bootstrap; 24.30 cmpxchg_func_t* os::atomic_cmpxchg_func = os::atomic_cmpxchg_bootstrap; 24.31 cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap; 24.32 add_func_t* os::atomic_add_func = os::atomic_add_bootstrap; 24.33 -fence_func_t* os::fence_func = os::fence_bootstrap; 24.34 24.35 extern "C" _solaris_raw_setup_fpu(address ptr); 24.36 void os::setup_fpu() {
25.1 --- a/src/os_cpu/solaris_x86/vm/os_solaris_x86.hpp Wed Apr 01 22:31:26 2009 -0700 25.2 +++ b/src/os_cpu/solaris_x86/vm/os_solaris_x86.hpp Thu Apr 02 17:01:00 2009 -0700 25.3 @@ -32,13 +32,11 @@ 25.4 static jint (*atomic_cmpxchg_func) (jint, volatile jint*, jint); 25.5 static jlong (*atomic_cmpxchg_long_func)(jlong, volatile jlong*, jlong); 25.6 static jint (*atomic_add_func) (jint, volatile jint*); 25.7 - static void (*fence_func) (); 25.8 25.9 static jint atomic_xchg_bootstrap (jint, volatile jint*); 25.10 static jint atomic_cmpxchg_bootstrap (jint, volatile jint*, jint); 25.11 static jlong atomic_cmpxchg_long_bootstrap(jlong, volatile jlong*, jlong); 25.12 static jint atomic_add_bootstrap (jint, volatile jint*); 25.13 - static void fence_bootstrap (); 25.14 25.15 static void setup_fpu(); 25.16 #endif // AMD64
26.1 --- a/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp Wed Apr 01 22:31:26 2009 -0700 26.2 +++ b/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp Thu Apr 02 17:01:00 2009 -0700 26.3 @@ -46,7 +46,7 @@ 26.4 26.5 inline void OrderAccess::fence() { 26.6 #ifdef AMD64 26.7 - (*os::fence_func)(); 26.8 + StubRoutines_fence(); 26.9 #else 26.10 if (os::is_MP()) { 26.11 __asm {
27.1 --- a/src/os_cpu/windows_x86/vm/os_windows_x86.cpp Wed Apr 01 22:31:26 2009 -0700 27.2 +++ b/src/os_cpu/windows_x86/vm/os_windows_x86.cpp Thu Apr 02 17:01:00 2009 -0700 27.3 @@ -196,7 +196,6 @@ 27.4 typedef jlong cmpxchg_long_func_t (jlong, volatile jlong*, jlong); 27.5 typedef jint add_func_t (jint, volatile jint*); 27.6 typedef intptr_t add_ptr_func_t (intptr_t, volatile intptr_t*); 27.7 -typedef void fence_func_t (); 27.8 27.9 #ifdef AMD64 27.10 27.11 @@ -292,27 +291,11 @@ 27.12 return (*dest) += add_value; 27.13 } 27.14 27.15 -void os::fence_bootstrap() { 27.16 - // try to use the stub: 27.17 - fence_func_t* func = CAST_TO_FN_PTR(fence_func_t*, StubRoutines::fence_entry()); 27.18 - 27.19 - if (func != NULL) { 27.20 - os::fence_func = func; 27.21 - (*func)(); 27.22 - return; 27.23 - } 27.24 - assert(Threads::number_of_threads() == 0, "for bootstrap only"); 27.25 - 27.26 - // don't have to do anything for a single thread 27.27 -} 27.28 - 27.29 - 27.30 xchg_func_t* os::atomic_xchg_func = os::atomic_xchg_bootstrap; 27.31 xchg_ptr_func_t* os::atomic_xchg_ptr_func = os::atomic_xchg_ptr_bootstrap; 27.32 cmpxchg_func_t* os::atomic_cmpxchg_func = os::atomic_cmpxchg_bootstrap; 27.33 add_func_t* os::atomic_add_func = os::atomic_add_bootstrap; 27.34 add_ptr_func_t* os::atomic_add_ptr_func = os::atomic_add_ptr_bootstrap; 27.35 -fence_func_t* os::fence_func = os::fence_bootstrap; 27.36 27.37 #endif // AMD64 27.38
28.1 --- a/src/os_cpu/windows_x86/vm/os_windows_x86.hpp Wed Apr 01 22:31:26 2009 -0700 28.2 +++ b/src/os_cpu/windows_x86/vm/os_windows_x86.hpp Thu Apr 02 17:01:00 2009 -0700 28.3 @@ -35,9 +35,6 @@ 28.4 static jint (*atomic_add_func) (jint, volatile jint*); 28.5 static intptr_t (*atomic_add_ptr_func) (intptr_t, volatile intptr_t*); 28.6 28.7 - static void (*fence_func) (); 28.8 - 28.9 - 28.10 static jint atomic_xchg_bootstrap (jint, volatile jint*); 28.11 static intptr_t atomic_xchg_ptr_bootstrap (intptr_t, volatile intptr_t*); 28.12 28.13 @@ -53,8 +50,6 @@ 28.14 #ifdef AMD64 28.15 static jint atomic_add_bootstrap (jint, volatile jint*); 28.16 static intptr_t atomic_add_ptr_bootstrap (intptr_t, volatile intptr_t*); 28.17 - 28.18 - static void fence_bootstrap (); 28.19 #endif // AMD64 28.20 28.21 static void setup_fpu();
29.1 --- a/src/share/vm/adlc/formssel.cpp Wed Apr 01 22:31:26 2009 -0700 29.2 +++ b/src/share/vm/adlc/formssel.cpp Thu Apr 02 17:01:00 2009 -0700 29.3 @@ -574,9 +574,13 @@ 29.4 // TEMPORARY 29.5 // if( is_simple_chain_rule(globals) ) return false; 29.6 29.7 - // String-compare uses many memorys edges, but writes none 29.8 + // String.(compareTo/equals/indexOf) and Arrays.equals use many memorys edges, 29.9 + // but writes none 29.10 if( _matrule && _matrule->_rChild && 29.11 - strcmp(_matrule->_rChild->_opType,"StrComp")==0 ) 29.12 + ( strcmp(_matrule->_rChild->_opType,"StrComp" )==0 || 29.13 + strcmp(_matrule->_rChild->_opType,"StrEquals" )==0 || 29.14 + strcmp(_matrule->_rChild->_opType,"StrIndexOf" )==0 || 29.15 + strcmp(_matrule->_rChild->_opType,"AryEq" )==0 )) 29.16 return true; 29.17 29.18 // Check if instruction has a USE of a memory operand class, but no defs 29.19 @@ -815,8 +819,10 @@ 29.20 return AdlcVMDeps::Parms; // Skip the machine-state edges 29.21 29.22 if( _matrule->_rChild && 29.23 - strcmp(_matrule->_rChild->_opType,"StrComp")==0 ) { 29.24 - // String compare takes 1 control and 4 memory edges. 29.25 + ( strcmp(_matrule->_rChild->_opType,"StrComp" )==0 || 29.26 + strcmp(_matrule->_rChild->_opType,"StrEquals" )==0 || 29.27 + strcmp(_matrule->_rChild->_opType,"StrIndexOf")==0 )) { 29.28 + // String.(compareTo/equals/indexOf) take 1 control and 4 memory edges. 29.29 return 5; 29.30 } 29.31
30.1 --- a/src/share/vm/asm/assembler.hpp Wed Apr 01 22:31:26 2009 -0700 30.2 +++ b/src/share/vm/asm/assembler.hpp Thu Apr 02 17:01:00 2009 -0700 30.3 @@ -1,5 +1,5 @@ 30.4 /* 30.5 - * Copyright 1997-2006 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 @@ -143,15 +143,15 @@ 30.11 // A union type for code which has to assemble both constant and 30.12 // non-constant operands, when the distinction cannot be made 30.13 // statically. 30.14 -class RegisterConstant VALUE_OBJ_CLASS_SPEC { 30.15 +class RegisterOrConstant VALUE_OBJ_CLASS_SPEC { 30.16 private: 30.17 Register _r; 30.18 intptr_t _c; 30.19 30.20 public: 30.21 - RegisterConstant(): _r(noreg), _c(0) {} 30.22 - RegisterConstant(Register r): _r(r), _c(0) {} 30.23 - RegisterConstant(intptr_t c): _r(noreg), _c(c) {} 30.24 + RegisterOrConstant(): _r(noreg), _c(0) {} 30.25 + RegisterOrConstant(Register r): _r(r), _c(0) {} 30.26 + RegisterOrConstant(intptr_t c): _r(noreg), _c(c) {} 30.27 30.28 Register as_register() const { assert(is_register(),""); return _r; } 30.29 intptr_t as_constant() const { assert(is_constant(),""); return _c; } 30.30 @@ -310,13 +310,13 @@ 30.31 // offsets in code which must be generated before the object class is loaded. 30.32 // Field offsets are never zero, since an object's header (mark word) 30.33 // is located at offset zero. 30.34 - RegisterConstant delayed_value(int(*value_fn)(), Register tmp, int offset = 0) { 30.35 - return delayed_value(delayed_value_addr(value_fn), tmp, offset); 30.36 + RegisterOrConstant delayed_value(int(*value_fn)(), Register tmp, int offset = 0) { 30.37 + return delayed_value_impl(delayed_value_addr(value_fn), tmp, offset); 30.38 } 30.39 - RegisterConstant delayed_value(address(*value_fn)(), Register tmp, int offset = 0) { 30.40 - return delayed_value(delayed_value_addr(value_fn), tmp, offset); 30.41 + RegisterOrConstant delayed_value(address(*value_fn)(), Register tmp, int offset = 0) { 30.42 + return delayed_value_impl(delayed_value_addr(value_fn), tmp, offset); 30.43 } 30.44 - virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr, Register tmp, int offset) = 0; 30.45 + virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, Register tmp, int offset) = 0; 30.46 // Last overloading is platform-dependent; look in assembler_<arch>.cpp. 30.47 static intptr_t* delayed_value_addr(int(*constant_fn)()); 30.48 static intptr_t* delayed_value_addr(address(*constant_fn)());
31.1 --- a/src/share/vm/ci/ciTypeFlow.cpp Wed Apr 01 22:31:26 2009 -0700 31.2 +++ b/src/share/vm/ci/ciTypeFlow.cpp Thu Apr 02 17:01:00 2009 -0700 31.3 @@ -2237,7 +2237,6 @@ 31.4 for (SuccIter iter(tail); !iter.done(); iter.next()) { 31.5 if (iter.succ() == head) { 31.6 iter.set_succ(clone); 31.7 - break; 31.8 } 31.9 } 31.10 flow_block(tail, temp_vector, temp_set);
32.1 --- a/src/share/vm/classfile/javaClasses.cpp Wed Apr 01 22:31:26 2009 -0700 32.2 +++ b/src/share/vm/classfile/javaClasses.cpp Thu Apr 02 17:01:00 2009 -0700 32.3 @@ -239,22 +239,20 @@ 32.4 typeArrayOop value = java_lang_String::value(obj); 32.5 int offset = java_lang_String::offset(obj); 32.6 int length = java_lang_String::length(obj); 32.7 - 32.8 - ResourceMark rm(THREAD); 32.9 - symbolHandle result; 32.10 - 32.11 - if (length > 0) { 32.12 - int utf8_length = UNICODE::utf8_length(value->char_at_addr(offset), length); 32.13 - char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1); 32.14 - UNICODE::convert_to_utf8(value->char_at_addr(offset), length, chars); 32.15 - // Allocate the symbol 32.16 - result = oopFactory::new_symbol_handle(chars, utf8_length, CHECK_(symbolHandle())); 32.17 - } else { 32.18 - result = oopFactory::new_symbol_handle("", 0, CHECK_(symbolHandle())); 32.19 - } 32.20 - return result; 32.21 + jchar* base = value->char_at_addr(offset); 32.22 + symbolOop sym = SymbolTable::lookup_unicode(base, length, THREAD); 32.23 + return symbolHandle(THREAD, sym); 32.24 } 32.25 32.26 +symbolOop java_lang_String::as_symbol_or_null(oop java_string) { 32.27 + typeArrayOop value = java_lang_String::value(java_string); 32.28 + int offset = java_lang_String::offset(java_string); 32.29 + int length = java_lang_String::length(java_string); 32.30 + jchar* base = value->char_at_addr(offset); 32.31 + return SymbolTable::probe_unicode(base, length); 32.32 +} 32.33 + 32.34 + 32.35 int java_lang_String::utf8_length(oop java_string) { 32.36 typeArrayOop value = java_lang_String::value(java_string); 32.37 int offset = java_lang_String::offset(java_string); 32.38 @@ -385,6 +383,48 @@ 32.39 } 32.40 32.41 32.42 +void java_lang_Class::print_signature(oop java_class, outputStream* st) { 32.43 + assert(java_lang_Class::is_instance(java_class), "must be a Class object"); 32.44 + symbolOop name = NULL; 32.45 + bool is_instance = false; 32.46 + if (is_primitive(java_class)) { 32.47 + name = vmSymbols::type_signature(primitive_type(java_class)); 32.48 + } else { 32.49 + klassOop k = as_klassOop(java_class); 32.50 + is_instance = Klass::cast(k)->oop_is_instance(); 32.51 + name = Klass::cast(k)->name(); 32.52 + } 32.53 + if (name == NULL) { 32.54 + st->print("<null>"); 32.55 + return; 32.56 + } 32.57 + if (is_instance) st->print("L"); 32.58 + st->write((char*) name->base(), (int) name->utf8_length()); 32.59 + if (is_instance) st->print(";"); 32.60 +} 32.61 + 32.62 +symbolOop java_lang_Class::as_signature(oop java_class, bool intern_if_not_found, TRAPS) { 32.63 + assert(java_lang_Class::is_instance(java_class), "must be a Class object"); 32.64 + symbolOop name = NULL; 32.65 + if (is_primitive(java_class)) { 32.66 + return vmSymbols::type_signature(primitive_type(java_class)); 32.67 + } else { 32.68 + klassOop k = as_klassOop(java_class); 32.69 + if (!Klass::cast(k)->oop_is_instance()) { 32.70 + return Klass::cast(k)->name(); 32.71 + } else { 32.72 + ResourceMark rm; 32.73 + const char* sigstr = Klass::cast(k)->signature_name(); 32.74 + int siglen = (int) strlen(sigstr); 32.75 + if (!intern_if_not_found) 32.76 + return SymbolTable::probe(sigstr, siglen); 32.77 + else 32.78 + return oopFactory::new_symbol(sigstr, siglen, THREAD); 32.79 + } 32.80 + } 32.81 +} 32.82 + 32.83 + 32.84 klassOop java_lang_Class::array_klass(oop java_class) { 32.85 klassOop k = klassOop(java_class->obj_field(array_klass_offset)); 32.86 assert(k == NULL || k->is_klass() && Klass::cast(k)->oop_is_javaArray(), "should be array klass"); 32.87 @@ -412,6 +452,8 @@ 32.88 32.89 32.90 bool java_lang_Class::is_primitive(oop java_class) { 32.91 + // should assert: 32.92 + //assert(java_lang_Class::is_instance(java_class), "must be a Class object"); 32.93 klassOop k = klassOop(java_class->obj_field(klass_offset)); 32.94 return k == NULL; 32.95 } 32.96 @@ -431,6 +473,19 @@ 32.97 return type; 32.98 } 32.99 32.100 +BasicType java_lang_Class::as_BasicType(oop java_class, klassOop* reference_klass) { 32.101 + assert(java_lang_Class::is_instance(java_class), "must be a Class object"); 32.102 + if (is_primitive(java_class)) { 32.103 + if (reference_klass != NULL) 32.104 + (*reference_klass) = NULL; 32.105 + return primitive_type(java_class); 32.106 + } else { 32.107 + if (reference_klass != NULL) 32.108 + (*reference_klass) = as_klassOop(java_class); 32.109 + return T_OBJECT; 32.110 + } 32.111 +} 32.112 + 32.113 32.114 oop java_lang_Class::primitive_mirror(BasicType t) { 32.115 oop mirror = Universe::java_mirror(t); 32.116 @@ -1988,6 +2043,21 @@ 32.117 } 32.118 32.119 32.120 +void java_lang_boxing_object::print(BasicType type, jvalue* value, outputStream* st) { 32.121 + switch (type) { 32.122 + case T_BOOLEAN: st->print("%s", value->z ? "true" : "false"); break; 32.123 + case T_CHAR: st->print("%d", value->c); break; 32.124 + case T_BYTE: st->print("%d", value->b); break; 32.125 + case T_SHORT: st->print("%d", value->s); break; 32.126 + case T_INT: st->print("%d", value->i); break; 32.127 + case T_LONG: st->print(INT64_FORMAT, value->j); break; 32.128 + case T_FLOAT: st->print("%f", value->f); break; 32.129 + case T_DOUBLE: st->print("%lf", value->d); break; 32.130 + default: st->print("type %d?", type); break; 32.131 + } 32.132 +} 32.133 + 32.134 + 32.135 // Support for java_lang_ref_Reference 32.136 oop java_lang_ref_Reference::pending_list_lock() { 32.137 instanceKlass* ik = instanceKlass::cast(SystemDictionary::reference_klass());
33.1 --- a/src/share/vm/classfile/javaClasses.hpp Wed Apr 01 22:31:26 2009 -0700 33.2 +++ b/src/share/vm/classfile/javaClasses.hpp Thu Apr 02 17:01:00 2009 -0700 33.3 @@ -107,6 +107,7 @@ 33.4 33.5 // Conversion 33.6 static symbolHandle as_symbol(Handle java_string, TRAPS); 33.7 + static symbolOop as_symbol_or_null(oop java_string); 33.8 33.9 // Testers 33.10 static bool is_instance(oop obj) { 33.11 @@ -149,6 +150,9 @@ 33.12 static oop create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS); 33.13 // Conversion 33.14 static klassOop as_klassOop(oop java_class); 33.15 + static BasicType as_BasicType(oop java_class, klassOop* reference_klass = NULL); 33.16 + static symbolOop as_signature(oop java_class, bool intern_if_not_found, TRAPS); 33.17 + static void print_signature(oop java_class, outputStream *st); 33.18 // Testing 33.19 static bool is_instance(oop obj) { 33.20 return obj != NULL && obj->klass() == SystemDictionary::class_klass(); 33.21 @@ -668,6 +672,8 @@ 33.22 static BasicType basic_type(oop box); 33.23 static bool is_instance(oop box) { return basic_type(box) != T_ILLEGAL; } 33.24 static bool is_instance(oop box, BasicType type) { return basic_type(box) == type; } 33.25 + static void print(oop box, outputStream* st) { jvalue value; print(get_value(box, &value), &value, st); } 33.26 + static void print(BasicType type, jvalue* value, outputStream* st); 33.27 33.28 static int value_offset_in_bytes(BasicType type) { 33.29 return ( type == T_LONG || type == T_DOUBLE ) ? long_value_offset :
34.1 --- a/src/share/vm/classfile/loaderConstraints.hpp Wed Apr 01 22:31:26 2009 -0700 34.2 +++ b/src/share/vm/classfile/loaderConstraints.hpp Thu Apr 02 17:01:00 2009 -0700 34.3 @@ -1,5 +1,5 @@ 34.4 /* 34.5 - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. 34.6 + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. 34.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 34.8 * 34.9 * This code is free software; you can redistribute it and/or modify it 34.10 @@ -60,8 +60,10 @@ 34.11 bool add_entry(symbolHandle name, klassOop klass1, Handle loader1, 34.12 klassOop klass2, Handle loader2); 34.13 34.14 - void check_signature_loaders(symbolHandle signature, Handle loader1, 34.15 - Handle loader2, bool is_method, TRAPS); 34.16 + // Note: The main entry point for this module is via SystemDictionary. 34.17 + // SystemDictionary::check_signature_loaders(symbolHandle signature, 34.18 + // Handle loader1, Handle loader2, 34.19 + // bool is_method, TRAPS) 34.20 34.21 klassOop find_constrained_klass(symbolHandle name, Handle loader); 34.22 klassOop find_constrained_elem_klass(symbolHandle name, symbolHandle elem_name,
35.1 --- a/src/share/vm/classfile/symbolTable.cpp Wed Apr 01 22:31:26 2009 -0700 35.2 +++ b/src/share/vm/classfile/symbolTable.cpp Thu Apr 02 17:01:00 2009 -0700 35.3 @@ -1,5 +1,5 @@ 35.4 /* 35.5 - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. 35.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 35.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 35.8 * 35.9 * This code is free software; you can redistribute it and/or modify it 35.10 @@ -109,6 +109,40 @@ 35.11 return the_table()->lookup(index, name, len, hash); 35.12 } 35.13 35.14 +// Suggestion: Push unicode-based lookup all the way into the hashing 35.15 +// and probing logic, so there is no need for convert_to_utf8 until 35.16 +// an actual new symbolOop is created. 35.17 +symbolOop SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) { 35.18 + int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); 35.19 + char stack_buf[128]; 35.20 + if (utf8_length < (int) sizeof(stack_buf)) { 35.21 + char* chars = stack_buf; 35.22 + UNICODE::convert_to_utf8(name, utf16_length, chars); 35.23 + return lookup(chars, utf8_length, THREAD); 35.24 + } else { 35.25 + ResourceMark rm(THREAD); 35.26 + char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);; 35.27 + UNICODE::convert_to_utf8(name, utf16_length, chars); 35.28 + return lookup(chars, utf8_length, THREAD); 35.29 + } 35.30 +} 35.31 + 35.32 +symbolOop SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length, 35.33 + unsigned int& hash) { 35.34 + int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); 35.35 + char stack_buf[128]; 35.36 + if (utf8_length < (int) sizeof(stack_buf)) { 35.37 + char* chars = stack_buf; 35.38 + UNICODE::convert_to_utf8(name, utf16_length, chars); 35.39 + return lookup_only(chars, utf8_length, hash); 35.40 + } else { 35.41 + ResourceMark rm; 35.42 + char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);; 35.43 + UNICODE::convert_to_utf8(name, utf16_length, chars); 35.44 + return lookup_only(chars, utf8_length, hash); 35.45 + } 35.46 +} 35.47 + 35.48 void SymbolTable::add(constantPoolHandle cp, int names_count, 35.49 const char** names, int* lengths, int* cp_indices, 35.50 unsigned int* hashValues, TRAPS) { 35.51 @@ -126,15 +160,6 @@ 35.52 } 35.53 } 35.54 35.55 -// Needed for preloading classes in signatures when compiling. 35.56 - 35.57 -symbolOop SymbolTable::probe(const char* name, int len) { 35.58 - unsigned int hashValue = hash_symbol(name, len); 35.59 - int index = the_table()->hash_to_index(hashValue); 35.60 - return the_table()->lookup(index, name, len, hashValue); 35.61 -} 35.62 - 35.63 - 35.64 symbolOop SymbolTable::basic_add(int index, u1 *name, int len, 35.65 unsigned int hashValue, TRAPS) { 35.66 assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(),
36.1 --- a/src/share/vm/classfile/symbolTable.hpp Wed Apr 01 22:31:26 2009 -0700 36.2 +++ b/src/share/vm/classfile/symbolTable.hpp Thu Apr 02 17:01:00 2009 -0700 36.3 @@ -1,5 +1,5 @@ 36.4 /* 36.5 - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. 36.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 36.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 36.8 * 36.9 * This code is free software; you can redistribute it and/or modify it 36.10 @@ -91,6 +91,10 @@ 36.11 // Only copy to C string to be added if lookup failed. 36.12 static symbolOop lookup(symbolHandle sym, int begin, int end, TRAPS); 36.13 36.14 + // jchar (utf16) version of lookups 36.15 + static symbolOop lookup_unicode(const jchar* name, int len, TRAPS); 36.16 + static symbolOop lookup_only_unicode(const jchar* name, int len, unsigned int& hash); 36.17 + 36.18 static void add(constantPoolHandle cp, int names_count, 36.19 const char** names, int* lengths, int* cp_indices, 36.20 unsigned int* hashValues, TRAPS); 36.21 @@ -112,7 +116,14 @@ 36.22 // Needed for preloading classes in signatures when compiling. 36.23 // Returns the symbol is already present in symbol table, otherwise 36.24 // NULL. NO ALLOCATION IS GUARANTEED! 36.25 - static symbolOop probe(const char* name, int len); 36.26 + static symbolOop probe(const char* name, int len) { 36.27 + unsigned int ignore_hash; 36.28 + return lookup_only(name, len, ignore_hash); 36.29 + } 36.30 + static symbolOop probe_unicode(const jchar* name, int len) { 36.31 + unsigned int ignore_hash; 36.32 + return lookup_only_unicode(name, len, ignore_hash); 36.33 + } 36.34 36.35 // Histogram 36.36 static void print_histogram() PRODUCT_RETURN;
37.1 --- a/src/share/vm/classfile/systemDictionary.cpp Wed Apr 01 22:31:26 2009 -0700 37.2 +++ b/src/share/vm/classfile/systemDictionary.cpp Thu Apr 02 17:01:00 2009 -0700 37.3 @@ -1964,6 +1964,13 @@ 37.4 return T_OBJECT; 37.5 } 37.6 37.7 +KlassHandle SystemDictionaryHandles::box_klass(BasicType t) { 37.8 + if (t >= T_BOOLEAN && t <= T_VOID) 37.9 + return KlassHandle(&SystemDictionary::_box_klasses[t], true); 37.10 + else 37.11 + return KlassHandle(); 37.12 +} 37.13 + 37.14 // Constraints on class loaders. The details of the algorithm can be 37.15 // found in the OOPSLA'98 paper "Dynamic Class Loading in the Java 37.16 // Virtual Machine" by Sheng Liang and Gilad Bracha. The basic idea is 37.17 @@ -2174,11 +2181,56 @@ 37.18 } 37.19 37.20 37.21 +// Signature constraints ensure that callers and callees agree about 37.22 +// the meaning of type names in their signatures. This routine is the 37.23 +// intake for constraints. It collects them from several places: 37.24 +// 37.25 +// * LinkResolver::resolve_method (if check_access is true) requires 37.26 +// that the resolving class (the caller) and the defining class of 37.27 +// the resolved method (the callee) agree on each type in the 37.28 +// method's signature. 37.29 +// 37.30 +// * LinkResolver::resolve_interface_method performs exactly the same 37.31 +// checks. 37.32 +// 37.33 +// * LinkResolver::resolve_field requires that the constant pool 37.34 +// attempting to link to a field agree with the field's defining 37.35 +// class about the type of the field signature. 37.36 +// 37.37 +// * klassVtable::initialize_vtable requires that, when a class 37.38 +// overrides a vtable entry allocated by a superclass, that the 37.39 +// overriding method (i.e., the callee) agree with the superclass 37.40 +// on each type in the method's signature. 37.41 +// 37.42 +// * klassItable::initialize_itable requires that, when a class fills 37.43 +// in its itables, for each non-abstract method installed in an 37.44 +// itable, the method (i.e., the callee) agree with the interface 37.45 +// on each type in the method's signature. 37.46 +// 37.47 +// All those methods have a boolean (check_access, checkconstraints) 37.48 +// which turns off the checks. This is used from specialized contexts 37.49 +// such as bootstrapping, dumping, and debugging. 37.50 +// 37.51 +// No direct constraint is placed between the class and its 37.52 +// supertypes. Constraints are only placed along linked relations 37.53 +// between callers and callees. When a method overrides or implements 37.54 +// an abstract method in a supertype (superclass or interface), the 37.55 +// constraints are placed as if the supertype were the caller to the 37.56 +// overriding method. (This works well, since callers to the 37.57 +// supertype have already established agreement between themselves and 37.58 +// the supertype.) As a result of all this, a class can disagree with 37.59 +// its supertype about the meaning of a type name, as long as that 37.60 +// class neither calls a relevant method of the supertype, nor is 37.61 +// called (perhaps via an override) from the supertype. 37.62 +// 37.63 +// 37.64 +// SystemDictionary::check_signature_loaders(sig, l1, l2) 37.65 +// 37.66 // Make sure all class components (including arrays) in the given 37.67 // signature will be resolved to the same class in both loaders. 37.68 // Returns the name of the type that failed a loader constraint check, or 37.69 // NULL if no constraint failed. The returned C string needs cleaning up 37.70 -// with a ResourceMark in the caller 37.71 +// with a ResourceMark in the caller. No exception except OOME is thrown. 37.72 char* SystemDictionary::check_signature_loaders(symbolHandle signature, 37.73 Handle loader1, Handle loader2, 37.74 bool is_method, TRAPS) {
38.1 --- a/src/share/vm/classfile/systemDictionary.hpp Wed Apr 01 22:31:26 2009 -0700 38.2 +++ b/src/share/vm/classfile/systemDictionary.hpp Thu Apr 02 17:01:00 2009 -0700 38.3 @@ -161,6 +161,7 @@ 38.4 class SystemDictionary : AllStatic { 38.5 friend class VMStructs; 38.6 friend class CompactingPermGenGen; 38.7 + friend class SystemDictionaryHandles; 38.8 NOT_PRODUCT(friend class instanceKlassKlass;) 38.9 38.10 public: 38.11 @@ -595,3 +596,18 @@ 38.12 static bool _has_loadClassInternal; 38.13 static bool _has_checkPackageAccess; 38.14 }; 38.15 + 38.16 +// Cf. vmSymbols vs. vmSymbolHandles 38.17 +class SystemDictionaryHandles : AllStatic { 38.18 +public: 38.19 + #define WK_KLASS_HANDLE_DECLARE(name, ignore_symbol, option) \ 38.20 + static KlassHandle name() { \ 38.21 + SystemDictionary::name(); \ 38.22 + klassOop* loc = &SystemDictionary::_well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)]; \ 38.23 + return KlassHandle(loc, true); \ 38.24 + } 38.25 + WK_KLASSES_DO(WK_KLASS_HANDLE_DECLARE); 38.26 + #undef WK_KLASS_HANDLE_DECLARE 38.27 + 38.28 + static KlassHandle box_klass(BasicType t); 38.29 +};
39.1 --- a/src/share/vm/classfile/vmSymbols.hpp Wed Apr 01 22:31:26 2009 -0700 39.2 +++ b/src/share/vm/classfile/vmSymbols.hpp Thu Apr 02 17:01:00 2009 -0700 39.3 @@ -49,6 +49,8 @@ 39.4 template(java_lang_Object, "java/lang/Object") \ 39.5 template(java_lang_Class, "java/lang/Class") \ 39.6 template(java_lang_String, "java/lang/String") \ 39.7 + template(java_lang_StringValue, "java/lang/StringValue") \ 39.8 + template(java_lang_StringCache, "java/lang/StringValue$StringCache") \ 39.9 template(java_lang_Thread, "java/lang/Thread") \ 39.10 template(java_lang_ThreadGroup, "java/lang/ThreadGroup") \ 39.11 template(java_lang_Cloneable, "java/lang/Cloneable") \ 39.12 @@ -285,6 +287,8 @@ 39.13 template(frontCacheEnabled_name, "frontCacheEnabled") \ 39.14 template(stringCacheEnabled_name, "stringCacheEnabled") \ 39.15 template(bitCount_name, "bitCount") \ 39.16 + template(profile_name, "profile") \ 39.17 + template(equals_name, "equals") \ 39.18 \ 39.19 /* non-intrinsic name/signature pairs: */ \ 39.20 template(register_method_name, "register") \ 39.21 @@ -576,7 +580,6 @@ 39.22 do_signature(copyOfRange_signature, "([Ljava/lang/Object;IILjava/lang/Class;)[Ljava/lang/Object;") \ 39.23 \ 39.24 do_intrinsic(_equalsC, java_util_Arrays, equals_name, equalsC_signature, F_S) \ 39.25 - do_name( equals_name, "equals") \ 39.26 do_signature(equalsC_signature, "([C[C)Z") \ 39.27 \ 39.28 do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \ 39.29 @@ -586,6 +589,7 @@ 39.30 do_name( compareTo_name, "compareTo") \ 39.31 do_intrinsic(_indexOf, java_lang_String, indexOf_name, string_int_signature, F_R) \ 39.32 do_name( indexOf_name, "indexOf") \ 39.33 + do_intrinsic(_equals, java_lang_String, equals_name, object_boolean_signature, F_R) \ 39.34 \ 39.35 do_class(java_nio_Buffer, "java/nio/Buffer") \ 39.36 do_intrinsic(_checkIndex, java_nio_Buffer, checkIndex_name, int_int_signature, F_R) \
40.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed Apr 01 22:31:26 2009 -0700 40.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu Apr 02 17:01:00 2009 -0700 40.3 @@ -3847,7 +3847,7 @@ 40.4 MutexLockerEx ml(ovflw_stk->par_lock(), 40.5 Mutex::_no_safepoint_check_flag); 40.6 // Grab up to 1/4 the size of the work queue 40.7 - size_t num = MIN2((size_t)work_q->max_elems()/4, 40.8 + size_t num = MIN2((size_t)(work_q->max_elems() - work_q->size())/4, 40.9 (size_t)ParGCDesiredObjsFromOverflowList); 40.10 num = MIN2(num, ovflw_stk->length()); 40.11 for (int i = (int) num; i > 0; i--) { 40.12 @@ -5204,13 +5204,12 @@ 40.13 NOT_PRODUCT(int num_steals = 0;) 40.14 oop obj_to_scan; 40.15 CMSBitMap* bm = &(_collector->_markBitMap); 40.16 - size_t num_from_overflow_list = 40.17 - MIN2((size_t)work_q->max_elems()/4, 40.18 - (size_t)ParGCDesiredObjsFromOverflowList); 40.19 40.20 while (true) { 40.21 // Completely finish any left over work from (an) earlier round(s) 40.22 cl->trim_queue(0); 40.23 + size_t num_from_overflow_list = MIN2((size_t)(work_q->max_elems() - work_q->size())/4, 40.24 + (size_t)ParGCDesiredObjsFromOverflowList); 40.25 // Now check if there's any work in the overflow list 40.26 if (_collector->par_take_from_overflow_list(num_from_overflow_list, 40.27 work_q)) { 40.28 @@ -5622,13 +5621,12 @@ 40.29 OopTaskQueue* work_q = work_queue(i); 40.30 NOT_PRODUCT(int num_steals = 0;) 40.31 oop obj_to_scan; 40.32 - size_t num_from_overflow_list = 40.33 - MIN2((size_t)work_q->max_elems()/4, 40.34 - (size_t)ParGCDesiredObjsFromOverflowList); 40.35 40.36 while (true) { 40.37 // Completely finish any left over work from (an) earlier round(s) 40.38 drain->trim_queue(0); 40.39 + size_t num_from_overflow_list = MIN2((size_t)(work_q->max_elems() - work_q->size())/4, 40.40 + (size_t)ParGCDesiredObjsFromOverflowList); 40.41 // Now check if there's any work in the overflow list 40.42 if (_collector->par_take_from_overflow_list(num_from_overflow_list, 40.43 work_q)) { 40.44 @@ -9021,7 +9019,7 @@ 40.45 // Transfer some number of overflown objects to usual marking 40.46 // stack. Return true if some objects were transferred. 40.47 bool MarkRefsIntoAndScanClosure::take_from_overflow_list() { 40.48 - size_t num = MIN2((size_t)_mark_stack->capacity()/4, 40.49 + size_t num = MIN2((size_t)(_mark_stack->capacity() - _mark_stack->length())/4, 40.50 (size_t)ParGCDesiredObjsFromOverflowList); 40.51 40.52 bool res = _collector->take_from_overflow_list(num, _mark_stack);
41.1 --- a/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp Wed Apr 01 22:31:26 2009 -0700 41.2 +++ b/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp Thu Apr 02 17:01:00 2009 -0700 41.3 @@ -277,8 +277,6 @@ 41.4 gclog_or_tty->print("H: "); 41.5 if (hr->in_collection_set()) 41.6 gclog_or_tty->print("CS: "); 41.7 - if (hr->popular()) 41.8 - gclog_or_tty->print("pop: "); 41.9 gclog_or_tty->print_cr("Region " PTR_FORMAT " (%s%s) " 41.10 "[" PTR_FORMAT ", " PTR_FORMAT"] " 41.11 "Used: " SIZE_FORMAT "K, garbage: " SIZE_FORMAT "K.",
42.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Apr 01 22:31:26 2009 -0700 42.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Apr 02 17:01:00 2009 -0700 42.3 @@ -42,21 +42,6 @@ 42.4 42.5 // Local to this file. 42.6 42.7 -// Finds the first HeapRegion. 42.8 -// No longer used, but might be handy someday. 42.9 - 42.10 -class FindFirstRegionClosure: public HeapRegionClosure { 42.11 - HeapRegion* _a_region; 42.12 -public: 42.13 - FindFirstRegionClosure() : _a_region(NULL) {} 42.14 - bool doHeapRegion(HeapRegion* r) { 42.15 - _a_region = r; 42.16 - return true; 42.17 - } 42.18 - HeapRegion* result() { return _a_region; } 42.19 -}; 42.20 - 42.21 - 42.22 class RefineCardTableEntryClosure: public CardTableEntryClosure { 42.23 SuspendibleThreadSet* _sts; 42.24 G1RemSet* _g1rs; 42.25 @@ -1207,13 +1192,12 @@ 42.26 bool par) { 42.27 assert(!hr->continuesHumongous(), "should have filtered these out"); 42.28 size_t res = 0; 42.29 - if (!hr->popular() && hr->used() > 0 && hr->garbage_bytes() == hr->used()) { 42.30 - if (!hr->is_young()) { 42.31 - if (G1PolicyVerbose > 0) 42.32 - gclog_or_tty->print_cr("Freeing empty region "PTR_FORMAT "(" SIZE_FORMAT " bytes)" 42.33 - " during cleanup", hr, hr->used()); 42.34 - free_region_work(hr, pre_used, cleared_h, freed_regions, list, par); 42.35 - } 42.36 + if (hr->used() > 0 && hr->garbage_bytes() == hr->used() && 42.37 + !hr->is_young()) { 42.38 + if (G1PolicyVerbose > 0) 42.39 + gclog_or_tty->print_cr("Freeing empty region "PTR_FORMAT "(" SIZE_FORMAT " bytes)" 42.40 + " during cleanup", hr, hr->used()); 42.41 + free_region_work(hr, pre_used, cleared_h, freed_regions, list, par); 42.42 } 42.43 } 42.44 42.45 @@ -1342,10 +1326,6 @@ 42.46 _refine_cte_cl(NULL), 42.47 _free_region_list(NULL), _free_region_list_size(0), 42.48 _free_regions(0), 42.49 - _popular_object_boundary(NULL), 42.50 - _cur_pop_hr_index(0), 42.51 - _popular_regions_to_be_evacuated(NULL), 42.52 - _pop_obj_rc_at_copy(), 42.53 _full_collection(false), 42.54 _unclean_region_list(), 42.55 _unclean_regions_coming(false), 42.56 @@ -1520,26 +1500,11 @@ 42.57 _czft = new ConcurrentZFThread(); 42.58 } 42.59 42.60 - 42.61 - 42.62 - // Allocate the popular regions; take them off free lists. 42.63 - size_t pop_byte_size = G1NumPopularRegions * HeapRegion::GrainBytes; 42.64 - expand(pop_byte_size); 42.65 - _popular_object_boundary = 42.66 - _g1_reserved.start() + (G1NumPopularRegions * HeapRegion::GrainWords); 42.67 - for (int i = 0; i < G1NumPopularRegions; i++) { 42.68 - HeapRegion* hr = newAllocRegion(HeapRegion::GrainWords); 42.69 - // assert(hr != NULL && hr->bottom() < _popular_object_boundary, 42.70 - // "Should be enough, and all should be below boundary."); 42.71 - hr->set_popular(true); 42.72 - } 42.73 - assert(_cur_pop_hr_index == 0, "Start allocating at the first region."); 42.74 - 42.75 // Initialize the from_card cache structure of HeapRegionRemSet. 42.76 HeapRegionRemSet::init_heap(max_regions()); 42.77 42.78 - // Now expand into the rest of the initial heap size. 42.79 - expand(init_byte_size - pop_byte_size); 42.80 + // Now expand into the initial heap size. 42.81 + expand(init_byte_size); 42.82 42.83 // Perform any initialization actions delegated to the policy. 42.84 g1_policy()->init(); 42.85 @@ -1654,8 +1619,7 @@ 42.86 class SumUsedRegionsClosure: public HeapRegionClosure { 42.87 size_t _num; 42.88 public: 42.89 - // _num is set to 1 to account for the popular region 42.90 - SumUsedRegionsClosure() : _num(G1NumPopularRegions) {} 42.91 + SumUsedRegionsClosure() : _num(0) {} 42.92 bool doHeapRegion(HeapRegion* r) { 42.93 if (r->continuesHumongous() || r->used() > 0 || r->is_gc_alloc_region()) { 42.94 _num += 1; 42.95 @@ -1758,14 +1722,20 @@ 42.96 } 42.97 }; 42.98 42.99 -void G1CollectedHeap::oop_iterate(OopClosure* cl) { 42.100 +void G1CollectedHeap::oop_iterate(OopClosure* cl, bool do_perm) { 42.101 IterateOopClosureRegionClosure blk(_g1_committed, cl); 42.102 _hrs->iterate(&blk); 42.103 + if (do_perm) { 42.104 + perm_gen()->oop_iterate(cl); 42.105 + } 42.106 } 42.107 42.108 -void G1CollectedHeap::oop_iterate(MemRegion mr, OopClosure* cl) { 42.109 +void G1CollectedHeap::oop_iterate(MemRegion mr, OopClosure* cl, bool do_perm) { 42.110 IterateOopClosureRegionClosure blk(mr, cl); 42.111 _hrs->iterate(&blk); 42.112 + if (do_perm) { 42.113 + perm_gen()->oop_iterate(cl); 42.114 + } 42.115 } 42.116 42.117 // Iterates an ObjectClosure over all objects within a HeapRegion. 42.118 @@ -1782,9 +1752,12 @@ 42.119 } 42.120 }; 42.121 42.122 -void G1CollectedHeap::object_iterate(ObjectClosure* cl) { 42.123 +void G1CollectedHeap::object_iterate(ObjectClosure* cl, bool do_perm) { 42.124 IterateObjectClosureRegionClosure blk(cl); 42.125 _hrs->iterate(&blk); 42.126 + if (do_perm) { 42.127 + perm_gen()->object_iterate(cl); 42.128 + } 42.129 } 42.130 42.131 void G1CollectedHeap::object_iterate_since_last_GC(ObjectClosure* cl) { 42.132 @@ -2318,9 +2291,6 @@ 42.133 if (SummarizeG1ZFStats) { 42.134 ConcurrentZFThread::print_summary_info(); 42.135 } 42.136 - if (G1SummarizePopularity) { 42.137 - print_popularity_summary_info(); 42.138 - } 42.139 g1_policy()->print_yg_surv_rate_info(); 42.140 42.141 GCOverheadReporter::printGCOverhead(); 42.142 @@ -2414,7 +2384,7 @@ 42.143 VerifyMarkedObjsClosure verifycl(this); 42.144 // MutexLockerEx x(getMarkBitMapLock(), 42.145 // Mutex::_no_safepoint_check_flag); 42.146 - object_iterate(&verifycl); 42.147 + object_iterate(&verifycl, false); 42.148 } 42.149 42.150 void G1CollectedHeap::do_sync_mark() { 42.151 @@ -2495,30 +2465,19 @@ 42.152 // </NEW PREDICTION> 42.153 42.154 void 42.155 -G1CollectedHeap::do_collection_pause_at_safepoint(HeapRegion* popular_region) { 42.156 +G1CollectedHeap::do_collection_pause_at_safepoint() { 42.157 char verbose_str[128]; 42.158 sprintf(verbose_str, "GC pause "); 42.159 - if (popular_region != NULL) 42.160 - strcat(verbose_str, "(popular)"); 42.161 - else if (g1_policy()->in_young_gc_mode()) { 42.162 + if (g1_policy()->in_young_gc_mode()) { 42.163 if (g1_policy()->full_young_gcs()) 42.164 strcat(verbose_str, "(young)"); 42.165 else 42.166 strcat(verbose_str, "(partial)"); 42.167 } 42.168 - bool reset_should_initiate_conc_mark = false; 42.169 - if (popular_region != NULL && g1_policy()->should_initiate_conc_mark()) { 42.170 - // we currently do not allow an initial mark phase to be piggy-backed 42.171 - // on a popular pause 42.172 - reset_should_initiate_conc_mark = true; 42.173 - g1_policy()->unset_should_initiate_conc_mark(); 42.174 - } 42.175 if (g1_policy()->should_initiate_conc_mark()) 42.176 strcat(verbose_str, " (initial-mark)"); 42.177 42.178 - GCCauseSetter x(this, (popular_region == NULL ? 42.179 - GCCause::_g1_inc_collection_pause : 42.180 - GCCause::_g1_pop_region_collection_pause)); 42.181 + GCCauseSetter x(this, GCCause::_g1_inc_collection_pause); 42.182 42.183 // if PrintGCDetails is on, we'll print long statistics information 42.184 // in the collector policy code, so let's not print this as the output 42.185 @@ -2609,7 +2568,7 @@ 42.186 save_marks(); 42.187 42.188 // We must do this before any possible evacuation that should propagate 42.189 - // marks, including evacuation of popular objects in a popular pause. 42.190 + // marks. 42.191 if (mark_in_progress()) { 42.192 double start_time_sec = os::elapsedTime(); 42.193 42.194 @@ -2626,29 +2585,15 @@ 42.195 42.196 assert(regions_accounted_for(), "Region leakage."); 42.197 42.198 - bool abandoned = false; 42.199 - 42.200 if (mark_in_progress()) 42.201 concurrent_mark()->newCSet(); 42.202 42.203 // Now choose the CS. 42.204 - if (popular_region == NULL) { 42.205 - g1_policy()->choose_collection_set(); 42.206 - } else { 42.207 - // We may be evacuating a single region (for popularity). 42.208 - g1_policy()->record_popular_pause_preamble_start(); 42.209 - popularity_pause_preamble(popular_region); 42.210 - g1_policy()->record_popular_pause_preamble_end(); 42.211 - abandoned = (g1_policy()->collection_set() == NULL); 42.212 - // Now we allow more regions to be added (we have to collect 42.213 - // all popular regions). 42.214 - if (!abandoned) { 42.215 - g1_policy()->choose_collection_set(popular_region); 42.216 - } 42.217 - } 42.218 + g1_policy()->choose_collection_set(); 42.219 + 42.220 // We may abandon a pause if we find no region that will fit in the MMU 42.221 // pause. 42.222 - abandoned = (g1_policy()->collection_set() == NULL); 42.223 + bool abandoned = (g1_policy()->collection_set() == NULL); 42.224 42.225 // Nothing to do if we were unable to choose a collection set. 42.226 if (!abandoned) { 42.227 @@ -2673,12 +2618,6 @@ 42.228 _in_cset_fast_test = NULL; 42.229 _in_cset_fast_test_base = NULL; 42.230 42.231 - if (popular_region != NULL) { 42.232 - // We have to wait until now, because we don't want the region to 42.233 - // be rescheduled for pop-evac during RS update. 42.234 - popular_region->set_popular_pending(false); 42.235 - } 42.236 - 42.237 release_gc_alloc_regions(false /* totally */); 42.238 42.239 cleanup_surviving_young_words(); 42.240 @@ -2724,8 +2663,7 @@ 42.241 double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS; 42.242 g1_policy()->record_pause_time_ms(pause_time_ms); 42.243 GCOverheadReporter::recordSTWEnd(end_time_sec); 42.244 - g1_policy()->record_collection_pause_end(popular_region != NULL, 42.245 - abandoned); 42.246 + g1_policy()->record_collection_pause_end(abandoned); 42.247 42.248 assert(regions_accounted_for(), "Region leakage."); 42.249 42.250 @@ -2759,9 +2697,6 @@ 42.251 42.252 assert(verify_region_lists(), "Bad region lists."); 42.253 42.254 - if (reset_should_initiate_conc_mark) 42.255 - g1_policy()->set_should_initiate_conc_mark(); 42.256 - 42.257 if (ExitAfterGCNum > 0 && total_collections() == ExitAfterGCNum) { 42.258 gclog_or_tty->print_cr("Stopping after GC #%d", ExitAfterGCNum); 42.259 print_tracing_info(); 42.260 @@ -4707,7 +4642,6 @@ 42.261 size_t& freed_regions, 42.262 UncleanRegionList* list, 42.263 bool par) { 42.264 - assert(!hr->popular(), "should not free popular regions"); 42.265 pre_used += hr->used(); 42.266 if (hr->isHumongous()) { 42.267 assert(hr->startsHumongous(), 42.268 @@ -4791,12 +4725,6 @@ 42.269 42.270 42.271 void G1CollectedHeap::do_collection_pause_if_appropriate(size_t word_size) { 42.272 - // First do any popular regions. 42.273 - HeapRegion* hr; 42.274 - while ((hr = popular_region_to_evac()) != NULL) { 42.275 - evac_popular_region(hr); 42.276 - } 42.277 - // Now do heuristic pauses. 42.278 if (g1_policy()->should_do_collection_pause(word_size)) { 42.279 do_collection_pause(); 42.280 } 42.281 @@ -5192,7 +5120,7 @@ 42.282 public: 42.283 RegionCounter() : _n(0) {} 42.284 bool doHeapRegion(HeapRegion* r) { 42.285 - if (r->is_empty() && !r->popular()) { 42.286 + if (r->is_empty()) { 42.287 assert(!r->isHumongous(), "H regions should not be empty."); 42.288 _n++; 42.289 } 42.290 @@ -5336,14 +5264,8 @@ 42.291 r->set_zero_fill_allocated(); 42.292 } else { 42.293 assert(r->is_empty(), "tautology"); 42.294 - if (r->popular()) { 42.295 - if (r->zero_fill_state() != HeapRegion::Allocated) { 42.296 - r->ensure_zero_filled_locked(); 42.297 - r->set_zero_fill_allocated(); 42.298 - } 42.299 - } else { 42.300 - _n++; 42.301 - switch (r->zero_fill_state()) { 42.302 + _n++; 42.303 + switch (r->zero_fill_state()) { 42.304 case HeapRegion::NotZeroFilled: 42.305 case HeapRegion::ZeroFilling: 42.306 _g1->put_region_on_unclean_list_locked(r); 42.307 @@ -5354,7 +5276,6 @@ 42.308 case HeapRegion::ZeroFilled: 42.309 _g1->put_free_region_on_list_locked(r); 42.310 break; 42.311 - } 42.312 } 42.313 } 42.314 return false; 42.315 @@ -5402,376 +5323,6 @@ 42.316 heap_region_iterate(&rs); 42.317 } 42.318 42.319 -class CountObjClosure: public ObjectClosure { 42.320 - size_t _n; 42.321 -public: 42.322 - CountObjClosure() : _n(0) {} 42.323 - void do_object(oop obj) { _n++; } 42.324 - size_t n() { return _n; } 42.325 -}; 42.326 - 42.327 -size_t G1CollectedHeap::pop_object_used_objs() { 42.328 - size_t sum_objs = 0; 42.329 - for (int i = 0; i < G1NumPopularRegions; i++) { 42.330 - CountObjClosure cl; 42.331 - _hrs->at(i)->object_iterate(&cl); 42.332 - sum_objs += cl.n(); 42.333 - } 42.334 - return sum_objs; 42.335 -} 42.336 - 42.337 -size_t G1CollectedHeap::pop_object_used_bytes() { 42.338 - size_t sum_bytes = 0; 42.339 - for (int i = 0; i < G1NumPopularRegions; i++) { 42.340 - sum_bytes += _hrs->at(i)->used(); 42.341 - } 42.342 - return sum_bytes; 42.343 -} 42.344 - 42.345 - 42.346 -static int nq = 0; 42.347 - 42.348 -HeapWord* G1CollectedHeap::allocate_popular_object(size_t word_size) { 42.349 - while (_cur_pop_hr_index < G1NumPopularRegions) { 42.350 - HeapRegion* cur_pop_region = _hrs->at(_cur_pop_hr_index); 42.351 - HeapWord* res = cur_pop_region->allocate(word_size); 42.352 - if (res != NULL) { 42.353 - // We account for popular objs directly in the used summary: 42.354 - _summary_bytes_used += (word_size * HeapWordSize); 42.355 - return res; 42.356 - } 42.357 - // Otherwise, try the next region (first making sure that we remember 42.358 - // the last "top" value as the "next_top_at_mark_start", so that 42.359 - // objects made popular during markings aren't automatically considered 42.360 - // live). 42.361 - cur_pop_region->note_end_of_copying(); 42.362 - // Otherwise, try the next region. 42.363 - _cur_pop_hr_index++; 42.364 - } 42.365 - // XXX: For now !!! 42.366 - vm_exit_out_of_memory(word_size, 42.367 - "Not enough pop obj space (To Be Fixed)"); 42.368 - return NULL; 42.369 -} 42.370 - 42.371 -class HeapRegionList: public CHeapObj { 42.372 - public: 42.373 - HeapRegion* hr; 42.374 - HeapRegionList* next; 42.375 -}; 42.376 - 42.377 -void G1CollectedHeap::schedule_popular_region_evac(HeapRegion* r) { 42.378 - // This might happen during parallel GC, so protect by this lock. 42.379 - MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); 42.380 - // We don't schedule regions whose evacuations are already pending, or 42.381 - // are already being evacuated. 42.382 - if (!r->popular_pending() && !r->in_collection_set()) { 42.383 - r->set_popular_pending(true); 42.384 - if (G1TracePopularity) { 42.385 - gclog_or_tty->print_cr("Scheduling region "PTR_FORMAT" " 42.386 - "["PTR_FORMAT", "PTR_FORMAT") for pop-object evacuation.", 42.387 - r, r->bottom(), r->end()); 42.388 - } 42.389 - HeapRegionList* hrl = new HeapRegionList; 42.390 - hrl->hr = r; 42.391 - hrl->next = _popular_regions_to_be_evacuated; 42.392 - _popular_regions_to_be_evacuated = hrl; 42.393 - } 42.394 -} 42.395 - 42.396 -HeapRegion* G1CollectedHeap::popular_region_to_evac() { 42.397 - MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); 42.398 - HeapRegion* res = NULL; 42.399 - while (_popular_regions_to_be_evacuated != NULL && res == NULL) { 42.400 - HeapRegionList* hrl = _popular_regions_to_be_evacuated; 42.401 - _popular_regions_to_be_evacuated = hrl->next; 42.402 - res = hrl->hr; 42.403 - // The G1RSPopLimit may have increased, so recheck here... 42.404 - if (res->rem_set()->occupied() < (size_t) G1RSPopLimit) { 42.405 - // Hah: don't need to schedule. 42.406 - if (G1TracePopularity) { 42.407 - gclog_or_tty->print_cr("Unscheduling region "PTR_FORMAT" " 42.408 - "["PTR_FORMAT", "PTR_FORMAT") " 42.409 - "for pop-object evacuation (size %d < limit %d)", 42.410 - res, res->bottom(), res->end(), 42.411 - res->rem_set()->occupied(), G1RSPopLimit); 42.412 - } 42.413 - res->set_popular_pending(false); 42.414 - res = NULL; 42.415 - } 42.416 - // We do not reset res->popular() here; if we did so, it would allow 42.417 - // the region to be "rescheduled" for popularity evacuation. Instead, 42.418 - // this is done in the collection pause, with the world stopped. 42.419 - // So the invariant is that the regions in the list have the popularity 42.420 - // boolean set, but having the boolean set does not imply membership 42.421 - // on the list (though there can at most one such pop-pending region 42.422 - // not on the list at any time). 42.423 - delete hrl; 42.424 - } 42.425 - return res; 42.426 -} 42.427 - 42.428 -void G1CollectedHeap::evac_popular_region(HeapRegion* hr) { 42.429 - while (true) { 42.430 - // Don't want to do a GC pause while cleanup is being completed! 42.431 - wait_for_cleanup_complete(); 42.432 - 42.433 - // Read the GC count while holding the Heap_lock 42.434 - int gc_count_before = SharedHeap::heap()->total_collections(); 42.435 - g1_policy()->record_stop_world_start(); 42.436 - 42.437 - { 42.438 - MutexUnlocker mu(Heap_lock); // give up heap lock, execute gets it back 42.439 - VM_G1PopRegionCollectionPause op(gc_count_before, hr); 42.440 - VMThread::execute(&op); 42.441 - 42.442 - // If the prolog succeeded, we didn't do a GC for this. 42.443 - if (op.prologue_succeeded()) break; 42.444 - } 42.445 - // Otherwise we didn't. We should recheck the size, though, since 42.446 - // the limit may have increased... 42.447 - if (hr->rem_set()->occupied() < (size_t) G1RSPopLimit) { 42.448 - hr->set_popular_pending(false); 42.449 - break; 42.450 - } 42.451 - } 42.452 -} 42.453 - 42.454 -void G1CollectedHeap::atomic_inc_obj_rc(oop obj) { 42.455 - Atomic::inc(obj_rc_addr(obj)); 42.456 -} 42.457 - 42.458 -class CountRCClosure: public OopsInHeapRegionClosure { 42.459 - G1CollectedHeap* _g1h; 42.460 - bool _parallel; 42.461 -public: 42.462 - CountRCClosure(G1CollectedHeap* g1h) : 42.463 - _g1h(g1h), _parallel(ParallelGCThreads > 0) 42.464 - {} 42.465 - void do_oop(narrowOop* p) { 42.466 - guarantee(false, "NYI"); 42.467 - } 42.468 - void do_oop(oop* p) { 42.469 - oop obj = *p; 42.470 - assert(obj != NULL, "Precondition."); 42.471 - if (_parallel) { 42.472 - // We go sticky at the limit to avoid excess contention. 42.473 - // If we want to track the actual RC's further, we'll need to keep a 42.474 - // per-thread hash table or something for the popular objects. 42.475 - if (_g1h->obj_rc(obj) < G1ObjPopLimit) { 42.476 - _g1h->atomic_inc_obj_rc(obj); 42.477 - } 42.478 - } else { 42.479 - _g1h->inc_obj_rc(obj); 42.480 - } 42.481 - } 42.482 -}; 42.483 - 42.484 -class EvacPopObjClosure: public ObjectClosure { 42.485 - G1CollectedHeap* _g1h; 42.486 - size_t _pop_objs; 42.487 - size_t _max_rc; 42.488 -public: 42.489 - EvacPopObjClosure(G1CollectedHeap* g1h) : 42.490 - _g1h(g1h), _pop_objs(0), _max_rc(0) {} 42.491 - 42.492 - void do_object(oop obj) { 42.493 - size_t rc = _g1h->obj_rc(obj); 42.494 - _max_rc = MAX2(rc, _max_rc); 42.495 - if (rc >= (size_t) G1ObjPopLimit) { 42.496 - _g1h->_pop_obj_rc_at_copy.add((double)rc); 42.497 - size_t word_sz = obj->size(); 42.498 - HeapWord* new_pop_loc = _g1h->allocate_popular_object(word_sz); 42.499 - oop new_pop_obj = (oop)new_pop_loc; 42.500 - Copy::aligned_disjoint_words((HeapWord*)obj, new_pop_loc, word_sz); 42.501 - obj->forward_to(new_pop_obj); 42.502 - G1ScanAndBalanceClosure scan_and_balance(_g1h); 42.503 - new_pop_obj->oop_iterate_backwards(&scan_and_balance); 42.504 - // preserve "next" mark bit if marking is in progress. 42.505 - if (_g1h->mark_in_progress() && !_g1h->is_obj_ill(obj)) { 42.506 - _g1h->concurrent_mark()->markAndGrayObjectIfNecessary(new_pop_obj); 42.507 - } 42.508 - 42.509 - if (G1TracePopularity) { 42.510 - gclog_or_tty->print_cr("Found obj " PTR_FORMAT " of word size " SIZE_FORMAT 42.511 - " pop (%d), move to " PTR_FORMAT, 42.512 - (void*) obj, word_sz, 42.513 - _g1h->obj_rc(obj), (void*) new_pop_obj); 42.514 - } 42.515 - _pop_objs++; 42.516 - } 42.517 - } 42.518 - size_t pop_objs() { return _pop_objs; } 42.519 - size_t max_rc() { return _max_rc; } 42.520 -}; 42.521 - 42.522 -class G1ParCountRCTask : public AbstractGangTask { 42.523 - G1CollectedHeap* _g1h; 42.524 - BitMap _bm; 42.525 - 42.526 - size_t getNCards() { 42.527 - return (_g1h->capacity() + G1BlockOffsetSharedArray::N_bytes - 1) 42.528 - / G1BlockOffsetSharedArray::N_bytes; 42.529 - } 42.530 - CountRCClosure _count_rc_closure; 42.531 -public: 42.532 - G1ParCountRCTask(G1CollectedHeap* g1h) : 42.533 - AbstractGangTask("G1 Par RC Count task"), 42.534 - _g1h(g1h), _bm(getNCards()), _count_rc_closure(g1h) 42.535 - {} 42.536 - 42.537 - void work(int i) { 42.538 - ResourceMark rm; 42.539 - HandleMark hm; 42.540 - _g1h->g1_rem_set()->oops_into_collection_set_do(&_count_rc_closure, i); 42.541 - } 42.542 -}; 42.543 - 42.544 -void G1CollectedHeap::popularity_pause_preamble(HeapRegion* popular_region) { 42.545 - // We're evacuating a single region (for popularity). 42.546 - if (G1TracePopularity) { 42.547 - gclog_or_tty->print_cr("Doing pop region pause for ["PTR_FORMAT", "PTR_FORMAT")", 42.548 - popular_region->bottom(), popular_region->end()); 42.549 - } 42.550 - g1_policy()->set_single_region_collection_set(popular_region); 42.551 - size_t max_rc; 42.552 - if (!compute_reference_counts_and_evac_popular(popular_region, 42.553 - &max_rc)) { 42.554 - // We didn't evacuate any popular objects. 42.555 - // We increase the RS popularity limit, to prevent this from 42.556 - // happening in the future. 42.557 - if (G1RSPopLimit < (1 << 30)) { 42.558 - G1RSPopLimit *= 2; 42.559 - } 42.560 - // For now, interesting enough for a message: 42.561 -#if 1 42.562 - gclog_or_tty->print_cr("In pop region pause for ["PTR_FORMAT", "PTR_FORMAT"), " 42.563 - "failed to find a pop object (max = %d).", 42.564 - popular_region->bottom(), popular_region->end(), 42.565 - max_rc); 42.566 - gclog_or_tty->print_cr("Increased G1RSPopLimit to %d.", G1RSPopLimit); 42.567 -#endif // 0 42.568 - // Also, we reset the collection set to NULL, to make the rest of 42.569 - // the collection do nothing. 42.570 - assert(popular_region->next_in_collection_set() == NULL, 42.571 - "should be single-region."); 42.572 - popular_region->set_in_collection_set(false); 42.573 - popular_region->set_popular_pending(false); 42.574 - g1_policy()->clear_collection_set(); 42.575 - } 42.576 -} 42.577 - 42.578 -bool G1CollectedHeap:: 42.579 -compute_reference_counts_and_evac_popular(HeapRegion* popular_region, 42.580 - size_t* max_rc) { 42.581 - HeapWord* rc_region_bot; 42.582 - HeapWord* rc_region_end; 42.583 - 42.584 - // Set up the reference count region. 42.585 - HeapRegion* rc_region = newAllocRegion(HeapRegion::GrainWords); 42.586 - if (rc_region != NULL) { 42.587 - rc_region_bot = rc_region->bottom(); 42.588 - rc_region_end = rc_region->end(); 42.589 - } else { 42.590 - rc_region_bot = NEW_C_HEAP_ARRAY(HeapWord, HeapRegion::GrainWords); 42.591 - if (rc_region_bot == NULL) { 42.592 - vm_exit_out_of_memory(HeapRegion::GrainWords, 42.593 - "No space for RC region."); 42.594 - } 42.595 - rc_region_end = rc_region_bot + HeapRegion::GrainWords; 42.596 - } 42.597 - 42.598 - if (G1TracePopularity) 42.599 - gclog_or_tty->print_cr("RC region is ["PTR_FORMAT", "PTR_FORMAT")", 42.600 - rc_region_bot, rc_region_end); 42.601 - if (rc_region_bot > popular_region->bottom()) { 42.602 - _rc_region_above = true; 42.603 - _rc_region_diff = 42.604 - pointer_delta(rc_region_bot, popular_region->bottom(), 1); 42.605 - } else { 42.606 - assert(rc_region_bot < popular_region->bottom(), "Can't be equal."); 42.607 - _rc_region_above = false; 42.608 - _rc_region_diff = 42.609 - pointer_delta(popular_region->bottom(), rc_region_bot, 1); 42.610 - } 42.611 - g1_policy()->record_pop_compute_rc_start(); 42.612 - // Count external references. 42.613 - g1_rem_set()->prepare_for_oops_into_collection_set_do(); 42.614 - if (ParallelGCThreads > 0) { 42.615 - 42.616 - set_par_threads(workers()->total_workers()); 42.617 - G1ParCountRCTask par_count_rc_task(this); 42.618 - workers()->run_task(&par_count_rc_task); 42.619 - set_par_threads(0); 42.620 - 42.621 - } else { 42.622 - CountRCClosure count_rc_closure(this); 42.623 - g1_rem_set()->oops_into_collection_set_do(&count_rc_closure, 0); 42.624 - } 42.625 - g1_rem_set()->cleanup_after_oops_into_collection_set_do(); 42.626 - g1_policy()->record_pop_compute_rc_end(); 42.627 - 42.628 - // Now evacuate popular objects. 42.629 - g1_policy()->record_pop_evac_start(); 42.630 - EvacPopObjClosure evac_pop_obj_cl(this); 42.631 - popular_region->object_iterate(&evac_pop_obj_cl); 42.632 - *max_rc = evac_pop_obj_cl.max_rc(); 42.633 - 42.634 - // Make sure the last "top" value of the current popular region is copied 42.635 - // as the "next_top_at_mark_start", so that objects made popular during 42.636 - // markings aren't automatically considered live. 42.637 - HeapRegion* cur_pop_region = _hrs->at(_cur_pop_hr_index); 42.638 - cur_pop_region->note_end_of_copying(); 42.639 - 42.640 - if (rc_region != NULL) { 42.641 - free_region(rc_region); 42.642 - } else { 42.643 - FREE_C_HEAP_ARRAY(HeapWord, rc_region_bot); 42.644 - } 42.645 - g1_policy()->record_pop_evac_end(); 42.646 - 42.647 - return evac_pop_obj_cl.pop_objs() > 0; 42.648 -} 42.649 - 42.650 -class CountPopObjInfoClosure: public HeapRegionClosure { 42.651 - size_t _objs; 42.652 - size_t _bytes; 42.653 - 42.654 - class CountObjClosure: public ObjectClosure { 42.655 - int _n; 42.656 - public: 42.657 - CountObjClosure() : _n(0) {} 42.658 - void do_object(oop obj) { _n++; } 42.659 - size_t n() { return _n; } 42.660 - }; 42.661 - 42.662 -public: 42.663 - CountPopObjInfoClosure() : _objs(0), _bytes(0) {} 42.664 - bool doHeapRegion(HeapRegion* r) { 42.665 - _bytes += r->used(); 42.666 - CountObjClosure blk; 42.667 - r->object_iterate(&blk); 42.668 - _objs += blk.n(); 42.669 - return false; 42.670 - } 42.671 - size_t objs() { return _objs; } 42.672 - size_t bytes() { return _bytes; } 42.673 -}; 42.674 - 42.675 - 42.676 -void G1CollectedHeap::print_popularity_summary_info() const { 42.677 - CountPopObjInfoClosure blk; 42.678 - for (int i = 0; i <= _cur_pop_hr_index; i++) { 42.679 - blk.doHeapRegion(_hrs->at(i)); 42.680 - } 42.681 - gclog_or_tty->print_cr("\nPopular objects: %d objs, %d bytes.", 42.682 - blk.objs(), blk.bytes()); 42.683 - gclog_or_tty->print_cr(" RC at copy = [avg = %5.2f, max = %5.2f, sd = %5.2f].", 42.684 - _pop_obj_rc_at_copy.avg(), 42.685 - _pop_obj_rc_at_copy.maximum(), 42.686 - _pop_obj_rc_at_copy.sd()); 42.687 -} 42.688 - 42.689 void G1CollectedHeap::set_refine_cte_cl_concurrency(bool concurrent) { 42.690 _refine_cte_cl->set_concurrent(concurrent); 42.691 } 42.692 @@ -5845,7 +5396,6 @@ 42.693 } 42.694 42.695 bool G1CollectedHeap::print_region_accounting_info() { 42.696 - gclog_or_tty->print_cr("P regions: %d.", G1NumPopularRegions); 42.697 gclog_or_tty->print_cr("Free regions: %d (count: %d count list %d) (clean: %d unclean: %d).", 42.698 free_regions(), 42.699 count_free_regions(), count_free_regions_list(),
43.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Apr 01 22:31:26 2009 -0700 43.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Apr 02 17:01:00 2009 -0700 43.3 @@ -29,7 +29,6 @@ 43.4 43.5 class HeapRegion; 43.6 class HeapRegionSeq; 43.7 -class HeapRegionList; 43.8 class PermanentGenerationSpec; 43.9 class GenerationSpec; 43.10 class OopsInHeapRegionClosure; 43.11 @@ -143,7 +142,6 @@ 43.12 friend class VM_GenCollectForPermanentAllocation; 43.13 friend class VM_G1CollectFull; 43.14 friend class VM_G1IncCollectionPause; 43.15 - friend class VM_G1PopRegionCollectionPause; 43.16 friend class VMStructs; 43.17 43.18 // Closures used in implementation. 43.19 @@ -253,10 +251,6 @@ 43.20 // than the current allocation region. 43.21 size_t _summary_bytes_used; 43.22 43.23 - // Summary information about popular objects; method to print it. 43.24 - NumberSeq _pop_obj_rc_at_copy; 43.25 - void print_popularity_summary_info() const; 43.26 - 43.27 // This is used for a quick test on whether a reference points into 43.28 // the collection set or not. Basically, we have an array, with one 43.29 // byte per region, and that byte denotes whether the corresponding 43.30 @@ -447,10 +441,8 @@ 43.31 virtual void do_collection_pause(); 43.32 43.33 // The guts of the incremental collection pause, executed by the vm 43.34 - // thread. If "popular_region" is non-NULL, this pause should evacuate 43.35 - // this single region whose remembered set has gotten large, moving 43.36 - // any popular objects to one of the popular regions. 43.37 - virtual void do_collection_pause_at_safepoint(HeapRegion* popular_region); 43.38 + // thread. 43.39 + virtual void do_collection_pause_at_safepoint(); 43.40 43.41 // Actually do the work of evacuating the collection set. 43.42 virtual void evacuate_collection_set(); 43.43 @@ -625,67 +617,10 @@ 43.44 43.45 SubTasksDone* _process_strong_tasks; 43.46 43.47 - // Allocate space to hold a popular object. Result is guaranteed below 43.48 - // "popular_object_boundary()". Note: CURRENTLY halts the system if we 43.49 - // run out of space to hold popular objects. 43.50 - HeapWord* allocate_popular_object(size_t word_size); 43.51 - 43.52 - // The boundary between popular and non-popular objects. 43.53 - HeapWord* _popular_object_boundary; 43.54 - 43.55 - HeapRegionList* _popular_regions_to_be_evacuated; 43.56 - 43.57 - // Compute which objects in "single_region" are popular. If any are, 43.58 - // evacuate them to a popular region, leaving behind forwarding pointers, 43.59 - // and select "popular_region" as the single collection set region. 43.60 - // Otherwise, leave the collection set null. 43.61 - void popularity_pause_preamble(HeapRegion* populer_region); 43.62 - 43.63 - // Compute which objects in "single_region" are popular, and evacuate 43.64 - // them to a popular region, leaving behind forwarding pointers. 43.65 - // Returns "true" if at least one popular object is discovered and 43.66 - // evacuated. In any case, "*max_rc" is set to the maximum reference 43.67 - // count of an object in the region. 43.68 - bool compute_reference_counts_and_evac_popular(HeapRegion* populer_region, 43.69 - size_t* max_rc); 43.70 - // Subroutines used in the above. 43.71 - bool _rc_region_above; 43.72 - size_t _rc_region_diff; 43.73 - jint* obj_rc_addr(oop obj) { 43.74 - uintptr_t obj_addr = (uintptr_t)obj; 43.75 - if (_rc_region_above) { 43.76 - jint* res = (jint*)(obj_addr + _rc_region_diff); 43.77 - assert((uintptr_t)res > obj_addr, "RC region is above."); 43.78 - return res; 43.79 - } else { 43.80 - jint* res = (jint*)(obj_addr - _rc_region_diff); 43.81 - assert((uintptr_t)res < obj_addr, "RC region is below."); 43.82 - return res; 43.83 - } 43.84 - } 43.85 - jint obj_rc(oop obj) { 43.86 - return *obj_rc_addr(obj); 43.87 - } 43.88 - void inc_obj_rc(oop obj) { 43.89 - (*obj_rc_addr(obj))++; 43.90 - } 43.91 - void atomic_inc_obj_rc(oop obj); 43.92 - 43.93 - 43.94 - // Number of popular objects and bytes (latter is cheaper!). 43.95 - size_t pop_object_used_objs(); 43.96 - size_t pop_object_used_bytes(); 43.97 - 43.98 - // Index of the popular region in which allocation is currently being 43.99 - // done. 43.100 - int _cur_pop_hr_index; 43.101 - 43.102 // List of regions which require zero filling. 43.103 UncleanRegionList _unclean_region_list; 43.104 bool _unclean_regions_coming; 43.105 43.106 - bool check_age_cohort_well_formed_work(int a, HeapRegion* hr); 43.107 - 43.108 public: 43.109 void set_refine_cte_cl_concurrency(bool concurrent); 43.110 43.111 @@ -930,14 +865,25 @@ 43.112 43.113 // Iterate over all the ref-containing fields of all objects, calling 43.114 // "cl.do_oop" on each. 43.115 - virtual void oop_iterate(OopClosure* cl); 43.116 + virtual void oop_iterate(OopClosure* cl) { 43.117 + oop_iterate(cl, true); 43.118 + } 43.119 + void oop_iterate(OopClosure* cl, bool do_perm); 43.120 43.121 // Same as above, restricted to a memory region. 43.122 - virtual void oop_iterate(MemRegion mr, OopClosure* cl); 43.123 + virtual void oop_iterate(MemRegion mr, OopClosure* cl) { 43.124 + oop_iterate(mr, cl, true); 43.125 + } 43.126 + void oop_iterate(MemRegion mr, OopClosure* cl, bool do_perm); 43.127 43.128 // Iterate over all objects, calling "cl.do_object" on each. 43.129 - virtual void object_iterate(ObjectClosure* cl); 43.130 - virtual void safe_object_iterate(ObjectClosure* cl) { object_iterate(cl); } 43.131 + virtual void object_iterate(ObjectClosure* cl) { 43.132 + object_iterate(cl, true); 43.133 + } 43.134 + virtual void safe_object_iterate(ObjectClosure* cl) { 43.135 + object_iterate(cl, true); 43.136 + } 43.137 + void object_iterate(ObjectClosure* cl, bool do_perm); 43.138 43.139 // Iterate over all objects allocated since the last collection, calling 43.140 // "cl.do_object" on each. The heap must have been initialized properly 43.141 @@ -1066,21 +1012,6 @@ 43.142 // words. 43.143 virtual size_t large_typearray_limit(); 43.144 43.145 - // All popular objects are guaranteed to have addresses below this 43.146 - // boundary. 43.147 - HeapWord* popular_object_boundary() { 43.148 - return _popular_object_boundary; 43.149 - } 43.150 - 43.151 - // Declare the region as one that should be evacuated because its 43.152 - // remembered set is too large. 43.153 - void schedule_popular_region_evac(HeapRegion* r); 43.154 - // If there is a popular region to evacuate it, remove it from the list 43.155 - // and return it. 43.156 - HeapRegion* popular_region_to_evac(); 43.157 - // Evacuate the given popular region. 43.158 - void evac_popular_region(HeapRegion* r); 43.159 - 43.160 // Returns "true" iff the given word_size is "very large". 43.161 static bool isHumongous(size_t word_size) { 43.162 return word_size >= VeryLargeInWords;
44.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Wed Apr 01 22:31:26 2009 -0700 44.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Apr 02 17:01:00 2009 -0700 44.3 @@ -91,10 +91,8 @@ 44.4 44.5 _all_mod_union_times_ms(new NumberSeq()), 44.6 44.7 - _non_pop_summary(new NonPopSummary()), 44.8 - _pop_summary(new PopSummary()), 44.9 - _non_pop_abandoned_summary(new NonPopAbandonedSummary()), 44.10 - _pop_abandoned_summary(new PopAbandonedSummary()), 44.11 + _summary(new Summary()), 44.12 + _abandoned_summary(new AbandonedSummary()), 44.13 44.14 _cur_clear_ct_time_ms(0.0), 44.15 44.16 @@ -109,9 +107,6 @@ 44.17 _cur_aux_times_ms(new double[_aux_num]), 44.18 _cur_aux_times_set(new bool[_aux_num]), 44.19 44.20 - _pop_compute_rc_start(0.0), 44.21 - _pop_evac_start(0.0), 44.22 - 44.23 _concurrent_mark_init_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), 44.24 _concurrent_mark_remark_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), 44.25 _concurrent_mark_cleanup_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), 44.26 @@ -224,16 +219,6 @@ 44.27 44.28 _par_last_termination_times_ms = new double[_parallel_gc_threads]; 44.29 44.30 - // we store the data from the first pass during popularity pauses 44.31 - _pop_par_last_update_rs_start_times_ms = new double[_parallel_gc_threads]; 44.32 - _pop_par_last_update_rs_times_ms = new double[_parallel_gc_threads]; 44.33 - _pop_par_last_update_rs_processed_buffers = new double[_parallel_gc_threads]; 44.34 - 44.35 - _pop_par_last_scan_rs_start_times_ms = new double[_parallel_gc_threads]; 44.36 - _pop_par_last_scan_rs_times_ms = new double[_parallel_gc_threads]; 44.37 - 44.38 - _pop_par_last_closure_app_times_ms = new double[_parallel_gc_threads]; 44.39 - 44.40 // start conservatively 44.41 _expensive_region_limit_ms = 0.5 * (double) G1MaxPauseTimeMS; 44.42 44.43 @@ -1047,23 +1032,6 @@ 44.44 calculate_young_list_target_config(); 44.45 } 44.46 44.47 -void G1CollectorPolicy::record_pop_compute_rc_start() { 44.48 - _pop_compute_rc_start = os::elapsedTime(); 44.49 -} 44.50 -void G1CollectorPolicy::record_pop_compute_rc_end() { 44.51 - double ms = (os::elapsedTime() - _pop_compute_rc_start)*1000.0; 44.52 - _cur_popular_compute_rc_time_ms = ms; 44.53 - _pop_compute_rc_start = 0.0; 44.54 -} 44.55 -void G1CollectorPolicy::record_pop_evac_start() { 44.56 - _pop_evac_start = os::elapsedTime(); 44.57 -} 44.58 -void G1CollectorPolicy::record_pop_evac_end() { 44.59 - double ms = (os::elapsedTime() - _pop_evac_start)*1000.0; 44.60 - _cur_popular_evac_time_ms = ms; 44.61 - _pop_evac_start = 0.0; 44.62 -} 44.63 - 44.64 void G1CollectorPolicy::record_before_bytes(size_t bytes) { 44.65 _bytes_in_to_space_before_gc += bytes; 44.66 } 44.67 @@ -1120,13 +1088,6 @@ 44.68 _par_last_scan_new_refs_times_ms[i] = -666.0; 44.69 _par_last_obj_copy_times_ms[i] = -666.0; 44.70 _par_last_termination_times_ms[i] = -666.0; 44.71 - 44.72 - _pop_par_last_update_rs_start_times_ms[i] = -666.0; 44.73 - _pop_par_last_update_rs_times_ms[i] = -666.0; 44.74 - _pop_par_last_update_rs_processed_buffers[i] = -666.0; 44.75 - _pop_par_last_scan_rs_start_times_ms[i] = -666.0; 44.76 - _pop_par_last_scan_rs_times_ms[i] = -666.0; 44.77 - _pop_par_last_closure_app_times_ms[i] = -666.0; 44.78 } 44.79 #endif 44.80 44.81 @@ -1185,25 +1146,6 @@ 44.82 guarantee( false, "we should never reach here" ); 44.83 } 44.84 44.85 -void G1CollectorPolicy::record_popular_pause_preamble_start() { 44.86 - _cur_popular_preamble_start_ms = os::elapsedTime() * 1000.0; 44.87 -} 44.88 - 44.89 -void G1CollectorPolicy::record_popular_pause_preamble_end() { 44.90 - _cur_popular_preamble_time_ms = 44.91 - (os::elapsedTime() * 1000.0) - _cur_popular_preamble_start_ms; 44.92 - 44.93 - // copy the recorded statistics of the first pass to temporary arrays 44.94 - for (int i = 0; i < _parallel_gc_threads; ++i) { 44.95 - _pop_par_last_update_rs_start_times_ms[i] = _par_last_update_rs_start_times_ms[i]; 44.96 - _pop_par_last_update_rs_times_ms[i] = _par_last_update_rs_times_ms[i]; 44.97 - _pop_par_last_update_rs_processed_buffers[i] = _par_last_update_rs_processed_buffers[i]; 44.98 - _pop_par_last_scan_rs_start_times_ms[i] = _par_last_scan_rs_start_times_ms[i]; 44.99 - _pop_par_last_scan_rs_times_ms[i] = _par_last_scan_rs_times_ms[i]; 44.100 - _pop_par_last_closure_app_times_ms[i] = _par_last_obj_copy_times_ms[i]; 44.101 - } 44.102 -} 44.103 - 44.104 void G1CollectorPolicy::record_mark_closure_time(double mark_closure_time_ms) { 44.105 _mark_closure_time_ms = mark_closure_time_ms; 44.106 } 44.107 @@ -1465,8 +1407,7 @@ 44.108 // Anything below that is considered to be zero 44.109 #define MIN_TIMER_GRANULARITY 0.0000001 44.110 44.111 -void G1CollectorPolicy::record_collection_pause_end(bool popular, 44.112 - bool abandoned) { 44.113 +void G1CollectorPolicy::record_collection_pause_end(bool abandoned) { 44.114 double end_time_sec = os::elapsedTime(); 44.115 double elapsed_ms = _last_pause_time_ms; 44.116 bool parallel = ParallelGCThreads > 0; 44.117 @@ -1587,42 +1528,10 @@ 44.118 } 44.119 44.120 PauseSummary* summary; 44.121 - if (!abandoned && !popular) 44.122 - summary = _non_pop_summary; 44.123 - else if (!abandoned && popular) 44.124 - summary = _pop_summary; 44.125 - else if (abandoned && !popular) 44.126 - summary = _non_pop_abandoned_summary; 44.127 - else if (abandoned && popular) 44.128 - summary = _pop_abandoned_summary; 44.129 - else 44.130 - guarantee(false, "should not get here!"); 44.131 - 44.132 - double pop_update_rs_time; 44.133 - double pop_update_rs_processed_buffers; 44.134 - double pop_scan_rs_time; 44.135 - double pop_closure_app_time; 44.136 - double pop_other_time; 44.137 - 44.138 - if (popular) { 44.139 - PopPreambleSummary* preamble_summary = summary->pop_preamble_summary(); 44.140 - guarantee(preamble_summary != NULL, "should not be null!"); 44.141 - 44.142 - pop_update_rs_time = avg_value(_pop_par_last_update_rs_times_ms); 44.143 - pop_update_rs_processed_buffers = 44.144 - sum_of_values(_pop_par_last_update_rs_processed_buffers); 44.145 - pop_scan_rs_time = avg_value(_pop_par_last_scan_rs_times_ms); 44.146 - pop_closure_app_time = avg_value(_pop_par_last_closure_app_times_ms); 44.147 - pop_other_time = _cur_popular_preamble_time_ms - 44.148 - (pop_update_rs_time + pop_scan_rs_time + pop_closure_app_time + 44.149 - _cur_popular_evac_time_ms); 44.150 - 44.151 - preamble_summary->record_pop_preamble_time_ms(_cur_popular_preamble_time_ms); 44.152 - preamble_summary->record_pop_update_rs_time_ms(pop_update_rs_time); 44.153 - preamble_summary->record_pop_scan_rs_time_ms(pop_scan_rs_time); 44.154 - preamble_summary->record_pop_closure_app_time_ms(pop_closure_app_time); 44.155 - preamble_summary->record_pop_evacuation_time_ms(_cur_popular_evac_time_ms); 44.156 - preamble_summary->record_pop_other_time_ms(pop_other_time); 44.157 + if (abandoned) { 44.158 + summary = _abandoned_summary; 44.159 + } else { 44.160 + summary = _summary; 44.161 } 44.162 44.163 double ext_root_scan_time = avg_value(_par_last_ext_root_scan_times_ms); 44.164 @@ -1694,8 +1603,6 @@ 44.165 } 44.166 44.167 double other_time_ms = elapsed_ms; 44.168 - if (popular) 44.169 - other_time_ms -= _cur_popular_preamble_time_ms; 44.170 44.171 if (!abandoned) { 44.172 if (_satb_drain_time_set) 44.173 @@ -1712,41 +1619,24 @@ 44.174 44.175 if (PrintGCDetails) { 44.176 gclog_or_tty->print_cr("%s%s, %1.8lf secs]", 44.177 - (popular && !abandoned) ? " (popular)" : 44.178 - (!popular && abandoned) ? " (abandoned)" : 44.179 - (popular && abandoned) ? " (popular/abandoned)" : "", 44.180 + abandoned ? " (abandoned)" : "", 44.181 (last_pause_included_initial_mark) ? " (initial-mark)" : "", 44.182 elapsed_ms / 1000.0); 44.183 44.184 if (!abandoned) { 44.185 - if (_satb_drain_time_set) 44.186 + if (_satb_drain_time_set) { 44.187 print_stats(1, "SATB Drain Time", _cur_satb_drain_time_ms); 44.188 - if (_last_satb_drain_processed_buffers >= 0) 44.189 + } 44.190 + if (_last_satb_drain_processed_buffers >= 0) { 44.191 print_stats(2, "Processed Buffers", _last_satb_drain_processed_buffers); 44.192 - } 44.193 - if (popular) 44.194 - print_stats(1, "Popularity Preamble", _cur_popular_preamble_time_ms); 44.195 - if (parallel) { 44.196 - if (popular) { 44.197 - print_par_stats(2, "Update RS (Start)", _pop_par_last_update_rs_start_times_ms, false); 44.198 - print_par_stats(2, "Update RS", _pop_par_last_update_rs_times_ms); 44.199 + } 44.200 + if (parallel) { 44.201 + print_stats(1, "Parallel Time", _cur_collection_par_time_ms); 44.202 + print_par_stats(2, "Update RS (Start)", _par_last_update_rs_start_times_ms, false); 44.203 + print_par_stats(2, "Update RS", _par_last_update_rs_times_ms); 44.204 if (G1RSBarrierUseQueue) 44.205 print_par_buffers(3, "Processed Buffers", 44.206 - _pop_par_last_update_rs_processed_buffers, true); 44.207 - print_par_stats(2, "Scan RS", _pop_par_last_scan_rs_times_ms); 44.208 - print_par_stats(2, "Closure app", _pop_par_last_closure_app_times_ms); 44.209 - print_stats(2, "Evacuation", _cur_popular_evac_time_ms); 44.210 - print_stats(2, "Other", pop_other_time); 44.211 - } 44.212 - if (!abandoned) { 44.213 - print_stats(1, "Parallel Time", _cur_collection_par_time_ms); 44.214 - if (!popular) { 44.215 - print_par_stats(2, "Update RS (Start)", _par_last_update_rs_start_times_ms, false); 44.216 - print_par_stats(2, "Update RS", _par_last_update_rs_times_ms); 44.217 - if (G1RSBarrierUseQueue) 44.218 - print_par_buffers(3, "Processed Buffers", 44.219 - _par_last_update_rs_processed_buffers, true); 44.220 - } 44.221 + _par_last_update_rs_processed_buffers, true); 44.222 print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms); 44.223 print_par_stats(2, "Mark Stack Scanning", _par_last_mark_stack_scan_times_ms); 44.224 print_par_stats(2, "Scan-Only Scanning", _par_last_scan_only_times_ms); 44.225 @@ -1757,25 +1647,11 @@ 44.226 print_par_stats(2, "Termination", _par_last_termination_times_ms); 44.227 print_stats(2, "Other", parallel_other_time); 44.228 print_stats(1, "Clear CT", _cur_clear_ct_time_ms); 44.229 - } 44.230 - } else { 44.231 - if (popular) { 44.232 - print_stats(2, "Update RS", pop_update_rs_time); 44.233 + } else { 44.234 + print_stats(1, "Update RS", update_rs_time); 44.235 if (G1RSBarrierUseQueue) 44.236 - print_stats(3, "Processed Buffers", 44.237 - (int)pop_update_rs_processed_buffers); 44.238 - print_stats(2, "Scan RS", pop_scan_rs_time); 44.239 - print_stats(2, "Closure App", pop_closure_app_time); 44.240 - print_stats(2, "Evacuation", _cur_popular_evac_time_ms); 44.241 - print_stats(2, "Other", pop_other_time); 44.242 - } 44.243 - if (!abandoned) { 44.244 - if (!popular) { 44.245 - print_stats(1, "Update RS", update_rs_time); 44.246 - if (G1RSBarrierUseQueue) 44.247 - print_stats(2, "Processed Buffers", 44.248 - (int)update_rs_processed_buffers); 44.249 - } 44.250 + print_stats(2, "Processed Buffers", 44.251 + (int)update_rs_processed_buffers); 44.252 print_stats(1, "Ext Root Scanning", ext_root_scan_time); 44.253 print_stats(1, "Mark Stack Scanning", mark_stack_scan_time); 44.254 print_stats(1, "Scan-Only Scanning", scan_only_time); 44.255 @@ -1855,7 +1731,7 @@ 44.256 44.257 // <NEW PREDICTION> 44.258 44.259 - if (!popular && update_stats) { 44.260 + if (update_stats) { 44.261 double pause_time_ms = elapsed_ms; 44.262 44.263 size_t diff = 0; 44.264 @@ -2454,36 +2330,8 @@ 44.265 void G1CollectorPolicy::print_summary(PauseSummary* summary) const { 44.266 bool parallel = ParallelGCThreads > 0; 44.267 MainBodySummary* body_summary = summary->main_body_summary(); 44.268 - PopPreambleSummary* preamble_summary = summary->pop_preamble_summary(); 44.269 - 44.270 if (summary->get_total_seq()->num() > 0) { 44.271 - print_summary_sd(0, 44.272 - (preamble_summary == NULL) ? "Non-Popular Pauses" : 44.273 - "Popular Pauses", 44.274 - summary->get_total_seq()); 44.275 - if (preamble_summary != NULL) { 44.276 - print_summary(1, "Popularity Preamble", 44.277 - preamble_summary->get_pop_preamble_seq()); 44.278 - print_summary(2, "Update RS", preamble_summary->get_pop_update_rs_seq()); 44.279 - print_summary(2, "Scan RS", preamble_summary->get_pop_scan_rs_seq()); 44.280 - print_summary(2, "Closure App", 44.281 - preamble_summary->get_pop_closure_app_seq()); 44.282 - print_summary(2, "Evacuation", 44.283 - preamble_summary->get_pop_evacuation_seq()); 44.284 - print_summary(2, "Other", preamble_summary->get_pop_other_seq()); 44.285 - { 44.286 - NumberSeq* other_parts[] = { 44.287 - preamble_summary->get_pop_update_rs_seq(), 44.288 - preamble_summary->get_pop_scan_rs_seq(), 44.289 - preamble_summary->get_pop_closure_app_seq(), 44.290 - preamble_summary->get_pop_evacuation_seq() 44.291 - }; 44.292 - NumberSeq calc_other_times_ms(preamble_summary->get_pop_preamble_seq(), 44.293 - 4, other_parts); 44.294 - check_other_times(2, preamble_summary->get_pop_other_seq(), 44.295 - &calc_other_times_ms); 44.296 - } 44.297 - } 44.298 + print_summary_sd(0, "Evacuation Pauses", summary->get_total_seq()); 44.299 if (body_summary != NULL) { 44.300 print_summary(1, "SATB Drain", body_summary->get_satb_drain_seq()); 44.301 if (parallel) { 44.302 @@ -2537,19 +2385,15 @@ 44.303 // parallel 44.304 NumberSeq* other_parts[] = { 44.305 body_summary->get_satb_drain_seq(), 44.306 - (preamble_summary == NULL) ? NULL : 44.307 - preamble_summary->get_pop_preamble_seq(), 44.308 body_summary->get_parallel_seq(), 44.309 body_summary->get_clear_ct_seq() 44.310 }; 44.311 - calc_other_times_ms = NumberSeq (summary->get_total_seq(), 44.312 - 4, other_parts); 44.313 + calc_other_times_ms = NumberSeq(summary->get_total_seq(), 44.314 + 3, other_parts); 44.315 } else { 44.316 // serial 44.317 NumberSeq* other_parts[] = { 44.318 body_summary->get_satb_drain_seq(), 44.319 - (preamble_summary == NULL) ? NULL : 44.320 - preamble_summary->get_pop_preamble_seq(), 44.321 body_summary->get_update_rs_seq(), 44.322 body_summary->get_ext_root_scan_seq(), 44.323 body_summary->get_mark_stack_scan_seq(), 44.324 @@ -2558,16 +2402,11 @@ 44.325 body_summary->get_obj_copy_seq() 44.326 }; 44.327 calc_other_times_ms = NumberSeq(summary->get_total_seq(), 44.328 - 8, other_parts); 44.329 + 7, other_parts); 44.330 } 44.331 } else { 44.332 // abandoned 44.333 - NumberSeq* other_parts[] = { 44.334 - (preamble_summary == NULL) ? NULL : 44.335 - preamble_summary->get_pop_preamble_seq() 44.336 - }; 44.337 - calc_other_times_ms = NumberSeq(summary->get_total_seq(), 44.338 - 1, other_parts); 44.339 + calc_other_times_ms = NumberSeq(); 44.340 } 44.341 check_other_times(1, summary->get_other_seq(), &calc_other_times_ms); 44.342 } 44.343 @@ -2579,18 +2418,12 @@ 44.344 } 44.345 44.346 void 44.347 -G1CollectorPolicy::print_abandoned_summary(PauseSummary* non_pop_summary, 44.348 - PauseSummary* pop_summary) const { 44.349 +G1CollectorPolicy::print_abandoned_summary(PauseSummary* summary) const { 44.350 bool printed = false; 44.351 - if (non_pop_summary->get_total_seq()->num() > 0) { 44.352 + if (summary->get_total_seq()->num() > 0) { 44.353 printed = true; 44.354 - print_summary(non_pop_summary); 44.355 + print_summary(summary); 44.356 } 44.357 - if (pop_summary->get_total_seq()->num() > 0) { 44.358 - printed = true; 44.359 - print_summary(pop_summary); 44.360 - } 44.361 - 44.362 if (!printed) { 44.363 print_indent(0); 44.364 gclog_or_tty->print_cr("none"); 44.365 @@ -2608,15 +2441,11 @@ 44.366 gclog_or_tty->print_cr(" Partial Young GC Pauses: %8d", _partial_young_pause_num); 44.367 gclog_or_tty->print_cr(""); 44.368 44.369 - gclog_or_tty->print_cr("NON-POPULAR PAUSES"); 44.370 - print_summary(_non_pop_summary); 44.371 - 44.372 - gclog_or_tty->print_cr("POPULAR PAUSES"); 44.373 - print_summary(_pop_summary); 44.374 + gclog_or_tty->print_cr("EVACUATION PAUSES"); 44.375 + print_summary(_summary); 44.376 44.377 gclog_or_tty->print_cr("ABANDONED PAUSES"); 44.378 - print_abandoned_summary(_non_pop_abandoned_summary, 44.379 - _pop_abandoned_summary); 44.380 + print_abandoned_summary(_abandoned_summary); 44.381 44.382 gclog_or_tty->print_cr("MISC"); 44.383 print_summary_sd(0, "Stop World", _all_stop_world_times_ms); 44.384 @@ -2702,14 +2531,6 @@ 44.385 _conc_refine_enabled++; 44.386 } 44.387 44.388 -void G1CollectorPolicy::set_single_region_collection_set(HeapRegion* hr) { 44.389 - assert(collection_set() == NULL, "Must be no current CS."); 44.390 - _collection_set_size = 0; 44.391 - _collection_set_bytes_used_before = 0; 44.392 - add_to_collection_set(hr); 44.393 - count_CS_bytes_used(); 44.394 -} 44.395 - 44.396 bool 44.397 G1CollectorPolicy::should_add_next_region_to_young_list() { 44.398 assert(in_young_gc_mode(), "should be in young GC mode"); 44.399 @@ -2787,15 +2608,6 @@ 44.400 } 44.401 } 44.402 44.403 - 44.404 -void 44.405 -G1CollectorPolicy_BestRegionsFirst:: 44.406 -set_single_region_collection_set(HeapRegion* hr) { 44.407 - G1CollectorPolicy::set_single_region_collection_set(hr); 44.408 - _collectionSetChooser->removeRegion(hr); 44.409 -} 44.410 - 44.411 - 44.412 bool 44.413 G1CollectorPolicy_BestRegionsFirst::should_do_collection_pause(size_t 44.414 word_size) { 44.415 @@ -3061,19 +2873,13 @@ 44.416 44.417 void 44.418 G1CollectorPolicy_BestRegionsFirst:: 44.419 -choose_collection_set(HeapRegion* pop_region) { 44.420 +choose_collection_set() { 44.421 double non_young_start_time_sec; 44.422 start_recording_regions(); 44.423 44.424 - if (pop_region != NULL) { 44.425 - _target_pause_time_ms = (double) G1MaxPauseTimeMS; 44.426 - } else { 44.427 - guarantee(_target_pause_time_ms > -1.0, 44.428 - "_target_pause_time_ms should have been set!"); 44.429 - } 44.430 - 44.431 - // pop region is either null (and so is CS), or else it *is* the CS. 44.432 - assert(_collection_set == pop_region, "Precondition"); 44.433 + guarantee(_target_pause_time_ms > -1.0, 44.434 + "_target_pause_time_ms should have been set!"); 44.435 + assert(_collection_set == NULL, "Precondition"); 44.436 44.437 double base_time_ms = predict_base_elapsed_time_ms(_pending_cards); 44.438 double predicted_pause_time_ms = base_time_ms; 44.439 @@ -3100,15 +2906,13 @@ 44.440 size_t expansion_bytes = 44.441 _g1->expansion_regions() * HeapRegion::GrainBytes; 44.442 44.443 - if (pop_region == NULL) { 44.444 - _collection_set_bytes_used_before = 0; 44.445 - _collection_set_size = 0; 44.446 - } 44.447 + _collection_set_bytes_used_before = 0; 44.448 + _collection_set_size = 0; 44.449 44.450 // Adjust for expansion and slop. 44.451 max_live_bytes = max_live_bytes + expansion_bytes; 44.452 44.453 - assert(pop_region != NULL || _g1->regions_accounted_for(), "Region leakage!"); 44.454 + assert(_g1->regions_accounted_for(), "Region leakage!"); 44.455 44.456 HeapRegion* hr; 44.457 if (in_young_gc_mode()) { 44.458 @@ -3135,14 +2939,9 @@ 44.459 double predicted_time_ms = predict_region_elapsed_time_ms(hr, true); 44.460 time_remaining_ms -= predicted_time_ms; 44.461 predicted_pause_time_ms += predicted_time_ms; 44.462 - if (hr == pop_region) { 44.463 - // The popular region was young. Skip over it. 44.464 - assert(hr->in_collection_set(), "It's the pop region."); 44.465 - } else { 44.466 - assert(!hr->in_collection_set(), "It's not the pop region."); 44.467 - add_to_collection_set(hr); 44.468 - record_cset_region(hr, true); 44.469 - } 44.470 + assert(!hr->in_collection_set(), "invariant"); 44.471 + add_to_collection_set(hr); 44.472 + record_cset_region(hr, true); 44.473 max_live_bytes -= MIN2(hr->max_live_bytes(), max_live_bytes); 44.474 if (G1PolicyVerbose > 0) { 44.475 gclog_or_tty->print_cr(" Added [" PTR_FORMAT ", " PTR_FORMAT") to CS.", 44.476 @@ -3165,10 +2964,6 @@ 44.477 // don't bother adding more regions... 44.478 goto choose_collection_set_end; 44.479 } 44.480 - } else if (pop_region != NULL) { 44.481 - // We're not in young mode, and we chose a popular region; don't choose 44.482 - // any more. 44.483 - return; 44.484 } 44.485 44.486 if (!in_young_gc_mode() || !full_young_gcs()) { 44.487 @@ -3178,7 +2973,7 @@ 44.488 do { 44.489 hr = _collectionSetChooser->getNextMarkedRegion(time_remaining_ms, 44.490 avg_prediction); 44.491 - if (hr != NULL && !hr->popular()) { 44.492 + if (hr != NULL) { 44.493 double predicted_time_ms = predict_region_elapsed_time_ms(hr, false); 44.494 time_remaining_ms -= predicted_time_ms; 44.495 predicted_pause_time_ms += predicted_time_ms; 44.496 @@ -3225,8 +3020,8 @@ 44.497 } 44.498 44.499 void G1CollectorPolicy_BestRegionsFirst:: 44.500 -record_collection_pause_end(bool popular, bool abandoned) { 44.501 - G1CollectorPolicy::record_collection_pause_end(popular, abandoned); 44.502 +record_collection_pause_end(bool abandoned) { 44.503 + G1CollectorPolicy::record_collection_pause_end(abandoned); 44.504 assert(assertMarkedBytesDataOK(), "Marked regions not OK at pause end."); 44.505 } 44.506
45.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Wed Apr 01 22:31:26 2009 -0700 45.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu Apr 02 17:01:00 2009 -0700 45.3 @@ -47,7 +47,6 @@ 45.4 } 45.5 45.6 class MainBodySummary; 45.7 -class PopPreambleSummary; 45.8 45.9 class PauseSummary: public CHeapObj { 45.10 define_num_seq(total) 45.11 @@ -55,7 +54,6 @@ 45.12 45.13 public: 45.14 virtual MainBodySummary* main_body_summary() { return NULL; } 45.15 - virtual PopPreambleSummary* pop_preamble_summary() { return NULL; } 45.16 }; 45.17 45.18 class MainBodySummary: public CHeapObj { 45.19 @@ -75,36 +73,13 @@ 45.20 define_num_seq(clear_ct) // parallel only 45.21 }; 45.22 45.23 -class PopPreambleSummary: public CHeapObj { 45.24 - define_num_seq(pop_preamble) 45.25 - define_num_seq(pop_update_rs) 45.26 - define_num_seq(pop_scan_rs) 45.27 - define_num_seq(pop_closure_app) 45.28 - define_num_seq(pop_evacuation) 45.29 - define_num_seq(pop_other) 45.30 -}; 45.31 - 45.32 -class NonPopSummary: public PauseSummary, 45.33 - public MainBodySummary { 45.34 +class Summary: public PauseSummary, 45.35 + public MainBodySummary { 45.36 public: 45.37 virtual MainBodySummary* main_body_summary() { return this; } 45.38 }; 45.39 45.40 -class PopSummary: public PauseSummary, 45.41 - public MainBodySummary, 45.42 - public PopPreambleSummary { 45.43 -public: 45.44 - virtual MainBodySummary* main_body_summary() { return this; } 45.45 - virtual PopPreambleSummary* pop_preamble_summary() { return this; } 45.46 -}; 45.47 - 45.48 -class NonPopAbandonedSummary: public PauseSummary { 45.49 -}; 45.50 - 45.51 -class PopAbandonedSummary: public PauseSummary, 45.52 - public PopPreambleSummary { 45.53 -public: 45.54 - virtual PopPreambleSummary* pop_preamble_summary() { return this; } 45.55 +class AbandonedSummary: public PauseSummary { 45.56 }; 45.57 45.58 class G1CollectorPolicy: public CollectorPolicy { 45.59 @@ -146,10 +121,6 @@ 45.60 double _cur_satb_drain_time_ms; 45.61 double _cur_clear_ct_time_ms; 45.62 bool _satb_drain_time_set; 45.63 - double _cur_popular_preamble_start_ms; 45.64 - double _cur_popular_preamble_time_ms; 45.65 - double _cur_popular_compute_rc_time_ms; 45.66 - double _cur_popular_evac_time_ms; 45.67 45.68 double _cur_CH_strong_roots_end_sec; 45.69 double _cur_CH_strong_roots_dur_ms; 45.70 @@ -173,10 +144,8 @@ 45.71 TruncatedSeq* _concurrent_mark_remark_times_ms; 45.72 TruncatedSeq* _concurrent_mark_cleanup_times_ms; 45.73 45.74 - NonPopSummary* _non_pop_summary; 45.75 - PopSummary* _pop_summary; 45.76 - NonPopAbandonedSummary* _non_pop_abandoned_summary; 45.77 - PopAbandonedSummary* _pop_abandoned_summary; 45.78 + Summary* _summary; 45.79 + AbandonedSummary* _abandoned_summary; 45.80 45.81 NumberSeq* _all_pause_times_ms; 45.82 NumberSeq* _all_full_gc_times_ms; 45.83 @@ -210,18 +179,6 @@ 45.84 double* _par_last_obj_copy_times_ms; 45.85 double* _par_last_termination_times_ms; 45.86 45.87 - // there are two pases during popular pauses, so we need to store 45.88 - // somewhere the results of the first pass 45.89 - double* _pop_par_last_update_rs_start_times_ms; 45.90 - double* _pop_par_last_update_rs_times_ms; 45.91 - double* _pop_par_last_update_rs_processed_buffers; 45.92 - double* _pop_par_last_scan_rs_start_times_ms; 45.93 - double* _pop_par_last_scan_rs_times_ms; 45.94 - double* _pop_par_last_closure_app_times_ms; 45.95 - 45.96 - double _pop_compute_rc_start; 45.97 - double _pop_evac_start; 45.98 - 45.99 // indicates that we are in young GC mode 45.100 bool _in_young_gc_mode; 45.101 45.102 @@ -634,8 +591,7 @@ 45.103 NumberSeq* calc_other_times_ms) const; 45.104 45.105 void print_summary (PauseSummary* stats) const; 45.106 - void print_abandoned_summary(PauseSummary* non_pop_summary, 45.107 - PauseSummary* pop_summary) const; 45.108 + void print_abandoned_summary(PauseSummary* summary) const; 45.109 45.110 void print_summary (int level, const char* str, NumberSeq* seq) const; 45.111 void print_summary_sd (int level, const char* str, NumberSeq* seq) const; 45.112 @@ -856,9 +812,6 @@ 45.113 virtual void record_collection_pause_start(double start_time_sec, 45.114 size_t start_used); 45.115 45.116 - virtual void record_popular_pause_preamble_start(); 45.117 - virtual void record_popular_pause_preamble_end(); 45.118 - 45.119 // Must currently be called while the world is stopped. 45.120 virtual void record_concurrent_mark_init_start(); 45.121 virtual void record_concurrent_mark_init_end(); 45.122 @@ -881,7 +834,7 @@ 45.123 virtual void record_collection_pause_end_CH_strong_roots(); 45.124 virtual void record_collection_pause_end_G1_strong_roots(); 45.125 45.126 - virtual void record_collection_pause_end(bool popular, bool abandoned); 45.127 + virtual void record_collection_pause_end(bool abandoned); 45.128 45.129 // Record the fact that a full collection occurred. 45.130 virtual void record_full_collection_start(); 45.131 @@ -990,12 +943,6 @@ 45.132 _cur_aux_times_ms[i] += ms; 45.133 } 45.134 45.135 - void record_pop_compute_rc_start(); 45.136 - void record_pop_compute_rc_end(); 45.137 - 45.138 - void record_pop_evac_start(); 45.139 - void record_pop_evac_end(); 45.140 - 45.141 // Record the fact that "bytes" bytes allocated in a region. 45.142 void record_before_bytes(size_t bytes); 45.143 void record_after_bytes(size_t bytes); 45.144 @@ -1008,9 +955,7 @@ 45.145 // Choose a new collection set. Marks the chosen regions as being 45.146 // "in_collection_set", and links them together. The head and number of 45.147 // the collection set are available via access methods. 45.148 - // If "pop_region" is non-NULL, it is a popular region that has already 45.149 - // been added to the collection set. 45.150 - virtual void choose_collection_set(HeapRegion* pop_region = NULL) = 0; 45.151 + virtual void choose_collection_set() = 0; 45.152 45.153 void clear_collection_set() { _collection_set = NULL; } 45.154 45.155 @@ -1018,9 +963,6 @@ 45.156 // current collection set. 45.157 HeapRegion* collection_set() { return _collection_set; } 45.158 45.159 - // Sets the collection set to the given single region. 45.160 - virtual void set_single_region_collection_set(HeapRegion* hr); 45.161 - 45.162 // The number of elements in the current collection set. 45.163 size_t collection_set_size() { return _collection_set_size; } 45.164 45.165 @@ -1203,7 +1145,7 @@ 45.166 // If the estimated is less then desirable, resize if possible. 45.167 void expand_if_possible(size_t numRegions); 45.168 45.169 - virtual void choose_collection_set(HeapRegion* pop_region = NULL); 45.170 + virtual void choose_collection_set(); 45.171 virtual void record_collection_pause_start(double start_time_sec, 45.172 size_t start_used); 45.173 virtual void record_concurrent_mark_cleanup_end(size_t freed_bytes, 45.174 @@ -1214,9 +1156,8 @@ 45.175 G1CollectorPolicy_BestRegionsFirst() { 45.176 _collectionSetChooser = new CollectionSetChooser(); 45.177 } 45.178 - void record_collection_pause_end(bool popular, bool abandoned); 45.179 + void record_collection_pause_end(bool abandoned); 45.180 bool should_do_collection_pause(size_t word_size); 45.181 - virtual void set_single_region_collection_set(HeapRegion* hr); 45.182 // This is not needed any more, after the CSet choosing code was 45.183 // changed to use the pause prediction work. But let's leave the 45.184 // hook in just in case.
46.1 --- a/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Wed Apr 01 22:31:26 2009 -0700 46.2 +++ b/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Thu Apr 02 17:01:00 2009 -0700 46.3 @@ -157,7 +157,6 @@ 46.4 class G1PrepareCompactClosure: public HeapRegionClosure { 46.5 ModRefBarrierSet* _mrbs; 46.6 CompactPoint _cp; 46.7 - bool _popular_only; 46.8 46.9 void free_humongous_region(HeapRegion* hr) { 46.10 HeapWord* bot = hr->bottom(); 46.11 @@ -172,17 +171,11 @@ 46.12 } 46.13 46.14 public: 46.15 - G1PrepareCompactClosure(CompactibleSpace* cs, bool popular_only) : 46.16 + G1PrepareCompactClosure(CompactibleSpace* cs) : 46.17 _cp(NULL, cs, cs->initialize_threshold()), 46.18 - _mrbs(G1CollectedHeap::heap()->mr_bs()), 46.19 - _popular_only(popular_only) 46.20 + _mrbs(G1CollectedHeap::heap()->mr_bs()) 46.21 {} 46.22 bool doHeapRegion(HeapRegion* hr) { 46.23 - if (_popular_only && !hr->popular()) 46.24 - return true; // terminate early 46.25 - else if (!_popular_only && hr->popular()) 46.26 - return false; // skip this one. 46.27 - 46.28 if (hr->isHumongous()) { 46.29 if (hr->startsHumongous()) { 46.30 oop obj = oop(hr->bottom()); 46.31 @@ -203,20 +196,15 @@ 46.32 return false; 46.33 } 46.34 }; 46.35 -// Stolen verbatim from g1CollectedHeap.cpp 46.36 + 46.37 +// Finds the first HeapRegion. 46.38 class FindFirstRegionClosure: public HeapRegionClosure { 46.39 HeapRegion* _a_region; 46.40 - bool _find_popular; 46.41 public: 46.42 - FindFirstRegionClosure(bool find_popular) : 46.43 - _a_region(NULL), _find_popular(find_popular) {} 46.44 + FindFirstRegionClosure() : _a_region(NULL) {} 46.45 bool doHeapRegion(HeapRegion* r) { 46.46 - if (r->popular() == _find_popular) { 46.47 - _a_region = r; 46.48 - return true; 46.49 - } else { 46.50 - return false; 46.51 - } 46.52 + _a_region = r; 46.53 + return true; 46.54 } 46.55 HeapRegion* result() { return _a_region; } 46.56 }; 46.57 @@ -242,30 +230,15 @@ 46.58 TraceTime tm("phase 2", PrintGC && Verbose, true, gclog_or_tty); 46.59 GenMarkSweep::trace("2"); 46.60 46.61 - // First we compact the popular regions. 46.62 - if (G1NumPopularRegions > 0) { 46.63 - CompactibleSpace* sp = g1h->first_compactible_space(); 46.64 - FindFirstRegionClosure cl(true /*find_popular*/); 46.65 - g1h->heap_region_iterate(&cl); 46.66 - HeapRegion *r = cl.result(); 46.67 - assert(r->popular(), "should have found a popular region."); 46.68 - assert(r == sp, "first popular heap region should " 46.69 - "== first compactible space"); 46.70 - G1PrepareCompactClosure blk(sp, true/*popular_only*/); 46.71 - g1h->heap_region_iterate(&blk); 46.72 - } 46.73 - 46.74 - // Now we do the regular regions. 46.75 - FindFirstRegionClosure cl(false /*find_popular*/); 46.76 + FindFirstRegionClosure cl; 46.77 g1h->heap_region_iterate(&cl); 46.78 HeapRegion *r = cl.result(); 46.79 - assert(!r->popular(), "should have founda non-popular region."); 46.80 CompactibleSpace* sp = r; 46.81 if (r->isHumongous() && oop(r->bottom())->is_gc_marked()) { 46.82 sp = r->next_compaction_space(); 46.83 } 46.84 46.85 - G1PrepareCompactClosure blk(sp, false/*popular_only*/); 46.86 + G1PrepareCompactClosure blk(sp); 46.87 g1h->heap_region_iterate(&blk); 46.88 46.89 CompactPoint perm_cp(pg, NULL, NULL);
47.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp Wed Apr 01 22:31:26 2009 -0700 47.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp Thu Apr 02 17:01:00 2009 -0700 47.3 @@ -580,9 +580,7 @@ 47.4 virtual void do_oop(oop* p) { 47.5 HeapRegion* to = _g1->heap_region_containing(*p); 47.6 if (to->in_collection_set()) { 47.7 - if (to->rem_set()->add_reference(p, 0)) { 47.8 - _g1->schedule_popular_region_evac(to); 47.9 - } 47.10 + to->rem_set()->add_reference(p, 0); 47.11 } 47.12 } 47.13 }; 47.14 @@ -1024,9 +1022,8 @@ 47.15 gclog_or_tty->print_cr(" %d occupied cards represented.", 47.16 blk.occupied()); 47.17 gclog_or_tty->print_cr(" Max sz region = [" PTR_FORMAT ", " PTR_FORMAT " )" 47.18 - " %s, cap = " SIZE_FORMAT "K, occ = " SIZE_FORMAT "K.", 47.19 + ", cap = " SIZE_FORMAT "K, occ = " SIZE_FORMAT "K.", 47.20 blk.max_mem_sz_region()->bottom(), blk.max_mem_sz_region()->end(), 47.21 - (blk.max_mem_sz_region()->popular() ? "POP" : ""), 47.22 (blk.max_mem_sz_region()->rem_set()->mem_size() + K - 1)/K, 47.23 (blk.max_mem_sz_region()->rem_set()->occupied() + K - 1)/K); 47.24 gclog_or_tty->print_cr(" Did %d coarsenings.",
48.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp Wed Apr 01 22:31:26 2009 -0700 48.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp Thu Apr 02 17:01:00 2009 -0700 48.3 @@ -65,7 +65,6 @@ 48.4 HeapRegion* to = _g1->heap_region_containing(obj); 48.5 // The test below could be optimized by applying a bit op to to and from. 48.6 if (to != NULL && from != NULL && from != to) { 48.7 - bool update_delayed = false; 48.8 // There is a tricky infinite loop if we keep pushing 48.9 // self forwarding pointers onto our _new_refs list. 48.10 // The _par_traversal_in_progress flag is true during the collection pause, 48.11 @@ -77,10 +76,7 @@ 48.12 // or processed (if an evacuation failure occurs) at the end 48.13 // of the collection. 48.14 // See HRInto_G1RemSet::cleanup_after_oops_into_collection_set_do(). 48.15 - update_delayed = true; 48.16 - } 48.17 - 48.18 - if (!to->popular() && !update_delayed) { 48.19 + } else { 48.20 #if G1_REM_SET_LOGGING 48.21 gclog_or_tty->print_cr("Adding " PTR_FORMAT " (" PTR_FORMAT ") to RS" 48.22 " for region [" PTR_FORMAT ", " PTR_FORMAT ")", 48.23 @@ -88,9 +84,7 @@ 48.24 to->bottom(), to->end()); 48.25 #endif 48.26 assert(to->rem_set() != NULL, "Need per-region 'into' remsets."); 48.27 - if (to->rem_set()->add_reference(p, tid)) { 48.28 - _g1->schedule_popular_region_evac(to); 48.29 - } 48.30 + to->rem_set()->add_reference(p, tid); 48.31 } 48.32 } 48.33 }
49.1 --- a/src/share/vm/gc_implementation/g1/g1_globals.hpp Wed Apr 01 22:31:26 2009 -0700 49.2 +++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp Thu Apr 02 17:01:00 2009 -0700 49.3 @@ -185,15 +185,9 @@ 49.4 product(intx, G1InefficientPausePct, 80, \ 49.5 "Threshold of an 'inefficient' pauses (as % of cum efficiency.") \ 49.6 \ 49.7 - product(intx, G1RSPopLimit, 32768, \ 49.8 - "Limit that defines popularity. Should go away! XXX") \ 49.9 - \ 49.10 develop(bool, G1RSCountHisto, false, \ 49.11 "If true, print a histogram of RS occupancies after each pause") \ 49.12 \ 49.13 - product(intx, G1ObjPopLimit, 256, \ 49.14 - "Limit that defines popularity for an object.") \ 49.15 - \ 49.16 product(bool, G1TraceFileOverwrite, false, \ 49.17 "Allow the trace file to be overwritten") \ 49.18 \ 49.19 @@ -201,16 +195,6 @@ 49.20 "When > 0, print the occupancies of the <n> best and worst" \ 49.21 "regions.") \ 49.22 \ 49.23 - develop(bool, G1TracePopularity, false, \ 49.24 - "When true, provide detailed tracing of popularity.") \ 49.25 - \ 49.26 - product(bool, G1SummarizePopularity, false, \ 49.27 - "When true, provide end-of-run-summarization of popularity.") \ 49.28 - \ 49.29 - product(intx, G1NumPopularRegions, 1, \ 49.30 - "Number of regions reserved to hold popular objects. " \ 49.31 - "Should go away later.") \ 49.32 - \ 49.33 develop(bool, G1PrintParCleanupStats, false, \ 49.34 "When true, print extra stats about parallel cleanup.") \ 49.35 \
50.1 --- a/src/share/vm/gc_implementation/g1/heapRegion.cpp Wed Apr 01 22:31:26 2009 -0700 50.2 +++ b/src/share/vm/gc_implementation/g1/heapRegion.cpp Thu Apr 02 17:01:00 2009 -0700 50.3 @@ -104,7 +104,6 @@ 50.4 HeapRegion* to = _g1h->heap_region_containing(*p); 50.5 if (from != NULL && to != NULL && 50.6 from != to && 50.7 - !to->popular() && 50.8 !to->isHumongous()) { 50.9 jbyte cv_obj = *_bs->byte_for_const(_containing_obj); 50.10 jbyte cv_field = *_bs->byte_for_const(p); 50.11 @@ -285,8 +284,6 @@ 50.12 } 50.13 zero_marked_bytes(); 50.14 set_sort_index(-1); 50.15 - if ((uintptr_t)bottom() >= (uintptr_t)g1h->popular_object_boundary()) 50.16 - set_popular(false); 50.17 50.18 _offsets.resize(HeapRegion::GrainWords); 50.19 init_top_at_mark_start(); 50.20 @@ -371,7 +368,6 @@ 50.21 _next_in_special_set(NULL), _orig_end(NULL), 50.22 _claimed(InitialClaimValue), _evacuation_failed(false), 50.23 _prev_marked_bytes(0), _next_marked_bytes(0), _sort_index(-1), 50.24 - _popularity(NotPopular), 50.25 _young_type(NotYoung), _next_young_region(NULL), 50.26 _young_index_in_cset(-1), _surv_rate_group(NULL), _age_index(-1), 50.27 _rem_set(NULL), _zfs(NotZeroFilled)
51.1 --- a/src/share/vm/gc_implementation/g1/heapRegion.hpp Wed Apr 01 22:31:26 2009 -0700 51.2 +++ b/src/share/vm/gc_implementation/g1/heapRegion.hpp Thu Apr 02 17:01:00 2009 -0700 51.3 @@ -238,15 +238,6 @@ 51.4 // See "sort_index" method. -1 means is not in the array. 51.5 int _sort_index; 51.6 51.7 - // Means it has (or at least had) a very large RS, and should not be 51.8 - // considered for membership in a collection set. 51.9 - enum PopularityState { 51.10 - NotPopular, 51.11 - PopularPending, 51.12 - Popular 51.13 - }; 51.14 - PopularityState _popularity; 51.15 - 51.16 // <PREDICTION> 51.17 double _gc_efficiency; 51.18 // </PREDICTION> 51.19 @@ -433,10 +424,6 @@ 51.20 _next_in_special_set = r; 51.21 } 51.22 51.23 - bool is_reserved() { 51.24 - return popular(); 51.25 - } 51.26 - 51.27 bool is_on_free_list() { 51.28 return _is_on_free_list; 51.29 } 51.30 @@ -609,23 +596,6 @@ 51.31 init_top_at_mark_start(); 51.32 } 51.33 51.34 - bool popular() { return _popularity == Popular; } 51.35 - void set_popular(bool b) { 51.36 - if (b) { 51.37 - _popularity = Popular; 51.38 - } else { 51.39 - _popularity = NotPopular; 51.40 - } 51.41 - } 51.42 - bool popular_pending() { return _popularity == PopularPending; } 51.43 - void set_popular_pending(bool b) { 51.44 - if (b) { 51.45 - _popularity = PopularPending; 51.46 - } else { 51.47 - _popularity = NotPopular; 51.48 - } 51.49 - } 51.50 - 51.51 // <PREDICTION> 51.52 void calc_gc_efficiency(void); 51.53 double gc_efficiency() { return _gc_efficiency;}
52.1 --- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Wed Apr 01 22:31:26 2009 -0700 52.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Thu Apr 02 17:01:00 2009 -0700 52.3 @@ -188,32 +188,6 @@ 52.4 // the _outgoing_region_map. 52.5 void clear_outgoing_entries(); 52.6 52.7 -#if MAYBE 52.8 - // Audit the given card index. 52.9 - void audit_card(size_t card_num, HeapRegion* hr, u2* rc_arr, 52.10 - HeapRegionRemSet* empty_cards, size_t* one_obj_cards); 52.11 - 52.12 - // Assumes that "audit_stage1" has been called for "hr", to set up 52.13 - // "shadow" and "new_rs" appropriately. Identifies individual popular 52.14 - // objects; returns "true" if any are found. 52.15 - bool audit_find_pop(HeapRegion* hr, u2* rc_arr); 52.16 - 52.17 - // Assumes that "audit_stage1" has been called for "hr", to set up 52.18 - // "shadow" and "new_rs" appropriately. Identifies individual popular 52.19 - // objects, and determines the number of entries in "new_rs" if any such 52.20 - // popular objects are ignored. If this is sufficiently small, returns 52.21 - // "false" to indicate that a constraint should not be introduced. 52.22 - // Otherwise, returns "true" to indicate that we should go ahead with 52.23 - // adding the constraint. 52.24 - bool audit_stag(HeapRegion* hr, u2* rc_arr); 52.25 - 52.26 - 52.27 - u2* alloc_rc_array(); 52.28 - 52.29 - SeqHeapRegionRemSet* audit_post(u2* rc_arr, size_t multi_obj_crds, 52.30 - SeqHeapRegionRemSet* empty_cards); 52.31 -#endif 52.32 - 52.33 enum ParIterState { Unclaimed, Claimed, Complete }; 52.34 ParIterState _iter_state; 52.35 52.36 @@ -261,16 +235,14 @@ 52.37 52.38 /* Used in the sequential case. Returns "true" iff this addition causes 52.39 the size limit to be reached. */ 52.40 - bool add_reference(oop* from) { 52.41 + void add_reference(oop* from) { 52.42 _other_regions.add_reference(from); 52.43 - return false; 52.44 } 52.45 52.46 /* Used in the parallel case. Returns "true" iff this addition causes 52.47 the size limit to be reached. */ 52.48 - bool add_reference(oop* from, int tid) { 52.49 + void add_reference(oop* from, int tid) { 52.50 _other_regions.add_reference(from, tid); 52.51 - return false; 52.52 } 52.53 52.54 // Records the fact that the current region contains an outgoing 52.55 @@ -338,20 +310,6 @@ 52.56 } 52.57 void print() const; 52.58 52.59 -#if MAYBE 52.60 - // We are about to introduce a constraint, requiring the collection time 52.61 - // of the region owning this RS to be <= "hr", and forgetting pointers 52.62 - // from the owning region to "hr." Before doing so, examines this rem 52.63 - // set for pointers to "hr", possibly identifying some popular objects., 52.64 - // and possibly finding some cards to no longer contain pointers to "hr", 52.65 - // 52.66 - // These steps may prevent the the constraint from being necessary; in 52.67 - // which case returns a set of cards now thought to contain no pointers 52.68 - // into HR. In the normal (I assume) case, returns NULL, indicating that 52.69 - // we should go ahead and add the constraint. 52.70 - virtual SeqHeapRegionRemSet* audit(HeapRegion* hr) = 0; 52.71 -#endif 52.72 - 52.73 // Called during a stop-world phase to perform any deferred cleanups. 52.74 // The second version may be called by parallel threads after then finish 52.75 // collection work.
53.1 --- a/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp Wed Apr 01 22:31:26 2009 -0700 53.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp Thu Apr 02 17:01:00 2009 -0700 53.3 @@ -74,7 +74,6 @@ 53.4 // [first, cur) 53.5 HeapRegion* curhr = _regions.at(cur); 53.6 if (curhr->is_empty() 53.7 - && !curhr->is_reserved() 53.8 && (first == cur 53.9 || (_regions.at(cur-1)->end() == 53.10 curhr->bottom()))) { 53.11 @@ -121,35 +120,27 @@ 53.12 } 53.13 } 53.14 53.15 -void HeapRegionSeq::print_empty_runs(bool reserved_are_empty) { 53.16 +void HeapRegionSeq::print_empty_runs() { 53.17 int empty_run = 0; 53.18 int n_empty = 0; 53.19 - bool at_least_one_reserved = false; 53.20 int empty_run_start; 53.21 for (int i = 0; i < _regions.length(); i++) { 53.22 HeapRegion* r = _regions.at(i); 53.23 if (r->continuesHumongous()) continue; 53.24 - if (r->is_empty() && (reserved_are_empty || !r->is_reserved())) { 53.25 + if (r->is_empty()) { 53.26 assert(!r->isHumongous(), "H regions should not be empty."); 53.27 if (empty_run == 0) empty_run_start = i; 53.28 empty_run++; 53.29 n_empty++; 53.30 - if (r->is_reserved()) { 53.31 - at_least_one_reserved = true; 53.32 - } 53.33 } else { 53.34 if (empty_run > 0) { 53.35 gclog_or_tty->print(" %d:%d", empty_run_start, empty_run); 53.36 - if (reserved_are_empty && at_least_one_reserved) 53.37 - gclog_or_tty->print("(R)"); 53.38 empty_run = 0; 53.39 - at_least_one_reserved = false; 53.40 } 53.41 } 53.42 } 53.43 if (empty_run > 0) { 53.44 gclog_or_tty->print(" %d:%d", empty_run_start, empty_run); 53.45 - if (reserved_are_empty && at_least_one_reserved) gclog_or_tty->print("(R)"); 53.46 } 53.47 gclog_or_tty->print_cr(" [tot = %d]", n_empty); 53.48 } 53.49 @@ -193,7 +184,6 @@ 53.50 int cur = first; 53.51 while (cur >= 0 && 53.52 (_regions.at(cur)->is_empty() 53.53 - && !_regions.at(cur)->is_reserved() 53.54 && (first == cur 53.55 || (_regions.at(cur+1)->bottom() == 53.56 _regions.at(cur)->end())))) {
54.1 --- a/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp Wed Apr 01 22:31:26 2009 -0700 54.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp Thu Apr 02 17:01:00 2009 -0700 54.3 @@ -104,8 +104,7 @@ 54.4 54.5 void print(); 54.6 54.7 - // Prints out runs of empty regions. If the arg is "true" reserved 54.8 - // (popular regions are considered "empty". 54.9 - void print_empty_runs(bool reserved_are_empty); 54.10 + // Prints out runs of empty regions. 54.11 + void print_empty_runs(); 54.12 54.13 };
55.1 --- a/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Wed Apr 01 22:31:26 2009 -0700 55.2 +++ b/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Thu Apr 02 17:01:00 2009 -0700 55.3 @@ -43,16 +43,9 @@ 55.4 JvmtiGCForAllocationMarker jgcm; 55.5 G1CollectedHeap* g1h = G1CollectedHeap::heap(); 55.6 GCCauseSetter x(g1h, GCCause::_g1_inc_collection_pause); 55.7 - g1h->do_collection_pause_at_safepoint(NULL); 55.8 + g1h->do_collection_pause_at_safepoint(); 55.9 } 55.10 55.11 -void VM_G1PopRegionCollectionPause::doit() { 55.12 - JvmtiGCForAllocationMarker jgcm; 55.13 - G1CollectedHeap* g1h = G1CollectedHeap::heap(); 55.14 - g1h->do_collection_pause_at_safepoint(_pop_region); 55.15 -} 55.16 - 55.17 - 55.18 void VM_CGC_Operation::doit() { 55.19 gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); 55.20 TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
56.1 --- a/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp Wed Apr 01 22:31:26 2009 -0700 56.2 +++ b/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp Thu Apr 02 17:01:00 2009 -0700 56.3 @@ -77,20 +77,6 @@ 56.4 } 56.5 }; 56.6 56.7 -class VM_G1PopRegionCollectionPause: public VM_GC_Operation { 56.8 - HeapRegion* _pop_region; 56.9 - public: 56.10 - VM_G1PopRegionCollectionPause(int gc_count_before, HeapRegion* pop_region) : 56.11 - VM_GC_Operation(gc_count_before), 56.12 - _pop_region(pop_region) 56.13 - {} 56.14 - virtual VMOp_Type type() const { return VMOp_G1PopRegionCollectionPause; } 56.15 - virtual void doit(); 56.16 - virtual const char* name() const { 56.17 - return "garbage-first popular region collection pause"; 56.18 - } 56.19 -}; 56.20 - 56.21 // Concurrent GC stop-the-world operations such as initial and final mark; 56.22 // consider sharing these with CMS's counterparts. 56.23 class VM_CGC_Operation: public VM_Operation {
57.1 --- a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Wed Apr 01 22:31:26 2009 -0700 57.2 +++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Thu Apr 02 17:01:00 2009 -0700 57.3 @@ -36,7 +36,7 @@ 57.4 ObjToScanQueueSet* work_queue_set_, 57.5 size_t desired_plab_sz_, 57.6 ParallelTaskTerminator& term_) : 57.7 - _to_space(to_space_), _old_gen(old_gen_), _thread_num(thread_num_), 57.8 + _to_space(to_space_), _old_gen(old_gen_), _young_gen(gen_), _thread_num(thread_num_), 57.9 _work_queue(work_queue_set_->queue(thread_num_)), _to_space_full(false), 57.10 _ageTable(false), // false ==> not the global age table, no perf data. 57.11 _to_space_alloc_buffer(desired_plab_sz_), 57.12 @@ -57,6 +57,11 @@ 57.13 _start = os::elapsedTime(); 57.14 _old_gen_closure.set_generation(old_gen_); 57.15 _old_gen_root_closure.set_generation(old_gen_); 57.16 + if (UseCompressedOops) { 57.17 + _overflow_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(512, true); 57.18 + } else { 57.19 + _overflow_stack = NULL; 57.20 + } 57.21 } 57.22 #ifdef _MSC_VER 57.23 #pragma warning( pop ) 57.24 @@ -81,7 +86,7 @@ 57.25 assert(old->is_objArray(), "must be obj array"); 57.26 assert(old->is_forwarded(), "must be forwarded"); 57.27 assert(Universe::heap()->is_in_reserved(old), "must be in heap."); 57.28 - assert(!_old_gen->is_in(old), "must be in young generation."); 57.29 + assert(!old_gen()->is_in(old), "must be in young generation."); 57.30 57.31 objArrayOop obj = objArrayOop(old->forwardee()); 57.32 // Process ParGCArrayScanChunk elements now 57.33 @@ -119,26 +124,68 @@ 57.34 57.35 void ParScanThreadState::trim_queues(int max_size) { 57.36 ObjToScanQueue* queue = work_queue(); 57.37 - while (queue->size() > (juint)max_size) { 57.38 - oop obj_to_scan; 57.39 - if (queue->pop_local(obj_to_scan)) { 57.40 - note_pop(); 57.41 - 57.42 - if ((HeapWord *)obj_to_scan < young_old_boundary()) { 57.43 - if (obj_to_scan->is_objArray() && 57.44 - obj_to_scan->is_forwarded() && 57.45 - obj_to_scan->forwardee() != obj_to_scan) { 57.46 - scan_partial_array_and_push_remainder(obj_to_scan); 57.47 + do { 57.48 + while (queue->size() > (juint)max_size) { 57.49 + oop obj_to_scan; 57.50 + if (queue->pop_local(obj_to_scan)) { 57.51 + note_pop(); 57.52 + if ((HeapWord *)obj_to_scan < young_old_boundary()) { 57.53 + if (obj_to_scan->is_objArray() && 57.54 + obj_to_scan->is_forwarded() && 57.55 + obj_to_scan->forwardee() != obj_to_scan) { 57.56 + scan_partial_array_and_push_remainder(obj_to_scan); 57.57 + } else { 57.58 + // object is in to_space 57.59 + obj_to_scan->oop_iterate(&_to_space_closure); 57.60 + } 57.61 } else { 57.62 - // object is in to_space 57.63 - obj_to_scan->oop_iterate(&_to_space_closure); 57.64 + // object is in old generation 57.65 + obj_to_scan->oop_iterate(&_old_gen_closure); 57.66 } 57.67 - } else { 57.68 - // object is in old generation 57.69 - obj_to_scan->oop_iterate(&_old_gen_closure); 57.70 } 57.71 } 57.72 + // For the case of compressed oops, we have a private, non-shared 57.73 + // overflow stack, so we eagerly drain it so as to more evenly 57.74 + // distribute load early. Note: this may be good to do in 57.75 + // general rather than delay for the final stealing phase. 57.76 + // If applicable, we'll transfer a set of objects over to our 57.77 + // work queue, allowing them to be stolen and draining our 57.78 + // private overflow stack. 57.79 + } while (ParGCTrimOverflow && young_gen()->take_from_overflow_list(this)); 57.80 +} 57.81 + 57.82 +bool ParScanThreadState::take_from_overflow_stack() { 57.83 + assert(UseCompressedOops, "Else should not call"); 57.84 + assert(young_gen()->overflow_list() == NULL, "Error"); 57.85 + ObjToScanQueue* queue = work_queue(); 57.86 + GrowableArray<oop>* of_stack = overflow_stack(); 57.87 + uint num_overflow_elems = of_stack->length(); 57.88 + uint num_take_elems = MIN2(MIN2((queue->max_elems() - queue->size())/4, 57.89 + (juint)ParGCDesiredObjsFromOverflowList), 57.90 + num_overflow_elems); 57.91 + // Transfer the most recent num_take_elems from the overflow 57.92 + // stack to our work queue. 57.93 + for (size_t i = 0; i != num_take_elems; i++) { 57.94 + oop cur = of_stack->pop(); 57.95 + oop obj_to_push = cur->forwardee(); 57.96 + assert(Universe::heap()->is_in_reserved(cur), "Should be in heap"); 57.97 + assert(!old_gen()->is_in_reserved(cur), "Should be in young gen"); 57.98 + assert(Universe::heap()->is_in_reserved(obj_to_push), "Should be in heap"); 57.99 + if (should_be_partially_scanned(obj_to_push, cur)) { 57.100 + assert(arrayOop(cur)->length() == 0, "entire array remaining to be scanned"); 57.101 + obj_to_push = cur; 57.102 + } 57.103 + bool ok = queue->push(obj_to_push); 57.104 + assert(ok, "Should have succeeded"); 57.105 } 57.106 + assert(young_gen()->overflow_list() == NULL, "Error"); 57.107 + return num_take_elems > 0; // was something transferred? 57.108 +} 57.109 + 57.110 +void ParScanThreadState::push_on_overflow_stack(oop p) { 57.111 + assert(UseCompressedOops, "Else should not call"); 57.112 + overflow_stack()->push(p); 57.113 + assert(young_gen()->overflow_list() == NULL, "Error"); 57.114 } 57.115 57.116 HeapWord* ParScanThreadState::alloc_in_to_space_slow(size_t word_sz) { 57.117 @@ -425,8 +472,7 @@ 57.118 ResourceMark rm; 57.119 HandleMark hm; 57.120 // We would need multiple old-gen queues otherwise. 57.121 - guarantee(gch->n_gens() == 2, 57.122 - "Par young collection currently only works with one older gen."); 57.123 + assert(gch->n_gens() == 2, "Par young collection currently only works with one older gen."); 57.124 57.125 Generation* old_gen = gch->next_gen(_gen); 57.126 57.127 @@ -1169,36 +1215,75 @@ 57.128 } 57.129 #endif 57.130 57.131 +// In case we are using compressed oops, we need to be careful. 57.132 +// If the object being pushed is an object array, then its length 57.133 +// field keeps track of the "grey boundary" at which the next 57.134 +// incremental scan will be done (see ParGCArrayScanChunk). 57.135 +// When using compressed oops, this length field is kept in the 57.136 +// lower 32 bits of the erstwhile klass word and cannot be used 57.137 +// for the overflow chaining pointer (OCP below). As such the OCP 57.138 +// would itself need to be compressed into the top 32-bits in this 57.139 +// case. Unfortunately, see below, in the event that we have a 57.140 +// promotion failure, the node to be pushed on the list can be 57.141 +// outside of the Java heap, so the heap-based pointer compression 57.142 +// would not work (we would have potential aliasing between C-heap 57.143 +// and Java-heap pointers). For this reason, when using compressed 57.144 +// oops, we simply use a worker-thread-local, non-shared overflow 57.145 +// list in the form of a growable array, with a slightly different 57.146 +// overflow stack draining strategy. If/when we start using fat 57.147 +// stacks here, we can go back to using (fat) pointer chains 57.148 +// (although some performance comparisons would be useful since 57.149 +// single global lists have their own performance disadvantages 57.150 +// as we were made painfully aware not long ago, see 6786503). 57.151 #define BUSY (oop(0x1aff1aff)) 57.152 void ParNewGeneration::push_on_overflow_list(oop from_space_obj, ParScanThreadState* par_scan_state) { 57.153 - // if the object has been forwarded to itself, then we cannot 57.154 - // use the klass pointer for the linked list. Instead we have 57.155 - // to allocate an oopDesc in the C-Heap and use that for the linked list. 57.156 - // XXX This is horribly inefficient when a promotion failure occurs 57.157 - // and should be fixed. XXX FIX ME !!! 57.158 + assert(is_in_reserved(from_space_obj), "Should be from this generation"); 57.159 + if (UseCompressedOops) { 57.160 + // In the case of compressed oops, we use a private, not-shared 57.161 + // overflow stack. 57.162 + par_scan_state->push_on_overflow_stack(from_space_obj); 57.163 + } else { 57.164 + // if the object has been forwarded to itself, then we cannot 57.165 + // use the klass pointer for the linked list. Instead we have 57.166 + // to allocate an oopDesc in the C-Heap and use that for the linked list. 57.167 + // XXX This is horribly inefficient when a promotion failure occurs 57.168 + // and should be fixed. XXX FIX ME !!! 57.169 #ifndef PRODUCT 57.170 - Atomic::inc_ptr(&_num_par_pushes); 57.171 - assert(_num_par_pushes > 0, "Tautology"); 57.172 + Atomic::inc_ptr(&_num_par_pushes); 57.173 + assert(_num_par_pushes > 0, "Tautology"); 57.174 #endif 57.175 - if (from_space_obj->forwardee() == from_space_obj) { 57.176 - oopDesc* listhead = NEW_C_HEAP_ARRAY(oopDesc, 1); 57.177 - listhead->forward_to(from_space_obj); 57.178 - from_space_obj = listhead; 57.179 + if (from_space_obj->forwardee() == from_space_obj) { 57.180 + oopDesc* listhead = NEW_C_HEAP_ARRAY(oopDesc, 1); 57.181 + listhead->forward_to(from_space_obj); 57.182 + from_space_obj = listhead; 57.183 + } 57.184 + oop observed_overflow_list = _overflow_list; 57.185 + oop cur_overflow_list; 57.186 + do { 57.187 + cur_overflow_list = observed_overflow_list; 57.188 + if (cur_overflow_list != BUSY) { 57.189 + from_space_obj->set_klass_to_list_ptr(cur_overflow_list); 57.190 + } else { 57.191 + from_space_obj->set_klass_to_list_ptr(NULL); 57.192 + } 57.193 + observed_overflow_list = 57.194 + (oop)Atomic::cmpxchg_ptr(from_space_obj, &_overflow_list, cur_overflow_list); 57.195 + } while (cur_overflow_list != observed_overflow_list); 57.196 } 57.197 - oop observed_overflow_list = _overflow_list; 57.198 - oop cur_overflow_list; 57.199 - do { 57.200 - cur_overflow_list = observed_overflow_list; 57.201 - if (cur_overflow_list != BUSY) { 57.202 - from_space_obj->set_klass_to_list_ptr(cur_overflow_list); 57.203 - } else { 57.204 - from_space_obj->set_klass_to_list_ptr(NULL); 57.205 - } 57.206 - observed_overflow_list = 57.207 - (oop)Atomic::cmpxchg_ptr(from_space_obj, &_overflow_list, cur_overflow_list); 57.208 - } while (cur_overflow_list != observed_overflow_list); 57.209 } 57.210 57.211 +bool ParNewGeneration::take_from_overflow_list(ParScanThreadState* par_scan_state) { 57.212 + bool res; 57.213 + 57.214 + if (UseCompressedOops) { 57.215 + res = par_scan_state->take_from_overflow_stack(); 57.216 + } else { 57.217 + res = take_from_overflow_list_work(par_scan_state); 57.218 + } 57.219 + return res; 57.220 +} 57.221 + 57.222 + 57.223 // *NOTE*: The overflow list manipulation code here and 57.224 // in CMSCollector:: are very similar in shape, 57.225 // except that in the CMS case we thread the objects 57.226 @@ -1213,14 +1298,13 @@ 57.227 // similar changes might be needed. 57.228 // See CMSCollector::par_take_from_overflow_list() for 57.229 // more extensive documentation comments. 57.230 -bool 57.231 -ParNewGeneration::take_from_overflow_list(ParScanThreadState* par_scan_state) { 57.232 +bool ParNewGeneration::take_from_overflow_list_work(ParScanThreadState* par_scan_state) { 57.233 ObjToScanQueue* work_q = par_scan_state->work_queue(); 57.234 - assert(work_q->size() == 0, "Should first empty local work queue"); 57.235 // How many to take? 57.236 - size_t objsFromOverflow = MIN2((size_t)work_q->max_elems()/4, 57.237 + size_t objsFromOverflow = MIN2((size_t)(work_q->max_elems() - work_q->size())/4, 57.238 (size_t)ParGCDesiredObjsFromOverflowList); 57.239 57.240 + assert(par_scan_state->overflow_stack() == NULL, "Error"); 57.241 if (_overflow_list == NULL) return false; 57.242 57.243 // Otherwise, there was something there; try claiming the list.
58.1 --- a/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Wed Apr 01 22:31:26 2009 -0700 58.2 +++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Thu Apr 02 17:01:00 2009 -0700 58.3 @@ -55,6 +55,7 @@ 58.4 friend class ParScanThreadStateSet; 58.5 private: 58.6 ObjToScanQueue *_work_queue; 58.7 + GrowableArray<oop>* _overflow_stack; 58.8 58.9 ParGCAllocBuffer _to_space_alloc_buffer; 58.10 58.11 @@ -79,6 +80,9 @@ 58.12 Space* _to_space; 58.13 Space* to_space() { return _to_space; } 58.14 58.15 + ParNewGeneration* _young_gen; 58.16 + ParNewGeneration* young_gen() const { return _young_gen; } 58.17 + 58.18 Generation* _old_gen; 58.19 Generation* old_gen() { return _old_gen; } 58.20 58.21 @@ -134,6 +138,11 @@ 58.22 // Decrease queue size below "max_size". 58.23 void trim_queues(int max_size); 58.24 58.25 + // Private overflow stack usage 58.26 + GrowableArray<oop>* overflow_stack() { return _overflow_stack; } 58.27 + bool take_from_overflow_stack(); 58.28 + void push_on_overflow_stack(oop p); 58.29 + 58.30 // Is new_obj a candidate for scan_partial_array_and_push_remainder method. 58.31 inline bool should_be_partially_scanned(oop new_obj, oop old_obj) const; 58.32 58.33 @@ -378,13 +387,17 @@ 58.34 NOT_PRODUCT(int _overflow_counter;) 58.35 NOT_PRODUCT(bool should_simulate_overflow();) 58.36 58.37 + // Accessor for overflow list 58.38 + oop overflow_list() { return _overflow_list; } 58.39 + 58.40 // Push the given (from-space) object on the global overflow list. 58.41 void push_on_overflow_list(oop from_space_obj, ParScanThreadState* par_scan_state); 58.42 58.43 // If the global overflow list is non-empty, move some tasks from it 58.44 - // onto "work_q" (which must be empty). No more than 1/4 of the 58.45 - // max_elems of "work_q" are moved. 58.46 + // onto "work_q" (which need not be empty). No more than 1/4 of the 58.47 + // available space on "work_q" is used. 58.48 bool take_from_overflow_list(ParScanThreadState* par_scan_state); 58.49 + bool take_from_overflow_list_work(ParScanThreadState* par_scan_state); 58.50 58.51 // The task queues to be used by parallel GC threads. 58.52 ObjToScanQueueSet* task_queues() {
59.1 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Wed Apr 01 22:31:26 2009 -0700 59.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Thu Apr 02 17:01:00 2009 -0700 59.3 @@ -1,5 +1,5 @@ 59.4 /* 59.5 - * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. 59.6 + * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. 59.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 59.8 * 59.9 * This code is free software; you can redistribute it and/or modify it 59.10 @@ -825,6 +825,7 @@ 59.11 if (young_gen()->is_in_reserved(addr)) { 59.12 assert(young_gen()->is_in(addr), 59.13 "addr should be in allocated part of young gen"); 59.14 + if (Debugging) return NULL; // called from find() in debug.cpp 59.15 Unimplemented(); 59.16 } else if (old_gen()->is_in_reserved(addr)) { 59.17 assert(old_gen()->is_in(addr),
60.1 --- a/src/share/vm/gc_interface/gcCause.hpp Wed Apr 01 22:31:26 2009 -0700 60.2 +++ b/src/share/vm/gc_interface/gcCause.hpp Thu Apr 02 17:01:00 2009 -0700 60.3 @@ -60,7 +60,7 @@ 60.4 _old_generation_too_full_to_scavenge, 60.5 _adaptive_size_policy, 60.6 60.7 - _g1_inc_collection_pause, _g1_pop_region_collection_pause, 60.8 + _g1_inc_collection_pause, 60.9 60.10 _last_ditch_collection, 60.11 _last_gc_cause
61.1 --- a/src/share/vm/includeDB_core Wed Apr 01 22:31:26 2009 -0700 61.2 +++ b/src/share/vm/includeDB_core Thu Apr 02 17:01:00 2009 -0700 61.3 @@ -3154,6 +3154,8 @@ 61.4 oopsHierarchy.cpp thread_<os_family>.inline.hpp 61.5 61.6 orderAccess.cpp orderAccess.hpp 61.7 +orderAccess.cpp stubRoutines.hpp 61.8 +orderAccess.cpp thread.hpp 61.9 61.10 orderAccess.hpp allocation.hpp 61.11 orderAccess.hpp os.hpp
62.1 --- a/src/share/vm/oops/instanceKlass.cpp Wed Apr 01 22:31:26 2009 -0700 62.2 +++ b/src/share/vm/oops/instanceKlass.cpp Thu Apr 02 17:01:00 2009 -0700 62.3 @@ -1,5 +1,5 @@ 62.4 /* 62.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 62.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 62.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 62.8 * 62.9 * This code is free software; you can redistribute it and/or modify it 62.10 @@ -1813,6 +1813,8 @@ 62.11 oop class_loader2, symbolOop class_name2) { 62.12 if (class_loader1 != class_loader2) { 62.13 return false; 62.14 + } else if (class_name1 == class_name2) { 62.15 + return true; // skip painful bytewise comparison 62.16 } else { 62.17 ResourceMark rm; 62.18 62.19 @@ -1879,6 +1881,56 @@ 62.20 return(is_same_class_package(targetclassloader(), targetclassname())); 62.21 } 62.22 62.23 +/* defined for now in jvm.cpp, for historical reasons *-- 62.24 +klassOop instanceKlass::compute_enclosing_class_impl(instanceKlassHandle self, 62.25 + symbolOop& simple_name_result, TRAPS) { 62.26 + ... 62.27 +} 62.28 +*/ 62.29 + 62.30 +// tell if two classes have the same enclosing class (at package level) 62.31 +bool instanceKlass::is_same_package_member_impl(instanceKlassHandle class1, 62.32 + klassOop class2_oop, TRAPS) { 62.33 + if (class2_oop == class1->as_klassOop()) return true; 62.34 + if (!Klass::cast(class2_oop)->oop_is_instance()) return false; 62.35 + instanceKlassHandle class2(THREAD, class2_oop); 62.36 + 62.37 + // must be in same package before we try anything else 62.38 + if (!class1->is_same_class_package(class2->class_loader(), class2->name())) 62.39 + return false; 62.40 + 62.41 + // As long as there is an outer1.getEnclosingClass, 62.42 + // shift the search outward. 62.43 + instanceKlassHandle outer1 = class1; 62.44 + for (;;) { 62.45 + // As we walk along, look for equalities between outer1 and class2. 62.46 + // Eventually, the walks will terminate as outer1 stops 62.47 + // at the top-level class around the original class. 62.48 + symbolOop ignore_name; 62.49 + klassOop next = outer1->compute_enclosing_class(ignore_name, CHECK_false); 62.50 + if (next == NULL) break; 62.51 + if (next == class2()) return true; 62.52 + outer1 = instanceKlassHandle(THREAD, next); 62.53 + } 62.54 + 62.55 + // Now do the same for class2. 62.56 + instanceKlassHandle outer2 = class2; 62.57 + for (;;) { 62.58 + symbolOop ignore_name; 62.59 + klassOop next = outer2->compute_enclosing_class(ignore_name, CHECK_false); 62.60 + if (next == NULL) break; 62.61 + // Might as well check the new outer against all available values. 62.62 + if (next == class1()) return true; 62.63 + if (next == outer1()) return true; 62.64 + outer2 = instanceKlassHandle(THREAD, next); 62.65 + } 62.66 + 62.67 + // If by this point we have not found an equality between the 62.68 + // two classes, we know they are in separate package members. 62.69 + return false; 62.70 +} 62.71 + 62.72 + 62.73 jint instanceKlass::compute_modifier_flags(TRAPS) const { 62.74 klassOop k = as_klassOop(); 62.75 jint access = access_flags().as_int(); 62.76 @@ -2015,9 +2067,11 @@ 62.77 62.78 // Printing 62.79 62.80 +#define BULLET " - " 62.81 + 62.82 void FieldPrinter::do_field(fieldDescriptor* fd) { 62.83 - if (fd->is_static() == (_obj == NULL)) { 62.84 - _st->print(" - "); 62.85 + _st->print(BULLET); 62.86 + if (fd->is_static() || (_obj == NULL)) { 62.87 fd->print_on(_st); 62.88 _st->cr(); 62.89 } else { 62.90 @@ -2038,7 +2092,7 @@ 62.91 value->is_typeArray() && 62.92 offset <= (juint) value->length() && 62.93 offset + length <= (juint) value->length()) { 62.94 - st->print("string: "); 62.95 + st->print(BULLET"string: "); 62.96 Handle h_obj(obj); 62.97 java_lang_String::print(h_obj, st); 62.98 st->cr(); 62.99 @@ -2046,23 +2100,26 @@ 62.100 } 62.101 } 62.102 62.103 - st->print_cr("fields:"); 62.104 + st->print_cr(BULLET"---- fields (total size %d words):", oop_size(obj)); 62.105 FieldPrinter print_nonstatic_field(st, obj); 62.106 do_nonstatic_fields(&print_nonstatic_field); 62.107 62.108 if (as_klassOop() == SystemDictionary::class_klass()) { 62.109 + st->print(BULLET"signature: "); 62.110 + java_lang_Class::print_signature(obj, st); 62.111 + st->cr(); 62.112 klassOop mirrored_klass = java_lang_Class::as_klassOop(obj); 62.113 - st->print(" - fake entry for mirror: "); 62.114 + st->print(BULLET"fake entry for mirror: "); 62.115 mirrored_klass->print_value_on(st); 62.116 st->cr(); 62.117 - st->print(" - fake entry resolved_constructor: "); 62.118 + st->print(BULLET"fake entry resolved_constructor: "); 62.119 methodOop ctor = java_lang_Class::resolved_constructor(obj); 62.120 ctor->print_value_on(st); 62.121 klassOop array_klass = java_lang_Class::array_klass(obj); 62.122 - st->print(" - fake entry for array: "); 62.123 + st->cr(); 62.124 + st->print(BULLET"fake entry for array: "); 62.125 array_klass->print_value_on(st); 62.126 st->cr(); 62.127 - st->cr(); 62.128 } 62.129 } 62.130 62.131 @@ -2070,6 +2127,28 @@ 62.132 st->print("a "); 62.133 name()->print_value_on(st); 62.134 obj->print_address_on(st); 62.135 + if (as_klassOop() == SystemDictionary::string_klass() 62.136 + && java_lang_String::value(obj) != NULL) { 62.137 + ResourceMark rm; 62.138 + int len = java_lang_String::length(obj); 62.139 + int plen = (len < 24 ? len : 12); 62.140 + char* str = java_lang_String::as_utf8_string(obj, 0, plen); 62.141 + st->print(" = \"%s\"", str); 62.142 + if (len > plen) 62.143 + st->print("...[%d]", len); 62.144 + } else if (as_klassOop() == SystemDictionary::class_klass()) { 62.145 + klassOop k = java_lang_Class::as_klassOop(obj); 62.146 + st->print(" = "); 62.147 + if (k != NULL) { 62.148 + k->print_value_on(st); 62.149 + } else { 62.150 + const char* tname = type2name(java_lang_Class::primitive_type(obj)); 62.151 + st->print("%s", tname ? tname : "type?"); 62.152 + } 62.153 + } else if (java_lang_boxing_object::is_instance(obj)) { 62.154 + st->print(" = "); 62.155 + java_lang_boxing_object::print(obj, st); 62.156 + } 62.157 } 62.158 62.159 #endif // ndef PRODUCT
63.1 --- a/src/share/vm/oops/instanceKlass.hpp Wed Apr 01 22:31:26 2009 -0700 63.2 +++ b/src/share/vm/oops/instanceKlass.hpp Thu Apr 02 17:01:00 2009 -0700 63.3 @@ -1,5 +1,5 @@ 63.4 /* 63.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 63.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 63.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 63.8 * 63.9 * This code is free software; you can redistribute it and/or modify it 63.10 @@ -311,6 +311,22 @@ 63.11 bool is_same_class_package(oop classloader2, symbolOop classname2); 63.12 static bool is_same_class_package(oop class_loader1, symbolOop class_name1, oop class_loader2, symbolOop class_name2); 63.13 63.14 + // find an enclosing class (defined where original code was, in jvm.cpp!) 63.15 + klassOop compute_enclosing_class(symbolOop& simple_name_result, TRAPS) { 63.16 + instanceKlassHandle self(THREAD, this->as_klassOop()); 63.17 + return compute_enclosing_class_impl(self, simple_name_result, THREAD); 63.18 + } 63.19 + static klassOop compute_enclosing_class_impl(instanceKlassHandle self, 63.20 + symbolOop& simple_name_result, TRAPS); 63.21 + 63.22 + // tell if two classes have the same enclosing class (at package level) 63.23 + bool is_same_package_member(klassOop class2, TRAPS) { 63.24 + instanceKlassHandle self(THREAD, this->as_klassOop()); 63.25 + return is_same_package_member_impl(self, class2, THREAD); 63.26 + } 63.27 + static bool is_same_package_member_impl(instanceKlassHandle self, 63.28 + klassOop class2, TRAPS); 63.29 + 63.30 // initialization state 63.31 bool is_loaded() const { return _init_state >= loaded; } 63.32 bool is_linked() const { return _init_state >= linked; }
64.1 --- a/src/share/vm/oops/instanceKlassKlass.cpp Wed Apr 01 22:31:26 2009 -0700 64.2 +++ b/src/share/vm/oops/instanceKlassKlass.cpp Thu Apr 02 17:01:00 2009 -0700 64.3 @@ -1,5 +1,5 @@ 64.4 /* 64.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 64.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 64.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 64.8 * 64.9 * This code is free software; you can redistribute it and/or modify it 64.10 @@ -487,6 +487,8 @@ 64.11 64.12 // Printing 64.13 64.14 +#define BULLET " - " 64.15 + 64.16 static const char* state_names[] = { 64.17 "unparseable_by_gc", "allocated", "loaded", "linked", "being_initialized", "fully_initialized", "initialization_error" 64.18 }; 64.19 @@ -497,13 +499,13 @@ 64.20 instanceKlass* ik = instanceKlass::cast(klassOop(obj)); 64.21 klassKlass::oop_print_on(obj, st); 64.22 64.23 - st->print(" - instance size: %d", ik->size_helper()); st->cr(); 64.24 - st->print(" - klass size: %d", ik->object_size()); st->cr(); 64.25 - st->print(" - access: "); ik->access_flags().print_on(st); st->cr(); 64.26 - st->print(" - state: "); st->print_cr(state_names[ik->_init_state]); 64.27 - st->print(" - name: "); ik->name()->print_value_on(st); st->cr(); 64.28 - st->print(" - super: "); ik->super()->print_value_on(st); st->cr(); 64.29 - st->print(" - sub: "); 64.30 + st->print(BULLET"instance size: %d", ik->size_helper()); st->cr(); 64.31 + st->print(BULLET"klass size: %d", ik->object_size()); st->cr(); 64.32 + st->print(BULLET"access: "); ik->access_flags().print_on(st); st->cr(); 64.33 + st->print(BULLET"state: "); st->print_cr(state_names[ik->_init_state]); 64.34 + st->print(BULLET"name: "); ik->name()->print_value_on(st); st->cr(); 64.35 + st->print(BULLET"super: "); ik->super()->print_value_on(st); st->cr(); 64.36 + st->print(BULLET"sub: "); 64.37 Klass* sub = ik->subklass(); 64.38 int n; 64.39 for (n = 0; sub != NULL; n++, sub = sub->next_sibling()) { 64.40 @@ -516,12 +518,12 @@ 64.41 st->cr(); 64.42 64.43 if (ik->is_interface()) { 64.44 - st->print_cr(" - nof implementors: %d", ik->nof_implementors()); 64.45 + st->print_cr(BULLET"nof implementors: %d", ik->nof_implementors()); 64.46 int print_impl = 0; 64.47 for (int i = 0; i < instanceKlass::implementors_limit; i++) { 64.48 if (ik->implementor(i) != NULL) { 64.49 if (++print_impl == 1) 64.50 - st->print_cr(" - implementor: "); 64.51 + st->print_cr(BULLET"implementor: "); 64.52 st->print(" "); 64.53 ik->implementor(i)->print_value_on(st); 64.54 } 64.55 @@ -529,34 +531,33 @@ 64.56 if (print_impl > 0) st->cr(); 64.57 } 64.58 64.59 - st->print(" - arrays: "); ik->array_klasses()->print_value_on(st); st->cr(); 64.60 - st->print(" - methods: "); ik->methods()->print_value_on(st); st->cr(); 64.61 + st->print(BULLET"arrays: "); ik->array_klasses()->print_value_on(st); st->cr(); 64.62 + st->print(BULLET"methods: "); ik->methods()->print_value_on(st); st->cr(); 64.63 if (Verbose) { 64.64 objArrayOop methods = ik->methods(); 64.65 for(int i = 0; i < methods->length(); i++) { 64.66 tty->print("%d : ", i); methods->obj_at(i)->print_value(); tty->cr(); 64.67 } 64.68 } 64.69 - st->print(" - method ordering: "); ik->method_ordering()->print_value_on(st); st->cr(); 64.70 - st->print(" - local interfaces: "); ik->local_interfaces()->print_value_on(st); st->cr(); 64.71 - st->print(" - trans. interfaces: "); ik->transitive_interfaces()->print_value_on(st); st->cr(); 64.72 - st->print(" - constants: "); ik->constants()->print_value_on(st); st->cr(); 64.73 - st->print(" - class loader: "); ik->class_loader()->print_value_on(st); st->cr(); 64.74 - st->print(" - protection domain: "); ik->protection_domain()->print_value_on(st); st->cr(); 64.75 - st->print(" - host class: "); ik->host_klass()->print_value_on(st); st->cr(); 64.76 - st->print(" - signers: "); ik->signers()->print_value_on(st); st->cr(); 64.77 + st->print(BULLET"method ordering: "); ik->method_ordering()->print_value_on(st); st->cr(); 64.78 + st->print(BULLET"local interfaces: "); ik->local_interfaces()->print_value_on(st); st->cr(); 64.79 + st->print(BULLET"trans. interfaces: "); ik->transitive_interfaces()->print_value_on(st); st->cr(); 64.80 + st->print(BULLET"constants: "); ik->constants()->print_value_on(st); st->cr(); 64.81 + st->print(BULLET"class loader: "); ik->class_loader()->print_value_on(st); st->cr(); 64.82 + st->print(BULLET"protection domain: "); ik->protection_domain()->print_value_on(st); st->cr(); 64.83 + st->print(BULLET"host class: "); ik->host_klass()->print_value_on(st); st->cr(); 64.84 + st->print(BULLET"signers: "); ik->signers()->print_value_on(st); st->cr(); 64.85 if (ik->source_file_name() != NULL) { 64.86 - st->print(" - source file: "); 64.87 + st->print(BULLET"source file: "); 64.88 ik->source_file_name()->print_value_on(st); 64.89 st->cr(); 64.90 } 64.91 if (ik->source_debug_extension() != NULL) { 64.92 - st->print(" - source debug extension: "); 64.93 + st->print(BULLET"source debug extension: "); 64.94 ik->source_debug_extension()->print_value_on(st); 64.95 st->cr(); 64.96 } 64.97 64.98 - st->print_cr(" - previous version: "); 64.99 { 64.100 ResourceMark rm; 64.101 // PreviousVersionInfo objects returned via PreviousVersionWalker 64.102 @@ -564,38 +565,43 @@ 64.103 // GrowableArray _after_ the PreviousVersionWalker destructor 64.104 // has destroyed the handles. 64.105 { 64.106 + bool have_pv = false; 64.107 PreviousVersionWalker pvw(ik); 64.108 for (PreviousVersionInfo * pv_info = pvw.next_previous_version(); 64.109 pv_info != NULL; pv_info = pvw.next_previous_version()) { 64.110 + if (!have_pv) 64.111 + st->print(BULLET"previous version: "); 64.112 + have_pv = true; 64.113 pv_info->prev_constant_pool_handle()()->print_value_on(st); 64.114 } 64.115 - st->cr(); 64.116 + if (have_pv) st->cr(); 64.117 } // pvw is cleaned up 64.118 } // rm is cleaned up 64.119 64.120 if (ik->generic_signature() != NULL) { 64.121 - st->print(" - generic signature: "); 64.122 + st->print(BULLET"generic signature: "); 64.123 ik->generic_signature()->print_value_on(st); 64.124 + st->cr(); 64.125 } 64.126 - st->print(" - inner classes: "); ik->inner_classes()->print_value_on(st); st->cr(); 64.127 - st->print(" - java mirror: "); ik->java_mirror()->print_value_on(st); st->cr(); 64.128 - st->print(" - vtable length %d (start addr: " INTPTR_FORMAT ")", ik->vtable_length(), ik->start_of_vtable()); st->cr(); 64.129 - st->print(" - itable length %d (start addr: " INTPTR_FORMAT ")", ik->itable_length(), ik->start_of_itable()); st->cr(); 64.130 - st->print_cr(" - static fields:"); 64.131 + st->print(BULLET"inner classes: "); ik->inner_classes()->print_value_on(st); st->cr(); 64.132 + st->print(BULLET"java mirror: "); ik->java_mirror()->print_value_on(st); st->cr(); 64.133 + st->print(BULLET"vtable length %d (start addr: " INTPTR_FORMAT ")", ik->vtable_length(), ik->start_of_vtable()); st->cr(); 64.134 + st->print(BULLET"itable length %d (start addr: " INTPTR_FORMAT ")", ik->itable_length(), ik->start_of_itable()); st->cr(); 64.135 + st->print_cr(BULLET"---- static fields (%d words):", ik->static_field_size()); 64.136 FieldPrinter print_static_field(st); 64.137 ik->do_local_static_fields(&print_static_field); 64.138 - st->print_cr(" - non-static fields:"); 64.139 - FieldPrinter print_nonstatic_field(st, obj); 64.140 + st->print_cr(BULLET"---- non-static fields (%d words):", ik->nonstatic_field_size()); 64.141 + FieldPrinter print_nonstatic_field(st); 64.142 ik->do_nonstatic_fields(&print_nonstatic_field); 64.143 64.144 - st->print(" - static oop maps: "); 64.145 + st->print(BULLET"static oop maps: "); 64.146 if (ik->static_oop_field_size() > 0) { 64.147 int first_offset = ik->offset_of_static_fields(); 64.148 st->print("%d-%d", first_offset, first_offset + ik->static_oop_field_size() - 1); 64.149 } 64.150 st->cr(); 64.151 64.152 - st->print(" - non-static oop maps: "); 64.153 + st->print(BULLET"non-static oop maps: "); 64.154 OopMapBlock* map = ik->start_of_nonstatic_oop_maps(); 64.155 OopMapBlock* end_map = map + ik->nonstatic_oop_map_size(); 64.156 while (map < end_map) {
65.1 --- a/src/share/vm/oops/klassVtable.cpp Wed Apr 01 22:31:26 2009 -0700 65.2 +++ b/src/share/vm/oops/klassVtable.cpp Thu Apr 02 17:01:00 2009 -0700 65.3 @@ -1,5 +1,5 @@ 65.4 /* 65.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 65.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 65.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 65.8 * 65.9 * This code is free software; you can redistribute it and/or modify it 65.10 @@ -1148,6 +1148,27 @@ 65.11 return index; 65.12 } 65.13 65.14 + 65.15 +// inverse to compute_itable_index 65.16 +methodOop klassItable::method_for_itable_index(klassOop intf, int itable_index) { 65.17 + assert(instanceKlass::cast(intf)->is_interface(), "sanity check"); 65.18 + objArrayOop methods = instanceKlass::cast(intf)->methods(); 65.19 + 65.20 + int index = itable_index; 65.21 + // Adjust for <clinit>, which is left out of table if first method 65.22 + if (methods->length() > 0 && ((methodOop)methods->obj_at(0))->name() == vmSymbols::class_initializer_name()) { 65.23 + index++; 65.24 + } 65.25 + 65.26 + if (itable_index < 0 || index >= methods->length()) 65.27 + return NULL; // help caller defend against bad indexes 65.28 + 65.29 + methodOop m = (methodOop)methods->obj_at(index); 65.30 + assert(compute_itable_index(m) == itable_index, "correct inverse"); 65.31 + 65.32 + return m; 65.33 +} 65.34 + 65.35 void klassVtable::verify(outputStream* st, bool forced) { 65.36 // make sure table is initialized 65.37 if (!Universe::is_fully_initialized()) return;
66.1 --- a/src/share/vm/oops/klassVtable.hpp Wed Apr 01 22:31:26 2009 -0700 66.2 +++ b/src/share/vm/oops/klassVtable.hpp Thu Apr 02 17:01:00 2009 -0700 66.3 @@ -1,5 +1,5 @@ 66.4 /* 66.5 - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. 66.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 66.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 66.8 * 66.9 * This code is free software; you can redistribute it and/or modify it 66.10 @@ -301,6 +301,8 @@ 66.11 66.12 // Resolving of method to index 66.13 static int compute_itable_index(methodOop m); 66.14 + // ...and back again: 66.15 + static methodOop method_for_itable_index(klassOop klass, int itable_index); 66.16 66.17 // Debugging/Statistics 66.18 static void print_statistics() PRODUCT_RETURN;
67.1 --- a/src/share/vm/oops/methodKlass.cpp Wed Apr 01 22:31:26 2009 -0700 67.2 +++ b/src/share/vm/oops/methodKlass.cpp Thu Apr 02 17:01:00 2009 -0700 67.3 @@ -1,5 +1,5 @@ 67.4 /* 67.5 - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 67.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 67.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 67.8 * 67.9 * This code is free software; you can redistribute it and/or modify it 67.10 @@ -247,9 +247,14 @@ 67.11 st->print_cr(" - size of params: %d", m->size_of_parameters()); 67.12 st->print_cr(" - method size: %d", m->method_size()); 67.13 st->print_cr(" - vtable index: %d", m->_vtable_index); 67.14 + st->print_cr(" - i2i entry: " INTPTR_FORMAT, m->interpreter_entry()); 67.15 + st->print_cr(" - adapter: " INTPTR_FORMAT, m->adapter()); 67.16 + st->print_cr(" - compiled entry " INTPTR_FORMAT, m->from_compiled_entry()); 67.17 st->print_cr(" - code size: %d", m->code_size()); 67.18 - st->print_cr(" - code start: " INTPTR_FORMAT, m->code_base()); 67.19 - st->print_cr(" - code end (excl): " INTPTR_FORMAT, m->code_base() + m->code_size()); 67.20 + if (m->code_size() != 0) { 67.21 + st->print_cr(" - code start: " INTPTR_FORMAT, m->code_base()); 67.22 + st->print_cr(" - code end (excl): " INTPTR_FORMAT, m->code_base() + m->code_size()); 67.23 + } 67.24 if (m->method_data() != NULL) { 67.25 st->print_cr(" - method data: " INTPTR_FORMAT, (address)m->method_data()); 67.26 } 67.27 @@ -293,6 +298,10 @@ 67.28 m->code()->print_value_on(st); 67.29 st->cr(); 67.30 } 67.31 + if (m->is_native()) { 67.32 + st->print_cr(" - native function: " INTPTR_FORMAT, m->native_function()); 67.33 + st->print_cr(" - signature handler: " INTPTR_FORMAT, m->signature_handler()); 67.34 + } 67.35 } 67.36 67.37
68.1 --- a/src/share/vm/oops/objArrayKlass.cpp Wed Apr 01 22:31:26 2009 -0700 68.2 +++ b/src/share/vm/oops/objArrayKlass.cpp Thu Apr 02 17:01:00 2009 -0700 68.3 @@ -1,5 +1,5 @@ 68.4 /* 68.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 68.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 68.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 68.8 * 68.9 * This code is free software; you can redistribute it and/or modify it 68.10 @@ -502,12 +502,25 @@ 68.11 } 68.12 } 68.13 68.14 +static int max_objArray_print_length = 4; 68.15 68.16 void objArrayKlass::oop_print_value_on(oop obj, outputStream* st) { 68.17 assert(obj->is_objArray(), "must be objArray"); 68.18 + st->print("a "); 68.19 element_klass()->print_value_on(st); 68.20 - st->print("a [%d] ", objArrayOop(obj)->length()); 68.21 - as_klassOop()->klass()->print_value_on(st); 68.22 + int len = objArrayOop(obj)->length(); 68.23 + st->print("[%d] ", len); 68.24 + obj->print_address_on(st); 68.25 + if (PrintOopAddress || PrintMiscellaneous && (WizardMode || Verbose)) { 68.26 + st->print("{"); 68.27 + for (int i = 0; i < len; i++) { 68.28 + if (i > max_objArray_print_length) { 68.29 + st->print("..."); break; 68.30 + } 68.31 + st->print(" "INTPTR_FORMAT, (intptr_t)(void*)objArrayOop(obj)->obj_at(i)); 68.32 + } 68.33 + st->print(" }"); 68.34 + } 68.35 } 68.36 68.37 #endif // PRODUCT
69.1 --- a/src/share/vm/oops/oop.cpp Wed Apr 01 22:31:26 2009 -0700 69.2 +++ b/src/share/vm/oops/oop.cpp Thu Apr 02 17:01:00 2009 -0700 69.3 @@ -1,5 +1,5 @@ 69.4 /* 69.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 69.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 69.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 69.8 * 69.9 * This code is free software; you can redistribute it and/or modify it 69.10 @@ -65,11 +65,7 @@ 69.11 69.12 void oopDesc::print_address_on(outputStream* st) const { 69.13 if (PrintOopAddress) { 69.14 - st->print("{"); 69.15 - if (PrintOopAddress) { 69.16 - st->print(INTPTR_FORMAT, this); 69.17 - } 69.18 - st->print("}"); 69.19 + st->print("{"INTPTR_FORMAT"}", this); 69.20 } 69.21 } 69.22
70.1 --- a/src/share/vm/opto/block.hpp Wed Apr 01 22:31:26 2009 -0700 70.2 +++ b/src/share/vm/opto/block.hpp Thu Apr 02 17:01:00 2009 -0700 70.3 @@ -371,6 +371,7 @@ 70.4 Block *_broot; // Basic block of root 70.5 uint _rpo_ctr; 70.6 CFGLoop* _root_loop; 70.7 + float _outer_loop_freq; // Outmost loop frequency 70.8 70.9 // Per node latency estimation, valid only during GCM 70.10 GrowableArray<uint> _node_latency; 70.11 @@ -537,6 +538,7 @@ 70.12 void compute_loop_depth(int depth); 70.13 void compute_freq(); // compute frequency with loop assuming head freq 1.0f 70.14 void scale_freq(); // scale frequency by loop trip count (including outer loops) 70.15 + float outer_loop_freq() const; // frequency of outer loop 70.16 bool in_loop_nest(Block* b); 70.17 float trip_count() const { return 1.0f / _exit_prob; } 70.18 virtual bool is_loop() { return true; }
71.1 --- a/src/share/vm/opto/bytecodeInfo.cpp Wed Apr 01 22:31:26 2009 -0700 71.2 +++ b/src/share/vm/opto/bytecodeInfo.cpp Thu Apr 02 17:01:00 2009 -0700 71.3 @@ -232,6 +232,14 @@ 71.4 return "disallowed by CompilerOracle"; 71.5 } 71.6 71.7 + if (UseStringCache) { 71.8 + // Do not inline StringCache::profile() method used only at the beginning. 71.9 + if (callee_method->name() == ciSymbol::profile_name() && 71.10 + callee_method->holder()->name() == ciSymbol::java_lang_StringCache()) { 71.11 + return "profiling method"; 71.12 + } 71.13 + } 71.14 + 71.15 return NULL; 71.16 } 71.17
72.1 --- a/src/share/vm/opto/c2_globals.hpp Wed Apr 01 22:31:26 2009 -0700 72.2 +++ b/src/share/vm/opto/c2_globals.hpp Thu Apr 02 17:01:00 2009 -0700 72.3 @@ -391,7 +391,7 @@ 72.4 product(intx, EliminateAllocationArraySizeLimit, 64, \ 72.5 "Array size (number of elements) limit for scalar replacement") \ 72.6 \ 72.7 - product(bool, UseOptoBiasInlining, true, \ 72.8 + product(bool, UseOptoBiasInlining, true, \ 72.9 "Generate biased locking code in C2 ideal graph") \ 72.10 \ 72.11 product(intx, ValueSearchLimit, 1000, \ 72.12 @@ -410,7 +410,7 @@ 72.13 "Miniumum %% of a successor (predecessor) for which block layout "\ 72.14 "a will allow a fork (join) in a single chain") \ 72.15 \ 72.16 - product(bool, BlockLayoutRotateLoops, false, \ 72.17 + product(bool, BlockLayoutRotateLoops, true, \ 72.18 "Allow back branches to be fall throughs in the block layour") \ 72.19 72.20 C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG)
73.1 --- a/src/share/vm/opto/chaitin.cpp Wed Apr 01 22:31:26 2009 -0700 73.2 +++ b/src/share/vm/opto/chaitin.cpp Thu Apr 02 17:01:00 2009 -0700 73.3 @@ -149,6 +149,9 @@ 73.4 #endif 73.5 { 73.6 NOT_PRODUCT( Compile::TracePhase t3("ctorChaitin", &_t_ctorChaitin, TimeCompiler); ) 73.7 + 73.8 + _high_frequency_lrg = MIN2(float(OPTO_LRG_HIGH_FREQ), _cfg._outer_loop_freq); 73.9 + 73.10 uint i,j; 73.11 // Build a list of basic blocks, sorted by frequency 73.12 _blks = NEW_RESOURCE_ARRAY( Block *, _cfg._num_blocks );
74.1 --- a/src/share/vm/opto/chaitin.hpp Wed Apr 01 22:31:26 2009 -0700 74.2 +++ b/src/share/vm/opto/chaitin.hpp Thu Apr 02 17:01:00 2009 -0700 74.3 @@ -338,6 +338,8 @@ 74.4 74.5 Block **_blks; // Array of blocks sorted by frequency for coalescing 74.6 74.7 + float _high_frequency_lrg; // Frequency at which LRG will be spilled for debug info 74.8 + 74.9 #ifndef PRODUCT 74.10 bool _trace_spilling; 74.11 #endif 74.12 @@ -360,6 +362,8 @@ 74.13 74.14 uint n2lidx( const Node *n ) const { return _names[n->_idx]; } 74.15 74.16 + float high_frequency_lrg() const { return _high_frequency_lrg; } 74.17 + 74.18 #ifndef PRODUCT 74.19 bool trace_spilling() const { return _trace_spilling; } 74.20 #endif
75.1 --- a/src/share/vm/opto/classes.hpp Wed Apr 01 22:31:26 2009 -0700 75.2 +++ b/src/share/vm/opto/classes.hpp Thu Apr 02 17:01:00 2009 -0700 75.3 @@ -218,6 +218,8 @@ 75.4 macro(StoreP) 75.5 macro(StoreN) 75.6 macro(StrComp) 75.7 +macro(StrEquals) 75.8 +macro(StrIndexOf) 75.9 macro(SubD) 75.10 macro(SubF) 75.11 macro(SubI)
76.1 --- a/src/share/vm/opto/coalesce.cpp Wed Apr 01 22:31:26 2009 -0700 76.2 +++ b/src/share/vm/opto/coalesce.cpp Thu Apr 02 17:01:00 2009 -0700 76.3 @@ -473,7 +473,7 @@ 76.4 } // End of is two-adr 76.5 76.6 // Insert a copy at a debug use for a lrg which has high frequency 76.7 - if( (b->_freq < OPTO_DEBUG_SPLIT_FREQ) && n->is_MachSafePoint() ) { 76.8 + if( b->_freq < OPTO_DEBUG_SPLIT_FREQ || b->is_uncommon(_phc._cfg._bbs) ) { 76.9 // Walk the debug inputs to the node and check for lrg freq 76.10 JVMState* jvms = n->jvms(); 76.11 uint debug_start = jvms ? jvms->debug_start() : 999999; 76.12 @@ -487,7 +487,7 @@ 76.13 LRG &lrg = lrgs(nidx); 76.14 76.15 // If this lrg has a high frequency use/def 76.16 - if( lrg._maxfreq >= OPTO_LRG_HIGH_FREQ ) { 76.17 + if( lrg._maxfreq >= _phc.high_frequency_lrg() ) { 76.18 // If the live range is also live out of this block (like it 76.19 // would be for a fast/slow idiom), the normal spill mechanism 76.20 // does an excellent job. If it is not live out of this block
77.1 --- a/src/share/vm/opto/gcm.cpp Wed Apr 01 22:31:26 2009 -0700 77.2 +++ b/src/share/vm/opto/gcm.cpp Thu Apr 02 17:01:00 2009 -0700 77.3 @@ -438,6 +438,12 @@ 77.4 #endif 77.5 assert(load_alias_idx || (load->is_Mach() && load->as_Mach()->ideal_Opcode() == Op_StrComp), 77.6 "String compare is only known 'load' that does not conflict with any stores"); 77.7 + assert(load_alias_idx || (load->is_Mach() && load->as_Mach()->ideal_Opcode() == Op_StrEquals), 77.8 + "String equals is a 'load' that does not conflict with any stores"); 77.9 + assert(load_alias_idx || (load->is_Mach() && load->as_Mach()->ideal_Opcode() == Op_StrIndexOf), 77.10 + "String indexOf is a 'load' that does not conflict with any stores"); 77.11 + assert(load_alias_idx || (load->is_Mach() && load->as_Mach()->ideal_Opcode() == Op_AryEq), 77.12 + "Arrays equals is a 'load' that do not conflict with any stores"); 77.13 77.14 if (!C->alias_type(load_alias_idx)->is_rewritable()) { 77.15 // It is impossible to spoil this load by putting stores before it, 77.16 @@ -1374,6 +1380,9 @@ 77.17 _root_loop->_freq = 1.0; 77.18 _root_loop->scale_freq(); 77.19 77.20 + // Save outmost loop frequency for LRG frequency threshold 77.21 + _outer_loop_freq = _root_loop->outer_loop_freq(); 77.22 + 77.23 // force paths ending at uncommon traps to be infrequent 77.24 if (!C->do_freq_based_layout()) { 77.25 Block_List worklist; 77.26 @@ -1898,6 +1907,7 @@ 77.27 // Do a top down traversal of loop tree (visit outer loops first.) 77.28 void CFGLoop::scale_freq() { 77.29 float loop_freq = _freq * trip_count(); 77.30 + _freq = loop_freq; 77.31 for (int i = 0; i < _members.length(); i++) { 77.32 CFGElement* s = _members.at(i); 77.33 float block_freq = s->_freq * loop_freq; 77.34 @@ -1912,6 +1922,14 @@ 77.35 } 77.36 } 77.37 77.38 +// Frequency of outer loop 77.39 +float CFGLoop::outer_loop_freq() const { 77.40 + if (_child != NULL) { 77.41 + return _child->_freq; 77.42 + } 77.43 + return _freq; 77.44 +} 77.45 + 77.46 #ifndef PRODUCT 77.47 //------------------------------dump_tree-------------------------------------- 77.48 void CFGLoop::dump_tree() const {
78.1 --- a/src/share/vm/opto/lcm.cpp Wed Apr 01 22:31:26 2009 -0700 78.2 +++ b/src/share/vm/opto/lcm.cpp Thu Apr 02 17:01:00 2009 -0700 78.3 @@ -137,6 +137,8 @@ 78.4 if( mach->in(2) != val ) continue; 78.5 break; // Found a memory op? 78.6 case Op_StrComp: 78.7 + case Op_StrEquals: 78.8 + case Op_StrIndexOf: 78.9 case Op_AryEq: 78.10 // Not a legit memory op for implicit null check regardless of 78.11 // embedded loads
79.1 --- a/src/share/vm/opto/library_call.cpp Wed Apr 01 22:31:26 2009 -0700 79.2 +++ b/src/share/vm/opto/library_call.cpp Thu Apr 02 17:01:00 2009 -0700 79.3 @@ -136,6 +136,7 @@ 79.4 bool inline_string_compareTo(); 79.5 bool inline_string_indexOf(); 79.6 Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i); 79.7 + bool inline_string_equals(); 79.8 Node* pop_math_arg(); 79.9 bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName); 79.10 bool inline_math_native(vmIntrinsics::ID id); 79.11 @@ -261,6 +262,7 @@ 79.12 switch (id) { 79.13 case vmIntrinsics::_indexOf: 79.14 case vmIntrinsics::_compareTo: 79.15 + case vmIntrinsics::_equals: 79.16 case vmIntrinsics::_equalsC: 79.17 break; // InlineNatives does not control String.compareTo 79.18 default: 79.19 @@ -275,6 +277,9 @@ 79.20 case vmIntrinsics::_indexOf: 79.21 if (!SpecialStringIndexOf) return NULL; 79.22 break; 79.23 + case vmIntrinsics::_equals: 79.24 + if (!SpecialStringEquals) return NULL; 79.25 + break; 79.26 case vmIntrinsics::_equalsC: 79.27 if (!SpecialArraysEquals) return NULL; 79.28 break; 79.29 @@ -442,6 +447,8 @@ 79.30 return inline_string_compareTo(); 79.31 case vmIntrinsics::_indexOf: 79.32 return inline_string_indexOf(); 79.33 + case vmIntrinsics::_equals: 79.34 + return inline_string_equals(); 79.35 79.36 case vmIntrinsics::_getObject: 79.37 return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, false); 79.38 @@ -793,6 +800,8 @@ 79.39 //------------------------------inline_string_compareTo------------------------ 79.40 bool LibraryCallKit::inline_string_compareTo() { 79.41 79.42 + if (!Matcher::has_match_rule(Op_StrComp)) return false; 79.43 + 79.44 const int value_offset = java_lang_String::value_offset_in_bytes(); 79.45 const int count_offset = java_lang_String::count_offset_in_bytes(); 79.46 const int offset_offset = java_lang_String::offset_offset_in_bytes(); 79.47 @@ -830,6 +839,82 @@ 79.48 return true; 79.49 } 79.50 79.51 +//------------------------------inline_string_equals------------------------ 79.52 +bool LibraryCallKit::inline_string_equals() { 79.53 + 79.54 + if (!Matcher::has_match_rule(Op_StrEquals)) return false; 79.55 + 79.56 + const int value_offset = java_lang_String::value_offset_in_bytes(); 79.57 + const int count_offset = java_lang_String::count_offset_in_bytes(); 79.58 + const int offset_offset = java_lang_String::offset_offset_in_bytes(); 79.59 + 79.60 + _sp += 2; 79.61 + Node* argument = pop(); // pop non-receiver first: it was pushed second 79.62 + Node* receiver = pop(); 79.63 + 79.64 + // Null check on self without removing any arguments. The argument 79.65 + // null check technically happens in the wrong place, which can lead to 79.66 + // invalid stack traces when string compare is inlined into a method 79.67 + // which handles NullPointerExceptions. 79.68 + _sp += 2; 79.69 + receiver = do_null_check(receiver, T_OBJECT); 79.70 + //should not do null check for argument for String.equals(), because spec 79.71 + //allows to specify NULL as argument. 79.72 + _sp -= 2; 79.73 + 79.74 + if (stopped()) { 79.75 + return true; 79.76 + } 79.77 + 79.78 + // get String klass for instanceOf 79.79 + ciInstanceKlass* klass = env()->String_klass(); 79.80 + 79.81 + // two paths (plus control) merge 79.82 + RegionNode* region = new (C, 3) RegionNode(3); 79.83 + Node* phi = new (C, 3) PhiNode(region, TypeInt::BOOL); 79.84 + 79.85 + Node* inst = gen_instanceof(argument, makecon(TypeKlassPtr::make(klass))); 79.86 + Node* cmp = _gvn.transform(new (C, 3) CmpINode(inst, intcon(1))); 79.87 + Node* bol = _gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::eq)); 79.88 + 79.89 + IfNode* iff = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN); 79.90 + 79.91 + Node* if_true = _gvn.transform(new (C, 1) IfTrueNode(iff)); 79.92 + set_control(if_true); 79.93 + 79.94 + const TypeInstPtr* string_type = 79.95 + TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0); 79.96 + 79.97 + // instanceOf == true 79.98 + Node* equals = 79.99 + _gvn.transform(new (C, 7) StrEqualsNode( 79.100 + control(), 79.101 + memory(TypeAryPtr::CHARS), 79.102 + memory(string_type->add_offset(value_offset)), 79.103 + memory(string_type->add_offset(count_offset)), 79.104 + memory(string_type->add_offset(offset_offset)), 79.105 + receiver, 79.106 + argument)); 79.107 + 79.108 + phi->init_req(1, _gvn.transform(equals)); 79.109 + region->init_req(1, if_true); 79.110 + 79.111 + //instanceOf == false, fallthrough 79.112 + Node* if_false = _gvn.transform(new (C, 1) IfFalseNode(iff)); 79.113 + set_control(if_false); 79.114 + 79.115 + phi->init_req(2, _gvn.transform(intcon(0))); 79.116 + region->init_req(2, if_false); 79.117 + 79.118 + // post merge 79.119 + set_control(_gvn.transform(region)); 79.120 + record_for_igvn(region); 79.121 + 79.122 + push(_gvn.transform(phi)); 79.123 + 79.124 + return true; 79.125 +} 79.126 + 79.127 //------------------------------inline_array_equals---------------------------- 79.128 bool LibraryCallKit::inline_array_equals() { 79.129 79.130 @@ -994,80 +1079,115 @@ 79.131 return result; 79.132 } 79.133 79.134 - 79.135 //------------------------------inline_string_indexOf------------------------ 79.136 bool LibraryCallKit::inline_string_indexOf() { 79.137 79.138 + const int value_offset = java_lang_String::value_offset_in_bytes(); 79.139 + const int count_offset = java_lang_String::count_offset_in_bytes(); 79.140 + const int offset_offset = java_lang_String::offset_offset_in_bytes(); 79.141 + 79.142 _sp += 2; 79.143 Node *argument = pop(); // pop non-receiver first: it was pushed second 79.144 Node *receiver = pop(); 79.145 79.146 - // don't intrinsify if argument isn't a constant string. 79.147 - if (!argument->is_Con()) { 79.148 - return false; 79.149 + Node* result; 79.150 + if (Matcher::has_match_rule(Op_StrIndexOf) && 79.151 + UseSSE42Intrinsics) { 79.152 + // Generate SSE4.2 version of indexOf 79.153 + // We currently only have match rules that use SSE4.2 79.154 + 79.155 + // Null check on self without removing any arguments. The argument 79.156 + // null check technically happens in the wrong place, which can lead to 79.157 + // invalid stack traces when string compare is inlined into a method 79.158 + // which handles NullPointerExceptions. 79.159 + _sp += 2; 79.160 + receiver = do_null_check(receiver, T_OBJECT); 79.161 + argument = do_null_check(argument, T_OBJECT); 79.162 + _sp -= 2; 79.163 + 79.164 + if (stopped()) { 79.165 + return true; 79.166 + } 79.167 + 79.168 + ciInstanceKlass* klass = env()->String_klass(); 79.169 + const TypeInstPtr* string_type = 79.170 + TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0); 79.171 + 79.172 + result = 79.173 + _gvn.transform(new (C, 7) 79.174 + StrIndexOfNode(control(), 79.175 + memory(TypeAryPtr::CHARS), 79.176 + memory(string_type->add_offset(value_offset)), 79.177 + memory(string_type->add_offset(count_offset)), 79.178 + memory(string_type->add_offset(offset_offset)), 79.179 + receiver, 79.180 + argument)); 79.181 + } else { //Use LibraryCallKit::string_indexOf 79.182 + // don't intrinsify is argument isn't a constant string. 79.183 + if (!argument->is_Con()) { 79.184 + return false; 79.185 + } 79.186 + const TypeOopPtr* str_type = _gvn.type(argument)->isa_oopptr(); 79.187 + if (str_type == NULL) { 79.188 + return false; 79.189 + } 79.190 + ciInstanceKlass* klass = env()->String_klass(); 79.191 + ciObject* str_const = str_type->const_oop(); 79.192 + if (str_const == NULL || str_const->klass() != klass) { 79.193 + return false; 79.194 + } 79.195 + ciInstance* str = str_const->as_instance(); 79.196 + assert(str != NULL, "must be instance"); 79.197 + 79.198 + ciObject* v = str->field_value_by_offset(value_offset).as_object(); 79.199 + int o = str->field_value_by_offset(offset_offset).as_int(); 79.200 + int c = str->field_value_by_offset(count_offset).as_int(); 79.201 + ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array 79.202 + 79.203 + // constant strings have no offset and count == length which 79.204 + // simplifies the resulting code somewhat so lets optimize for that. 79.205 + if (o != 0 || c != pat->length()) { 79.206 + return false; 79.207 + } 79.208 + 79.209 + // Null check on self without removing any arguments. The argument 79.210 + // null check technically happens in the wrong place, which can lead to 79.211 + // invalid stack traces when string compare is inlined into a method 79.212 + // which handles NullPointerExceptions. 79.213 + _sp += 2; 79.214 + receiver = do_null_check(receiver, T_OBJECT); 79.215 + // No null check on the argument is needed since it's a constant String oop. 79.216 + _sp -= 2; 79.217 + if (stopped()) { 79.218 + return true; 79.219 + } 79.220 + 79.221 + // The null string as a pattern always returns 0 (match at beginning of string) 79.222 + if (c == 0) { 79.223 + push(intcon(0)); 79.224 + return true; 79.225 + } 79.226 + 79.227 + // Generate default indexOf 79.228 + jchar lastChar = pat->char_at(o + (c - 1)); 79.229 + int cache = 0; 79.230 + int i; 79.231 + for (i = 0; i < c - 1; i++) { 79.232 + assert(i < pat->length(), "out of range"); 79.233 + cache |= (1 << (pat->char_at(o + i) & (sizeof(cache) * BitsPerByte - 1))); 79.234 + } 79.235 + 79.236 + int md2 = c; 79.237 + for (i = 0; i < c - 1; i++) { 79.238 + assert(i < pat->length(), "out of range"); 79.239 + if (pat->char_at(o + i) == lastChar) { 79.240 + md2 = (c - 1) - i; 79.241 + } 79.242 + } 79.243 + 79.244 + result = string_indexOf(receiver, pat, o, cache, md2); 79.245 } 79.246 - const TypeOopPtr* str_type = _gvn.type(argument)->isa_oopptr(); 79.247 - if (str_type == NULL) { 79.248 - return false; 79.249 - } 79.250 - ciInstanceKlass* klass = env()->String_klass(); 79.251 - ciObject* str_const = str_type->const_oop(); 79.252 - if (str_const == NULL || str_const->klass() != klass) { 79.253 - return false; 79.254 - } 79.255 - ciInstance* str = str_const->as_instance(); 79.256 - assert(str != NULL, "must be instance"); 79.257 - 79.258 - const int value_offset = java_lang_String::value_offset_in_bytes(); 79.259 - const int count_offset = java_lang_String::count_offset_in_bytes(); 79.260 - const int offset_offset = java_lang_String::offset_offset_in_bytes(); 79.261 - 79.262 - ciObject* v = str->field_value_by_offset(value_offset).as_object(); 79.263 - int o = str->field_value_by_offset(offset_offset).as_int(); 79.264 - int c = str->field_value_by_offset(count_offset).as_int(); 79.265 - ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array 79.266 - 79.267 - // constant strings have no offset and count == length which 79.268 - // simplifies the resulting code somewhat so lets optimize for that. 79.269 - if (o != 0 || c != pat->length()) { 79.270 - return false; 79.271 - } 79.272 - 79.273 - // Null check on self without removing any arguments. The argument 79.274 - // null check technically happens in the wrong place, which can lead to 79.275 - // invalid stack traces when string compare is inlined into a method 79.276 - // which handles NullPointerExceptions. 79.277 - _sp += 2; 79.278 - receiver = do_null_check(receiver, T_OBJECT); 79.279 - // No null check on the argument is needed since it's a constant String oop. 79.280 - _sp -= 2; 79.281 - if (stopped()) { 79.282 - return true; 79.283 - } 79.284 - 79.285 - // The null string as a pattern always returns 0 (match at beginning of string) 79.286 - if (c == 0) { 79.287 - push(intcon(0)); 79.288 - return true; 79.289 - } 79.290 - 79.291 - jchar lastChar = pat->char_at(o + (c - 1)); 79.292 - int cache = 0; 79.293 - int i; 79.294 - for (i = 0; i < c - 1; i++) { 79.295 - assert(i < pat->length(), "out of range"); 79.296 - cache |= (1 << (pat->char_at(o + i) & (sizeof(cache) * BitsPerByte - 1))); 79.297 - } 79.298 - 79.299 - int md2 = c; 79.300 - for (i = 0; i < c - 1; i++) { 79.301 - assert(i < pat->length(), "out of range"); 79.302 - if (pat->char_at(o + i) == lastChar) { 79.303 - md2 = (c - 1) - i; 79.304 - } 79.305 - } 79.306 - 79.307 - Node* result = string_indexOf(receiver, pat, o, cache, md2); 79.308 + 79.309 push(result); 79.310 return true; 79.311 }
80.1 --- a/src/share/vm/opto/loopnode.cpp Wed Apr 01 22:31:26 2009 -0700 80.2 +++ b/src/share/vm/opto/loopnode.cpp Thu Apr 02 17:01:00 2009 -0700 80.3 @@ -2668,6 +2668,8 @@ 80.4 case Op_LoadD_unaligned: 80.5 case Op_LoadL_unaligned: 80.6 case Op_StrComp: // Does a bunch of load-like effects 80.7 + case Op_StrEquals: 80.8 + case Op_StrIndexOf: 80.9 case Op_AryEq: 80.10 pinned = false; 80.11 }
81.1 --- a/src/share/vm/opto/machnode.cpp Wed Apr 01 22:31:26 2009 -0700 81.2 +++ b/src/share/vm/opto/machnode.cpp Thu Apr 02 17:01:00 2009 -0700 81.3 @@ -340,6 +340,10 @@ 81.4 if (base == NodeSentinel) return TypePtr::BOTTOM; 81.5 81.6 const Type* t = base->bottom_type(); 81.7 + if (UseCompressedOops && Universe::narrow_oop_shift() == 0) { 81.8 + // 32-bit unscaled narrow oop can be the base of any address expression 81.9 + t = t->make_ptr(); 81.10 + } 81.11 if (t->isa_intptr_t() && offset != 0 && offset != Type::OffsetBot) { 81.12 // We cannot assert that the offset does not look oop-ish here. 81.13 // Depending on the heap layout the cardmark base could land 81.14 @@ -353,6 +357,7 @@ 81.15 81.16 // be conservative if we do not recognize the type 81.17 if (tp == NULL) { 81.18 + assert(false, "this path may produce not optimal code"); 81.19 return TypePtr::BOTTOM; 81.20 } 81.21 assert(tp->base() != Type::AnyPtr, "not a bare pointer");
82.1 --- a/src/share/vm/opto/matcher.cpp Wed Apr 01 22:31:26 2009 -0700 82.2 +++ b/src/share/vm/opto/matcher.cpp Thu Apr 02 17:01:00 2009 -0700 82.3 @@ -746,6 +746,8 @@ 82.4 if (nidx == Compile::AliasIdxBot && midx == Compile::AliasIdxTop) { 82.5 switch (n->Opcode()) { 82.6 case Op_StrComp: 82.7 + case Op_StrEquals: 82.8 + case Op_StrIndexOf: 82.9 case Op_AryEq: 82.10 case Op_MemBarVolatile: 82.11 case Op_MemBarCPUOrder: // %%% these ideals should have narrower adr_type? 82.12 @@ -1788,6 +1790,8 @@ 82.13 mstack.push(n->in(0), Pre_Visit); // Visit Control input 82.14 continue; // while (mstack.is_nonempty()) 82.15 case Op_StrComp: 82.16 + case Op_StrEquals: 82.17 + case Op_StrIndexOf: 82.18 case Op_AryEq: 82.19 set_shared(n); // Force result into register (it will be anyways) 82.20 break;
83.1 --- a/src/share/vm/opto/memnode.cpp Wed Apr 01 22:31:26 2009 -0700 83.2 +++ b/src/share/vm/opto/memnode.cpp Thu Apr 02 17:01:00 2009 -0700 83.3 @@ -2481,6 +2481,31 @@ 83.4 return remove_dead_region(phase, can_reshape) ? this : NULL; 83.5 } 83.6 83.7 +// Do we match on this edge? No memory edges 83.8 +uint StrEqualsNode::match_edge(uint idx) const { 83.9 + return idx == 5 || idx == 6; 83.10 +} 83.11 + 83.12 +//------------------------------Ideal------------------------------------------ 83.13 +// Return a node which is more "ideal" than the current node. Strip out 83.14 +// control copies 83.15 +Node *StrEqualsNode::Ideal(PhaseGVN *phase, bool can_reshape){ 83.16 + return remove_dead_region(phase, can_reshape) ? this : NULL; 83.17 +} 83.18 + 83.19 +//============================================================================= 83.20 +// Do we match on this edge? No memory edges 83.21 +uint StrIndexOfNode::match_edge(uint idx) const { 83.22 + return idx == 5 || idx == 6; 83.23 +} 83.24 + 83.25 +//------------------------------Ideal------------------------------------------ 83.26 +// Return a node which is more "ideal" than the current node. Strip out 83.27 +// control copies 83.28 +Node *StrIndexOfNode::Ideal(PhaseGVN *phase, bool can_reshape){ 83.29 + return remove_dead_region(phase, can_reshape) ? this : NULL; 83.30 +} 83.31 + 83.32 //------------------------------Ideal------------------------------------------ 83.33 // Return a node which is more "ideal" than the current node. Strip out 83.34 // control copies 83.35 @@ -2488,7 +2513,6 @@ 83.36 return remove_dead_region(phase, can_reshape) ? this : NULL; 83.37 } 83.38 83.39 - 83.40 //============================================================================= 83.41 MemBarNode::MemBarNode(Compile* C, int alias_idx, Node* precedent) 83.42 : MultiNode(TypeFunc::Parms + (precedent == NULL? 0: 1)),
84.1 --- a/src/share/vm/opto/memnode.hpp Wed Apr 01 22:31:26 2009 -0700 84.2 +++ b/src/share/vm/opto/memnode.hpp Thu Apr 02 17:01:00 2009 -0700 84.3 @@ -765,6 +765,54 @@ 84.4 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 84.5 }; 84.6 84.7 +//------------------------------StrEquals------------------------------------- 84.8 +class StrEqualsNode: public Node { 84.9 +public: 84.10 + StrEqualsNode(Node *control, 84.11 + Node* char_array_mem, 84.12 + Node* value_mem, 84.13 + Node* count_mem, 84.14 + Node* offset_mem, 84.15 + Node* s1, Node* s2): Node(control, 84.16 + char_array_mem, 84.17 + value_mem, 84.18 + count_mem, 84.19 + offset_mem, 84.20 + s1, s2) {}; 84.21 + virtual int Opcode() const; 84.22 + virtual bool depends_only_on_test() const { return false; } 84.23 + virtual const Type* bottom_type() const { return TypeInt::BOOL; } 84.24 + // a StrEqualsNode (conservatively) aliases with everything: 84.25 + virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; } 84.26 + virtual uint match_edge(uint idx) const; 84.27 + virtual uint ideal_reg() const { return Op_RegI; } 84.28 + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 84.29 +}; 84.30 + 84.31 +//------------------------------StrIndexOf------------------------------------- 84.32 +class StrIndexOfNode: public Node { 84.33 +public: 84.34 + StrIndexOfNode(Node *control, 84.35 + Node* char_array_mem, 84.36 + Node* value_mem, 84.37 + Node* count_mem, 84.38 + Node* offset_mem, 84.39 + Node* s1, Node* s2): Node(control, 84.40 + char_array_mem, 84.41 + value_mem, 84.42 + count_mem, 84.43 + offset_mem, 84.44 + s1, s2) {}; 84.45 + virtual int Opcode() const; 84.46 + virtual bool depends_only_on_test() const { return false; } 84.47 + virtual const Type* bottom_type() const { return TypeInt::INT; } 84.48 + // a StrIndexOfNode (conservatively) aliases with everything: 84.49 + virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; } 84.50 + virtual uint match_edge(uint idx) const; 84.51 + virtual uint ideal_reg() const { return Op_RegI; } 84.52 + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 84.53 +}; 84.54 + 84.55 //------------------------------AryEq--------------------------------------- 84.56 class AryEqNode: public Node { 84.57 public:
85.1 --- a/src/share/vm/opto/parse1.cpp Wed Apr 01 22:31:26 2009 -0700 85.2 +++ b/src/share/vm/opto/parse1.cpp Thu Apr 02 17:01:00 2009 -0700 85.3 @@ -95,7 +95,7 @@ 85.4 switch( bt ) { // Signature is flattened 85.5 case T_INT: l = new (C, 3) LoadINode( 0, mem, adr, TypeRawPtr::BOTTOM ); break; 85.6 case T_FLOAT: l = new (C, 3) LoadFNode( 0, mem, adr, TypeRawPtr::BOTTOM ); break; 85.7 - case T_ADDRESS: 85.8 + case T_ADDRESS: l = new (C, 3) LoadPNode( 0, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM ); break; 85.9 case T_OBJECT: l = new (C, 3) LoadPNode( 0, mem, adr, TypeRawPtr::BOTTOM, TypeInstPtr::BOTTOM ); break; 85.10 case T_LONG: 85.11 case T_DOUBLE: {
86.1 --- a/src/share/vm/opto/subnode.cpp Wed Apr 01 22:31:26 2009 -0700 86.2 +++ b/src/share/vm/opto/subnode.cpp Thu Apr 02 17:01:00 2009 -0700 86.3 @@ -639,8 +639,8 @@ 86.4 int kps = (p0->isa_klassptr()?1:0) + (p1->isa_klassptr()?1:0); 86.5 if (klass0 && klass1 && 86.6 kps != 1 && // both or neither are klass pointers 86.7 - !klass0->is_interface() && // do not trust interfaces 86.8 - !klass1->is_interface()) { 86.9 + klass0->is_loaded() && !klass0->is_interface() && // do not trust interfaces 86.10 + klass1->is_loaded() && !klass1->is_interface()) { 86.11 bool unrelated_classes = false; 86.12 // See if neither subclasses the other, or if the class on top 86.13 // is precise. In either of these cases, the compare is known
87.1 --- a/src/share/vm/opto/superword.cpp Wed Apr 01 22:31:26 2009 -0700 87.2 +++ b/src/share/vm/opto/superword.cpp Thu Apr 02 17:01:00 2009 -0700 87.3 @@ -454,9 +454,13 @@ 87.4 // or need to run igvn.optimize() again before SLP 87.5 } else if (out->is_Phi() && out->bottom_type() == Type::MEMORY && !in_bb(out)) { 87.6 // Ditto. Not sure what else to check further. 87.7 - } else if (out->Opcode() == Op_StoreCM && out->in(4) == n) { 87.8 + } else if (out->Opcode() == Op_StoreCM && out->in(MemNode::OopStore) == n) { 87.9 // StoreCM has an input edge used as a precedence edge. 87.10 // Maybe an issue when oop stores are vectorized. 87.11 + } else if( out->is_MergeMem() && prev && 87.12 + prev->Opcode() == Op_StoreCM && out == prev->in(MemNode::OopStore)) { 87.13 + // Oop store is a MergeMem! This should not happen. Temporarily remove the assertion 87.14 + // for this case because it could not be superwordized anyway. 87.15 } else { 87.16 assert(out == prev || prev == NULL, "no branches off of store slice"); 87.17 } 87.18 @@ -912,54 +916,175 @@ 87.19 } 87.20 } 87.21 87.22 -//------------------------------co_locate_pack--------------------------- 87.23 -// Within a pack, move stores down to the last executed store, 87.24 -// and move loads up to the first executed load. 87.25 +//-------------------------------remove_and_insert------------------- 87.26 +//remove "current" from its current position in the memory graph and insert 87.27 +//it after the appropriate insertion point (lip or uip) 87.28 +void SuperWord::remove_and_insert(MemNode *current, MemNode *prev, MemNode *lip, 87.29 + Node *uip, Unique_Node_List &sched_before) { 87.30 + Node* my_mem = current->in(MemNode::Memory); 87.31 + _igvn.hash_delete(current); 87.32 + _igvn.hash_delete(my_mem); 87.33 + 87.34 + //remove current_store from its current position in the memmory graph 87.35 + for (DUIterator i = current->outs(); current->has_out(i); i++) { 87.36 + Node* use = current->out(i); 87.37 + if (use->is_Mem()) { 87.38 + assert(use->in(MemNode::Memory) == current, "must be"); 87.39 + _igvn.hash_delete(use); 87.40 + if (use == prev) { // connect prev to my_mem 87.41 + use->set_req(MemNode::Memory, my_mem); 87.42 + } else if (sched_before.member(use)) { 87.43 + _igvn.hash_delete(uip); 87.44 + use->set_req(MemNode::Memory, uip); 87.45 + } else { 87.46 + _igvn.hash_delete(lip); 87.47 + use->set_req(MemNode::Memory, lip); 87.48 + } 87.49 + _igvn._worklist.push(use); 87.50 + --i; //deleted this edge; rescan position 87.51 + } 87.52 + } 87.53 + 87.54 + bool sched_up = sched_before.member(current); 87.55 + Node *insert_pt = sched_up ? uip : lip; 87.56 + _igvn.hash_delete(insert_pt); 87.57 + 87.58 + // all uses of insert_pt's memory state should use current's instead 87.59 + for (DUIterator i = insert_pt->outs(); insert_pt->has_out(i); i++) { 87.60 + Node* use = insert_pt->out(i); 87.61 + if (use->is_Mem()) { 87.62 + assert(use->in(MemNode::Memory) == insert_pt, "must be"); 87.63 + _igvn.hash_delete(use); 87.64 + use->set_req(MemNode::Memory, current); 87.65 + _igvn._worklist.push(use); 87.66 + --i; //deleted this edge; rescan position 87.67 + } else if (!sched_up && use->is_Phi() && use->bottom_type() == Type::MEMORY) { 87.68 + uint pos; //lip (lower insert point) must be the last one in the memory slice 87.69 + _igvn.hash_delete(use); 87.70 + for (pos=1; pos < use->req(); pos++) { 87.71 + if (use->in(pos) == insert_pt) break; 87.72 + } 87.73 + use->set_req(pos, current); 87.74 + _igvn._worklist.push(use); 87.75 + --i; 87.76 + } 87.77 + } 87.78 + 87.79 + //connect current to insert_pt 87.80 + current->set_req(MemNode::Memory, insert_pt); 87.81 + _igvn._worklist.push(current); 87.82 +} 87.83 + 87.84 +//------------------------------co_locate_pack---------------------------------- 87.85 +// To schedule a store pack, we need to move any sandwiched memory ops either before 87.86 +// or after the pack, based upon dependence information: 87.87 +// (1) If any store in the pack depends on the sandwiched memory op, the 87.88 +// sandwiched memory op must be scheduled BEFORE the pack; 87.89 +// (2) If a sandwiched memory op depends on any store in the pack, the 87.90 +// sandwiched memory op must be scheduled AFTER the pack; 87.91 +// (3) If a sandwiched memory op (say, memA) depends on another sandwiched 87.92 +// memory op (say memB), memB must be scheduled before memA. So, if memA is 87.93 +// scheduled before the pack, memB must also be scheduled before the pack; 87.94 +// (4) If there is no dependence restriction for a sandwiched memory op, we simply 87.95 +// schedule this store AFTER the pack 87.96 +// (5) We know there is no dependence cycle, so there in no other case; 87.97 +// (6) Finally, all memory ops in another single pack should be moved in the same direction. 87.98 +// 87.99 +// To schedule a load pack: the memory edge of every loads in the pack must be 87.100 +// the same as the memory edge of the last executed load in the pack 87.101 void SuperWord::co_locate_pack(Node_List* pk) { 87.102 if (pk->at(0)->is_Store()) { 87.103 - // Push Stores down towards last executed pack member 87.104 MemNode* first = executed_first(pk)->as_Mem(); 87.105 MemNode* last = executed_last(pk)->as_Mem(); 87.106 - MemNode* insert_pt = last; 87.107 + Unique_Node_List schedule_before_pack; 87.108 + Unique_Node_List memops; 87.109 + 87.110 MemNode* current = last->in(MemNode::Memory)->as_Mem(); 87.111 + MemNode* previous = last; 87.112 while (true) { 87.113 assert(in_bb(current), "stay in block"); 87.114 + memops.push(previous); 87.115 + for (DUIterator i = current->outs(); current->has_out(i); i++) { 87.116 + Node* use = current->out(i); 87.117 + if (use->is_Mem() && use != previous) 87.118 + memops.push(use); 87.119 + } 87.120 + if(current == first) break; 87.121 + previous = current; 87.122 + current = current->in(MemNode::Memory)->as_Mem(); 87.123 + } 87.124 + 87.125 + // determine which memory operations should be scheduled before the pack 87.126 + for (uint i = 1; i < memops.size(); i++) { 87.127 + Node *s1 = memops.at(i); 87.128 + if (!in_pack(s1, pk) && !schedule_before_pack.member(s1)) { 87.129 + for (uint j = 0; j< i; j++) { 87.130 + Node *s2 = memops.at(j); 87.131 + if (!independent(s1, s2)) { 87.132 + if (in_pack(s2, pk) || schedule_before_pack.member(s2)) { 87.133 + schedule_before_pack.push(s1); //s1 must be scheduled before 87.134 + Node_List* mem_pk = my_pack(s1); 87.135 + if (mem_pk != NULL) { 87.136 + for (uint ii = 0; ii < mem_pk->size(); ii++) { 87.137 + Node* s = mem_pk->at(ii); // follow partner 87.138 + if (memops.member(s) && !schedule_before_pack.member(s)) 87.139 + schedule_before_pack.push(s); 87.140 + } 87.141 + } 87.142 + } 87.143 + } 87.144 + } 87.145 + } 87.146 + } 87.147 + 87.148 + MemNode* lower_insert_pt = last; 87.149 + Node* upper_insert_pt = first->in(MemNode::Memory); 87.150 + previous = last; //previous store in pk 87.151 + current = last->in(MemNode::Memory)->as_Mem(); 87.152 + 87.153 + //start scheduling from "last" to "first" 87.154 + while (true) { 87.155 + assert(in_bb(current), "stay in block"); 87.156 + assert(in_pack(previous, pk), "previous stays in pack"); 87.157 Node* my_mem = current->in(MemNode::Memory); 87.158 + 87.159 if (in_pack(current, pk)) { 87.160 - // Forward users of my memory state to my input memory state 87.161 + // Forward users of my memory state (except "previous) to my input memory state 87.162 _igvn.hash_delete(current); 87.163 - _igvn.hash_delete(my_mem); 87.164 for (DUIterator i = current->outs(); current->has_out(i); i++) { 87.165 Node* use = current->out(i); 87.166 - if (use->is_Mem()) { 87.167 + if (use->is_Mem() && use != previous) { 87.168 assert(use->in(MemNode::Memory) == current, "must be"); 87.169 _igvn.hash_delete(use); 87.170 - use->set_req(MemNode::Memory, my_mem); 87.171 + if (schedule_before_pack.member(use)) { 87.172 + _igvn.hash_delete(upper_insert_pt); 87.173 + use->set_req(MemNode::Memory, upper_insert_pt); 87.174 + } else { 87.175 + _igvn.hash_delete(lower_insert_pt); 87.176 + use->set_req(MemNode::Memory, lower_insert_pt); 87.177 + } 87.178 _igvn._worklist.push(use); 87.179 --i; // deleted this edge; rescan position 87.180 } 87.181 } 87.182 - // put current immediately before insert_pt 87.183 - current->set_req(MemNode::Memory, insert_pt->in(MemNode::Memory)); 87.184 - _igvn.hash_delete(insert_pt); 87.185 - insert_pt->set_req(MemNode::Memory, current); 87.186 - _igvn._worklist.push(insert_pt); 87.187 - _igvn._worklist.push(current); 87.188 - insert_pt = current; 87.189 + previous = current; 87.190 + } else { // !in_pack(current, pk) ==> a sandwiched store 87.191 + remove_and_insert(current, previous, lower_insert_pt, upper_insert_pt, schedule_before_pack); 87.192 } 87.193 + 87.194 if (current == first) break; 87.195 current = my_mem->as_Mem(); 87.196 - } 87.197 - } else if (pk->at(0)->is_Load()) { 87.198 - // Pull Loads up towards first executed pack member 87.199 - LoadNode* first = executed_first(pk)->as_Load(); 87.200 - Node* first_mem = first->in(MemNode::Memory); 87.201 - _igvn.hash_delete(first_mem); 87.202 - // Give each load same memory state as first 87.203 + } // end while 87.204 + } else if (pk->at(0)->is_Load()) { //load 87.205 + // all use the memory state that the last executed load uses 87.206 + LoadNode* last_load = executed_last(pk)->as_Load(); 87.207 + Node* last_mem = last_load->in(MemNode::Memory); 87.208 + _igvn.hash_delete(last_mem); 87.209 + // Give each load same memory state as last 87.210 for (uint i = 0; i < pk->size(); i++) { 87.211 LoadNode* ld = pk->at(i)->as_Load(); 87.212 _igvn.hash_delete(ld); 87.213 - ld->set_req(MemNode::Memory, first_mem); 87.214 + ld->set_req(MemNode::Memory, last_mem); 87.215 _igvn._worklist.push(ld); 87.216 } 87.217 }
88.1 --- a/src/share/vm/opto/superword.hpp Wed Apr 01 22:31:26 2009 -0700 88.2 +++ b/src/share/vm/opto/superword.hpp Thu Apr 02 17:01:00 2009 -0700 88.3 @@ -341,8 +341,11 @@ 88.4 void filter_packs(); 88.5 // Adjust the memory graph for the packed operations 88.6 void schedule(); 88.7 - // Within a pack, move stores down to the last executed store, 88.8 - // and move loads up to the first executed load. 88.9 + // Remove "current" from its current position in the memory graph and insert 88.10 + // it after the appropriate insert points (lip or uip); 88.11 + void remove_and_insert(MemNode *current, MemNode *prev, MemNode *lip, Node *uip, Unique_Node_List &schd_before); 88.12 + // Within a store pack, schedule stores together by moving out the sandwiched memory ops according 88.13 + // to dependence info; and within a load pack, move loads down to the last executed load. 88.14 void co_locate_pack(Node_List* p); 88.15 // Convert packs into vector node operations 88.16 void output();
89.1 --- a/src/share/vm/prims/jvm.cpp Wed Apr 01 22:31:26 2009 -0700 89.2 +++ b/src/share/vm/prims/jvm.cpp Thu Apr 02 17:01:00 2009 -0700 89.3 @@ -1252,7 +1252,7 @@ 89.4 89.5 // Throws an exception if outer klass has not declared k as 89.6 // an inner klass 89.7 - Reflection::check_for_inner_class(k, inner_klass, CHECK_NULL); 89.8 + Reflection::check_for_inner_class(k, inner_klass, true, CHECK_NULL); 89.9 89.10 result->obj_at_put(members, inner_klass->java_mirror()); 89.11 members++; 89.12 @@ -1275,16 +1275,29 @@ 89.13 89.14 89.15 JVM_ENTRY(jclass, JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass)) 89.16 - const int inner_class_info_index = 0; 89.17 - const int outer_class_info_index = 1; 89.18 - 89.19 +{ 89.20 // ofClass is a reference to a java_lang_Class object. 89.21 if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || 89.22 ! Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_instance()) { 89.23 return NULL; 89.24 } 89.25 89.26 - instanceKlassHandle k(thread, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass))); 89.27 + symbolOop simple_name = NULL; 89.28 + klassOop outer_klass 89.29 + = instanceKlass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)) 89.30 + )->compute_enclosing_class(simple_name, CHECK_NULL); 89.31 + if (outer_klass == NULL) return NULL; // already a top-level class 89.32 + if (simple_name == NULL) return NULL; // an anonymous class (inside a method) 89.33 + return (jclass) JNIHandles::make_local(env, Klass::cast(outer_klass)->java_mirror()); 89.34 +} 89.35 +JVM_END 89.36 + 89.37 +// should be in instanceKlass.cpp, but is here for historical reasons 89.38 +klassOop instanceKlass::compute_enclosing_class_impl(instanceKlassHandle k, 89.39 + symbolOop& simple_name_result, TRAPS) { 89.40 + Thread* thread = THREAD; 89.41 + const int inner_class_info_index = inner_class_inner_class_info_offset; 89.42 + const int outer_class_info_index = inner_class_outer_class_info_offset; 89.43 89.44 if (k->inner_classes()->length() == 0) { 89.45 // No inner class info => no declaring class 89.46 @@ -1298,35 +1311,51 @@ 89.47 bool found = false; 89.48 klassOop ok; 89.49 instanceKlassHandle outer_klass; 89.50 + bool inner_is_member = false; 89.51 + int simple_name_index = 0; 89.52 89.53 // Find inner_klass attribute 89.54 - for(int i = 0; i < i_length && !found; i+= 4) { 89.55 + for (int i = 0; i < i_length && !found; i += inner_class_next_offset) { 89.56 int ioff = i_icls->ushort_at(i + inner_class_info_index); 89.57 int ooff = i_icls->ushort_at(i + outer_class_info_index); 89.58 - 89.59 - if (ioff != 0 && ooff != 0) { 89.60 + int noff = i_icls->ushort_at(i + inner_class_inner_name_offset); 89.61 + if (ioff != 0) { 89.62 // Check to see if the name matches the class we're looking for 89.63 // before attempting to find the class. 89.64 if (i_cp->klass_name_at_matches(k, ioff)) { 89.65 klassOop inner_klass = i_cp->klass_at(ioff, CHECK_NULL); 89.66 - if (k() == inner_klass) { 89.67 - found = true; 89.68 + found = (k() == inner_klass); 89.69 + if (found && ooff != 0) { 89.70 ok = i_cp->klass_at(ooff, CHECK_NULL); 89.71 outer_klass = instanceKlassHandle(thread, ok); 89.72 + simple_name_index = noff; 89.73 + inner_is_member = true; 89.74 } 89.75 } 89.76 } 89.77 } 89.78 89.79 + if (found && outer_klass.is_null()) { 89.80 + // It may be anonymous; try for that. 89.81 + int encl_method_class_idx = k->enclosing_method_class_index(); 89.82 + if (encl_method_class_idx != 0) { 89.83 + ok = i_cp->klass_at(encl_method_class_idx, CHECK_NULL); 89.84 + outer_klass = instanceKlassHandle(thread, ok); 89.85 + inner_is_member = false; 89.86 + } 89.87 + } 89.88 + 89.89 // If no inner class attribute found for this class. 89.90 - if (!found) return NULL; 89.91 + if (outer_klass.is_null()) return NULL; 89.92 89.93 // Throws an exception if outer klass has not declared k as an inner klass 89.94 - Reflection::check_for_inner_class(outer_klass, k, CHECK_NULL); 89.95 - 89.96 - return (jclass)JNIHandles::make_local(env, outer_klass->java_mirror()); 89.97 -JVM_END 89.98 - 89.99 + // We need evidence that each klass knows about the other, or else 89.100 + // the system could allow a spoof of an inner class to gain access rights. 89.101 + Reflection::check_for_inner_class(outer_klass, k, inner_is_member, CHECK_NULL); 89.102 + 89.103 + simple_name_result = (inner_is_member ? i_cp->symbol_at(simple_name_index) : symbolOop(NULL)); 89.104 + return outer_klass(); 89.105 +} 89.106 89.107 JVM_ENTRY(jstring, JVM_GetClassSignature(JNIEnv *env, jclass cls)) 89.108 assert (cls != NULL, "illegal class");
90.1 --- a/src/share/vm/runtime/arguments.cpp Wed Apr 01 22:31:26 2009 -0700 90.2 +++ b/src/share/vm/runtime/arguments.cpp Thu Apr 02 17:01:00 2009 -0700 90.3 @@ -1366,9 +1366,6 @@ 90.4 if (AggressiveOpts && FLAG_IS_DEFAULT(DoEscapeAnalysis)) { 90.5 FLAG_SET_DEFAULT(DoEscapeAnalysis, true); 90.6 } 90.7 - if (AggressiveOpts && FLAG_IS_DEFAULT(SpecialArraysEquals)) { 90.8 - FLAG_SET_DEFAULT(SpecialArraysEquals, true); 90.9 - } 90.10 if (AggressiveOpts && FLAG_IS_DEFAULT(BiasedLockingStartupDelay)) { 90.11 FLAG_SET_DEFAULT(BiasedLockingStartupDelay, 500); 90.12 }
91.1 --- a/src/share/vm/runtime/fieldDescriptor.cpp Wed Apr 01 22:31:26 2009 -0700 91.2 +++ b/src/share/vm/runtime/fieldDescriptor.cpp Thu Apr 02 17:01:00 2009 -0700 91.3 @@ -1,5 +1,5 @@ 91.4 /* 91.5 - * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. 91.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 91.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 91.8 * 91.9 * This code is free software; you can redistribute it and/or modify it 91.10 @@ -107,13 +107,14 @@ 91.11 void fieldDescriptor::print_on_for(outputStream* st, oop obj) { 91.12 print_on(st); 91.13 BasicType ft = field_type(); 91.14 - jint as_int; 91.15 + jint as_int = 0; 91.16 switch (ft) { 91.17 case T_BYTE: 91.18 as_int = (jint)obj->byte_field(offset()); 91.19 st->print(" %d", obj->byte_field(offset())); 91.20 break; 91.21 case T_CHAR: 91.22 + as_int = (jint)obj->char_field(offset()); 91.23 { 91.24 jchar c = obj->char_field(offset()); 91.25 as_int = c; 91.26 @@ -128,6 +129,7 @@ 91.27 st->print(" %f", obj->float_field(offset())); 91.28 break; 91.29 case T_INT: 91.30 + as_int = obj->int_field(offset()); 91.31 st->print(" %d", obj->int_field(offset())); 91.32 break; 91.33 case T_LONG: 91.34 @@ -144,12 +146,12 @@ 91.35 break; 91.36 case T_ARRAY: 91.37 st->print(" "); 91.38 - as_int = obj->int_field(offset()); 91.39 + NOT_LP64(as_int = obj->int_field(offset())); 91.40 obj->obj_field(offset())->print_value_on(st); 91.41 break; 91.42 case T_OBJECT: 91.43 st->print(" "); 91.44 - as_int = obj->int_field(offset()); 91.45 + NOT_LP64(as_int = obj->int_field(offset())); 91.46 obj->obj_field(offset())->print_value_on(st); 91.47 break; 91.48 default: 91.49 @@ -158,9 +160,9 @@ 91.50 } 91.51 // Print a hint as to the underlying integer representation. This can be wrong for 91.52 // pointers on an LP64 machine 91.53 - if (ft == T_LONG || ft == T_DOUBLE) { 91.54 + if (ft == T_LONG || ft == T_DOUBLE LP64_ONLY(|| !is_java_primitive(ft)) ) { 91.55 st->print(" (%x %x)", obj->int_field(offset()), obj->int_field(offset()+sizeof(jint))); 91.56 - } else { 91.57 + } else if (as_int < 0 || as_int > 9) { 91.58 st->print(" (%x)", as_int); 91.59 } 91.60 }
92.1 --- a/src/share/vm/runtime/globals.hpp Wed Apr 01 22:31:26 2009 -0700 92.2 +++ b/src/share/vm/runtime/globals.hpp Thu Apr 02 17:01:00 2009 -0700 92.3 @@ -47,6 +47,7 @@ 92.4 define_pd_global(intx, OnStackReplacePercentage, 0); 92.5 define_pd_global(bool, ResizeTLAB, false); 92.6 define_pd_global(intx, FreqInlineSize, 0); 92.7 +define_pd_global(intx, InlineSmallCode, 0); 92.8 define_pd_global(intx, NewSizeThreadIncrease, 4*K); 92.9 define_pd_global(intx, NewRatio, 4); 92.10 define_pd_global(intx, InlineClassNatives, true); 92.11 @@ -490,9 +491,15 @@ 92.12 develop(bool, SpecialStringIndexOf, true, \ 92.13 "special version of string indexOf") \ 92.14 \ 92.15 - product(bool, SpecialArraysEquals, false, \ 92.16 + develop(bool, SpecialStringEquals, true, \ 92.17 + "special version of string equals") \ 92.18 + \ 92.19 + develop(bool, SpecialArraysEquals, true, \ 92.20 "special version of Arrays.equals(char[],char[])") \ 92.21 \ 92.22 + product(bool, UseSSE42Intrinsics, false, \ 92.23 + "SSE4.2 versions of intrinsics") \ 92.24 + \ 92.25 develop(bool, TraceCallFixup, false, \ 92.26 "traces all call fixups") \ 92.27 \ 92.28 @@ -1316,6 +1323,9 @@ 92.29 product(intx, ParGCArrayScanChunk, 50, \ 92.30 "Scan a subset and push remainder, if array is bigger than this") \ 92.31 \ 92.32 + product(bool, ParGCTrimOverflow, true, \ 92.33 + "Eagerly trim the overflow lists (useful for UseCompressedOops") \ 92.34 + \ 92.35 notproduct(bool, ParGCWorkQueueOverflowALot, false, \ 92.36 "Whether we should simulate work queue overflow in ParNew") \ 92.37 \ 92.38 @@ -2616,7 +2626,7 @@ 92.39 develop(intx, MaxRecursiveInlineLevel, 1, \ 92.40 "maximum number of nested recursive calls that are inlined") \ 92.41 \ 92.42 - product(intx, InlineSmallCode, 1000, \ 92.43 + product_pd(intx, InlineSmallCode, \ 92.44 "Only inline already compiled methods if their code size is " \ 92.45 "less than this") \ 92.46 \
93.1 --- a/src/share/vm/runtime/handles.hpp Wed Apr 01 22:31:26 2009 -0700 93.2 +++ b/src/share/vm/runtime/handles.hpp Thu Apr 02 17:01:00 2009 -0700 93.3 @@ -1,5 +1,5 @@ 93.4 /* 93.5 - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 93.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 93.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 93.8 * 93.9 * This code is free software; you can redistribute it and/or modify it 93.10 @@ -137,6 +137,14 @@ 93.11 assert(is_null() || obj()->is_klass(), "not a klassOop"); 93.12 } 93.13 93.14 + // Direct interface, use very sparingly. 93.15 + // Used by SystemDictionaryHandles to create handles on existing WKKs. 93.16 + // The obj of such a klass handle may be null, because the handle is formed 93.17 + // during system bootstrapping. 93.18 + KlassHandle(klassOop *handle, bool dummy) : Handle((oop*)handle, dummy) { 93.19 + assert(SharedSkipVerify || is_null() || obj() == NULL || obj()->is_klass(), "not a klassOop"); 93.20 + } 93.21 + 93.22 // General access 93.23 klassOop operator () () const { return obj(); } 93.24 Klass* operator -> () const { return as_klass(); }
94.1 --- a/src/share/vm/runtime/orderAccess.cpp Wed Apr 01 22:31:26 2009 -0700 94.2 +++ b/src/share/vm/runtime/orderAccess.cpp Thu Apr 02 17:01:00 2009 -0700 94.3 @@ -26,3 +26,15 @@ 94.4 # include "incls/_orderAccess.cpp.incl" 94.5 94.6 volatile intptr_t OrderAccess::dummy = 0; 94.7 + 94.8 +void OrderAccess::StubRoutines_fence() { 94.9 + // Use a stub if it exists. It may not exist during bootstrap so do 94.10 + // nothing in that case but assert if no fence code exists after threads have been created 94.11 + void (*func)() = CAST_TO_FN_PTR(void (*)(), StubRoutines::fence_entry()); 94.12 + 94.13 + if (func != NULL) { 94.14 + (*func)(); 94.15 + return; 94.16 + } 94.17 + assert(Threads::number_of_threads() == 0, "for bootstrap only"); 94.18 +}
95.1 --- a/src/share/vm/runtime/orderAccess.hpp Wed Apr 01 22:31:26 2009 -0700 95.2 +++ b/src/share/vm/runtime/orderAccess.hpp Thu Apr 02 17:01:00 2009 -0700 95.3 @@ -300,4 +300,10 @@ 95.4 // In order to force a memory access, implementations may 95.5 // need a volatile externally visible dummy variable. 95.6 static volatile intptr_t dummy; 95.7 + 95.8 + private: 95.9 + // This is a helper that invokes the StubRoutines::fence_entry() 95.10 + // routine if it exists, It should only be used by platforms that 95.11 + // don't another way to do the inline eassembly. 95.12 + static void StubRoutines_fence(); 95.13 };
96.1 --- a/src/share/vm/runtime/reflection.cpp Wed Apr 01 22:31:26 2009 -0700 96.2 +++ b/src/share/vm/runtime/reflection.cpp Thu Apr 02 17:01:00 2009 -0700 96.3 @@ -1,5 +1,5 @@ 96.4 /* 96.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 96.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 96.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 96.8 * 96.9 * This code is free software; you can redistribute it and/or modify it 96.10 @@ -554,10 +554,18 @@ 96.11 return instanceKlass::cast(class1)->is_same_class_package(class2); 96.12 } 96.13 96.14 +bool Reflection::is_same_package_member(klassOop class1, klassOop class2, TRAPS) { 96.15 + return instanceKlass::cast(class1)->is_same_package_member(class2, THREAD); 96.16 +} 96.17 + 96.18 96.19 // Checks that the 'outer' klass has declared 'inner' as being an inner klass. If not, 96.20 // throw an incompatible class change exception 96.21 -void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner, TRAPS) { 96.22 +// If inner_is_member, require the inner to be a member of the outer. 96.23 +// If !inner_is_member, require the inner to be anonymous (a non-member). 96.24 +// Caller is responsible for figuring out in advance which case must be true. 96.25 +void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner, 96.26 + bool inner_is_member, TRAPS) { 96.27 const int inner_class_info_index = 0; 96.28 const int outer_class_info_index = 1; 96.29 96.30 @@ -567,7 +575,7 @@ 96.31 int ioff = icls->ushort_at(i + inner_class_info_index); 96.32 int ooff = icls->ushort_at(i + outer_class_info_index); 96.33 96.34 - if (ioff != 0 && ooff != 0) { 96.35 + if (inner_is_member && ioff != 0 && ooff != 0) { 96.36 klassOop o = cp->klass_at(ooff, CHECK); 96.37 if (o == outer()) { 96.38 klassOop i = cp->klass_at(ioff, CHECK); 96.39 @@ -576,6 +584,13 @@ 96.40 } 96.41 } 96.42 } 96.43 + if (!inner_is_member && ioff != 0 && ooff == 0 && 96.44 + cp->klass_name_at_matches(inner, ioff)) { 96.45 + klassOop i = cp->klass_at(ioff, CHECK); 96.46 + if (i == inner()) { 96.47 + return; 96.48 + } 96.49 + } 96.50 } 96.51 96.52 // 'inner' not declared as an inner klass in outer
97.1 --- a/src/share/vm/runtime/reflection.hpp Wed Apr 01 22:31:26 2009 -0700 97.2 +++ b/src/share/vm/runtime/reflection.hpp Thu Apr 02 17:01:00 2009 -0700 97.3 @@ -1,5 +1,5 @@ 97.4 /* 97.5 - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. 97.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 97.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 97.8 * 97.9 * This code is free software; you can redistribute it and/or modify it 97.10 @@ -87,12 +87,18 @@ 97.11 bool classloader_only, 97.12 bool protected_restriction = false); 97.13 static bool is_same_class_package(klassOop class1, klassOop class2); 97.14 + static bool is_same_package_member(klassOop class1, klassOop class2, TRAPS); 97.15 97.16 static bool can_relax_access_check_for( 97.17 klassOop accessor, klassOop accesee, bool classloader_only); 97.18 97.19 // inner class reflection 97.20 - static void check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner, TRAPS); 97.21 + // raise an ICCE unless the required relationship can be proven to hold 97.22 + // If inner_is_member, require the inner to be a member of the outer. 97.23 + // If !inner_is_member, require the inner to be anonymous (a non-member). 97.24 + // Caller is responsible for figuring out in advance which case must be true. 97.25 + static void check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner, 97.26 + bool inner_is_member, TRAPS); 97.27 97.28 // 97.29 // Support for reflection based on dynamic bytecode generation (JDK 1.4)
98.1 --- a/src/share/vm/runtime/sharedRuntime.cpp Wed Apr 01 22:31:26 2009 -0700 98.2 +++ b/src/share/vm/runtime/sharedRuntime.cpp Thu Apr 02 17:01:00 2009 -0700 98.3 @@ -675,48 +675,6 @@ 98.4 JRT_END 98.5 98.6 98.7 -// --------------------------------------------------------------------------------------------------------- 98.8 -// Non-product code 98.9 -#ifndef PRODUCT 98.10 - 98.11 -void SharedRuntime::verify_caller_frame(frame caller_frame, methodHandle callee_method) { 98.12 - ResourceMark rm; 98.13 - assert (caller_frame.is_interpreted_frame(), "sanity check"); 98.14 - assert (callee_method->has_compiled_code(), "callee must be compiled"); 98.15 - methodHandle caller_method (Thread::current(), caller_frame.interpreter_frame_method()); 98.16 - jint bci = caller_frame.interpreter_frame_bci(); 98.17 - methodHandle method = find_callee_method_inside_interpreter(caller_frame, caller_method, bci); 98.18 - assert (callee_method == method, "incorrect method"); 98.19 -} 98.20 - 98.21 -methodHandle SharedRuntime::find_callee_method_inside_interpreter(frame caller_frame, methodHandle caller_method, int bci) { 98.22 - EXCEPTION_MARK; 98.23 - Bytecode_invoke* bytecode = Bytecode_invoke_at(caller_method, bci); 98.24 - methodHandle staticCallee = bytecode->static_target(CATCH); // Non-product code 98.25 - 98.26 - bytecode = Bytecode_invoke_at(caller_method, bci); 98.27 - int bytecode_index = bytecode->index(); 98.28 - Bytecodes::Code bc = bytecode->adjusted_invoke_code(); 98.29 - 98.30 - Handle receiver; 98.31 - if (bc == Bytecodes::_invokeinterface || 98.32 - bc == Bytecodes::_invokevirtual || 98.33 - bc == Bytecodes::_invokespecial) { 98.34 - symbolHandle signature (THREAD, staticCallee->signature()); 98.35 - receiver = Handle(THREAD, retrieve_receiver(signature, caller_frame)); 98.36 - } else { 98.37 - receiver = Handle(); 98.38 - } 98.39 - CallInfo result; 98.40 - constantPoolHandle constants (THREAD, caller_method->constants()); 98.41 - LinkResolver::resolve_invoke(result, receiver, constants, bytecode_index, bc, CATCH); // Non-product code 98.42 - methodHandle calleeMethod = result.selected_method(); 98.43 - return calleeMethod; 98.44 -} 98.45 - 98.46 -#endif // PRODUCT 98.47 - 98.48 - 98.49 JRT_ENTRY_NO_ASYNC(void, SharedRuntime::register_finalizer(JavaThread* thread, oopDesc* obj)) 98.50 assert(obj->is_oop(), "must be a valid oop"); 98.51 assert(obj->klass()->klass_part()->has_finalizer(), "shouldn't be here otherwise");
99.1 --- a/src/share/vm/runtime/sharedRuntime.hpp Wed Apr 01 22:31:26 2009 -0700 99.2 +++ b/src/share/vm/runtime/sharedRuntime.hpp Thu Apr 02 17:01:00 2009 -0700 99.3 @@ -1,5 +1,5 @@ 99.4 /* 99.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 99.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 99.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 99.8 * 99.9 * This code is free software; you can redistribute it and/or modify it 99.10 @@ -180,9 +180,6 @@ 99.11 99.12 static oop retrieve_receiver( symbolHandle sig, frame caller ); 99.13 99.14 - static void verify_caller_frame(frame caller_frame, methodHandle callee_method) PRODUCT_RETURN; 99.15 - static methodHandle find_callee_method_inside_interpreter(frame caller_frame, methodHandle caller_method, int bci) PRODUCT_RETURN_(return methodHandle();); 99.16 - 99.17 static void register_finalizer(JavaThread* thread, oopDesc* obj); 99.18 99.19 // dtrace notifications
100.1 --- a/src/share/vm/runtime/thread.cpp Wed Apr 01 22:31:26 2009 -0700 100.2 +++ b/src/share/vm/runtime/thread.cpp Thu Apr 02 17:01:00 2009 -0700 100.3 @@ -3007,17 +3007,19 @@ 100.4 } 100.5 100.6 if (UseStringCache) { 100.7 - // Forcibly initialize java/lang/String and mutate the private 100.8 + // Forcibly initialize java/lang/StringValue and mutate the private 100.9 // static final "stringCacheEnabled" field before we start creating instances 100.10 - klassOop k_o = SystemDictionary::resolve_or_null(vmSymbolHandles::java_lang_String(), Handle(), Handle(), CHECK_0); 100.11 - KlassHandle k = KlassHandle(THREAD, k_o); 100.12 - guarantee(k.not_null(), "Must find java/lang/String"); 100.13 - instanceKlassHandle ik = instanceKlassHandle(THREAD, k()); 100.14 - ik->initialize(CHECK_0); 100.15 - fieldDescriptor fd; 100.16 - // Possible we might not find this field; if so, don't break 100.17 - if (ik->find_local_field(vmSymbols::stringCacheEnabled_name(), vmSymbols::bool_signature(), &fd)) { 100.18 - k()->bool_field_put(fd.offset(), true); 100.19 + klassOop k_o = SystemDictionary::resolve_or_null(vmSymbolHandles::java_lang_StringValue(), Handle(), Handle(), CHECK_0); 100.20 + // Possible that StringValue isn't present: if so, silently don't break 100.21 + if (k_o != NULL) { 100.22 + KlassHandle k = KlassHandle(THREAD, k_o); 100.23 + instanceKlassHandle ik = instanceKlassHandle(THREAD, k()); 100.24 + ik->initialize(CHECK_0); 100.25 + fieldDescriptor fd; 100.26 + // Possible we might not find this field: if so, silently don't break 100.27 + if (ik->find_local_field(vmSymbols::stringCacheEnabled_name(), vmSymbols::bool_signature(), &fd)) { 100.28 + k()->bool_field_put(fd.offset(), true); 100.29 + } 100.30 } 100.31 } 100.32 }
101.1 --- a/src/share/vm/runtime/vm_operations.hpp Wed Apr 01 22:31:26 2009 -0700 101.2 +++ b/src/share/vm/runtime/vm_operations.hpp Thu Apr 02 17:01:00 2009 -0700 101.3 @@ -59,7 +59,6 @@ 101.4 template(G1CollectFull) \ 101.5 template(G1CollectForAllocation) \ 101.6 template(G1IncCollectionPause) \ 101.7 - template(G1PopRegionCollectionPause) \ 101.8 template(EnableBiasedLocking) \ 101.9 template(RevokeBias) \ 101.10 template(BulkRevokeBias) \
102.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 102.2 +++ b/test/compiler/6636138/Test1.java Thu Apr 02 17:01:00 2009 -0700 102.3 @@ -0,0 +1,67 @@ 102.4 +/* 102.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 102.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 102.7 + * 102.8 + * This code is free software; you can redistribute it and/or modify it 102.9 + * under the terms of the GNU General Public License version 2 only, as 102.10 + * published by the Free Software Foundation. 102.11 + * 102.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 102.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 102.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 102.15 + * version 2 for more details (a copy is included in the LICENSE file that 102.16 + * accompanied this code). 102.17 + * 102.18 + * You should have received a copy of the GNU General Public License version 102.19 + * 2 along with this work; if not, write to the Free Software Foundation, 102.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 102.21 + * 102.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 102.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 102.24 + * have any questions. 102.25 + */ 102.26 + 102.27 +/** 102.28 + * @test 102.29 + * @bug 6636138 102.30 + * @summary SuperWord::co_locate_pack(Node_List* p) generates memory graph that leads to memory order violation. 102.31 + * 102.32 + * @run main/othervm -server -Xbatch -XX:CompileOnly=Test1.init -XX:+UseSuperword Test1 102.33 + */ 102.34 + 102.35 +class Test1 { 102.36 + 102.37 + public static void init(int src[], int [] dst, int[] ref) { 102.38 + // initialize the arrays 102.39 + for (int i =0; i<src.length; i++) { 102.40 + src[i] = i; 102.41 + dst[i] = 2; // yes, dst[i] needed(otherwise src[i] will be replaced with i) 102.42 + ref[i] = src[i]; // src[i] depends on the store src[i] 102.43 + } 102.44 + } 102.45 + 102.46 + public static void verify(int src[], int[] ref) { 102.47 + // check whether src and ref are equal 102.48 + for (int i = 0; i < src.length; i++) { 102.49 + if (src[i] != ref[i]) { 102.50 + System.out.println("Error: src and ref don't match at " + i); 102.51 + System.exit(-1); 102.52 + } 102.53 + } 102.54 + } 102.55 + 102.56 + public static void test() { 102.57 + int[] src = new int[34]; 102.58 + int[] dst = new int[34]; 102.59 + int[] ref = new int[34]; 102.60 + 102.61 + init(src, dst, ref); 102.62 + verify(src, ref); 102.63 + } 102.64 + 102.65 + public static void main(String[] args) { 102.66 + for (int i=0; i< 2000; i++) { 102.67 + test(); 102.68 + } 102.69 + } 102.70 +}
103.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 103.2 +++ b/test/compiler/6636138/Test2.java Thu Apr 02 17:01:00 2009 -0700 103.3 @@ -0,0 +1,70 @@ 103.4 +/* 103.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 103.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 103.7 + * 103.8 + * This code is free software; you can redistribute it and/or modify it 103.9 + * under the terms of the GNU General Public License version 2 only, as 103.10 + * published by the Free Software Foundation. 103.11 + * 103.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 103.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 103.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 103.15 + * version 2 for more details (a copy is included in the LICENSE file that 103.16 + * accompanied this code). 103.17 + * 103.18 + * You should have received a copy of the GNU General Public License version 103.19 + * 2 along with this work; if not, write to the Free Software Foundation, 103.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 103.21 + * 103.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 103.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 103.24 + * have any questions. 103.25 + */ 103.26 + 103.27 +/** 103.28 + * @test 103.29 + * @bug 6636138 103.30 + * @summary SuperWord::co_locate_pack(Node_List* p) generates memory graph that leads to memory order violation. 103.31 + * 103.32 + * @run main/othervm -server -Xbatch -XX:CompileOnly=Test2.shift -XX:+UseSuperword Test2 103.33 + */ 103.34 + 103.35 +class Test2 { 103.36 + 103.37 + public static void init(int src[]) { 103.38 + // Initialize the array 103.39 + for (int i = 0; i < src.length; i++) 103.40 + src[i] = i; 103.41 + } 103.42 + 103.43 + public static void shift(int src[]) { 103.44 + //left-shift the array 103.45 + for (int i = src.length-1; i > 0; i--){ 103.46 + int tmp = src[i]; 103.47 + src[i] = src[i-1]; 103.48 + src[i-1] = tmp; 103.49 + } 103.50 + } 103.51 + 103.52 + public static void verify(int src[]) { 103.53 + for (int i = 0; i < src.length; i++){ 103.54 + int value = (i-1 + src.length)%src.length; // correct value after shifting 103.55 + if (src[i] != value) { 103.56 + System.out.println("Error: src["+i+"] should be "+ value + " instead of " + src[i]); 103.57 + System.exit(-1); 103.58 + } 103.59 + } 103.60 + } 103.61 + 103.62 + public static void test() { 103.63 + int[] src = new int[10]; 103.64 + init(src); 103.65 + shift(src); 103.66 + verify(src); 103.67 + } 103.68 + 103.69 + public static void main(String[] args) { 103.70 + for (int i=0; i< 2000; i++) 103.71 + test(); 103.72 + } 103.73 +}