Fri, 09 Oct 2009 15:18:52 -0700
Merge
1.1 --- a/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java Fri Oct 02 11:26:25 2009 -0700 1.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java Fri Oct 09 15:18:52 2009 -0700 1.3 @@ -33,6 +33,7 @@ 1.4 1.5 public class CodeCache { 1.6 private static AddressField heapField; 1.7 + private static AddressField scavengeRootNMethodsField; 1.8 private static VirtualConstructor virtualConstructor; 1.9 1.10 private CodeHeap heap; 1.11 @@ -49,6 +50,7 @@ 1.12 Type type = db.lookupType("CodeCache"); 1.13 1.14 heapField = type.getAddressField("_heap"); 1.15 + scavengeRootNMethodsField = type.getAddressField("_scavenge_root_nmethods"); 1.16 1.17 virtualConstructor = new VirtualConstructor(db); 1.18 // Add mappings for all possible CodeBlob subclasses 1.19 @@ -67,6 +69,10 @@ 1.20 heap = (CodeHeap) VMObjectFactory.newObject(CodeHeap.class, heapField.getValue()); 1.21 } 1.22 1.23 + public NMethod scavengeRootMethods() { 1.24 + return (NMethod) VMObjectFactory.newObject(NMethod.class, scavengeRootNMethodsField.getValue()); 1.25 + } 1.26 + 1.27 public boolean contains(Address p) { 1.28 return getHeap().contains(p); 1.29 }
2.1 --- a/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Fri Oct 02 11:26:25 2009 -0700 2.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Fri Oct 09 15:18:52 2009 -0700 2.3 @@ -40,7 +40,10 @@ 2.4 /** != InvocationEntryBci if this nmethod is an on-stack replacement method */ 2.5 private static CIntegerField entryBCIField; 2.6 /** To support simple linked-list chaining of nmethods */ 2.7 - private static AddressField linkField; 2.8 + private static AddressField osrLinkField; 2.9 + private static AddressField scavengeRootLinkField; 2.10 + private static CIntegerField scavengeRootStateField; 2.11 + 2.12 /** Offsets for different nmethod parts */ 2.13 private static CIntegerField exceptionOffsetField; 2.14 private static CIntegerField deoptOffsetField; 2.15 @@ -87,7 +90,10 @@ 2.16 zombieInstructionSizeField = type.getCIntegerField("_zombie_instruction_size"); 2.17 methodField = type.getOopField("_method"); 2.18 entryBCIField = type.getCIntegerField("_entry_bci"); 2.19 - linkField = type.getAddressField("_link"); 2.20 + osrLinkField = type.getAddressField("_osr_link"); 2.21 + scavengeRootLinkField = type.getAddressField("_scavenge_root_link"); 2.22 + scavengeRootStateField = type.getCIntegerField("_scavenge_root_state"); 2.23 + 2.24 exceptionOffsetField = type.getCIntegerField("_exception_offset"); 2.25 deoptOffsetField = type.getCIntegerField("_deoptimize_offset"); 2.26 origPCOffsetField = type.getCIntegerField("_orig_pc_offset"); 2.27 @@ -219,10 +225,19 @@ 2.28 return getEntryBCI(); 2.29 } 2.30 2.31 - public NMethod getLink() { 2.32 - return (NMethod) VMObjectFactory.newObject(NMethod.class, linkField.getValue(addr)); 2.33 + public NMethod getOSRLink() { 2.34 + return (NMethod) VMObjectFactory.newObject(NMethod.class, osrLinkField.getValue(addr)); 2.35 } 2.36 2.37 + public NMethod getScavengeRootLink() { 2.38 + return (NMethod) VMObjectFactory.newObject(NMethod.class, scavengeRootLinkField.getValue(addr)); 2.39 + } 2.40 + 2.41 + public int getScavengeRootState() { 2.42 + return (int) scavengeRootStateField.getValue(addr); 2.43 + } 2.44 + 2.45 + 2.46 /** Tells whether frames described by this nmethod can be 2.47 deoptimized. Note: native wrappers cannot be deoptimized. */ 2.48 public boolean canBeDeoptimized() { return isJavaMethod(); }
3.1 --- a/src/cpu/sparc/vm/assembler_sparc.cpp Fri Oct 02 11:26:25 2009 -0700 3.2 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp Fri Oct 09 15:18:52 2009 -0700 3.3 @@ -4676,3 +4676,50 @@ 3.4 load_ptr_contents(base, G6_heapbase); 3.5 } 3.6 } 3.7 + 3.8 +// Compare char[] arrays aligned to 4 bytes. 3.9 +void MacroAssembler::char_arrays_equals(Register ary1, Register ary2, 3.10 + Register limit, Register result, 3.11 + Register chr1, Register chr2, Label& Ldone) { 3.12 + Label Lvector, Lloop; 3.13 + assert(chr1 == result, "should be the same"); 3.14 + 3.15 + // Note: limit contains number of bytes (2*char_elements) != 0. 3.16 + andcc(limit, 0x2, chr1); // trailing character ? 3.17 + br(Assembler::zero, false, Assembler::pt, Lvector); 3.18 + delayed()->nop(); 3.19 + 3.20 + // compare the trailing char 3.21 + sub(limit, sizeof(jchar), limit); 3.22 + lduh(ary1, limit, chr1); 3.23 + lduh(ary2, limit, chr2); 3.24 + cmp(chr1, chr2); 3.25 + br(Assembler::notEqual, true, Assembler::pt, Ldone); 3.26 + delayed()->mov(G0, result); // not equal 3.27 + 3.28 + // only one char ? 3.29 + br_on_reg_cond(rc_z, true, Assembler::pn, limit, Ldone); 3.30 + delayed()->add(G0, 1, result); // zero-length arrays are equal 3.31 + 3.32 + // word by word compare, dont't need alignment check 3.33 + bind(Lvector); 3.34 + // Shift ary1 and ary2 to the end of the arrays, negate limit 3.35 + add(ary1, limit, ary1); 3.36 + add(ary2, limit, ary2); 3.37 + neg(limit, limit); 3.38 + 3.39 + lduw(ary1, limit, chr1); 3.40 + bind(Lloop); 3.41 + lduw(ary2, limit, chr2); 3.42 + cmp(chr1, chr2); 3.43 + br(Assembler::notEqual, true, Assembler::pt, Ldone); 3.44 + delayed()->mov(G0, result); // not equal 3.45 + inccc(limit, 2*sizeof(jchar)); 3.46 + // annul LDUW if branch is not taken to prevent access past end of array 3.47 + br(Assembler::notZero, true, Assembler::pt, Lloop); 3.48 + delayed()->lduw(ary1, limit, chr1); // hoisted 3.49 + 3.50 + // Caller should set it: 3.51 + // add(G0, 1, result); // equals 3.52 +} 3.53 +
4.1 --- a/src/cpu/sparc/vm/assembler_sparc.hpp Fri Oct 02 11:26:25 2009 -0700 4.2 +++ b/src/cpu/sparc/vm/assembler_sparc.hpp Fri Oct 09 15:18:52 2009 -0700 4.3 @@ -2455,6 +2455,11 @@ 4.4 void inc_counter(address counter_addr, Register Rtmp1, Register Rtmp2); 4.5 void inc_counter(int* counter_addr, Register Rtmp1, Register Rtmp2); 4.6 4.7 + // Compare char[] arrays aligned to 4 bytes. 4.8 + void char_arrays_equals(Register ary1, Register ary2, 4.9 + Register limit, Register result, 4.10 + Register chr1, Register chr2, Label& Ldone); 4.11 + 4.12 #undef VIRTUAL 4.13 4.14 };
5.1 --- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Fri Oct 02 11:26:25 2009 -0700 5.2 +++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Fri Oct 09 15:18:52 2009 -0700 5.3 @@ -2171,7 +2171,7 @@ 5.4 // subtype which we can't check or src is the same array as dst 5.5 // but not necessarily exactly of type default_type. 5.6 Label known_ok, halt; 5.7 - jobject2reg(op->expected_type()->encoding(), tmp); 5.8 + jobject2reg(op->expected_type()->constant_encoding(), tmp); 5.9 __ ld_ptr(dst, oopDesc::klass_offset_in_bytes(), tmp2); 5.10 if (basic_type != T_OBJECT) { 5.11 __ cmp(tmp, tmp2); 5.12 @@ -2429,7 +2429,7 @@ 5.13 assert(data->is_BitData(), "need BitData for checkcast"); 5.14 Register mdo = k_RInfo; 5.15 Register data_val = Rtmp1; 5.16 - jobject2reg(md->encoding(), mdo); 5.17 + jobject2reg(md->constant_encoding(), mdo); 5.18 5.19 int mdo_offset_bias = 0; 5.20 if (!Assembler::is_simm13(md->byte_offset_of_slot(data, DataLayout::header_offset()) + data->size_in_bytes())) { 5.21 @@ -2452,7 +2452,7 @@ 5.22 // patching may screw with our temporaries on sparc, 5.23 // so let's do it before loading the class 5.24 if (k->is_loaded()) { 5.25 - jobject2reg(k->encoding(), k_RInfo); 5.26 + jobject2reg(k->constant_encoding(), k_RInfo); 5.27 } else { 5.28 jobject2reg_with_patching(k_RInfo, op->info_for_patch()); 5.29 } 5.30 @@ -2513,7 +2513,7 @@ 5.31 // patching may screw with our temporaries on sparc, 5.32 // so let's do it before loading the class 5.33 if (k->is_loaded()) { 5.34 - jobject2reg(k->encoding(), k_RInfo); 5.35 + jobject2reg(k->constant_encoding(), k_RInfo); 5.36 } else { 5.37 jobject2reg_with_patching(k_RInfo, op->info_for_patch()); 5.38 } 5.39 @@ -2717,7 +2717,7 @@ 5.40 assert(op->tmp1()->is_single_cpu(), "tmp1 must be allocated"); 5.41 Register mdo = op->mdo()->as_register(); 5.42 Register tmp1 = op->tmp1()->as_register(); 5.43 - jobject2reg(md->encoding(), mdo); 5.44 + jobject2reg(md->constant_encoding(), mdo); 5.45 int mdo_offset_bias = 0; 5.46 if (!Assembler::is_simm13(md->byte_offset_of_slot(data, CounterData::count_offset()) + 5.47 data->size_in_bytes())) { 5.48 @@ -2774,7 +2774,7 @@ 5.49 if (receiver == NULL) { 5.50 Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)) - 5.51 mdo_offset_bias); 5.52 - jobject2reg(known_klass->encoding(), tmp1); 5.53 + jobject2reg(known_klass->constant_encoding(), tmp1); 5.54 __ st_ptr(tmp1, recv_addr); 5.55 Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)) - 5.56 mdo_offset_bias);
6.1 --- a/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Fri Oct 02 11:26:25 2009 -0700 6.2 +++ b/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Fri Oct 09 15:18:52 2009 -0700 6.3 @@ -668,7 +668,7 @@ 6.4 __ add(obj.result(), offset.result(), addr); 6.5 6.6 if (type == objectType) { // Write-barrier needed for Object fields. 6.7 - pre_barrier(obj.result(), false, NULL); 6.8 + pre_barrier(addr, false, NULL); 6.9 } 6.10 6.11 if (type == objectType) 6.12 @@ -896,7 +896,7 @@ 6.13 LIR_Opr len = length.result(); 6.14 BasicType elem_type = x->elt_type(); 6.15 6.16 - __ oop2reg(ciTypeArrayKlass::make(elem_type)->encoding(), klass_reg); 6.17 + __ oop2reg(ciTypeArrayKlass::make(elem_type)->constant_encoding(), klass_reg); 6.18 6.19 CodeStub* slow_path = new NewTypeArrayStub(klass_reg, len, reg, info); 6.20 __ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, elem_type, klass_reg, slow_path);
7.1 --- a/src/cpu/sparc/vm/sparc.ad Fri Oct 02 11:26:25 2009 -0700 7.2 +++ b/src/cpu/sparc/vm/sparc.ad Fri Oct 09 15:18:52 2009 -0700 7.3 @@ -2838,63 +2838,41 @@ 7.4 %} 7.5 7.6 7.7 - enc_class enc_String_Compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{ 7.8 + enc_class enc_String_Compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result) %{ 7.9 Label Ldone, Lloop; 7.10 MacroAssembler _masm(&cbuf); 7.11 7.12 Register str1_reg = reg_to_register_object($str1$$reg); 7.13 Register str2_reg = reg_to_register_object($str2$$reg); 7.14 - Register tmp1_reg = reg_to_register_object($tmp1$$reg); 7.15 - Register tmp2_reg = reg_to_register_object($tmp2$$reg); 7.16 + Register cnt1_reg = reg_to_register_object($cnt1$$reg); 7.17 + Register cnt2_reg = reg_to_register_object($cnt2$$reg); 7.18 Register result_reg = reg_to_register_object($result$$reg); 7.19 7.20 - // Get the first character position in both strings 7.21 - // [8] char array, [12] offset, [16] count 7.22 - int value_offset = java_lang_String:: value_offset_in_bytes(); 7.23 - int offset_offset = java_lang_String::offset_offset_in_bytes(); 7.24 - int count_offset = java_lang_String:: count_offset_in_bytes(); 7.25 - 7.26 - // load str1 (jchar*) base address into tmp1_reg 7.27 - __ load_heap_oop(str1_reg, value_offset, tmp1_reg); 7.28 - __ ld(str1_reg, offset_offset, result_reg); 7.29 - __ add(tmp1_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1_reg); 7.30 - __ ld(str1_reg, count_offset, str1_reg); // hoisted 7.31 - __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg); 7.32 - __ load_heap_oop(str2_reg, value_offset, tmp2_reg); // hoisted 7.33 - __ add(result_reg, tmp1_reg, tmp1_reg); 7.34 - 7.35 - // load str2 (jchar*) base address into tmp2_reg 7.36 - // __ ld_ptr(str2_reg, value_offset, tmp2_reg); // hoisted 7.37 - __ ld(str2_reg, offset_offset, result_reg); 7.38 - __ add(tmp2_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp2_reg); 7.39 - __ ld(str2_reg, count_offset, str2_reg); // hoisted 7.40 - __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg); 7.41 - __ subcc(str1_reg, str2_reg, O7); // hoisted 7.42 - __ add(result_reg, tmp2_reg, tmp2_reg); 7.43 + assert(result_reg != str1_reg && 7.44 + result_reg != str2_reg && 7.45 + result_reg != cnt1_reg && 7.46 + result_reg != cnt2_reg , 7.47 + "need different registers"); 7.48 7.49 // Compute the minimum of the string lengths(str1_reg) and the 7.50 // difference of the string lengths (stack) 7.51 7.52 - // discard string base pointers, after loading up the lengths 7.53 - // __ ld(str1_reg, count_offset, str1_reg); // hoisted 7.54 - // __ ld(str2_reg, count_offset, str2_reg); // hoisted 7.55 - 7.56 // See if the lengths are different, and calculate min in str1_reg. 7.57 // Stash diff in O7 in case we need it for a tie-breaker. 7.58 Label Lskip; 7.59 - // __ subcc(str1_reg, str2_reg, O7); // hoisted 7.60 - __ sll(str1_reg, exact_log2(sizeof(jchar)), str1_reg); // scale the limit 7.61 + __ subcc(cnt1_reg, cnt2_reg, O7); 7.62 + __ sll(cnt1_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit 7.63 __ br(Assembler::greater, true, Assembler::pt, Lskip); 7.64 - // str2 is shorter, so use its count: 7.65 - __ delayed()->sll(str2_reg, exact_log2(sizeof(jchar)), str1_reg); // scale the limit 7.66 + // cnt2 is shorter, so use its count: 7.67 + __ delayed()->sll(cnt2_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit 7.68 __ bind(Lskip); 7.69 7.70 - // reallocate str1_reg, str2_reg, result_reg 7.71 + // reallocate cnt1_reg, cnt2_reg, result_reg 7.72 // Note: limit_reg holds the string length pre-scaled by 2 7.73 - Register limit_reg = str1_reg; 7.74 - Register chr2_reg = str2_reg; 7.75 + Register limit_reg = cnt1_reg; 7.76 + Register chr2_reg = cnt2_reg; 7.77 Register chr1_reg = result_reg; 7.78 - // tmp{12} are the base pointers 7.79 + // str{12} are the base pointers 7.80 7.81 // Is the minimum length zero? 7.82 __ cmp(limit_reg, (int)(0 * sizeof(jchar))); // use cast to resolve overloading ambiguity 7.83 @@ -2902,8 +2880,8 @@ 7.84 __ delayed()->mov(O7, result_reg); // result is difference in lengths 7.85 7.86 // Load first characters 7.87 - __ lduh(tmp1_reg, 0, chr1_reg); 7.88 - __ lduh(tmp2_reg, 0, chr2_reg); 7.89 + __ lduh(str1_reg, 0, chr1_reg); 7.90 + __ lduh(str2_reg, 0, chr2_reg); 7.91 7.92 // Compare first characters 7.93 __ subcc(chr1_reg, chr2_reg, chr1_reg); 7.94 @@ -2915,7 +2893,7 @@ 7.95 // Check after comparing first character to see if strings are equivalent 7.96 Label LSkip2; 7.97 // Check if the strings start at same location 7.98 - __ cmp(tmp1_reg, tmp2_reg); 7.99 + __ cmp(str1_reg, str2_reg); 7.100 __ brx(Assembler::notEqual, true, Assembler::pt, LSkip2); 7.101 __ delayed()->nop(); 7.102 7.103 @@ -2932,23 +2910,23 @@ 7.104 __ br(Assembler::equal, true, Assembler::pn, Ldone); 7.105 __ delayed()->mov(O7, result_reg); // result is difference in lengths 7.106 7.107 - // Shift tmp1_reg and tmp2_reg to the end of the arrays, negate limit 7.108 - __ add(tmp1_reg, limit_reg, tmp1_reg); 7.109 - __ add(tmp2_reg, limit_reg, tmp2_reg); 7.110 + // Shift str1_reg and str2_reg to the end of the arrays, negate limit 7.111 + __ add(str1_reg, limit_reg, str1_reg); 7.112 + __ add(str2_reg, limit_reg, str2_reg); 7.113 __ neg(chr1_reg, limit_reg); // limit = -(limit-2) 7.114 7.115 // Compare the rest of the characters 7.116 - __ lduh(tmp1_reg, limit_reg, chr1_reg); 7.117 + __ lduh(str1_reg, limit_reg, chr1_reg); 7.118 __ bind(Lloop); 7.119 - // __ lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted 7.120 - __ lduh(tmp2_reg, limit_reg, chr2_reg); 7.121 + // __ lduh(str1_reg, limit_reg, chr1_reg); // hoisted 7.122 + __ lduh(str2_reg, limit_reg, chr2_reg); 7.123 __ subcc(chr1_reg, chr2_reg, chr1_reg); 7.124 __ br(Assembler::notZero, false, Assembler::pt, Ldone); 7.125 assert(chr1_reg == result_reg, "result must be pre-placed"); 7.126 __ delayed()->inccc(limit_reg, sizeof(jchar)); 7.127 // annul LDUH if branch is not taken to prevent access past end of string 7.128 __ br(Assembler::notZero, true, Assembler::pt, Lloop); 7.129 - __ delayed()->lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted 7.130 + __ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted 7.131 7.132 // If strings are equal up to min length, return the length difference. 7.133 __ mov(O7, result_reg); 7.134 @@ -2957,125 +2935,80 @@ 7.135 __ bind(Ldone); 7.136 %} 7.137 7.138 -enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{ 7.139 - Label Lword, Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone; 7.140 +enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result) %{ 7.141 + Label Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone; 7.142 MacroAssembler _masm(&cbuf); 7.143 7.144 Register str1_reg = reg_to_register_object($str1$$reg); 7.145 Register str2_reg = reg_to_register_object($str2$$reg); 7.146 - Register tmp1_reg = reg_to_register_object($tmp1$$reg); 7.147 - Register tmp2_reg = reg_to_register_object($tmp2$$reg); 7.148 + Register cnt_reg = reg_to_register_object($cnt$$reg); 7.149 + Register tmp1_reg = O7; 7.150 Register result_reg = reg_to_register_object($result$$reg); 7.151 7.152 - // Get the first character position in both strings 7.153 - // [8] char array, [12] offset, [16] count 7.154 - int value_offset = java_lang_String:: value_offset_in_bytes(); 7.155 - int offset_offset = java_lang_String::offset_offset_in_bytes(); 7.156 - int count_offset = java_lang_String:: count_offset_in_bytes(); 7.157 - 7.158 - // load str1 (jchar*) base address into tmp1_reg 7.159 - __ load_heap_oop(Address(str1_reg, value_offset), tmp1_reg); 7.160 - __ ld(Address(str1_reg, offset_offset), result_reg); 7.161 - __ add(tmp1_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1_reg); 7.162 - __ ld(Address(str1_reg, count_offset), str1_reg); // hoisted 7.163 - __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg); 7.164 - __ load_heap_oop(Address(str2_reg, value_offset), tmp2_reg); // hoisted 7.165 - __ add(result_reg, tmp1_reg, tmp1_reg); 7.166 - 7.167 - // load str2 (jchar*) base address into tmp2_reg 7.168 - // __ ld_ptr(Address(str2_reg, value_offset), tmp2_reg); // hoisted 7.169 - __ ld(Address(str2_reg, offset_offset), result_reg); 7.170 - __ add(tmp2_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp2_reg); 7.171 - __ ld(Address(str2_reg, count_offset), str2_reg); // hoisted 7.172 - __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg); 7.173 - __ cmp(str1_reg, str2_reg); // hoisted 7.174 - __ add(result_reg, tmp2_reg, tmp2_reg); 7.175 - 7.176 - __ sll(str1_reg, exact_log2(sizeof(jchar)), str1_reg); 7.177 - __ br(Assembler::notEqual, true, Assembler::pt, Ldone); 7.178 - __ delayed()->mov(G0, result_reg); // not equal 7.179 - 7.180 - __ br_zero(Assembler::equal, true, Assembler::pn, str1_reg, Ldone); 7.181 - __ delayed()->add(G0, 1, result_reg); //equals 7.182 - 7.183 - __ cmp(tmp1_reg, tmp2_reg); //same string ? 7.184 + assert(result_reg != str1_reg && 7.185 + result_reg != str2_reg && 7.186 + result_reg != cnt_reg && 7.187 + result_reg != tmp1_reg , 7.188 + "need different registers"); 7.189 + 7.190 + __ cmp(str1_reg, str2_reg); //same char[] ? 7.191 __ brx(Assembler::equal, true, Assembler::pn, Ldone); 7.192 __ delayed()->add(G0, 1, result_reg); 7.193 7.194 + __ br_on_reg_cond(Assembler::rc_z, true, Assembler::pn, cnt_reg, Ldone); 7.195 + __ delayed()->add(G0, 1, result_reg); // count == 0 7.196 + 7.197 //rename registers 7.198 - Register limit_reg = str1_reg; 7.199 - Register chr2_reg = str2_reg; 7.200 + Register limit_reg = cnt_reg; 7.201 Register chr1_reg = result_reg; 7.202 - // tmp{12} are the base pointers 7.203 + Register chr2_reg = tmp1_reg; 7.204 7.205 //check for alignment and position the pointers to the ends 7.206 - __ or3(tmp1_reg, tmp2_reg, chr1_reg); 7.207 - __ andcc(chr1_reg, 0x3, chr1_reg); // notZero means at least one not 4-byte aligned 7.208 - __ br(Assembler::notZero, false, Assembler::pn, Lchar); 7.209 - __ delayed()->nop(); 7.210 - 7.211 - __ bind(Lword); 7.212 - __ and3(limit_reg, 0x2, O7); //remember the remainder (either 0 or 2) 7.213 - __ andn(limit_reg, 0x3, limit_reg); 7.214 - __ br_zero(Assembler::zero, false, Assembler::pn, limit_reg, Lpost_word); 7.215 - __ delayed()->nop(); 7.216 - 7.217 - __ add(tmp1_reg, limit_reg, tmp1_reg); 7.218 - __ add(tmp2_reg, limit_reg, tmp2_reg); 7.219 - __ neg(limit_reg); 7.220 - 7.221 - __ lduw(tmp1_reg, limit_reg, chr1_reg); 7.222 - __ bind(Lword_loop); 7.223 - __ lduw(tmp2_reg, limit_reg, chr2_reg); 7.224 - __ cmp(chr1_reg, chr2_reg); 7.225 - __ br(Assembler::notEqual, true, Assembler::pt, Ldone); 7.226 - __ delayed()->mov(G0, result_reg); 7.227 - __ inccc(limit_reg, 2*sizeof(jchar)); 7.228 - // annul LDUW if branch i s not taken to prevent access past end of string 7.229 - __ br(Assembler::notZero, true, Assembler::pt, Lword_loop); //annul on taken 7.230 - __ delayed()->lduw(tmp1_reg, limit_reg, chr1_reg); // hoisted 7.231 - 7.232 - __ bind(Lpost_word); 7.233 - __ br_zero(Assembler::zero, true, Assembler::pt, O7, Ldone); 7.234 - __ delayed()->add(G0, 1, result_reg); 7.235 - 7.236 - __ lduh(tmp1_reg, 0, chr1_reg); 7.237 - __ lduh(tmp2_reg, 0, chr2_reg); 7.238 - __ cmp (chr1_reg, chr2_reg); 7.239 - __ br(Assembler::notEqual, true, Assembler::pt, Ldone); 7.240 - __ delayed()->mov(G0, result_reg); 7.241 + __ or3(str1_reg, str2_reg, chr1_reg); 7.242 + __ andcc(chr1_reg, 0x3, chr1_reg); 7.243 + // notZero means at least one not 4-byte aligned. 7.244 + // We could optimize the case when both arrays are not aligned 7.245 + // but it is not frequent case and it requires additional checks. 7.246 + __ br(Assembler::notZero, false, Assembler::pn, Lchar); // char by char compare 7.247 + __ delayed()->sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg); // set byte count 7.248 + 7.249 + // Compare char[] arrays aligned to 4 bytes. 7.250 + __ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg, 7.251 + chr1_reg, chr2_reg, Ldone); 7.252 __ ba(false,Ldone); 7.253 __ delayed()->add(G0, 1, result_reg); 7.254 7.255 + // char by char compare 7.256 __ bind(Lchar); 7.257 - __ add(tmp1_reg, limit_reg, tmp1_reg); 7.258 - __ add(tmp2_reg, limit_reg, tmp2_reg); 7.259 + __ add(str1_reg, limit_reg, str1_reg); 7.260 + __ add(str2_reg, limit_reg, str2_reg); 7.261 __ neg(limit_reg); //negate count 7.262 7.263 - __ lduh(tmp1_reg, limit_reg, chr1_reg); 7.264 + __ lduh(str1_reg, limit_reg, chr1_reg); 7.265 + // Lchar_loop 7.266 __ bind(Lchar_loop); 7.267 - __ lduh(tmp2_reg, limit_reg, chr2_reg); 7.268 + __ lduh(str2_reg, limit_reg, chr2_reg); 7.269 __ cmp(chr1_reg, chr2_reg); 7.270 __ br(Assembler::notEqual, true, Assembler::pt, Ldone); 7.271 __ delayed()->mov(G0, result_reg); //not equal 7.272 __ inccc(limit_reg, sizeof(jchar)); 7.273 // annul LDUH if branch is not taken to prevent access past end of string 7.274 - __ br(Assembler::notZero, true, Assembler::pt, Lchar_loop); //annul on taken 7.275 - __ delayed()->lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted 7.276 + __ br(Assembler::notZero, true, Assembler::pt, Lchar_loop); 7.277 + __ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted 7.278 7.279 __ add(G0, 1, result_reg); //equal 7.280 7.281 __ bind(Ldone); 7.282 %} 7.283 7.284 -enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{ 7.285 +enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, notemp_iRegI result) %{ 7.286 Label Lvector, Ldone, Lloop; 7.287 MacroAssembler _masm(&cbuf); 7.288 7.289 Register ary1_reg = reg_to_register_object($ary1$$reg); 7.290 Register ary2_reg = reg_to_register_object($ary2$$reg); 7.291 Register tmp1_reg = reg_to_register_object($tmp1$$reg); 7.292 - Register tmp2_reg = reg_to_register_object($tmp2$$reg); 7.293 + Register tmp2_reg = O7; 7.294 Register result_reg = reg_to_register_object($result$$reg); 7.295 7.296 int length_offset = arrayOopDesc::length_offset_in_bytes(); 7.297 @@ -3101,7 +3034,7 @@ 7.298 __ br(Assembler::notEqual, true, Assembler::pn, Ldone); 7.299 __ delayed()->mov(G0, result_reg); // not equal 7.300 7.301 - __ br_zero(Assembler::zero, true, Assembler::pn, tmp1_reg, Ldone); 7.302 + __ br_on_reg_cond(Assembler::rc_z, true, Assembler::pn, tmp1_reg, Ldone); 7.303 __ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal 7.304 7.305 // load array addresses 7.306 @@ -3109,45 +3042,16 @@ 7.307 __ add(ary2_reg, base_offset, ary2_reg); 7.308 7.309 // renaming registers 7.310 - Register chr1_reg = tmp2_reg; // for characters in ary1 7.311 - Register chr2_reg = result_reg; // for characters in ary2 7.312 + Register chr1_reg = result_reg; // for characters in ary1 7.313 + Register chr2_reg = tmp2_reg; // for characters in ary2 7.314 Register limit_reg = tmp1_reg; // length 7.315 7.316 // set byte count 7.317 __ sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg); 7.318 - __ andcc(limit_reg, 0x2, chr1_reg); //trailing character ? 7.319 - __ br(Assembler::zero, false, Assembler::pt, Lvector); 7.320 - __ delayed()->nop(); 7.321 - 7.322 - //compare the trailing char 7.323 - __ sub(limit_reg, sizeof(jchar), limit_reg); 7.324 - __ lduh(ary1_reg, limit_reg, chr1_reg); 7.325 - __ lduh(ary2_reg, limit_reg, chr2_reg); 7.326 - __ cmp(chr1_reg, chr2_reg); 7.327 - __ br(Assembler::notEqual, true, Assembler::pt, Ldone); 7.328 - __ delayed()->mov(G0, result_reg); // not equal 7.329 - 7.330 - // only one char ? 7.331 - __ br_zero(Assembler::zero, true, Assembler::pn, limit_reg, Ldone); 7.332 - __ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal 7.333 - 7.334 - __ bind(Lvector); 7.335 - // Shift ary1_reg and ary2_reg to the end of the arrays, negate limit 7.336 - __ add(ary1_reg, limit_reg, ary1_reg); 7.337 - __ add(ary2_reg, limit_reg, ary2_reg); 7.338 - __ neg(limit_reg, limit_reg); 7.339 - 7.340 - __ lduw(ary1_reg, limit_reg, chr1_reg); 7.341 - __ bind(Lloop); 7.342 - __ lduw(ary2_reg, limit_reg, chr2_reg); 7.343 - __ cmp(chr1_reg, chr2_reg); 7.344 - __ br(Assembler::notEqual, false, Assembler::pt, Ldone); 7.345 - __ delayed()->mov(G0, result_reg); // not equal 7.346 - __ inccc(limit_reg, 2*sizeof(jchar)); 7.347 - // annul LDUW if branch is not taken to prevent access past end of string 7.348 - __ br(Assembler::notZero, true, Assembler::pt, Lloop); //annul on taken 7.349 - __ delayed()->lduw(ary1_reg, limit_reg, chr1_reg); // hoisted 7.350 - 7.351 + 7.352 + // Compare char[] arrays aligned to 4 bytes. 7.353 + __ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg, 7.354 + chr1_reg, chr2_reg, Ldone); 7.355 __ add(G0, 1, result_reg); // equals 7.356 7.357 __ bind(Ldone); 7.358 @@ -9471,33 +9375,33 @@ 7.359 ins_pipe(long_memory_op); 7.360 %} 7.361 7.362 -instruct string_compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result, 7.363 - o7RegI tmp3, flagsReg ccr) %{ 7.364 - match(Set result (StrComp str1 str2)); 7.365 - effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3); 7.366 +instruct string_compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result, 7.367 + o7RegI tmp, flagsReg ccr) %{ 7.368 + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); 7.369 + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp); 7.370 ins_cost(300); 7.371 - format %{ "String Compare $str1,$str2 -> $result" %} 7.372 - ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, result) ); 7.373 + format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp" %} 7.374 + ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result) ); 7.375 ins_pipe(long_memory_op); 7.376 %} 7.377 7.378 -instruct string_equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result, 7.379 - o7RegI tmp3, flagsReg ccr) %{ 7.380 - match(Set result (StrEquals str1 str2)); 7.381 - effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3); 7.382 +instruct string_equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result, 7.383 + o7RegI tmp, flagsReg ccr) %{ 7.384 + match(Set result (StrEquals (Binary str1 str2) cnt)); 7.385 + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp, KILL ccr); 7.386 ins_cost(300); 7.387 - format %{ "String Equals $str1,$str2 -> $result" %} 7.388 - ins_encode( enc_String_Equals(str1, str2, tmp1, tmp2, result) ); 7.389 + format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp" %} 7.390 + ins_encode( enc_String_Equals(str1, str2, cnt, result) ); 7.391 ins_pipe(long_memory_op); 7.392 %} 7.393 7.394 -instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result, 7.395 - flagsReg ccr) %{ 7.396 +instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result, 7.397 + o7RegI tmp2, flagsReg ccr) %{ 7.398 match(Set result (AryEq ary1 ary2)); 7.399 effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr); 7.400 ins_cost(300); 7.401 - format %{ "Array Equals $ary1,$ary2 -> $result" %} 7.402 - ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result)); 7.403 + format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1,$tmp2" %} 7.404 + ins_encode( enc_Array_Equals(ary1, ary2, tmp1, result)); 7.405 ins_pipe(long_memory_op); 7.406 %} 7.407
8.1 --- a/src/cpu/x86/vm/assembler_x86.cpp Fri Oct 02 11:26:25 2009 -0700 8.2 +++ b/src/cpu/x86/vm/assembler_x86.cpp Fri Oct 09 15:18:52 2009 -0700 8.3 @@ -8404,6 +8404,319 @@ 8.4 } 8.5 #endif // _LP64 8.6 8.7 +// IndexOf substring. 8.8 +void MacroAssembler::string_indexof(Register str1, Register str2, 8.9 + Register cnt1, Register cnt2, Register result, 8.10 + XMMRegister vec, Register tmp) { 8.11 + assert(UseSSE42Intrinsics, "SSE4.2 is required"); 8.12 + 8.13 + Label RELOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR, 8.14 + SCAN_SUBSTR, RET_NOT_FOUND, CLEANUP; 8.15 + 8.16 + push(str1); // string addr 8.17 + push(str2); // substr addr 8.18 + push(cnt2); // substr count 8.19 + jmpb(PREP_FOR_SCAN); 8.20 + 8.21 + // Substr count saved at sp 8.22 + // Substr saved at sp+1*wordSize 8.23 + // String saved at sp+2*wordSize 8.24 + 8.25 + // Reload substr for rescan 8.26 + bind(RELOAD_SUBSTR); 8.27 + movl(cnt2, Address(rsp, 0)); 8.28 + movptr(str2, Address(rsp, wordSize)); 8.29 + // We came here after the beginninig of the substring was 8.30 + // matched but the rest of it was not so we need to search 8.31 + // again. Start from the next element after the previous match. 8.32 + subptr(str1, result); // Restore counter 8.33 + shrl(str1, 1); 8.34 + addl(cnt1, str1); 8.35 + lea(str1, Address(result, 2)); // Reload string 8.36 + 8.37 + // Load substr 8.38 + bind(PREP_FOR_SCAN); 8.39 + movdqu(vec, Address(str2, 0)); 8.40 + addl(cnt1, 8); // prime the loop 8.41 + subptr(str1, 16); 8.42 + 8.43 + // Scan string for substr in 16-byte vectors 8.44 + bind(SCAN_TO_SUBSTR); 8.45 + subl(cnt1, 8); 8.46 + addptr(str1, 16); 8.47 + 8.48 + // pcmpestri 8.49 + // inputs: 8.50 + // xmm - substring 8.51 + // rax - substring length (elements count) 8.52 + // mem - scaned string 8.53 + // rdx - string length (elements count) 8.54 + // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) 8.55 + // outputs: 8.56 + // rcx - matched index in string 8.57 + assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); 8.58 + 8.59 + pcmpestri(vec, Address(str1, 0), 0x0d); 8.60 + jcc(Assembler::above, SCAN_TO_SUBSTR); // CF == 0 && ZF == 0 8.61 + jccb(Assembler::aboveEqual, RET_NOT_FOUND); // CF == 0 8.62 + 8.63 + // Fallthrough: found a potential substr 8.64 + 8.65 + // Make sure string is still long enough 8.66 + subl(cnt1, tmp); 8.67 + cmpl(cnt1, cnt2); 8.68 + jccb(Assembler::negative, RET_NOT_FOUND); 8.69 + // Compute start addr of substr 8.70 + lea(str1, Address(str1, tmp, Address::times_2)); 8.71 + movptr(result, str1); // save 8.72 + 8.73 + // Compare potential substr 8.74 + addl(cnt1, 8); // prime the loop 8.75 + addl(cnt2, 8); 8.76 + subptr(str1, 16); 8.77 + subptr(str2, 16); 8.78 + 8.79 + // Scan 16-byte vectors of string and substr 8.80 + bind(SCAN_SUBSTR); 8.81 + subl(cnt1, 8); 8.82 + subl(cnt2, 8); 8.83 + addptr(str1, 16); 8.84 + addptr(str2, 16); 8.85 + movdqu(vec, Address(str2, 0)); 8.86 + pcmpestri(vec, Address(str1, 0), 0x0d); 8.87 + jcc(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0 8.88 + jcc(Assembler::positive, SCAN_SUBSTR); // SF == 0 8.89 + 8.90 + // Compute substr offset 8.91 + subptr(result, Address(rsp, 2*wordSize)); 8.92 + shrl(result, 1); // index 8.93 + jmpb(CLEANUP); 8.94 + 8.95 + bind(RET_NOT_FOUND); 8.96 + movl(result, -1); 8.97 + 8.98 + bind(CLEANUP); 8.99 + addptr(rsp, 3*wordSize); 8.100 +} 8.101 + 8.102 +// Compare strings. 8.103 +void MacroAssembler::string_compare(Register str1, Register str2, 8.104 + Register cnt1, Register cnt2, Register result, 8.105 + XMMRegister vec1, XMMRegister vec2) { 8.106 + Label LENGTH_DIFF_LABEL, POP_LABEL, DONE_LABEL, WHILE_HEAD_LABEL; 8.107 + 8.108 + // Compute the minimum of the string lengths and the 8.109 + // difference of the string lengths (stack). 8.110 + // Do the conditional move stuff 8.111 + movl(result, cnt1); 8.112 + subl(cnt1, cnt2); 8.113 + push(cnt1); 8.114 + if (VM_Version::supports_cmov()) { 8.115 + cmovl(Assembler::lessEqual, cnt2, result); 8.116 + } else { 8.117 + Label GT_LABEL; 8.118 + jccb(Assembler::greater, GT_LABEL); 8.119 + movl(cnt2, result); 8.120 + bind(GT_LABEL); 8.121 + } 8.122 + 8.123 + // Is the minimum length zero? 8.124 + testl(cnt2, cnt2); 8.125 + jcc(Assembler::zero, LENGTH_DIFF_LABEL); 8.126 + 8.127 + // Load first characters 8.128 + load_unsigned_short(result, Address(str1, 0)); 8.129 + load_unsigned_short(cnt1, Address(str2, 0)); 8.130 + 8.131 + // Compare first characters 8.132 + subl(result, cnt1); 8.133 + jcc(Assembler::notZero, POP_LABEL); 8.134 + decrementl(cnt2); 8.135 + jcc(Assembler::zero, LENGTH_DIFF_LABEL); 8.136 + 8.137 + { 8.138 + // Check after comparing first character to see if strings are equivalent 8.139 + Label LSkip2; 8.140 + // Check if the strings start at same location 8.141 + cmpptr(str1, str2); 8.142 + jccb(Assembler::notEqual, LSkip2); 8.143 + 8.144 + // Check if the length difference is zero (from stack) 8.145 + cmpl(Address(rsp, 0), 0x0); 8.146 + jcc(Assembler::equal, LENGTH_DIFF_LABEL); 8.147 + 8.148 + // Strings might not be equivalent 8.149 + bind(LSkip2); 8.150 + } 8.151 + 8.152 + // Advance to next character 8.153 + addptr(str1, 2); 8.154 + addptr(str2, 2); 8.155 + 8.156 + if (UseSSE42Intrinsics) { 8.157 + // With SSE4.2, use double quad vector compare 8.158 + Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL; 8.159 + // Setup to compare 16-byte vectors 8.160 + movl(cnt1, cnt2); 8.161 + andl(cnt2, 0xfffffff8); // cnt2 holds the vector count 8.162 + andl(cnt1, 0x00000007); // cnt1 holds the tail count 8.163 + testl(cnt2, cnt2); 8.164 + jccb(Assembler::zero, COMPARE_TAIL); 8.165 + 8.166 + lea(str2, Address(str2, cnt2, Address::times_2)); 8.167 + lea(str1, Address(str1, cnt2, Address::times_2)); 8.168 + negptr(cnt2); 8.169 + 8.170 + bind(COMPARE_VECTORS); 8.171 + movdqu(vec1, Address(str1, cnt2, Address::times_2)); 8.172 + movdqu(vec2, Address(str2, cnt2, Address::times_2)); 8.173 + pxor(vec1, vec2); 8.174 + ptest(vec1, vec1); 8.175 + jccb(Assembler::notZero, VECTOR_NOT_EQUAL); 8.176 + addptr(cnt2, 8); 8.177 + jcc(Assembler::notZero, COMPARE_VECTORS); 8.178 + jmpb(COMPARE_TAIL); 8.179 + 8.180 + // Mismatched characters in the vectors 8.181 + bind(VECTOR_NOT_EQUAL); 8.182 + lea(str1, Address(str1, cnt2, Address::times_2)); 8.183 + lea(str2, Address(str2, cnt2, Address::times_2)); 8.184 + movl(cnt1, 8); 8.185 + 8.186 + // Compare tail (< 8 chars), or rescan last vectors to 8.187 + // find 1st mismatched characters 8.188 + bind(COMPARE_TAIL); 8.189 + testl(cnt1, cnt1); 8.190 + jccb(Assembler::zero, LENGTH_DIFF_LABEL); 8.191 + movl(cnt2, cnt1); 8.192 + // Fallthru to tail compare 8.193 + } 8.194 + 8.195 + // Shift str2 and str1 to the end of the arrays, negate min 8.196 + lea(str1, Address(str1, cnt2, Address::times_2, 0)); 8.197 + lea(str2, Address(str2, cnt2, Address::times_2, 0)); 8.198 + negptr(cnt2); 8.199 + 8.200 + // Compare the rest of the characters 8.201 + bind(WHILE_HEAD_LABEL); 8.202 + load_unsigned_short(result, Address(str1, cnt2, Address::times_2, 0)); 8.203 + load_unsigned_short(cnt1, Address(str2, cnt2, Address::times_2, 0)); 8.204 + subl(result, cnt1); 8.205 + jccb(Assembler::notZero, POP_LABEL); 8.206 + increment(cnt2); 8.207 + jcc(Assembler::notZero, WHILE_HEAD_LABEL); 8.208 + 8.209 + // Strings are equal up to min length. Return the length difference. 8.210 + bind(LENGTH_DIFF_LABEL); 8.211 + pop(result); 8.212 + jmpb(DONE_LABEL); 8.213 + 8.214 + // Discard the stored length difference 8.215 + bind(POP_LABEL); 8.216 + addptr(rsp, wordSize); 8.217 + 8.218 + // That's it 8.219 + bind(DONE_LABEL); 8.220 +} 8.221 + 8.222 +// Compare char[] arrays aligned to 4 bytes or substrings. 8.223 +void MacroAssembler::char_arrays_equals(bool is_array_equ, Register ary1, Register ary2, 8.224 + Register limit, Register result, Register chr, 8.225 + XMMRegister vec1, XMMRegister vec2) { 8.226 + Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR; 8.227 + 8.228 + int length_offset = arrayOopDesc::length_offset_in_bytes(); 8.229 + int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 8.230 + 8.231 + // Check the input args 8.232 + cmpptr(ary1, ary2); 8.233 + jcc(Assembler::equal, TRUE_LABEL); 8.234 + 8.235 + if (is_array_equ) { 8.236 + // Need additional checks for arrays_equals. 8.237 + andptr(ary1, ary2); 8.238 + jcc(Assembler::zero, FALSE_LABEL); // One pointer is NULL 8.239 + 8.240 + // Check the lengths 8.241 + movl(limit, Address(ary1, length_offset)); 8.242 + cmpl(limit, Address(ary2, length_offset)); 8.243 + jcc(Assembler::notEqual, FALSE_LABEL); 8.244 + } 8.245 + 8.246 + // count == 0 8.247 + testl(limit, limit); 8.248 + jcc(Assembler::zero, TRUE_LABEL); 8.249 + 8.250 + if (is_array_equ) { 8.251 + // Load array address 8.252 + lea(ary1, Address(ary1, base_offset)); 8.253 + lea(ary2, Address(ary2, base_offset)); 8.254 + } 8.255 + 8.256 + shll(limit, 1); // byte count != 0 8.257 + movl(result, limit); // copy 8.258 + 8.259 + if (UseSSE42Intrinsics) { 8.260 + // With SSE4.2, use double quad vector compare 8.261 + Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; 8.262 + // Compare 16-byte vectors 8.263 + andl(result, 0x0000000e); // tail count (in bytes) 8.264 + andl(limit, 0xfffffff0); // vector count (in bytes) 8.265 + jccb(Assembler::zero, COMPARE_TAIL); 8.266 + 8.267 + lea(ary1, Address(ary1, limit, Address::times_1)); 8.268 + lea(ary2, Address(ary2, limit, Address::times_1)); 8.269 + negptr(limit); 8.270 + 8.271 + bind(COMPARE_WIDE_VECTORS); 8.272 + movdqu(vec1, Address(ary1, limit, Address::times_1)); 8.273 + movdqu(vec2, Address(ary2, limit, Address::times_1)); 8.274 + pxor(vec1, vec2); 8.275 + ptest(vec1, vec1); 8.276 + jccb(Assembler::notZero, FALSE_LABEL); 8.277 + addptr(limit, 16); 8.278 + jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); 8.279 + 8.280 + bind(COMPARE_TAIL); // limit is zero 8.281 + movl(limit, result); 8.282 + // Fallthru to tail compare 8.283 + } 8.284 + 8.285 + // Compare 4-byte vectors 8.286 + andl(limit, 0xfffffffc); // vector count (in bytes) 8.287 + jccb(Assembler::zero, COMPARE_CHAR); 8.288 + 8.289 + lea(ary1, Address(ary1, limit, Address::times_1)); 8.290 + lea(ary2, Address(ary2, limit, Address::times_1)); 8.291 + negptr(limit); 8.292 + 8.293 + bind(COMPARE_VECTORS); 8.294 + movl(chr, Address(ary1, limit, Address::times_1)); 8.295 + cmpl(chr, Address(ary2, limit, Address::times_1)); 8.296 + jccb(Assembler::notEqual, FALSE_LABEL); 8.297 + addptr(limit, 4); 8.298 + jcc(Assembler::notZero, COMPARE_VECTORS); 8.299 + 8.300 + // Compare trailing char (final 2 bytes), if any 8.301 + bind(COMPARE_CHAR); 8.302 + testl(result, 0x2); // tail char 8.303 + jccb(Assembler::zero, TRUE_LABEL); 8.304 + load_unsigned_short(chr, Address(ary1, 0)); 8.305 + load_unsigned_short(limit, Address(ary2, 0)); 8.306 + cmpl(chr, limit); 8.307 + jccb(Assembler::notEqual, FALSE_LABEL); 8.308 + 8.309 + bind(TRUE_LABEL); 8.310 + movl(result, 1); // return true 8.311 + jmpb(DONE); 8.312 + 8.313 + bind(FALSE_LABEL); 8.314 + xorl(result, result); // return false 8.315 + 8.316 + // That's it 8.317 + bind(DONE); 8.318 +} 8.319 + 8.320 Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { 8.321 switch (cond) { 8.322 // Note some conditions are synonyms for others
9.1 --- a/src/cpu/x86/vm/assembler_x86.hpp Fri Oct 02 11:26:25 2009 -0700 9.2 +++ b/src/cpu/x86/vm/assembler_x86.hpp Fri Oct 09 15:18:52 2009 -0700 9.3 @@ -2206,6 +2206,20 @@ 9.4 void movl2ptr(Register dst, Address src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(movl(dst, src)); } 9.5 void movl2ptr(Register dst, Register src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(if (dst != src) movl(dst, src)); } 9.6 9.7 + // IndexOf strings. 9.8 + void string_indexof(Register str1, Register str2, 9.9 + Register cnt1, Register cnt2, Register result, 9.10 + XMMRegister vec, Register tmp); 9.11 + 9.12 + // Compare strings. 9.13 + void string_compare(Register str1, Register str2, 9.14 + Register cnt1, Register cnt2, Register result, 9.15 + XMMRegister vec1, XMMRegister vec2); 9.16 + 9.17 + // Compare char[] arrays. 9.18 + void char_arrays_equals(bool is_array_equ, Register ary1, Register ary2, 9.19 + Register limit, Register result, Register chr, 9.20 + XMMRegister vec1, XMMRegister vec2); 9.21 9.22 #undef VIRTUAL 9.23
10.1 --- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Fri Oct 02 11:26:25 2009 -0700 10.2 +++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Fri Oct 09 15:18:52 2009 -0700 10.3 @@ -1638,7 +1638,7 @@ 10.4 jobject2reg_with_patching(k_RInfo, op->info_for_patch()); 10.5 } else { 10.6 #ifdef _LP64 10.7 - __ movoop(k_RInfo, k->encoding()); 10.8 + __ movoop(k_RInfo, k->constant_encoding()); 10.9 #else 10.10 k_RInfo = noreg; 10.11 #endif // _LP64 10.12 @@ -1661,7 +1661,7 @@ 10.13 assert(data != NULL, "need data for checkcast"); 10.14 assert(data->is_BitData(), "need BitData for checkcast"); 10.15 Register mdo = klass_RInfo; 10.16 - __ movoop(mdo, md->encoding()); 10.17 + __ movoop(mdo, md->constant_encoding()); 10.18 Address data_addr(mdo, md->byte_offset_of_slot(data, DataLayout::header_offset())); 10.19 int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant()); 10.20 __ orl(data_addr, header_bits); 10.21 @@ -1679,7 +1679,7 @@ 10.22 #ifdef _LP64 10.23 __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); 10.24 #else 10.25 - __ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->encoding()); 10.26 + __ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding()); 10.27 #endif // _LP64 10.28 } else { 10.29 __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); 10.30 @@ -1696,7 +1696,7 @@ 10.31 #ifdef _LP64 10.32 __ cmpptr(k_RInfo, Address(klass_RInfo, k->super_check_offset())); 10.33 #else 10.34 - __ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->encoding()); 10.35 + __ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->constant_encoding()); 10.36 #endif // _LP64 10.37 if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() != k->super_check_offset()) { 10.38 __ jcc(Assembler::notEqual, *stub->entry()); 10.39 @@ -1707,7 +1707,7 @@ 10.40 #ifdef _LP64 10.41 __ cmpptr(klass_RInfo, k_RInfo); 10.42 #else 10.43 - __ cmpoop(klass_RInfo, k->encoding()); 10.44 + __ cmpoop(klass_RInfo, k->constant_encoding()); 10.45 #endif // _LP64 10.46 __ jcc(Assembler::equal, done); 10.47 10.48 @@ -1715,7 +1715,7 @@ 10.49 #ifdef _LP64 10.50 __ push(k_RInfo); 10.51 #else 10.52 - __ pushoop(k->encoding()); 10.53 + __ pushoop(k->constant_encoding()); 10.54 #endif // _LP64 10.55 __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); 10.56 __ pop(klass_RInfo); 10.57 @@ -1763,7 +1763,7 @@ 10.58 if (!k->is_loaded()) { 10.59 jobject2reg_with_patching(k_RInfo, op->info_for_patch()); 10.60 } else { 10.61 - LP64_ONLY(__ movoop(k_RInfo, k->encoding())); 10.62 + LP64_ONLY(__ movoop(k_RInfo, k->constant_encoding())); 10.63 } 10.64 assert(obj != k_RInfo, "must be different"); 10.65 10.66 @@ -1774,7 +1774,7 @@ 10.67 // get object class 10.68 // not a safepoint as obj null check happens earlier 10.69 if (LP64_ONLY(false &&) k->is_loaded()) { 10.70 - NOT_LP64(__ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->encoding())); 10.71 + NOT_LP64(__ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding())); 10.72 k_RInfo = noreg; 10.73 } else { 10.74 __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); 10.75 @@ -1791,14 +1791,14 @@ 10.76 #ifndef _LP64 10.77 if (k->is_loaded()) { 10.78 // See if we get an immediate positive hit 10.79 - __ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->encoding()); 10.80 + __ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->constant_encoding()); 10.81 __ jcc(Assembler::equal, one); 10.82 if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() == k->super_check_offset()) { 10.83 // check for self 10.84 - __ cmpoop(klass_RInfo, k->encoding()); 10.85 + __ cmpoop(klass_RInfo, k->constant_encoding()); 10.86 __ jcc(Assembler::equal, one); 10.87 __ push(klass_RInfo); 10.88 - __ pushoop(k->encoding()); 10.89 + __ pushoop(k->constant_encoding()); 10.90 __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); 10.91 __ pop(klass_RInfo); 10.92 __ pop(dst); 10.93 @@ -3112,7 +3112,7 @@ 10.94 // subtype which we can't check or src is the same array as dst 10.95 // but not necessarily exactly of type default_type. 10.96 Label known_ok, halt; 10.97 - __ movoop(tmp, default_type->encoding()); 10.98 + __ movoop(tmp, default_type->constant_encoding()); 10.99 if (basic_type != T_OBJECT) { 10.100 __ cmpptr(tmp, dst_klass_addr); 10.101 __ jcc(Assembler::notEqual, halt); 10.102 @@ -3200,7 +3200,7 @@ 10.103 assert(data->is_CounterData(), "need CounterData for calls"); 10.104 assert(op->mdo()->is_single_cpu(), "mdo must be allocated"); 10.105 Register mdo = op->mdo()->as_register(); 10.106 - __ movoop(mdo, md->encoding()); 10.107 + __ movoop(mdo, md->constant_encoding()); 10.108 Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); 10.109 __ addl(counter_addr, DataLayout::counter_increment); 10.110 Bytecodes::Code bc = method->java_code_at_bci(bci); 10.111 @@ -3240,7 +3240,7 @@ 10.112 ciKlass* receiver = vc_data->receiver(i); 10.113 if (receiver == NULL) { 10.114 Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i))); 10.115 - __ movoop(recv_addr, known_klass->encoding()); 10.116 + __ movoop(recv_addr, known_klass->constant_encoding()); 10.117 Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))); 10.118 __ addl(data_addr, DataLayout::counter_increment); 10.119 return;
11.1 --- a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Fri Oct 02 11:26:25 2009 -0700 11.2 +++ b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Fri Oct 09 15:18:52 2009 -0700 11.3 @@ -994,7 +994,7 @@ 11.4 LIR_Opr len = length.result(); 11.5 BasicType elem_type = x->elt_type(); 11.6 11.7 - __ oop2reg(ciTypeArrayKlass::make(elem_type)->encoding(), klass_reg); 11.8 + __ oop2reg(ciTypeArrayKlass::make(elem_type)->constant_encoding(), klass_reg); 11.9 11.10 CodeStub* slow_path = new NewTypeArrayStub(klass_reg, len, reg, info); 11.11 __ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, elem_type, klass_reg, slow_path);
12.1 --- a/src/cpu/x86/vm/x86_32.ad Fri Oct 02 11:26:25 2009 -0700 12.2 +++ b/src/cpu/x86/vm/x86_32.ad Fri Oct 09 15:18:52 2009 -0700 12.3 @@ -379,7 +379,7 @@ 12.4 int format) { 12.5 #ifdef ASSERT 12.6 if (rspec.reloc()->type() == relocInfo::oop_type && d32 != 0 && d32 != (int)Universe::non_oop_word()) { 12.7 - assert(oop(d32)->is_oop() && oop(d32)->is_perm(), "cannot embed non-perm oops in code"); 12.8 + assert(oop(d32)->is_oop() && (ScavengeRootsInCode || !oop(d32)->is_scavengable()), "cannot embed scavengable oops in code"); 12.9 } 12.10 #endif 12.11 cbuf.relocate(cbuf.inst_mark(), rspec, format); 12.12 @@ -3701,458 +3701,6 @@ 12.13 } 12.14 %} 12.15 12.16 - enc_class enc_String_Compare(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2, 12.17 - eAXRegI tmp3, eBXRegI tmp4, eCXRegI result) %{ 12.18 - Label ECX_GOOD_LABEL, LENGTH_DIFF_LABEL, 12.19 - POP_LABEL, DONE_LABEL, CONT_LABEL, 12.20 - WHILE_HEAD_LABEL; 12.21 - MacroAssembler masm(&cbuf); 12.22 - 12.23 - XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 12.24 - XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 12.25 - 12.26 - // Get the first character position in both strings 12.27 - // [8] char array, [12] offset, [16] count 12.28 - int value_offset = java_lang_String::value_offset_in_bytes(); 12.29 - int offset_offset = java_lang_String::offset_offset_in_bytes(); 12.30 - int count_offset = java_lang_String::count_offset_in_bytes(); 12.31 - int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 12.32 - 12.33 - masm.movptr(rax, Address(rsi, value_offset)); 12.34 - masm.movl(rcx, Address(rsi, offset_offset)); 12.35 - masm.lea(rax, Address(rax, rcx, Address::times_2, base_offset)); 12.36 - masm.movptr(rbx, Address(rdi, value_offset)); 12.37 - masm.movl(rcx, Address(rdi, offset_offset)); 12.38 - masm.lea(rbx, Address(rbx, rcx, Address::times_2, base_offset)); 12.39 - 12.40 - // Compute the minimum of the string lengths(rsi) and the 12.41 - // difference of the string lengths (stack) 12.42 - 12.43 - if (VM_Version::supports_cmov()) { 12.44 - masm.movl(rdi, Address(rdi, count_offset)); 12.45 - masm.movl(rsi, Address(rsi, count_offset)); 12.46 - masm.movl(rcx, rdi); 12.47 - masm.subl(rdi, rsi); 12.48 - masm.push(rdi); 12.49 - masm.cmovl(Assembler::lessEqual, rsi, rcx); 12.50 - } else { 12.51 - masm.movl(rdi, Address(rdi, count_offset)); 12.52 - masm.movl(rcx, Address(rsi, count_offset)); 12.53 - masm.movl(rsi, rdi); 12.54 - masm.subl(rdi, rcx); 12.55 - masm.push(rdi); 12.56 - masm.jccb(Assembler::lessEqual, ECX_GOOD_LABEL); 12.57 - masm.movl(rsi, rcx); 12.58 - // rsi holds min, rcx is unused 12.59 - } 12.60 - 12.61 - // Is the minimum length zero? 12.62 - masm.bind(ECX_GOOD_LABEL); 12.63 - masm.testl(rsi, rsi); 12.64 - masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL); 12.65 - 12.66 - // Load first characters 12.67 - masm.load_unsigned_short(rcx, Address(rbx, 0)); 12.68 - masm.load_unsigned_short(rdi, Address(rax, 0)); 12.69 - 12.70 - // Compare first characters 12.71 - masm.subl(rcx, rdi); 12.72 - masm.jcc(Assembler::notZero, POP_LABEL); 12.73 - masm.decrementl(rsi); 12.74 - masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL); 12.75 - 12.76 - { 12.77 - // Check after comparing first character to see if strings are equivalent 12.78 - Label LSkip2; 12.79 - // Check if the strings start at same location 12.80 - masm.cmpptr(rbx,rax); 12.81 - masm.jccb(Assembler::notEqual, LSkip2); 12.82 - 12.83 - // Check if the length difference is zero (from stack) 12.84 - masm.cmpl(Address(rsp, 0), 0x0); 12.85 - masm.jcc(Assembler::equal, LENGTH_DIFF_LABEL); 12.86 - 12.87 - // Strings might not be equivalent 12.88 - masm.bind(LSkip2); 12.89 - } 12.90 - 12.91 - // Advance to next character 12.92 - masm.addptr(rax, 2); 12.93 - masm.addptr(rbx, 2); 12.94 - 12.95 - if (UseSSE42Intrinsics) { 12.96 - // With SSE4.2, use double quad vector compare 12.97 - Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL; 12.98 - // Setup to compare 16-byte vectors 12.99 - masm.movl(rdi, rsi); 12.100 - masm.andl(rsi, 0xfffffff8); // rsi holds the vector count 12.101 - masm.andl(rdi, 0x00000007); // rdi holds the tail count 12.102 - masm.testl(rsi, rsi); 12.103 - masm.jccb(Assembler::zero, COMPARE_TAIL); 12.104 - 12.105 - masm.lea(rax, Address(rax, rsi, Address::times_2)); 12.106 - masm.lea(rbx, Address(rbx, rsi, Address::times_2)); 12.107 - masm.negl(rsi); 12.108 - 12.109 - masm.bind(COMPARE_VECTORS); 12.110 - masm.movdqu(tmp1Reg, Address(rax, rsi, Address::times_2)); 12.111 - masm.movdqu(tmp2Reg, Address(rbx, rsi, Address::times_2)); 12.112 - masm.pxor(tmp1Reg, tmp2Reg); 12.113 - masm.ptest(tmp1Reg, tmp1Reg); 12.114 - masm.jccb(Assembler::notZero, VECTOR_NOT_EQUAL); 12.115 - masm.addl(rsi, 8); 12.116 - masm.jcc(Assembler::notZero, COMPARE_VECTORS); 12.117 - masm.jmpb(COMPARE_TAIL); 12.118 - 12.119 - // Mismatched characters in the vectors 12.120 - masm.bind(VECTOR_NOT_EQUAL); 12.121 - masm.lea(rax, Address(rax, rsi, Address::times_2)); 12.122 - masm.lea(rbx, Address(rbx, rsi, Address::times_2)); 12.123 - masm.movl(rdi, 8); 12.124 - 12.125 - // Compare tail (< 8 chars), or rescan last vectors to 12.126 - // find 1st mismatched characters 12.127 - masm.bind(COMPARE_TAIL); 12.128 - masm.testl(rdi, rdi); 12.129 - masm.jccb(Assembler::zero, LENGTH_DIFF_LABEL); 12.130 - masm.movl(rsi, rdi); 12.131 - // Fallthru to tail compare 12.132 - } 12.133 - 12.134 - //Shift rax, and rbx, to the end of the arrays, negate min 12.135 - masm.lea(rax, Address(rax, rsi, Address::times_2, 0)); 12.136 - masm.lea(rbx, Address(rbx, rsi, Address::times_2, 0)); 12.137 - masm.negl(rsi); 12.138 - 12.139 - // Compare the rest of the characters 12.140 - masm.bind(WHILE_HEAD_LABEL); 12.141 - masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0)); 12.142 - masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0)); 12.143 - masm.subl(rcx, rdi); 12.144 - masm.jccb(Assembler::notZero, POP_LABEL); 12.145 - masm.incrementl(rsi); 12.146 - masm.jcc(Assembler::notZero, WHILE_HEAD_LABEL); 12.147 - 12.148 - // Strings are equal up to min length. Return the length difference. 12.149 - masm.bind(LENGTH_DIFF_LABEL); 12.150 - masm.pop(rcx); 12.151 - masm.jmpb(DONE_LABEL); 12.152 - 12.153 - // Discard the stored length difference 12.154 - masm.bind(POP_LABEL); 12.155 - masm.addptr(rsp, 4); 12.156 - 12.157 - // That's it 12.158 - masm.bind(DONE_LABEL); 12.159 - %} 12.160 - 12.161 - enc_class enc_String_Equals(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2, 12.162 - eBXRegI tmp3, eCXRegI tmp4, eAXRegI result) %{ 12.163 - Label RET_TRUE, RET_FALSE, DONE, COMPARE_VECTORS, COMPARE_CHAR; 12.164 - MacroAssembler masm(&cbuf); 12.165 - 12.166 - XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 12.167 - XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 12.168 - 12.169 - int value_offset = java_lang_String::value_offset_in_bytes(); 12.170 - int offset_offset = java_lang_String::offset_offset_in_bytes(); 12.171 - int count_offset = java_lang_String::count_offset_in_bytes(); 12.172 - int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 12.173 - 12.174 - // does source == target string? 12.175 - masm.cmpptr(rdi, rsi); 12.176 - masm.jcc(Assembler::equal, RET_TRUE); 12.177 - 12.178 - // get and compare counts 12.179 - masm.movl(rcx, Address(rdi, count_offset)); 12.180 - masm.movl(rax, Address(rsi, count_offset)); 12.181 - masm.cmpl(rcx, rax); 12.182 - masm.jcc(Assembler::notEqual, RET_FALSE); 12.183 - masm.testl(rax, rax); 12.184 - masm.jcc(Assembler::zero, RET_TRUE); 12.185 - 12.186 - // get source string offset and value 12.187 - masm.movptr(rbx, Address(rsi, value_offset)); 12.188 - masm.movl(rax, Address(rsi, offset_offset)); 12.189 - masm.leal(rsi, Address(rbx, rax, Address::times_2, base_offset)); 12.190 - 12.191 - // get compare string offset and value 12.192 - masm.movptr(rbx, Address(rdi, value_offset)); 12.193 - masm.movl(rax, Address(rdi, offset_offset)); 12.194 - masm.leal(rdi, Address(rbx, rax, Address::times_2, base_offset)); 12.195 - 12.196 - // Set byte count 12.197 - masm.shll(rcx, 1); 12.198 - masm.movl(rax, rcx); 12.199 - 12.200 - if (UseSSE42Intrinsics) { 12.201 - // With SSE4.2, use double quad vector compare 12.202 - Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; 12.203 - // Compare 16-byte vectors 12.204 - masm.andl(rcx, 0xfffffff0); // vector count (in bytes) 12.205 - masm.andl(rax, 0x0000000e); // tail count (in bytes) 12.206 - masm.testl(rcx, rcx); 12.207 - masm.jccb(Assembler::zero, COMPARE_TAIL); 12.208 - masm.lea(rdi, Address(rdi, rcx, Address::times_1)); 12.209 - masm.lea(rsi, Address(rsi, rcx, Address::times_1)); 12.210 - masm.negl(rcx); 12.211 - 12.212 - masm.bind(COMPARE_WIDE_VECTORS); 12.213 - masm.movdqu(tmp1Reg, Address(rdi, rcx, Address::times_1)); 12.214 - masm.movdqu(tmp2Reg, Address(rsi, rcx, Address::times_1)); 12.215 - masm.pxor(tmp1Reg, tmp2Reg); 12.216 - masm.ptest(tmp1Reg, tmp1Reg); 12.217 - masm.jccb(Assembler::notZero, RET_FALSE); 12.218 - masm.addl(rcx, 16); 12.219 - masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); 12.220 - masm.bind(COMPARE_TAIL); 12.221 - masm.movl(rcx, rax); 12.222 - // Fallthru to tail compare 12.223 - } 12.224 - 12.225 - // Compare 4-byte vectors 12.226 - masm.andl(rcx, 0xfffffffc); // vector count (in bytes) 12.227 - masm.andl(rax, 0x00000002); // tail char (in bytes) 12.228 - masm.testl(rcx, rcx); 12.229 - masm.jccb(Assembler::zero, COMPARE_CHAR); 12.230 - masm.lea(rdi, Address(rdi, rcx, Address::times_1)); 12.231 - masm.lea(rsi, Address(rsi, rcx, Address::times_1)); 12.232 - masm.negl(rcx); 12.233 - 12.234 - masm.bind(COMPARE_VECTORS); 12.235 - masm.movl(rbx, Address(rdi, rcx, Address::times_1)); 12.236 - masm.cmpl(rbx, Address(rsi, rcx, Address::times_1)); 12.237 - masm.jccb(Assembler::notEqual, RET_FALSE); 12.238 - masm.addl(rcx, 4); 12.239 - masm.jcc(Assembler::notZero, COMPARE_VECTORS); 12.240 - 12.241 - // Compare trailing char (final 2 bytes), if any 12.242 - masm.bind(COMPARE_CHAR); 12.243 - masm.testl(rax, rax); 12.244 - masm.jccb(Assembler::zero, RET_TRUE); 12.245 - masm.load_unsigned_short(rbx, Address(rdi, 0)); 12.246 - masm.load_unsigned_short(rcx, Address(rsi, 0)); 12.247 - masm.cmpl(rbx, rcx); 12.248 - masm.jccb(Assembler::notEqual, RET_FALSE); 12.249 - 12.250 - masm.bind(RET_TRUE); 12.251 - masm.movl(rax, 1); // return true 12.252 - masm.jmpb(DONE); 12.253 - 12.254 - masm.bind(RET_FALSE); 12.255 - masm.xorl(rax, rax); // return false 12.256 - 12.257 - masm.bind(DONE); 12.258 - %} 12.259 - 12.260 - enc_class enc_String_IndexOf(eSIRegP str1, eDIRegP str2, regXD tmp1, eAXRegI tmp2, 12.261 - eCXRegI tmp3, eDXRegI tmp4, eBXRegI result) %{ 12.262 - // SSE4.2 version 12.263 - Label LOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR, 12.264 - SCAN_SUBSTR, RET_NEG_ONE, RET_NOT_FOUND, CLEANUP, DONE; 12.265 - MacroAssembler masm(&cbuf); 12.266 - 12.267 - XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 12.268 - 12.269 - // Get the first character position in both strings 12.270 - // [8] char array, [12] offset, [16] count 12.271 - int value_offset = java_lang_String::value_offset_in_bytes(); 12.272 - int offset_offset = java_lang_String::offset_offset_in_bytes(); 12.273 - int count_offset = java_lang_String::count_offset_in_bytes(); 12.274 - int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 12.275 - 12.276 - // Get counts for string and substr 12.277 - masm.movl(rdx, Address(rsi, count_offset)); 12.278 - masm.movl(rax, Address(rdi, count_offset)); 12.279 - // Check for substr count > string count 12.280 - masm.cmpl(rax, rdx); 12.281 - masm.jcc(Assembler::greater, RET_NEG_ONE); 12.282 - 12.283 - // Start the indexOf operation 12.284 - // Get start addr of string 12.285 - masm.movptr(rbx, Address(rsi, value_offset)); 12.286 - masm.movl(rcx, Address(rsi, offset_offset)); 12.287 - masm.lea(rsi, Address(rbx, rcx, Address::times_2, base_offset)); 12.288 - masm.push(rsi); 12.289 - 12.290 - // Get start addr of substr 12.291 - masm.movptr(rbx, Address(rdi, value_offset)); 12.292 - masm.movl(rcx, Address(rdi, offset_offset)); 12.293 - masm.lea(rdi, Address(rbx, rcx, Address::times_2, base_offset)); 12.294 - masm.push(rdi); 12.295 - masm.push(rax); 12.296 - masm.jmpb(PREP_FOR_SCAN); 12.297 - 12.298 - // Substr count saved at sp 12.299 - // Substr saved at sp+4 12.300 - // String saved at sp+8 12.301 - 12.302 - // Prep to load substr for scan 12.303 - masm.bind(LOAD_SUBSTR); 12.304 - masm.movptr(rdi, Address(rsp, 4)); 12.305 - masm.movl(rax, Address(rsp, 0)); 12.306 - 12.307 - // Load substr 12.308 - masm.bind(PREP_FOR_SCAN); 12.309 - masm.movdqu(tmp1Reg, Address(rdi, 0)); 12.310 - masm.addl(rdx, 8); // prime the loop 12.311 - masm.subptr(rsi, 16); 12.312 - 12.313 - // Scan string for substr in 16-byte vectors 12.314 - masm.bind(SCAN_TO_SUBSTR); 12.315 - masm.subl(rdx, 8); 12.316 - masm.addptr(rsi, 16); 12.317 - masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d); 12.318 - masm.jcc(Assembler::above, SCAN_TO_SUBSTR); // CF == 0 && ZF == 0 12.319 - masm.jccb(Assembler::aboveEqual, RET_NOT_FOUND); // CF == 0 12.320 - 12.321 - // Fallthru: found a potential substr 12.322 - 12.323 - // Make sure string is still long enough 12.324 - masm.subl(rdx, rcx); 12.325 - masm.cmpl(rdx, rax); 12.326 - masm.jccb(Assembler::negative, RET_NOT_FOUND); 12.327 - // Compute start addr of substr 12.328 - masm.lea(rsi, Address(rsi, rcx, Address::times_2)); 12.329 - masm.movptr(rbx, rsi); 12.330 - 12.331 - // Compare potential substr 12.332 - masm.addl(rdx, 8); // prime the loop 12.333 - masm.addl(rax, 8); 12.334 - masm.subptr(rsi, 16); 12.335 - masm.subptr(rdi, 16); 12.336 - 12.337 - // Scan 16-byte vectors of string and substr 12.338 - masm.bind(SCAN_SUBSTR); 12.339 - masm.subl(rax, 8); 12.340 - masm.subl(rdx, 8); 12.341 - masm.addptr(rsi, 16); 12.342 - masm.addptr(rdi, 16); 12.343 - masm.movdqu(tmp1Reg, Address(rdi, 0)); 12.344 - masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d); 12.345 - masm.jcc(Assembler::noOverflow, LOAD_SUBSTR); // OF == 0 12.346 - masm.jcc(Assembler::positive, SCAN_SUBSTR); // SF == 0 12.347 - 12.348 - // Compute substr offset 12.349 - masm.movptr(rsi, Address(rsp, 8)); 12.350 - masm.subptr(rbx, rsi); 12.351 - masm.shrl(rbx, 1); 12.352 - masm.jmpb(CLEANUP); 12.353 - 12.354 - masm.bind(RET_NEG_ONE); 12.355 - masm.movl(rbx, -1); 12.356 - masm.jmpb(DONE); 12.357 - 12.358 - masm.bind(RET_NOT_FOUND); 12.359 - masm.movl(rbx, -1); 12.360 - 12.361 - masm.bind(CLEANUP); 12.362 - masm.addptr(rsp, 12); 12.363 - 12.364 - masm.bind(DONE); 12.365 - %} 12.366 - 12.367 - enc_class enc_Array_Equals(eDIRegP ary1, eSIRegP ary2, regXD tmp1, regXD tmp2, 12.368 - eBXRegI tmp3, eDXRegI tmp4, eAXRegI result) %{ 12.369 - Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR; 12.370 - MacroAssembler masm(&cbuf); 12.371 - 12.372 - XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 12.373 - XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 12.374 - Register ary1Reg = as_Register($ary1$$reg); 12.375 - Register ary2Reg = as_Register($ary2$$reg); 12.376 - Register tmp3Reg = as_Register($tmp3$$reg); 12.377 - Register tmp4Reg = as_Register($tmp4$$reg); 12.378 - Register resultReg = as_Register($result$$reg); 12.379 - 12.380 - int length_offset = arrayOopDesc::length_offset_in_bytes(); 12.381 - int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 12.382 - 12.383 - // Check the input args 12.384 - masm.cmpptr(ary1Reg, ary2Reg); 12.385 - masm.jcc(Assembler::equal, TRUE_LABEL); 12.386 - masm.testptr(ary1Reg, ary1Reg); 12.387 - masm.jcc(Assembler::zero, FALSE_LABEL); 12.388 - masm.testptr(ary2Reg, ary2Reg); 12.389 - masm.jcc(Assembler::zero, FALSE_LABEL); 12.390 - 12.391 - // Check the lengths 12.392 - masm.movl(tmp4Reg, Address(ary1Reg, length_offset)); 12.393 - masm.movl(resultReg, Address(ary2Reg, length_offset)); 12.394 - masm.cmpl(tmp4Reg, resultReg); 12.395 - masm.jcc(Assembler::notEqual, FALSE_LABEL); 12.396 - masm.testl(resultReg, resultReg); 12.397 - masm.jcc(Assembler::zero, TRUE_LABEL); 12.398 - 12.399 - // Load array addrs 12.400 - masm.lea(ary1Reg, Address(ary1Reg, base_offset)); 12.401 - masm.lea(ary2Reg, Address(ary2Reg, base_offset)); 12.402 - 12.403 - // Set byte count 12.404 - masm.shll(tmp4Reg, 1); 12.405 - masm.movl(resultReg, tmp4Reg); 12.406 - 12.407 - if (UseSSE42Intrinsics) { 12.408 - // With SSE4.2, use double quad vector compare 12.409 - Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; 12.410 - // Compare 16-byte vectors 12.411 - masm.andl(tmp4Reg, 0xfffffff0); // vector count (in bytes) 12.412 - masm.andl(resultReg, 0x0000000e); // tail count (in bytes) 12.413 - masm.testl(tmp4Reg, tmp4Reg); 12.414 - masm.jccb(Assembler::zero, COMPARE_TAIL); 12.415 - masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 12.416 - masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 12.417 - masm.negl(tmp4Reg); 12.418 - 12.419 - masm.bind(COMPARE_WIDE_VECTORS); 12.420 - masm.movdqu(tmp1Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 12.421 - masm.movdqu(tmp2Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 12.422 - masm.pxor(tmp1Reg, tmp2Reg); 12.423 - masm.ptest(tmp1Reg, tmp1Reg); 12.424 - 12.425 - masm.jccb(Assembler::notZero, FALSE_LABEL); 12.426 - masm.addl(tmp4Reg, 16); 12.427 - masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); 12.428 - masm.bind(COMPARE_TAIL); 12.429 - masm.movl(tmp4Reg, resultReg); 12.430 - // Fallthru to tail compare 12.431 - } 12.432 - 12.433 - // Compare 4-byte vectors 12.434 - masm.andl(tmp4Reg, 0xfffffffc); // vector count (in bytes) 12.435 - masm.andl(resultReg, 0x00000002); // tail char (in bytes) 12.436 - masm.testl(tmp4Reg, tmp4Reg); 12.437 - masm.jccb(Assembler::zero, COMPARE_CHAR); 12.438 - masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 12.439 - masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 12.440 - masm.negl(tmp4Reg); 12.441 - 12.442 - masm.bind(COMPARE_VECTORS); 12.443 - masm.movl(tmp3Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 12.444 - masm.cmpl(tmp3Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 12.445 - masm.jccb(Assembler::notEqual, FALSE_LABEL); 12.446 - masm.addl(tmp4Reg, 4); 12.447 - masm.jcc(Assembler::notZero, COMPARE_VECTORS); 12.448 - 12.449 - // Compare trailing char (final 2 bytes), if any 12.450 - masm.bind(COMPARE_CHAR); 12.451 - masm.testl(resultReg, resultReg); 12.452 - masm.jccb(Assembler::zero, TRUE_LABEL); 12.453 - masm.load_unsigned_short(tmp3Reg, Address(ary1Reg, 0)); 12.454 - masm.load_unsigned_short(tmp4Reg, Address(ary2Reg, 0)); 12.455 - masm.cmpl(tmp3Reg, tmp4Reg); 12.456 - masm.jccb(Assembler::notEqual, FALSE_LABEL); 12.457 - 12.458 - masm.bind(TRUE_LABEL); 12.459 - masm.movl(resultReg, 1); // return true 12.460 - masm.jmpb(DONE); 12.461 - 12.462 - masm.bind(FALSE_LABEL); 12.463 - masm.xorl(resultReg, resultReg); // return false 12.464 - 12.465 - // That's it 12.466 - masm.bind(DONE); 12.467 - %} 12.468 12.469 enc_class enc_pop_rdx() %{ 12.470 emit_opcode(cbuf,0x5A); 12.471 @@ -12718,48 +12266,64 @@ 12.472 ins_pipe( pipe_slow ); 12.473 %} 12.474 12.475 -instruct string_compare(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2, 12.476 - eAXRegI tmp3, eBXRegI tmp4, eCXRegI result, eFlagsReg cr) %{ 12.477 - match(Set result (StrComp str1 str2)); 12.478 - effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr); 12.479 - //ins_cost(300); 12.480 - 12.481 - format %{ "String Compare $str1,$str2 -> $result // KILL EAX, EBX" %} 12.482 - ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, tmp3, tmp4, result) ); 12.483 +instruct string_compare(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eBXRegI cnt2, 12.484 + eAXRegI result, regXD tmp1, regXD tmp2, eFlagsReg cr) %{ 12.485 + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); 12.486 + effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); 12.487 + 12.488 + format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1, $tmp2" %} 12.489 + ins_encode %{ 12.490 + __ string_compare($str1$$Register, $str2$$Register, 12.491 + $cnt1$$Register, $cnt2$$Register, $result$$Register, 12.492 + $tmp1$$XMMRegister, $tmp2$$XMMRegister); 12.493 + %} 12.494 ins_pipe( pipe_slow ); 12.495 %} 12.496 12.497 // fast string equals 12.498 -instruct string_equals(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2, 12.499 - eBXRegI tmp3, eCXRegI tmp4, eAXRegI result, eFlagsReg cr) %{ 12.500 - match(Set result (StrEquals str1 str2)); 12.501 - effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr); 12.502 - 12.503 - format %{ "String Equals $str1,$str2 -> $result // KILL EBX, ECX" %} 12.504 - ins_encode( enc_String_Equals(tmp1, tmp2, str1, str2, tmp3, tmp4, result) ); 12.505 - ins_pipe( pipe_slow ); 12.506 -%} 12.507 - 12.508 -instruct string_indexof(eSIRegP str1, eDIRegP str2, regXD tmp1, eAXRegI tmp2, 12.509 - eCXRegI tmp3, eDXRegI tmp4, eBXRegI result, eFlagsReg cr) %{ 12.510 +instruct string_equals(eDIRegP str1, eSIRegP str2, eCXRegI cnt, eAXRegI result, 12.511 + regXD tmp1, regXD tmp2, eBXRegI tmp3, eFlagsReg cr) %{ 12.512 + match(Set result (StrEquals (Binary str1 str2) cnt)); 12.513 + effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp3, KILL cr); 12.514 + 12.515 + format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %} 12.516 + ins_encode %{ 12.517 + __ char_arrays_equals(false, $str1$$Register, $str2$$Register, 12.518 + $cnt$$Register, $result$$Register, $tmp3$$Register, 12.519 + $tmp1$$XMMRegister, $tmp2$$XMMRegister); 12.520 + %} 12.521 + ins_pipe( pipe_slow ); 12.522 +%} 12.523 + 12.524 +instruct string_indexof(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2, 12.525 + eBXRegI result, regXD tmp1, eCXRegI tmp2, eFlagsReg cr) %{ 12.526 predicate(UseSSE42Intrinsics); 12.527 - match(Set result (StrIndexOf str1 str2)); 12.528 - effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, KILL tmp2, KILL tmp3, KILL tmp4, KILL cr); 12.529 - 12.530 - format %{ "String IndexOf $str1,$str2 -> $result // KILL EAX, ECX, EDX" %} 12.531 - ins_encode( enc_String_IndexOf(str1, str2, tmp1, tmp2, tmp3, tmp4, result) ); 12.532 + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); 12.533 + effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp2, KILL cr); 12.534 + 12.535 + format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp2, $tmp1" %} 12.536 + ins_encode %{ 12.537 + __ string_indexof($str1$$Register, $str2$$Register, 12.538 + $cnt1$$Register, $cnt2$$Register, $result$$Register, 12.539 + $tmp1$$XMMRegister, $tmp2$$Register); 12.540 + %} 12.541 ins_pipe( pipe_slow ); 12.542 %} 12.543 12.544 // fast array equals 12.545 -instruct array_equals(eDIRegP ary1, eSIRegP ary2, regXD tmp1, regXD tmp2, eBXRegI tmp3, 12.546 - eDXRegI tmp4, eAXRegI result, eFlagsReg cr) %{ 12.547 +instruct array_equals(eDIRegP ary1, eSIRegP ary2, eAXRegI result, 12.548 + regXD tmp1, regXD tmp2, eCXRegI tmp3, eBXRegI tmp4, eFlagsReg cr) 12.549 +%{ 12.550 match(Set result (AryEq ary1 ary2)); 12.551 effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr); 12.552 //ins_cost(300); 12.553 12.554 - format %{ "Array Equals $ary1,$ary2 -> $result // KILL EBX, EDX" %} 12.555 - ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, tmp4, result) ); 12.556 + format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %} 12.557 + ins_encode %{ 12.558 + __ char_arrays_equals(true, $ary1$$Register, $ary2$$Register, 12.559 + $tmp3$$Register, $result$$Register, $tmp4$$Register, 12.560 + $tmp1$$XMMRegister, $tmp2$$XMMRegister); 12.561 + %} 12.562 ins_pipe( pipe_slow ); 12.563 %} 12.564
13.1 --- a/src/cpu/x86/vm/x86_64.ad Fri Oct 02 11:26:25 2009 -0700 13.2 +++ b/src/cpu/x86/vm/x86_64.ad Fri Oct 09 15:18:52 2009 -0700 13.3 @@ -683,7 +683,7 @@ 13.4 #ifdef ASSERT 13.5 if (rspec.reloc()->type() == relocInfo::oop_type && 13.6 d32 != 0 && d32 != (intptr_t) Universe::non_oop_word()) { 13.7 - assert(oop((intptr_t)d32)->is_oop() && oop((intptr_t)d32)->is_perm(), "cannot embed non-perm oops in code"); 13.8 + assert(oop((intptr_t)d32)->is_oop() && (ScavengeRootsInCode || !oop((intptr_t)d32)->is_scavengable()), "cannot embed scavengable oops in code"); 13.9 } 13.10 #endif 13.11 cbuf.relocate(cbuf.inst_mark(), rspec, format); 13.12 @@ -721,8 +721,8 @@ 13.13 #ifdef ASSERT 13.14 if (rspec.reloc()->type() == relocInfo::oop_type && 13.15 d64 != 0 && d64 != (int64_t) Universe::non_oop_word()) { 13.16 - assert(oop(d64)->is_oop() && oop(d64)->is_perm(), 13.17 - "cannot embed non-perm oops in code"); 13.18 + assert(oop(d64)->is_oop() && (ScavengeRootsInCode || !oop(d64)->is_scavengable()), 13.19 + "cannot embed scavengable oops in code"); 13.20 } 13.21 #endif 13.22 cbuf.relocate(cbuf.inst_mark(), rspec, format); 13.23 @@ -3701,448 +3701,6 @@ 13.24 } 13.25 %} 13.26 13.27 - enc_class enc_String_Compare(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2, 13.28 - rax_RegI tmp3, rbx_RegI tmp4, rcx_RegI result) %{ 13.29 - Label RCX_GOOD_LABEL, LENGTH_DIFF_LABEL, 13.30 - POP_LABEL, DONE_LABEL, CONT_LABEL, 13.31 - WHILE_HEAD_LABEL; 13.32 - MacroAssembler masm(&cbuf); 13.33 - 13.34 - XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 13.35 - XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 13.36 - 13.37 - // Get the first character position in both strings 13.38 - // [8] char array, [12] offset, [16] count 13.39 - int value_offset = java_lang_String::value_offset_in_bytes(); 13.40 - int offset_offset = java_lang_String::offset_offset_in_bytes(); 13.41 - int count_offset = java_lang_String::count_offset_in_bytes(); 13.42 - int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 13.43 - 13.44 - masm.load_heap_oop(rax, Address(rsi, value_offset)); 13.45 - masm.movl(rcx, Address(rsi, offset_offset)); 13.46 - masm.lea(rax, Address(rax, rcx, Address::times_2, base_offset)); 13.47 - masm.load_heap_oop(rbx, Address(rdi, value_offset)); 13.48 - masm.movl(rcx, Address(rdi, offset_offset)); 13.49 - masm.lea(rbx, Address(rbx, rcx, Address::times_2, base_offset)); 13.50 - 13.51 - // Compute the minimum of the string lengths(rsi) and the 13.52 - // difference of the string lengths (stack) 13.53 - 13.54 - // do the conditional move stuff 13.55 - masm.movl(rdi, Address(rdi, count_offset)); 13.56 - masm.movl(rsi, Address(rsi, count_offset)); 13.57 - masm.movl(rcx, rdi); 13.58 - masm.subl(rdi, rsi); 13.59 - masm.push(rdi); 13.60 - masm.cmov(Assembler::lessEqual, rsi, rcx); 13.61 - 13.62 - // Is the minimum length zero? 13.63 - masm.bind(RCX_GOOD_LABEL); 13.64 - masm.testl(rsi, rsi); 13.65 - masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL); 13.66 - 13.67 - // Load first characters 13.68 - masm.load_unsigned_short(rcx, Address(rbx, 0)); 13.69 - masm.load_unsigned_short(rdi, Address(rax, 0)); 13.70 - 13.71 - // Compare first characters 13.72 - masm.subl(rcx, rdi); 13.73 - masm.jcc(Assembler::notZero, POP_LABEL); 13.74 - masm.decrementl(rsi); 13.75 - masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL); 13.76 - 13.77 - { 13.78 - // Check after comparing first character to see if strings are equivalent 13.79 - Label LSkip2; 13.80 - // Check if the strings start at same location 13.81 - masm.cmpptr(rbx, rax); 13.82 - masm.jccb(Assembler::notEqual, LSkip2); 13.83 - 13.84 - // Check if the length difference is zero (from stack) 13.85 - masm.cmpl(Address(rsp, 0), 0x0); 13.86 - masm.jcc(Assembler::equal, LENGTH_DIFF_LABEL); 13.87 - 13.88 - // Strings might not be equivalent 13.89 - masm.bind(LSkip2); 13.90 - } 13.91 - 13.92 - // Advance to next character 13.93 - masm.addptr(rax, 2); 13.94 - masm.addptr(rbx, 2); 13.95 - 13.96 - if (UseSSE42Intrinsics) { 13.97 - // With SSE4.2, use double quad vector compare 13.98 - Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL; 13.99 - // Setup to compare 16-byte vectors 13.100 - masm.movl(rdi, rsi); 13.101 - masm.andl(rsi, 0xfffffff8); // rsi holds the vector count 13.102 - masm.andl(rdi, 0x00000007); // rdi holds the tail count 13.103 - masm.testl(rsi, rsi); 13.104 - masm.jccb(Assembler::zero, COMPARE_TAIL); 13.105 - 13.106 - masm.lea(rax, Address(rax, rsi, Address::times_2)); 13.107 - masm.lea(rbx, Address(rbx, rsi, Address::times_2)); 13.108 - masm.negptr(rsi); 13.109 - 13.110 - masm.bind(COMPARE_VECTORS); 13.111 - masm.movdqu(tmp1Reg, Address(rax, rsi, Address::times_2)); 13.112 - masm.movdqu(tmp2Reg, Address(rbx, rsi, Address::times_2)); 13.113 - masm.pxor(tmp1Reg, tmp2Reg); 13.114 - masm.ptest(tmp1Reg, tmp1Reg); 13.115 - masm.jccb(Assembler::notZero, VECTOR_NOT_EQUAL); 13.116 - masm.addptr(rsi, 8); 13.117 - masm.jcc(Assembler::notZero, COMPARE_VECTORS); 13.118 - masm.jmpb(COMPARE_TAIL); 13.119 - 13.120 - // Mismatched characters in the vectors 13.121 - masm.bind(VECTOR_NOT_EQUAL); 13.122 - masm.lea(rax, Address(rax, rsi, Address::times_2)); 13.123 - masm.lea(rbx, Address(rbx, rsi, Address::times_2)); 13.124 - masm.movl(rdi, 8); 13.125 - 13.126 - // Compare tail (< 8 chars), or rescan last vectors to 13.127 - // find 1st mismatched characters 13.128 - masm.bind(COMPARE_TAIL); 13.129 - masm.testl(rdi, rdi); 13.130 - masm.jccb(Assembler::zero, LENGTH_DIFF_LABEL); 13.131 - masm.movl(rsi, rdi); 13.132 - // Fallthru to tail compare 13.133 - } 13.134 - 13.135 - // Shift RAX and RBX to the end of the arrays, negate min 13.136 - masm.lea(rax, Address(rax, rsi, Address::times_2, 0)); 13.137 - masm.lea(rbx, Address(rbx, rsi, Address::times_2, 0)); 13.138 - masm.negptr(rsi); 13.139 - 13.140 - // Compare the rest of the characters 13.141 - masm.bind(WHILE_HEAD_LABEL); 13.142 - masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0)); 13.143 - masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0)); 13.144 - masm.subl(rcx, rdi); 13.145 - masm.jccb(Assembler::notZero, POP_LABEL); 13.146 - masm.increment(rsi); 13.147 - masm.jcc(Assembler::notZero, WHILE_HEAD_LABEL); 13.148 - 13.149 - // Strings are equal up to min length. Return the length difference. 13.150 - masm.bind(LENGTH_DIFF_LABEL); 13.151 - masm.pop(rcx); 13.152 - masm.jmpb(DONE_LABEL); 13.153 - 13.154 - // Discard the stored length difference 13.155 - masm.bind(POP_LABEL); 13.156 - masm.addptr(rsp, 8); 13.157 - 13.158 - // That's it 13.159 - masm.bind(DONE_LABEL); 13.160 - %} 13.161 - 13.162 - enc_class enc_String_IndexOf(rsi_RegP str1, rdi_RegP str2, regD tmp1, rax_RegI tmp2, 13.163 - rcx_RegI tmp3, rdx_RegI tmp4, rbx_RegI result) %{ 13.164 - // SSE4.2 version 13.165 - Label LOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR, 13.166 - SCAN_SUBSTR, RET_NEG_ONE, RET_NOT_FOUND, CLEANUP, DONE; 13.167 - MacroAssembler masm(&cbuf); 13.168 - 13.169 - XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 13.170 - 13.171 - // Get the first character position in both strings 13.172 - // [8] char array, [12] offset, [16] count 13.173 - int value_offset = java_lang_String::value_offset_in_bytes(); 13.174 - int offset_offset = java_lang_String::offset_offset_in_bytes(); 13.175 - int count_offset = java_lang_String::count_offset_in_bytes(); 13.176 - int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 13.177 - 13.178 - // Get counts for string and substr 13.179 - masm.movl(rdx, Address(rsi, count_offset)); 13.180 - masm.movl(rax, Address(rdi, count_offset)); 13.181 - // Check for substr count > string count 13.182 - masm.cmpl(rax, rdx); 13.183 - masm.jcc(Assembler::greater, RET_NEG_ONE); 13.184 - 13.185 - // Start the indexOf operation 13.186 - // Get start addr of string 13.187 - masm.load_heap_oop(rbx, Address(rsi, value_offset)); 13.188 - masm.movl(rcx, Address(rsi, offset_offset)); 13.189 - masm.lea(rsi, Address(rbx, rcx, Address::times_2, base_offset)); 13.190 - masm.push(rsi); 13.191 - 13.192 - // Get start addr of substr 13.193 - masm.load_heap_oop(rbx, Address(rdi, value_offset)); 13.194 - masm.movl(rcx, Address(rdi, offset_offset)); 13.195 - masm.lea(rdi, Address(rbx, rcx, Address::times_2, base_offset)); 13.196 - masm.push(rdi); 13.197 - masm.push(rax); 13.198 - masm.jmpb(PREP_FOR_SCAN); 13.199 - 13.200 - // Substr count saved at sp 13.201 - // Substr saved at sp+8 13.202 - // String saved at sp+16 13.203 - 13.204 - // Prep to load substr for scan 13.205 - masm.bind(LOAD_SUBSTR); 13.206 - masm.movptr(rdi, Address(rsp, 8)); 13.207 - masm.movl(rax, Address(rsp, 0)); 13.208 - 13.209 - // Load substr 13.210 - masm.bind(PREP_FOR_SCAN); 13.211 - masm.movdqu(tmp1Reg, Address(rdi, 0)); 13.212 - masm.addq(rdx, 8); // prime the loop 13.213 - masm.subptr(rsi, 16); 13.214 - 13.215 - // Scan string for substr in 16-byte vectors 13.216 - masm.bind(SCAN_TO_SUBSTR); 13.217 - masm.subq(rdx, 8); 13.218 - masm.addptr(rsi, 16); 13.219 - masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d); 13.220 - masm.jcc(Assembler::above, SCAN_TO_SUBSTR); 13.221 - masm.jccb(Assembler::aboveEqual, RET_NOT_FOUND); 13.222 - 13.223 - // Fallthru: found a potential substr 13.224 - 13.225 - //Make sure string is still long enough 13.226 - masm.subl(rdx, rcx); 13.227 - masm.cmpl(rdx, rax); 13.228 - masm.jccb(Assembler::negative, RET_NOT_FOUND); 13.229 - // Compute start addr of substr 13.230 - masm.lea(rsi, Address(rsi, rcx, Address::times_2)); 13.231 - masm.movptr(rbx, rsi); 13.232 - 13.233 - // Compare potential substr 13.234 - masm.addq(rdx, 8); // prime the loop 13.235 - masm.addq(rax, 8); 13.236 - masm.subptr(rsi, 16); 13.237 - masm.subptr(rdi, 16); 13.238 - 13.239 - // Scan 16-byte vectors of string and substr 13.240 - masm.bind(SCAN_SUBSTR); 13.241 - masm.subq(rax, 8); 13.242 - masm.subq(rdx, 8); 13.243 - masm.addptr(rsi, 16); 13.244 - masm.addptr(rdi, 16); 13.245 - masm.movdqu(tmp1Reg, Address(rdi, 0)); 13.246 - masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d); 13.247 - masm.jcc(Assembler::noOverflow, LOAD_SUBSTR); // OF == 0 13.248 - masm.jcc(Assembler::positive, SCAN_SUBSTR); // SF == 0 13.249 - 13.250 - // Compute substr offset 13.251 - masm.movptr(rsi, Address(rsp, 16)); 13.252 - masm.subptr(rbx, rsi); 13.253 - masm.shrl(rbx, 1); 13.254 - masm.jmpb(CLEANUP); 13.255 - 13.256 - masm.bind(RET_NEG_ONE); 13.257 - masm.movl(rbx, -1); 13.258 - masm.jmpb(DONE); 13.259 - 13.260 - masm.bind(RET_NOT_FOUND); 13.261 - masm.movl(rbx, -1); 13.262 - 13.263 - masm.bind(CLEANUP); 13.264 - masm.addptr(rsp, 24); 13.265 - 13.266 - masm.bind(DONE); 13.267 - %} 13.268 - 13.269 - enc_class enc_String_Equals(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2, 13.270 - rbx_RegI tmp3, rcx_RegI tmp2, rax_RegI result) %{ 13.271 - Label RET_TRUE, RET_FALSE, DONE, COMPARE_VECTORS, COMPARE_CHAR; 13.272 - MacroAssembler masm(&cbuf); 13.273 - 13.274 - XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 13.275 - XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 13.276 - 13.277 - int value_offset = java_lang_String::value_offset_in_bytes(); 13.278 - int offset_offset = java_lang_String::offset_offset_in_bytes(); 13.279 - int count_offset = java_lang_String::count_offset_in_bytes(); 13.280 - int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 13.281 - 13.282 - // does source == target string? 13.283 - masm.cmpptr(rdi, rsi); 13.284 - masm.jcc(Assembler::equal, RET_TRUE); 13.285 - 13.286 - // get and compare counts 13.287 - masm.movl(rcx, Address(rdi, count_offset)); 13.288 - masm.movl(rax, Address(rsi, count_offset)); 13.289 - masm.cmpl(rcx, rax); 13.290 - masm.jcc(Assembler::notEqual, RET_FALSE); 13.291 - masm.testl(rax, rax); 13.292 - masm.jcc(Assembler::zero, RET_TRUE); 13.293 - 13.294 - // get source string offset and value 13.295 - masm.load_heap_oop(rbx, Address(rsi, value_offset)); 13.296 - masm.movl(rax, Address(rsi, offset_offset)); 13.297 - masm.lea(rsi, Address(rbx, rax, Address::times_2, base_offset)); 13.298 - 13.299 - // get compare string offset and value 13.300 - masm.load_heap_oop(rbx, Address(rdi, value_offset)); 13.301 - masm.movl(rax, Address(rdi, offset_offset)); 13.302 - masm.lea(rdi, Address(rbx, rax, Address::times_2, base_offset)); 13.303 - 13.304 - // Set byte count 13.305 - masm.shll(rcx, 1); 13.306 - masm.movl(rax, rcx); 13.307 - 13.308 - if (UseSSE42Intrinsics) { 13.309 - // With SSE4.2, use double quad vector compare 13.310 - Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; 13.311 - // Compare 16-byte vectors 13.312 - masm.andl(rcx, 0xfffffff0); // vector count (in bytes) 13.313 - masm.andl(rax, 0x0000000e); // tail count (in bytes) 13.314 - masm.testl(rcx, rcx); 13.315 - masm.jccb(Assembler::zero, COMPARE_TAIL); 13.316 - masm.lea(rdi, Address(rdi, rcx, Address::times_1)); 13.317 - masm.lea(rsi, Address(rsi, rcx, Address::times_1)); 13.318 - masm.negptr(rcx); 13.319 - 13.320 - masm.bind(COMPARE_WIDE_VECTORS); 13.321 - masm.movdqu(tmp1Reg, Address(rdi, rcx, Address::times_1)); 13.322 - masm.movdqu(tmp2Reg, Address(rsi, rcx, Address::times_1)); 13.323 - masm.pxor(tmp1Reg, tmp2Reg); 13.324 - masm.ptest(tmp1Reg, tmp1Reg); 13.325 - masm.jccb(Assembler::notZero, RET_FALSE); 13.326 - masm.addptr(rcx, 16); 13.327 - masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); 13.328 - masm.bind(COMPARE_TAIL); 13.329 - masm.movl(rcx, rax); 13.330 - // Fallthru to tail compare 13.331 - } 13.332 - 13.333 - // Compare 4-byte vectors 13.334 - masm.andl(rcx, 0xfffffffc); // vector count (in bytes) 13.335 - masm.andl(rax, 0x00000002); // tail char (in bytes) 13.336 - masm.testl(rcx, rcx); 13.337 - masm.jccb(Assembler::zero, COMPARE_CHAR); 13.338 - masm.lea(rdi, Address(rdi, rcx, Address::times_1)); 13.339 - masm.lea(rsi, Address(rsi, rcx, Address::times_1)); 13.340 - masm.negptr(rcx); 13.341 - 13.342 - masm.bind(COMPARE_VECTORS); 13.343 - masm.movl(rbx, Address(rdi, rcx, Address::times_1)); 13.344 - masm.cmpl(rbx, Address(rsi, rcx, Address::times_1)); 13.345 - masm.jccb(Assembler::notEqual, RET_FALSE); 13.346 - masm.addptr(rcx, 4); 13.347 - masm.jcc(Assembler::notZero, COMPARE_VECTORS); 13.348 - 13.349 - // Compare trailing char (final 2 bytes), if any 13.350 - masm.bind(COMPARE_CHAR); 13.351 - masm.testl(rax, rax); 13.352 - masm.jccb(Assembler::zero, RET_TRUE); 13.353 - masm.load_unsigned_short(rbx, Address(rdi, 0)); 13.354 - masm.load_unsigned_short(rcx, Address(rsi, 0)); 13.355 - masm.cmpl(rbx, rcx); 13.356 - masm.jccb(Assembler::notEqual, RET_FALSE); 13.357 - 13.358 - masm.bind(RET_TRUE); 13.359 - masm.movl(rax, 1); // return true 13.360 - masm.jmpb(DONE); 13.361 - 13.362 - masm.bind(RET_FALSE); 13.363 - masm.xorl(rax, rax); // return false 13.364 - 13.365 - masm.bind(DONE); 13.366 - %} 13.367 - 13.368 - enc_class enc_Array_Equals(rdi_RegP ary1, rsi_RegP ary2, regD tmp1, regD tmp2, 13.369 - rax_RegI tmp3, rbx_RegI tmp4, rcx_RegI result) %{ 13.370 - Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR; 13.371 - MacroAssembler masm(&cbuf); 13.372 - 13.373 - XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 13.374 - XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 13.375 - Register ary1Reg = as_Register($ary1$$reg); 13.376 - Register ary2Reg = as_Register($ary2$$reg); 13.377 - Register tmp3Reg = as_Register($tmp3$$reg); 13.378 - Register tmp4Reg = as_Register($tmp4$$reg); 13.379 - Register resultReg = as_Register($result$$reg); 13.380 - 13.381 - int length_offset = arrayOopDesc::length_offset_in_bytes(); 13.382 - int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 13.383 - 13.384 - // Check the input args 13.385 - masm.cmpq(ary1Reg, ary2Reg); 13.386 - masm.jcc(Assembler::equal, TRUE_LABEL); 13.387 - masm.testq(ary1Reg, ary1Reg); 13.388 - masm.jcc(Assembler::zero, FALSE_LABEL); 13.389 - masm.testq(ary2Reg, ary2Reg); 13.390 - masm.jcc(Assembler::zero, FALSE_LABEL); 13.391 - 13.392 - // Check the lengths 13.393 - masm.movl(tmp4Reg, Address(ary1Reg, length_offset)); 13.394 - masm.movl(resultReg, Address(ary2Reg, length_offset)); 13.395 - masm.cmpl(tmp4Reg, resultReg); 13.396 - masm.jcc(Assembler::notEqual, FALSE_LABEL); 13.397 - masm.testl(resultReg, resultReg); 13.398 - masm.jcc(Assembler::zero, TRUE_LABEL); 13.399 - 13.400 - //load array address 13.401 - masm.lea(ary1Reg, Address(ary1Reg, base_offset)); 13.402 - masm.lea(ary2Reg, Address(ary2Reg, base_offset)); 13.403 - 13.404 - //set byte count 13.405 - masm.shll(tmp4Reg, 1); 13.406 - masm.movl(resultReg,tmp4Reg); 13.407 - 13.408 - if (UseSSE42Intrinsics){ 13.409 - // With SSE4.2, use double quad vector compare 13.410 - Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; 13.411 - // Compare 16-byte vectors 13.412 - masm.andl(tmp4Reg, 0xfffffff0); // vector count (in bytes) 13.413 - masm.andl(resultReg, 0x0000000e); // tail count (in bytes) 13.414 - masm.testl(tmp4Reg, tmp4Reg); 13.415 - masm.jccb(Assembler::zero, COMPARE_TAIL); 13.416 - masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 13.417 - masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 13.418 - masm.negptr(tmp4Reg); 13.419 - 13.420 - masm.bind(COMPARE_WIDE_VECTORS); 13.421 - masm.movdqu(tmp1Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 13.422 - masm.movdqu(tmp2Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 13.423 - masm.pxor(tmp1Reg, tmp2Reg); 13.424 - masm.ptest(tmp1Reg, tmp1Reg); 13.425 - 13.426 - masm.jccb(Assembler::notZero, FALSE_LABEL); 13.427 - masm.addptr(tmp4Reg, 16); 13.428 - masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); 13.429 - masm.bind(COMPARE_TAIL); 13.430 - masm.movl(tmp4Reg, resultReg); 13.431 - // Fallthru to tail compare 13.432 - } 13.433 - 13.434 - // Compare 4-byte vectors 13.435 - masm.andl(tmp4Reg, 0xfffffffc); // vector count (in bytes) 13.436 - masm.andl(resultReg, 0x00000002); // tail char (in bytes) 13.437 - masm.testl(tmp4Reg, tmp4Reg); //if tmp2 == 0, only compare char 13.438 - masm.jccb(Assembler::zero, COMPARE_CHAR); 13.439 - masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 13.440 - masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 13.441 - masm.negptr(tmp4Reg); 13.442 - 13.443 - masm.bind(COMPARE_VECTORS); 13.444 - masm.movl(tmp3Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 13.445 - masm.cmpl(tmp3Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 13.446 - masm.jccb(Assembler::notEqual, FALSE_LABEL); 13.447 - masm.addptr(tmp4Reg, 4); 13.448 - masm.jcc(Assembler::notZero, COMPARE_VECTORS); 13.449 - 13.450 - // Compare trailing char (final 2 bytes), if any 13.451 - masm.bind(COMPARE_CHAR); 13.452 - masm.testl(resultReg, resultReg); 13.453 - masm.jccb(Assembler::zero, TRUE_LABEL); 13.454 - masm.load_unsigned_short(tmp3Reg, Address(ary1Reg, 0)); 13.455 - masm.load_unsigned_short(tmp4Reg, Address(ary2Reg, 0)); 13.456 - masm.cmpl(tmp3Reg, tmp4Reg); 13.457 - masm.jccb(Assembler::notEqual, FALSE_LABEL); 13.458 - 13.459 - masm.bind(TRUE_LABEL); 13.460 - masm.movl(resultReg, 1); // return true 13.461 - masm.jmpb(DONE); 13.462 - 13.463 - masm.bind(FALSE_LABEL); 13.464 - masm.xorl(resultReg, resultReg); // return false 13.465 - 13.466 - // That's it 13.467 - masm.bind(DONE); 13.468 - %} 13.469 13.470 enc_class enc_rethrow() 13.471 %{ 13.472 @@ -12096,52 +11654,67 @@ 13.473 ins_pipe(pipe_slow); 13.474 %} 13.475 13.476 -instruct string_compare(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2, 13.477 - rax_RegI tmp3, rbx_RegI tmp4, rcx_RegI result, rFlagsReg cr) 13.478 -%{ 13.479 - match(Set result (StrComp str1 str2)); 13.480 - effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr); 13.481 - //ins_cost(300); 13.482 - 13.483 - format %{ "String Compare $str1, $str2 -> $result // XXX KILL RAX, RBX" %} 13.484 - ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, tmp3, tmp4, result) ); 13.485 +instruct string_compare(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rbx_RegI cnt2, 13.486 + rax_RegI result, regD tmp1, regD tmp2, rFlagsReg cr) 13.487 +%{ 13.488 + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); 13.489 + effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); 13.490 + 13.491 + format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1, $tmp2" %} 13.492 + ins_encode %{ 13.493 + __ string_compare($str1$$Register, $str2$$Register, 13.494 + $cnt1$$Register, $cnt2$$Register, $result$$Register, 13.495 + $tmp1$$XMMRegister, $tmp2$$XMMRegister); 13.496 + %} 13.497 ins_pipe( pipe_slow ); 13.498 %} 13.499 13.500 -instruct string_indexof(rsi_RegP str1, rdi_RegP str2, regD tmp1, rax_RegI tmp2, 13.501 - rcx_RegI tmp3, rdx_RegI tmp4, rbx_RegI result, rFlagsReg cr) 13.502 +instruct string_indexof(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2, 13.503 + rbx_RegI result, regD tmp1, rcx_RegI tmp2, rFlagsReg cr) 13.504 %{ 13.505 predicate(UseSSE42Intrinsics); 13.506 - match(Set result (StrIndexOf str1 str2)); 13.507 - effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, KILL tmp2, KILL tmp3, KILL tmp4, KILL cr); 13.508 - 13.509 - format %{ "String IndexOf $str1,$str2 -> $result // KILL RAX, RCX, RDX" %} 13.510 - ins_encode( enc_String_IndexOf(str1, str2, tmp1, tmp2, tmp3, tmp4, result) ); 13.511 + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); 13.512 + effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp2, KILL cr); 13.513 + 13.514 + format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1, $tmp2" %} 13.515 + ins_encode %{ 13.516 + __ string_indexof($str1$$Register, $str2$$Register, 13.517 + $cnt1$$Register, $cnt2$$Register, $result$$Register, 13.518 + $tmp1$$XMMRegister, $tmp2$$Register); 13.519 + %} 13.520 ins_pipe( pipe_slow ); 13.521 %} 13.522 13.523 // fast string equals 13.524 -instruct string_equals(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2, rbx_RegI tmp3, 13.525 - rcx_RegI tmp4, rax_RegI result, rFlagsReg cr) 13.526 -%{ 13.527 - match(Set result (StrEquals str1 str2)); 13.528 - effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr); 13.529 - 13.530 - format %{ "String Equals $str1,$str2 -> $result // KILL RBX, RCX" %} 13.531 - ins_encode( enc_String_Equals(str1, str2, tmp1, tmp2, tmp3, tmp4, result) ); 13.532 +instruct string_equals(rdi_RegP str1, rsi_RegP str2, rcx_RegI cnt, rax_RegI result, 13.533 + regD tmp1, regD tmp2, rbx_RegI tmp3, rFlagsReg cr) 13.534 +%{ 13.535 + match(Set result (StrEquals (Binary str1 str2) cnt)); 13.536 + effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp3, KILL cr); 13.537 + 13.538 + format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %} 13.539 + ins_encode %{ 13.540 + __ char_arrays_equals(false, $str1$$Register, $str2$$Register, 13.541 + $cnt$$Register, $result$$Register, $tmp3$$Register, 13.542 + $tmp1$$XMMRegister, $tmp2$$XMMRegister); 13.543 + %} 13.544 ins_pipe( pipe_slow ); 13.545 %} 13.546 13.547 // fast array equals 13.548 -instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, regD tmp1, regD tmp2, rax_RegI tmp3, 13.549 - rbx_RegI tmp4, rcx_RegI result, rFlagsReg cr) 13.550 +instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result, 13.551 + regD tmp1, regD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr) 13.552 %{ 13.553 match(Set result (AryEq ary1 ary2)); 13.554 effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr); 13.555 //ins_cost(300); 13.556 13.557 - format %{ "Array Equals $ary1,$ary2 -> $result // KILL RAX, RBX" %} 13.558 - ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, tmp4, result) ); 13.559 + format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %} 13.560 + ins_encode %{ 13.561 + __ char_arrays_equals(true, $ary1$$Register, $ary2$$Register, 13.562 + $tmp3$$Register, $result$$Register, $tmp4$$Register, 13.563 + $tmp1$$XMMRegister, $tmp2$$XMMRegister); 13.564 + %} 13.565 ins_pipe( pipe_slow ); 13.566 %} 13.567
14.1 --- a/src/share/vm/adlc/formssel.cpp Fri Oct 02 11:26:25 2009 -0700 14.2 +++ b/src/share/vm/adlc/formssel.cpp Fri Oct 09 15:18:52 2009 -0700 14.3 @@ -828,11 +828,13 @@ 14.4 return AdlcVMDeps::Parms; // Skip the machine-state edges 14.5 14.6 if( _matrule->_rChild && 14.7 - ( strcmp(_matrule->_rChild->_opType,"StrComp" )==0 || 14.8 + ( strcmp(_matrule->_rChild->_opType,"AryEq" )==0 || 14.9 + strcmp(_matrule->_rChild->_opType,"StrComp" )==0 || 14.10 strcmp(_matrule->_rChild->_opType,"StrEquals" )==0 || 14.11 strcmp(_matrule->_rChild->_opType,"StrIndexOf")==0 )) { 14.12 - // String.(compareTo/equals/indexOf) take 1 control and 4 memory edges. 14.13 - return 5; 14.14 + // String.(compareTo/equals/indexOf) and Arrays.equals 14.15 + // take 1 control and 1 memory edges. 14.16 + return 2; 14.17 } 14.18 14.19 // Check for handling of 'Memory' input/edge in the ideal world.
15.1 --- a/src/share/vm/c1/c1_GraphBuilder.cpp Fri Oct 02 11:26:25 2009 -0700 15.2 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Fri Oct 09 15:18:52 2009 -0700 15.3 @@ -1442,7 +1442,7 @@ 15.4 switch (field_type) { 15.5 case T_ARRAY: 15.6 case T_OBJECT: 15.7 - if (field_val.as_object()->has_encoding()) { 15.8 + if (field_val.as_object()->should_be_constant()) { 15.9 constant = new Constant(as_ValueType(field_val)); 15.10 } 15.11 break;
16.1 --- a/src/share/vm/c1/c1_InstructionPrinter.cpp Fri Oct 02 11:26:25 2009 -0700 16.2 +++ b/src/share/vm/c1/c1_InstructionPrinter.cpp Fri Oct 09 15:18:52 2009 -0700 16.3 @@ -133,12 +133,12 @@ 16.4 ciMethod* m = (ciMethod*)value; 16.5 output()->print("<method %s.%s>", m->holder()->name()->as_utf8(), m->name()->as_utf8()); 16.6 } else { 16.7 - output()->print("<object 0x%x>", value->encoding()); 16.8 + output()->print("<object 0x%x>", value->constant_encoding()); 16.9 } 16.10 } else if (type->as_InstanceConstant() != NULL) { 16.11 - output()->print("<instance 0x%x>", type->as_InstanceConstant()->value()->encoding()); 16.12 + output()->print("<instance 0x%x>", type->as_InstanceConstant()->value()->constant_encoding()); 16.13 } else if (type->as_ArrayConstant() != NULL) { 16.14 - output()->print("<array 0x%x>", type->as_ArrayConstant()->value()->encoding()); 16.15 + output()->print("<array 0x%x>", type->as_ArrayConstant()->value()->constant_encoding()); 16.16 } else if (type->as_ClassConstant() != NULL) { 16.17 ciInstanceKlass* klass = type->as_ClassConstant()->value(); 16.18 if (!klass->is_loaded()) {
17.1 --- a/src/share/vm/c1/c1_LIRGenerator.cpp Fri Oct 02 11:26:25 2009 -0700 17.2 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp Fri Oct 09 15:18:52 2009 -0700 17.3 @@ -440,7 +440,7 @@ 17.4 __ oop2reg_patch(NULL, r, info); 17.5 } else { 17.6 // no patching needed 17.7 - __ oop2reg(obj->encoding(), r); 17.8 + __ oop2reg(obj->constant_encoding(), r); 17.9 } 17.10 } 17.11 17.12 @@ -831,7 +831,7 @@ 17.13 int taken_count_offset = md->byte_offset_of_slot(data, BranchData::taken_offset()); 17.14 int not_taken_count_offset = md->byte_offset_of_slot(data, BranchData::not_taken_offset()); 17.15 LIR_Opr md_reg = new_register(T_OBJECT); 17.16 - __ move(LIR_OprFact::oopConst(md->encoding()), md_reg); 17.17 + __ move(LIR_OprFact::oopConst(md->constant_encoding()), md_reg); 17.18 LIR_Opr data_offset_reg = new_register(T_INT); 17.19 __ cmove(lir_cond(cond), 17.20 LIR_OprFact::intConst(taken_count_offset), 17.21 @@ -1071,7 +1071,7 @@ 17.22 LIR_OprList* args = new LIR_OprList(); 17.23 args->append(getThreadPointer()); 17.24 LIR_Opr meth = new_register(T_OBJECT); 17.25 - __ oop2reg(method()->encoding(), meth); 17.26 + __ oop2reg(method()->constant_encoding(), meth); 17.27 args->append(meth); 17.28 call_runtime(&signature, args, CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), voidType, NULL); 17.29 } 17.30 @@ -1784,7 +1784,7 @@ 17.31 LIR_OprList* args = new LIR_OprList(); 17.32 args->append(getThreadPointer()); 17.33 LIR_Opr meth = new_register(T_OBJECT); 17.34 - __ oop2reg(method()->encoding(), meth); 17.35 + __ oop2reg(method()->constant_encoding(), meth); 17.36 args->append(meth); 17.37 call_runtime(&signature, args, CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), voidType, NULL); 17.38 } 17.39 @@ -2207,7 +2207,7 @@ 17.40 LIR_OprList* args = new LIR_OprList(); 17.41 args->append(getThreadPointer()); 17.42 LIR_Opr meth = new_register(T_OBJECT); 17.43 - __ oop2reg(method()->encoding(), meth); 17.44 + __ oop2reg(method()->constant_encoding(), meth); 17.45 args->append(meth); 17.46 call_runtime(&signature, args, CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), voidType, NULL); 17.47 } 17.48 @@ -2216,7 +2216,7 @@ 17.49 LIR_Opr obj; 17.50 if (method()->is_static()) { 17.51 obj = new_register(T_OBJECT); 17.52 - __ oop2reg(method()->holder()->java_mirror()->encoding(), obj); 17.53 + __ oop2reg(method()->holder()->java_mirror()->constant_encoding(), obj); 17.54 } else { 17.55 Local* receiver = x->state()->local_at(0)->as_Local(); 17.56 assert(receiver != NULL, "must already exist"); 17.57 @@ -2660,7 +2660,7 @@ 17.58 } 17.59 17.60 LIR_Opr meth = new_register(T_OBJECT); 17.61 - __ oop2reg(method()->encoding(), meth); 17.62 + __ oop2reg(method()->constant_encoding(), meth); 17.63 LIR_Opr result = increment_and_return_counter(meth, offset, InvocationCounter::count_increment); 17.64 __ cmp(lir_cond_aboveEqual, result, LIR_OprFact::intConst(limit)); 17.65 CodeStub* overflow = new CounterOverflowStub(info, info->bci());
18.1 --- a/src/share/vm/c1/c1_ValueType.cpp Fri Oct 02 11:26:25 2009 -0700 18.2 +++ b/src/share/vm/c1/c1_ValueType.cpp Fri Oct 09 15:18:52 2009 -0700 18.3 @@ -86,7 +86,7 @@ 18.4 18.5 jobject ObjectType::encoding() const { 18.6 assert(is_constant(), "must be"); 18.7 - return constant_value()->encoding(); 18.8 + return constant_value()->constant_encoding(); 18.9 } 18.10 18.11 bool ObjectType::is_loaded() const {
19.1 --- a/src/share/vm/ci/ciEnv.cpp Fri Oct 02 11:26:25 2009 -0700 19.2 +++ b/src/share/vm/ci/ciEnv.cpp Fri Oct 09 15:18:52 2009 -0700 19.3 @@ -257,7 +257,7 @@ 19.4 19.5 // ------------------------------------------------------------------ 19.6 // ciEnv::make_array 19.7 -ciArray* ciEnv::make_array(GrowableArray<ciObject*>* objects) { 19.8 +ciArray* ciEnv::make_system_array(GrowableArray<ciObject*>* objects) { 19.9 VM_ENTRY_MARK; 19.10 int length = objects->length(); 19.11 objArrayOop a = oopFactory::new_system_objArray(length, THREAD);
20.1 --- a/src/share/vm/ci/ciEnv.hpp Fri Oct 02 11:26:25 2009 -0700 20.2 +++ b/src/share/vm/ci/ciEnv.hpp Fri Oct 09 15:18:52 2009 -0700 20.3 @@ -339,8 +339,8 @@ 20.4 // but consider adding to vmSymbols.hpp instead. 20.5 20.6 // Use this to make a holder for non-perm compile time constants. 20.7 - // The resulting array is guaranteed to satisfy "has_encoding". 20.8 - ciArray* make_array(GrowableArray<ciObject*>* objects); 20.9 + // The resulting array is guaranteed to satisfy "can_be_constant". 20.10 + ciArray* make_system_array(GrowableArray<ciObject*>* objects); 20.11 20.12 // converts the ciKlass* representing the holder of a method into a 20.13 // ciInstanceKlass*. This is needed since the holder of a method in
21.1 --- a/src/share/vm/ci/ciMethod.cpp Fri Oct 02 11:26:25 2009 -0700 21.2 +++ b/src/share/vm/ci/ciMethod.cpp Fri Oct 09 15:18:52 2009 -0700 21.3 @@ -325,10 +325,10 @@ 21.4 } 21.5 21.6 // ------------------------------------------------------------------ 21.7 -// ciMethod::liveness_at_bci 21.8 +// ciMethod::raw_liveness_at_bci 21.9 // 21.10 // Which local variables are live at a specific bci? 21.11 -MethodLivenessResult ciMethod::liveness_at_bci(int bci) { 21.12 +MethodLivenessResult ciMethod::raw_liveness_at_bci(int bci) { 21.13 check_is_loaded(); 21.14 if (_liveness == NULL) { 21.15 // Create the liveness analyzer. 21.16 @@ -336,7 +336,17 @@ 21.17 _liveness = new (arena) MethodLiveness(arena, this); 21.18 _liveness->compute_liveness(); 21.19 } 21.20 - MethodLivenessResult result = _liveness->get_liveness_at(bci); 21.21 + return _liveness->get_liveness_at(bci); 21.22 +} 21.23 + 21.24 +// ------------------------------------------------------------------ 21.25 +// ciMethod::liveness_at_bci 21.26 +// 21.27 +// Which local variables are live at a specific bci? When debugging 21.28 +// will return true for all locals in some cases to improve debug 21.29 +// information. 21.30 +MethodLivenessResult ciMethod::liveness_at_bci(int bci) { 21.31 + MethodLivenessResult result = raw_liveness_at_bci(bci); 21.32 if (CURRENT_ENV->jvmti_can_access_local_variables() || DeoptimizeALot || CompileTheWorld) { 21.33 // Keep all locals live for the user's edification and amusement. 21.34 result.at_put_range(0, result.size(), true);
22.1 --- a/src/share/vm/ci/ciMethod.hpp Fri Oct 02 11:26:25 2009 -0700 22.2 +++ b/src/share/vm/ci/ciMethod.hpp Fri Oct 09 15:18:52 2009 -0700 22.3 @@ -149,6 +149,12 @@ 22.4 bool has_monitor_bytecodes() const { return _uses_monitors; } 22.5 bool has_balanced_monitors(); 22.6 22.7 + // Returns a bitmap indicating which locals are required to be 22.8 + // maintained as live for deopt. raw_liveness_at_bci is always the 22.9 + // direct output of the liveness computation while liveness_at_bci 22.10 + // may mark all locals as live to improve support for debugging Java 22.11 + // code by maintaining the state of as many locals as possible. 22.12 + MethodLivenessResult raw_liveness_at_bci(int bci); 22.13 MethodLivenessResult liveness_at_bci(int bci); 22.14 22.15 // Get the interpreters viewpoint on oop liveness. MethodLiveness is
23.1 --- a/src/share/vm/ci/ciObject.cpp Fri Oct 02 11:26:25 2009 -0700 23.2 +++ b/src/share/vm/ci/ciObject.cpp Fri Oct 09 15:18:52 2009 -0700 23.3 @@ -55,6 +55,7 @@ 23.4 } 23.5 _klass = NULL; 23.6 _ident = 0; 23.7 + init_flags_from(o); 23.8 } 23.9 23.10 // ------------------------------------------------------------------ 23.11 @@ -69,6 +70,7 @@ 23.12 } 23.13 _klass = NULL; 23.14 _ident = 0; 23.15 + init_flags_from(h()); 23.16 } 23.17 23.18 // ------------------------------------------------------------------ 23.19 @@ -158,7 +160,7 @@ 23.20 } 23.21 23.22 // ------------------------------------------------------------------ 23.23 -// ciObject::encoding 23.24 +// ciObject::constant_encoding 23.25 // 23.26 // The address which the compiler should embed into the 23.27 // generated code to represent this oop. This address 23.28 @@ -172,16 +174,24 @@ 23.29 // 23.30 // This method should be changed to return an generified address 23.31 // to discourage use of the JNI handle. 23.32 -jobject ciObject::encoding() { 23.33 +jobject ciObject::constant_encoding() { 23.34 assert(is_null_object() || handle() != NULL, "cannot embed null pointer"); 23.35 - assert(has_encoding(), "oop must be NULL or perm"); 23.36 + assert(can_be_constant(), "oop must be NULL or perm"); 23.37 return handle(); 23.38 } 23.39 23.40 // ------------------------------------------------------------------ 23.41 -// ciObject::has_encoding 23.42 -bool ciObject::has_encoding() { 23.43 - return handle() == NULL || is_perm(); 23.44 +// ciObject::can_be_constant 23.45 +bool ciObject::can_be_constant() { 23.46 + if (ScavengeRootsInCode >= 1) return true; // now everybody can encode as a constant 23.47 + return handle() == NULL || !is_scavengable(); 23.48 +} 23.49 + 23.50 +// ------------------------------------------------------------------ 23.51 +// ciObject::should_be_constant() 23.52 +bool ciObject::should_be_constant() { 23.53 + if (ScavengeRootsInCode >= 2) return true; // force everybody to be a constant 23.54 + return handle() == NULL || !is_scavengable(); 23.55 } 23.56 23.57 23.58 @@ -195,8 +205,9 @@ 23.59 void ciObject::print(outputStream* st) { 23.60 st->print("<%s", type_string()); 23.61 GUARDED_VM_ENTRY(print_impl(st);) 23.62 - st->print(" ident=%d %s address=0x%x>", ident(), 23.63 + st->print(" ident=%d %s%s address=0x%x>", ident(), 23.64 is_perm() ? "PERM" : "", 23.65 + is_scavengable() ? "SCAVENGABLE" : "", 23.66 (address)this); 23.67 } 23.68
24.1 --- a/src/share/vm/ci/ciObject.hpp Fri Oct 02 11:26:25 2009 -0700 24.2 +++ b/src/share/vm/ci/ciObject.hpp Fri Oct 09 15:18:52 2009 -0700 24.3 @@ -51,9 +51,10 @@ 24.4 ciKlass* _klass; 24.5 uint _ident; 24.6 24.7 - enum { FLAG_BITS = 1}; 24.8 + enum { FLAG_BITS = 2 }; 24.9 enum { 24.10 - PERM_FLAG = 1 24.11 + PERM_FLAG = 1, 24.12 + SCAVENGABLE_FLAG = 2 24.13 }; 24.14 protected: 24.15 ciObject(); 24.16 @@ -68,8 +69,15 @@ 24.17 return JNIHandles::resolve_non_null(_handle); 24.18 } 24.19 24.20 - void set_perm() { 24.21 - _ident |= PERM_FLAG; 24.22 + void init_flags_from(oop x) { 24.23 + int flags = 0; 24.24 + if (x != NULL) { 24.25 + if (x->is_perm()) 24.26 + flags |= PERM_FLAG; 24.27 + if (x->is_scavengable()) 24.28 + flags |= SCAVENGABLE_FLAG; 24.29 + } 24.30 + _ident |= flags; 24.31 } 24.32 24.33 // Virtual behavior of the print() method. 24.34 @@ -91,17 +99,27 @@ 24.35 // A hash value for the convenience of compilers. 24.36 int hash(); 24.37 24.38 - // Tells if this oop has an encoding. (I.e., is it null or perm?) 24.39 + // Tells if this oop has an encoding as a constant. 24.40 + // True if is_scavengable is false. 24.41 + // Also true if ScavengeRootsInCode is non-zero. 24.42 // If it does not have an encoding, the compiler is responsible for 24.43 // making other arrangements for dealing with the oop. 24.44 - // See ciEnv::make_perm_array 24.45 - bool has_encoding(); 24.46 + // See ciEnv::make_array 24.47 + bool can_be_constant(); 24.48 + 24.49 + // Tells if this oop should be made a constant. 24.50 + // True if is_scavengable is false or ScavengeRootsInCode > 1. 24.51 + bool should_be_constant(); 24.52 24.53 // Is this object guaranteed to be in the permanent part of the heap? 24.54 // If so, CollectedHeap::can_elide_permanent_oop_store_barriers is relevant. 24.55 // If the answer is false, no guarantees are made. 24.56 bool is_perm() { return (_ident & PERM_FLAG) != 0; } 24.57 24.58 + // Might this object possibly move during a scavenge operation? 24.59 + // If the answer is true and ScavengeRootsInCode==0, the oop cannot be embedded in code. 24.60 + bool is_scavengable() { return (_ident & SCAVENGABLE_FLAG) != 0; } 24.61 + 24.62 // The address which the compiler should embed into the 24.63 // generated code to represent this oop. This address 24.64 // is not the true address of the oop -- it will get patched 24.65 @@ -109,7 +127,7 @@ 24.66 // 24.67 // Usage note: no address arithmetic allowed. Oop must 24.68 // be registered with the oopRecorder. 24.69 - jobject encoding(); 24.70 + jobject constant_encoding(); 24.71 24.72 // What kind of ciObject is this? 24.73 virtual bool is_null_object() const { return false; }
25.1 --- a/src/share/vm/ci/ciObjectFactory.cpp Fri Oct 02 11:26:25 2009 -0700 25.2 +++ b/src/share/vm/ci/ciObjectFactory.cpp Fri Oct 09 15:18:52 2009 -0700 25.3 @@ -261,12 +261,11 @@ 25.4 ciObject* new_object = create_new_object(keyHandle()); 25.5 assert(keyHandle() == new_object->get_oop(), "must be properly recorded"); 25.6 init_ident_of(new_object); 25.7 - if (!keyHandle->is_perm()) { 25.8 + if (!new_object->is_perm()) { 25.9 // Not a perm-space object. 25.10 insert_non_perm(bucket, keyHandle(), new_object); 25.11 return new_object; 25.12 } 25.13 - new_object->set_perm(); 25.14 if (len != _ci_objects->length()) { 25.15 // creating the new object has recursively entered new objects 25.16 // into the table. We need to recompute our index.
26.1 --- a/src/share/vm/ci/ciTypeFlow.cpp Fri Oct 02 11:26:25 2009 -0700 26.2 +++ b/src/share/vm/ci/ciTypeFlow.cpp Fri Oct 09 15:18:52 2009 -0700 26.3 @@ -2486,8 +2486,13 @@ 26.4 // Assume irreducible entries need more data flow 26.5 add_to_work_list(succ); 26.6 } 26.7 - lp = lp->parent(); 26.8 - assert(lp != NULL, "nested loop must have parent by now"); 26.9 + Loop* plp = lp->parent(); 26.10 + if (plp == NULL) { 26.11 + // This only happens for some irreducible cases. The parent 26.12 + // will be updated during a later pass. 26.13 + break; 26.14 + } 26.15 + lp = plp; 26.16 } 26.17 26.18 // Merge loop tree branch for all successors.
27.1 --- a/src/share/vm/classfile/systemDictionary.cpp Fri Oct 02 11:26:25 2009 -0700 27.2 +++ b/src/share/vm/classfile/systemDictionary.cpp Fri Oct 09 15:18:52 2009 -0700 27.3 @@ -2417,6 +2417,8 @@ 27.4 vmSymbols::makeSite_name(), vmSymbols::makeSite_signature(), 27.5 &args, CHECK_(empty)); 27.6 oop call_site_oop = (oop) result.get_jobject(); 27.7 + assert(call_site_oop->is_oop() 27.8 + /*&& sun_dyn_CallSiteImpl::is_instance(call_site_oop)*/, "must be sane"); 27.9 sun_dyn_CallSiteImpl::set_vmmethod(call_site_oop, mh_invdyn()); 27.10 if (TraceMethodHandles) { 27.11 tty->print_cr("Linked invokedynamic bci=%d site="INTPTR_FORMAT":", caller_bci, call_site_oop); 27.12 @@ -2453,6 +2455,8 @@ 27.13 oop boot_method_oop = (oop) result.get_jobject(); 27.14 27.15 if (boot_method_oop != NULL) { 27.16 + assert(boot_method_oop->is_oop() 27.17 + && java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane"); 27.18 // probably no race conditions, but let's be careful: 27.19 if (Atomic::cmpxchg_ptr(boot_method_oop, ik->adr_bootstrap_method(), NULL) == NULL) 27.20 ik->set_bootstrap_method(boot_method_oop);
28.1 --- a/src/share/vm/code/codeBlob.hpp Fri Oct 02 11:26:25 2009 -0700 28.2 +++ b/src/share/vm/code/codeBlob.hpp Fri Oct 09 15:18:52 2009 -0700 28.3 @@ -175,6 +175,8 @@ 28.4 OopClosure* keep_alive, 28.5 bool unloading_occurred); 28.6 virtual void oops_do(OopClosure* f) = 0; 28.7 + // (All CodeBlob subtypes other than NMethod currently have 28.8 + // an empty oops_do() method. 28.9 28.10 // OopMap for frame 28.11 OopMapSet* oop_maps() const { return _oop_maps; }
29.1 --- a/src/share/vm/code/codeCache.cpp Fri Oct 02 11:26:25 2009 -0700 29.2 +++ b/src/share/vm/code/codeCache.cpp Fri Oct 09 15:18:52 2009 -0700 29.3 @@ -95,6 +95,7 @@ 29.4 int CodeCache::_number_of_blobs = 0; 29.5 int CodeCache::_number_of_nmethods_with_dependencies = 0; 29.6 bool CodeCache::_needs_cache_clean = false; 29.7 +nmethod* CodeCache::_scavenge_root_nmethods = NULL; 29.8 29.9 29.10 CodeBlob* CodeCache::first() { 29.11 @@ -148,10 +149,7 @@ 29.12 } 29.13 } 29.14 verify_if_often(); 29.15 - if (PrintCodeCache2) { // Need to add a new flag 29.16 - ResourceMark rm; 29.17 - tty->print_cr("CodeCache allocation: addr: " INTPTR_FORMAT ", size: 0x%x\n", cb, size); 29.18 - } 29.19 + print_trace("allocation", cb, size); 29.20 return cb; 29.21 } 29.22 29.23 @@ -159,10 +157,7 @@ 29.24 assert_locked_or_safepoint(CodeCache_lock); 29.25 verify_if_often(); 29.26 29.27 - if (PrintCodeCache2) { // Need to add a new flag 29.28 - ResourceMark rm; 29.29 - tty->print_cr("CodeCache free: addr: " INTPTR_FORMAT ", size: 0x%x\n", cb, cb->size()); 29.30 - } 29.31 + print_trace("free", cb); 29.32 if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) { 29.33 _number_of_nmethods_with_dependencies--; 29.34 } 29.35 @@ -260,14 +255,148 @@ 29.36 } 29.37 } 29.38 29.39 -void CodeCache::oops_do(OopClosure* f) { 29.40 +void CodeCache::blobs_do(CodeBlobClosure* f) { 29.41 assert_locked_or_safepoint(CodeCache_lock); 29.42 FOR_ALL_ALIVE_BLOBS(cb) { 29.43 - cb->oops_do(f); 29.44 + f->do_code_blob(cb); 29.45 + 29.46 +#ifdef ASSERT 29.47 + if (cb->is_nmethod()) 29.48 + ((nmethod*)cb)->verify_scavenge_root_oops(); 29.49 +#endif //ASSERT 29.50 } 29.51 } 29.52 29.53 +// Walk the list of methods which might contain non-perm oops. 29.54 +void CodeCache::scavenge_root_nmethods_do(CodeBlobClosure* f) { 29.55 + assert_locked_or_safepoint(CodeCache_lock); 29.56 + debug_only(mark_scavenge_root_nmethods()); 29.57 + 29.58 + for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) { 29.59 + debug_only(cur->clear_scavenge_root_marked()); 29.60 + assert(cur->scavenge_root_not_marked(), ""); 29.61 + assert(cur->on_scavenge_root_list(), "else shouldn't be on this list"); 29.62 + 29.63 + bool is_live = (!cur->is_zombie() && !cur->is_unloaded()); 29.64 +#ifndef PRODUCT 29.65 + if (TraceScavenge) { 29.66 + cur->print_on(tty, is_live ? "scavenge root" : "dead scavenge root"); tty->cr(); 29.67 + } 29.68 +#endif //PRODUCT 29.69 + if (is_live) 29.70 + // Perform cur->oops_do(f), maybe just once per nmethod. 29.71 + f->do_code_blob(cur); 29.72 + } 29.73 + 29.74 + // Check for stray marks. 29.75 + debug_only(verify_perm_nmethods(NULL)); 29.76 +} 29.77 + 29.78 +void CodeCache::add_scavenge_root_nmethod(nmethod* nm) { 29.79 + assert_locked_or_safepoint(CodeCache_lock); 29.80 + nm->set_on_scavenge_root_list(); 29.81 + nm->set_scavenge_root_link(_scavenge_root_nmethods); 29.82 + set_scavenge_root_nmethods(nm); 29.83 + print_trace("add_scavenge_root", nm); 29.84 +} 29.85 + 29.86 +void CodeCache::drop_scavenge_root_nmethod(nmethod* nm) { 29.87 + assert_locked_or_safepoint(CodeCache_lock); 29.88 + print_trace("drop_scavenge_root", nm); 29.89 + nmethod* last = NULL; 29.90 + nmethod* cur = scavenge_root_nmethods(); 29.91 + while (cur != NULL) { 29.92 + nmethod* next = cur->scavenge_root_link(); 29.93 + if (cur == nm) { 29.94 + if (last != NULL) 29.95 + last->set_scavenge_root_link(next); 29.96 + else set_scavenge_root_nmethods(next); 29.97 + nm->set_scavenge_root_link(NULL); 29.98 + nm->clear_on_scavenge_root_list(); 29.99 + return; 29.100 + } 29.101 + last = cur; 29.102 + cur = next; 29.103 + } 29.104 + assert(false, "should have been on list"); 29.105 +} 29.106 + 29.107 +void CodeCache::prune_scavenge_root_nmethods() { 29.108 + assert_locked_or_safepoint(CodeCache_lock); 29.109 + debug_only(mark_scavenge_root_nmethods()); 29.110 + 29.111 + nmethod* last = NULL; 29.112 + nmethod* cur = scavenge_root_nmethods(); 29.113 + while (cur != NULL) { 29.114 + nmethod* next = cur->scavenge_root_link(); 29.115 + debug_only(cur->clear_scavenge_root_marked()); 29.116 + assert(cur->scavenge_root_not_marked(), ""); 29.117 + assert(cur->on_scavenge_root_list(), "else shouldn't be on this list"); 29.118 + 29.119 + if (!cur->is_zombie() && !cur->is_unloaded() 29.120 + && cur->detect_scavenge_root_oops()) { 29.121 + // Keep it. Advance 'last' to prevent deletion. 29.122 + last = cur; 29.123 + } else { 29.124 + // Prune it from the list, so we don't have to look at it any more. 29.125 + print_trace("prune_scavenge_root", cur); 29.126 + cur->set_scavenge_root_link(NULL); 29.127 + cur->clear_on_scavenge_root_list(); 29.128 + if (last != NULL) 29.129 + last->set_scavenge_root_link(next); 29.130 + else set_scavenge_root_nmethods(next); 29.131 + } 29.132 + cur = next; 29.133 + } 29.134 + 29.135 + // Check for stray marks. 29.136 + debug_only(verify_perm_nmethods(NULL)); 29.137 +} 29.138 + 29.139 +#ifndef PRODUCT 29.140 +void CodeCache::asserted_non_scavengable_nmethods_do(CodeBlobClosure* f) { 29.141 + // While we are here, verify the integrity of the list. 29.142 + mark_scavenge_root_nmethods(); 29.143 + for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) { 29.144 + assert(cur->on_scavenge_root_list(), "else shouldn't be on this list"); 29.145 + cur->clear_scavenge_root_marked(); 29.146 + } 29.147 + verify_perm_nmethods(f); 29.148 +} 29.149 + 29.150 +// Temporarily mark nmethods that are claimed to be on the non-perm list. 29.151 +void CodeCache::mark_scavenge_root_nmethods() { 29.152 + FOR_ALL_ALIVE_BLOBS(cb) { 29.153 + if (cb->is_nmethod()) { 29.154 + nmethod *nm = (nmethod*)cb; 29.155 + assert(nm->scavenge_root_not_marked(), "clean state"); 29.156 + if (nm->on_scavenge_root_list()) 29.157 + nm->set_scavenge_root_marked(); 29.158 + } 29.159 + } 29.160 +} 29.161 + 29.162 +// If the closure is given, run it on the unlisted nmethods. 29.163 +// Also make sure that the effects of mark_scavenge_root_nmethods is gone. 29.164 +void CodeCache::verify_perm_nmethods(CodeBlobClosure* f_or_null) { 29.165 + FOR_ALL_ALIVE_BLOBS(cb) { 29.166 + bool call_f = (f_or_null != NULL); 29.167 + if (cb->is_nmethod()) { 29.168 + nmethod *nm = (nmethod*)cb; 29.169 + assert(nm->scavenge_root_not_marked(), "must be already processed"); 29.170 + if (nm->on_scavenge_root_list()) 29.171 + call_f = false; // don't show this one to the client 29.172 + nm->verify_scavenge_root_oops(); 29.173 + } else { 29.174 + call_f = false; // not an nmethod 29.175 + } 29.176 + if (call_f) f_or_null->do_code_blob(cb); 29.177 + } 29.178 +} 29.179 +#endif //PRODUCT 29.180 + 29.181 void CodeCache::gc_prologue() { 29.182 + assert(!nmethod::oops_do_marking_is_active(), "oops_do_marking_epilogue must be called"); 29.183 } 29.184 29.185 29.186 @@ -285,6 +414,8 @@ 29.187 cb->fix_oop_relocations(); 29.188 } 29.189 set_needs_cache_clean(false); 29.190 + prune_scavenge_root_nmethods(); 29.191 + assert(!nmethod::oops_do_marking_is_active(), "oops_do_marking_prologue must be called"); 29.192 } 29.193 29.194 29.195 @@ -508,6 +639,14 @@ 29.196 } 29.197 } 29.198 29.199 +void CodeCache::print_trace(const char* event, CodeBlob* cb, int size) { 29.200 + if (PrintCodeCache2) { // Need to add a new flag 29.201 + ResourceMark rm; 29.202 + if (size == 0) size = cb->size(); 29.203 + tty->print_cr("CodeCache %s: addr: " INTPTR_FORMAT ", size: 0x%x", event, cb, size); 29.204 + } 29.205 +} 29.206 + 29.207 void CodeCache::print_internals() { 29.208 int nmethodCount = 0; 29.209 int runtimeStubCount = 0;
30.1 --- a/src/share/vm/code/codeCache.hpp Fri Oct 02 11:26:25 2009 -0700 30.2 +++ b/src/share/vm/code/codeCache.hpp Fri Oct 09 15:18:52 2009 -0700 30.3 @@ -45,8 +45,13 @@ 30.4 static int _number_of_blobs; 30.5 static int _number_of_nmethods_with_dependencies; 30.6 static bool _needs_cache_clean; 30.7 + static nmethod* _scavenge_root_nmethods; // linked via nm->scavenge_root_link() 30.8 30.9 static void verify_if_often() PRODUCT_RETURN; 30.10 + 30.11 + static void mark_scavenge_root_nmethods() PRODUCT_RETURN; 30.12 + static void verify_perm_nmethods(CodeBlobClosure* f_or_null) PRODUCT_RETURN; 30.13 + 30.14 public: 30.15 30.16 // Initialization 30.17 @@ -61,6 +66,7 @@ 30.18 static void flush(); // flushes all CodeBlobs 30.19 static bool contains(void *p); // returns whether p is included 30.20 static void blobs_do(void f(CodeBlob* cb)); // iterates over all CodeBlobs 30.21 + static void blobs_do(CodeBlobClosure* f); // iterates over all CodeBlobs 30.22 static void nmethods_do(void f(nmethod* nm)); // iterates over all nmethods 30.23 30.24 // Lookup 30.25 @@ -106,12 +112,24 @@ 30.26 static void do_unloading(BoolObjectClosure* is_alive, 30.27 OopClosure* keep_alive, 30.28 bool unloading_occurred); 30.29 - static void oops_do(OopClosure* f); 30.30 + static void oops_do(OopClosure* f) { 30.31 + CodeBlobToOopClosure oopc(f, /*do_marking=*/ false); 30.32 + blobs_do(&oopc); 30.33 + } 30.34 + static void asserted_non_scavengable_nmethods_do(CodeBlobClosure* f = NULL) PRODUCT_RETURN; 30.35 + static void scavenge_root_nmethods_do(CodeBlobClosure* f); 30.36 + 30.37 + static nmethod* scavenge_root_nmethods() { return _scavenge_root_nmethods; } 30.38 + static void set_scavenge_root_nmethods(nmethod* nm) { _scavenge_root_nmethods = nm; } 30.39 + static void add_scavenge_root_nmethod(nmethod* nm); 30.40 + static void drop_scavenge_root_nmethod(nmethod* nm); 30.41 + static void prune_scavenge_root_nmethods(); 30.42 30.43 // Printing/debugging 30.44 static void print() PRODUCT_RETURN; // prints summary 30.45 static void print_internals(); 30.46 static void verify(); // verifies the code cache 30.47 + static void print_trace(const char* event, CodeBlob* cb, int size = 0) PRODUCT_RETURN; 30.48 30.49 // The full limits of the codeCache 30.50 static address low_bound() { return (address) _heap->low_boundary(); }
31.1 --- a/src/share/vm/code/debugInfoRec.cpp Fri Oct 02 11:26:25 2009 -0700 31.2 +++ b/src/share/vm/code/debugInfoRec.cpp Fri Oct 09 15:18:52 2009 -0700 31.3 @@ -299,7 +299,7 @@ 31.4 stream()->write_int(sender_stream_offset); 31.5 31.6 // serialize scope 31.7 - jobject method_enc = (method == NULL)? NULL: method->encoding(); 31.8 + jobject method_enc = (method == NULL)? NULL: method->constant_encoding(); 31.9 stream()->write_int(oop_recorder()->find_index(method_enc)); 31.10 stream()->write_bci(bci); 31.11 assert(method == NULL ||
32.1 --- a/src/share/vm/code/dependencies.cpp Fri Oct 02 11:26:25 2009 -0700 32.2 +++ b/src/share/vm/code/dependencies.cpp Fri Oct 09 15:18:52 2009 -0700 32.3 @@ -302,7 +302,7 @@ 32.4 bytes.write_byte(code_byte); 32.5 for (int j = 0; j < stride; j++) { 32.6 if (j == skipj) continue; 32.7 - bytes.write_int(_oop_recorder->find_index(deps->at(i+j)->encoding())); 32.8 + bytes.write_int(_oop_recorder->find_index(deps->at(i+j)->constant_encoding())); 32.9 } 32.10 } 32.11 }
33.1 --- a/src/share/vm/code/nmethod.cpp Fri Oct 02 11:26:25 2009 -0700 33.2 +++ b/src/share/vm/code/nmethod.cpp Fri Oct 09 15:18:52 2009 -0700 33.3 @@ -581,10 +581,13 @@ 33.4 debug_only(No_Safepoint_Verifier nsv;) 33.5 assert_locked_or_safepoint(CodeCache_lock); 33.6 33.7 - NOT_PRODUCT(_has_debug_info = false; ) 33.8 + NOT_PRODUCT(_has_debug_info = false); 33.9 + _oops_do_mark_link = NULL; 33.10 _method = method; 33.11 _entry_bci = InvocationEntryBci; 33.12 - _link = NULL; 33.13 + _osr_link = NULL; 33.14 + _scavenge_root_link = NULL; 33.15 + _scavenge_root_state = 0; 33.16 _compiler = NULL; 33.17 // We have no exception handler or deopt handler make the 33.18 // values something that will never match a pc like the nmethod vtable entry 33.19 @@ -618,7 +621,7 @@ 33.20 _stack_traversal_mark = 0; 33.21 33.22 code_buffer->copy_oops_to(this); 33.23 - debug_only(check_store();) 33.24 + debug_only(verify_scavenge_root_oops()); 33.25 CodeCache::commit(this); 33.26 VTune::create_nmethod(this); 33.27 } 33.28 @@ -668,10 +671,13 @@ 33.29 debug_only(No_Safepoint_Verifier nsv;) 33.30 assert_locked_or_safepoint(CodeCache_lock); 33.31 33.32 - NOT_PRODUCT(_has_debug_info = false; ) 33.33 + NOT_PRODUCT(_has_debug_info = false); 33.34 + _oops_do_mark_link = NULL; 33.35 _method = method; 33.36 _entry_bci = InvocationEntryBci; 33.37 - _link = NULL; 33.38 + _osr_link = NULL; 33.39 + _scavenge_root_link = NULL; 33.40 + _scavenge_root_state = 0; 33.41 _compiler = NULL; 33.42 // We have no exception handler or deopt handler make the 33.43 // values something that will never match a pc like the nmethod vtable entry 33.44 @@ -703,7 +709,7 @@ 33.45 _stack_traversal_mark = 0; 33.46 33.47 code_buffer->copy_oops_to(this); 33.48 - debug_only(check_store();) 33.49 + debug_only(verify_scavenge_root_oops()); 33.50 CodeCache::commit(this); 33.51 VTune::create_nmethod(this); 33.52 } 33.53 @@ -770,12 +776,15 @@ 33.54 debug_only(No_Safepoint_Verifier nsv;) 33.55 assert_locked_or_safepoint(CodeCache_lock); 33.56 33.57 - NOT_PRODUCT(_has_debug_info = false; ) 33.58 + NOT_PRODUCT(_has_debug_info = false); 33.59 + _oops_do_mark_link = NULL; 33.60 _method = method; 33.61 _compile_id = compile_id; 33.62 _comp_level = comp_level; 33.63 _entry_bci = entry_bci; 33.64 - _link = NULL; 33.65 + _osr_link = NULL; 33.66 + _scavenge_root_link = NULL; 33.67 + _scavenge_root_state = 0; 33.68 _compiler = compiler; 33.69 _orig_pc_offset = orig_pc_offset; 33.70 #ifdef HAVE_DTRACE_H 33.71 @@ -813,7 +822,10 @@ 33.72 code_buffer->copy_oops_to(this); 33.73 debug_info->copy_to(this); 33.74 dependencies->copy_to(this); 33.75 - debug_only(check_store();) 33.76 + if (ScavengeRootsInCode && detect_scavenge_root_oops()) { 33.77 + CodeCache::add_scavenge_root_nmethod(this); 33.78 + } 33.79 + debug_only(verify_scavenge_root_oops()); 33.80 33.81 CodeCache::commit(this); 33.82 33.83 @@ -902,23 +914,30 @@ 33.84 if (st != NULL) { 33.85 ttyLocker ttyl; 33.86 // Print a little tag line that looks like +PrintCompilation output: 33.87 - st->print("%3d%c %s", 33.88 + int tlen = (int) strlen(title); 33.89 + bool do_nl = false; 33.90 + if (tlen > 0 && title[tlen-1] == '\n') { tlen--; do_nl = true; } 33.91 + st->print("%3d%c %.*s", 33.92 compile_id(), 33.93 is_osr_method() ? '%' : 33.94 method() != NULL && 33.95 is_native_method() ? 'n' : ' ', 33.96 - title); 33.97 + tlen, title); 33.98 #ifdef TIERED 33.99 st->print(" (%d) ", comp_level()); 33.100 #endif // TIERED 33.101 if (WizardMode) st->print(" (" INTPTR_FORMAT ")", this); 33.102 - if (method() != NULL) { 33.103 - method()->print_short_name(st); 33.104 + if (Universe::heap()->is_gc_active() && method() != NULL) { 33.105 + st->print("(method)"); 33.106 + } else if (method() != NULL) { 33.107 + method()->print_short_name(st); 33.108 if (is_osr_method()) 33.109 st->print(" @ %d", osr_entry_bci()); 33.110 if (method()->code_size() > 0) 33.111 st->print(" (%d bytes)", method()->code_size()); 33.112 } 33.113 + 33.114 + if (do_nl) st->cr(); 33.115 } 33.116 } 33.117 33.118 @@ -1033,6 +1052,7 @@ 33.119 } 33.120 } 33.121 33.122 +// This is a private interface with the sweeper. 33.123 void nmethod::mark_as_seen_on_stack() { 33.124 assert(is_not_entrant(), "must be a non-entrant method"); 33.125 set_stack_traversal_mark(NMethodSweeper::traversal_count()); 33.126 @@ -1077,7 +1097,8 @@ 33.127 " unloadable], methodOop(" INTPTR_FORMAT 33.128 "), cause(" INTPTR_FORMAT ")", 33.129 this, (address)_method, (address)cause); 33.130 - cause->klass()->print(); 33.131 + if (!Universe::heap()->is_gc_active()) 33.132 + cause->klass()->print(); 33.133 } 33.134 // Unlink the osr method, so we do not look this up again 33.135 if (is_osr_method()) { 33.136 @@ -1109,7 +1130,8 @@ 33.137 // The methodOop is gone at this point 33.138 assert(_method == NULL, "Tautology"); 33.139 33.140 - set_link(NULL); 33.141 + set_osr_link(NULL); 33.142 + //set_scavenge_root_link(NULL); // done by prune_scavenge_root_nmethods 33.143 NMethodSweeper::notify(this); 33.144 } 33.145 33.146 @@ -1295,6 +1317,10 @@ 33.147 ec = next; 33.148 } 33.149 33.150 + if (on_scavenge_root_list()) { 33.151 + CodeCache::drop_scavenge_root_nmethod(this); 33.152 + } 33.153 + 33.154 ((CodeBlob*)(this))->flush(); 33.155 33.156 CodeCache::free(this); 33.157 @@ -1354,7 +1380,10 @@ 33.158 return false; 33.159 } 33.160 } 33.161 - assert(unloading_occurred, "Inconsistency in unloading"); 33.162 + // If ScavengeRootsInCode is true, an nmethod might be unloaded 33.163 + // simply because one of its constant oops has gone dead. 33.164 + // No actual classes need to be unloaded in order for this to occur. 33.165 + assert(unloading_occurred || ScavengeRootsInCode, "Inconsistency in unloading"); 33.166 make_unloaded(is_alive, obj); 33.167 return true; 33.168 } 33.169 @@ -1529,13 +1558,12 @@ 33.170 // the (strong) marking phase, and then again when walking 33.171 // the code cache contents during the weak roots processing 33.172 // phase. The two uses are distinguished by means of the 33.173 -// do_nmethods() method in the closure "f" below -- which 33.174 -// answers "yes" in the first case, and "no" in the second 33.175 +// 'do_strong_roots_only' flag, which is true in the first 33.176 // case. We want to walk the weak roots in the nmethod 33.177 // only in the second case. The weak roots in the nmethod 33.178 // are the oops in the ExceptionCache and the InlineCache 33.179 // oops. 33.180 -void nmethod::oops_do(OopClosure* f) { 33.181 +void nmethod::oops_do(OopClosure* f, bool do_strong_roots_only) { 33.182 // make sure the oops ready to receive visitors 33.183 assert(!is_zombie() && !is_unloaded(), 33.184 "should not call follow on zombie or unloaded nmethod"); 33.185 @@ -1553,7 +1581,7 @@ 33.186 33.187 // Compiled code 33.188 f->do_oop((oop*) &_method); 33.189 - if (!f->do_nmethods()) { 33.190 + if (!do_strong_roots_only) { 33.191 // weak roots processing phase -- update ExceptionCache oops 33.192 ExceptionCache* ec = exception_cache(); 33.193 while(ec != NULL) { 33.194 @@ -1579,12 +1607,108 @@ 33.195 } 33.196 33.197 // Scopes 33.198 + // This includes oop constants not inlined in the code stream. 33.199 for (oop* p = oops_begin(); p < oops_end(); p++) { 33.200 if (*p == Universe::non_oop_word()) continue; // skip non-oops 33.201 f->do_oop(p); 33.202 } 33.203 } 33.204 33.205 +#define NMETHOD_SENTINEL ((nmethod*)badAddress) 33.206 + 33.207 +nmethod* volatile nmethod::_oops_do_mark_nmethods; 33.208 + 33.209 +// An nmethod is "marked" if its _mark_link is set non-null. 33.210 +// Even if it is the end of the linked list, it will have a non-null link value, 33.211 +// as long as it is on the list. 33.212 +// This code must be MP safe, because it is used from parallel GC passes. 33.213 +bool nmethod::test_set_oops_do_mark() { 33.214 + assert(nmethod::oops_do_marking_is_active(), "oops_do_marking_prologue must be called"); 33.215 + nmethod* observed_mark_link = _oops_do_mark_link; 33.216 + if (observed_mark_link == NULL) { 33.217 + // Claim this nmethod for this thread to mark. 33.218 + observed_mark_link = (nmethod*) 33.219 + Atomic::cmpxchg_ptr(NMETHOD_SENTINEL, &_oops_do_mark_link, NULL); 33.220 + if (observed_mark_link == NULL) { 33.221 + 33.222 + // Atomically append this nmethod (now claimed) to the head of the list: 33.223 + nmethod* observed_mark_nmethods = _oops_do_mark_nmethods; 33.224 + for (;;) { 33.225 + nmethod* required_mark_nmethods = observed_mark_nmethods; 33.226 + _oops_do_mark_link = required_mark_nmethods; 33.227 + observed_mark_nmethods = (nmethod*) 33.228 + Atomic::cmpxchg_ptr(this, &_oops_do_mark_nmethods, required_mark_nmethods); 33.229 + if (observed_mark_nmethods == required_mark_nmethods) 33.230 + break; 33.231 + } 33.232 + // Mark was clear when we first saw this guy. 33.233 + NOT_PRODUCT(if (TraceScavenge) print_on(tty, "oops_do, mark\n")); 33.234 + return false; 33.235 + } 33.236 + } 33.237 + // On fall through, another racing thread marked this nmethod before we did. 33.238 + return true; 33.239 +} 33.240 + 33.241 +void nmethod::oops_do_marking_prologue() { 33.242 + NOT_PRODUCT(if (TraceScavenge) tty->print_cr("[oops_do_marking_prologue")); 33.243 + assert(_oops_do_mark_nmethods == NULL, "must not call oops_do_marking_prologue twice in a row"); 33.244 + // We use cmpxchg_ptr instead of regular assignment here because the user 33.245 + // may fork a bunch of threads, and we need them all to see the same state. 33.246 + void* observed = Atomic::cmpxchg_ptr(NMETHOD_SENTINEL, &_oops_do_mark_nmethods, NULL); 33.247 + guarantee(observed == NULL, "no races in this sequential code"); 33.248 +} 33.249 + 33.250 +void nmethod::oops_do_marking_epilogue() { 33.251 + assert(_oops_do_mark_nmethods != NULL, "must not call oops_do_marking_epilogue twice in a row"); 33.252 + nmethod* cur = _oops_do_mark_nmethods; 33.253 + while (cur != NMETHOD_SENTINEL) { 33.254 + assert(cur != NULL, "not NULL-terminated"); 33.255 + nmethod* next = cur->_oops_do_mark_link; 33.256 + cur->_oops_do_mark_link = NULL; 33.257 + NOT_PRODUCT(if (TraceScavenge) cur->print_on(tty, "oops_do, unmark\n")); 33.258 + cur = next; 33.259 + } 33.260 + void* required = _oops_do_mark_nmethods; 33.261 + void* observed = Atomic::cmpxchg_ptr(NULL, &_oops_do_mark_nmethods, required); 33.262 + guarantee(observed == required, "no races in this sequential code"); 33.263 + NOT_PRODUCT(if (TraceScavenge) tty->print_cr("oops_do_marking_epilogue]")); 33.264 +} 33.265 + 33.266 +class DetectScavengeRoot: public OopClosure { 33.267 + bool _detected_scavenge_root; 33.268 +public: 33.269 + DetectScavengeRoot() : _detected_scavenge_root(false) 33.270 + { NOT_PRODUCT(_print_nm = NULL); } 33.271 + bool detected_scavenge_root() { return _detected_scavenge_root; } 33.272 + virtual void do_oop(oop* p) { 33.273 + if ((*p) != NULL && (*p)->is_scavengable()) { 33.274 + NOT_PRODUCT(maybe_print(p)); 33.275 + _detected_scavenge_root = true; 33.276 + } 33.277 + } 33.278 + virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } 33.279 + 33.280 +#ifndef PRODUCT 33.281 + nmethod* _print_nm; 33.282 + void maybe_print(oop* p) { 33.283 + if (_print_nm == NULL) return; 33.284 + if (!_detected_scavenge_root) _print_nm->print_on(tty, "new scavenge root"); 33.285 + tty->print_cr(""PTR_FORMAT"[offset=%d] detected non-perm oop "PTR_FORMAT" (found at "PTR_FORMAT")", 33.286 + _print_nm, (int)((intptr_t)p - (intptr_t)_print_nm), 33.287 + (intptr_t)(*p), (intptr_t)p); 33.288 + (*p)->print(); 33.289 + } 33.290 +#endif //PRODUCT 33.291 +}; 33.292 + 33.293 +bool nmethod::detect_scavenge_root_oops() { 33.294 + DetectScavengeRoot detect_scavenge_root; 33.295 + NOT_PRODUCT(if (TraceScavenge) detect_scavenge_root._print_nm = this); 33.296 + oops_do(&detect_scavenge_root); 33.297 + return detect_scavenge_root.detected_scavenge_root(); 33.298 +} 33.299 + 33.300 // Method that knows how to preserve outgoing arguments at call. This method must be 33.301 // called with a frame corresponding to a Java invoke 33.302 void nmethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { 33.303 @@ -1899,6 +2023,24 @@ 33.304 // ----------------------------------------------------------------------------- 33.305 // Verification 33.306 33.307 +class VerifyOopsClosure: public OopClosure { 33.308 + nmethod* _nm; 33.309 + bool _ok; 33.310 +public: 33.311 + VerifyOopsClosure(nmethod* nm) : _nm(nm), _ok(true) { } 33.312 + bool ok() { return _ok; } 33.313 + virtual void do_oop(oop* p) { 33.314 + if ((*p) == NULL || (*p)->is_oop()) return; 33.315 + if (_ok) { 33.316 + _nm->print_nmethod(true); 33.317 + _ok = false; 33.318 + } 33.319 + tty->print_cr("*** non-oop "PTR_FORMAT" found at "PTR_FORMAT" (offset %d)", 33.320 + (intptr_t)(*p), (intptr_t)p, (int)((intptr_t)p - (intptr_t)_nm)); 33.321 + } 33.322 + virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } 33.323 +}; 33.324 + 33.325 void nmethod::verify() { 33.326 33.327 // Hmm. OSR methods can be deopted but not marked as zombie or not_entrant 33.328 @@ -1932,6 +2074,11 @@ 33.329 } 33.330 } 33.331 33.332 + VerifyOopsClosure voc(this); 33.333 + oops_do(&voc); 33.334 + assert(voc.ok(), "embedded oops must be OK"); 33.335 + verify_scavenge_root_oops(); 33.336 + 33.337 verify_scopes(); 33.338 } 33.339 33.340 @@ -1995,19 +2142,34 @@ 33.341 // Non-product code 33.342 #ifndef PRODUCT 33.343 33.344 -void nmethod::check_store() { 33.345 - // Make sure all oops in the compiled code are tenured 33.346 +class DebugScavengeRoot: public OopClosure { 33.347 + nmethod* _nm; 33.348 + bool _ok; 33.349 +public: 33.350 + DebugScavengeRoot(nmethod* nm) : _nm(nm), _ok(true) { } 33.351 + bool ok() { return _ok; } 33.352 + virtual void do_oop(oop* p) { 33.353 + if ((*p) == NULL || !(*p)->is_scavengable()) return; 33.354 + if (_ok) { 33.355 + _nm->print_nmethod(true); 33.356 + _ok = false; 33.357 + } 33.358 + tty->print_cr("*** non-perm oop "PTR_FORMAT" found at "PTR_FORMAT" (offset %d)", 33.359 + (intptr_t)(*p), (intptr_t)p, (int)((intptr_t)p - (intptr_t)_nm)); 33.360 + (*p)->print(); 33.361 + } 33.362 + virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } 33.363 +}; 33.364 33.365 - RelocIterator iter(this); 33.366 - while (iter.next()) { 33.367 - if (iter.type() == relocInfo::oop_type) { 33.368 - oop_Relocation* reloc = iter.oop_reloc(); 33.369 - oop obj = reloc->oop_value(); 33.370 - if (obj != NULL && !obj->is_perm()) { 33.371 - fatal("must be permanent oop in compiled code"); 33.372 - } 33.373 - } 33.374 +void nmethod::verify_scavenge_root_oops() { 33.375 + if (!on_scavenge_root_list()) { 33.376 + // Actually look inside, to verify the claim that it's clean. 33.377 + DebugScavengeRoot debug_scavenge_root(this); 33.378 + oops_do(&debug_scavenge_root); 33.379 + if (!debug_scavenge_root.ok()) 33.380 + fatal("found an unadvertised bad non-perm oop in the code cache"); 33.381 } 33.382 + assert(scavenge_root_not_marked(), ""); 33.383 } 33.384 33.385 #endif // PRODUCT 33.386 @@ -2040,6 +2202,7 @@ 33.387 if (is_not_entrant()) tty->print("not_entrant "); 33.388 if (is_zombie()) tty->print("zombie "); 33.389 if (is_unloaded()) tty->print("unloaded "); 33.390 + if (on_scavenge_root_list()) tty->print("scavenge_root "); 33.391 tty->print_cr("}:"); 33.392 } 33.393 if (size () > 0) tty->print_cr(" total in heap [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d",
34.1 --- a/src/share/vm/code/nmethod.hpp Fri Oct 02 11:26:25 2009 -0700 34.2 +++ b/src/share/vm/code/nmethod.hpp Fri Oct 09 15:18:52 2009 -0700 34.3 @@ -125,6 +125,7 @@ 34.4 class nmethod : public CodeBlob { 34.5 friend class VMStructs; 34.6 friend class NMethodSweeper; 34.7 + friend class CodeCache; // non-perm oops 34.8 private: 34.9 // Shared fields for all nmethod's 34.10 static int _zombie_instruction_size; 34.11 @@ -132,7 +133,12 @@ 34.12 methodOop _method; 34.13 int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method 34.14 34.15 - nmethod* _link; // To support simple linked-list chaining of nmethods 34.16 + // To support simple linked-list chaining of nmethods: 34.17 + nmethod* _osr_link; // from instanceKlass::osr_nmethods_head 34.18 + nmethod* _scavenge_root_link; // from CodeCache::scavenge_root_nmethods 34.19 + 34.20 + static nmethod* volatile _oops_do_mark_nmethods; 34.21 + nmethod* volatile _oops_do_mark_link; 34.22 34.23 AbstractCompiler* _compiler; // The compiler which compiled this nmethod 34.24 34.25 @@ -174,6 +180,8 @@ 34.26 // used by jvmti to track if an unload event has been posted for this nmethod. 34.27 bool _unload_reported; 34.28 34.29 + jbyte _scavenge_root_state; 34.30 + 34.31 NOT_PRODUCT(bool _has_debug_info; ) 34.32 34.33 // Nmethod Flushing lock (if non-zero, then the nmethod is not removed) 34.34 @@ -242,7 +250,6 @@ 34.35 34.36 // helper methods 34.37 void* operator new(size_t size, int nmethod_size); 34.38 - void check_store(); 34.39 34.40 const char* reloc_string_for(u_char* begin, u_char* end); 34.41 void make_not_entrant_or_zombie(int state); 34.42 @@ -406,6 +413,24 @@ 34.43 int version() const { return flags.version; } 34.44 void set_version(int v); 34.45 34.46 + // Non-perm oop support 34.47 + bool on_scavenge_root_list() const { return (_scavenge_root_state & 1) != 0; } 34.48 + protected: 34.49 + enum { npl_on_list = 0x01, npl_marked = 0x10 }; 34.50 + void set_on_scavenge_root_list() { _scavenge_root_state = npl_on_list; } 34.51 + void clear_on_scavenge_root_list() { _scavenge_root_state = 0; } 34.52 + // assertion-checking and pruning logic uses the bits of _scavenge_root_state 34.53 +#ifndef PRODUCT 34.54 + void set_scavenge_root_marked() { _scavenge_root_state |= npl_marked; } 34.55 + void clear_scavenge_root_marked() { _scavenge_root_state &= ~npl_marked; } 34.56 + bool scavenge_root_not_marked() { return (_scavenge_root_state &~ npl_on_list) == 0; } 34.57 + // N.B. there is no positive marked query, and we only use the not_marked query for asserts. 34.58 +#endif //PRODUCT 34.59 + nmethod* scavenge_root_link() const { return _scavenge_root_link; } 34.60 + void set_scavenge_root_link(nmethod *n) { _scavenge_root_link = n; } 34.61 + 34.62 + public: 34.63 + 34.64 // Sweeper support 34.65 long stack_traversal_mark() { return _stack_traversal_mark; } 34.66 void set_stack_traversal_mark(long l) { _stack_traversal_mark = l; } 34.67 @@ -424,8 +449,8 @@ 34.68 int osr_entry_bci() const { assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod"); return _entry_bci; } 34.69 address osr_entry() const { assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod"); return _osr_entry_point; } 34.70 void invalidate_osr_method(); 34.71 - nmethod* link() const { return _link; } 34.72 - void set_link(nmethod *n) { _link = n; } 34.73 + nmethod* osr_link() const { return _osr_link; } 34.74 + void set_osr_link(nmethod *n) { _osr_link = n; } 34.75 34.76 // tells whether frames described by this nmethod can be deoptimized 34.77 // note: native wrappers cannot be deoptimized. 34.78 @@ -465,7 +490,16 @@ 34.79 34.80 void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, 34.81 OopClosure* f); 34.82 - void oops_do(OopClosure* f); 34.83 + virtual void oops_do(OopClosure* f) { oops_do(f, false); } 34.84 + void oops_do(OopClosure* f, bool do_strong_roots_only); 34.85 + bool detect_scavenge_root_oops(); 34.86 + void verify_scavenge_root_oops() PRODUCT_RETURN; 34.87 + 34.88 + bool test_set_oops_do_mark(); 34.89 + static void oops_do_marking_prologue(); 34.90 + static void oops_do_marking_epilogue(); 34.91 + static bool oops_do_marking_is_active() { return _oops_do_mark_nmethods != NULL; } 34.92 + DEBUG_ONLY(bool test_oops_do_mark() { return _oops_do_mark_link != NULL; }) 34.93 34.94 // ScopeDesc for an instruction 34.95 ScopeDesc* scope_desc_at(address pc);
35.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp Fri Oct 02 11:26:25 2009 -0700 35.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp Fri Oct 09 15:18:52 2009 -0700 35.3 @@ -47,20 +47,15 @@ 35.4 private: 35.5 const MemRegion _span; 35.6 CMSBitMap* _bitMap; 35.7 - const bool _should_do_nmethods; 35.8 protected: 35.9 DO_OOP_WORK_DEFN 35.10 public: 35.11 - MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap, 35.12 - bool should_do_nmethods); 35.13 + MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap); 35.14 virtual void do_oop(oop* p); 35.15 virtual void do_oop(narrowOop* p); 35.16 inline void do_oop_nv(oop* p) { MarkRefsIntoClosure::do_oop_work(p); } 35.17 inline void do_oop_nv(narrowOop* p) { MarkRefsIntoClosure::do_oop_work(p); } 35.18 bool do_header() { return true; } 35.19 - virtual const bool do_nmethods() const { 35.20 - return _should_do_nmethods; 35.21 - } 35.22 Prefetch::style prefetch_style() { 35.23 return Prefetch::do_read; 35.24 } 35.25 @@ -73,20 +68,16 @@ 35.26 const MemRegion _span; 35.27 CMSBitMap* _verification_bm; 35.28 CMSBitMap* _cms_bm; 35.29 - const bool _should_do_nmethods; 35.30 protected: 35.31 DO_OOP_WORK_DEFN 35.32 public: 35.33 MarkRefsIntoVerifyClosure(MemRegion span, CMSBitMap* verification_bm, 35.34 - CMSBitMap* cms_bm, bool should_do_nmethods); 35.35 + CMSBitMap* cms_bm); 35.36 virtual void do_oop(oop* p); 35.37 virtual void do_oop(narrowOop* p); 35.38 inline void do_oop_nv(oop* p) { MarkRefsIntoVerifyClosure::do_oop_work(p); } 35.39 inline void do_oop_nv(narrowOop* p) { MarkRefsIntoVerifyClosure::do_oop_work(p); } 35.40 bool do_header() { return true; } 35.41 - virtual const bool do_nmethods() const { 35.42 - return _should_do_nmethods; 35.43 - } 35.44 Prefetch::style prefetch_style() { 35.45 return Prefetch::do_read; 35.46 } 35.47 @@ -228,7 +219,6 @@ 35.48 inline void do_oop_nv(oop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); } 35.49 inline void do_oop_nv(narrowOop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); } 35.50 bool do_header() { return true; } 35.51 - virtual const bool do_nmethods() const { return true; } 35.52 Prefetch::style prefetch_style() { 35.53 return Prefetch::do_read; 35.54 } 35.55 @@ -273,7 +263,6 @@ 35.56 inline void do_oop_nv(oop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); } 35.57 inline void do_oop_nv(narrowOop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); } 35.58 bool do_header() { return true; } 35.59 - virtual const bool do_nmethods() const { return true; } 35.60 // When ScanMarkedObjectsAgainClosure is used, 35.61 // it passes [Par_]MarkRefsIntoAndScanClosure to oop_oop_iterate(), 35.62 // and this delegation is used.
36.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Oct 02 11:26:25 2009 -0700 36.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Oct 09 15:18:52 2009 -0700 36.3 @@ -2852,14 +2852,17 @@ 36.4 GenCollectedHeap* gch = GenCollectedHeap::heap(); 36.5 36.6 // Mark from roots one level into CMS 36.7 - MarkRefsIntoClosure notOlder(_span, verification_mark_bm(), true /* nmethods */); 36.8 + MarkRefsIntoClosure notOlder(_span, verification_mark_bm()); 36.9 gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel. 36.10 36.11 gch->gen_process_strong_roots(_cmsGen->level(), 36.12 true, // younger gens are roots 36.13 + true, // activate StrongRootsScope 36.14 true, // collecting perm gen 36.15 SharedHeap::ScanningOption(roots_scanning_options()), 36.16 - NULL, ¬Older); 36.17 + ¬Older, 36.18 + true, // walk code active on stacks 36.19 + NULL); 36.20 36.21 // Now mark from the roots 36.22 assert(_revisitStack.isEmpty(), "Should be empty"); 36.23 @@ -2901,13 +2904,16 @@ 36.24 36.25 // Mark from roots one level into CMS 36.26 MarkRefsIntoVerifyClosure notOlder(_span, verification_mark_bm(), 36.27 - markBitMap(), true /* nmethods */); 36.28 + markBitMap()); 36.29 gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel. 36.30 gch->gen_process_strong_roots(_cmsGen->level(), 36.31 true, // younger gens are roots 36.32 + true, // activate StrongRootsScope 36.33 true, // collecting perm gen 36.34 SharedHeap::ScanningOption(roots_scanning_options()), 36.35 - NULL, ¬Older); 36.36 + ¬Older, 36.37 + true, // walk code active on stacks 36.38 + NULL); 36.39 36.40 // Now mark from the roots 36.41 assert(_revisitStack.isEmpty(), "Should be empty"); 36.42 @@ -3484,8 +3490,10 @@ 36.43 FalseClosure falseClosure; 36.44 // In the case of a synchronous collection, we will elide the 36.45 // remark step, so it's important to catch all the nmethod oops 36.46 - // in this step; hence the last argument to the constrcutor below. 36.47 - MarkRefsIntoClosure notOlder(_span, &_markBitMap, !asynch /* nmethods */); 36.48 + // in this step. 36.49 + // The final 'true' flag to gen_process_strong_roots will ensure this. 36.50 + // If 'async' is true, we can relax the nmethod tracing. 36.51 + MarkRefsIntoClosure notOlder(_span, &_markBitMap); 36.52 GenCollectedHeap* gch = GenCollectedHeap::heap(); 36.53 36.54 verify_work_stacks_empty(); 36.55 @@ -3504,9 +3512,12 @@ 36.56 gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel. 36.57 gch->gen_process_strong_roots(_cmsGen->level(), 36.58 true, // younger gens are roots 36.59 + true, // activate StrongRootsScope 36.60 true, // collecting perm gen 36.61 SharedHeap::ScanningOption(roots_scanning_options()), 36.62 - NULL, ¬Older); 36.63 + ¬Older, 36.64 + true, // walk all of code cache if (so & SO_CodeCache) 36.65 + NULL); 36.66 } 36.67 36.68 // Clear mod-union table; it will be dirtied in the prologue of 36.69 @@ -5040,9 +5051,15 @@ 36.70 _timer.start(); 36.71 gch->gen_process_strong_roots(_collector->_cmsGen->level(), 36.72 false, // yg was scanned above 36.73 + false, // this is parallel code 36.74 true, // collecting perm gen 36.75 SharedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()), 36.76 - NULL, &par_mrias_cl); 36.77 + &par_mrias_cl, 36.78 + true, // walk all of code cache if (so & SO_CodeCache) 36.79 + NULL); 36.80 + assert(_collector->should_unload_classes() 36.81 + || (_collector->CMSCollector::roots_scanning_options() & SharedHeap::SO_CodeCache), 36.82 + "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops"); 36.83 _timer.stop(); 36.84 if (PrintCMSStatistics != 0) { 36.85 gclog_or_tty->print_cr( 36.86 @@ -5423,7 +5440,6 @@ 36.87 36.88 // Set up for parallel process_strong_roots work. 36.89 gch->set_par_threads(n_workers); 36.90 - gch->change_strong_roots_parity(); 36.91 // We won't be iterating over the cards in the card table updating 36.92 // the younger_gen cards, so we shouldn't call the following else 36.93 // the verification code as well as subsequent younger_refs_iterate 36.94 @@ -5454,8 +5470,10 @@ 36.95 if (n_workers > 1) { 36.96 // Make refs discovery MT-safe 36.97 ReferenceProcessorMTMutator mt(ref_processor(), true); 36.98 + GenCollectedHeap::StrongRootsScope srs(gch); 36.99 workers->run_task(&tsk); 36.100 } else { 36.101 + GenCollectedHeap::StrongRootsScope srs(gch); 36.102 tsk.work(0); 36.103 } 36.104 gch->set_par_threads(0); // 0 ==> non-parallel. 36.105 @@ -5539,11 +5557,18 @@ 36.106 verify_work_stacks_empty(); 36.107 36.108 gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel. 36.109 + GenCollectedHeap::StrongRootsScope srs(gch); 36.110 gch->gen_process_strong_roots(_cmsGen->level(), 36.111 true, // younger gens as roots 36.112 + false, // use the local StrongRootsScope 36.113 true, // collecting perm gen 36.114 SharedHeap::ScanningOption(roots_scanning_options()), 36.115 - NULL, &mrias_cl); 36.116 + &mrias_cl, 36.117 + true, // walk code active on stacks 36.118 + NULL); 36.119 + assert(should_unload_classes() 36.120 + || (roots_scanning_options() & SharedHeap::SO_CodeCache), 36.121 + "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops"); 36.122 } 36.123 verify_work_stacks_empty(); 36.124 // Restore evacuated mark words, if any, used for overflow list links 36.125 @@ -6418,10 +6443,9 @@ 36.126 // generation then this will lose younger_gen cards! 36.127 36.128 MarkRefsIntoClosure::MarkRefsIntoClosure( 36.129 - MemRegion span, CMSBitMap* bitMap, bool should_do_nmethods): 36.130 + MemRegion span, CMSBitMap* bitMap): 36.131 _span(span), 36.132 - _bitMap(bitMap), 36.133 - _should_do_nmethods(should_do_nmethods) 36.134 + _bitMap(bitMap) 36.135 { 36.136 assert(_ref_processor == NULL, "deliberately left NULL"); 36.137 assert(_bitMap->covers(_span), "_bitMap/_span mismatch"); 36.138 @@ -6442,12 +6466,11 @@ 36.139 36.140 // A variant of the above, used for CMS marking verification. 36.141 MarkRefsIntoVerifyClosure::MarkRefsIntoVerifyClosure( 36.142 - MemRegion span, CMSBitMap* verification_bm, CMSBitMap* cms_bm, 36.143 - bool should_do_nmethods): 36.144 + MemRegion span, CMSBitMap* verification_bm, CMSBitMap* cms_bm): 36.145 _span(span), 36.146 _verification_bm(verification_bm), 36.147 - _cms_bm(cms_bm), 36.148 - _should_do_nmethods(should_do_nmethods) { 36.149 + _cms_bm(cms_bm) 36.150 +{ 36.151 assert(_ref_processor == NULL, "deliberately left NULL"); 36.152 assert(_verification_bm->covers(_span), "_verification_bm/_span mismatch"); 36.153 }
37.1 --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Oct 02 11:26:25 2009 -0700 37.2 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Oct 09 15:18:52 2009 -0700 37.3 @@ -746,10 +746,11 @@ 37.4 // clear the mark bitmap (no grey objects to start with) 37.5 _nextMarkBitMap->clearAll(); 37.6 PrintReachableClosure prcl(_nextMarkBitMap); 37.7 - g1h->process_strong_roots( 37.8 + g1h->process_strong_roots(true, // activate StrongRootsScope 37.9 false, // fake perm gen collection 37.10 SharedHeap::SO_AllClasses, 37.11 &prcl, // Regular roots 37.12 + NULL, // do not visit active blobs 37.13 &prcl // Perm Gen Roots 37.14 ); 37.15 // The root iteration above "consumed" dirty cards in the perm gen. 37.16 @@ -852,9 +853,11 @@ 37.17 g1h->set_marking_started(); 37.18 g1h->rem_set()->prepare_for_younger_refs_iterate(false); 37.19 37.20 - g1h->process_strong_roots(false, // fake perm gen collection 37.21 + g1h->process_strong_roots(true, // activate StrongRootsScope 37.22 + false, // fake perm gen collection 37.23 SharedHeap::SO_AllClasses, 37.24 ¬Older, // Regular roots 37.25 + NULL, // do not visit active blobs 37.26 &older // Perm Gen Roots 37.27 ); 37.28 checkpointRootsInitialPost(); 37.29 @@ -1915,7 +1918,7 @@ 37.30 g1h->ensure_parsability(false); 37.31 37.32 if (ParallelGCThreads > 0) { 37.33 - g1h->change_strong_roots_parity(); 37.34 + G1CollectedHeap::StrongRootsScope srs(g1h); 37.35 // this is remark, so we'll use up all available threads 37.36 int active_workers = ParallelGCThreads; 37.37 set_phase(active_workers, false); 37.38 @@ -1932,7 +1935,7 @@ 37.39 SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); 37.40 guarantee( satb_mq_set.completed_buffers_num() == 0, "invariant" ); 37.41 } else { 37.42 - g1h->change_strong_roots_parity(); 37.43 + G1CollectedHeap::StrongRootsScope srs(g1h); 37.44 // this is remark, so we'll use up all available threads 37.45 int active_workers = 1; 37.46 set_phase(active_workers, false);
38.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Oct 02 11:26:25 2009 -0700 38.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Oct 09 15:18:52 2009 -0700 38.3 @@ -2300,9 +2300,12 @@ 38.4 if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) { 38.5 if (!silent) { gclog_or_tty->print("roots "); } 38.6 VerifyRootsClosure rootsCl(use_prev_marking); 38.7 - process_strong_roots(false, 38.8 + CodeBlobToOopClosure blobsCl(&rootsCl, /*do_marking=*/ false); 38.9 + process_strong_roots(true, // activate StrongRootsScope 38.10 + false, 38.11 SharedHeap::SO_AllClasses, 38.12 &rootsCl, 38.13 + &blobsCl, 38.14 &rootsCl); 38.15 rem_set()->invalidate(perm_gen()->used_region(), false); 38.16 if (!silent) { gclog_or_tty->print("heapRegions "); } 38.17 @@ -3987,8 +3990,14 @@ 38.18 BufferingOopsInGenClosure buf_scan_perm(scan_perm); 38.19 buf_scan_perm.set_generation(perm_gen()); 38.20 38.21 - process_strong_roots(collecting_perm_gen, so, 38.22 + // Walk the code cache w/o buffering, because StarTask cannot handle 38.23 + // unaligned oop locations. 38.24 + CodeBlobToOopClosure eager_scan_code_roots(scan_non_heap_roots, /*do_marking=*/ true); 38.25 + 38.26 + process_strong_roots(false, // no scoping; this is parallel code 38.27 + collecting_perm_gen, so, 38.28 &buf_scan_non_heap_roots, 38.29 + &eager_scan_code_roots, 38.30 &buf_scan_perm); 38.31 // Finish up any enqueued closure apps. 38.32 buf_scan_non_heap_roots.done(); 38.33 @@ -4078,7 +4087,8 @@ 38.34 void 38.35 G1CollectedHeap::g1_process_weak_roots(OopClosure* root_closure, 38.36 OopClosure* non_root_closure) { 38.37 - SharedHeap::process_weak_roots(root_closure, non_root_closure); 38.38 + CodeBlobToOopClosure roots_in_blobs(root_closure, /*do_marking=*/ false); 38.39 + SharedHeap::process_weak_roots(root_closure, &roots_in_blobs, non_root_closure); 38.40 } 38.41 38.42 38.43 @@ -4112,15 +4122,16 @@ 38.44 38.45 init_for_evac_failure(NULL); 38.46 38.47 - change_strong_roots_parity(); // In preparation for parallel strong roots. 38.48 rem_set()->prepare_for_younger_refs_iterate(true); 38.49 38.50 assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty"); 38.51 double start_par = os::elapsedTime(); 38.52 if (ParallelGCThreads > 0) { 38.53 // The individual threads will set their evac-failure closures. 38.54 + StrongRootsScope srs(this); 38.55 workers()->run_task(&g1_par_task); 38.56 } else { 38.57 + StrongRootsScope srs(this); 38.58 g1_par_task.work(0); 38.59 } 38.60
39.1 --- a/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Fri Oct 02 11:26:25 2009 -0700 39.2 +++ b/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Fri Oct 09 15:18:52 2009 -0700 39.3 @@ -121,9 +121,11 @@ 39.4 39.5 SharedHeap* sh = SharedHeap::heap(); 39.6 39.7 - sh->process_strong_roots(true, // Collecting permanent generation. 39.8 + sh->process_strong_roots(true, // activeate StrongRootsScope 39.9 + true, // Collecting permanent generation. 39.10 SharedHeap::SO_SystemClasses, 39.11 &GenMarkSweep::follow_root_closure, 39.12 + &GenMarkSweep::follow_code_root_closure, 39.13 &GenMarkSweep::follow_root_closure); 39.14 39.15 // Process reference objects found during marking 39.16 @@ -286,9 +288,11 @@ 39.17 39.18 SharedHeap* sh = SharedHeap::heap(); 39.19 39.20 - sh->process_strong_roots(true, // Collecting permanent generation. 39.21 + sh->process_strong_roots(true, // activate StrongRootsScope 39.22 + true, // Collecting permanent generation. 39.23 SharedHeap::SO_AllClasses, 39.24 &GenMarkSweep::adjust_root_pointer_closure, 39.25 + NULL, // do not touch code cache here 39.26 &GenMarkSweep::adjust_pointer_closure); 39.27 39.28 g1h->ref_processor()->weak_oops_do(&GenMarkSweep::adjust_root_pointer_closure);
40.1 --- a/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge Fri Oct 02 11:26:25 2009 -0700 40.2 +++ b/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge Fri Oct 09 15:18:52 2009 -0700 40.3 @@ -373,6 +373,7 @@ 40.4 psScavenge.inline.hpp psPromotionManager.hpp 40.5 psScavenge.inline.hpp psScavenge.hpp 40.6 40.7 +pcTasks.cpp codeCache.hpp 40.8 pcTasks.cpp collectedHeap.hpp 40.9 pcTasks.cpp fprofiler.hpp 40.10 pcTasks.cpp jniHandles.hpp 40.11 @@ -392,6 +393,7 @@ 40.12 pcTasks.hpp psTasks.hpp 40.13 40.14 psTasks.cpp cardTableExtension.hpp 40.15 +psTasks.cpp codeCache.hpp 40.16 psTasks.cpp fprofiler.hpp 40.17 psTasks.cpp gcTaskManager.hpp 40.18 psTasks.cpp iterator.hpp
41.1 --- a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Oct 02 11:26:25 2009 -0700 41.2 +++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Oct 09 15:18:52 2009 -0700 41.3 @@ -480,12 +480,14 @@ 41.4 41.5 par_scan_state.start_strong_roots(); 41.6 gch->gen_process_strong_roots(_gen->level(), 41.7 - true, // Process younger gens, if any, 41.8 - // as strong roots. 41.9 - false,// not collecting perm generation. 41.10 + true, // Process younger gens, if any, 41.11 + // as strong roots. 41.12 + false, // no scope; this is parallel code 41.13 + false, // not collecting perm generation. 41.14 SharedHeap::SO_AllClasses, 41.15 - &par_scan_state.older_gen_closure(), 41.16 - &par_scan_state.to_space_root_closure()); 41.17 + &par_scan_state.to_space_root_closure(), 41.18 + true, // walk *all* scavengable nmethods 41.19 + &par_scan_state.older_gen_closure()); 41.20 par_scan_state.end_strong_roots(); 41.21 41.22 // "evacuate followers". 41.23 @@ -799,15 +801,16 @@ 41.24 ParNewGenTask tsk(this, _next_gen, reserved().end(), &thread_state_set); 41.25 int n_workers = workers->total_workers(); 41.26 gch->set_par_threads(n_workers); 41.27 - gch->change_strong_roots_parity(); 41.28 gch->rem_set()->prepare_for_younger_refs_iterate(true); 41.29 // It turns out that even when we're using 1 thread, doing the work in a 41.30 // separate thread causes wide variance in run times. We can't help this 41.31 // in the multi-threaded case, but we special-case n=1 here to get 41.32 // repeatable measurements of the 1-thread overhead of the parallel code. 41.33 if (n_workers > 1) { 41.34 + GenCollectedHeap::StrongRootsScope srs(gch); 41.35 workers->run_task(&tsk); 41.36 } else { 41.37 + GenCollectedHeap::StrongRootsScope srs(gch); 41.38 tsk.work(0); 41.39 } 41.40 thread_state_set.reset();
42.1 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Fri Oct 02 11:26:25 2009 -0700 42.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Fri Oct 09 15:18:52 2009 -0700 42.3 @@ -962,6 +962,14 @@ 42.4 _old_gen->resize(desired_free_space); 42.5 } 42.6 42.7 +ParallelScavengeHeap::ParStrongRootsScope::ParStrongRootsScope() { 42.8 + // nothing particular 42.9 +} 42.10 + 42.11 +ParallelScavengeHeap::ParStrongRootsScope::~ParStrongRootsScope() { 42.12 + // nothing particular 42.13 +} 42.14 + 42.15 #ifndef PRODUCT 42.16 void ParallelScavengeHeap::record_gen_tops_before_GC() { 42.17 if (ZapUnusedHeapArea) {
43.1 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Fri Oct 02 11:26:25 2009 -0700 43.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Fri Oct 09 15:18:52 2009 -0700 43.3 @@ -234,6 +234,13 @@ 43.4 43.5 // Mangle the unused parts of all spaces in the heap 43.6 void gen_mangle_unused_area() PRODUCT_RETURN; 43.7 + 43.8 + // Call these in sequential code around the processing of strong roots. 43.9 + class ParStrongRootsScope : public MarkingCodeBlobClosure::MarkScope { 43.10 + public: 43.11 + ParStrongRootsScope(); 43.12 + ~ParStrongRootsScope(); 43.13 + }; 43.14 }; 43.15 43.16 inline size_t ParallelScavengeHeap::set_alignment(size_t& var, size_t val)
44.1 --- a/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Fri Oct 02 11:26:25 2009 -0700 44.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Fri Oct 09 15:18:52 2009 -0700 44.3 @@ -39,12 +39,13 @@ 44.4 ParCompactionManager* cm = 44.5 ParCompactionManager::gc_thread_compaction_manager(which); 44.6 PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm); 44.7 + CodeBlobToOopClosure mark_and_push_in_blobs(&mark_and_push_closure, /*do_marking=*/ true); 44.8 44.9 if (_java_thread != NULL) 44.10 - _java_thread->oops_do(&mark_and_push_closure); 44.11 + _java_thread->oops_do(&mark_and_push_closure, &mark_and_push_in_blobs); 44.12 44.13 if (_vm_thread != NULL) 44.14 - _vm_thread->oops_do(&mark_and_push_closure); 44.15 + _vm_thread->oops_do(&mark_and_push_closure, &mark_and_push_in_blobs); 44.16 44.17 // Do the real work 44.18 cm->drain_marking_stacks(&mark_and_push_closure); 44.19 @@ -78,7 +79,8 @@ 44.20 case threads: 44.21 { 44.22 ResourceMark rm; 44.23 - Threads::oops_do(&mark_and_push_closure); 44.24 + CodeBlobToOopClosure each_active_code_blob(&mark_and_push_closure, /*do_marking=*/ true); 44.25 + Threads::oops_do(&mark_and_push_closure, &each_active_code_blob); 44.26 } 44.27 break; 44.28 44.29 @@ -106,6 +108,11 @@ 44.30 vmSymbols::oops_do(&mark_and_push_closure); 44.31 break; 44.32 44.33 + case code_cache: 44.34 + // Do not treat nmethods as strong roots for mark/sweep, since we can unload them. 44.35 + //CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure(&mark_and_push_closure)); 44.36 + break; 44.37 + 44.38 default: 44.39 fatal("Unknown root type"); 44.40 }
45.1 --- a/src/share/vm/gc_implementation/parallelScavenge/pcTasks.hpp Fri Oct 02 11:26:25 2009 -0700 45.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/pcTasks.hpp Fri Oct 09 15:18:52 2009 -0700 45.3 @@ -92,7 +92,8 @@ 45.4 jvmti = 7, 45.5 system_dictionary = 8, 45.6 vm_symbols = 9, 45.7 - reference_processing = 10 45.8 + reference_processing = 10, 45.9 + code_cache = 11 45.10 }; 45.11 private: 45.12 RootType _root_type;
46.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Fri Oct 02 11:26:25 2009 -0700 46.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Fri Oct 09 15:18:52 2009 -0700 46.3 @@ -511,16 +511,22 @@ 46.4 assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); 46.5 46.6 // General strong roots. 46.7 - Universe::oops_do(mark_and_push_closure()); 46.8 - ReferenceProcessor::oops_do(mark_and_push_closure()); 46.9 - JNIHandles::oops_do(mark_and_push_closure()); // Global (strong) JNI handles 46.10 - Threads::oops_do(mark_and_push_closure()); 46.11 - ObjectSynchronizer::oops_do(mark_and_push_closure()); 46.12 - FlatProfiler::oops_do(mark_and_push_closure()); 46.13 - Management::oops_do(mark_and_push_closure()); 46.14 - JvmtiExport::oops_do(mark_and_push_closure()); 46.15 - SystemDictionary::always_strong_oops_do(mark_and_push_closure()); 46.16 - vmSymbols::oops_do(mark_and_push_closure()); 46.17 + { 46.18 + ParallelScavengeHeap::ParStrongRootsScope psrs; 46.19 + Universe::oops_do(mark_and_push_closure()); 46.20 + ReferenceProcessor::oops_do(mark_and_push_closure()); 46.21 + JNIHandles::oops_do(mark_and_push_closure()); // Global (strong) JNI handles 46.22 + CodeBlobToOopClosure each_active_code_blob(mark_and_push_closure(), /*do_marking=*/ true); 46.23 + Threads::oops_do(mark_and_push_closure(), &each_active_code_blob); 46.24 + ObjectSynchronizer::oops_do(mark_and_push_closure()); 46.25 + FlatProfiler::oops_do(mark_and_push_closure()); 46.26 + Management::oops_do(mark_and_push_closure()); 46.27 + JvmtiExport::oops_do(mark_and_push_closure()); 46.28 + SystemDictionary::always_strong_oops_do(mark_and_push_closure()); 46.29 + vmSymbols::oops_do(mark_and_push_closure()); 46.30 + // Do not treat nmethods as strong roots for mark/sweep, since we can unload them. 46.31 + //CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure(mark_and_push_closure())); 46.32 + } 46.33 46.34 // Flush marking stack. 46.35 follow_stack(); 46.36 @@ -617,7 +623,7 @@ 46.37 Universe::oops_do(adjust_root_pointer_closure()); 46.38 ReferenceProcessor::oops_do(adjust_root_pointer_closure()); 46.39 JNIHandles::oops_do(adjust_root_pointer_closure()); // Global (strong) JNI handles 46.40 - Threads::oops_do(adjust_root_pointer_closure()); 46.41 + Threads::oops_do(adjust_root_pointer_closure(), NULL); 46.42 ObjectSynchronizer::oops_do(adjust_root_pointer_closure()); 46.43 FlatProfiler::oops_do(adjust_root_pointer_closure()); 46.44 Management::oops_do(adjust_root_pointer_closure()); 46.45 @@ -625,6 +631,7 @@ 46.46 // SO_AllClasses 46.47 SystemDictionary::oops_do(adjust_root_pointer_closure()); 46.48 vmSymbols::oops_do(adjust_root_pointer_closure()); 46.49 + //CodeCache::scavenge_root_nmethods_oops_do(adjust_root_pointer_closure()); 46.50 46.51 // Now adjust pointers in remaining weak roots. (All of which should 46.52 // have been cleared if they pointed to non-surviving objects.)
47.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Oct 02 11:26:25 2009 -0700 47.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Oct 09 15:18:52 2009 -0700 47.3 @@ -2322,6 +2322,7 @@ 47.4 47.5 { 47.6 TraceTime tm_m("par mark", print_phases(), true, gclog_or_tty); 47.7 + ParallelScavengeHeap::ParStrongRootsScope psrs; 47.8 47.9 GCTaskQueue* q = GCTaskQueue::create(); 47.10 47.11 @@ -2335,6 +2336,7 @@ 47.12 q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::system_dictionary)); 47.13 q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::jvmti)); 47.14 q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::vm_symbols)); 47.15 + q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::code_cache)); 47.16 47.17 if (parallel_gc_threads > 1) { 47.18 for (uint j = 0; j < parallel_gc_threads; j++) { 47.19 @@ -2408,7 +2410,7 @@ 47.20 Universe::oops_do(adjust_root_pointer_closure()); 47.21 ReferenceProcessor::oops_do(adjust_root_pointer_closure()); 47.22 JNIHandles::oops_do(adjust_root_pointer_closure()); // Global (strong) JNI handles 47.23 - Threads::oops_do(adjust_root_pointer_closure()); 47.24 + Threads::oops_do(adjust_root_pointer_closure(), NULL); 47.25 ObjectSynchronizer::oops_do(adjust_root_pointer_closure()); 47.26 FlatProfiler::oops_do(adjust_root_pointer_closure()); 47.27 Management::oops_do(adjust_root_pointer_closure());
48.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Fri Oct 02 11:26:25 2009 -0700 48.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Fri Oct 09 15:18:52 2009 -0700 48.3 @@ -799,8 +799,7 @@ 48.4 FollowRootClosure(ParCompactionManager* cm) : _compaction_manager(cm) { } 48.5 virtual void do_oop(oop* p); 48.6 virtual void do_oop(narrowOop* p); 48.7 - virtual const bool do_nmethods() const { return true; } 48.8 - }; 48.9 + }; 48.10 48.11 class FollowStackClosure: public VoidClosure { 48.12 private: 48.13 @@ -817,6 +816,8 @@ 48.14 AdjustPointerClosure(bool is_root) : _is_root(is_root) { } 48.15 virtual void do_oop(oop* p); 48.16 virtual void do_oop(narrowOop* p); 48.17 + // do not walk from thread stacks to the code cache on this phase 48.18 + virtual void do_code_blob(CodeBlob* cb) const { } 48.19 }; 48.20 48.21 // Closure for verifying update of pointers. Does not 48.22 @@ -1063,7 +1064,6 @@ 48.23 MarkAndPushClosure(ParCompactionManager* cm) : _compaction_manager(cm) { } 48.24 virtual void do_oop(oop* p); 48.25 virtual void do_oop(narrowOop* p); 48.26 - virtual const bool do_nmethods() const { return true; } 48.27 }; 48.28 48.29 PSParallelCompact();
49.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Fri Oct 02 11:26:25 2009 -0700 49.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Fri Oct 09 15:18:52 2009 -0700 49.3 @@ -358,6 +358,7 @@ 49.4 PSPromotionManager* promotion_manager = PSPromotionManager::vm_thread_promotion_manager(); 49.5 { 49.6 // TraceTime("Roots"); 49.7 + ParallelScavengeHeap::ParStrongRootsScope psrs; 49.8 49.9 GCTaskQueue* q = GCTaskQueue::create(); 49.10 49.11 @@ -376,6 +377,7 @@ 49.12 q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::management)); 49.13 q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::system_dictionary)); 49.14 q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::jvmti)); 49.15 + q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::code_cache)); 49.16 49.17 ParallelTaskTerminator terminator( 49.18 gc_task_manager()->workers(),
50.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp Fri Oct 02 11:26:25 2009 -0700 50.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp Fri Oct 09 15:18:52 2009 -0700 50.3 @@ -66,7 +66,7 @@ 50.4 case threads: 50.5 { 50.6 ResourceMark rm; 50.7 - Threads::oops_do(&roots_closure); 50.8 + Threads::oops_do(&roots_closure, NULL); 50.9 } 50.10 break; 50.11 50.12 @@ -90,6 +90,14 @@ 50.13 JvmtiExport::oops_do(&roots_closure); 50.14 break; 50.15 50.16 + 50.17 + case code_cache: 50.18 + { 50.19 + CodeBlobToOopClosure each_scavengable_code_blob(&roots_closure, /*do_marking=*/ true); 50.20 + CodeCache::scavenge_root_nmethods_do(&each_scavengable_code_blob); 50.21 + } 50.22 + break; 50.23 + 50.24 default: 50.25 fatal("Unknown root type"); 50.26 } 50.27 @@ -107,12 +115,13 @@ 50.28 50.29 PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(which); 50.30 PSScavengeRootsClosure roots_closure(pm); 50.31 + CodeBlobToOopClosure roots_in_blobs(&roots_closure, /*do_marking=*/ true); 50.32 50.33 if (_java_thread != NULL) 50.34 - _java_thread->oops_do(&roots_closure); 50.35 + _java_thread->oops_do(&roots_closure, &roots_in_blobs); 50.36 50.37 if (_vm_thread != NULL) 50.38 - _vm_thread->oops_do(&roots_closure); 50.39 + _vm_thread->oops_do(&roots_closure, &roots_in_blobs); 50.40 50.41 // Do the real work 50.42 pm->drain_stacks(false);
51.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psTasks.hpp Fri Oct 02 11:26:25 2009 -0700 51.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psTasks.hpp Fri Oct 09 15:18:52 2009 -0700 51.3 @@ -54,7 +54,8 @@ 51.4 flat_profiler = 5, 51.5 system_dictionary = 6, 51.6 management = 7, 51.7 - jvmti = 8 51.8 + jvmti = 8, 51.9 + code_cache = 9 51.10 }; 51.11 private: 51.12 RootType _root_type;
52.1 --- a/src/share/vm/gc_implementation/shared/markSweep.cpp Fri Oct 02 11:26:25 2009 -0700 52.2 +++ b/src/share/vm/gc_implementation/shared/markSweep.cpp Fri Oct 09 15:18:52 2009 -0700 52.3 @@ -93,6 +93,7 @@ 52.4 } 52.5 52.6 MarkSweep::FollowRootClosure MarkSweep::follow_root_closure; 52.7 +CodeBlobToOopClosure MarkSweep::follow_code_root_closure(&MarkSweep::follow_root_closure, /*do_marking=*/ true); 52.8 52.9 void MarkSweep::FollowRootClosure::do_oop(oop* p) { follow_root(p); } 52.10 void MarkSweep::FollowRootClosure::do_oop(narrowOop* p) { follow_root(p); }
53.1 --- a/src/share/vm/gc_implementation/shared/markSweep.hpp Fri Oct 02 11:26:25 2009 -0700 53.2 +++ b/src/share/vm/gc_implementation/shared/markSweep.hpp Fri Oct 09 15:18:52 2009 -0700 53.3 @@ -58,14 +58,12 @@ 53.4 public: 53.5 virtual void do_oop(oop* p); 53.6 virtual void do_oop(narrowOop* p); 53.7 - virtual const bool do_nmethods() const { return true; } 53.8 }; 53.9 53.10 class MarkAndPushClosure: public OopClosure { 53.11 public: 53.12 virtual void do_oop(oop* p); 53.13 virtual void do_oop(narrowOop* p); 53.14 - virtual const bool do_nmethods() const { return true; } 53.15 virtual const bool should_remember_mdo() const { return true; } 53.16 virtual void remember_mdo(DataLayout* p) { MarkSweep::revisit_mdo(p); } 53.17 }; 53.18 @@ -173,6 +171,7 @@ 53.19 public: 53.20 // Public closures 53.21 static FollowRootClosure follow_root_closure; 53.22 + static CodeBlobToOopClosure follow_code_root_closure; // => follow_root_closure 53.23 static MarkAndPushClosure mark_and_push_closure; 53.24 static FollowStackClosure follow_stack_closure; 53.25 static AdjustPointerClosure adjust_root_pointer_closure;
54.1 --- a/src/share/vm/gc_interface/collectedHeap.hpp Fri Oct 02 11:26:25 2009 -0700 54.2 +++ b/src/share/vm/gc_interface/collectedHeap.hpp Fri Oct 09 15:18:52 2009 -0700 54.3 @@ -263,6 +263,14 @@ 54.4 return p == NULL || is_permanent(p); 54.5 } 54.6 54.7 + // An object is scavengable if its location may move during a scavenge. 54.8 + // (A scavenge is a GC which is not a full GC.) 54.9 + // Currently, this just means it is not perm (and not null). 54.10 + // This could change if we rethink what's in perm-gen. 54.11 + bool is_scavengable(const void *p) const { 54.12 + return !is_in_permanent_or_null(p); 54.13 + } 54.14 + 54.15 // Returns "TRUE" if "p" is a method oop in the 54.16 // current heap, with high probability. This predicate 54.17 // is not stable, in general.
55.1 --- a/src/share/vm/memory/defNewGeneration.cpp Fri Oct 02 11:26:25 2009 -0700 55.2 +++ b/src/share/vm/memory/defNewGeneration.cpp Fri Oct 09 15:18:52 2009 -0700 55.3 @@ -555,12 +555,14 @@ 55.4 "save marks have not been newly set."); 55.5 55.6 gch->gen_process_strong_roots(_level, 55.7 - true, // Process younger gens, if any, as 55.8 - // strong roots. 55.9 - false,// not collecting permanent generation. 55.10 + true, // Process younger gens, if any, 55.11 + // as strong roots. 55.12 + true, // activate StrongRootsScope 55.13 + false, // not collecting perm generation. 55.14 SharedHeap::SO_AllClasses, 55.15 - &fsc_with_gc_barrier, 55.16 - &fsc_with_no_gc_barrier); 55.17 + &fsc_with_no_gc_barrier, 55.18 + true, // walk *all* scavengable nmethods 55.19 + &fsc_with_gc_barrier); 55.20 55.21 // "evacuate followers". 55.22 evacuate_followers.do_void();
56.1 --- a/src/share/vm/memory/genCollectedHeap.cpp Fri Oct 02 11:26:25 2009 -0700 56.2 +++ b/src/share/vm/memory/genCollectedHeap.cpp Fri Oct 09 15:18:52 2009 -0700 56.3 @@ -677,13 +677,23 @@ 56.4 void GenCollectedHeap:: 56.5 gen_process_strong_roots(int level, 56.6 bool younger_gens_as_roots, 56.7 + bool activate_scope, 56.8 bool collecting_perm_gen, 56.9 SharedHeap::ScanningOption so, 56.10 - OopsInGenClosure* older_gens, 56.11 - OopsInGenClosure* not_older_gens) { 56.12 + OopsInGenClosure* not_older_gens, 56.13 + bool do_code_roots, 56.14 + OopsInGenClosure* older_gens) { 56.15 // General strong roots. 56.16 - SharedHeap::process_strong_roots(collecting_perm_gen, so, 56.17 - not_older_gens, older_gens); 56.18 + 56.19 + if (!do_code_roots) { 56.20 + SharedHeap::process_strong_roots(activate_scope, collecting_perm_gen, so, 56.21 + not_older_gens, NULL, older_gens); 56.22 + } else { 56.23 + bool do_code_marking = (activate_scope || nmethod::oops_do_marking_is_active()); 56.24 + CodeBlobToOopClosure code_roots(not_older_gens, /*do_marking=*/ do_code_marking); 56.25 + SharedHeap::process_strong_roots(activate_scope, collecting_perm_gen, so, 56.26 + not_older_gens, &code_roots, older_gens); 56.27 + } 56.28 56.29 if (younger_gens_as_roots) { 56.30 if (!_gen_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) { 56.31 @@ -706,8 +716,9 @@ 56.32 } 56.33 56.34 void GenCollectedHeap::gen_process_weak_roots(OopClosure* root_closure, 56.35 + CodeBlobClosure* code_roots, 56.36 OopClosure* non_root_closure) { 56.37 - SharedHeap::process_weak_roots(root_closure, non_root_closure); 56.38 + SharedHeap::process_weak_roots(root_closure, code_roots, non_root_closure); 56.39 // "Local" "weak" refs 56.40 for (int i = 0; i < _n_gens; i++) { 56.41 _gens[i]->ref_processor()->weak_oops_do(root_closure);
57.1 --- a/src/share/vm/memory/genCollectedHeap.hpp Fri Oct 02 11:26:25 2009 -0700 57.2 +++ b/src/share/vm/memory/genCollectedHeap.hpp Fri Oct 09 15:18:52 2009 -0700 57.3 @@ -408,16 +408,22 @@ 57.4 // "SO_SystemClasses" to all the "system" classes and loaders; 57.5 // "SO_Symbols_and_Strings" applies the closure to all entries in 57.6 // SymbolsTable and StringTable. 57.7 - void gen_process_strong_roots(int level, bool younger_gens_as_roots, 57.8 + void gen_process_strong_roots(int level, 57.9 + bool younger_gens_as_roots, 57.10 + // The remaining arguments are in an order 57.11 + // consistent with SharedHeap::process_strong_roots: 57.12 + bool activate_scope, 57.13 bool collecting_perm_gen, 57.14 SharedHeap::ScanningOption so, 57.15 - OopsInGenClosure* older_gens, 57.16 - OopsInGenClosure* not_older_gens); 57.17 + OopsInGenClosure* not_older_gens, 57.18 + bool do_code_roots, 57.19 + OopsInGenClosure* older_gens); 57.20 57.21 // Apply "blk" to all the weak roots of the system. These include 57.22 // JNI weak roots, the code cache, system dictionary, symbol table, 57.23 // string table, and referents of reachable weak refs. 57.24 void gen_process_weak_roots(OopClosure* root_closure, 57.25 + CodeBlobClosure* code_roots, 57.26 OopClosure* non_root_closure); 57.27 57.28 // Set the saved marks of generations, if that makes sense.
58.1 --- a/src/share/vm/memory/genMarkSweep.cpp Fri Oct 02 11:26:25 2009 -0700 58.2 +++ b/src/share/vm/memory/genMarkSweep.cpp Fri Oct 09 15:18:52 2009 -0700 58.3 @@ -244,9 +244,12 @@ 58.4 58.5 gch->gen_process_strong_roots(level, 58.6 false, // Younger gens are not roots. 58.7 + true, // activate StrongRootsScope 58.8 true, // Collecting permanent generation. 58.9 SharedHeap::SO_SystemClasses, 58.10 - &follow_root_closure, &follow_root_closure); 58.11 + &follow_root_closure, 58.12 + true, // walk code active on stacks 58.13 + &follow_root_closure); 58.14 58.15 // Process reference objects found during marking 58.16 { 58.17 @@ -338,14 +341,19 @@ 58.18 58.19 gch->gen_process_strong_roots(level, 58.20 false, // Younger gens are not roots. 58.21 + true, // activate StrongRootsScope 58.22 true, // Collecting permanent generation. 58.23 SharedHeap::SO_AllClasses, 58.24 &adjust_root_pointer_closure, 58.25 + false, // do not walk code 58.26 &adjust_root_pointer_closure); 58.27 58.28 // Now adjust pointers in remaining weak roots. (All of which should 58.29 // have been cleared if they pointed to non-surviving objects.) 58.30 + CodeBlobToOopClosure adjust_code_pointer_closure(&adjust_pointer_closure, 58.31 + /*do_marking=*/ false); 58.32 gch->gen_process_weak_roots(&adjust_root_pointer_closure, 58.33 + &adjust_code_pointer_closure, 58.34 &adjust_pointer_closure); 58.35 58.36 adjust_marks();
59.1 --- a/src/share/vm/memory/iterator.cpp Fri Oct 02 11:26:25 2009 -0700 59.2 +++ b/src/share/vm/memory/iterator.cpp Fri Oct 09 15:18:52 2009 -0700 59.3 @@ -46,3 +46,42 @@ 59.4 } 59.5 #endif 59.6 59.7 + 59.8 +MarkingCodeBlobClosure::MarkScope::MarkScope(bool activate) 59.9 + : _active(activate) 59.10 +{ 59.11 + if (_active) nmethod::oops_do_marking_prologue(); 59.12 +} 59.13 + 59.14 +MarkingCodeBlobClosure::MarkScope::~MarkScope() { 59.15 + if (_active) nmethod::oops_do_marking_epilogue(); 59.16 +} 59.17 + 59.18 +void MarkingCodeBlobClosure::do_code_blob(CodeBlob* cb) { 59.19 + if (!cb->is_nmethod()) return; 59.20 + nmethod* nm = (nmethod*) cb; 59.21 + if (!nm->test_set_oops_do_mark()) { 59.22 + NOT_PRODUCT(if (TraceScavenge) nm->print_on(tty, "oops_do, 1st visit\n")); 59.23 + do_newly_marked_nmethod(nm); 59.24 + } else { 59.25 + NOT_PRODUCT(if (TraceScavenge) nm->print_on(tty, "oops_do, skipped on 2nd visit\n")); 59.26 + } 59.27 +} 59.28 + 59.29 +void CodeBlobToOopClosure::do_newly_marked_nmethod(nmethod* nm) { 59.30 + nm->oops_do(_cl, /*do_strong_roots_only=*/ true); 59.31 +} 59.32 + 59.33 +void CodeBlobToOopClosure::do_code_blob(CodeBlob* cb) { 59.34 + if (!_do_marking) { 59.35 + NOT_PRODUCT(if (TraceScavenge && Verbose && cb->is_nmethod()) ((nmethod*)cb)->print_on(tty, "oops_do, unmarked visit\n")); 59.36 + // This assert won't work, since there are lots of mini-passes 59.37 + // (mostly in debug mode) that co-exist with marking phases. 59.38 + //assert(!(cb->is_nmethod() && ((nmethod*)cb)->test_oops_do_mark()), "found marked nmethod during mark-free phase"); 59.39 + cb->oops_do(_cl); 59.40 + } else { 59.41 + MarkingCodeBlobClosure::do_code_blob(cb); 59.42 + } 59.43 +} 59.44 + 59.45 +
60.1 --- a/src/share/vm/memory/iterator.hpp Fri Oct 02 11:26:25 2009 -0700 60.2 +++ b/src/share/vm/memory/iterator.hpp Fri Oct 09 15:18:52 2009 -0700 60.3 @@ -24,6 +24,8 @@ 60.4 60.5 // The following classes are C++ `closures` for iterating over objects, roots and spaces 60.6 60.7 +class CodeBlob; 60.8 +class nmethod; 60.9 class ReferenceProcessor; 60.10 class DataLayout; 60.11 60.12 @@ -69,9 +71,6 @@ 60.13 virtual const bool should_remember_mdo() const { return false; } 60.14 virtual void remember_mdo(DataLayout* v) { /* do nothing */ } 60.15 60.16 - // If "true", invoke on nmethods (when scanning compiled frames). 60.17 - virtual const bool do_nmethods() const { return false; } 60.18 - 60.19 // The methods below control how object iterations invoking this closure 60.20 // should be performed: 60.21 60.22 @@ -176,6 +175,51 @@ 60.23 }; 60.24 60.25 60.26 +// CodeBlobClosure is used for iterating through code blobs 60.27 +// in the code cache or on thread stacks 60.28 + 60.29 +class CodeBlobClosure : public Closure { 60.30 + public: 60.31 + // Called for each code blob. 60.32 + virtual void do_code_blob(CodeBlob* cb) = 0; 60.33 +}; 60.34 + 60.35 + 60.36 +class MarkingCodeBlobClosure : public CodeBlobClosure { 60.37 + public: 60.38 + // Called for each code blob, but at most once per unique blob. 60.39 + virtual void do_newly_marked_nmethod(nmethod* nm) = 0; 60.40 + 60.41 + virtual void do_code_blob(CodeBlob* cb); 60.42 + // = { if (!nmethod(cb)->test_set_oops_do_mark()) do_newly_marked_nmethod(cb); } 60.43 + 60.44 + class MarkScope : public StackObj { 60.45 + protected: 60.46 + bool _active; 60.47 + public: 60.48 + MarkScope(bool activate = true); 60.49 + // = { if (active) nmethod::oops_do_marking_prologue(); } 60.50 + ~MarkScope(); 60.51 + // = { if (active) nmethod::oops_do_marking_epilogue(); } 60.52 + }; 60.53 +}; 60.54 + 60.55 + 60.56 +// Applies an oop closure to all ref fields in code blobs 60.57 +// iterated over in an object iteration. 60.58 +class CodeBlobToOopClosure: public MarkingCodeBlobClosure { 60.59 + OopClosure* _cl; 60.60 + bool _do_marking; 60.61 +public: 60.62 + virtual void do_newly_marked_nmethod(nmethod* cb); 60.63 + // = { cb->oops_do(_cl); } 60.64 + virtual void do_code_blob(CodeBlob* cb); 60.65 + // = { if (_do_marking) super::do_code_blob(cb); else cb->oops_do(_cl); } 60.66 + CodeBlobToOopClosure(OopClosure* cl, bool do_marking) 60.67 + : _cl(cl), _do_marking(do_marking) {} 60.68 +}; 60.69 + 60.70 + 60.71 60.72 // MonitorClosure is used for iterating over monitors in the monitors cache 60.73
61.1 --- a/src/share/vm/memory/sharedHeap.cpp Fri Oct 02 11:26:25 2009 -0700 61.2 +++ b/src/share/vm/memory/sharedHeap.cpp Fri Oct 09 15:18:52 2009 -0700 61.3 @@ -100,12 +100,27 @@ 61.4 "Not in range."); 61.5 } 61.6 61.7 -void SharedHeap::process_strong_roots(bool collecting_perm_gen, 61.8 +SharedHeap::StrongRootsScope::StrongRootsScope(SharedHeap* outer, bool activate) 61.9 + : MarkScope(activate) 61.10 +{ 61.11 + if (_active) { 61.12 + outer->change_strong_roots_parity(); 61.13 + } 61.14 +} 61.15 + 61.16 +SharedHeap::StrongRootsScope::~StrongRootsScope() { 61.17 + // nothing particular 61.18 +} 61.19 + 61.20 +void SharedHeap::process_strong_roots(bool activate_scope, 61.21 + bool collecting_perm_gen, 61.22 ScanningOption so, 61.23 OopClosure* roots, 61.24 + CodeBlobClosure* code_roots, 61.25 OopsInGenClosure* perm_blk) { 61.26 + StrongRootsScope srs(this, activate_scope); 61.27 // General strong roots. 61.28 - if (n_par_threads() == 0) change_strong_roots_parity(); 61.29 + assert(_strong_roots_parity != 0, "must have called prologue code"); 61.30 if (!_process_strong_tasks->is_task_claimed(SH_PS_Universe_oops_do)) { 61.31 Universe::oops_do(roots); 61.32 ReferenceProcessor::oops_do(roots); 61.33 @@ -117,9 +132,9 @@ 61.34 JNIHandles::oops_do(roots); 61.35 // All threads execute this; the individual threads are task groups. 61.36 if (ParallelGCThreads > 0) { 61.37 - Threads::possibly_parallel_oops_do(roots); 61.38 + Threads::possibly_parallel_oops_do(roots, code_roots); 61.39 } else { 61.40 - Threads::oops_do(roots); 61.41 + Threads::oops_do(roots, code_roots); 61.42 } 61.43 if (!_process_strong_tasks-> is_task_claimed(SH_PS_ObjectSynchronizer_oops_do)) 61.44 ObjectSynchronizer::oops_do(roots); 61.45 @@ -156,11 +171,29 @@ 61.46 } 61.47 61.48 if (!_process_strong_tasks->is_task_claimed(SH_PS_CodeCache_oops_do)) { 61.49 - if (so & SO_CodeCache) { 61.50 - CodeCache::oops_do(roots); 61.51 - } 61.52 + if (so & SO_CodeCache) { 61.53 + // (Currently, CMSCollector uses this to do intermediate-strength collections.) 61.54 + assert(collecting_perm_gen, "scanning all of code cache"); 61.55 + assert(code_roots != NULL, "must supply closure for code cache"); 61.56 + if (code_roots != NULL) { 61.57 + CodeCache::blobs_do(code_roots); 61.58 + } 61.59 + } else if (so & (SO_SystemClasses|SO_AllClasses)) { 61.60 + if (!collecting_perm_gen) { 61.61 + // If we are collecting from class statics, but we are not going to 61.62 + // visit all of the CodeCache, collect from the non-perm roots if any. 61.63 + // This makes the code cache function temporarily as a source of strong 61.64 + // roots for oops, until the next major collection. 61.65 + // 61.66 + // If collecting_perm_gen is true, we require that this phase will call 61.67 + // CodeCache::do_unloading. This will kill off nmethods with expired 61.68 + // weak references, such as stale invokedynamic targets. 61.69 + CodeCache::scavenge_root_nmethods_do(code_roots); 61.70 + } 61.71 + } 61.72 // Verify if the code cache contents are in the perm gen 61.73 - NOT_PRODUCT(CodeCache::oops_do(&assert_is_perm_closure)); 61.74 + NOT_PRODUCT(CodeBlobToOopClosure assert_code_is_perm(&assert_is_perm_closure, /*do_marking=*/ false)); 61.75 + NOT_PRODUCT(CodeCache::asserted_non_scavengable_nmethods_do(&assert_code_is_perm)); 61.76 } 61.77 61.78 // Roots that should point only into permanent generation. 61.79 @@ -220,11 +253,12 @@ 61.80 // just skip adjusting any shared entries in the string table. 61.81 61.82 void SharedHeap::process_weak_roots(OopClosure* root_closure, 61.83 + CodeBlobClosure* code_roots, 61.84 OopClosure* non_root_closure) { 61.85 // Global (weak) JNI handles 61.86 JNIHandles::weak_oops_do(&always_true, root_closure); 61.87 61.88 - CodeCache::oops_do(non_root_closure); 61.89 + CodeCache::blobs_do(code_roots); 61.90 SymbolTable::oops_do(root_closure); 61.91 if (UseSharedSpaces && !DumpSharedSpaces) { 61.92 SkipAdjustingSharedStrings skip_closure(root_closure);
62.1 --- a/src/share/vm/memory/sharedHeap.hpp Fri Oct 02 11:26:25 2009 -0700 62.2 +++ b/src/share/vm/memory/sharedHeap.hpp Fri Oct 09 15:18:52 2009 -0700 62.3 @@ -165,9 +165,21 @@ 62.4 // c) to never return a distinguished value (zero) with which such 62.5 // task-claiming variables may be initialized, to indicate "never 62.6 // claimed". 62.7 + private: 62.8 void change_strong_roots_parity(); 62.9 + public: 62.10 int strong_roots_parity() { return _strong_roots_parity; } 62.11 62.12 + // Call these in sequential code around process_strong_roots. 62.13 + // strong_roots_prologue calls change_strong_roots_parity, if 62.14 + // parallel tasks are enabled. 62.15 + class StrongRootsScope : public MarkingCodeBlobClosure::MarkScope { 62.16 + public: 62.17 + StrongRootsScope(SharedHeap* outer, bool activate = true); 62.18 + ~StrongRootsScope(); 62.19 + }; 62.20 + friend class StrongRootsScope; 62.21 + 62.22 enum ScanningOption { 62.23 SO_None = 0x0, 62.24 SO_AllClasses = 0x1, 62.25 @@ -198,15 +210,18 @@ 62.26 // "SO_Symbols" applies the closure to all entries in SymbolsTable; 62.27 // "SO_Strings" applies the closure to all entries in StringTable; 62.28 // "SO_CodeCache" applies the closure to all elements of the CodeCache. 62.29 - void process_strong_roots(bool collecting_perm_gen, 62.30 + void process_strong_roots(bool activate_scope, 62.31 + bool collecting_perm_gen, 62.32 ScanningOption so, 62.33 OopClosure* roots, 62.34 + CodeBlobClosure* code_roots, 62.35 OopsInGenClosure* perm_blk); 62.36 62.37 // Apply "blk" to all the weak roots of the system. These include 62.38 // JNI weak roots, the code cache, system dictionary, symbol table, 62.39 // string table. 62.40 void process_weak_roots(OopClosure* root_closure, 62.41 + CodeBlobClosure* code_roots, 62.42 OopClosure* non_root_closure); 62.43 62.44
63.1 --- a/src/share/vm/oops/instanceKlass.cpp Fri Oct 02 11:26:25 2009 -0700 63.2 +++ b/src/share/vm/oops/instanceKlass.cpp Fri Oct 09 15:18:52 2009 -0700 63.3 @@ -2152,7 +2152,7 @@ 63.4 // This is a short non-blocking critical region, so the no safepoint check is ok. 63.5 OsrList_lock->lock_without_safepoint_check(); 63.6 assert(n->is_osr_method(), "wrong kind of nmethod"); 63.7 - n->set_link(osr_nmethods_head()); 63.8 + n->set_osr_link(osr_nmethods_head()); 63.9 set_osr_nmethods_head(n); 63.10 // Remember to unlock again 63.11 OsrList_lock->unlock(); 63.12 @@ -2168,17 +2168,17 @@ 63.13 // Search for match 63.14 while(cur != NULL && cur != n) { 63.15 last = cur; 63.16 - cur = cur->link(); 63.17 + cur = cur->osr_link(); 63.18 } 63.19 if (cur == n) { 63.20 if (last == NULL) { 63.21 // Remove first element 63.22 - set_osr_nmethods_head(osr_nmethods_head()->link()); 63.23 + set_osr_nmethods_head(osr_nmethods_head()->osr_link()); 63.24 } else { 63.25 - last->set_link(cur->link()); 63.26 + last->set_osr_link(cur->osr_link()); 63.27 } 63.28 } 63.29 - n->set_link(NULL); 63.30 + n->set_osr_link(NULL); 63.31 // Remember to unlock again 63.32 OsrList_lock->unlock(); 63.33 } 63.34 @@ -2195,7 +2195,7 @@ 63.35 OsrList_lock->unlock(); 63.36 return osr; 63.37 } 63.38 - osr = osr->link(); 63.39 + osr = osr->osr_link(); 63.40 } 63.41 OsrList_lock->unlock(); 63.42 return NULL;
64.1 --- a/src/share/vm/oops/oop.hpp Fri Oct 02 11:26:25 2009 -0700 64.2 +++ b/src/share/vm/oops/oop.hpp Fri Oct 09 15:18:52 2009 -0700 64.3 @@ -330,6 +330,7 @@ 64.4 64.5 bool is_perm() const; 64.6 bool is_perm_or_null() const; 64.7 + bool is_scavengable() const; 64.8 bool is_shared() const; 64.9 bool is_shared_readonly() const; 64.10 bool is_shared_readwrite() const;
65.1 --- a/src/share/vm/oops/oop.inline2.hpp Fri Oct 02 11:26:25 2009 -0700 65.2 +++ b/src/share/vm/oops/oop.inline2.hpp Fri Oct 09 15:18:52 2009 -0700 65.3 @@ -34,3 +34,7 @@ 65.4 inline bool oopDesc::is_perm_or_null() const { 65.5 return this == NULL || is_perm(); 65.6 } 65.7 + 65.8 +inline bool oopDesc::is_scavengable() const { 65.9 + return Universe::heap()->is_scavengable(this); 65.10 +}
66.1 --- a/src/share/vm/opto/connode.cpp Fri Oct 02 11:26:25 2009 -0700 66.2 +++ b/src/share/vm/opto/connode.cpp Fri Oct 09 15:18:52 2009 -0700 66.3 @@ -1085,6 +1085,9 @@ 66.4 switch (op) { 66.5 case Op_SubX: 66.6 x = in(1)->in(1); 66.7 + // Avoid ideal transformations ping-pong between this and AddP for raw pointers. 66.8 + if (phase->find_intptr_t_con(x, -1) == 0) 66.9 + break; 66.10 y = in(1)->in(2); 66.11 if (fits_in_int(phase->type(y), true)) { 66.12 return addP_of_X2P(phase, x, y, true);
67.1 --- a/src/share/vm/opto/escape.cpp Fri Oct 02 11:26:25 2009 -0700 67.2 +++ b/src/share/vm/opto/escape.cpp Fri Oct 09 15:18:52 2009 -0700 67.3 @@ -524,12 +524,15 @@ 67.4 // inlining) which was not eliminated during parsing since the exactness 67.5 // of the allocation type was not propagated to the subclass type check. 67.6 // 67.7 + // Or the type 't' could be not related to 'base_t' at all. 67.8 + // It could happened when CHA type is different from MDO type on a dead path 67.9 + // (for example, from instanceof check) which is not collapsed during parsing. 67.10 + // 67.11 // Do nothing for such AddP node and don't process its users since 67.12 // this code branch will go away. 67.13 // 67.14 if (!t->is_known_instance() && 67.15 - !t->klass()->equals(base_t->klass()) && 67.16 - t->klass()->is_subtype_of(base_t->klass())) { 67.17 + !base_t->klass()->is_subtype_of(t->klass())) { 67.18 return false; // bail out 67.19 } 67.20
68.1 --- a/src/share/vm/opto/graphKit.cpp Fri Oct 02 11:26:25 2009 -0700 68.2 +++ b/src/share/vm/opto/graphKit.cpp Fri Oct 09 15:18:52 2009 -0700 68.3 @@ -1450,7 +1450,7 @@ 68.4 68.5 case BarrierSet::CardTableModRef: 68.6 case BarrierSet::CardTableExtension: 68.7 - write_barrier_post(store, obj, adr, val, use_precise); 68.8 + write_barrier_post(store, obj, adr, adr_idx, val, use_precise); 68.9 break; 68.10 68.11 case BarrierSet::ModRef: 68.12 @@ -3165,6 +3165,7 @@ 68.13 void GraphKit::write_barrier_post(Node* oop_store, 68.14 Node* obj, 68.15 Node* adr, 68.16 + uint adr_idx, 68.17 Node* val, 68.18 bool use_precise) { 68.19 // No store check needed if we're storing a NULL or an old object 68.20 @@ -3214,7 +3215,7 @@ 68.21 __ store(__ ctrl(), card_adr, zero, bt, adr_type); 68.22 } else { 68.23 // Specialized path for CM store barrier 68.24 - __ storeCM(__ ctrl(), card_adr, zero, oop_store, bt, adr_type); 68.25 + __ storeCM(__ ctrl(), card_adr, zero, oop_store, adr_idx, bt, adr_type); 68.26 } 68.27 68.28 // Final sync IdealKit and GraphKit. 68.29 @@ -3314,6 +3315,7 @@ 68.30 void GraphKit::g1_mark_card(IdealKit& ideal, 68.31 Node* card_adr, 68.32 Node* oop_store, 68.33 + uint oop_alias_idx, 68.34 Node* index, 68.35 Node* index_adr, 68.36 Node* buffer, 68.37 @@ -3323,7 +3325,7 @@ 68.38 Node* no_base = __ top(); 68.39 BasicType card_bt = T_BYTE; 68.40 // Smash zero into card. MUST BE ORDERED WRT TO STORE 68.41 - __ storeCM(__ ctrl(), card_adr, zero, oop_store, card_bt, Compile::AliasIdxRaw); 68.42 + __ storeCM(__ ctrl(), card_adr, zero, oop_store, oop_alias_idx, card_bt, Compile::AliasIdxRaw); 68.43 68.44 // Now do the queue work 68.45 __ if_then(index, BoolTest::ne, zero); { 68.46 @@ -3435,13 +3437,13 @@ 68.47 Node* card_val = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw); 68.48 68.49 __ if_then(card_val, BoolTest::ne, zero); { 68.50 - g1_mark_card(ideal, card_adr, oop_store, index, index_adr, buffer, tf); 68.51 + g1_mark_card(ideal, card_adr, oop_store, alias_idx, index, index_adr, buffer, tf); 68.52 } __ end_if(); 68.53 } __ end_if(); 68.54 } __ end_if(); 68.55 } else { 68.56 // Object.clone() instrinsic uses this path. 68.57 - g1_mark_card(ideal, card_adr, oop_store, index, index_adr, buffer, tf); 68.58 + g1_mark_card(ideal, card_adr, oop_store, alias_idx, index, index_adr, buffer, tf); 68.59 } 68.60 68.61 // Final sync IdealKit and GraphKit.
69.1 --- a/src/share/vm/opto/graphKit.hpp Fri Oct 02 11:26:25 2009 -0700 69.2 +++ b/src/share/vm/opto/graphKit.hpp Fri Oct 09 15:18:52 2009 -0700 69.3 @@ -603,7 +603,8 @@ 69.4 void sync_kit(IdealKit& ideal); 69.5 69.6 // vanilla/CMS post barrier 69.7 - void write_barrier_post(Node *store, Node* obj, Node* adr, Node* val, bool use_precise); 69.8 + void write_barrier_post(Node *store, Node* obj, 69.9 + Node* adr, uint adr_idx, Node* val, bool use_precise); 69.10 69.11 // G1 pre/post barriers 69.12 void g1_write_barrier_pre(Node* obj, 69.13 @@ -622,7 +623,8 @@ 69.14 bool use_precise); 69.15 // Helper function for g1 69.16 private: 69.17 - void g1_mark_card(IdealKit& ideal, Node* card_adr, Node* store, Node* index, Node* index_adr, 69.18 + void g1_mark_card(IdealKit& ideal, Node* card_adr, Node* store, uint oop_alias_idx, 69.19 + Node* index, Node* index_adr, 69.20 Node* buffer, const TypeFunc* tf); 69.21 69.22 public:
70.1 --- a/src/share/vm/opto/idealKit.cpp Fri Oct 02 11:26:25 2009 -0700 70.2 +++ b/src/share/vm/opto/idealKit.cpp Fri Oct 09 15:18:52 2009 -0700 70.3 @@ -378,7 +378,7 @@ 70.4 70.5 // Card mark store. Must be ordered so that it will come after the store of 70.6 // the oop. 70.7 -Node* IdealKit::storeCM(Node* ctl, Node* adr, Node *val, Node* oop_store, 70.8 +Node* IdealKit::storeCM(Node* ctl, Node* adr, Node *val, Node* oop_store, int oop_adr_idx, 70.9 BasicType bt, 70.10 int adr_idx) { 70.11 assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" ); 70.12 @@ -388,7 +388,7 @@ 70.13 70.14 // Add required edge to oop_store, optimizer does not support precedence edges. 70.15 // Convert required edge to precedence edge before allocation. 70.16 - Node* st = new (C, 5) StoreCMNode(ctl, mem, adr, adr_type, val, oop_store); 70.17 + Node* st = new (C, 5) StoreCMNode(ctl, mem, adr, adr_type, val, oop_store, oop_adr_idx); 70.18 70.19 st = transform(st); 70.20 set_memory(st, adr_idx);
71.1 --- a/src/share/vm/opto/idealKit.hpp Fri Oct 02 11:26:25 2009 -0700 71.2 +++ b/src/share/vm/opto/idealKit.hpp Fri Oct 09 15:18:52 2009 -0700 71.3 @@ -216,6 +216,7 @@ 71.4 Node* adr, 71.5 Node* val, 71.6 Node* oop_store, 71.7 + int oop_adr_idx, 71.8 BasicType bt, 71.9 int adr_idx); 71.10
72.1 --- a/src/share/vm/opto/library_call.cpp Fri Oct 02 11:26:25 2009 -0700 72.2 +++ b/src/share/vm/opto/library_call.cpp Fri Oct 09 15:18:52 2009 -0700 72.3 @@ -133,6 +133,7 @@ 72.4 return generate_method_call(method_id, true, false); 72.5 } 72.6 72.7 + Node* make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, Node* cnt2); 72.8 bool inline_string_compareTo(); 72.9 bool inline_string_indexOf(); 72.10 Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i); 72.11 @@ -796,6 +797,64 @@ 72.12 } 72.13 72.14 72.15 +//------------------------------make_string_method_node------------------------ 72.16 +// Helper method for String intrinsic finctions. 72.17 +Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, Node* cnt2) { 72.18 + const int value_offset = java_lang_String::value_offset_in_bytes(); 72.19 + const int count_offset = java_lang_String::count_offset_in_bytes(); 72.20 + const int offset_offset = java_lang_String::offset_offset_in_bytes(); 72.21 + 72.22 + Node* no_ctrl = NULL; 72.23 + 72.24 + ciInstanceKlass* klass = env()->String_klass(); 72.25 + const TypeInstPtr* string_type = 72.26 + TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0); 72.27 + 72.28 + const TypeAryPtr* value_type = 72.29 + TypeAryPtr::make(TypePtr::NotNull, 72.30 + TypeAry::make(TypeInt::CHAR,TypeInt::POS), 72.31 + ciTypeArrayKlass::make(T_CHAR), true, 0); 72.32 + 72.33 + // Get start addr of string and substring 72.34 + Node* str1_valuea = basic_plus_adr(str1, str1, value_offset); 72.35 + Node* str1_value = make_load(no_ctrl, str1_valuea, value_type, T_OBJECT, string_type->add_offset(value_offset)); 72.36 + Node* str1_offseta = basic_plus_adr(str1, str1, offset_offset); 72.37 + Node* str1_offset = make_load(no_ctrl, str1_offseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset)); 72.38 + Node* str1_start = array_element_address(str1_value, str1_offset, T_CHAR); 72.39 + 72.40 + // Pin loads from String::equals() argument since it could be NULL. 72.41 + Node* str2_ctrl = (opcode == Op_StrEquals) ? control() : no_ctrl; 72.42 + Node* str2_valuea = basic_plus_adr(str2, str2, value_offset); 72.43 + Node* str2_value = make_load(str2_ctrl, str2_valuea, value_type, T_OBJECT, string_type->add_offset(value_offset)); 72.44 + Node* str2_offseta = basic_plus_adr(str2, str2, offset_offset); 72.45 + Node* str2_offset = make_load(str2_ctrl, str2_offseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset)); 72.46 + Node* str2_start = array_element_address(str2_value, str2_offset, T_CHAR); 72.47 + 72.48 + Node* result = NULL; 72.49 + switch (opcode) { 72.50 + case Op_StrIndexOf: 72.51 + result = new (C, 6) StrIndexOfNode(control(), memory(TypeAryPtr::CHARS), 72.52 + str1_start, cnt1, str2_start, cnt2); 72.53 + break; 72.54 + case Op_StrComp: 72.55 + result = new (C, 6) StrCompNode(control(), memory(TypeAryPtr::CHARS), 72.56 + str1_start, cnt1, str2_start, cnt2); 72.57 + break; 72.58 + case Op_StrEquals: 72.59 + result = new (C, 5) StrEqualsNode(control(), memory(TypeAryPtr::CHARS), 72.60 + str1_start, str2_start, cnt1); 72.61 + break; 72.62 + default: 72.63 + ShouldNotReachHere(); 72.64 + return NULL; 72.65 + } 72.66 + 72.67 + // All these intrinsics have checks. 72.68 + C->set_has_split_ifs(true); // Has chance for split-if optimization 72.69 + 72.70 + return _gvn.transform(result); 72.71 +} 72.72 + 72.73 //------------------------------inline_string_compareTo------------------------ 72.74 bool LibraryCallKit::inline_string_compareTo() { 72.75 72.76 @@ -824,16 +883,16 @@ 72.77 ciInstanceKlass* klass = env()->String_klass(); 72.78 const TypeInstPtr* string_type = 72.79 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0); 72.80 - 72.81 - Node* compare = 72.82 - _gvn.transform(new (C, 7) StrCompNode( 72.83 - control(), 72.84 - memory(TypeAryPtr::CHARS), 72.85 - memory(string_type->add_offset(value_offset)), 72.86 - memory(string_type->add_offset(count_offset)), 72.87 - memory(string_type->add_offset(offset_offset)), 72.88 - receiver, 72.89 - argument)); 72.90 + Node* no_ctrl = NULL; 72.91 + 72.92 + // Get counts for string and argument 72.93 + Node* receiver_cnta = basic_plus_adr(receiver, receiver, count_offset); 72.94 + Node* receiver_cnt = make_load(no_ctrl, receiver_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); 72.95 + 72.96 + Node* argument_cnta = basic_plus_adr(argument, argument, count_offset); 72.97 + Node* argument_cnt = make_load(no_ctrl, argument_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); 72.98 + 72.99 + Node* compare = make_string_method_node(Op_StrComp, receiver, receiver_cnt, argument, argument_cnt); 72.100 push(compare); 72.101 return true; 72.102 } 72.103 @@ -865,45 +924,71 @@ 72.104 return true; 72.105 } 72.106 72.107 + // paths (plus control) merge 72.108 + RegionNode* region = new (C, 5) RegionNode(5); 72.109 + Node* phi = new (C, 5) PhiNode(region, TypeInt::BOOL); 72.110 + 72.111 + // does source == target string? 72.112 + Node* cmp = _gvn.transform(new (C, 3) CmpPNode(receiver, argument)); 72.113 + Node* bol = _gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::eq)); 72.114 + 72.115 + Node* if_eq = generate_slow_guard(bol, NULL); 72.116 + if (if_eq != NULL) { 72.117 + // receiver == argument 72.118 + phi->init_req(2, intcon(1)); 72.119 + region->init_req(2, if_eq); 72.120 + } 72.121 + 72.122 // get String klass for instanceOf 72.123 ciInstanceKlass* klass = env()->String_klass(); 72.124 72.125 - // two paths (plus control) merge 72.126 - RegionNode* region = new (C, 3) RegionNode(3); 72.127 - Node* phi = new (C, 3) PhiNode(region, TypeInt::BOOL); 72.128 - 72.129 - Node* inst = gen_instanceof(argument, makecon(TypeKlassPtr::make(klass))); 72.130 - Node* cmp = _gvn.transform(new (C, 3) CmpINode(inst, intcon(1))); 72.131 - Node* bol = _gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::eq)); 72.132 - 72.133 - IfNode* iff = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN); 72.134 - 72.135 - Node* if_true = _gvn.transform(new (C, 1) IfTrueNode(iff)); 72.136 - set_control(if_true); 72.137 + if (!stopped()) { 72.138 + Node* inst = gen_instanceof(argument, makecon(TypeKlassPtr::make(klass))); 72.139 + Node* cmp = _gvn.transform(new (C, 3) CmpINode(inst, intcon(1))); 72.140 + Node* bol = _gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::ne)); 72.141 + 72.142 + Node* inst_false = generate_guard(bol, NULL, PROB_MIN); 72.143 + //instanceOf == true, fallthrough 72.144 + 72.145 + if (inst_false != NULL) { 72.146 + phi->init_req(3, intcon(0)); 72.147 + region->init_req(3, inst_false); 72.148 + } 72.149 + } 72.150 72.151 const TypeInstPtr* string_type = 72.152 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0); 72.153 72.154 - // instanceOf == true 72.155 - Node* equals = 72.156 - _gvn.transform(new (C, 7) StrEqualsNode( 72.157 - control(), 72.158 - memory(TypeAryPtr::CHARS), 72.159 - memory(string_type->add_offset(value_offset)), 72.160 - memory(string_type->add_offset(count_offset)), 72.161 - memory(string_type->add_offset(offset_offset)), 72.162 - receiver, 72.163 - argument)); 72.164 - 72.165 - phi->init_req(1, _gvn.transform(equals)); 72.166 - region->init_req(1, if_true); 72.167 - 72.168 - //instanceOf == false, fallthrough 72.169 - Node* if_false = _gvn.transform(new (C, 1) IfFalseNode(iff)); 72.170 - set_control(if_false); 72.171 - 72.172 - phi->init_req(2, _gvn.transform(intcon(0))); 72.173 - region->init_req(2, if_false); 72.174 + Node* no_ctrl = NULL; 72.175 + Node* receiver_cnt; 72.176 + Node* argument_cnt; 72.177 + 72.178 + if (!stopped()) { 72.179 + // Get counts for string and argument 72.180 + Node* receiver_cnta = basic_plus_adr(receiver, receiver, count_offset); 72.181 + receiver_cnt = make_load(no_ctrl, receiver_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); 72.182 + 72.183 + // Pin load from argument string since it could be NULL. 72.184 + Node* argument_cnta = basic_plus_adr(argument, argument, count_offset); 72.185 + argument_cnt = make_load(control(), argument_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); 72.186 + 72.187 + // Check for receiver count != argument count 72.188 + Node* cmp = _gvn.transform( new(C, 3) CmpINode(receiver_cnt, argument_cnt) ); 72.189 + Node* bol = _gvn.transform( new(C, 2) BoolNode(cmp, BoolTest::ne) ); 72.190 + Node* if_ne = generate_slow_guard(bol, NULL); 72.191 + if (if_ne != NULL) { 72.192 + phi->init_req(4, intcon(0)); 72.193 + region->init_req(4, if_ne); 72.194 + } 72.195 + } 72.196 + 72.197 + // Check for count == 0 is done by mach node StrEquals. 72.198 + 72.199 + if (!stopped()) { 72.200 + Node* equals = make_string_method_node(Op_StrEquals, receiver, receiver_cnt, argument, argument_cnt); 72.201 + phi->init_req(1, equals); 72.202 + region->init_req(1, control()); 72.203 + } 72.204 72.205 // post merge 72.206 set_control(_gvn.transform(region)); 72.207 @@ -924,10 +1009,8 @@ 72.208 Node *argument1 = pop(); 72.209 72.210 Node* equals = 72.211 - _gvn.transform(new (C, 3) AryEqNode(control(), 72.212 - argument1, 72.213 - argument2) 72.214 - ); 72.215 + _gvn.transform(new (C, 4) AryEqNode(control(), memory(TypeAryPtr::CHARS), 72.216 + argument1, argument2) ); 72.217 push(equals); 72.218 return true; 72.219 } 72.220 @@ -1108,19 +1191,40 @@ 72.221 return true; 72.222 } 72.223 72.224 + // Make the merge point 72.225 + RegionNode* result_rgn = new (C, 3) RegionNode(3); 72.226 + Node* result_phi = new (C, 3) PhiNode(result_rgn, TypeInt::INT); 72.227 + Node* no_ctrl = NULL; 72.228 + 72.229 ciInstanceKlass* klass = env()->String_klass(); 72.230 const TypeInstPtr* string_type = 72.231 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0); 72.232 72.233 - result = 72.234 - _gvn.transform(new (C, 7) 72.235 - StrIndexOfNode(control(), 72.236 - memory(TypeAryPtr::CHARS), 72.237 - memory(string_type->add_offset(value_offset)), 72.238 - memory(string_type->add_offset(count_offset)), 72.239 - memory(string_type->add_offset(offset_offset)), 72.240 - receiver, 72.241 - argument)); 72.242 + // Get counts for string and substr 72.243 + Node* source_cnta = basic_plus_adr(receiver, receiver, count_offset); 72.244 + Node* source_cnt = make_load(no_ctrl, source_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); 72.245 + 72.246 + Node* substr_cnta = basic_plus_adr(argument, argument, count_offset); 72.247 + Node* substr_cnt = make_load(no_ctrl, substr_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); 72.248 + 72.249 + // Check for substr count > string count 72.250 + Node* cmp = _gvn.transform( new(C, 3) CmpINode(substr_cnt, source_cnt) ); 72.251 + Node* bol = _gvn.transform( new(C, 2) BoolNode(cmp, BoolTest::gt) ); 72.252 + Node* if_gt = generate_slow_guard(bol, NULL); 72.253 + if (if_gt != NULL) { 72.254 + result_phi->init_req(2, intcon(-1)); 72.255 + result_rgn->init_req(2, if_gt); 72.256 + } 72.257 + 72.258 + if (!stopped()) { 72.259 + result = make_string_method_node(Op_StrIndexOf, receiver, source_cnt, argument, substr_cnt); 72.260 + result_phi->init_req(1, result); 72.261 + result_rgn->init_req(1, control()); 72.262 + } 72.263 + set_control(_gvn.transform(result_rgn)); 72.264 + record_for_igvn(result_rgn); 72.265 + result = _gvn.transform(result_phi); 72.266 + 72.267 } else { //Use LibraryCallKit::string_indexOf 72.268 // don't intrinsify is argument isn't a constant string. 72.269 if (!argument->is_Con()) {
73.1 --- a/src/share/vm/opto/matcher.cpp Fri Oct 02 11:26:25 2009 -0700 73.2 +++ b/src/share/vm/opto/matcher.cpp Fri Oct 09 15:18:52 2009 -0700 73.3 @@ -2032,6 +2032,23 @@ 73.4 n->del_req(3); 73.5 break; 73.6 } 73.7 + case Op_StrEquals: { 73.8 + Node *pair1 = new (C, 3) BinaryNode(n->in(2),n->in(3)); 73.9 + n->set_req(2,pair1); 73.10 + n->set_req(3,n->in(4)); 73.11 + n->del_req(4); 73.12 + break; 73.13 + } 73.14 + case Op_StrComp: 73.15 + case Op_StrIndexOf: { 73.16 + Node *pair1 = new (C, 3) BinaryNode(n->in(2),n->in(3)); 73.17 + n->set_req(2,pair1); 73.18 + Node *pair2 = new (C, 3) BinaryNode(n->in(4),n->in(5)); 73.19 + n->set_req(3,pair2); 73.20 + n->del_req(5); 73.21 + n->del_req(4); 73.22 + break; 73.23 + } 73.24 default: 73.25 break; 73.26 }
74.1 --- a/src/share/vm/opto/memnode.cpp Fri Oct 02 11:26:25 2009 -0700 74.2 +++ b/src/share/vm/opto/memnode.cpp Fri Oct 09 15:18:52 2009 -0700 74.3 @@ -2313,6 +2313,22 @@ 74.4 return this; 74.5 } 74.6 74.7 +//============================================================================= 74.8 +//------------------------------Ideal--------------------------------------- 74.9 +Node *StoreCMNode::Ideal(PhaseGVN *phase, bool can_reshape){ 74.10 + Node* progress = StoreNode::Ideal(phase, can_reshape); 74.11 + if (progress != NULL) return progress; 74.12 + 74.13 + Node* my_store = in(MemNode::OopStore); 74.14 + if (my_store->is_MergeMem()) { 74.15 + Node* mem = my_store->as_MergeMem()->memory_at(oop_alias_idx()); 74.16 + set_req(MemNode::OopStore, mem); 74.17 + return this; 74.18 + } 74.19 + 74.20 + return NULL; 74.21 +} 74.22 + 74.23 //------------------------------Value----------------------------------------- 74.24 const Type *StoreCMNode::Value( PhaseTransform *phase ) const { 74.25 // Either input is TOP ==> the result is TOP 74.26 @@ -2498,7 +2514,7 @@ 74.27 //============================================================================= 74.28 // Do we match on this edge? No memory edges 74.29 uint StrCompNode::match_edge(uint idx) const { 74.30 - return idx == 5 || idx == 6; 74.31 + return idx == 2 || idx == 3; // StrComp (Binary str1 cnt1) (Binary str2 cnt2) 74.32 } 74.33 74.34 //------------------------------Ideal------------------------------------------ 74.35 @@ -2508,9 +2524,10 @@ 74.36 return remove_dead_region(phase, can_reshape) ? this : NULL; 74.37 } 74.38 74.39 +//============================================================================= 74.40 // Do we match on this edge? No memory edges 74.41 uint StrEqualsNode::match_edge(uint idx) const { 74.42 - return idx == 5 || idx == 6; 74.43 + return idx == 2 || idx == 3; // StrEquals (Binary str1 str2) cnt 74.44 } 74.45 74.46 //------------------------------Ideal------------------------------------------ 74.47 @@ -2523,7 +2540,7 @@ 74.48 //============================================================================= 74.49 // Do we match on this edge? No memory edges 74.50 uint StrIndexOfNode::match_edge(uint idx) const { 74.51 - return idx == 5 || idx == 6; 74.52 + return idx == 2 || idx == 3; // StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2) 74.53 } 74.54 74.55 //------------------------------Ideal------------------------------------------ 74.56 @@ -2533,6 +2550,11 @@ 74.57 return remove_dead_region(phase, can_reshape) ? this : NULL; 74.58 } 74.59 74.60 +//============================================================================= 74.61 +// Do we match on this edge? No memory edges 74.62 +uint AryEqNode::match_edge(uint idx) const { 74.63 + return idx == 2 || idx == 3; // StrEquals ary1 ary2 74.64 +} 74.65 //------------------------------Ideal------------------------------------------ 74.66 // Return a node which is more "ideal" than the current node. Strip out 74.67 // control copies
75.1 --- a/src/share/vm/opto/memnode.hpp Fri Oct 02 11:26:25 2009 -0700 75.2 +++ b/src/share/vm/opto/memnode.hpp Fri Oct 09 15:18:52 2009 -0700 75.3 @@ -582,12 +582,16 @@ 75.4 // The last StoreCM before a SafePoint must be preserved and occur after its "oop" store 75.5 // Preceeding equivalent StoreCMs may be eliminated. 75.6 class StoreCMNode : public StoreNode { 75.7 + private: 75.8 + int _oop_alias_idx; // The alias_idx of OopStore 75.9 public: 75.10 - StoreCMNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, Node *oop_store ) : StoreNode(c,mem,adr,at,val,oop_store) {} 75.11 + StoreCMNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, Node *oop_store, int oop_alias_idx ) : StoreNode(c,mem,adr,at,val,oop_store), _oop_alias_idx(oop_alias_idx) {} 75.12 virtual int Opcode() const; 75.13 virtual Node *Identity( PhaseTransform *phase ); 75.14 + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 75.15 virtual const Type *Value( PhaseTransform *phase ) const; 75.16 virtual BasicType memory_type() const { return T_VOID; } // unspecific 75.17 + int oop_alias_idx() const { return _oop_alias_idx; } 75.18 }; 75.19 75.20 //------------------------------LoadPLockedNode--------------------------------- 75.21 @@ -744,22 +748,15 @@ 75.22 //------------------------------StrComp------------------------------------- 75.23 class StrCompNode: public Node { 75.24 public: 75.25 - StrCompNode(Node *control, 75.26 - Node* char_array_mem, 75.27 - Node* value_mem, 75.28 - Node* count_mem, 75.29 - Node* offset_mem, 75.30 - Node* s1, Node* s2): Node(control, 75.31 - char_array_mem, 75.32 - value_mem, 75.33 - count_mem, 75.34 - offset_mem, 75.35 - s1, s2) {}; 75.36 + StrCompNode(Node* control, Node* char_array_mem, 75.37 + Node* s1, Node* c1, 75.38 + Node* s2, Node* c2): Node(control, char_array_mem, 75.39 + s1, c1, 75.40 + s2, c2) {}; 75.41 virtual int Opcode() const; 75.42 virtual bool depends_only_on_test() const { return false; } 75.43 virtual const Type* bottom_type() const { return TypeInt::INT; } 75.44 - // a StrCompNode (conservatively) aliases with everything: 75.45 - virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; } 75.46 + virtual const TypePtr* adr_type() const { return TypeAryPtr::CHARS; } 75.47 virtual uint match_edge(uint idx) const; 75.48 virtual uint ideal_reg() const { return Op_RegI; } 75.49 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 75.50 @@ -768,22 +765,13 @@ 75.51 //------------------------------StrEquals------------------------------------- 75.52 class StrEqualsNode: public Node { 75.53 public: 75.54 - StrEqualsNode(Node *control, 75.55 - Node* char_array_mem, 75.56 - Node* value_mem, 75.57 - Node* count_mem, 75.58 - Node* offset_mem, 75.59 - Node* s1, Node* s2): Node(control, 75.60 - char_array_mem, 75.61 - value_mem, 75.62 - count_mem, 75.63 - offset_mem, 75.64 - s1, s2) {}; 75.65 + StrEqualsNode(Node* control, Node* char_array_mem, 75.66 + Node* s1, Node* s2, Node* c): Node(control, char_array_mem, 75.67 + s1, s2, c) {}; 75.68 virtual int Opcode() const; 75.69 virtual bool depends_only_on_test() const { return false; } 75.70 virtual const Type* bottom_type() const { return TypeInt::BOOL; } 75.71 - // a StrEqualsNode (conservatively) aliases with everything: 75.72 - virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; } 75.73 + virtual const TypePtr* adr_type() const { return TypeAryPtr::CHARS; } 75.74 virtual uint match_edge(uint idx) const; 75.75 virtual uint ideal_reg() const { return Op_RegI; } 75.76 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 75.77 @@ -792,22 +780,15 @@ 75.78 //------------------------------StrIndexOf------------------------------------- 75.79 class StrIndexOfNode: public Node { 75.80 public: 75.81 - StrIndexOfNode(Node *control, 75.82 - Node* char_array_mem, 75.83 - Node* value_mem, 75.84 - Node* count_mem, 75.85 - Node* offset_mem, 75.86 - Node* s1, Node* s2): Node(control, 75.87 - char_array_mem, 75.88 - value_mem, 75.89 - count_mem, 75.90 - offset_mem, 75.91 - s1, s2) {}; 75.92 + StrIndexOfNode(Node* control, Node* char_array_mem, 75.93 + Node* s1, Node* c1, 75.94 + Node* s2, Node* c2): Node(control, char_array_mem, 75.95 + s1, c1, 75.96 + s2, c2) {}; 75.97 virtual int Opcode() const; 75.98 virtual bool depends_only_on_test() const { return false; } 75.99 virtual const Type* bottom_type() const { return TypeInt::INT; } 75.100 - // a StrIndexOfNode (conservatively) aliases with everything: 75.101 - virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; } 75.102 + virtual const TypePtr* adr_type() const { return TypeAryPtr::CHARS; } 75.103 virtual uint match_edge(uint idx) const; 75.104 virtual uint ideal_reg() const { return Op_RegI; } 75.105 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 75.106 @@ -816,11 +797,13 @@ 75.107 //------------------------------AryEq--------------------------------------- 75.108 class AryEqNode: public Node { 75.109 public: 75.110 - AryEqNode(Node *control, Node* s1, Node* s2): Node(control, s1, s2) {}; 75.111 + AryEqNode(Node* control, Node* char_array_mem, 75.112 + Node* s1, Node* s2): Node(control, char_array_mem, s1, s2) {}; 75.113 virtual int Opcode() const; 75.114 virtual bool depends_only_on_test() const { return false; } 75.115 virtual const Type* bottom_type() const { return TypeInt::BOOL; } 75.116 virtual const TypePtr* adr_type() const { return TypeAryPtr::CHARS; } 75.117 + virtual uint match_edge(uint idx) const; 75.118 virtual uint ideal_reg() const { return Op_RegI; } 75.119 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 75.120 };
76.1 --- a/src/share/vm/opto/output.cpp Fri Oct 02 11:26:25 2009 -0700 76.2 +++ b/src/share/vm/opto/output.cpp Fri Oct 09 15:18:52 2009 -0700 76.3 @@ -611,7 +611,7 @@ 76.4 assert(cik->is_instance_klass() || 76.5 cik->is_array_klass(), "Not supported allocation."); 76.6 sv = new ObjectValue(spobj->_idx, 76.7 - new ConstantOopWriteValue(cik->encoding())); 76.8 + new ConstantOopWriteValue(cik->constant_encoding())); 76.9 Compile::set_sv_for_object_node(objs, sv); 76.10 76.11 uint first_ind = spobj->first_index(); 76.12 @@ -702,13 +702,13 @@ 76.13 case Type::AryPtr: 76.14 case Type::InstPtr: 76.15 case Type::KlassPtr: // fall through 76.16 - array->append(new ConstantOopWriteValue(t->isa_oopptr()->const_oop()->encoding())); 76.17 + array->append(new ConstantOopWriteValue(t->isa_oopptr()->const_oop()->constant_encoding())); 76.18 break; 76.19 case Type::NarrowOop: 76.20 if (t == TypeNarrowOop::NULL_PTR) { 76.21 array->append(new ConstantOopWriteValue(NULL)); 76.22 } else { 76.23 - array->append(new ConstantOopWriteValue(t->make_ptr()->isa_oopptr()->const_oop()->encoding())); 76.24 + array->append(new ConstantOopWriteValue(t->make_ptr()->isa_oopptr()->const_oop()->constant_encoding())); 76.25 } 76.26 break; 76.27 case Type::Int: 76.28 @@ -871,7 +871,7 @@ 76.29 assert(cik->is_instance_klass() || 76.30 cik->is_array_klass(), "Not supported allocation."); 76.31 ObjectValue* sv = new ObjectValue(spobj->_idx, 76.32 - new ConstantOopWriteValue(cik->encoding())); 76.33 + new ConstantOopWriteValue(cik->constant_encoding())); 76.34 Compile::set_sv_for_object_node(objs, sv); 76.35 76.36 uint first_ind = spobj->first_index(); 76.37 @@ -890,7 +890,7 @@ 76.38 } 76.39 } else { 76.40 const TypePtr *tp = obj_node->bottom_type()->make_ptr(); 76.41 - scval = new ConstantOopWriteValue(tp->is_instptr()->const_oop()->encoding()); 76.42 + scval = new ConstantOopWriteValue(tp->is_instptr()->const_oop()->constant_encoding()); 76.43 } 76.44 76.45 OptoReg::Name box_reg = BoxLockNode::stack_slot(box_node);
77.1 --- a/src/share/vm/opto/parse.hpp Fri Oct 02 11:26:25 2009 -0700 77.2 +++ b/src/share/vm/opto/parse.hpp Fri Oct 09 15:18:52 2009 -0700 77.3 @@ -469,7 +469,7 @@ 77.4 77.5 // loading from a constant field or the constant pool 77.6 // returns false if push failed (non-perm field constants only, not ldcs) 77.7 - bool push_constant(ciConstant con); 77.8 + bool push_constant(ciConstant con, bool require_constant = false); 77.9 77.10 // implementation of object creation bytecodes 77.11 void do_new();
78.1 --- a/src/share/vm/opto/parse1.cpp Fri Oct 02 11:26:25 2009 -0700 78.2 +++ b/src/share/vm/opto/parse1.cpp Fri Oct 09 15:18:52 2009 -0700 78.3 @@ -229,7 +229,9 @@ 78.4 } 78.5 } 78.6 78.7 - MethodLivenessResult live_locals = method()->liveness_at_bci(osr_bci()); 78.8 + // Use the raw liveness computation to make sure that unexpected 78.9 + // values don't propagate into the OSR frame. 78.10 + MethodLivenessResult live_locals = method()->raw_liveness_at_bci(osr_bci()); 78.11 if (!live_locals.is_valid()) { 78.12 // Degenerate or breakpointed method. 78.13 C->record_method_not_compilable("OSR in empty or breakpointed method");
79.1 --- a/src/share/vm/opto/parse2.cpp Fri Oct 02 11:26:25 2009 -0700 79.2 +++ b/src/share/vm/opto/parse2.cpp Fri Oct 09 15:18:52 2009 -0700 79.3 @@ -1325,7 +1325,8 @@ 79.4 } 79.5 } 79.6 } 79.7 - push_constant(constant); 79.8 + bool pushed = push_constant(constant, true); 79.9 + guarantee(pushed, "must be possible to push this constant"); 79.10 } 79.11 79.12 break;
80.1 --- a/src/share/vm/opto/parse3.cpp Fri Oct 02 11:26:25 2009 -0700 80.2 +++ b/src/share/vm/opto/parse3.cpp Fri Oct 09 15:18:52 2009 -0700 80.3 @@ -267,7 +267,7 @@ 80.4 } 80.5 80.6 80.7 -bool Parse::push_constant(ciConstant constant) { 80.8 +bool Parse::push_constant(ciConstant constant, bool require_constant) { 80.9 switch (constant.basic_type()) { 80.10 case T_BOOLEAN: push( intcon(constant.as_boolean()) ); break; 80.11 case T_INT: push( intcon(constant.as_int()) ); break; 80.12 @@ -279,13 +279,16 @@ 80.13 case T_LONG: push_pair( longcon(constant.as_long()) ); break; 80.14 case T_ARRAY: 80.15 case T_OBJECT: { 80.16 - // the oop is in perm space if the ciObject "has_encoding" 80.17 + // cases: 80.18 + // can_be_constant = (oop not scavengable || ScavengeRootsInCode != 0) 80.19 + // should_be_constant = (oop not scavengable || ScavengeRootsInCode >= 2) 80.20 + // An oop is not scavengable if it is in the perm gen. 80.21 ciObject* oop_constant = constant.as_object(); 80.22 if (oop_constant->is_null_object()) { 80.23 push( zerocon(T_OBJECT) ); 80.24 break; 80.25 - } else if (oop_constant->has_encoding()) { 80.26 - push( makecon(TypeOopPtr::make_from_constant(oop_constant)) ); 80.27 + } else if (require_constant || oop_constant->should_be_constant()) { 80.28 + push( makecon(TypeOopPtr::make_from_constant(oop_constant, require_constant)) ); 80.29 break; 80.30 } else { 80.31 // we cannot inline the oop, but we can use it later to narrow a type
81.1 --- a/src/share/vm/opto/superword.cpp Fri Oct 02 11:26:25 2009 -0700 81.2 +++ b/src/share/vm/opto/superword.cpp Fri Oct 09 15:18:52 2009 -0700 81.3 @@ -457,10 +457,6 @@ 81.4 } else if (out->Opcode() == Op_StoreCM && out->in(MemNode::OopStore) == n) { 81.5 // StoreCM has an input edge used as a precedence edge. 81.6 // Maybe an issue when oop stores are vectorized. 81.7 - } else if( out->is_MergeMem() && prev && 81.8 - prev->Opcode() == Op_StoreCM && out == prev->in(MemNode::OopStore)) { 81.9 - // Oop store is a MergeMem! This should not happen. Temporarily remove the assertion 81.10 - // for this case because it could not be superwordized anyway. 81.11 } else { 81.12 assert(out == prev || prev == NULL, "no branches off of store slice"); 81.13 } 81.14 @@ -477,6 +473,12 @@ 81.15 // Can s1 and s2 be in a pack with s1 immediately preceding s2 and 81.16 // s1 aligned at "align" 81.17 bool SuperWord::stmts_can_pack(Node* s1, Node* s2, int align) { 81.18 + 81.19 + // Do not use superword for non-primitives 81.20 + if((s1->is_Mem() && !is_java_primitive(s1->as_Mem()->memory_type())) || 81.21 + (s2->is_Mem() && !is_java_primitive(s2->as_Mem()->memory_type()))) 81.22 + return false; 81.23 + 81.24 if (isomorphic(s1, s2)) { 81.25 if (independent(s1, s2)) { 81.26 if (!exists_at(s1, 0) && !exists_at(s2, 1)) {
82.1 --- a/src/share/vm/opto/type.cpp Fri Oct 02 11:26:25 2009 -0700 82.2 +++ b/src/share/vm/opto/type.cpp Fri Oct 09 15:18:52 2009 -0700 82.3 @@ -296,7 +296,7 @@ 82.4 false, 0, oopDesc::mark_offset_in_bytes()); 82.5 TypeInstPtr::KLASS = TypeInstPtr::make(TypePtr::BotPTR, current->env()->Object_klass(), 82.6 false, 0, oopDesc::klass_offset_in_bytes()); 82.7 - TypeOopPtr::BOTTOM = TypeOopPtr::make(TypePtr::BotPTR, OffsetBot); 82.8 + TypeOopPtr::BOTTOM = TypeOopPtr::make(TypePtr::BotPTR, OffsetBot, TypeOopPtr::InstanceBot); 82.9 82.10 TypeNarrowOop::NULL_PTR = TypeNarrowOop::make( TypePtr::NULL_PTR ); 82.11 TypeNarrowOop::BOTTOM = TypeNarrowOop::make( TypeInstPtr::BOTTOM ); 82.12 @@ -492,8 +492,13 @@ 82.13 bool Type::interface_vs_oop(const Type *t) const { 82.14 bool result = false; 82.15 82.16 - const TypeInstPtr* this_inst = this->isa_instptr(); 82.17 - const TypeInstPtr* t_inst = t->isa_instptr(); 82.18 + const TypePtr* this_ptr = this->make_ptr(); // In case it is narrow_oop 82.19 + const TypePtr* t_ptr = t->make_ptr(); 82.20 + if( this_ptr == NULL || t_ptr == NULL ) 82.21 + return result; 82.22 + 82.23 + const TypeInstPtr* this_inst = this_ptr->isa_instptr(); 82.24 + const TypeInstPtr* t_inst = t_ptr->isa_instptr(); 82.25 if( this_inst && this_inst->is_loaded() && t_inst && t_inst->is_loaded() ) { 82.26 bool this_interface = this_inst->klass()->is_interface(); 82.27 bool t_interface = t_inst->klass()->is_interface(); 82.28 @@ -2249,7 +2254,7 @@ 82.29 const Type *TypeOopPtr::cast_to_ptr_type(PTR ptr) const { 82.30 assert(_base == OopPtr, "subclass must override cast_to_ptr_type"); 82.31 if( ptr == _ptr ) return this; 82.32 - return make(ptr, _offset); 82.33 + return make(ptr, _offset, _instance_id); 82.34 } 82.35 82.36 //-----------------------------cast_to_instance_id---------------------------- 82.37 @@ -2319,8 +2324,10 @@ 82.38 if (ptr == Null) return TypePtr::make(AnyPtr, ptr, offset); 82.39 // else fall through: 82.40 case TopPTR: 82.41 - case AnyNull: 82.42 - return make(ptr, offset); 82.43 + case AnyNull: { 82.44 + int instance_id = meet_instance_id(InstanceTop); 82.45 + return make(ptr, offset, instance_id); 82.46 + } 82.47 case BotPTR: 82.48 case NotNull: 82.49 return TypePtr::make(AnyPtr, ptr, offset); 82.50 @@ -2411,14 +2418,13 @@ 82.51 82.52 //------------------------------make_from_constant----------------------------- 82.53 // Make a java pointer from an oop constant 82.54 -const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o) { 82.55 +const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o, bool require_constant) { 82.56 if (o->is_method_data() || o->is_method()) { 82.57 // Treat much like a typeArray of bytes, like below, but fake the type... 82.58 - assert(o->has_encoding(), "must be a perm space object"); 82.59 const Type* etype = (Type*)get_const_basic_type(T_BYTE); 82.60 const TypeAry* arr0 = TypeAry::make(etype, TypeInt::POS); 82.61 ciKlass *klass = ciTypeArrayKlass::make((BasicType) T_BYTE); 82.62 - assert(o->has_encoding(), "method data oops should be tenured"); 82.63 + assert(o->can_be_constant(), "method data oops should be tenured"); 82.64 const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0); 82.65 return arr; 82.66 } else { 82.67 @@ -2427,8 +2433,9 @@ 82.68 ciKlass *klass = o->klass(); 82.69 if (klass->is_instance_klass()) { 82.70 // Element is an instance 82.71 - if (!o->has_encoding()) { // not a perm-space constant 82.72 - // %%% remove this restriction by rewriting non-perm ConPNodes in a later phase 82.73 + if (require_constant) { 82.74 + if (!o->can_be_constant()) return NULL; 82.75 + } else if (!o->should_be_constant()) { 82.76 return TypeInstPtr::make(TypePtr::NotNull, klass, true, NULL, 0); 82.77 } 82.78 return TypeInstPtr::make(o); 82.79 @@ -2440,8 +2447,9 @@ 82.80 // We used to pass NotNull in here, asserting that the sub-arrays 82.81 // are all not-null. This is not true in generally, as code can 82.82 // slam NULLs down in the subarrays. 82.83 - if (!o->has_encoding()) { // not a perm-space constant 82.84 - // %%% remove this restriction by rewriting non-perm ConPNodes in a later phase 82.85 + if (require_constant) { 82.86 + if (!o->can_be_constant()) return NULL; 82.87 + } else if (!o->should_be_constant()) { 82.88 return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0); 82.89 } 82.90 const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0); 82.91 @@ -2453,8 +2461,9 @@ 82.92 const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length())); 82.93 // We used to pass NotNull in here, asserting that the array pointer 82.94 // is not-null. That was not true in general. 82.95 - if (!o->has_encoding()) { // not a perm-space constant 82.96 - // %%% remove this restriction by rewriting non-perm ConPNodes in a later phase 82.97 + if (require_constant) { 82.98 + if (!o->can_be_constant()) return NULL; 82.99 + } else if (!o->should_be_constant()) { 82.100 return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0); 82.101 } 82.102 const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0); 82.103 @@ -2483,7 +2492,7 @@ 82.104 ShouldNotReachHere(); 82.105 } 82.106 82.107 - return (intptr_t)const_oop()->encoding(); 82.108 + return (intptr_t)const_oop()->constant_encoding(); 82.109 } 82.110 82.111 82.112 @@ -2591,7 +2600,7 @@ 82.113 82.114 //------------------------------add_offset------------------------------------- 82.115 const TypePtr *TypeOopPtr::add_offset( intptr_t offset ) const { 82.116 - return make( _ptr, xadd_offset(offset) ); 82.117 + return make( _ptr, xadd_offset(offset), _instance_id); 82.118 } 82.119 82.120 //------------------------------meet_instance_id-------------------------------- 82.121 @@ -2694,6 +2703,7 @@ 82.122 const TypeInstPtr *TypeInstPtr::xmeet_unloaded(const TypeInstPtr *tinst) const { 82.123 int off = meet_offset(tinst->offset()); 82.124 PTR ptr = meet_ptr(tinst->ptr()); 82.125 + int instance_id = meet_instance_id(tinst->instance_id()); 82.126 82.127 const TypeInstPtr *loaded = is_loaded() ? this : tinst; 82.128 const TypeInstPtr *unloaded = is_loaded() ? tinst : this; 82.129 @@ -2714,7 +2724,7 @@ 82.130 assert(loaded->ptr() != TypePtr::Null, "insanity check"); 82.131 // 82.132 if( loaded->ptr() == TypePtr::TopPTR ) { return unloaded; } 82.133 - else if (loaded->ptr() == TypePtr::AnyNull) { return TypeInstPtr::make( ptr, unloaded->klass() ); } 82.134 + else if (loaded->ptr() == TypePtr::AnyNull) { return TypeInstPtr::make( ptr, unloaded->klass(), false, NULL, off, instance_id ); } 82.135 else if (loaded->ptr() == TypePtr::BotPTR ) { return TypeInstPtr::BOTTOM; } 82.136 else if (loaded->ptr() == TypePtr::Constant || loaded->ptr() == TypePtr::NotNull) { 82.137 if (unloaded->ptr() == TypePtr::BotPTR ) { return TypeInstPtr::BOTTOM; } 82.138 @@ -3338,14 +3348,19 @@ 82.139 ciObject* o = const_oop(); 82.140 if( _ptr == Constant ) { 82.141 if( tap->const_oop() != NULL && !o->equals(tap->const_oop()) ) { 82.142 + xk = (klass() == tap->klass()); 82.143 ptr = NotNull; 82.144 o = NULL; 82.145 instance_id = InstanceBot; 82.146 + } else { 82.147 + xk = true; 82.148 } 82.149 } else if( above_centerline(_ptr) ) { 82.150 o = tap->const_oop(); 82.151 + xk = true; 82.152 + } else { 82.153 + xk = this->_klass_is_exact; 82.154 } 82.155 - xk = true; 82.156 return TypeAryPtr::make( ptr, o, tary, tap->_klass, xk, off, instance_id ); 82.157 } 82.158 case NotNull:
83.1 --- a/src/share/vm/opto/type.hpp Fri Oct 02 11:26:25 2009 -0700 83.2 +++ b/src/share/vm/opto/type.hpp Fri Oct 09 15:18:52 2009 -0700 83.3 @@ -711,10 +711,13 @@ 83.4 return make_from_klass_common(klass, false, false); 83.5 } 83.6 // Creates a singleton type given an object. 83.7 - static const TypeOopPtr* make_from_constant(ciObject* o); 83.8 + // If the object cannot be rendered as a constant, 83.9 + // may return a non-singleton type. 83.10 + // If require_constant, produce a NULL if a singleton is not possible. 83.11 + static const TypeOopPtr* make_from_constant(ciObject* o, bool require_constant = false); 83.12 83.13 // Make a generic (unclassed) pointer to an oop. 83.14 - static const TypeOopPtr* make(PTR ptr, int offset, int instance_id = InstanceBot); 83.15 + static const TypeOopPtr* make(PTR ptr, int offset, int instance_id); 83.16 83.17 ciObject* const_oop() const { return _const_oop; } 83.18 virtual ciKlass* klass() const { return _klass; }
84.1 --- a/src/share/vm/prims/jvmtiTagMap.cpp Fri Oct 02 11:26:25 2009 -0700 84.2 +++ b/src/share/vm/prims/jvmtiTagMap.cpp Fri Oct 09 15:18:52 2009 -0700 84.3 @@ -3126,6 +3126,12 @@ 84.4 // exceptions) will be visible. 84.5 blk.set_kind(JVMTI_HEAP_REFERENCE_OTHER); 84.6 Universe::oops_do(&blk); 84.7 + 84.8 + // If there are any non-perm roots in the code cache, visit them. 84.9 + blk.set_kind(JVMTI_HEAP_REFERENCE_OTHER); 84.10 + CodeBlobToOopClosure look_in_blobs(&blk, false); 84.11 + CodeCache::scavenge_root_nmethods_do(&look_in_blobs); 84.12 + 84.13 return true; 84.14 } 84.15
85.1 --- a/src/share/vm/runtime/arguments.cpp Fri Oct 02 11:26:25 2009 -0700 85.2 +++ b/src/share/vm/runtime/arguments.cpp Fri Oct 09 15:18:52 2009 -0700 85.3 @@ -2648,16 +2648,22 @@ 85.4 85.5 if (EnableInvokeDynamic && !EnableMethodHandles) { 85.6 if (!FLAG_IS_DEFAULT(EnableMethodHandles)) { 85.7 - warning("forcing EnableMethodHandles true to allow EnableInvokeDynamic"); 85.8 + warning("forcing EnableMethodHandles true because EnableInvokeDynamic is true"); 85.9 } 85.10 EnableMethodHandles = true; 85.11 } 85.12 if (EnableMethodHandles && !AnonymousClasses) { 85.13 if (!FLAG_IS_DEFAULT(AnonymousClasses)) { 85.14 - warning("forcing AnonymousClasses true to enable EnableMethodHandles"); 85.15 + warning("forcing AnonymousClasses true because EnableMethodHandles is true"); 85.16 } 85.17 AnonymousClasses = true; 85.18 } 85.19 + if ((EnableMethodHandles || AnonymousClasses) && ScavengeRootsInCode == 0) { 85.20 + if (!FLAG_IS_DEFAULT(ScavengeRootsInCode)) { 85.21 + warning("forcing ScavengeRootsInCode non-zero because EnableMethodHandles or AnonymousClasses is true"); 85.22 + } 85.23 + ScavengeRootsInCode = 1; 85.24 + } 85.25 85.26 if (PrintGCDetails) { 85.27 // Turn on -verbose:gc options as well
86.1 --- a/src/share/vm/runtime/frame.cpp Fri Oct 02 11:26:25 2009 -0700 86.2 +++ b/src/share/vm/runtime/frame.cpp Fri Oct 09 15:18:52 2009 -0700 86.3 @@ -1043,7 +1043,7 @@ 86.4 finder.oops_do(); 86.5 } 86.6 86.7 -void frame::oops_code_blob_do(OopClosure* f, const RegisterMap* reg_map) { 86.8 +void frame::oops_code_blob_do(OopClosure* f, CodeBlobClosure* cf, const RegisterMap* reg_map) { 86.9 assert(_cb != NULL, "sanity check"); 86.10 if (_cb->oop_maps() != NULL) { 86.11 OopMapSet::oops_do(this, reg_map, f); 86.12 @@ -1058,21 +1058,9 @@ 86.13 // oops referenced from nmethods active on thread stacks so as to 86.14 // prevent them from being collected. However, this visit should be 86.15 // restricted to certain phases of the collection only. The 86.16 - // closure answers whether it wants nmethods to be traced. 86.17 - // (All CodeBlob subtypes other than NMethod currently have 86.18 - // an empty oops_do() method. 86.19 - if (f->do_nmethods()) { 86.20 - _cb->oops_do(f); 86.21 - } 86.22 -} 86.23 - 86.24 -void frame::nmethods_code_blob_do() { 86.25 - assert(_cb != NULL, "sanity check"); 86.26 - 86.27 - // If we see an activation belonging to a non_entrant nmethod, we mark it. 86.28 - if (_cb->is_nmethod() && ((nmethod *)_cb)->is_not_entrant()) { 86.29 - ((nmethod*)_cb)->mark_as_seen_on_stack(); 86.30 - } 86.31 + // closure decides how it wants nmethods to be traced. 86.32 + if (cf != NULL) 86.33 + cf->do_code_blob(_cb); 86.34 } 86.35 86.36 class CompiledArgumentOopFinder: public SignatureInfo { 86.37 @@ -1201,18 +1189,18 @@ 86.38 } 86.39 86.40 86.41 -void frame::oops_do_internal(OopClosure* f, RegisterMap* map, bool use_interpreter_oop_map_cache) { 86.42 +void frame::oops_do_internal(OopClosure* f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache) { 86.43 if (is_interpreted_frame()) { oops_interpreted_do(f, map, use_interpreter_oop_map_cache); 86.44 } else if (is_entry_frame()) { oops_entry_do (f, map); 86.45 - } else if (CodeCache::contains(pc())) { oops_code_blob_do (f, map); 86.46 + } else if (CodeCache::contains(pc())) { oops_code_blob_do (f, cf, map); 86.47 } else { 86.48 ShouldNotReachHere(); 86.49 } 86.50 } 86.51 86.52 -void frame::nmethods_do() { 86.53 +void frame::nmethods_do(CodeBlobClosure* cf) { 86.54 if (_cb != NULL && _cb->is_nmethod()) { 86.55 - nmethods_code_blob_do(); 86.56 + cf->do_code_blob(_cb); 86.57 } 86.58 } 86.59 86.60 @@ -1358,7 +1346,7 @@ 86.61 } 86.62 } 86.63 COMPILER2_PRESENT(assert(DerivedPointerTable::is_empty(), "must be empty before verify");) 86.64 - oops_do_internal(&VerifyOopClosure::verify_oop, (RegisterMap*)map, false); 86.65 + oops_do_internal(&VerifyOopClosure::verify_oop, NULL, (RegisterMap*)map, false); 86.66 } 86.67 86.68
87.1 --- a/src/share/vm/runtime/frame.hpp Fri Oct 02 11:26:25 2009 -0700 87.2 +++ b/src/share/vm/runtime/frame.hpp Fri Oct 09 15:18:52 2009 -0700 87.3 @@ -384,16 +384,14 @@ 87.4 void oops_interpreted_arguments_do(symbolHandle signature, bool is_static, OopClosure* f); 87.5 87.6 // Iteration of oops 87.7 - void oops_do_internal(OopClosure* f, RegisterMap* map, bool use_interpreter_oop_map_cache); 87.8 + void oops_do_internal(OopClosure* f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache); 87.9 void oops_entry_do(OopClosure* f, const RegisterMap* map); 87.10 - void oops_code_blob_do(OopClosure* f, const RegisterMap* map); 87.11 + void oops_code_blob_do(OopClosure* f, CodeBlobClosure* cf, const RegisterMap* map); 87.12 int adjust_offset(methodOop method, int index); // helper for above fn 87.13 - // Iteration of nmethods 87.14 - void nmethods_code_blob_do(); 87.15 public: 87.16 // Memory management 87.17 - void oops_do(OopClosure* f, RegisterMap* map) { oops_do_internal(f, map, true); } 87.18 - void nmethods_do(); 87.19 + void oops_do(OopClosure* f, CodeBlobClosure* cf, RegisterMap* map) { oops_do_internal(f, cf, map, true); } 87.20 + void nmethods_do(CodeBlobClosure* cf); 87.21 87.22 void gc_prologue(); 87.23 void gc_epilogue();
88.1 --- a/src/share/vm/runtime/globals.hpp Fri Oct 02 11:26:25 2009 -0700 88.2 +++ b/src/share/vm/runtime/globals.hpp Fri Oct 09 15:18:52 2009 -0700 88.3 @@ -714,6 +714,11 @@ 88.4 diagnostic(bool, TraceNMethodInstalls, false, \ 88.5 "Trace nmethod intallation") \ 88.6 \ 88.7 + diagnostic(intx, ScavengeRootsInCode, 0, \ 88.8 + "0: do not allow scavengable oops in the code cache; " \ 88.9 + "1: allow scavenging from the code cache; " \ 88.10 + "2: emit as many constants as the compiler can see") \ 88.11 + \ 88.12 diagnostic(bool, TraceOSRBreakpoint, false, \ 88.13 "Trace OSR Breakpoint ") \ 88.14 \
89.1 --- a/src/share/vm/runtime/sweeper.cpp Fri Oct 02 11:26:25 2009 -0700 89.2 +++ b/src/share/vm/runtime/sweeper.cpp Fri Oct 09 15:18:52 2009 -0700 89.3 @@ -34,6 +34,17 @@ 89.4 jint NMethodSweeper::_not_entrant_seen_on_stack = 0; 89.5 bool NMethodSweeper::_rescan = false; 89.6 89.7 +class MarkActivationClosure: public CodeBlobClosure { 89.8 +public: 89.9 + virtual void do_code_blob(CodeBlob* cb) { 89.10 + // If we see an activation belonging to a non_entrant nmethod, we mark it. 89.11 + if (cb->is_nmethod() && ((nmethod*)cb)->is_not_entrant()) { 89.12 + ((nmethod*)cb)->mark_as_seen_on_stack(); 89.13 + } 89.14 + } 89.15 +}; 89.16 +static MarkActivationClosure mark_activation_closure; 89.17 + 89.18 void NMethodSweeper::sweep() { 89.19 assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint"); 89.20 if (!MethodFlushing) return; 89.21 @@ -57,7 +68,7 @@ 89.22 if (PrintMethodFlushing) { 89.23 tty->print_cr("### Sweep: stack traversal %d", _traversals); 89.24 } 89.25 - Threads::nmethods_do(); 89.26 + Threads::nmethods_do(&mark_activation_closure); 89.27 89.28 // reset the flags since we started a scan from the beginning. 89.29 _rescan = false;
90.1 --- a/src/share/vm/runtime/thread.cpp Fri Oct 02 11:26:25 2009 -0700 90.2 +++ b/src/share/vm/runtime/thread.cpp Fri Oct 09 15:18:52 2009 -0700 90.3 @@ -683,14 +683,15 @@ 90.4 return false; 90.5 } 90.6 90.7 -void Thread::oops_do(OopClosure* f) { 90.8 +void Thread::oops_do(OopClosure* f, CodeBlobClosure* cf) { 90.9 active_handles()->oops_do(f); 90.10 // Do oop for ThreadShadow 90.11 f->do_oop((oop*)&_pending_exception); 90.12 handle_area()->oops_do(f); 90.13 } 90.14 90.15 -void Thread::nmethods_do() { 90.16 +void Thread::nmethods_do(CodeBlobClosure* cf) { 90.17 + // no nmethods in a generic thread... 90.18 } 90.19 90.20 void Thread::print_on(outputStream* st) const { 90.21 @@ -2316,12 +2317,12 @@ 90.22 } 90.23 90.24 90.25 -void JavaThread::oops_do(OopClosure* f) { 90.26 +void JavaThread::oops_do(OopClosure* f, CodeBlobClosure* cf) { 90.27 // The ThreadProfiler oops_do is done from FlatProfiler::oops_do 90.28 // since there may be more than one thread using each ThreadProfiler. 90.29 90.30 // Traverse the GCHandles 90.31 - Thread::oops_do(f); 90.32 + Thread::oops_do(f, cf); 90.33 90.34 assert( (!has_last_Java_frame() && java_call_counter() == 0) || 90.35 (has_last_Java_frame() && java_call_counter() > 0), "wrong java_sp info!"); 90.36 @@ -2347,7 +2348,7 @@ 90.37 90.38 // Traverse the execution stack 90.39 for(StackFrameStream fst(this); !fst.is_done(); fst.next()) { 90.40 - fst.current()->oops_do(f, fst.register_map()); 90.41 + fst.current()->oops_do(f, cf, fst.register_map()); 90.42 } 90.43 } 90.44 90.45 @@ -2379,9 +2380,8 @@ 90.46 } 90.47 } 90.48 90.49 -void JavaThread::nmethods_do() { 90.50 - // Traverse the GCHandles 90.51 - Thread::nmethods_do(); 90.52 +void JavaThread::nmethods_do(CodeBlobClosure* cf) { 90.53 + Thread::nmethods_do(cf); // (super method is a no-op) 90.54 90.55 assert( (!has_last_Java_frame() && java_call_counter() == 0) || 90.56 (has_last_Java_frame() && java_call_counter() > 0), "wrong java_sp info!"); 90.57 @@ -2389,7 +2389,7 @@ 90.58 if (has_last_Java_frame()) { 90.59 // Traverse the execution stack 90.60 for(StackFrameStream fst(this); !fst.is_done(); fst.next()) { 90.61 - fst.current()->nmethods_do(); 90.62 + fst.current()->nmethods_do(cf); 90.63 } 90.64 } 90.65 } 90.66 @@ -2463,7 +2463,7 @@ 90.67 90.68 void JavaThread::verify() { 90.69 // Verify oops in the thread. 90.70 - oops_do(&VerifyOopClosure::verify_oop); 90.71 + oops_do(&VerifyOopClosure::verify_oop, NULL); 90.72 90.73 // Verify the stack frames. 90.74 frames_do(frame_verify); 90.75 @@ -3602,14 +3602,14 @@ 90.76 // uses the Threads_lock to gurantee this property. It also makes sure that 90.77 // all threads gets blocked when exiting or starting). 90.78 90.79 -void Threads::oops_do(OopClosure* f) { 90.80 +void Threads::oops_do(OopClosure* f, CodeBlobClosure* cf) { 90.81 ALL_JAVA_THREADS(p) { 90.82 - p->oops_do(f); 90.83 + p->oops_do(f, cf); 90.84 } 90.85 - VMThread::vm_thread()->oops_do(f); 90.86 + VMThread::vm_thread()->oops_do(f, cf); 90.87 } 90.88 90.89 -void Threads::possibly_parallel_oops_do(OopClosure* f) { 90.90 +void Threads::possibly_parallel_oops_do(OopClosure* f, CodeBlobClosure* cf) { 90.91 // Introduce a mechanism allowing parallel threads to claim threads as 90.92 // root groups. Overhead should be small enough to use all the time, 90.93 // even in sequential code. 90.94 @@ -3618,12 +3618,12 @@ 90.95 int cp = SharedHeap::heap()->strong_roots_parity(); 90.96 ALL_JAVA_THREADS(p) { 90.97 if (p->claim_oops_do(is_par, cp)) { 90.98 - p->oops_do(f); 90.99 + p->oops_do(f, cf); 90.100 } 90.101 } 90.102 VMThread* vmt = VMThread::vm_thread(); 90.103 if (vmt->claim_oops_do(is_par, cp)) 90.104 - vmt->oops_do(f); 90.105 + vmt->oops_do(f, cf); 90.106 } 90.107 90.108 #ifndef SERIALGC 90.109 @@ -3644,11 +3644,11 @@ 90.110 } 90.111 #endif // SERIALGC 90.112 90.113 -void Threads::nmethods_do() { 90.114 +void Threads::nmethods_do(CodeBlobClosure* cf) { 90.115 ALL_JAVA_THREADS(p) { 90.116 - p->nmethods_do(); 90.117 + p->nmethods_do(cf); 90.118 } 90.119 - VMThread::vm_thread()->nmethods_do(); 90.120 + VMThread::vm_thread()->nmethods_do(cf); 90.121 } 90.122 90.123 void Threads::gc_epilogue() {
91.1 --- a/src/share/vm/runtime/thread.hpp Fri Oct 02 11:26:25 2009 -0700 91.2 +++ b/src/share/vm/runtime/thread.hpp Fri Oct 09 15:18:52 2009 -0700 91.3 @@ -374,7 +374,8 @@ 91.4 91.5 // GC support 91.6 // Apply "f->do_oop" to all root oops in "this". 91.7 - void oops_do(OopClosure* f); 91.8 + // Apply "cf->do_code_blob" (if !NULL) to all code blobs active in frames 91.9 + void oops_do(OopClosure* f, CodeBlobClosure* cf); 91.10 91.11 // Handles the parallel case for the method below. 91.12 private: 91.13 @@ -398,7 +399,7 @@ 91.14 } 91.15 91.16 // Sweeper support 91.17 - void nmethods_do(); 91.18 + void nmethods_do(CodeBlobClosure* cf); 91.19 91.20 // Tells if adr belong to this thread. This is used 91.21 // for checking if a lock is owned by the running thread. 91.22 @@ -1229,10 +1230,10 @@ 91.23 void frames_do(void f(frame*, const RegisterMap*)); 91.24 91.25 // Memory operations 91.26 - void oops_do(OopClosure* f); 91.27 + void oops_do(OopClosure* f, CodeBlobClosure* cf); 91.28 91.29 // Sweeper operations 91.30 - void nmethods_do(); 91.31 + void nmethods_do(CodeBlobClosure* cf); 91.32 91.33 // Memory management operations 91.34 void gc_epilogue(); 91.35 @@ -1620,9 +1621,9 @@ 91.36 91.37 // Apply "f->do_oop" to all root oops in all threads. 91.38 // This version may only be called by sequential code. 91.39 - static void oops_do(OopClosure* f); 91.40 + static void oops_do(OopClosure* f, CodeBlobClosure* cf); 91.41 // This version may be called by sequential or parallel code. 91.42 - static void possibly_parallel_oops_do(OopClosure* f); 91.43 + static void possibly_parallel_oops_do(OopClosure* f, CodeBlobClosure* cf); 91.44 // This creates a list of GCTasks, one per thread. 91.45 static void create_thread_roots_tasks(GCTaskQueue* q); 91.46 // This creates a list of GCTasks, one per thread, for marking objects. 91.47 @@ -1630,13 +1631,13 @@ 91.48 91.49 // Apply "f->do_oop" to roots in all threads that 91.50 // are part of compiled frames 91.51 - static void compiled_frame_oops_do(OopClosure* f); 91.52 + static void compiled_frame_oops_do(OopClosure* f, CodeBlobClosure* cf); 91.53 91.54 static void convert_hcode_pointers(); 91.55 static void restore_hcode_pointers(); 91.56 91.57 // Sweeper 91.58 - static void nmethods_do(); 91.59 + static void nmethods_do(CodeBlobClosure* cf); 91.60 91.61 static void gc_epilogue(); 91.62 static void gc_prologue();
92.1 --- a/src/share/vm/runtime/vmStructs.cpp Fri Oct 02 11:26:25 2009 -0700 92.2 +++ b/src/share/vm/runtime/vmStructs.cpp Fri Oct 09 15:18:52 2009 -0700 92.3 @@ -549,6 +549,7 @@ 92.4 /********************************/ \ 92.5 \ 92.6 static_field(CodeCache, _heap, CodeHeap*) \ 92.7 + static_field(CodeCache, _scavenge_root_nmethods, nmethod*) \ 92.8 \ 92.9 /*******************************/ \ 92.10 /* CodeHeap (NOTE: incomplete) */ \ 92.11 @@ -618,7 +619,9 @@ 92.12 static_field(nmethod, _zombie_instruction_size, int) \ 92.13 nonstatic_field(nmethod, _method, methodOop) \ 92.14 nonstatic_field(nmethod, _entry_bci, int) \ 92.15 - nonstatic_field(nmethod, _link, nmethod*) \ 92.16 + nonstatic_field(nmethod, _osr_link, nmethod*) \ 92.17 + nonstatic_field(nmethod, _scavenge_root_link, nmethod*) \ 92.18 + nonstatic_field(nmethod, _scavenge_root_state, jbyte) \ 92.19 nonstatic_field(nmethod, _exception_offset, int) \ 92.20 nonstatic_field(nmethod, _deoptimize_offset, int) \ 92.21 nonstatic_field(nmethod, _orig_pc_offset, int) \
93.1 --- a/src/share/vm/runtime/vmThread.cpp Fri Oct 02 11:26:25 2009 -0700 93.2 +++ b/src/share/vm/runtime/vmThread.cpp Fri Oct 09 15:18:52 2009 -0700 93.3 @@ -619,8 +619,8 @@ 93.4 } 93.5 93.6 93.7 -void VMThread::oops_do(OopClosure* f) { 93.8 - Thread::oops_do(f); 93.9 +void VMThread::oops_do(OopClosure* f, CodeBlobClosure* cf) { 93.10 + Thread::oops_do(f, cf); 93.11 _vm_queue->oops_do(f); 93.12 } 93.13 93.14 @@ -652,5 +652,5 @@ 93.15 #endif 93.16 93.17 void VMThread::verify() { 93.18 - oops_do(&VerifyOopClosure::verify_oop); 93.19 + oops_do(&VerifyOopClosure::verify_oop, NULL); 93.20 }
94.1 --- a/src/share/vm/runtime/vmThread.hpp Fri Oct 02 11:26:25 2009 -0700 94.2 +++ b/src/share/vm/runtime/vmThread.hpp Fri Oct 09 15:18:52 2009 -0700 94.3 @@ -121,7 +121,7 @@ 94.4 static VMThread* vm_thread() { return _vm_thread; } 94.5 94.6 // GC support 94.7 - void oops_do(OopClosure* f); 94.8 + void oops_do(OopClosure* f, CodeBlobClosure* cf); 94.9 94.10 // Debugging 94.11 void print_on(outputStream* st) const;
95.1 --- a/src/share/vm/utilities/debug.cpp Fri Oct 02 11:26:25 2009 -0700 95.2 +++ b/src/share/vm/utilities/debug.cpp Fri Oct 09 15:18:52 2009 -0700 95.3 @@ -702,11 +702,14 @@ 95.4 tty->print_cr("Searching strong roots:"); 95.5 Universe::oops_do(&lookFor, false); 95.6 JNIHandles::oops_do(&lookFor); // Global (strong) JNI handles 95.7 - Threads::oops_do(&lookFor); 95.8 + Threads::oops_do(&lookFor, NULL); 95.9 ObjectSynchronizer::oops_do(&lookFor); 95.10 //FlatProfiler::oops_do(&lookFor); 95.11 SystemDictionary::oops_do(&lookFor); 95.12 95.13 + tty->print_cr("Searching code cache:"); 95.14 + CodeCache::oops_do(&lookFor); 95.15 + 95.16 tty->print_cr("Done."); 95.17 } 95.18
96.1 --- a/test/compiler/6823453/Test.java Fri Oct 02 11:26:25 2009 -0700 96.2 +++ b/test/compiler/6823453/Test.java Fri Oct 09 15:18:52 2009 -0700 96.3 @@ -26,7 +26,7 @@ 96.4 * @test 96.5 * @bug 6823453 96.6 * @summary DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph") 96.7 - * @run main/othervm -Xcomp -XX:CompileOnly=Test -XX:+DeoptimizeALot Test 96.8 + * @run main/othervm -Xcomp -XX:+IgnoreUnrecognizedVMOptions -XX:CompileOnly=Test -XX:+DeoptimizeALot Test 96.9 */ 96.10 96.11 public class Test {
97.1 --- a/test/compiler/6833129/Test.java Fri Oct 02 11:26:25 2009 -0700 97.2 +++ b/test/compiler/6833129/Test.java Fri Oct 09 15:18:52 2009 -0700 97.3 @@ -25,7 +25,7 @@ 97.4 * @test 97.5 * @bug 6833129 97.6 * @summary Object.clone() and Arrays.copyOf ignore coping with -XX:+DeoptimizeALot 97.7 - * @run main/othervm -Xbatch -XX:+DeoptimizeALot Test 97.8 + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+DeoptimizeALot Test 97.9 */ 97.10 97.11 public class Test{
98.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 98.2 +++ b/test/compiler/6875866/Test.java Fri Oct 09 15:18:52 2009 -0700 98.3 @@ -0,0 +1,46 @@ 98.4 +/* 98.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 98.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 98.7 + * 98.8 + * This code is free software; you can redistribute it and/or modify it 98.9 + * under the terms of the GNU General Public License version 2 only, as 98.10 + * published by the Free Software Foundation. 98.11 + * 98.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 98.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 98.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 98.15 + * version 2 for more details (a copy is included in the LICENSE file that 98.16 + * accompanied this code). 98.17 + * 98.18 + * You should have received a copy of the GNU General Public License version 98.19 + * 2 along with this work; if not, write to the Free Software Foundation, 98.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 98.21 + * 98.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 98.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 98.24 + * have any questions. 98.25 + */ 98.26 + 98.27 +/** 98.28 + * @test 98.29 + * @bug 6875866 98.30 + * @summary Intrinsic for String.indexOf() is broken on x86 with SSE4.2 98.31 + * 98.32 + * @run main/othervm -Xcomp Test 98.33 + */ 98.34 + 98.35 +public class Test { 98.36 + 98.37 + static int IndexOfTest(String str) { 98.38 + return str.indexOf("11111xx1x"); 98.39 + } 98.40 + 98.41 + public static void main(String args[]) { 98.42 + String str = "11111xx11111xx1x"; 98.43 + int idx = IndexOfTest(str); 98.44 + System.out.println("IndexOf = " + idx); 98.45 + if (idx != 7) { 98.46 + System.exit(97); 98.47 + } 98.48 + } 98.49 +}
99.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 99.2 +++ b/test/compiler/6877254/Test.java Fri Oct 09 15:18:52 2009 -0700 99.3 @@ -0,0 +1,51 @@ 99.4 +/* 99.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 99.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 99.7 + * 99.8 + * This code is free software; you can redistribute it and/or modify it 99.9 + * under the terms of the GNU General Public License version 2 only, as 99.10 + * published by the Free Software Foundation. 99.11 + * 99.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 99.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 99.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 99.15 + * version 2 for more details (a copy is included in the LICENSE file that 99.16 + * accompanied this code). 99.17 + * 99.18 + * You should have received a copy of the GNU General Public License version 99.19 + * 2 along with this work; if not, write to the Free Software Foundation, 99.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 99.21 + * 99.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 99.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 99.24 + * have any questions. 99.25 + */ 99.26 + 99.27 +/** 99.28 + * @test 99.29 + * @bug 6877254 99.30 + * @summary Implement StoreCMNode::Ideal to promote its OopStore above the MergeMem 99.31 + * 99.32 + * @run main/othervm -server -Xcomp -XX:+UseConcMarkSweepGC Test 99.33 + */ 99.34 + 99.35 +public class Test { 99.36 + static byte var_1; 99.37 + static String var_2 = ""; 99.38 + static byte var_3; 99.39 + static float var_4 = 0; 99.40 + 99.41 + public static void main(String[] args) { 99.42 + int i = 0; 99.43 + 99.44 + for (String var_tmp = var_2; i < 11; var_1 = 0, i++) { 99.45 + var_2 = var_2; 99.46 + var_4 *= (var_4 *= (var_3 = 0)); 99.47 + } 99.48 + 99.49 + System.out.println("var_1 = " + var_1); 99.50 + System.out.println("var_2 = " + var_2); 99.51 + System.out.println("var_3 = " + var_3); 99.52 + System.out.println("var_4 = " + var_4); 99.53 + } 99.54 +}