Thu, 27 Mar 2014 14:50:50 -0700
Merge
.hgtags | file | annotate | diff | comparison | revisions | |
make/hotspot_version | file | annotate | diff | comparison | revisions | |
src/share/vm/gc_implementation/g1/heapRegionSets.cpp | file | annotate | diff | comparison | revisions | |
src/share/vm/gc_implementation/g1/heapRegionSets.hpp | file | annotate | diff | comparison | revisions |
1.1 --- a/.hgtags Thu Mar 20 10:34:48 2014 -0700 1.2 +++ b/.hgtags Thu Mar 27 14:50:50 2014 -0700 1.3 @@ -449,3 +449,4 @@ 1.4 57eb3e69397e9d5818c5fdaef65b47d9b03f7f88 jdk8u20-b05 1.5 804f89b6ff46728d60a69e9a338e63f362f7ac68 hs25.20-b06 1.6 c3d92e04873788275eeebec6bcd2948cdbd143a7 jdk8u20-b06 1.7 +39eae002499704438142e78f5e0e24d46d0b266f hs25.20-b07
2.1 --- a/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java Thu Mar 20 10:34:48 2014 -0700 2.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java Thu Mar 27 14:50:50 2014 -0700 2.3 @@ -51,9 +51,9 @@ 2.4 static private CIntegerField summaryBytesUsedField; 2.5 // G1MonitoringSupport* _g1mm; 2.6 static private AddressField g1mmField; 2.7 - // MasterOldRegionSet _old_set; 2.8 + // HeapRegionSet _old_set; 2.9 static private long oldSetFieldOffset; 2.10 - // MasterHumongousRegionSet _humongous_set; 2.11 + // HeapRegionSet _humongous_set; 2.12 static private long humongousSetFieldOffset; 2.13 2.14 static {
3.1 --- a/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSetBase.java Thu Mar 20 10:34:48 2014 -0700 3.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSetBase.java Thu Mar 27 14:50:50 2014 -0700 3.3 @@ -40,12 +40,8 @@ 3.4 // Mirror class for HeapRegionSetBase. Represents a group of regions. 3.5 3.6 public class HeapRegionSetBase extends VMObject { 3.7 - // uint _length; 3.8 - static private CIntegerField lengthField; 3.9 - // uint _region_num; 3.10 - static private CIntegerField regionNumField; 3.11 - // size_t _total_used_bytes; 3.12 - static private CIntegerField totalUsedBytesField; 3.13 + 3.14 + static private long countField; 3.15 3.16 static { 3.17 VM.registerVMInitializedObserver(new Observer() { 3.18 @@ -58,21 +54,13 @@ 3.19 static private synchronized void initialize(TypeDataBase db) { 3.20 Type type = db.lookupType("HeapRegionSetBase"); 3.21 3.22 - lengthField = type.getCIntegerField("_length"); 3.23 - regionNumField = type.getCIntegerField("_region_num"); 3.24 - totalUsedBytesField = type.getCIntegerField("_total_used_bytes"); 3.25 + countField = type.getField("_count").getOffset(); 3.26 } 3.27 3.28 - public long length() { 3.29 - return lengthField.getValue(addr); 3.30 - } 3.31 3.32 - public long regionNum() { 3.33 - return regionNumField.getValue(addr); 3.34 - } 3.35 - 3.36 - public long totalUsedBytes() { 3.37 - return totalUsedBytesField.getValue(addr); 3.38 + public HeapRegionSetCount count() { 3.39 + Address countFieldAddr = addr.addOffsetTo(countField); 3.40 + return (HeapRegionSetCount) VMObjectFactory.newObject(HeapRegionSetCount.class, countFieldAddr); 3.41 } 3.42 3.43 public HeapRegionSetBase(Address addr) {
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSetCount.java Thu Mar 27 14:50:50 2014 -0700 4.3 @@ -0,0 +1,73 @@ 4.4 +/* 4.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 + * 4.8 + * This code is free software; you can redistribute it and/or modify it 4.9 + * under the terms of the GNU General Public License version 2 only, as 4.10 + * published by the Free Software Foundation. 4.11 + * 4.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.15 + * version 2 for more details (a copy is included in the LICENSE file that 4.16 + * accompanied this code). 4.17 + * 4.18 + * You should have received a copy of the GNU General Public License version 4.19 + * 2 along with this work; if not, write to the Free Software Foundation, 4.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.21 + * 4.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.23 + * or visit www.oracle.com if you need additional information or have any 4.24 + * questions. 4.25 + * 4.26 + */ 4.27 + 4.28 +package sun.jvm.hotspot.gc_implementation.g1; 4.29 + 4.30 +import java.util.Iterator; 4.31 +import java.util.Observable; 4.32 +import java.util.Observer; 4.33 + 4.34 +import sun.jvm.hotspot.debugger.Address; 4.35 +import sun.jvm.hotspot.runtime.VM; 4.36 +import sun.jvm.hotspot.runtime.VMObject; 4.37 +import sun.jvm.hotspot.runtime.VMObjectFactory; 4.38 +import sun.jvm.hotspot.types.AddressField; 4.39 +import sun.jvm.hotspot.types.CIntegerField; 4.40 +import sun.jvm.hotspot.types.Type; 4.41 +import sun.jvm.hotspot.types.TypeDataBase; 4.42 + 4.43 +// Mirror class for HeapRegionSetCount. Represents a group of regions. 4.44 + 4.45 +public class HeapRegionSetCount extends VMObject { 4.46 + 4.47 + static private CIntegerField lengthField; 4.48 + static private CIntegerField capacityField; 4.49 + 4.50 + static { 4.51 + VM.registerVMInitializedObserver(new Observer() { 4.52 + public void update(Observable o, Object data) { 4.53 + initialize(VM.getVM().getTypeDataBase()); 4.54 + } 4.55 + }); 4.56 + } 4.57 + 4.58 + static private synchronized void initialize(TypeDataBase db) { 4.59 + Type type = db.lookupType("HeapRegionSetCount"); 4.60 + 4.61 + lengthField = type.getCIntegerField("_length"); 4.62 + capacityField = type.getCIntegerField("_capacity"); 4.63 + } 4.64 + 4.65 + public long length() { 4.66 + return lengthField.getValue(addr); 4.67 + } 4.68 + 4.69 + public long capacity() { 4.70 + return capacityField.getValue(addr); 4.71 + } 4.72 + 4.73 + public HeapRegionSetCount(Address addr) { 4.74 + super(addr); 4.75 + } 4.76 +}
5.1 --- a/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java Thu Mar 20 10:34:48 2014 -0700 5.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java Thu Mar 27 14:50:50 2014 -0700 5.3 @@ -114,7 +114,8 @@ 5.4 long survivorRegionNum = g1mm.survivorRegionNum(); 5.5 HeapRegionSetBase oldSet = g1h.oldSet(); 5.6 HeapRegionSetBase humongousSet = g1h.humongousSet(); 5.7 - long oldRegionNum = oldSet.regionNum() + humongousSet.regionNum(); 5.8 + long oldRegionNum = oldSet.count().length() 5.9 + + humongousSet.count().capacity() / HeapRegion.grainBytes(); 5.10 printG1Space("G1 Heap:", g1h.n_regions(), 5.11 g1h.used(), g1h.capacity()); 5.12 System.out.println("G1 Young Generation:");
6.1 --- a/make/hotspot_version Thu Mar 20 10:34:48 2014 -0700 6.2 +++ b/make/hotspot_version Thu Mar 27 14:50:50 2014 -0700 6.3 @@ -35,7 +35,7 @@ 6.4 6.5 HS_MAJOR_VER=25 6.6 HS_MINOR_VER=20 6.7 -HS_BUILD_NUMBER=06 6.8 +HS_BUILD_NUMBER=07 6.9 6.10 JDK_MAJOR_VER=1 6.11 JDK_MINOR_VER=8
7.1 --- a/src/cpu/sparc/vm/sparc.ad Thu Mar 20 10:34:48 2014 -0700 7.2 +++ b/src/cpu/sparc/vm/sparc.ad Thu Mar 27 14:50:50 2014 -0700 7.3 @@ -2029,19 +2029,6 @@ 7.4 return L7_REGP_mask(); 7.5 } 7.6 7.7 -const RegMask Matcher::mathExactI_result_proj_mask() { 7.8 - return G1_REGI_mask(); 7.9 -} 7.10 - 7.11 -const RegMask Matcher::mathExactL_result_proj_mask() { 7.12 - return G1_REGL_mask(); 7.13 -} 7.14 - 7.15 -const RegMask Matcher::mathExactI_flags_proj_mask() { 7.16 - return INT_FLAGS_mask(); 7.17 -} 7.18 - 7.19 - 7.20 %} 7.21 7.22
8.1 --- a/src/cpu/x86/vm/assembler_x86.cpp Thu Mar 20 10:34:48 2014 -0700 8.2 +++ b/src/cpu/x86/vm/assembler_x86.cpp Thu Mar 27 14:50:50 2014 -0700 8.3 @@ -1089,6 +1089,21 @@ 8.4 emit_arith(0x23, 0xC0, dst, src); 8.5 } 8.6 8.7 +void Assembler::andnl(Register dst, Register src1, Register src2) { 8.8 + assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); 8.9 + int encode = vex_prefix_0F38_and_encode(dst, src1, src2); 8.10 + emit_int8((unsigned char)0xF2); 8.11 + emit_int8((unsigned char)(0xC0 | encode)); 8.12 +} 8.13 + 8.14 +void Assembler::andnl(Register dst, Register src1, Address src2) { 8.15 + InstructionMark im(this); 8.16 + assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); 8.17 + vex_prefix_0F38(dst, src1, src2); 8.18 + emit_int8((unsigned char)0xF2); 8.19 + emit_operand(dst, src2); 8.20 +} 8.21 + 8.22 void Assembler::bsfl(Register dst, Register src) { 8.23 int encode = prefix_and_encode(dst->encoding(), src->encoding()); 8.24 emit_int8(0x0F); 8.25 @@ -1110,6 +1125,51 @@ 8.26 emit_int8((unsigned char)(0xC8 | encode)); 8.27 } 8.28 8.29 +void Assembler::blsil(Register dst, Register src) { 8.30 + assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); 8.31 + int encode = vex_prefix_0F38_and_encode(rbx, dst, src); 8.32 + emit_int8((unsigned char)0xF3); 8.33 + emit_int8((unsigned char)(0xC0 | encode)); 8.34 +} 8.35 + 8.36 +void Assembler::blsil(Register dst, Address src) { 8.37 + InstructionMark im(this); 8.38 + assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); 8.39 + vex_prefix_0F38(rbx, dst, src); 8.40 + emit_int8((unsigned char)0xF3); 8.41 + emit_operand(rbx, src); 8.42 +} 8.43 + 8.44 +void Assembler::blsmskl(Register dst, Register src) { 8.45 + assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); 8.46 + int encode = vex_prefix_0F38_and_encode(rdx, dst, src); 8.47 + emit_int8((unsigned char)0xF3); 8.48 + emit_int8((unsigned char)(0xC0 | encode)); 8.49 +} 8.50 + 8.51 +void Assembler::blsmskl(Register dst, Address src) { 8.52 + InstructionMark im(this); 8.53 + assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); 8.54 + vex_prefix_0F38(rdx, dst, src); 8.55 + emit_int8((unsigned char)0xF3); 8.56 + emit_operand(rdx, src); 8.57 +} 8.58 + 8.59 +void Assembler::blsrl(Register dst, Register src) { 8.60 + assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); 8.61 + int encode = vex_prefix_0F38_and_encode(rcx, dst, src); 8.62 + emit_int8((unsigned char)0xF3); 8.63 + emit_int8((unsigned char)(0xC0 | encode)); 8.64 +} 8.65 + 8.66 +void Assembler::blsrl(Register dst, Address src) { 8.67 + InstructionMark im(this); 8.68 + assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); 8.69 + vex_prefix_0F38(rcx, dst, src); 8.70 + emit_int8((unsigned char)0xF3); 8.71 + emit_operand(rcx, src); 8.72 +} 8.73 + 8.74 void Assembler::call(Label& L, relocInfo::relocType rtype) { 8.75 // suspect disp32 is always good 8.76 int operand = LP64_ONLY(disp32_operand) NOT_LP64(imm_operand); 8.77 @@ -2878,6 +2938,24 @@ 8.78 emit_operand(dst, src); 8.79 } 8.80 8.81 +void Assembler::tzcntl(Register dst, Register src) { 8.82 + assert(VM_Version::supports_bmi1(), "tzcnt instruction not supported"); 8.83 + emit_int8((unsigned char)0xF3); 8.84 + int encode = prefix_and_encode(dst->encoding(), src->encoding()); 8.85 + emit_int8(0x0F); 8.86 + emit_int8((unsigned char)0xBC); 8.87 + emit_int8((unsigned char)0xC0 | encode); 8.88 +} 8.89 + 8.90 +void Assembler::tzcntq(Register dst, Register src) { 8.91 + assert(VM_Version::supports_bmi1(), "tzcnt instruction not supported"); 8.92 + emit_int8((unsigned char)0xF3); 8.93 + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); 8.94 + emit_int8(0x0F); 8.95 + emit_int8((unsigned char)0xBC); 8.96 + emit_int8((unsigned char)(0xC0 | encode)); 8.97 +} 8.98 + 8.99 void Assembler::ucomisd(XMMRegister dst, Address src) { 8.100 NOT_LP64(assert(VM_Version::supports_sse2(), "")); 8.101 emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_66); 8.102 @@ -4837,6 +4915,21 @@ 8.103 emit_arith(0x23, 0xC0, dst, src); 8.104 } 8.105 8.106 +void Assembler::andnq(Register dst, Register src1, Register src2) { 8.107 + assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); 8.108 + int encode = vex_prefix_0F38_and_encode_q(dst, src1, src2); 8.109 + emit_int8((unsigned char)0xF2); 8.110 + emit_int8((unsigned char)(0xC0 | encode)); 8.111 +} 8.112 + 8.113 +void Assembler::andnq(Register dst, Register src1, Address src2) { 8.114 + InstructionMark im(this); 8.115 + assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); 8.116 + vex_prefix_0F38_q(dst, src1, src2); 8.117 + emit_int8((unsigned char)0xF2); 8.118 + emit_operand(dst, src2); 8.119 +} 8.120 + 8.121 void Assembler::bsfq(Register dst, Register src) { 8.122 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); 8.123 emit_int8(0x0F); 8.124 @@ -4858,6 +4951,51 @@ 8.125 emit_int8((unsigned char)(0xC8 | encode)); 8.126 } 8.127 8.128 +void Assembler::blsiq(Register dst, Register src) { 8.129 + assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); 8.130 + int encode = vex_prefix_0F38_and_encode_q(rbx, dst, src); 8.131 + emit_int8((unsigned char)0xF3); 8.132 + emit_int8((unsigned char)(0xC0 | encode)); 8.133 +} 8.134 + 8.135 +void Assembler::blsiq(Register dst, Address src) { 8.136 + InstructionMark im(this); 8.137 + assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); 8.138 + vex_prefix_0F38_q(rbx, dst, src); 8.139 + emit_int8((unsigned char)0xF3); 8.140 + emit_operand(rbx, src); 8.141 +} 8.142 + 8.143 +void Assembler::blsmskq(Register dst, Register src) { 8.144 + assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); 8.145 + int encode = vex_prefix_0F38_and_encode_q(rdx, dst, src); 8.146 + emit_int8((unsigned char)0xF3); 8.147 + emit_int8((unsigned char)(0xC0 | encode)); 8.148 +} 8.149 + 8.150 +void Assembler::blsmskq(Register dst, Address src) { 8.151 + InstructionMark im(this); 8.152 + assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); 8.153 + vex_prefix_0F38_q(rdx, dst, src); 8.154 + emit_int8((unsigned char)0xF3); 8.155 + emit_operand(rdx, src); 8.156 +} 8.157 + 8.158 +void Assembler::blsrq(Register dst, Register src) { 8.159 + assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); 8.160 + int encode = vex_prefix_0F38_and_encode_q(rcx, dst, src); 8.161 + emit_int8((unsigned char)0xF3); 8.162 + emit_int8((unsigned char)(0xC0 | encode)); 8.163 +} 8.164 + 8.165 +void Assembler::blsrq(Register dst, Address src) { 8.166 + InstructionMark im(this); 8.167 + assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported"); 8.168 + vex_prefix_0F38_q(rcx, dst, src); 8.169 + emit_int8((unsigned char)0xF3); 8.170 + emit_operand(rcx, src); 8.171 +} 8.172 + 8.173 void Assembler::cdqq() { 8.174 prefix(REX_W); 8.175 emit_int8((unsigned char)0x99);
9.1 --- a/src/cpu/x86/vm/assembler_x86.hpp Thu Mar 20 10:34:48 2014 -0700 9.2 +++ b/src/cpu/x86/vm/assembler_x86.hpp Thu Mar 27 14:50:50 2014 -0700 9.3 @@ -590,10 +590,35 @@ 9.4 vex_prefix(src, nds_enc, dst_enc, pre, VEX_OPCODE_0F, false, vector256); 9.5 } 9.6 9.7 + void vex_prefix_0F38(Register dst, Register nds, Address src) { 9.8 + bool vex_w = false; 9.9 + bool vector256 = false; 9.10 + vex_prefix(src, nds->encoding(), dst->encoding(), 9.11 + VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector256); 9.12 + } 9.13 + 9.14 + void vex_prefix_0F38_q(Register dst, Register nds, Address src) { 9.15 + bool vex_w = true; 9.16 + bool vector256 = false; 9.17 + vex_prefix(src, nds->encoding(), dst->encoding(), 9.18 + VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector256); 9.19 + } 9.20 int vex_prefix_and_encode(int dst_enc, int nds_enc, int src_enc, 9.21 VexSimdPrefix pre, VexOpcode opc, 9.22 bool vex_w, bool vector256); 9.23 9.24 + int vex_prefix_0F38_and_encode(Register dst, Register nds, Register src) { 9.25 + bool vex_w = false; 9.26 + bool vector256 = false; 9.27 + return vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), 9.28 + VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector256); 9.29 + } 9.30 + int vex_prefix_0F38_and_encode_q(Register dst, Register nds, Register src) { 9.31 + bool vex_w = true; 9.32 + bool vector256 = false; 9.33 + return vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), 9.34 + VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector256); 9.35 + } 9.36 int vex_prefix_and_encode(XMMRegister dst, XMMRegister nds, XMMRegister src, 9.37 VexSimdPrefix pre, bool vector256 = false, 9.38 VexOpcode opc = VEX_OPCODE_0F) { 9.39 @@ -897,6 +922,27 @@ 9.40 void andq(Register dst, Address src); 9.41 void andq(Register dst, Register src); 9.42 9.43 + // BMI instructions 9.44 + void andnl(Register dst, Register src1, Register src2); 9.45 + void andnl(Register dst, Register src1, Address src2); 9.46 + void andnq(Register dst, Register src1, Register src2); 9.47 + void andnq(Register dst, Register src1, Address src2); 9.48 + 9.49 + void blsil(Register dst, Register src); 9.50 + void blsil(Register dst, Address src); 9.51 + void blsiq(Register dst, Register src); 9.52 + void blsiq(Register dst, Address src); 9.53 + 9.54 + void blsmskl(Register dst, Register src); 9.55 + void blsmskl(Register dst, Address src); 9.56 + void blsmskq(Register dst, Register src); 9.57 + void blsmskq(Register dst, Address src); 9.58 + 9.59 + void blsrl(Register dst, Register src); 9.60 + void blsrl(Register dst, Address src); 9.61 + void blsrq(Register dst, Register src); 9.62 + void blsrq(Register dst, Address src); 9.63 + 9.64 void bsfl(Register dst, Register src); 9.65 void bsrl(Register dst, Register src); 9.66 9.67 @@ -1574,6 +1620,9 @@ 9.68 void testq(Register dst, int32_t imm32); 9.69 void testq(Register dst, Register src); 9.70 9.71 + // BMI - count trailing zeros 9.72 + void tzcntl(Register dst, Register src); 9.73 + void tzcntq(Register dst, Register src); 9.74 9.75 // Unordered Compare Scalar Double-Precision Floating-Point Values and set EFLAGS 9.76 void ucomisd(XMMRegister dst, Address src);
10.1 --- a/src/cpu/x86/vm/globals_x86.hpp Thu Mar 20 10:34:48 2014 -0700 10.2 +++ b/src/cpu/x86/vm/globals_x86.hpp Thu Mar 27 14:50:50 2014 -0700 10.3 @@ -134,5 +134,11 @@ 10.4 \ 10.5 product(bool, UseCountLeadingZerosInstruction, false, \ 10.6 "Use count leading zeros instruction") \ 10.7 + \ 10.8 + product(bool, UseCountTrailingZerosInstruction, false, \ 10.9 + "Use count trailing zeros instruction") \ 10.10 + \ 10.11 + product(bool, UseBMI1Instructions, false, \ 10.12 + "Use BMI instructions") 10.13 10.14 #endif // CPU_X86_VM_GLOBALS_X86_HPP
11.1 --- a/src/cpu/x86/vm/vm_version_x86.cpp Thu Mar 20 10:34:48 2014 -0700 11.2 +++ b/src/cpu/x86/vm/vm_version_x86.cpp Thu Mar 27 14:50:50 2014 -0700 11.3 @@ -50,8 +50,13 @@ 11.4 const char* VM_Version::_features_str = ""; 11.5 VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, }; 11.6 11.7 +// Address of instruction which causes SEGV 11.8 +address VM_Version::_cpuinfo_segv_addr = 0; 11.9 +// Address of instruction after the one which causes SEGV 11.10 +address VM_Version::_cpuinfo_cont_addr = 0; 11.11 + 11.12 static BufferBlob* stub_blob; 11.13 -static const int stub_size = 550; 11.14 +static const int stub_size = 600; 11.15 11.16 extern "C" { 11.17 typedef void (*getPsrInfo_stub_t)(void*); 11.18 @@ -234,9 +239,9 @@ 11.19 // Check if OS has enabled XGETBV instruction to access XCR0 11.20 // (OSXSAVE feature flag) and CPU supports AVX 11.21 // 11.22 - __ andl(rcx, 0x18000000); 11.23 + __ andl(rcx, 0x18000000); // cpuid1 bits osxsave | avx 11.24 __ cmpl(rcx, 0x18000000); 11.25 - __ jccb(Assembler::notEqual, sef_cpuid); 11.26 + __ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported 11.27 11.28 // 11.29 // XCR0, XFEATURE_ENABLED_MASK register 11.30 @@ -247,6 +252,47 @@ 11.31 __ movl(Address(rsi, 0), rax); 11.32 __ movl(Address(rsi, 4), rdx); 11.33 11.34 + __ andl(rax, 0x6); // xcr0 bits sse | ymm 11.35 + __ cmpl(rax, 0x6); 11.36 + __ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported 11.37 + 11.38 + // 11.39 + // Some OSs have a bug when upper 128bits of YMM 11.40 + // registers are not restored after a signal processing. 11.41 + // Generate SEGV here (reference through NULL) 11.42 + // and check upper YMM bits after it. 11.43 + // 11.44 + VM_Version::set_avx_cpuFeatures(); // Enable temporary to pass asserts 11.45 + 11.46 + // load value into all 32 bytes of ymm7 register 11.47 + __ movl(rcx, VM_Version::ymm_test_value()); 11.48 + 11.49 + __ movdl(xmm0, rcx); 11.50 + __ pshufd(xmm0, xmm0, 0x00); 11.51 + __ vinsertf128h(xmm0, xmm0, xmm0); 11.52 + __ vmovdqu(xmm7, xmm0); 11.53 +#ifdef _LP64 11.54 + __ vmovdqu(xmm8, xmm0); 11.55 + __ vmovdqu(xmm15, xmm0); 11.56 +#endif 11.57 + 11.58 + __ xorl(rsi, rsi); 11.59 + VM_Version::set_cpuinfo_segv_addr( __ pc() ); 11.60 + // Generate SEGV 11.61 + __ movl(rax, Address(rsi, 0)); 11.62 + 11.63 + VM_Version::set_cpuinfo_cont_addr( __ pc() ); 11.64 + // Returns here after signal. Save xmm0 to check it later. 11.65 + __ lea(rsi, Address(rbp, in_bytes(VM_Version::ymm_save_offset()))); 11.66 + __ vmovdqu(Address(rsi, 0), xmm0); 11.67 + __ vmovdqu(Address(rsi, 32), xmm7); 11.68 +#ifdef _LP64 11.69 + __ vmovdqu(Address(rsi, 64), xmm8); 11.70 + __ vmovdqu(Address(rsi, 96), xmm15); 11.71 +#endif 11.72 + 11.73 + VM_Version::clean_cpuFeatures(); 11.74 + 11.75 // 11.76 // cpuid(0x7) Structured Extended Features 11.77 // 11.78 @@ -429,7 +475,7 @@ 11.79 } 11.80 11.81 char buf[256]; 11.82 - jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", 11.83 + jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", 11.84 cores_per_cpu(), threads_per_core(), 11.85 cpu_family(), _model, _stepping, 11.86 (supports_cmov() ? ", cmov" : ""), 11.87 @@ -455,7 +501,9 @@ 11.88 (supports_ht() ? ", ht": ""), 11.89 (supports_tsc() ? ", tsc": ""), 11.90 (supports_tscinv_bit() ? ", tscinvbit": ""), 11.91 - (supports_tscinv() ? ", tscinv": "")); 11.92 + (supports_tscinv() ? ", tscinv": ""), 11.93 + (supports_bmi1() ? ", bmi1" : ""), 11.94 + (supports_bmi2() ? ", bmi2" : "")); 11.95 _features_str = strdup(buf); 11.96 11.97 // UseSSE is set to the smaller of what hardware supports and what 11.98 @@ -538,14 +586,28 @@ 11.99 if (MaxVectorSize > 32) { 11.100 FLAG_SET_DEFAULT(MaxVectorSize, 32); 11.101 } 11.102 - if (MaxVectorSize > 16 && UseAVX == 0) { 11.103 - // Only supported with AVX+ 11.104 + if (MaxVectorSize > 16 && (UseAVX == 0 || !os_supports_avx_vectors())) { 11.105 + // 32 bytes vectors (in YMM) are only supported with AVX+ 11.106 FLAG_SET_DEFAULT(MaxVectorSize, 16); 11.107 } 11.108 if (UseSSE < 2) { 11.109 - // Only supported with SSE2+ 11.110 + // Vectors (in XMM) are only supported with SSE2+ 11.111 FLAG_SET_DEFAULT(MaxVectorSize, 0); 11.112 } 11.113 +#ifdef ASSERT 11.114 + if (supports_avx() && PrintMiscellaneous && Verbose && TraceNewVectors) { 11.115 + tty->print_cr("State of YMM registers after signal handle:"); 11.116 + int nreg = 2 LP64_ONLY(+2); 11.117 + const char* ymm_name[4] = {"0", "7", "8", "15"}; 11.118 + for (int i = 0; i < nreg; i++) { 11.119 + tty->print("YMM%s:", ymm_name[i]); 11.120 + for (int j = 7; j >=0; j--) { 11.121 + tty->print(" %x", _cpuid_info.ymm_save[i*8 + j]); 11.122 + } 11.123 + tty->cr(); 11.124 + } 11.125 + } 11.126 +#endif 11.127 } 11.128 #endif 11.129 11.130 @@ -600,13 +662,6 @@ 11.131 } 11.132 } 11.133 11.134 - // Use count leading zeros count instruction if available. 11.135 - if (supports_lzcnt()) { 11.136 - if (FLAG_IS_DEFAULT(UseCountLeadingZerosInstruction)) { 11.137 - UseCountLeadingZerosInstruction = true; 11.138 - } 11.139 - } 11.140 - 11.141 // some defaults for AMD family 15h 11.142 if ( cpu_family() == 0x15 ) { 11.143 // On family 15h processors default is no sw prefetch 11.144 @@ -683,14 +738,35 @@ 11.145 } 11.146 } 11.147 } 11.148 -#if defined(COMPILER2) && defined(_ALLBSD_SOURCE) 11.149 - if (MaxVectorSize > 16) { 11.150 - // Limit vectors size to 16 bytes on BSD until it fixes 11.151 - // restoring upper 128bit of YMM registers on return 11.152 - // from signal handler. 11.153 - FLAG_SET_DEFAULT(MaxVectorSize, 16); 11.154 + 11.155 + // Use count leading zeros count instruction if available. 11.156 + if (supports_lzcnt()) { 11.157 + if (FLAG_IS_DEFAULT(UseCountLeadingZerosInstruction)) { 11.158 + UseCountLeadingZerosInstruction = true; 11.159 } 11.160 -#endif // COMPILER2 11.161 + } else if (UseCountLeadingZerosInstruction) { 11.162 + warning("lzcnt instruction is not available on this CPU"); 11.163 + FLAG_SET_DEFAULT(UseCountLeadingZerosInstruction, false); 11.164 + } 11.165 + 11.166 + if (supports_bmi1()) { 11.167 + if (FLAG_IS_DEFAULT(UseBMI1Instructions)) { 11.168 + UseBMI1Instructions = true; 11.169 + } 11.170 + } else if (UseBMI1Instructions) { 11.171 + warning("BMI1 instructions are not available on this CPU"); 11.172 + FLAG_SET_DEFAULT(UseBMI1Instructions, false); 11.173 + } 11.174 + 11.175 + // Use count trailing zeros instruction if available 11.176 + if (supports_bmi1()) { 11.177 + if (FLAG_IS_DEFAULT(UseCountTrailingZerosInstruction)) { 11.178 + UseCountTrailingZerosInstruction = UseBMI1Instructions; 11.179 + } 11.180 + } else if (UseCountTrailingZerosInstruction) { 11.181 + warning("tzcnt instruction is not available on this CPU"); 11.182 + FLAG_SET_DEFAULT(UseCountTrailingZerosInstruction, false); 11.183 + } 11.184 11.185 // Use population count instruction if available. 11.186 if (supports_popcnt()) { 11.187 @@ -790,6 +866,11 @@ 11.188 if (UseAES) { 11.189 tty->print(" UseAES=1"); 11.190 } 11.191 +#ifdef COMPILER2 11.192 + if (MaxVectorSize > 0) { 11.193 + tty->print(" MaxVectorSize=%d", MaxVectorSize); 11.194 + } 11.195 +#endif 11.196 tty->cr(); 11.197 tty->print("Allocation"); 11.198 if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow_prefetch()) {
12.1 --- a/src/cpu/x86/vm/vm_version_x86.hpp Thu Mar 20 10:34:48 2014 -0700 12.2 +++ b/src/cpu/x86/vm/vm_version_x86.hpp Thu Mar 27 14:50:50 2014 -0700 12.3 @@ -141,7 +141,8 @@ 12.4 struct { 12.5 uint32_t LahfSahf : 1, 12.6 CmpLegacy : 1, 12.7 - : 4, 12.8 + : 3, 12.9 + lzcnt_intel : 1, 12.10 lzcnt : 1, 12.11 sse4a : 1, 12.12 misalignsse : 1, 12.13 @@ -228,6 +229,9 @@ 12.14 // 0 if this instruction is not available 12.15 static const char* _features_str; 12.16 12.17 + static address _cpuinfo_segv_addr; // address of instruction which causes SEGV 12.18 + static address _cpuinfo_cont_addr; // address of instruction after the one which causes SEGV 12.19 + 12.20 enum { 12.21 CPU_CX8 = (1 << 0), // next bits are from cpuid 1 (EDX) 12.22 CPU_CMOV = (1 << 1), 12.23 @@ -251,7 +255,9 @@ 12.24 CPU_AVX2 = (1 << 18), 12.25 CPU_AES = (1 << 19), 12.26 CPU_ERMS = (1 << 20), // enhanced 'rep movsb/stosb' instructions 12.27 - CPU_CLMUL = (1 << 21) // carryless multiply for CRC 12.28 + CPU_CLMUL = (1 << 21), // carryless multiply for CRC 12.29 + CPU_BMI1 = (1 << 22), 12.30 + CPU_BMI2 = (1 << 23) 12.31 } cpuFeatureFlags; 12.32 12.33 enum { 12.34 @@ -358,6 +364,9 @@ 12.35 // extended control register XCR0 (the XFEATURE_ENABLED_MASK register) 12.36 XemXcr0Eax xem_xcr0_eax; 12.37 uint32_t xem_xcr0_edx; // reserved 12.38 + 12.39 + // Space to save ymm registers after signal handle 12.40 + int ymm_save[8*4]; // Save ymm0, ymm7, ymm8, ymm15 12.41 }; 12.42 12.43 // The actual cpuid info block 12.44 @@ -423,6 +432,8 @@ 12.45 if (_cpuid_info.sef_cpuid7_ebx.bits.avx2 != 0) 12.46 result |= CPU_AVX2; 12.47 } 12.48 + if(_cpuid_info.sef_cpuid7_ebx.bits.bmi1 != 0) 12.49 + result |= CPU_BMI1; 12.50 if (_cpuid_info.std_cpuid1_edx.bits.tsc != 0) 12.51 result |= CPU_TSC; 12.52 if (_cpuid_info.ext_cpuid7_edx.bits.tsc_invariance != 0) 12.53 @@ -444,10 +455,32 @@ 12.54 if (_cpuid_info.ext_cpuid1_ecx.bits.sse4a != 0) 12.55 result |= CPU_SSE4A; 12.56 } 12.57 + // Intel features. 12.58 + if(is_intel()) { 12.59 + if(_cpuid_info.sef_cpuid7_ebx.bits.bmi2 != 0) 12.60 + result |= CPU_BMI2; 12.61 + if(_cpuid_info.ext_cpuid1_ecx.bits.lzcnt_intel != 0) 12.62 + result |= CPU_LZCNT; 12.63 + } 12.64 12.65 return result; 12.66 } 12.67 12.68 + static bool os_supports_avx_vectors() { 12.69 + if (!supports_avx()) { 12.70 + return false; 12.71 + } 12.72 + // Verify that OS save/restore all bits of AVX registers 12.73 + // during signal processing. 12.74 + int nreg = 2 LP64_ONLY(+2); 12.75 + for (int i = 0; i < 8 * nreg; i++) { // 32 bytes per ymm register 12.76 + if (_cpuid_info.ymm_save[i] != ymm_test_value()) { 12.77 + return false; 12.78 + } 12.79 + } 12.80 + return true; 12.81 + } 12.82 + 12.83 static void get_processor_features(); 12.84 12.85 public: 12.86 @@ -464,6 +497,19 @@ 12.87 static ByteSize tpl_cpuidB1_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB1_eax); } 12.88 static ByteSize tpl_cpuidB2_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB2_eax); } 12.89 static ByteSize xem_xcr0_offset() { return byte_offset_of(CpuidInfo, xem_xcr0_eax); } 12.90 + static ByteSize ymm_save_offset() { return byte_offset_of(CpuidInfo, ymm_save); } 12.91 + 12.92 + // The value used to check ymm register after signal handle 12.93 + static int ymm_test_value() { return 0xCAFEBABE; } 12.94 + 12.95 + static void set_cpuinfo_segv_addr(address pc) { _cpuinfo_segv_addr = pc; } 12.96 + static bool is_cpuinfo_segv_addr(address pc) { return _cpuinfo_segv_addr == pc; } 12.97 + static void set_cpuinfo_cont_addr(address pc) { _cpuinfo_cont_addr = pc; } 12.98 + static address cpuinfo_cont_addr() { return _cpuinfo_cont_addr; } 12.99 + 12.100 + static void clean_cpuFeatures() { _cpuFeatures = 0; } 12.101 + static void set_avx_cpuFeatures() { _cpuFeatures = (CPU_SSE | CPU_SSE2 | CPU_AVX); } 12.102 + 12.103 12.104 // Initialization 12.105 static void initialize(); 12.106 @@ -560,7 +606,8 @@ 12.107 static bool supports_aes() { return (_cpuFeatures & CPU_AES) != 0; } 12.108 static bool supports_erms() { return (_cpuFeatures & CPU_ERMS) != 0; } 12.109 static bool supports_clmul() { return (_cpuFeatures & CPU_CLMUL) != 0; } 12.110 - 12.111 + static bool supports_bmi1() { return (_cpuFeatures & CPU_BMI1) != 0; } 12.112 + static bool supports_bmi2() { return (_cpuFeatures & CPU_BMI2) != 0; } 12.113 // Intel features 12.114 static bool is_intel_family_core() { return is_intel() && 12.115 extended_cpu_family() == CPU_FAMILY_INTEL_CORE; }
13.1 --- a/src/cpu/x86/vm/x86_32.ad Thu Mar 20 10:34:48 2014 -0700 13.2 +++ b/src/cpu/x86/vm/x86_32.ad Thu Mar 27 14:50:50 2014 -0700 13.3 @@ -1534,19 +1534,6 @@ 13.4 return EBP_REG_mask(); 13.5 } 13.6 13.7 -const RegMask Matcher::mathExactI_result_proj_mask() { 13.8 - return EAX_REG_mask(); 13.9 -} 13.10 - 13.11 -const RegMask Matcher::mathExactL_result_proj_mask() { 13.12 - ShouldNotReachHere(); 13.13 - return RegMask(); 13.14 -} 13.15 - 13.16 -const RegMask Matcher::mathExactI_flags_proj_mask() { 13.17 - return INT_FLAGS_mask(); 13.18 -} 13.19 - 13.20 // Returns true if the high 32 bits of the value is known to be zero. 13.21 bool is_operand_hi32_zero(Node* n) { 13.22 int opc = n->Opcode(); 13.23 @@ -5168,6 +5155,19 @@ 13.24 %} 13.25 13.26 instruct countTrailingZerosI(rRegI dst, rRegI src, eFlagsReg cr) %{ 13.27 + predicate(UseCountTrailingZerosInstruction); 13.28 + match(Set dst (CountTrailingZerosI src)); 13.29 + effect(KILL cr); 13.30 + 13.31 + format %{ "TZCNT $dst, $src\t# count trailing zeros (int)" %} 13.32 + ins_encode %{ 13.33 + __ tzcntl($dst$$Register, $src$$Register); 13.34 + %} 13.35 + ins_pipe(ialu_reg); 13.36 +%} 13.37 + 13.38 +instruct countTrailingZerosI_bsf(rRegI dst, rRegI src, eFlagsReg cr) %{ 13.39 + predicate(!UseCountTrailingZerosInstruction); 13.40 match(Set dst (CountTrailingZerosI src)); 13.41 effect(KILL cr); 13.42 13.43 @@ -5187,6 +5187,30 @@ 13.44 %} 13.45 13.46 instruct countTrailingZerosL(rRegI dst, eRegL src, eFlagsReg cr) %{ 13.47 + predicate(UseCountTrailingZerosInstruction); 13.48 + match(Set dst (CountTrailingZerosL src)); 13.49 + effect(TEMP dst, KILL cr); 13.50 + 13.51 + format %{ "TZCNT $dst, $src.lo\t# count trailing zeros (long) \n\t" 13.52 + "JNC done\n\t" 13.53 + "TZCNT $dst, $src.hi\n\t" 13.54 + "ADD $dst, 32\n" 13.55 + "done:" %} 13.56 + ins_encode %{ 13.57 + Register Rdst = $dst$$Register; 13.58 + Register Rsrc = $src$$Register; 13.59 + Label done; 13.60 + __ tzcntl(Rdst, Rsrc); 13.61 + __ jccb(Assembler::carryClear, done); 13.62 + __ tzcntl(Rdst, HIGH_FROM_LOW(Rsrc)); 13.63 + __ addl(Rdst, BitsPerInt); 13.64 + __ bind(done); 13.65 + %} 13.66 + ins_pipe(ialu_reg); 13.67 +%} 13.68 + 13.69 +instruct countTrailingZerosL_bsf(rRegI dst, eRegL src, eFlagsReg cr) %{ 13.70 + predicate(!UseCountTrailingZerosInstruction); 13.71 match(Set dst (CountTrailingZerosL src)); 13.72 effect(TEMP dst, KILL cr); 13.73 13.74 @@ -6999,44 +7023,6 @@ 13.75 //----------Arithmetic Instructions-------------------------------------------- 13.76 //----------Addition Instructions---------------------------------------------- 13.77 13.78 -instruct addExactI_eReg(eAXRegI dst, rRegI src, eFlagsReg cr) 13.79 -%{ 13.80 - match(AddExactI dst src); 13.81 - effect(DEF cr); 13.82 - 13.83 - format %{ "ADD $dst, $src\t# addExact int" %} 13.84 - ins_encode %{ 13.85 - __ addl($dst$$Register, $src$$Register); 13.86 - %} 13.87 - ins_pipe(ialu_reg_reg); 13.88 -%} 13.89 - 13.90 -instruct addExactI_eReg_imm(eAXRegI dst, immI src, eFlagsReg cr) 13.91 -%{ 13.92 - match(AddExactI dst src); 13.93 - effect(DEF cr); 13.94 - 13.95 - format %{ "ADD $dst, $src\t# addExact int" %} 13.96 - ins_encode %{ 13.97 - __ addl($dst$$Register, $src$$constant); 13.98 - %} 13.99 - ins_pipe(ialu_reg_reg); 13.100 -%} 13.101 - 13.102 -instruct addExactI_eReg_mem(eAXRegI dst, memory src, eFlagsReg cr) 13.103 -%{ 13.104 - match(AddExactI dst (LoadI src)); 13.105 - effect(DEF cr); 13.106 - 13.107 - ins_cost(125); 13.108 - format %{ "ADD $dst,$src\t# addExact int" %} 13.109 - ins_encode %{ 13.110 - __ addl($dst$$Register, $src$$Address); 13.111 - %} 13.112 - ins_pipe( ialu_reg_mem ); 13.113 -%} 13.114 - 13.115 - 13.116 // Integer Addition Instructions 13.117 instruct addI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{ 13.118 match(Set dst (AddI dst src)); 13.119 @@ -7346,43 +7332,6 @@ 13.120 13.121 //----------Subtraction Instructions------------------------------------------- 13.122 13.123 -instruct subExactI_eReg(eAXRegI dst, rRegI src, eFlagsReg cr) 13.124 -%{ 13.125 - match(SubExactI dst src); 13.126 - effect(DEF cr); 13.127 - 13.128 - format %{ "SUB $dst, $src\t# subExact int" %} 13.129 - ins_encode %{ 13.130 - __ subl($dst$$Register, $src$$Register); 13.131 - %} 13.132 - ins_pipe(ialu_reg_reg); 13.133 -%} 13.134 - 13.135 -instruct subExactI_eReg_imm(eAXRegI dst, immI src, eFlagsReg cr) 13.136 -%{ 13.137 - match(SubExactI dst src); 13.138 - effect(DEF cr); 13.139 - 13.140 - format %{ "SUB $dst, $src\t# subExact int" %} 13.141 - ins_encode %{ 13.142 - __ subl($dst$$Register, $src$$constant); 13.143 - %} 13.144 - ins_pipe(ialu_reg_reg); 13.145 -%} 13.146 - 13.147 -instruct subExactI_eReg_mem(eAXRegI dst, memory src, eFlagsReg cr) 13.148 -%{ 13.149 - match(SubExactI dst (LoadI src)); 13.150 - effect(DEF cr); 13.151 - 13.152 - ins_cost(125); 13.153 - format %{ "SUB $dst,$src\t# subExact int" %} 13.154 - ins_encode %{ 13.155 - __ subl($dst$$Register, $src$$Address); 13.156 - %} 13.157 - ins_pipe( ialu_reg_mem ); 13.158 -%} 13.159 - 13.160 // Integer Subtraction Instructions 13.161 instruct subI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{ 13.162 match(Set dst (SubI dst src)); 13.163 @@ -7451,17 +7400,6 @@ 13.164 ins_pipe( ialu_reg ); 13.165 %} 13.166 13.167 -instruct negExactI_eReg(eAXRegI dst, eFlagsReg cr) %{ 13.168 - match(NegExactI dst); 13.169 - effect(DEF cr); 13.170 - 13.171 - format %{ "NEG $dst\t# negExact int"%} 13.172 - ins_encode %{ 13.173 - __ negl($dst$$Register); 13.174 - %} 13.175 - ins_pipe(ialu_reg); 13.176 -%} 13.177 - 13.178 //----------Multiplication/Division Instructions------------------------------- 13.179 // Integer Multiplication Instructions 13.180 // Multiply Register 13.181 @@ -7673,46 +7611,6 @@ 13.182 ins_pipe( pipe_slow ); 13.183 %} 13.184 13.185 -instruct mulExactI_eReg(eAXRegI dst, rRegI src, eFlagsReg cr) 13.186 -%{ 13.187 - match(MulExactI dst src); 13.188 - effect(DEF cr); 13.189 - 13.190 - ins_cost(300); 13.191 - format %{ "IMUL $dst, $src\t# mulExact int" %} 13.192 - ins_encode %{ 13.193 - __ imull($dst$$Register, $src$$Register); 13.194 - %} 13.195 - ins_pipe(ialu_reg_reg_alu0); 13.196 -%} 13.197 - 13.198 -instruct mulExactI_eReg_imm(eAXRegI dst, rRegI src, immI imm, eFlagsReg cr) 13.199 -%{ 13.200 - match(MulExactI src imm); 13.201 - effect(DEF cr); 13.202 - 13.203 - ins_cost(300); 13.204 - format %{ "IMUL $dst, $src, $imm\t# mulExact int" %} 13.205 - ins_encode %{ 13.206 - __ imull($dst$$Register, $src$$Register, $imm$$constant); 13.207 - %} 13.208 - ins_pipe(ialu_reg_reg_alu0); 13.209 -%} 13.210 - 13.211 -instruct mulExactI_eReg_mem(eAXRegI dst, memory src, eFlagsReg cr) 13.212 -%{ 13.213 - match(MulExactI dst (LoadI src)); 13.214 - effect(DEF cr); 13.215 - 13.216 - ins_cost(350); 13.217 - format %{ "IMUL $dst, $src\t# mulExact int" %} 13.218 - ins_encode %{ 13.219 - __ imull($dst$$Register, $src$$Address); 13.220 - %} 13.221 - ins_pipe(ialu_reg_mem_alu0); 13.222 -%} 13.223 - 13.224 - 13.225 // Integer DIV with Register 13.226 instruct divI_eReg(eAXRegI rax, eDXRegI rdx, eCXRegI div, eFlagsReg cr) %{ 13.227 match(Set rax (DivI rax div)); 13.228 @@ -8156,6 +8054,123 @@ 13.229 ins_pipe( ialu_mem_imm ); 13.230 %} 13.231 13.232 +// BMI1 instructions 13.233 +instruct andnI_rReg_rReg_rReg(rRegI dst, rRegI src1, rRegI src2, immI_M1 minus_1, eFlagsReg cr) %{ 13.234 + match(Set dst (AndI (XorI src1 minus_1) src2)); 13.235 + predicate(UseBMI1Instructions); 13.236 + effect(KILL cr); 13.237 + 13.238 + format %{ "ANDNL $dst, $src1, $src2" %} 13.239 + 13.240 + ins_encode %{ 13.241 + __ andnl($dst$$Register, $src1$$Register, $src2$$Register); 13.242 + %} 13.243 + ins_pipe(ialu_reg); 13.244 +%} 13.245 + 13.246 +instruct andnI_rReg_rReg_mem(rRegI dst, rRegI src1, memory src2, immI_M1 minus_1, eFlagsReg cr) %{ 13.247 + match(Set dst (AndI (XorI src1 minus_1) (LoadI src2) )); 13.248 + predicate(UseBMI1Instructions); 13.249 + effect(KILL cr); 13.250 + 13.251 + ins_cost(125); 13.252 + format %{ "ANDNL $dst, $src1, $src2" %} 13.253 + 13.254 + ins_encode %{ 13.255 + __ andnl($dst$$Register, $src1$$Register, $src2$$Address); 13.256 + %} 13.257 + ins_pipe(ialu_reg_mem); 13.258 +%} 13.259 + 13.260 +instruct blsiI_rReg_rReg(rRegI dst, rRegI src, immI0 imm_zero, eFlagsReg cr) %{ 13.261 + match(Set dst (AndI (SubI imm_zero src) src)); 13.262 + predicate(UseBMI1Instructions); 13.263 + effect(KILL cr); 13.264 + 13.265 + format %{ "BLSIL $dst, $src" %} 13.266 + 13.267 + ins_encode %{ 13.268 + __ blsil($dst$$Register, $src$$Register); 13.269 + %} 13.270 + ins_pipe(ialu_reg); 13.271 +%} 13.272 + 13.273 +instruct blsiI_rReg_mem(rRegI dst, memory src, immI0 imm_zero, eFlagsReg cr) %{ 13.274 + match(Set dst (AndI (SubI imm_zero (LoadI src) ) (LoadI src) )); 13.275 + predicate(UseBMI1Instructions); 13.276 + effect(KILL cr); 13.277 + 13.278 + ins_cost(125); 13.279 + format %{ "BLSIL $dst, $src" %} 13.280 + 13.281 + ins_encode %{ 13.282 + __ blsil($dst$$Register, $src$$Address); 13.283 + %} 13.284 + ins_pipe(ialu_reg_mem); 13.285 +%} 13.286 + 13.287 +instruct blsmskI_rReg_rReg(rRegI dst, rRegI src, immI_M1 minus_1, eFlagsReg cr) 13.288 +%{ 13.289 + match(Set dst (XorI (AddI src minus_1) src)); 13.290 + predicate(UseBMI1Instructions); 13.291 + effect(KILL cr); 13.292 + 13.293 + format %{ "BLSMSKL $dst, $src" %} 13.294 + 13.295 + ins_encode %{ 13.296 + __ blsmskl($dst$$Register, $src$$Register); 13.297 + %} 13.298 + 13.299 + ins_pipe(ialu_reg); 13.300 +%} 13.301 + 13.302 +instruct blsmskI_rReg_mem(rRegI dst, memory src, immI_M1 minus_1, eFlagsReg cr) 13.303 +%{ 13.304 + match(Set dst (XorI (AddI (LoadI src) minus_1) (LoadI src) )); 13.305 + predicate(UseBMI1Instructions); 13.306 + effect(KILL cr); 13.307 + 13.308 + ins_cost(125); 13.309 + format %{ "BLSMSKL $dst, $src" %} 13.310 + 13.311 + ins_encode %{ 13.312 + __ blsmskl($dst$$Register, $src$$Address); 13.313 + %} 13.314 + 13.315 + ins_pipe(ialu_reg_mem); 13.316 +%} 13.317 + 13.318 +instruct blsrI_rReg_rReg(rRegI dst, rRegI src, immI_M1 minus_1, eFlagsReg cr) 13.319 +%{ 13.320 + match(Set dst (AndI (AddI src minus_1) src) ); 13.321 + predicate(UseBMI1Instructions); 13.322 + effect(KILL cr); 13.323 + 13.324 + format %{ "BLSRL $dst, $src" %} 13.325 + 13.326 + ins_encode %{ 13.327 + __ blsrl($dst$$Register, $src$$Register); 13.328 + %} 13.329 + 13.330 + ins_pipe(ialu_reg); 13.331 +%} 13.332 + 13.333 +instruct blsrI_rReg_mem(rRegI dst, memory src, immI_M1 minus_1, eFlagsReg cr) 13.334 +%{ 13.335 + match(Set dst (AndI (AddI (LoadI src) minus_1) (LoadI src) )); 13.336 + predicate(UseBMI1Instructions); 13.337 + effect(KILL cr); 13.338 + 13.339 + ins_cost(125); 13.340 + format %{ "BLSRL $dst, $src" %} 13.341 + 13.342 + ins_encode %{ 13.343 + __ blsrl($dst$$Register, $src$$Address); 13.344 + %} 13.345 + 13.346 + ins_pipe(ialu_reg_mem); 13.347 +%} 13.348 + 13.349 // Or Instructions 13.350 // Or Register with Register 13.351 instruct orI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{ 13.352 @@ -8578,6 +8593,91 @@ 13.353 instruct cadd_cmpLTMask_mem(ncxRegI p, ncxRegI q, memory y, eCXRegI tmp, eFlagsReg cr) %{ 13.354 match(Set p (AddI (AndI (CmpLTMask p q) (LoadI y)) (SubI p q))); 13.355 */ 13.356 +//----------Overflow Math Instructions----------------------------------------- 13.357 + 13.358 +instruct overflowAddI_eReg(eFlagsReg cr, eAXRegI op1, rRegI op2) 13.359 +%{ 13.360 + match(Set cr (OverflowAddI op1 op2)); 13.361 + effect(DEF cr, USE_KILL op1, USE op2); 13.362 + 13.363 + format %{ "ADD $op1, $op2\t# overflow check int" %} 13.364 + 13.365 + ins_encode %{ 13.366 + __ addl($op1$$Register, $op2$$Register); 13.367 + %} 13.368 + ins_pipe(ialu_reg_reg); 13.369 +%} 13.370 + 13.371 +instruct overflowAddI_rReg_imm(eFlagsReg cr, eAXRegI op1, immI op2) 13.372 +%{ 13.373 + match(Set cr (OverflowAddI op1 op2)); 13.374 + effect(DEF cr, USE_KILL op1, USE op2); 13.375 + 13.376 + format %{ "ADD $op1, $op2\t# overflow check int" %} 13.377 + 13.378 + ins_encode %{ 13.379 + __ addl($op1$$Register, $op2$$constant); 13.380 + %} 13.381 + ins_pipe(ialu_reg_reg); 13.382 +%} 13.383 + 13.384 +instruct overflowSubI_rReg(eFlagsReg cr, rRegI op1, rRegI op2) 13.385 +%{ 13.386 + match(Set cr (OverflowSubI op1 op2)); 13.387 + 13.388 + format %{ "CMP $op1, $op2\t# overflow check int" %} 13.389 + ins_encode %{ 13.390 + __ cmpl($op1$$Register, $op2$$Register); 13.391 + %} 13.392 + ins_pipe(ialu_reg_reg); 13.393 +%} 13.394 + 13.395 +instruct overflowSubI_rReg_imm(eFlagsReg cr, rRegI op1, immI op2) 13.396 +%{ 13.397 + match(Set cr (OverflowSubI op1 op2)); 13.398 + 13.399 + format %{ "CMP $op1, $op2\t# overflow check int" %} 13.400 + ins_encode %{ 13.401 + __ cmpl($op1$$Register, $op2$$constant); 13.402 + %} 13.403 + ins_pipe(ialu_reg_reg); 13.404 +%} 13.405 + 13.406 +instruct overflowNegI_rReg(eFlagsReg cr, immI0 zero, eAXRegI op2) 13.407 +%{ 13.408 + match(Set cr (OverflowSubI zero op2)); 13.409 + effect(DEF cr, USE_KILL op2); 13.410 + 13.411 + format %{ "NEG $op2\t# overflow check int" %} 13.412 + ins_encode %{ 13.413 + __ negl($op2$$Register); 13.414 + %} 13.415 + ins_pipe(ialu_reg_reg); 13.416 +%} 13.417 + 13.418 +instruct overflowMulI_rReg(eFlagsReg cr, eAXRegI op1, rRegI op2) 13.419 +%{ 13.420 + match(Set cr (OverflowMulI op1 op2)); 13.421 + effect(DEF cr, USE_KILL op1, USE op2); 13.422 + 13.423 + format %{ "IMUL $op1, $op2\t# overflow check int" %} 13.424 + ins_encode %{ 13.425 + __ imull($op1$$Register, $op2$$Register); 13.426 + %} 13.427 + ins_pipe(ialu_reg_reg_alu0); 13.428 +%} 13.429 + 13.430 +instruct overflowMulI_rReg_imm(eFlagsReg cr, rRegI op1, immI op2, rRegI tmp) 13.431 +%{ 13.432 + match(Set cr (OverflowMulI op1 op2)); 13.433 + effect(DEF cr, TEMP tmp, USE op1, USE op2); 13.434 + 13.435 + format %{ "IMUL $tmp, $op1, $op2\t# overflow check int" %} 13.436 + ins_encode %{ 13.437 + __ imull($tmp$$Register, $op1$$Register, $op2$$constant); 13.438 + %} 13.439 + ins_pipe(ialu_reg_reg_alu0); 13.440 +%} 13.441 13.442 //----------Long Instructions------------------------------------------------ 13.443 // Add Long Register with Register 13.444 @@ -8693,6 +8793,210 @@ 13.445 ins_pipe( ialu_reg_long_mem ); 13.446 %} 13.447 13.448 +// BMI1 instructions 13.449 +instruct andnL_eReg_eReg_eReg(eRegL dst, eRegL src1, eRegL src2, immL_M1 minus_1, eFlagsReg cr) %{ 13.450 + match(Set dst (AndL (XorL src1 minus_1) src2)); 13.451 + predicate(UseBMI1Instructions); 13.452 + effect(KILL cr, TEMP dst); 13.453 + 13.454 + format %{ "ANDNL $dst.lo, $src1.lo, $src2.lo\n\t" 13.455 + "ANDNL $dst.hi, $src1.hi, $src2.hi" 13.456 + %} 13.457 + 13.458 + ins_encode %{ 13.459 + Register Rdst = $dst$$Register; 13.460 + Register Rsrc1 = $src1$$Register; 13.461 + Register Rsrc2 = $src2$$Register; 13.462 + __ andnl(Rdst, Rsrc1, Rsrc2); 13.463 + __ andnl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rsrc1), HIGH_FROM_LOW(Rsrc2)); 13.464 + %} 13.465 + ins_pipe(ialu_reg_reg_long); 13.466 +%} 13.467 + 13.468 +instruct andnL_eReg_eReg_mem(eRegL dst, eRegL src1, memory src2, immL_M1 minus_1, eFlagsReg cr) %{ 13.469 + match(Set dst (AndL (XorL src1 minus_1) (LoadL src2) )); 13.470 + predicate(UseBMI1Instructions); 13.471 + effect(KILL cr, TEMP dst); 13.472 + 13.473 + ins_cost(125); 13.474 + format %{ "ANDNL $dst.lo, $src1.lo, $src2\n\t" 13.475 + "ANDNL $dst.hi, $src1.hi, $src2+4" 13.476 + %} 13.477 + 13.478 + ins_encode %{ 13.479 + Register Rdst = $dst$$Register; 13.480 + Register Rsrc1 = $src1$$Register; 13.481 + Address src2_hi = Address::make_raw($src2$$base, $src2$$index, $src2$$scale, $src2$$disp + 4, relocInfo::none); 13.482 + 13.483 + __ andnl(Rdst, Rsrc1, $src2$$Address); 13.484 + __ andnl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rsrc1), src2_hi); 13.485 + %} 13.486 + ins_pipe(ialu_reg_mem); 13.487 +%} 13.488 + 13.489 +instruct blsiL_eReg_eReg(eRegL dst, eRegL src, immL0 imm_zero, eFlagsReg cr) %{ 13.490 + match(Set dst (AndL (SubL imm_zero src) src)); 13.491 + predicate(UseBMI1Instructions); 13.492 + effect(KILL cr, TEMP dst); 13.493 + 13.494 + format %{ "MOVL $dst.hi, 0\n\t" 13.495 + "BLSIL $dst.lo, $src.lo\n\t" 13.496 + "JNZ done\n\t" 13.497 + "BLSIL $dst.hi, $src.hi\n" 13.498 + "done:" 13.499 + %} 13.500 + 13.501 + ins_encode %{ 13.502 + Label done; 13.503 + Register Rdst = $dst$$Register; 13.504 + Register Rsrc = $src$$Register; 13.505 + __ movl(HIGH_FROM_LOW(Rdst), 0); 13.506 + __ blsil(Rdst, Rsrc); 13.507 + __ jccb(Assembler::notZero, done); 13.508 + __ blsil(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rsrc)); 13.509 + __ bind(done); 13.510 + %} 13.511 + ins_pipe(ialu_reg); 13.512 +%} 13.513 + 13.514 +instruct blsiL_eReg_mem(eRegL dst, memory src, immL0 imm_zero, eFlagsReg cr) %{ 13.515 + match(Set dst (AndL (SubL imm_zero (LoadL src) ) (LoadL src) )); 13.516 + predicate(UseBMI1Instructions); 13.517 + effect(KILL cr, TEMP dst); 13.518 + 13.519 + ins_cost(125); 13.520 + format %{ "MOVL $dst.hi, 0\n\t" 13.521 + "BLSIL $dst.lo, $src\n\t" 13.522 + "JNZ done\n\t" 13.523 + "BLSIL $dst.hi, $src+4\n" 13.524 + "done:" 13.525 + %} 13.526 + 13.527 + ins_encode %{ 13.528 + Label done; 13.529 + Register Rdst = $dst$$Register; 13.530 + Address src_hi = Address::make_raw($src$$base, $src$$index, $src$$scale, $src$$disp + 4, relocInfo::none); 13.531 + 13.532 + __ movl(HIGH_FROM_LOW(Rdst), 0); 13.533 + __ blsil(Rdst, $src$$Address); 13.534 + __ jccb(Assembler::notZero, done); 13.535 + __ blsil(HIGH_FROM_LOW(Rdst), src_hi); 13.536 + __ bind(done); 13.537 + %} 13.538 + ins_pipe(ialu_reg_mem); 13.539 +%} 13.540 + 13.541 +instruct blsmskL_eReg_eReg(eRegL dst, eRegL src, immL_M1 minus_1, eFlagsReg cr) 13.542 +%{ 13.543 + match(Set dst (XorL (AddL src minus_1) src)); 13.544 + predicate(UseBMI1Instructions); 13.545 + effect(KILL cr, TEMP dst); 13.546 + 13.547 + format %{ "MOVL $dst.hi, 0\n\t" 13.548 + "BLSMSKL $dst.lo, $src.lo\n\t" 13.549 + "JNC done\n\t" 13.550 + "BLSMSKL $dst.hi, $src.hi\n" 13.551 + "done:" 13.552 + %} 13.553 + 13.554 + ins_encode %{ 13.555 + Label done; 13.556 + Register Rdst = $dst$$Register; 13.557 + Register Rsrc = $src$$Register; 13.558 + __ movl(HIGH_FROM_LOW(Rdst), 0); 13.559 + __ blsmskl(Rdst, Rsrc); 13.560 + __ jccb(Assembler::carryClear, done); 13.561 + __ blsmskl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rsrc)); 13.562 + __ bind(done); 13.563 + %} 13.564 + 13.565 + ins_pipe(ialu_reg); 13.566 +%} 13.567 + 13.568 +instruct blsmskL_eReg_mem(eRegL dst, memory src, immL_M1 minus_1, eFlagsReg cr) 13.569 +%{ 13.570 + match(Set dst (XorL (AddL (LoadL src) minus_1) (LoadL src) )); 13.571 + predicate(UseBMI1Instructions); 13.572 + effect(KILL cr, TEMP dst); 13.573 + 13.574 + ins_cost(125); 13.575 + format %{ "MOVL $dst.hi, 0\n\t" 13.576 + "BLSMSKL $dst.lo, $src\n\t" 13.577 + "JNC done\n\t" 13.578 + "BLSMSKL $dst.hi, $src+4\n" 13.579 + "done:" 13.580 + %} 13.581 + 13.582 + ins_encode %{ 13.583 + Label done; 13.584 + Register Rdst = $dst$$Register; 13.585 + Address src_hi = Address::make_raw($src$$base, $src$$index, $src$$scale, $src$$disp + 4, relocInfo::none); 13.586 + 13.587 + __ movl(HIGH_FROM_LOW(Rdst), 0); 13.588 + __ blsmskl(Rdst, $src$$Address); 13.589 + __ jccb(Assembler::carryClear, done); 13.590 + __ blsmskl(HIGH_FROM_LOW(Rdst), src_hi); 13.591 + __ bind(done); 13.592 + %} 13.593 + 13.594 + ins_pipe(ialu_reg_mem); 13.595 +%} 13.596 + 13.597 +instruct blsrL_eReg_eReg(eRegL dst, eRegL src, immL_M1 minus_1, eFlagsReg cr) 13.598 +%{ 13.599 + match(Set dst (AndL (AddL src minus_1) src) ); 13.600 + predicate(UseBMI1Instructions); 13.601 + effect(KILL cr, TEMP dst); 13.602 + 13.603 + format %{ "MOVL $dst.hi, $src.hi\n\t" 13.604 + "BLSRL $dst.lo, $src.lo\n\t" 13.605 + "JNC done\n\t" 13.606 + "BLSRL $dst.hi, $src.hi\n" 13.607 + "done:" 13.608 + %} 13.609 + 13.610 + ins_encode %{ 13.611 + Label done; 13.612 + Register Rdst = $dst$$Register; 13.613 + Register Rsrc = $src$$Register; 13.614 + __ movl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rsrc)); 13.615 + __ blsrl(Rdst, Rsrc); 13.616 + __ jccb(Assembler::carryClear, done); 13.617 + __ blsrl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rsrc)); 13.618 + __ bind(done); 13.619 + %} 13.620 + 13.621 + ins_pipe(ialu_reg); 13.622 +%} 13.623 + 13.624 +instruct blsrL_eReg_mem(eRegL dst, memory src, immL_M1 minus_1, eFlagsReg cr) 13.625 +%{ 13.626 + match(Set dst (AndL (AddL (LoadL src) minus_1) (LoadL src) )); 13.627 + predicate(UseBMI1Instructions); 13.628 + effect(KILL cr, TEMP dst); 13.629 + 13.630 + ins_cost(125); 13.631 + format %{ "MOVL $dst.hi, $src+4\n\t" 13.632 + "BLSRL $dst.lo, $src\n\t" 13.633 + "JNC done\n\t" 13.634 + "BLSRL $dst.hi, $src+4\n" 13.635 + "done:" 13.636 + %} 13.637 + 13.638 + ins_encode %{ 13.639 + Label done; 13.640 + Register Rdst = $dst$$Register; 13.641 + Address src_hi = Address::make_raw($src$$base, $src$$index, $src$$scale, $src$$disp + 4, relocInfo::none); 13.642 + __ movl(HIGH_FROM_LOW(Rdst), src_hi); 13.643 + __ blsrl(Rdst, $src$$Address); 13.644 + __ jccb(Assembler::carryClear, done); 13.645 + __ blsrl(HIGH_FROM_LOW(Rdst), src_hi); 13.646 + __ bind(done); 13.647 + %} 13.648 + 13.649 + ins_pipe(ialu_reg_mem); 13.650 +%} 13.651 + 13.652 // Or Long Register with Register 13.653 instruct orl_eReg(eRegL dst, eRegL src, eFlagsReg cr) %{ 13.654 match(Set dst (OrL dst src));
14.1 --- a/src/cpu/x86/vm/x86_64.ad Thu Mar 20 10:34:48 2014 -0700 14.2 +++ b/src/cpu/x86/vm/x86_64.ad Thu Mar 27 14:50:50 2014 -0700 14.3 @@ -1649,18 +1649,6 @@ 14.4 return PTR_RBP_REG_mask(); 14.5 } 14.6 14.7 -const RegMask Matcher::mathExactI_result_proj_mask() { 14.8 - return INT_RAX_REG_mask(); 14.9 -} 14.10 - 14.11 -const RegMask Matcher::mathExactL_result_proj_mask() { 14.12 - return LONG_RAX_REG_mask(); 14.13 -} 14.14 - 14.15 -const RegMask Matcher::mathExactI_flags_proj_mask() { 14.16 - return INT_FLAGS_mask(); 14.17 -} 14.18 - 14.19 %} 14.20 14.21 //----------ENCODING BLOCK----------------------------------------------------- 14.22 @@ -6026,6 +6014,19 @@ 14.23 %} 14.24 14.25 instruct countTrailingZerosI(rRegI dst, rRegI src, rFlagsReg cr) %{ 14.26 + predicate(UseCountTrailingZerosInstruction); 14.27 + match(Set dst (CountTrailingZerosI src)); 14.28 + effect(KILL cr); 14.29 + 14.30 + format %{ "tzcntl $dst, $src\t# count trailing zeros (int)" %} 14.31 + ins_encode %{ 14.32 + __ tzcntl($dst$$Register, $src$$Register); 14.33 + %} 14.34 + ins_pipe(ialu_reg); 14.35 +%} 14.36 + 14.37 +instruct countTrailingZerosI_bsf(rRegI dst, rRegI src, rFlagsReg cr) %{ 14.38 + predicate(!UseCountTrailingZerosInstruction); 14.39 match(Set dst (CountTrailingZerosI src)); 14.40 effect(KILL cr); 14.41 14.42 @@ -6045,6 +6046,19 @@ 14.43 %} 14.44 14.45 instruct countTrailingZerosL(rRegI dst, rRegL src, rFlagsReg cr) %{ 14.46 + predicate(UseCountTrailingZerosInstruction); 14.47 + match(Set dst (CountTrailingZerosL src)); 14.48 + effect(KILL cr); 14.49 + 14.50 + format %{ "tzcntq $dst, $src\t# count trailing zeros (long)" %} 14.51 + ins_encode %{ 14.52 + __ tzcntq($dst$$Register, $src$$Register); 14.53 + %} 14.54 + ins_pipe(ialu_reg); 14.55 +%} 14.56 + 14.57 +instruct countTrailingZerosL_bsf(rRegI dst, rRegL src, rFlagsReg cr) %{ 14.58 + predicate(!UseCountTrailingZerosInstruction); 14.59 match(Set dst (CountTrailingZerosL src)); 14.60 effect(KILL cr); 14.61 14.62 @@ -6728,82 +6742,6 @@ 14.63 //----------Arithmetic Instructions-------------------------------------------- 14.64 //----------Addition Instructions---------------------------------------------- 14.65 14.66 -instruct addExactI_rReg(rax_RegI dst, rRegI src, rFlagsReg cr) 14.67 -%{ 14.68 - match(AddExactI dst src); 14.69 - effect(DEF cr); 14.70 - 14.71 - format %{ "addl $dst, $src\t# addExact int" %} 14.72 - ins_encode %{ 14.73 - __ addl($dst$$Register, $src$$Register); 14.74 - %} 14.75 - ins_pipe(ialu_reg_reg); 14.76 -%} 14.77 - 14.78 -instruct addExactI_rReg_imm(rax_RegI dst, immI src, rFlagsReg cr) 14.79 -%{ 14.80 - match(AddExactI dst src); 14.81 - effect(DEF cr); 14.82 - 14.83 - format %{ "addl $dst, $src\t# addExact int" %} 14.84 - ins_encode %{ 14.85 - __ addl($dst$$Register, $src$$constant); 14.86 - %} 14.87 - ins_pipe(ialu_reg_reg); 14.88 -%} 14.89 - 14.90 -instruct addExactI_rReg_mem(rax_RegI dst, memory src, rFlagsReg cr) 14.91 -%{ 14.92 - match(AddExactI dst (LoadI src)); 14.93 - effect(DEF cr); 14.94 - 14.95 - ins_cost(125); // XXX 14.96 - format %{ "addl $dst, $src\t# addExact int" %} 14.97 - ins_encode %{ 14.98 - __ addl($dst$$Register, $src$$Address); 14.99 - %} 14.100 - 14.101 - ins_pipe(ialu_reg_mem); 14.102 -%} 14.103 - 14.104 -instruct addExactL_rReg(rax_RegL dst, rRegL src, rFlagsReg cr) 14.105 -%{ 14.106 - match(AddExactL dst src); 14.107 - effect(DEF cr); 14.108 - 14.109 - format %{ "addq $dst, $src\t# addExact long" %} 14.110 - ins_encode %{ 14.111 - __ addq($dst$$Register, $src$$Register); 14.112 - %} 14.113 - ins_pipe(ialu_reg_reg); 14.114 -%} 14.115 - 14.116 -instruct addExactL_rReg_imm(rax_RegL dst, immL32 src, rFlagsReg cr) 14.117 -%{ 14.118 - match(AddExactL dst src); 14.119 - effect(DEF cr); 14.120 - 14.121 - format %{ "addq $dst, $src\t# addExact long" %} 14.122 - ins_encode %{ 14.123 - __ addq($dst$$Register, $src$$constant); 14.124 - %} 14.125 - ins_pipe(ialu_reg_reg); 14.126 -%} 14.127 - 14.128 -instruct addExactL_rReg_mem(rax_RegL dst, memory src, rFlagsReg cr) 14.129 -%{ 14.130 - match(AddExactL dst (LoadL src)); 14.131 - effect(DEF cr); 14.132 - 14.133 - ins_cost(125); // XXX 14.134 - format %{ "addq $dst, $src\t# addExact long" %} 14.135 - ins_encode %{ 14.136 - __ addq($dst$$Register, $src$$Address); 14.137 - %} 14.138 - 14.139 - ins_pipe(ialu_reg_mem); 14.140 -%} 14.141 - 14.142 instruct addI_rReg(rRegI dst, rRegI src, rFlagsReg cr) 14.143 %{ 14.144 match(Set dst (AddI dst src)); 14.145 @@ -7416,80 +7354,6 @@ 14.146 ins_pipe(ialu_mem_imm); 14.147 %} 14.148 14.149 -instruct subExactI_rReg(rax_RegI dst, rRegI src, rFlagsReg cr) 14.150 -%{ 14.151 - match(SubExactI dst src); 14.152 - effect(DEF cr); 14.153 - 14.154 - format %{ "subl $dst, $src\t# subExact int" %} 14.155 - ins_encode %{ 14.156 - __ subl($dst$$Register, $src$$Register); 14.157 - %} 14.158 - ins_pipe(ialu_reg_reg); 14.159 -%} 14.160 - 14.161 -instruct subExactI_rReg_imm(rax_RegI dst, immI src, rFlagsReg cr) 14.162 -%{ 14.163 - match(SubExactI dst src); 14.164 - effect(DEF cr); 14.165 - 14.166 - format %{ "subl $dst, $src\t# subExact int" %} 14.167 - ins_encode %{ 14.168 - __ subl($dst$$Register, $src$$constant); 14.169 - %} 14.170 - ins_pipe(ialu_reg_reg); 14.171 -%} 14.172 - 14.173 -instruct subExactI_rReg_mem(rax_RegI dst, memory src, rFlagsReg cr) 14.174 -%{ 14.175 - match(SubExactI dst (LoadI src)); 14.176 - effect(DEF cr); 14.177 - 14.178 - ins_cost(125); 14.179 - format %{ "subl $dst, $src\t# subExact int" %} 14.180 - ins_encode %{ 14.181 - __ subl($dst$$Register, $src$$Address); 14.182 - %} 14.183 - ins_pipe(ialu_reg_mem); 14.184 -%} 14.185 - 14.186 -instruct subExactL_rReg(rax_RegL dst, rRegL src, rFlagsReg cr) 14.187 -%{ 14.188 - match(SubExactL dst src); 14.189 - effect(DEF cr); 14.190 - 14.191 - format %{ "subq $dst, $src\t# subExact long" %} 14.192 - ins_encode %{ 14.193 - __ subq($dst$$Register, $src$$Register); 14.194 - %} 14.195 - ins_pipe(ialu_reg_reg); 14.196 -%} 14.197 - 14.198 -instruct subExactL_rReg_imm(rax_RegL dst, immL32 src, rFlagsReg cr) 14.199 -%{ 14.200 - match(SubExactL dst (LoadL src)); 14.201 - effect(DEF cr); 14.202 - 14.203 - format %{ "subq $dst, $src\t# subExact long" %} 14.204 - ins_encode %{ 14.205 - __ subq($dst$$Register, $src$$constant); 14.206 - %} 14.207 - ins_pipe(ialu_reg_reg); 14.208 -%} 14.209 - 14.210 -instruct subExactL_rReg_mem(rax_RegI dst, memory src, rFlagsReg cr) 14.211 -%{ 14.212 - match(SubExactI dst src); 14.213 - effect(DEF cr); 14.214 - 14.215 - ins_cost(125); 14.216 - format %{ "subq $dst, $src\t# subExact long" %} 14.217 - ins_encode %{ 14.218 - __ subq($dst$$Register, $src$$Address); 14.219 - %} 14.220 - ins_pipe(ialu_reg_mem); 14.221 -%} 14.222 - 14.223 instruct subL_rReg(rRegL dst, rRegL src, rFlagsReg cr) 14.224 %{ 14.225 match(Set dst (SubL dst src)); 14.226 @@ -7606,31 +7470,6 @@ 14.227 ins_pipe(ialu_reg); 14.228 %} 14.229 14.230 -instruct negExactI_rReg(rax_RegI dst, rFlagsReg cr) 14.231 -%{ 14.232 - match(NegExactI dst); 14.233 - effect(KILL cr); 14.234 - 14.235 - format %{ "negl $dst\t# negExact int" %} 14.236 - ins_encode %{ 14.237 - __ negl($dst$$Register); 14.238 - %} 14.239 - ins_pipe(ialu_reg); 14.240 -%} 14.241 - 14.242 -instruct negExactL_rReg(rax_RegL dst, rFlagsReg cr) 14.243 -%{ 14.244 - match(NegExactL dst); 14.245 - effect(KILL cr); 14.246 - 14.247 - format %{ "negq $dst\t# negExact long" %} 14.248 - ins_encode %{ 14.249 - __ negq($dst$$Register); 14.250 - %} 14.251 - ins_pipe(ialu_reg); 14.252 -%} 14.253 - 14.254 - 14.255 //----------Multiplication/Division Instructions------------------------------- 14.256 // Integer Multiplication Instructions 14.257 // Multiply Register 14.258 @@ -7747,86 +7586,6 @@ 14.259 ins_pipe(ialu_reg_reg_alu0); 14.260 %} 14.261 14.262 - 14.263 -instruct mulExactI_rReg(rax_RegI dst, rRegI src, rFlagsReg cr) 14.264 -%{ 14.265 - match(MulExactI dst src); 14.266 - effect(DEF cr); 14.267 - 14.268 - ins_cost(300); 14.269 - format %{ "imull $dst, $src\t# mulExact int" %} 14.270 - ins_encode %{ 14.271 - __ imull($dst$$Register, $src$$Register); 14.272 - %} 14.273 - ins_pipe(ialu_reg_reg_alu0); 14.274 -%} 14.275 - 14.276 - 14.277 -instruct mulExactI_rReg_imm(rax_RegI dst, rRegI src, immI imm, rFlagsReg cr) 14.278 -%{ 14.279 - match(MulExactI src imm); 14.280 - effect(DEF cr); 14.281 - 14.282 - ins_cost(300); 14.283 - format %{ "imull $dst, $src, $imm\t# mulExact int" %} 14.284 - ins_encode %{ 14.285 - __ imull($dst$$Register, $src$$Register, $imm$$constant); 14.286 - %} 14.287 - ins_pipe(ialu_reg_reg_alu0); 14.288 -%} 14.289 - 14.290 -instruct mulExactI_rReg_mem(rax_RegI dst, memory src, rFlagsReg cr) 14.291 -%{ 14.292 - match(MulExactI dst (LoadI src)); 14.293 - effect(DEF cr); 14.294 - 14.295 - ins_cost(350); 14.296 - format %{ "imull $dst, $src\t# mulExact int" %} 14.297 - ins_encode %{ 14.298 - __ imull($dst$$Register, $src$$Address); 14.299 - %} 14.300 - ins_pipe(ialu_reg_mem_alu0); 14.301 -%} 14.302 - 14.303 -instruct mulExactL_rReg(rax_RegL dst, rRegL src, rFlagsReg cr) 14.304 -%{ 14.305 - match(MulExactL dst src); 14.306 - effect(DEF cr); 14.307 - 14.308 - ins_cost(300); 14.309 - format %{ "imulq $dst, $src\t# mulExact long" %} 14.310 - ins_encode %{ 14.311 - __ imulq($dst$$Register, $src$$Register); 14.312 - %} 14.313 - ins_pipe(ialu_reg_reg_alu0); 14.314 -%} 14.315 - 14.316 -instruct mulExactL_rReg_imm(rax_RegL dst, rRegL src, immL32 imm, rFlagsReg cr) 14.317 -%{ 14.318 - match(MulExactL src imm); 14.319 - effect(DEF cr); 14.320 - 14.321 - ins_cost(300); 14.322 - format %{ "imulq $dst, $src, $imm\t# mulExact long" %} 14.323 - ins_encode %{ 14.324 - __ imulq($dst$$Register, $src$$Register, $imm$$constant); 14.325 - %} 14.326 - ins_pipe(ialu_reg_reg_alu0); 14.327 -%} 14.328 - 14.329 -instruct mulExactL_rReg_mem(rax_RegL dst, memory src, rFlagsReg cr) 14.330 -%{ 14.331 - match(MulExactL dst (LoadL src)); 14.332 - effect(DEF cr); 14.333 - 14.334 - ins_cost(350); 14.335 - format %{ "imulq $dst, $src\t# mulExact long" %} 14.336 - ins_encode %{ 14.337 - __ imulq($dst$$Register, $src$$Address); 14.338 - %} 14.339 - ins_pipe(ialu_reg_mem_alu0); 14.340 -%} 14.341 - 14.342 instruct divI_rReg(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div, 14.343 rFlagsReg cr) 14.344 %{ 14.345 @@ -8879,6 +8638,122 @@ 14.346 ins_pipe(ialu_mem_imm); 14.347 %} 14.348 14.349 +// BMI1 instructions 14.350 +instruct andnI_rReg_rReg_mem(rRegI dst, rRegI src1, memory src2, immI_M1 minus_1, rFlagsReg cr) %{ 14.351 + match(Set dst (AndI (XorI src1 minus_1) (LoadI src2))); 14.352 + predicate(UseBMI1Instructions); 14.353 + effect(KILL cr); 14.354 + 14.355 + ins_cost(125); 14.356 + format %{ "andnl $dst, $src1, $src2" %} 14.357 + 14.358 + ins_encode %{ 14.359 + __ andnl($dst$$Register, $src1$$Register, $src2$$Address); 14.360 + %} 14.361 + ins_pipe(ialu_reg_mem); 14.362 +%} 14.363 + 14.364 +instruct andnI_rReg_rReg_rReg(rRegI dst, rRegI src1, rRegI src2, immI_M1 minus_1, rFlagsReg cr) %{ 14.365 + match(Set dst (AndI (XorI src1 minus_1) src2)); 14.366 + predicate(UseBMI1Instructions); 14.367 + effect(KILL cr); 14.368 + 14.369 + format %{ "andnl $dst, $src1, $src2" %} 14.370 + 14.371 + ins_encode %{ 14.372 + __ andnl($dst$$Register, $src1$$Register, $src2$$Register); 14.373 + %} 14.374 + ins_pipe(ialu_reg); 14.375 +%} 14.376 + 14.377 +instruct blsiI_rReg_rReg(rRegI dst, rRegI src, immI0 imm_zero, rFlagsReg cr) %{ 14.378 + match(Set dst (AndI (SubI imm_zero src) src)); 14.379 + predicate(UseBMI1Instructions); 14.380 + effect(KILL cr); 14.381 + 14.382 + format %{ "blsil $dst, $src" %} 14.383 + 14.384 + ins_encode %{ 14.385 + __ blsil($dst$$Register, $src$$Register); 14.386 + %} 14.387 + ins_pipe(ialu_reg); 14.388 +%} 14.389 + 14.390 +instruct blsiI_rReg_mem(rRegI dst, memory src, immI0 imm_zero, rFlagsReg cr) %{ 14.391 + match(Set dst (AndI (SubI imm_zero (LoadI src) ) (LoadI src) )); 14.392 + predicate(UseBMI1Instructions); 14.393 + effect(KILL cr); 14.394 + 14.395 + ins_cost(125); 14.396 + format %{ "blsil $dst, $src" %} 14.397 + 14.398 + ins_encode %{ 14.399 + __ blsil($dst$$Register, $src$$Address); 14.400 + %} 14.401 + ins_pipe(ialu_reg_mem); 14.402 +%} 14.403 + 14.404 +instruct blsmskI_rReg_mem(rRegI dst, memory src, immI_M1 minus_1, rFlagsReg cr) 14.405 +%{ 14.406 + match(Set dst (XorI (AddI (LoadI src) minus_1) (LoadI src) ) ); 14.407 + predicate(UseBMI1Instructions); 14.408 + effect(KILL cr); 14.409 + 14.410 + ins_cost(125); 14.411 + format %{ "blsmskl $dst, $src" %} 14.412 + 14.413 + ins_encode %{ 14.414 + __ blsmskl($dst$$Register, $src$$Address); 14.415 + %} 14.416 + ins_pipe(ialu_reg_mem); 14.417 +%} 14.418 + 14.419 +instruct blsmskI_rReg_rReg(rRegI dst, rRegI src, immI_M1 minus_1, rFlagsReg cr) 14.420 +%{ 14.421 + match(Set dst (XorI (AddI src minus_1) src)); 14.422 + predicate(UseBMI1Instructions); 14.423 + effect(KILL cr); 14.424 + 14.425 + format %{ "blsmskl $dst, $src" %} 14.426 + 14.427 + ins_encode %{ 14.428 + __ blsmskl($dst$$Register, $src$$Register); 14.429 + %} 14.430 + 14.431 + ins_pipe(ialu_reg); 14.432 +%} 14.433 + 14.434 +instruct blsrI_rReg_rReg(rRegI dst, rRegI src, immI_M1 minus_1, rFlagsReg cr) 14.435 +%{ 14.436 + match(Set dst (AndI (AddI src minus_1) src) ); 14.437 + predicate(UseBMI1Instructions); 14.438 + effect(KILL cr); 14.439 + 14.440 + format %{ "blsrl $dst, $src" %} 14.441 + 14.442 + ins_encode %{ 14.443 + __ blsrl($dst$$Register, $src$$Register); 14.444 + %} 14.445 + 14.446 + ins_pipe(ialu_reg_mem); 14.447 +%} 14.448 + 14.449 +instruct blsrI_rReg_mem(rRegI dst, memory src, immI_M1 minus_1, rFlagsReg cr) 14.450 +%{ 14.451 + match(Set dst (AndI (AddI (LoadI src) minus_1) (LoadI src) ) ); 14.452 + predicate(UseBMI1Instructions); 14.453 + effect(KILL cr); 14.454 + 14.455 + ins_cost(125); 14.456 + format %{ "blsrl $dst, $src" %} 14.457 + 14.458 + ins_encode %{ 14.459 + __ blsrl($dst$$Register, $src$$Address); 14.460 + %} 14.461 + 14.462 + ins_pipe(ialu_reg); 14.463 +%} 14.464 + 14.465 // Or Instructions 14.466 // Or Register with Register 14.467 instruct orI_rReg(rRegI dst, rRegI src, rFlagsReg cr) 14.468 @@ -9110,6 +8985,122 @@ 14.469 ins_pipe(ialu_mem_imm); 14.470 %} 14.471 14.472 +// BMI1 instructions 14.473 +instruct andnL_rReg_rReg_mem(rRegL dst, rRegL src1, memory src2, immL_M1 minus_1, rFlagsReg cr) %{ 14.474 + match(Set dst (AndL (XorL src1 minus_1) (LoadL src2))); 14.475 + predicate(UseBMI1Instructions); 14.476 + effect(KILL cr); 14.477 + 14.478 + ins_cost(125); 14.479 + format %{ "andnq $dst, $src1, $src2" %} 14.480 + 14.481 + ins_encode %{ 14.482 + __ andnq($dst$$Register, $src1$$Register, $src2$$Address); 14.483 + %} 14.484 + ins_pipe(ialu_reg_mem); 14.485 +%} 14.486 + 14.487 +instruct andnL_rReg_rReg_rReg(rRegL dst, rRegL src1, rRegL src2, immL_M1 minus_1, rFlagsReg cr) %{ 14.488 + match(Set dst (AndL (XorL src1 minus_1) src2)); 14.489 + predicate(UseBMI1Instructions); 14.490 + effect(KILL cr); 14.491 + 14.492 + format %{ "andnq $dst, $src1, $src2" %} 14.493 + 14.494 + ins_encode %{ 14.495 + __ andnq($dst$$Register, $src1$$Register, $src2$$Register); 14.496 + %} 14.497 + ins_pipe(ialu_reg_mem); 14.498 +%} 14.499 + 14.500 +instruct blsiL_rReg_rReg(rRegL dst, rRegL src, immL0 imm_zero, rFlagsReg cr) %{ 14.501 + match(Set dst (AndL (SubL imm_zero src) src)); 14.502 + predicate(UseBMI1Instructions); 14.503 + effect(KILL cr); 14.504 + 14.505 + format %{ "blsiq $dst, $src" %} 14.506 + 14.507 + ins_encode %{ 14.508 + __ blsiq($dst$$Register, $src$$Register); 14.509 + %} 14.510 + ins_pipe(ialu_reg); 14.511 +%} 14.512 + 14.513 +instruct blsiL_rReg_mem(rRegL dst, memory src, immL0 imm_zero, rFlagsReg cr) %{ 14.514 + match(Set dst (AndL (SubL imm_zero (LoadL src) ) (LoadL src) )); 14.515 + predicate(UseBMI1Instructions); 14.516 + effect(KILL cr); 14.517 + 14.518 + ins_cost(125); 14.519 + format %{ "blsiq $dst, $src" %} 14.520 + 14.521 + ins_encode %{ 14.522 + __ blsiq($dst$$Register, $src$$Address); 14.523 + %} 14.524 + ins_pipe(ialu_reg_mem); 14.525 +%} 14.526 + 14.527 +instruct blsmskL_rReg_mem(rRegL dst, memory src, immL_M1 minus_1, rFlagsReg cr) 14.528 +%{ 14.529 + match(Set dst (XorL (AddL (LoadL src) minus_1) (LoadL src) ) ); 14.530 + predicate(UseBMI1Instructions); 14.531 + effect(KILL cr); 14.532 + 14.533 + ins_cost(125); 14.534 + format %{ "blsmskq $dst, $src" %} 14.535 + 14.536 + ins_encode %{ 14.537 + __ blsmskq($dst$$Register, $src$$Address); 14.538 + %} 14.539 + ins_pipe(ialu_reg_mem); 14.540 +%} 14.541 + 14.542 +instruct blsmskL_rReg_rReg(rRegL dst, rRegL src, immL_M1 minus_1, rFlagsReg cr) 14.543 +%{ 14.544 + match(Set dst (XorL (AddL src minus_1) src)); 14.545 + predicate(UseBMI1Instructions); 14.546 + effect(KILL cr); 14.547 + 14.548 + format %{ "blsmskq $dst, $src" %} 14.549 + 14.550 + ins_encode %{ 14.551 + __ blsmskq($dst$$Register, $src$$Register); 14.552 + %} 14.553 + 14.554 + ins_pipe(ialu_reg); 14.555 +%} 14.556 + 14.557 +instruct blsrL_rReg_rReg(rRegL dst, rRegL src, immL_M1 minus_1, rFlagsReg cr) 14.558 +%{ 14.559 + match(Set dst (AndL (AddL src minus_1) src) ); 14.560 + predicate(UseBMI1Instructions); 14.561 + effect(KILL cr); 14.562 + 14.563 + format %{ "blsrq $dst, $src" %} 14.564 + 14.565 + ins_encode %{ 14.566 + __ blsrq($dst$$Register, $src$$Register); 14.567 + %} 14.568 + 14.569 + ins_pipe(ialu_reg); 14.570 +%} 14.571 + 14.572 +instruct blsrL_rReg_mem(rRegL dst, memory src, immL_M1 minus_1, rFlagsReg cr) 14.573 +%{ 14.574 + match(Set dst (AndL (AddL (LoadL src) minus_1) (LoadL src)) ); 14.575 + predicate(UseBMI1Instructions); 14.576 + effect(KILL cr); 14.577 + 14.578 + ins_cost(125); 14.579 + format %{ "blsrq $dst, $src" %} 14.580 + 14.581 + ins_encode %{ 14.582 + __ blsrq($dst$$Register, $src$$Address); 14.583 + %} 14.584 + 14.585 + ins_pipe(ialu_reg); 14.586 +%} 14.587 + 14.588 // Or Instructions 14.589 // Or Register with Register 14.590 instruct orL_rReg(rRegL dst, rRegL src, rFlagsReg cr) 14.591 @@ -10435,6 +10426,174 @@ 14.592 ins_pipe( pipe_slow ); 14.593 %} 14.594 14.595 +//----------Overflow Math Instructions----------------------------------------- 14.596 + 14.597 +instruct overflowAddI_rReg(rFlagsReg cr, rax_RegI op1, rRegI op2) 14.598 +%{ 14.599 + match(Set cr (OverflowAddI op1 op2)); 14.600 + effect(DEF cr, USE_KILL op1, USE op2); 14.601 + 14.602 + format %{ "addl $op1, $op2\t# overflow check int" %} 14.603 + 14.604 + ins_encode %{ 14.605 + __ addl($op1$$Register, $op2$$Register); 14.606 + %} 14.607 + ins_pipe(ialu_reg_reg); 14.608 +%} 14.609 + 14.610 +instruct overflowAddI_rReg_imm(rFlagsReg cr, rax_RegI op1, immI op2) 14.611 +%{ 14.612 + match(Set cr (OverflowAddI op1 op2)); 14.613 + effect(DEF cr, USE_KILL op1, USE op2); 14.614 + 14.615 + format %{ "addl $op1, $op2\t# overflow check int" %} 14.616 + 14.617 + ins_encode %{ 14.618 + __ addl($op1$$Register, $op2$$constant); 14.619 + %} 14.620 + ins_pipe(ialu_reg_reg); 14.621 +%} 14.622 + 14.623 +instruct overflowAddL_rReg(rFlagsReg cr, rax_RegL op1, rRegL op2) 14.624 +%{ 14.625 + match(Set cr (OverflowAddL op1 op2)); 14.626 + effect(DEF cr, USE_KILL op1, USE op2); 14.627 + 14.628 + format %{ "addq $op1, $op2\t# overflow check long" %} 14.629 + ins_encode %{ 14.630 + __ addq($op1$$Register, $op2$$Register); 14.631 + %} 14.632 + ins_pipe(ialu_reg_reg); 14.633 +%} 14.634 + 14.635 +instruct overflowAddL_rReg_imm(rFlagsReg cr, rax_RegL op1, immL32 op2) 14.636 +%{ 14.637 + match(Set cr (OverflowAddL op1 op2)); 14.638 + effect(DEF cr, USE_KILL op1, USE op2); 14.639 + 14.640 + format %{ "addq $op1, $op2\t# overflow check long" %} 14.641 + ins_encode %{ 14.642 + __ addq($op1$$Register, $op2$$constant); 14.643 + %} 14.644 + ins_pipe(ialu_reg_reg); 14.645 +%} 14.646 + 14.647 +instruct overflowSubI_rReg(rFlagsReg cr, rRegI op1, rRegI op2) 14.648 +%{ 14.649 + match(Set cr (OverflowSubI op1 op2)); 14.650 + 14.651 + format %{ "cmpl $op1, $op2\t# overflow check int" %} 14.652 + ins_encode %{ 14.653 + __ cmpl($op1$$Register, $op2$$Register); 14.654 + %} 14.655 + ins_pipe(ialu_reg_reg); 14.656 +%} 14.657 + 14.658 +instruct overflowSubI_rReg_imm(rFlagsReg cr, rRegI op1, immI op2) 14.659 +%{ 14.660 + match(Set cr (OverflowSubI op1 op2)); 14.661 + 14.662 + format %{ "cmpl $op1, $op2\t# overflow check int" %} 14.663 + ins_encode %{ 14.664 + __ cmpl($op1$$Register, $op2$$constant); 14.665 + %} 14.666 + ins_pipe(ialu_reg_reg); 14.667 +%} 14.668 + 14.669 +instruct overflowSubL_rReg(rFlagsReg cr, rRegL op1, rRegL op2) 14.670 +%{ 14.671 + match(Set cr (OverflowSubL op1 op2)); 14.672 + 14.673 + format %{ "cmpq $op1, $op2\t# overflow check long" %} 14.674 + ins_encode %{ 14.675 + __ cmpq($op1$$Register, $op2$$Register); 14.676 + %} 14.677 + ins_pipe(ialu_reg_reg); 14.678 +%} 14.679 + 14.680 +instruct overflowSubL_rReg_imm(rFlagsReg cr, rRegL op1, immL32 op2) 14.681 +%{ 14.682 + match(Set cr (OverflowSubL op1 op2)); 14.683 + 14.684 + format %{ "cmpq $op1, $op2\t# overflow check long" %} 14.685 + ins_encode %{ 14.686 + __ cmpq($op1$$Register, $op2$$constant); 14.687 + %} 14.688 + ins_pipe(ialu_reg_reg); 14.689 +%} 14.690 + 14.691 +instruct overflowNegI_rReg(rFlagsReg cr, immI0 zero, rax_RegI op2) 14.692 +%{ 14.693 + match(Set cr (OverflowSubI zero op2)); 14.694 + effect(DEF cr, USE_KILL op2); 14.695 + 14.696 + format %{ "negl $op2\t# overflow check int" %} 14.697 + ins_encode %{ 14.698 + __ negl($op2$$Register); 14.699 + %} 14.700 + ins_pipe(ialu_reg_reg); 14.701 +%} 14.702 + 14.703 +instruct overflowNegL_rReg(rFlagsReg cr, immL0 zero, rax_RegL op2) 14.704 +%{ 14.705 + match(Set cr (OverflowSubL zero op2)); 14.706 + effect(DEF cr, USE_KILL op2); 14.707 + 14.708 + format %{ "negq $op2\t# overflow check long" %} 14.709 + ins_encode %{ 14.710 + __ negq($op2$$Register); 14.711 + %} 14.712 + ins_pipe(ialu_reg_reg); 14.713 +%} 14.714 + 14.715 +instruct overflowMulI_rReg(rFlagsReg cr, rax_RegI op1, rRegI op2) 14.716 +%{ 14.717 + match(Set cr (OverflowMulI op1 op2)); 14.718 + effect(DEF cr, USE_KILL op1, USE op2); 14.719 + 14.720 + format %{ "imull $op1, $op2\t# overflow check int" %} 14.721 + ins_encode %{ 14.722 + __ imull($op1$$Register, $op2$$Register); 14.723 + %} 14.724 + ins_pipe(ialu_reg_reg_alu0); 14.725 +%} 14.726 + 14.727 +instruct overflowMulI_rReg_imm(rFlagsReg cr, rRegI op1, immI op2, rRegI tmp) 14.728 +%{ 14.729 + match(Set cr (OverflowMulI op1 op2)); 14.730 + effect(DEF cr, TEMP tmp, USE op1, USE op2); 14.731 + 14.732 + format %{ "imull $tmp, $op1, $op2\t# overflow check int" %} 14.733 + ins_encode %{ 14.734 + __ imull($tmp$$Register, $op1$$Register, $op2$$constant); 14.735 + %} 14.736 + ins_pipe(ialu_reg_reg_alu0); 14.737 +%} 14.738 + 14.739 +instruct overflowMulL_rReg(rFlagsReg cr, rax_RegL op1, rRegL op2) 14.740 +%{ 14.741 + match(Set cr (OverflowMulL op1 op2)); 14.742 + effect(DEF cr, USE_KILL op1, USE op2); 14.743 + 14.744 + format %{ "imulq $op1, $op2\t# overflow check long" %} 14.745 + ins_encode %{ 14.746 + __ imulq($op1$$Register, $op2$$Register); 14.747 + %} 14.748 + ins_pipe(ialu_reg_reg_alu0); 14.749 +%} 14.750 + 14.751 +instruct overflowMulL_rReg_imm(rFlagsReg cr, rRegL op1, immL32 op2, rRegL tmp) 14.752 +%{ 14.753 + match(Set cr (OverflowMulL op1 op2)); 14.754 + effect(DEF cr, TEMP tmp, USE op1, USE op2); 14.755 + 14.756 + format %{ "imulq $tmp, $op1, $op2\t# overflow check long" %} 14.757 + ins_encode %{ 14.758 + __ imulq($tmp$$Register, $op1$$Register, $op2$$constant); 14.759 + %} 14.760 + ins_pipe(ialu_reg_reg_alu0); 14.761 +%} 14.762 + 14.763 14.764 //----------Control Flow Instructions------------------------------------------ 14.765 // Signed compare Instructions
15.1 --- a/src/os/linux/vm/os_linux.cpp Thu Mar 20 10:34:48 2014 -0700 15.2 +++ b/src/os/linux/vm/os_linux.cpp Thu Mar 27 14:50:50 2014 -0700 15.3 @@ -109,6 +109,8 @@ 15.4 15.5 #define MAX_PATH (2 * K) 15.6 15.7 +#define MAX_SECS 100000000 15.8 + 15.9 // for timer info max values which include all bits 15.10 #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) 15.11 15.12 @@ -2471,7 +2473,6 @@ 15.13 sem_t _semaphore; 15.14 }; 15.15 15.16 - 15.17 Semaphore::Semaphore() { 15.18 sem_init(&_semaphore, 0, 0); 15.19 } 15.20 @@ -2493,8 +2494,22 @@ 15.21 } 15.22 15.23 bool Semaphore::timedwait(unsigned int sec, int nsec) { 15.24 + 15.25 struct timespec ts; 15.26 - unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); 15.27 + // Semaphore's are always associated with CLOCK_REALTIME 15.28 + os::Linux::clock_gettime(CLOCK_REALTIME, &ts); 15.29 + // see unpackTime for discussion on overflow checking 15.30 + if (sec >= MAX_SECS) { 15.31 + ts.tv_sec += MAX_SECS; 15.32 + ts.tv_nsec = 0; 15.33 + } else { 15.34 + ts.tv_sec += sec; 15.35 + ts.tv_nsec += nsec; 15.36 + if (ts.tv_nsec >= NANOSECS_PER_SEC) { 15.37 + ts.tv_nsec -= NANOSECS_PER_SEC; 15.38 + ++ts.tv_sec; // note: this must be <= max_secs 15.39 + } 15.40 + } 15.41 15.42 while (1) { 15.43 int result = sem_timedwait(&_semaphore, &ts); 15.44 @@ -5808,7 +5823,6 @@ 15.45 * is no need to track notifications. 15.46 */ 15.47 15.48 -#define MAX_SECS 100000000 15.49 /* 15.50 * This code is common to linux and solaris and will be moved to a 15.51 * common place in dolphin.
16.1 --- a/src/os/windows/vm/os_windows.cpp Thu Mar 20 10:34:48 2014 -0700 16.2 +++ b/src/os/windows/vm/os_windows.cpp Thu Mar 27 14:50:50 2014 -0700 16.3 @@ -2437,6 +2437,12 @@ 16.4 } 16.5 } 16.6 16.7 + if ((exception_code == EXCEPTION_ACCESS_VIOLATION) && 16.8 + VM_Version::is_cpuinfo_segv_addr(pc)) { 16.9 + // Verify that OS save/restore AVX registers. 16.10 + return Handle_Exception(exceptionInfo, VM_Version::cpuinfo_cont_addr()); 16.11 + } 16.12 + 16.13 if (t != NULL && t->is_Java_thread()) { 16.14 JavaThread* thread = (JavaThread*) t; 16.15 bool in_java = thread->thread_state() == _thread_in_Java;
17.1 --- a/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Thu Mar 20 10:34:48 2014 -0700 17.2 +++ b/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Thu Mar 27 14:50:50 2014 -0700 17.3 @@ -492,6 +492,11 @@ 17.4 } 17.5 } 17.6 17.7 + if ((sig == SIGSEGV || sig == SIGBUS) && VM_Version::is_cpuinfo_segv_addr(pc)) { 17.8 + // Verify that OS save/restore AVX registers. 17.9 + stub = VM_Version::cpuinfo_cont_addr(); 17.10 + } 17.11 + 17.12 // We test if stub is already set (by the stack overflow code 17.13 // above) so it is not overwritten by the code that follows. This 17.14 // check is not required on other platforms, because on other
18.1 --- a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Thu Mar 20 10:34:48 2014 -0700 18.2 +++ b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Thu Mar 27 14:50:50 2014 -0700 18.3 @@ -337,6 +337,11 @@ 18.4 } 18.5 } 18.6 18.7 + if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr(pc)) { 18.8 + // Verify that OS save/restore AVX registers. 18.9 + stub = VM_Version::cpuinfo_cont_addr(); 18.10 + } 18.11 + 18.12 if (thread->thread_state() == _thread_in_Java) { 18.13 // Java thread running in Java code => find exception handler if any 18.14 // a fault inside compiled code, the interpreter, or a stub
19.1 --- a/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Thu Mar 20 10:34:48 2014 -0700 19.2 +++ b/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Thu Mar 27 14:50:50 2014 -0700 19.3 @@ -459,6 +459,11 @@ 19.4 } 19.5 } 19.6 19.7 + if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr(pc)) { 19.8 + // Verify that OS save/restore AVX registers. 19.9 + stub = VM_Version::cpuinfo_cont_addr(); 19.10 + } 19.11 + 19.12 if (thread->thread_state() == _thread_in_vm) { 19.13 if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) { 19.14 stub = StubRoutines::handler_for_unsafe_access();
20.1 --- a/src/share/vm/adlc/archDesc.cpp Thu Mar 20 10:34:48 2014 -0700 20.2 +++ b/src/share/vm/adlc/archDesc.cpp Thu Mar 27 14:50:50 2014 -0700 20.3 @@ -1192,15 +1192,12 @@ 20.4 || strcmp(idealName,"CmpF") == 0 20.5 || strcmp(idealName,"FastLock") == 0 20.6 || strcmp(idealName,"FastUnlock") == 0 20.7 - || strcmp(idealName,"AddExactI") == 0 20.8 - || strcmp(idealName,"AddExactL") == 0 20.9 - || strcmp(idealName,"SubExactI") == 0 20.10 - || strcmp(idealName,"SubExactL") == 0 20.11 - || strcmp(idealName,"MulExactI") == 0 20.12 - || strcmp(idealName,"MulExactL") == 0 20.13 - || strcmp(idealName,"NegExactI") == 0 20.14 - || strcmp(idealName,"NegExactL") == 0 20.15 - || strcmp(idealName,"FlagsProj") == 0 20.16 + || strcmp(idealName,"OverflowAddI") == 0 20.17 + || strcmp(idealName,"OverflowAddL") == 0 20.18 + || strcmp(idealName,"OverflowSubI") == 0 20.19 + || strcmp(idealName,"OverflowSubL") == 0 20.20 + || strcmp(idealName,"OverflowMulI") == 0 20.21 + || strcmp(idealName,"OverflowMulL") == 0 20.22 || strcmp(idealName,"Bool") == 0 20.23 || strcmp(idealName,"Binary") == 0 ) { 20.24 // Removed ConI from the must_clone list. CPUs that cannot use
21.1 --- a/src/share/vm/adlc/formssel.cpp Thu Mar 20 10:34:48 2014 -0700 21.2 +++ b/src/share/vm/adlc/formssel.cpp Thu Mar 27 14:50:50 2014 -0700 21.3 @@ -649,6 +649,7 @@ 21.4 int USE_of_memory = 0; 21.5 int DEF_of_memory = 0; 21.6 const char* last_memory_DEF = NULL; // to test DEF/USE pairing in asserts 21.7 + const char* last_memory_USE = NULL; 21.8 Component *unique = NULL; 21.9 Component *comp = NULL; 21.10 ComponentList &components = (ComponentList &)_components; 21.11 @@ -670,7 +671,16 @@ 21.12 assert(0 == strcmp(last_memory_DEF, comp->_name), "every memory DEF is followed by a USE of the same name"); 21.13 last_memory_DEF = NULL; 21.14 } 21.15 - USE_of_memory++; 21.16 + // Handles same memory being used multiple times in the case of BMI1 instructions. 21.17 + if (last_memory_USE != NULL) { 21.18 + if (strcmp(comp->_name, last_memory_USE) != 0) { 21.19 + USE_of_memory++; 21.20 + } 21.21 + } else { 21.22 + USE_of_memory++; 21.23 + } 21.24 + last_memory_USE = comp->_name; 21.25 + 21.26 if (DEF_of_memory == 0) // defs take precedence 21.27 unique = comp; 21.28 } else {
22.1 --- a/src/share/vm/ci/ciClassList.hpp Thu Mar 20 10:34:48 2014 -0700 22.2 +++ b/src/share/vm/ci/ciClassList.hpp Thu Mar 27 14:50:50 2014 -0700 22.3 @@ -103,6 +103,7 @@ 22.4 friend class ciMethodType; \ 22.5 friend class ciReceiverTypeData; \ 22.6 friend class ciTypeEntries; \ 22.7 +friend class ciSpeculativeTrapData; \ 22.8 friend class ciSymbol; \ 22.9 friend class ciArray; \ 22.10 friend class ciObjArray; \
23.1 --- a/src/share/vm/ci/ciMethodData.cpp Thu Mar 20 10:34:48 2014 -0700 23.2 +++ b/src/share/vm/ci/ciMethodData.cpp Thu Mar 27 14:50:50 2014 -0700 23.3 @@ -78,6 +78,36 @@ 23.4 _parameters = NULL; 23.5 } 23.6 23.7 +void ciMethodData::load_extra_data() { 23.8 + MethodData* mdo = get_MethodData(); 23.9 + 23.10 + // speculative trap entries also hold a pointer to a Method so need to be translated 23.11 + DataLayout* dp_src = mdo->extra_data_base(); 23.12 + DataLayout* end_src = mdo->extra_data_limit(); 23.13 + DataLayout* dp_dst = extra_data_base(); 23.14 + for (;; dp_src = MethodData::next_extra(dp_src), dp_dst = MethodData::next_extra(dp_dst)) { 23.15 + assert(dp_src < end_src, "moved past end of extra data"); 23.16 + // New traps in the MDO can be added as we translate the copy so 23.17 + // look at the entries in the copy. 23.18 + switch(dp_dst->tag()) { 23.19 + case DataLayout::speculative_trap_data_tag: { 23.20 + ciSpeculativeTrapData* data_dst = new ciSpeculativeTrapData(dp_dst); 23.21 + SpeculativeTrapData* data_src = new SpeculativeTrapData(dp_src); 23.22 + data_dst->translate_from(data_src); 23.23 + break; 23.24 + } 23.25 + case DataLayout::bit_data_tag: 23.26 + break; 23.27 + case DataLayout::no_tag: 23.28 + case DataLayout::arg_info_data_tag: 23.29 + // An empty slot or ArgInfoData entry marks the end of the trap data 23.30 + return; 23.31 + default: 23.32 + fatal(err_msg("bad tag = %d", dp_dst->tag())); 23.33 + } 23.34 + } 23.35 +} 23.36 + 23.37 void ciMethodData::load_data() { 23.38 MethodData* mdo = get_MethodData(); 23.39 if (mdo == NULL) { 23.40 @@ -116,6 +146,8 @@ 23.41 parameters->translate_from(mdo->parameters_type_data()); 23.42 } 23.43 23.44 + load_extra_data(); 23.45 + 23.46 // Note: Extra data are all BitData, and do not need translation. 23.47 _current_mileage = MethodData::mileage_of(mdo->method()); 23.48 _invocation_counter = mdo->invocation_count(); 23.49 @@ -156,6 +188,12 @@ 23.50 set_type(translate_klass(k)); 23.51 } 23.52 23.53 +void ciSpeculativeTrapData::translate_from(const ProfileData* data) { 23.54 + Method* m = data->as_SpeculativeTrapData()->method(); 23.55 + ciMethod* ci_m = CURRENT_ENV->get_method(m); 23.56 + set_method(ci_m); 23.57 +} 23.58 + 23.59 // Get the data at an arbitrary (sort of) data index. 23.60 ciProfileData* ciMethodData::data_at(int data_index) { 23.61 if (out_of_bounds(data_index)) { 23.62 @@ -203,33 +241,65 @@ 23.63 return next; 23.64 } 23.65 23.66 -// Translate a bci to its corresponding data, or NULL. 23.67 -ciProfileData* ciMethodData::bci_to_data(int bci) { 23.68 - ciProfileData* data = data_before(bci); 23.69 - for ( ; is_valid(data); data = next_data(data)) { 23.70 - if (data->bci() == bci) { 23.71 - set_hint_di(dp_to_di(data->dp())); 23.72 - return data; 23.73 - } else if (data->bci() > bci) { 23.74 - break; 23.75 - } 23.76 - } 23.77 +ciProfileData* ciMethodData::bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots) { 23.78 // bci_to_extra_data(bci) ... 23.79 DataLayout* dp = data_layout_at(data_size()); 23.80 DataLayout* end = data_layout_at(data_size() + extra_data_size()); 23.81 - for (; dp < end; dp = MethodData::next_extra(dp)) { 23.82 - if (dp->tag() == DataLayout::no_tag) { 23.83 + two_free_slots = false; 23.84 + for (;dp < end; dp = MethodData::next_extra(dp)) { 23.85 + switch(dp->tag()) { 23.86 + case DataLayout::no_tag: 23.87 _saw_free_extra_data = true; // observed an empty slot (common case) 23.88 + two_free_slots = (MethodData::next_extra(dp)->tag() == DataLayout::no_tag); 23.89 return NULL; 23.90 + case DataLayout::arg_info_data_tag: 23.91 + return NULL; // ArgInfoData is at the end of extra data section. 23.92 + case DataLayout::bit_data_tag: 23.93 + if (m == NULL && dp->bci() == bci) { 23.94 + return new ciBitData(dp); 23.95 + } 23.96 + break; 23.97 + case DataLayout::speculative_trap_data_tag: { 23.98 + ciSpeculativeTrapData* data = new ciSpeculativeTrapData(dp); 23.99 + // data->method() might be null if the MDO is snapshotted 23.100 + // concurrently with a trap 23.101 + if (m != NULL && data->method() == m && dp->bci() == bci) { 23.102 + return data; 23.103 + } 23.104 + break; 23.105 } 23.106 - if (dp->tag() == DataLayout::arg_info_data_tag) { 23.107 - break; // ArgInfoData is at the end of extra data section. 23.108 + default: 23.109 + fatal(err_msg("bad tag = %d", dp->tag())); 23.110 } 23.111 - if (dp->bci() == bci) { 23.112 - assert(dp->tag() == DataLayout::bit_data_tag, "sane"); 23.113 - return new ciBitData(dp); 23.114 + } 23.115 + return NULL; 23.116 +} 23.117 + 23.118 +// Translate a bci to its corresponding data, or NULL. 23.119 +ciProfileData* ciMethodData::bci_to_data(int bci, ciMethod* m) { 23.120 + // If m is not NULL we look for a SpeculativeTrapData entry 23.121 + if (m == NULL) { 23.122 + ciProfileData* data = data_before(bci); 23.123 + for ( ; is_valid(data); data = next_data(data)) { 23.124 + if (data->bci() == bci) { 23.125 + set_hint_di(dp_to_di(data->dp())); 23.126 + return data; 23.127 + } else if (data->bci() > bci) { 23.128 + break; 23.129 + } 23.130 } 23.131 } 23.132 + bool two_free_slots = false; 23.133 + ciProfileData* result = bci_to_extra_data(bci, m, two_free_slots); 23.134 + if (result != NULL) { 23.135 + return result; 23.136 + } 23.137 + if (m != NULL && !two_free_slots) { 23.138 + // We were looking for a SpeculativeTrapData entry we didn't 23.139 + // find. Room is not available for more SpeculativeTrapData 23.140 + // entries, look in the non SpeculativeTrapData entries. 23.141 + return bci_to_data(bci, NULL); 23.142 + } 23.143 return NULL; 23.144 } 23.145 23.146 @@ -525,18 +595,25 @@ 23.147 st->print_cr("--- Extra data:"); 23.148 DataLayout* dp = data_layout_at(data_size()); 23.149 DataLayout* end = data_layout_at(data_size() + extra_data_size()); 23.150 - for (; dp < end; dp = MethodData::next_extra(dp)) { 23.151 - if (dp->tag() == DataLayout::no_tag) continue; 23.152 - if (dp->tag() == DataLayout::bit_data_tag) { 23.153 + for (;; dp = MethodData::next_extra(dp)) { 23.154 + assert(dp < end, "moved past end of extra data"); 23.155 + switch (dp->tag()) { 23.156 + case DataLayout::no_tag: 23.157 + continue; 23.158 + case DataLayout::bit_data_tag: 23.159 data = new BitData(dp); 23.160 - } else { 23.161 - assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo"); 23.162 + break; 23.163 + case DataLayout::arg_info_data_tag: 23.164 data = new ciArgInfoData(dp); 23.165 dp = end; // ArgInfoData is at the end of extra data section. 23.166 + break; 23.167 + default: 23.168 + fatal(err_msg("unexpected tag %d", dp->tag())); 23.169 } 23.170 st->print("%d", dp_to_di(data->dp())); 23.171 st->fill_to(6); 23.172 data->print_data_on(st); 23.173 + if (dp >= end) return; 23.174 } 23.175 } 23.176 23.177 @@ -569,8 +646,8 @@ 23.178 st->cr(); 23.179 } 23.180 23.181 -void ciCallTypeData::print_data_on(outputStream* st) const { 23.182 - print_shared(st, "ciCallTypeData"); 23.183 +void ciCallTypeData::print_data_on(outputStream* st, const char* extra) const { 23.184 + print_shared(st, "ciCallTypeData", extra); 23.185 if (has_arguments()) { 23.186 tab(st, true); 23.187 st->print("argument types"); 23.188 @@ -599,18 +676,18 @@ 23.189 } 23.190 } 23.191 23.192 -void ciReceiverTypeData::print_data_on(outputStream* st) const { 23.193 - print_shared(st, "ciReceiverTypeData"); 23.194 +void ciReceiverTypeData::print_data_on(outputStream* st, const char* extra) const { 23.195 + print_shared(st, "ciReceiverTypeData", extra); 23.196 print_receiver_data_on(st); 23.197 } 23.198 23.199 -void ciVirtualCallData::print_data_on(outputStream* st) const { 23.200 - print_shared(st, "ciVirtualCallData"); 23.201 +void ciVirtualCallData::print_data_on(outputStream* st, const char* extra) const { 23.202 + print_shared(st, "ciVirtualCallData", extra); 23.203 rtd_super()->print_receiver_data_on(st); 23.204 } 23.205 23.206 -void ciVirtualCallTypeData::print_data_on(outputStream* st) const { 23.207 - print_shared(st, "ciVirtualCallTypeData"); 23.208 +void ciVirtualCallTypeData::print_data_on(outputStream* st, const char* extra) const { 23.209 + print_shared(st, "ciVirtualCallTypeData", extra); 23.210 rtd_super()->print_receiver_data_on(st); 23.211 if (has_arguments()) { 23.212 tab(st, true); 23.213 @@ -624,8 +701,15 @@ 23.214 } 23.215 } 23.216 23.217 -void ciParametersTypeData::print_data_on(outputStream* st) const { 23.218 - st->print_cr("Parametertypes"); 23.219 +void ciParametersTypeData::print_data_on(outputStream* st, const char* extra) const { 23.220 + st->print_cr("ciParametersTypeData"); 23.221 parameters()->print_data_on(st); 23.222 } 23.223 + 23.224 +void ciSpeculativeTrapData::print_data_on(outputStream* st, const char* extra) const { 23.225 + st->print_cr("ciSpeculativeTrapData"); 23.226 + tab(st); 23.227 + method()->print_short_name(st); 23.228 + st->cr(); 23.229 +} 23.230 #endif
24.1 --- a/src/share/vm/ci/ciMethodData.hpp Thu Mar 20 10:34:48 2014 -0700 24.2 +++ b/src/share/vm/ci/ciMethodData.hpp Thu Mar 27 14:50:50 2014 -0700 24.3 @@ -31,6 +31,7 @@ 24.4 #include "ci/ciUtilities.hpp" 24.5 #include "oops/methodData.hpp" 24.6 #include "oops/oop.inline.hpp" 24.7 +#include "runtime/deoptimization.hpp" 24.8 24.9 class ciBitData; 24.10 class ciCounterData; 24.11 @@ -44,6 +45,7 @@ 24.12 class ciCallTypeData; 24.13 class ciVirtualCallTypeData; 24.14 class ciParametersTypeData; 24.15 +class ciSpeculativeTrapData;; 24.16 24.17 typedef ProfileData ciProfileData; 24.18 24.19 @@ -173,7 +175,7 @@ 24.20 } 24.21 24.22 #ifndef PRODUCT 24.23 - void print_data_on(outputStream* st) const; 24.24 + void print_data_on(outputStream* st, const char* extra) const; 24.25 #endif 24.26 }; 24.27 24.28 @@ -200,7 +202,7 @@ 24.29 } 24.30 void translate_receiver_data_from(const ProfileData* data); 24.31 #ifndef PRODUCT 24.32 - void print_data_on(outputStream* st) const; 24.33 + void print_data_on(outputStream* st, const char* extra) const; 24.34 void print_receiver_data_on(outputStream* st) const; 24.35 #endif 24.36 }; 24.37 @@ -225,7 +227,7 @@ 24.38 rtd_super()->translate_receiver_data_from(data); 24.39 } 24.40 #ifndef PRODUCT 24.41 - void print_data_on(outputStream* st) const; 24.42 + void print_data_on(outputStream* st, const char* extra) const; 24.43 #endif 24.44 }; 24.45 24.46 @@ -287,7 +289,7 @@ 24.47 } 24.48 24.49 #ifndef PRODUCT 24.50 - void print_data_on(outputStream* st) const; 24.51 + void print_data_on(outputStream* st, const char* extra) const; 24.52 #endif 24.53 }; 24.54 24.55 @@ -336,7 +338,26 @@ 24.56 } 24.57 24.58 #ifndef PRODUCT 24.59 - void print_data_on(outputStream* st) const; 24.60 + void print_data_on(outputStream* st, const char* extra) const; 24.61 +#endif 24.62 +}; 24.63 + 24.64 +class ciSpeculativeTrapData : public SpeculativeTrapData { 24.65 +public: 24.66 + ciSpeculativeTrapData(DataLayout* layout) : SpeculativeTrapData(layout) {} 24.67 + 24.68 + virtual void translate_from(const ProfileData* data); 24.69 + 24.70 + ciMethod* method() const { 24.71 + return (ciMethod*)intptr_at(method_offset); 24.72 + } 24.73 + 24.74 + void set_method(ciMethod* m) { 24.75 + set_intptr_at(method_offset, (intptr_t)m); 24.76 + } 24.77 + 24.78 +#ifndef PRODUCT 24.79 + void print_data_on(outputStream* st, const char* extra) const; 24.80 #endif 24.81 }; 24.82 24.83 @@ -436,6 +457,16 @@ 24.84 24.85 ciArgInfoData *arg_info() const; 24.86 24.87 + address data_base() const { 24.88 + return (address) _data; 24.89 + } 24.90 + DataLayout* limit_data_position() const { 24.91 + return (DataLayout*)((address)data_base() + _data_size); 24.92 + } 24.93 + 24.94 + void load_extra_data(); 24.95 + ciProfileData* bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots); 24.96 + 24.97 public: 24.98 bool is_method_data() const { return true; } 24.99 24.100 @@ -475,9 +506,11 @@ 24.101 ciProfileData* next_data(ciProfileData* current); 24.102 bool is_valid(ciProfileData* current) { return current != NULL; } 24.103 24.104 - // Get the data at an arbitrary bci, or NULL if there is none. 24.105 - ciProfileData* bci_to_data(int bci); 24.106 - ciProfileData* bci_to_extra_data(int bci, bool create_if_missing); 24.107 + DataLayout* extra_data_base() const { return limit_data_position(); } 24.108 + 24.109 + // Get the data at an arbitrary bci, or NULL if there is none. If m 24.110 + // is not NULL look for a SpeculativeTrapData if any first. 24.111 + ciProfileData* bci_to_data(int bci, ciMethod* m = NULL); 24.112 24.113 uint overflow_trap_count() const { 24.114 return _orig.overflow_trap_count(); 24.115 @@ -496,12 +529,13 @@ 24.116 24.117 // Helpful query functions that decode trap_state. 24.118 int has_trap_at(ciProfileData* data, int reason); 24.119 - int has_trap_at(int bci, int reason) { 24.120 - return has_trap_at(bci_to_data(bci), reason); 24.121 + int has_trap_at(int bci, ciMethod* m, int reason) { 24.122 + assert((m != NULL) == Deoptimization::reason_is_speculate(reason), "inconsistent method/reason"); 24.123 + return has_trap_at(bci_to_data(bci, m), reason); 24.124 } 24.125 int trap_recompiled_at(ciProfileData* data); 24.126 - int trap_recompiled_at(int bci) { 24.127 - return trap_recompiled_at(bci_to_data(bci)); 24.128 + int trap_recompiled_at(int bci, ciMethod* m) { 24.129 + return trap_recompiled_at(bci_to_data(bci, m)); 24.130 } 24.131 24.132 void clear_escape_info();
25.1 --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Mar 20 10:34:48 2014 -0700 25.2 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Mar 27 14:50:50 2014 -0700 25.3 @@ -1809,8 +1809,8 @@ 25.4 uint _regions_claimed; 25.5 size_t _freed_bytes; 25.6 FreeRegionList* _local_cleanup_list; 25.7 - OldRegionSet* _old_proxy_set; 25.8 - HumongousRegionSet* _humongous_proxy_set; 25.9 + HeapRegionSetCount _old_regions_removed; 25.10 + HeapRegionSetCount _humongous_regions_removed; 25.11 HRRSCleanupTask* _hrrs_cleanup_task; 25.12 double _claimed_region_time; 25.13 double _max_region_time; 25.14 @@ -1819,19 +1819,19 @@ 25.15 G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1, 25.16 int worker_num, 25.17 FreeRegionList* local_cleanup_list, 25.18 - OldRegionSet* old_proxy_set, 25.19 - HumongousRegionSet* humongous_proxy_set, 25.20 HRRSCleanupTask* hrrs_cleanup_task) : 25.21 _g1(g1), _worker_num(worker_num), 25.22 _max_live_bytes(0), _regions_claimed(0), 25.23 _freed_bytes(0), 25.24 _claimed_region_time(0.0), _max_region_time(0.0), 25.25 _local_cleanup_list(local_cleanup_list), 25.26 - _old_proxy_set(old_proxy_set), 25.27 - _humongous_proxy_set(humongous_proxy_set), 25.28 + _old_regions_removed(), 25.29 + _humongous_regions_removed(), 25.30 _hrrs_cleanup_task(hrrs_cleanup_task) { } 25.31 25.32 size_t freed_bytes() { return _freed_bytes; } 25.33 + const HeapRegionSetCount& old_regions_removed() { return _old_regions_removed; } 25.34 + const HeapRegionSetCount& humongous_regions_removed() { return _humongous_regions_removed; } 25.35 25.36 bool doHeapRegion(HeapRegion *hr) { 25.37 if (hr->continuesHumongous()) { 25.38 @@ -1844,13 +1844,22 @@ 25.39 _regions_claimed++; 25.40 hr->note_end_of_marking(); 25.41 _max_live_bytes += hr->max_live_bytes(); 25.42 - _g1->free_region_if_empty(hr, 25.43 - &_freed_bytes, 25.44 - _local_cleanup_list, 25.45 - _old_proxy_set, 25.46 - _humongous_proxy_set, 25.47 - _hrrs_cleanup_task, 25.48 - true /* par */); 25.49 + 25.50 + if (hr->used() > 0 && hr->max_live_bytes() == 0 && !hr->is_young()) { 25.51 + _freed_bytes += hr->used(); 25.52 + hr->set_containing_set(NULL); 25.53 + if (hr->isHumongous()) { 25.54 + assert(hr->startsHumongous(), "we should only see starts humongous"); 25.55 + _humongous_regions_removed.increment(1u, hr->capacity()); 25.56 + _g1->free_humongous_region(hr, _local_cleanup_list, true); 25.57 + } else { 25.58 + _old_regions_removed.increment(1u, hr->capacity()); 25.59 + _g1->free_region(hr, _local_cleanup_list, true); 25.60 + } 25.61 + } else { 25.62 + hr->rem_set()->do_cleanup_work(_hrrs_cleanup_task); 25.63 + } 25.64 + 25.65 double region_time = (os::elapsedTime() - start); 25.66 _claimed_region_time += region_time; 25.67 if (region_time > _max_region_time) { 25.68 @@ -1883,12 +1892,8 @@ 25.69 void work(uint worker_id) { 25.70 double start = os::elapsedTime(); 25.71 FreeRegionList local_cleanup_list("Local Cleanup List"); 25.72 - OldRegionSet old_proxy_set("Local Cleanup Old Proxy Set"); 25.73 - HumongousRegionSet humongous_proxy_set("Local Cleanup Humongous Proxy Set"); 25.74 HRRSCleanupTask hrrs_cleanup_task; 25.75 G1NoteEndOfConcMarkClosure g1_note_end(_g1h, worker_id, &local_cleanup_list, 25.76 - &old_proxy_set, 25.77 - &humongous_proxy_set, 25.78 &hrrs_cleanup_task); 25.79 if (G1CollectedHeap::use_parallel_gc_threads()) { 25.80 _g1h->heap_region_par_iterate_chunked(&g1_note_end, worker_id, 25.81 @@ -1900,13 +1905,10 @@ 25.82 assert(g1_note_end.complete(), "Shouldn't have yielded!"); 25.83 25.84 // Now update the lists 25.85 - _g1h->update_sets_after_freeing_regions(g1_note_end.freed_bytes(), 25.86 - NULL /* free_list */, 25.87 - &old_proxy_set, 25.88 - &humongous_proxy_set, 25.89 - true /* par */); 25.90 + _g1h->remove_from_old_sets(g1_note_end.old_regions_removed(), g1_note_end.humongous_regions_removed()); 25.91 { 25.92 MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); 25.93 + _g1h->decrement_summary_bytes(g1_note_end.freed_bytes()); 25.94 _max_live_bytes += g1_note_end.max_live_bytes(); 25.95 _freed_bytes += g1_note_end.freed_bytes(); 25.96 25.97 @@ -1920,7 +1922,7 @@ 25.98 25.99 G1HRPrinter* hr_printer = _g1h->hr_printer(); 25.100 if (hr_printer->is_active()) { 25.101 - HeapRegionLinkedListIterator iter(&local_cleanup_list); 25.102 + FreeRegionListIterator iter(&local_cleanup_list); 25.103 while (iter.more_available()) { 25.104 HeapRegion* hr = iter.get_next(); 25.105 hr_printer->cleanup(hr); 25.106 @@ -1971,7 +1973,6 @@ 25.107 return; 25.108 } 25.109 25.110 - HRSPhaseSetter x(HRSPhaseCleanup); 25.111 g1h->verify_region_sets_optional(); 25.112 25.113 if (VerifyDuringGC) { 25.114 @@ -2144,7 +2145,7 @@ 25.115 25.116 G1CollectedHeap* g1h = G1CollectedHeap::heap(); 25.117 25.118 - _cleanup_list.verify_optional(); 25.119 + _cleanup_list.verify_list(); 25.120 FreeRegionList tmp_free_list("Tmp Free List"); 25.121 25.122 if (G1ConcRegionFreeingVerbose) {
26.1 --- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp Thu Mar 20 10:34:48 2014 -0700 26.2 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp Thu Mar 27 14:50:50 2014 -0700 26.3 @@ -25,7 +25,7 @@ 26.4 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_HPP 26.5 #define SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_HPP 26.6 26.7 -#include "gc_implementation/g1/heapRegionSets.hpp" 26.8 +#include "gc_implementation/g1/heapRegionSet.hpp" 26.9 #include "utilities/taskqueue.hpp" 26.10 26.11 class G1CollectedHeap;
27.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Mar 20 10:34:48 2014 -0700 27.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Mar 27 14:50:50 2014 -0700 27.3 @@ -1298,7 +1298,6 @@ 27.4 27.5 size_t metadata_prev_used = MetaspaceAux::allocated_used_bytes(); 27.6 27.7 - HRSPhaseSetter x(HRSPhaseFullGC); 27.8 verify_region_sets_optional(); 27.9 27.10 const bool do_clear_all_soft_refs = clear_all_soft_refs || 27.11 @@ -1928,10 +1927,10 @@ 27.12 _g1mm(NULL), 27.13 _refine_cte_cl(NULL), 27.14 _full_collection(false), 27.15 - _free_list("Master Free List"), 27.16 - _secondary_free_list("Secondary Free List"), 27.17 - _old_set("Old Set"), 27.18 - _humongous_set("Master Humongous Set"), 27.19 + _free_list("Master Free List", new MasterFreeRegionListMtSafeChecker()), 27.20 + _secondary_free_list("Secondary Free List", new SecondaryFreeRegionListMtSafeChecker()), 27.21 + _old_set("Old Set", false /* humongous */, new OldRegionSetMtSafeChecker()), 27.22 + _humongous_set("Master Humongous Set", true /* humongous */, new HumongousRegionSetMtSafeChecker()), 27.23 _free_regions_coming(false), 27.24 _young_list(new YoungList(this)), 27.25 _gc_time_stamp(0), 27.26 @@ -2079,7 +2078,7 @@ 27.27 guarantee(HeapRegion::CardsPerRegion < max_cards_per_region, 27.28 "too many cards per region"); 27.29 27.30 - HeapRegionSet::set_unrealistically_long_length(max_regions() + 1); 27.31 + FreeRegionList::set_unrealistically_long_length(max_regions() + 1); 27.32 27.33 _bot_shared = new G1BlockOffsetSharedArray(_reserved, 27.34 heap_word_size(init_byte_size)); 27.35 @@ -3013,7 +3012,17 @@ 27.36 } 27.37 27.38 size_t G1CollectedHeap::tlab_capacity(Thread* ignored) const { 27.39 - return HeapRegion::GrainBytes; 27.40 + return (_g1_policy->young_list_target_length() - young_list()->survivor_length()) * HeapRegion::GrainBytes; 27.41 +} 27.42 + 27.43 +size_t G1CollectedHeap::tlab_used(Thread* ignored) const { 27.44 + return young_list()->eden_used_bytes(); 27.45 +} 27.46 + 27.47 +// For G1 TLABs should not contain humongous objects, so the maximum TLAB size 27.48 +// must be smaller than the humongous object limit. 27.49 +size_t G1CollectedHeap::max_tlab_size() const { 27.50 + return align_size_down(_humongous_object_threshold_in_words - 1, MinObjAlignment); 27.51 } 27.52 27.53 size_t G1CollectedHeap::unsafe_max_tlab_alloc(Thread* ignored) const { 27.54 @@ -3025,11 +3034,11 @@ 27.55 // humongous objects. 27.56 27.57 HeapRegion* hr = _mutator_alloc_region.get(); 27.58 - size_t max_tlab_size = _humongous_object_threshold_in_words * wordSize; 27.59 + size_t max_tlab = max_tlab_size() * wordSize; 27.60 if (hr == NULL) { 27.61 - return max_tlab_size; 27.62 + return max_tlab; 27.63 } else { 27.64 - return MIN2(MAX2(hr->free(), (size_t) MinTLABSize), max_tlab_size); 27.65 + return MIN2(MAX2(hr->free(), (size_t) MinTLABSize), max_tlab); 27.66 } 27.67 } 27.68 27.69 @@ -3668,6 +3677,7 @@ 27.70 // always_do_update_barrier = false; 27.71 assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer"); 27.72 // Fill TLAB's and such 27.73 + accumulate_statistics_all_tlabs(); 27.74 ensure_parsability(true); 27.75 27.76 if (G1SummarizeRSetStats && (G1SummarizeRSetStatsPeriod > 0) && 27.77 @@ -3692,6 +3702,8 @@ 27.78 "derived pointer present")); 27.79 // always_do_update_barrier = true; 27.80 27.81 + resize_all_tlabs(); 27.82 + 27.83 // We have just completed a GC. Update the soft reference 27.84 // policy with the new heap occupancy 27.85 Universe::update_heap_info_at_gc(); 27.86 @@ -3892,7 +3904,6 @@ 27.87 print_heap_before_gc(); 27.88 trace_heap_before_gc(_gc_tracer_stw); 27.89 27.90 - HRSPhaseSetter x(HRSPhaseEvacuation); 27.91 verify_region_sets_optional(); 27.92 verify_dirty_young_regions(); 27.93 27.94 @@ -5954,28 +5965,7 @@ 27.95 COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); 27.96 } 27.97 27.98 -void G1CollectedHeap::free_region_if_empty(HeapRegion* hr, 27.99 - size_t* pre_used, 27.100 - FreeRegionList* free_list, 27.101 - OldRegionSet* old_proxy_set, 27.102 - HumongousRegionSet* humongous_proxy_set, 27.103 - HRRSCleanupTask* hrrs_cleanup_task, 27.104 - bool par) { 27.105 - if (hr->used() > 0 && hr->max_live_bytes() == 0 && !hr->is_young()) { 27.106 - if (hr->isHumongous()) { 27.107 - assert(hr->startsHumongous(), "we should only see starts humongous"); 27.108 - free_humongous_region(hr, pre_used, free_list, humongous_proxy_set, par); 27.109 - } else { 27.110 - _old_set.remove_with_proxy(hr, old_proxy_set); 27.111 - free_region(hr, pre_used, free_list, par); 27.112 - } 27.113 - } else { 27.114 - hr->rem_set()->do_cleanup_work(hrrs_cleanup_task); 27.115 - } 27.116 -} 27.117 - 27.118 void G1CollectedHeap::free_region(HeapRegion* hr, 27.119 - size_t* pre_used, 27.120 FreeRegionList* free_list, 27.121 bool par) { 27.122 assert(!hr->isHumongous(), "this is only for non-humongous regions"); 27.123 @@ -5988,70 +5978,56 @@ 27.124 if (!hr->is_young()) { 27.125 _cg1r->hot_card_cache()->reset_card_counts(hr); 27.126 } 27.127 - *pre_used += hr->used(); 27.128 hr->hr_clear(par, true /* clear_space */); 27.129 free_list->add_as_head(hr); 27.130 } 27.131 27.132 void G1CollectedHeap::free_humongous_region(HeapRegion* hr, 27.133 - size_t* pre_used, 27.134 FreeRegionList* free_list, 27.135 - HumongousRegionSet* humongous_proxy_set, 27.136 bool par) { 27.137 assert(hr->startsHumongous(), "this is only for starts humongous regions"); 27.138 assert(free_list != NULL, "pre-condition"); 27.139 - assert(humongous_proxy_set != NULL, "pre-condition"); 27.140 - 27.141 - size_t hr_used = hr->used(); 27.142 + 27.143 size_t hr_capacity = hr->capacity(); 27.144 - size_t hr_pre_used = 0; 27.145 - _humongous_set.remove_with_proxy(hr, humongous_proxy_set); 27.146 // We need to read this before we make the region non-humongous, 27.147 // otherwise the information will be gone. 27.148 uint last_index = hr->last_hc_index(); 27.149 hr->set_notHumongous(); 27.150 - free_region(hr, &hr_pre_used, free_list, par); 27.151 + free_region(hr, free_list, par); 27.152 27.153 uint i = hr->hrs_index() + 1; 27.154 while (i < last_index) { 27.155 HeapRegion* curr_hr = region_at(i); 27.156 assert(curr_hr->continuesHumongous(), "invariant"); 27.157 curr_hr->set_notHumongous(); 27.158 - free_region(curr_hr, &hr_pre_used, free_list, par); 27.159 + free_region(curr_hr, free_list, par); 27.160 i += 1; 27.161 } 27.162 - assert(hr_pre_used == hr_used, 27.163 - err_msg("hr_pre_used: "SIZE_FORMAT" and hr_used: "SIZE_FORMAT" " 27.164 - "should be the same", hr_pre_used, hr_used)); 27.165 - *pre_used += hr_pre_used; 27.166 -} 27.167 - 27.168 -void G1CollectedHeap::update_sets_after_freeing_regions(size_t pre_used, 27.169 - FreeRegionList* free_list, 27.170 - OldRegionSet* old_proxy_set, 27.171 - HumongousRegionSet* humongous_proxy_set, 27.172 - bool par) { 27.173 - if (pre_used > 0) { 27.174 - Mutex* lock = (par) ? ParGCRareEvent_lock : NULL; 27.175 - MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag); 27.176 - assert(_summary_bytes_used >= pre_used, 27.177 - err_msg("invariant: _summary_bytes_used: "SIZE_FORMAT" " 27.178 - "should be >= pre_used: "SIZE_FORMAT, 27.179 - _summary_bytes_used, pre_used)); 27.180 - _summary_bytes_used -= pre_used; 27.181 - } 27.182 - if (free_list != NULL && !free_list->is_empty()) { 27.183 +} 27.184 + 27.185 +void G1CollectedHeap::remove_from_old_sets(const HeapRegionSetCount& old_regions_removed, 27.186 + const HeapRegionSetCount& humongous_regions_removed) { 27.187 + if (old_regions_removed.length() > 0 || humongous_regions_removed.length() > 0) { 27.188 + MutexLockerEx x(OldSets_lock, Mutex::_no_safepoint_check_flag); 27.189 + _old_set.bulk_remove(old_regions_removed); 27.190 + _humongous_set.bulk_remove(humongous_regions_removed); 27.191 + } 27.192 + 27.193 +} 27.194 + 27.195 +void G1CollectedHeap::prepend_to_freelist(FreeRegionList* list) { 27.196 + assert(list != NULL, "list can't be null"); 27.197 + if (!list->is_empty()) { 27.198 MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag); 27.199 - _free_list.add_as_head(free_list); 27.200 - } 27.201 - if (old_proxy_set != NULL && !old_proxy_set->is_empty()) { 27.202 - MutexLockerEx x(OldSets_lock, Mutex::_no_safepoint_check_flag); 27.203 - _old_set.update_from_proxy(old_proxy_set); 27.204 - } 27.205 - if (humongous_proxy_set != NULL && !humongous_proxy_set->is_empty()) { 27.206 - MutexLockerEx x(OldSets_lock, Mutex::_no_safepoint_check_flag); 27.207 - _humongous_set.update_from_proxy(humongous_proxy_set); 27.208 - } 27.209 + _free_list.add_as_head(list); 27.210 + } 27.211 +} 27.212 + 27.213 +void G1CollectedHeap::decrement_summary_bytes(size_t bytes) { 27.214 + assert(_summary_bytes_used >= bytes, 27.215 + err_msg("invariant: _summary_bytes_used: "SIZE_FORMAT" should be >= bytes: "SIZE_FORMAT, 27.216 + _summary_bytes_used, bytes)); 27.217 + _summary_bytes_used -= bytes; 27.218 } 27.219 27.220 class G1ParCleanupCTTask : public AbstractGangTask { 27.221 @@ -6244,7 +6220,8 @@ 27.222 27.223 // And the region is empty. 27.224 assert(!used_mr.is_empty(), "Should not have empty regions in a CS."); 27.225 - free_region(cur, &pre_used, &local_free_list, false /* par */); 27.226 + pre_used += cur->used(); 27.227 + free_region(cur, &local_free_list, false /* par */); 27.228 } else { 27.229 cur->uninstall_surv_rate_group(); 27.230 if (cur->is_young()) { 27.231 @@ -6272,10 +6249,8 @@ 27.232 young_time_ms += elapsed_ms; 27.233 } 27.234 27.235 - update_sets_after_freeing_regions(pre_used, &local_free_list, 27.236 - NULL /* old_proxy_set */, 27.237 - NULL /* humongous_proxy_set */, 27.238 - false /* par */); 27.239 + prepend_to_freelist(&local_free_list); 27.240 + decrement_summary_bytes(pre_used); 27.241 policy->phase_times()->record_young_free_cset_time_ms(young_time_ms); 27.242 policy->phase_times()->record_non_young_free_cset_time_ms(non_young_time_ms); 27.243 } 27.244 @@ -6387,10 +6362,10 @@ 27.245 27.246 class TearDownRegionSetsClosure : public HeapRegionClosure { 27.247 private: 27.248 - OldRegionSet *_old_set; 27.249 + HeapRegionSet *_old_set; 27.250 27.251 public: 27.252 - TearDownRegionSetsClosure(OldRegionSet* old_set) : _old_set(old_set) { } 27.253 + TearDownRegionSetsClosure(HeapRegionSet* old_set) : _old_set(old_set) { } 27.254 27.255 bool doHeapRegion(HeapRegion* r) { 27.256 if (r->is_empty()) { 27.257 @@ -6429,13 +6404,13 @@ 27.258 class RebuildRegionSetsClosure : public HeapRegionClosure { 27.259 private: 27.260 bool _free_list_only; 27.261 - OldRegionSet* _old_set; 27.262 + HeapRegionSet* _old_set; 27.263 FreeRegionList* _free_list; 27.264 size_t _total_used; 27.265 27.266 public: 27.267 RebuildRegionSetsClosure(bool free_list_only, 27.268 - OldRegionSet* old_set, FreeRegionList* free_list) : 27.269 + HeapRegionSet* old_set, FreeRegionList* free_list) : 27.270 _free_list_only(free_list_only), 27.271 _old_set(old_set), _free_list(free_list), _total_used(0) { 27.272 assert(_free_list->is_empty(), "pre-condition"); 27.273 @@ -6632,23 +6607,22 @@ 27.274 27.275 class VerifyRegionListsClosure : public HeapRegionClosure { 27.276 private: 27.277 - FreeRegionList* _free_list; 27.278 - OldRegionSet* _old_set; 27.279 - HumongousRegionSet* _humongous_set; 27.280 - uint _region_count; 27.281 + HeapRegionSet* _old_set; 27.282 + HeapRegionSet* _humongous_set; 27.283 + FreeRegionList* _free_list; 27.284 27.285 public: 27.286 - VerifyRegionListsClosure(OldRegionSet* old_set, 27.287 - HumongousRegionSet* humongous_set, 27.288 + HeapRegionSetCount _old_count; 27.289 + HeapRegionSetCount _humongous_count; 27.290 + HeapRegionSetCount _free_count; 27.291 + 27.292 + VerifyRegionListsClosure(HeapRegionSet* old_set, 27.293 + HeapRegionSet* humongous_set, 27.294 FreeRegionList* free_list) : 27.295 - _old_set(old_set), _humongous_set(humongous_set), 27.296 - _free_list(free_list), _region_count(0) { } 27.297 - 27.298 - uint region_count() { return _region_count; } 27.299 + _old_set(old_set), _humongous_set(humongous_set), _free_list(free_list), 27.300 + _old_count(), _humongous_count(), _free_count(){ } 27.301 27.302 bool doHeapRegion(HeapRegion* hr) { 27.303 - _region_count += 1; 27.304 - 27.305 if (hr->continuesHumongous()) { 27.306 return false; 27.307 } 27.308 @@ -6656,14 +6630,31 @@ 27.309 if (hr->is_young()) { 27.310 // TODO 27.311 } else if (hr->startsHumongous()) { 27.312 - _humongous_set->verify_next_region(hr); 27.313 + assert(hr->containing_set() == _humongous_set, err_msg("Heap region %u is starts humongous but not in humongous set.", hr->region_num())); 27.314 + _humongous_count.increment(1u, hr->capacity()); 27.315 } else if (hr->is_empty()) { 27.316 - _free_list->verify_next_region(hr); 27.317 + assert(hr->containing_set() == _free_list, err_msg("Heap region %u is empty but not on the free list.", hr->region_num())); 27.318 + _free_count.increment(1u, hr->capacity()); 27.319 } else { 27.320 - _old_set->verify_next_region(hr); 27.321 + assert(hr->containing_set() == _old_set, err_msg("Heap region %u is old but not in the old set.", hr->region_num())); 27.322 + _old_count.increment(1u, hr->capacity()); 27.323 } 27.324 return false; 27.325 } 27.326 + 27.327 + void verify_counts(HeapRegionSet* old_set, HeapRegionSet* humongous_set, FreeRegionList* free_list) { 27.328 + guarantee(old_set->length() == _old_count.length(), err_msg("Old set count mismatch. Expected %u, actual %u.", old_set->length(), _old_count.length())); 27.329 + guarantee(old_set->total_capacity_bytes() == _old_count.capacity(), err_msg("Old set capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT, 27.330 + old_set->total_capacity_bytes(), _old_count.capacity())); 27.331 + 27.332 + guarantee(humongous_set->length() == _humongous_count.length(), err_msg("Hum set count mismatch. Expected %u, actual %u.", humongous_set->length(), _humongous_count.length())); 27.333 + guarantee(humongous_set->total_capacity_bytes() == _humongous_count.capacity(), err_msg("Hum set capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT, 27.334 + humongous_set->total_capacity_bytes(), _humongous_count.capacity())); 27.335 + 27.336 + guarantee(free_list->length() == _free_count.length(), err_msg("Free list count mismatch. Expected %u, actual %u.", free_list->length(), _free_count.length())); 27.337 + guarantee(free_list->total_capacity_bytes() == _free_count.capacity(), err_msg("Free list capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT, 27.338 + free_list->total_capacity_bytes(), _free_count.capacity())); 27.339 + } 27.340 }; 27.341 27.342 HeapRegion* G1CollectedHeap::new_heap_region(uint hrs_index, 27.343 @@ -6679,16 +6670,14 @@ 27.344 assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */); 27.345 27.346 // First, check the explicit lists. 27.347 - _free_list.verify(); 27.348 + _free_list.verify_list(); 27.349 { 27.350 // Given that a concurrent operation might be adding regions to 27.351 // the secondary free list we have to take the lock before 27.352 // verifying it. 27.353 MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag); 27.354 - _secondary_free_list.verify(); 27.355 - } 27.356 - _old_set.verify(); 27.357 - _humongous_set.verify(); 27.358 + _secondary_free_list.verify_list(); 27.359 + } 27.360 27.361 // If a concurrent region freeing operation is in progress it will 27.362 // be difficult to correctly attributed any free regions we come 27.363 @@ -6711,16 +6700,10 @@ 27.364 27.365 // Finally, make sure that the region accounting in the lists is 27.366 // consistent with what we see in the heap. 27.367 - _old_set.verify_start(); 27.368 - _humongous_set.verify_start(); 27.369 - _free_list.verify_start(); 27.370 27.371 VerifyRegionListsClosure cl(&_old_set, &_humongous_set, &_free_list); 27.372 heap_region_iterate(&cl); 27.373 - 27.374 - _old_set.verify_end(); 27.375 - _humongous_set.verify_end(); 27.376 - _free_list.verify_end(); 27.377 + cl.verify_counts(&_old_set, &_humongous_set, &_free_list); 27.378 } 27.379 27.380 // Optimized nmethod scanning
28.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Mar 20 10:34:48 2014 -0700 28.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Mar 27 14:50:50 2014 -0700 28.3 @@ -34,7 +34,7 @@ 28.4 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" 28.5 #include "gc_implementation/g1/g1YCTypes.hpp" 28.6 #include "gc_implementation/g1/heapRegionSeq.hpp" 28.7 -#include "gc_implementation/g1/heapRegionSets.hpp" 28.8 +#include "gc_implementation/g1/heapRegionSet.hpp" 28.9 #include "gc_implementation/shared/hSpaceCounters.hpp" 28.10 #include "gc_implementation/shared/parGCAllocBuffer.hpp" 28.11 #include "memory/barrierSet.hpp" 28.12 @@ -243,18 +243,18 @@ 28.13 MemRegion _g1_committed; 28.14 28.15 // The master free list. It will satisfy all new region allocations. 28.16 - MasterFreeRegionList _free_list; 28.17 + FreeRegionList _free_list; 28.18 28.19 // The secondary free list which contains regions that have been 28.20 // freed up during the cleanup process. This will be appended to the 28.21 // master free list when appropriate. 28.22 - SecondaryFreeRegionList _secondary_free_list; 28.23 + FreeRegionList _secondary_free_list; 28.24 28.25 // It keeps track of the old regions. 28.26 - MasterOldRegionSet _old_set; 28.27 + HeapRegionSet _old_set; 28.28 28.29 // It keeps track of the humongous regions. 28.30 - MasterHumongousRegionSet _humongous_set; 28.31 + HeapRegionSet _humongous_set; 28.32 28.33 // The number of regions we could create by expansion. 28.34 uint _expansion_regions; 28.35 @@ -757,6 +757,26 @@ 28.36 28.37 G1HRPrinter* hr_printer() { return &_hr_printer; } 28.38 28.39 + // Frees a non-humongous region by initializing its contents and 28.40 + // adding it to the free list that's passed as a parameter (this is 28.41 + // usually a local list which will be appended to the master free 28.42 + // list later). The used bytes of freed regions are accumulated in 28.43 + // pre_used. If par is true, the region's RSet will not be freed 28.44 + // up. The assumption is that this will be done later. 28.45 + void free_region(HeapRegion* hr, 28.46 + FreeRegionList* free_list, 28.47 + bool par); 28.48 + 28.49 + // Frees a humongous region by collapsing it into individual regions 28.50 + // and calling free_region() for each of them. The freed regions 28.51 + // will be added to the free list that's passed as a parameter (this 28.52 + // is usually a local list which will be appended to the master free 28.53 + // list later). The used bytes of freed regions are accumulated in 28.54 + // pre_used. If par is true, the region's RSet will not be freed 28.55 + // up. The assumption is that this will be done later. 28.56 + void free_humongous_region(HeapRegion* hr, 28.57 + FreeRegionList* free_list, 28.58 + bool par); 28.59 protected: 28.60 28.61 // Shrink the garbage-first heap by at most the given size (in bytes!). 28.62 @@ -840,30 +860,6 @@ 28.63 // string table, and referents of reachable weak refs. 28.64 void g1_process_weak_roots(OopClosure* root_closure); 28.65 28.66 - // Frees a non-humongous region by initializing its contents and 28.67 - // adding it to the free list that's passed as a parameter (this is 28.68 - // usually a local list which will be appended to the master free 28.69 - // list later). The used bytes of freed regions are accumulated in 28.70 - // pre_used. If par is true, the region's RSet will not be freed 28.71 - // up. The assumption is that this will be done later. 28.72 - void free_region(HeapRegion* hr, 28.73 - size_t* pre_used, 28.74 - FreeRegionList* free_list, 28.75 - bool par); 28.76 - 28.77 - // Frees a humongous region by collapsing it into individual regions 28.78 - // and calling free_region() for each of them. The freed regions 28.79 - // will be added to the free list that's passed as a parameter (this 28.80 - // is usually a local list which will be appended to the master free 28.81 - // list later). The used bytes of freed regions are accumulated in 28.82 - // pre_used. If par is true, the region's RSet will not be freed 28.83 - // up. The assumption is that this will be done later. 28.84 - void free_humongous_region(HeapRegion* hr, 28.85 - size_t* pre_used, 28.86 - FreeRegionList* free_list, 28.87 - HumongousRegionSet* humongous_proxy_set, 28.88 - bool par); 28.89 - 28.90 // Notifies all the necessary spaces that the committed space has 28.91 // been updated (either expanded or shrunk). It should be called 28.92 // after _g1_storage is updated. 28.93 @@ -1242,10 +1238,6 @@ 28.94 bool is_on_master_free_list(HeapRegion* hr) { 28.95 return hr->containing_set() == &_free_list; 28.96 } 28.97 - 28.98 - bool is_in_humongous_set(HeapRegion* hr) { 28.99 - return hr->containing_set() == &_humongous_set; 28.100 - } 28.101 #endif // ASSERT 28.102 28.103 // Wrapper for the region list operations that can be called from 28.104 @@ -1298,27 +1290,9 @@ 28.105 // True iff an evacuation has failed in the most-recent collection. 28.106 bool evacuation_failed() { return _evacuation_failed; } 28.107 28.108 - // It will free a region if it has allocated objects in it that are 28.109 - // all dead. It calls either free_region() or 28.110 - // free_humongous_region() depending on the type of the region that 28.111 - // is passed to it. 28.112 - void free_region_if_empty(HeapRegion* hr, 28.113 - size_t* pre_used, 28.114 - FreeRegionList* free_list, 28.115 - OldRegionSet* old_proxy_set, 28.116 - HumongousRegionSet* humongous_proxy_set, 28.117 - HRRSCleanupTask* hrrs_cleanup_task, 28.118 - bool par); 28.119 - 28.120 - // It appends the free list to the master free list and updates the 28.121 - // master humongous list according to the contents of the proxy 28.122 - // list. It also adjusts the total used bytes according to pre_used 28.123 - // (if par is true, it will do so by taking the ParGCRareEvent_lock). 28.124 - void update_sets_after_freeing_regions(size_t pre_used, 28.125 - FreeRegionList* free_list, 28.126 - OldRegionSet* old_proxy_set, 28.127 - HumongousRegionSet* humongous_proxy_set, 28.128 - bool par); 28.129 + void remove_from_old_sets(const HeapRegionSetCount& old_regions_removed, const HeapRegionSetCount& humongous_regions_removed); 28.130 + void prepend_to_freelist(FreeRegionList* list); 28.131 + void decrement_summary_bytes(size_t bytes); 28.132 28.133 // Returns "TRUE" iff "p" points into the committed areas of the heap. 28.134 virtual bool is_in(const void* p) const; 28.135 @@ -1481,9 +1455,11 @@ 28.136 // Section on thread-local allocation buffers (TLABs) 28.137 // See CollectedHeap for semantics. 28.138 28.139 - virtual bool supports_tlab_allocation() const; 28.140 - virtual size_t tlab_capacity(Thread* thr) const; 28.141 - virtual size_t unsafe_max_tlab_alloc(Thread* thr) const; 28.142 + bool supports_tlab_allocation() const; 28.143 + size_t tlab_capacity(Thread* ignored) const; 28.144 + size_t tlab_used(Thread* ignored) const; 28.145 + size_t max_tlab_size() const; 28.146 + size_t unsafe_max_tlab_alloc(Thread* ignored) const; 28.147 28.148 // Can a compiler initialize a new object without store barriers? 28.149 // This permission only extends from the creation of a new object 28.150 @@ -1568,7 +1544,7 @@ 28.151 void set_region_short_lived_locked(HeapRegion* hr); 28.152 // add appropriate methods for any other surv rate groups 28.153 28.154 - YoungList* young_list() { return _young_list; } 28.155 + YoungList* young_list() const { return _young_list; } 28.156 28.157 // debugging 28.158 bool check_young_list_well_formed() {
29.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Thu Mar 20 10:34:48 2014 -0700 29.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Thu Mar 27 14:50:50 2014 -0700 29.3 @@ -30,6 +30,7 @@ 29.4 #include "gc_implementation/g1/g1AllocRegion.inline.hpp" 29.5 #include "gc_implementation/g1/g1CollectorPolicy.hpp" 29.6 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" 29.7 +#include "gc_implementation/g1/heapRegionSet.inline.hpp" 29.8 #include "gc_implementation/g1/heapRegionSeq.inline.hpp" 29.9 #include "utilities/taskqueue.hpp" 29.10
30.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu Mar 20 10:34:48 2014 -0700 30.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu Mar 27 14:50:50 2014 -0700 30.3 @@ -820,6 +820,8 @@ 30.4 // do that for any other surv rate groups 30.5 } 30.6 30.7 + size_t young_list_target_length() const { return _young_list_target_length; } 30.8 + 30.9 bool is_young_list_full() { 30.10 uint young_list_length = _g1->young_list()->length(); 30.11 uint young_list_target_length = _young_list_target_length;
31.1 --- a/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Thu Mar 20 10:34:48 2014 -0700 31.2 +++ b/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Thu Mar 27 14:50:50 2014 -0700 31.3 @@ -196,17 +196,19 @@ 31.4 G1CollectedHeap* _g1h; 31.5 ModRefBarrierSet* _mrbs; 31.6 CompactPoint _cp; 31.7 - HumongousRegionSet _humongous_proxy_set; 31.8 + HeapRegionSetCount _humongous_regions_removed; 31.9 31.10 void free_humongous_region(HeapRegion* hr) { 31.11 HeapWord* end = hr->end(); 31.12 - size_t dummy_pre_used; 31.13 FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep"); 31.14 31.15 assert(hr->startsHumongous(), 31.16 "Only the start of a humongous region should be freed."); 31.17 - _g1h->free_humongous_region(hr, &dummy_pre_used, &dummy_free_list, 31.18 - &_humongous_proxy_set, false /* par */); 31.19 + 31.20 + hr->set_containing_set(NULL); 31.21 + _humongous_regions_removed.increment(1u, hr->capacity()); 31.22 + 31.23 + _g1h->free_humongous_region(hr, &dummy_free_list, false /* par */); 31.24 hr->prepare_for_compaction(&_cp); 31.25 // Also clear the part of the card table that will be unused after 31.26 // compaction. 31.27 @@ -219,16 +221,13 @@ 31.28 : _g1h(G1CollectedHeap::heap()), 31.29 _mrbs(_g1h->g1_barrier_set()), 31.30 _cp(NULL, cs, cs->initialize_threshold()), 31.31 - _humongous_proxy_set("G1MarkSweep Humongous Proxy Set") { } 31.32 + _humongous_regions_removed() { } 31.33 31.34 void update_sets() { 31.35 // We'll recalculate total used bytes and recreate the free list 31.36 // at the end of the GC, so no point in updating those values here. 31.37 - _g1h->update_sets_after_freeing_regions(0, /* pre_used */ 31.38 - NULL, /* free_list */ 31.39 - NULL, /* old_proxy_set */ 31.40 - &_humongous_proxy_set, 31.41 - false /* par */); 31.42 + HeapRegionSetCount empty_set; 31.43 + _g1h->remove_from_old_sets(empty_set, _humongous_regions_removed); 31.44 } 31.45 31.46 bool doHeapRegion(HeapRegion* hr) {
32.1 --- a/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp Thu Mar 20 10:34:48 2014 -0700 32.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp Thu Mar 27 14:50:50 2014 -0700 32.3 @@ -25,7 +25,7 @@ 32.4 #include "precompiled.hpp" 32.5 #include "gc_implementation/g1/heapRegion.hpp" 32.6 #include "gc_implementation/g1/heapRegionSeq.inline.hpp" 32.7 -#include "gc_implementation/g1/heapRegionSets.hpp" 32.8 +#include "gc_implementation/g1/heapRegionSet.hpp" 32.9 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" 32.10 #include "memory/allocation.hpp" 32.11
33.1 --- a/src/share/vm/gc_implementation/g1/heapRegionSet.cpp Thu Mar 20 10:34:48 2014 -0700 33.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionSet.cpp Thu Mar 27 14:50:50 2014 -0700 33.3 @@ -23,171 +23,60 @@ 33.4 */ 33.5 33.6 #include "precompiled.hpp" 33.7 +#include "gc_implementation/g1/heapRegionRemSet.hpp" 33.8 #include "gc_implementation/g1/heapRegionSet.inline.hpp" 33.9 33.10 -uint HeapRegionSetBase::_unrealistically_long_length = 0; 33.11 -HRSPhase HeapRegionSetBase::_phase = HRSPhaseNone; 33.12 - 33.13 -//////////////////// HeapRegionSetBase //////////////////// 33.14 - 33.15 -void HeapRegionSetBase::set_unrealistically_long_length(uint len) { 33.16 - guarantee(_unrealistically_long_length == 0, "should only be set once"); 33.17 - _unrealistically_long_length = len; 33.18 -} 33.19 +uint FreeRegionList::_unrealistically_long_length = 0; 33.20 33.21 void HeapRegionSetBase::fill_in_ext_msg(hrs_ext_msg* msg, const char* message) { 33.22 - msg->append("[%s] %s ln: %u rn: %u cy: "SIZE_FORMAT" ud: "SIZE_FORMAT, 33.23 - name(), message, length(), region_num(), 33.24 - total_capacity_bytes(), total_used_bytes()); 33.25 + msg->append("[%s] %s ln: %u cy: "SIZE_FORMAT, 33.26 + name(), message, length(), total_capacity_bytes()); 33.27 fill_in_ext_msg_extra(msg); 33.28 } 33.29 33.30 -bool HeapRegionSetBase::verify_region(HeapRegion* hr, 33.31 - HeapRegionSetBase* expected_containing_set) { 33.32 - const char* error_message = NULL; 33.33 - 33.34 - if (!regions_humongous()) { 33.35 - if (hr->isHumongous()) { 33.36 - error_message = "the region should not be humongous"; 33.37 - } 33.38 - } else { 33.39 - if (!hr->isHumongous() || !hr->startsHumongous()) { 33.40 - error_message = "the region should be 'starts humongous'"; 33.41 - } 33.42 - } 33.43 - 33.44 - if (!regions_empty()) { 33.45 - if (hr->is_empty()) { 33.46 - error_message = "the region should not be empty"; 33.47 - } 33.48 - } else { 33.49 - if (!hr->is_empty()) { 33.50 - error_message = "the region should be empty"; 33.51 - } 33.52 - } 33.53 - 33.54 -#ifdef ASSERT 33.55 - // The _containing_set field is only available when ASSERT is defined. 33.56 - if (hr->containing_set() != expected_containing_set) { 33.57 - error_message = "inconsistent containing set found"; 33.58 - } 33.59 -#endif // ASSERT 33.60 - 33.61 - const char* extra_error_message = verify_region_extra(hr); 33.62 - if (extra_error_message != NULL) { 33.63 - error_message = extra_error_message; 33.64 - } 33.65 - 33.66 - if (error_message != NULL) { 33.67 - outputStream* out = tty; 33.68 - out->cr(); 33.69 - out->print_cr("## [%s] %s", name(), error_message); 33.70 - out->print_cr("## Offending Region: "PTR_FORMAT, hr); 33.71 - out->print_cr(" "HR_FORMAT, HR_FORMAT_PARAMS(hr)); 33.72 -#ifdef ASSERT 33.73 - out->print_cr(" containing set: "PTR_FORMAT, hr->containing_set()); 33.74 -#endif // ASSERT 33.75 - out->print_cr("## Offending Region Set: "PTR_FORMAT, this); 33.76 - print_on(out); 33.77 - return false; 33.78 - } else { 33.79 - return true; 33.80 - } 33.81 +#ifndef PRODUCT 33.82 +void HeapRegionSetBase::verify_region(HeapRegion* hr) { 33.83 + assert(hr->containing_set() == this, err_msg("Inconsistent containing set for %u", hr->hrs_index())); 33.84 + assert(!hr->is_young(), err_msg("Adding young region %u", hr->hrs_index())); // currently we don't use these sets for young regions 33.85 + assert(hr->isHumongous() == regions_humongous(), err_msg("Wrong humongous state for region %u and set %s", hr->hrs_index(), name())); 33.86 + assert(hr->is_empty() == regions_empty(), err_msg("Wrong empty state for region %u and set %s", hr->hrs_index(), name())); 33.87 + assert(hr->rem_set()->verify_ready_for_par_iteration(), err_msg("Wrong iteration state %u", hr->hrs_index())); 33.88 } 33.89 +#endif 33.90 33.91 void HeapRegionSetBase::verify() { 33.92 // It's important that we also observe the MT safety protocol even 33.93 // for the verification calls. If we do verification without the 33.94 // appropriate locks and the set changes underneath our feet 33.95 // verification might fail and send us on a wild goose chase. 33.96 - hrs_assert_mt_safety_ok(this); 33.97 + check_mt_safety(); 33.98 33.99 - guarantee(( is_empty() && length() == 0 && region_num() == 0 && 33.100 - total_used_bytes() == 0 && total_capacity_bytes() == 0) || 33.101 - (!is_empty() && length() >= 0 && region_num() >= 0 && 33.102 - total_used_bytes() >= 0 && total_capacity_bytes() >= 0), 33.103 - hrs_ext_msg(this, "invariant")); 33.104 - 33.105 - guarantee((!regions_humongous() && region_num() == length()) || 33.106 - ( regions_humongous() && region_num() >= length()), 33.107 - hrs_ext_msg(this, "invariant")); 33.108 - 33.109 - guarantee(!regions_empty() || total_used_bytes() == 0, 33.110 - hrs_ext_msg(this, "invariant")); 33.111 - 33.112 - guarantee(total_used_bytes() <= total_capacity_bytes(), 33.113 + guarantee(( is_empty() && length() == 0 && total_capacity_bytes() == 0) || 33.114 + (!is_empty() && length() >= 0 && total_capacity_bytes() >= 0), 33.115 hrs_ext_msg(this, "invariant")); 33.116 } 33.117 33.118 void HeapRegionSetBase::verify_start() { 33.119 // See comment in verify() about MT safety and verification. 33.120 - hrs_assert_mt_safety_ok(this); 33.121 + check_mt_safety(); 33.122 assert(!_verify_in_progress, 33.123 hrs_ext_msg(this, "verification should not be in progress")); 33.124 33.125 // Do the basic verification first before we do the checks over the regions. 33.126 HeapRegionSetBase::verify(); 33.127 33.128 - _calc_length = 0; 33.129 - _calc_region_num = 0; 33.130 - _calc_total_capacity_bytes = 0; 33.131 - _calc_total_used_bytes = 0; 33.132 _verify_in_progress = true; 33.133 } 33.134 33.135 -void HeapRegionSetBase::verify_next_region(HeapRegion* hr) { 33.136 - // See comment in verify() about MT safety and verification. 33.137 - hrs_assert_mt_safety_ok(this); 33.138 - assert(_verify_in_progress, 33.139 - hrs_ext_msg(this, "verification should be in progress")); 33.140 - 33.141 - guarantee(verify_region(hr, this), hrs_ext_msg(this, "region verification")); 33.142 - 33.143 - _calc_length += 1; 33.144 - _calc_region_num += hr->region_num(); 33.145 - _calc_total_capacity_bytes += hr->capacity(); 33.146 - _calc_total_used_bytes += hr->used(); 33.147 -} 33.148 - 33.149 void HeapRegionSetBase::verify_end() { 33.150 // See comment in verify() about MT safety and verification. 33.151 - hrs_assert_mt_safety_ok(this); 33.152 + check_mt_safety(); 33.153 assert(_verify_in_progress, 33.154 hrs_ext_msg(this, "verification should be in progress")); 33.155 33.156 - guarantee(length() == _calc_length, 33.157 - hrs_err_msg("[%s] length: %u should be == calc length: %u", 33.158 - name(), length(), _calc_length)); 33.159 - 33.160 - guarantee(region_num() == _calc_region_num, 33.161 - hrs_err_msg("[%s] region num: %u should be == calc region num: %u", 33.162 - name(), region_num(), _calc_region_num)); 33.163 - 33.164 - guarantee(total_capacity_bytes() == _calc_total_capacity_bytes, 33.165 - hrs_err_msg("[%s] capacity bytes: "SIZE_FORMAT" should be == " 33.166 - "calc capacity bytes: "SIZE_FORMAT, 33.167 - name(), 33.168 - total_capacity_bytes(), _calc_total_capacity_bytes)); 33.169 - 33.170 - guarantee(total_used_bytes() == _calc_total_used_bytes, 33.171 - hrs_err_msg("[%s] used bytes: "SIZE_FORMAT" should be == " 33.172 - "calc used bytes: "SIZE_FORMAT, 33.173 - name(), total_used_bytes(), _calc_total_used_bytes)); 33.174 - 33.175 _verify_in_progress = false; 33.176 } 33.177 33.178 -void HeapRegionSetBase::clear_phase() { 33.179 - assert(_phase != HRSPhaseNone, "pre-condition"); 33.180 - _phase = HRSPhaseNone; 33.181 -} 33.182 - 33.183 -void HeapRegionSetBase::set_phase(HRSPhase phase) { 33.184 - assert(_phase == HRSPhaseNone, "pre-condition"); 33.185 - assert(phase != HRSPhaseNone, "pre-condition"); 33.186 - _phase = phase; 33.187 -} 33.188 - 33.189 void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) { 33.190 out->cr(); 33.191 out->print_cr("Set: %s ("PTR_FORMAT")", name(), this); 33.192 @@ -196,76 +85,38 @@ 33.193 out->print_cr(" empty : %s", BOOL_TO_STR(regions_empty())); 33.194 out->print_cr(" Attributes"); 33.195 out->print_cr(" length : %14u", length()); 33.196 - out->print_cr(" region num : %14u", region_num()); 33.197 out->print_cr(" total capacity : "SIZE_FORMAT_W(14)" bytes", 33.198 total_capacity_bytes()); 33.199 - out->print_cr(" total used : "SIZE_FORMAT_W(14)" bytes", 33.200 - total_used_bytes()); 33.201 } 33.202 33.203 -void HeapRegionSetBase::clear() { 33.204 - _length = 0; 33.205 - _region_num = 0; 33.206 - _total_used_bytes = 0; 33.207 +HeapRegionSetBase::HeapRegionSetBase(const char* name, bool humongous, bool empty, HRSMtSafeChecker* mt_safety_checker) 33.208 + : _name(name), _verify_in_progress(false), 33.209 + _is_humongous(humongous), _is_empty(empty), _mt_safety_checker(mt_safety_checker), 33.210 + _count() 33.211 +{ } 33.212 + 33.213 +void FreeRegionList::set_unrealistically_long_length(uint len) { 33.214 + guarantee(_unrealistically_long_length == 0, "should only be set once"); 33.215 + _unrealistically_long_length = len; 33.216 } 33.217 33.218 -HeapRegionSetBase::HeapRegionSetBase(const char* name) 33.219 - : _name(name), _verify_in_progress(false), 33.220 - _calc_length(0), _calc_region_num(0), 33.221 - _calc_total_capacity_bytes(0), _calc_total_used_bytes(0) { } 33.222 - 33.223 -//////////////////// HeapRegionSet //////////////////// 33.224 - 33.225 -void HeapRegionSet::update_from_proxy(HeapRegionSet* proxy_set) { 33.226 - hrs_assert_mt_safety_ok(this); 33.227 - hrs_assert_mt_safety_ok(proxy_set); 33.228 - hrs_assert_sets_match(this, proxy_set); 33.229 - 33.230 - verify_optional(); 33.231 - proxy_set->verify_optional(); 33.232 - 33.233 - if (proxy_set->is_empty()) return; 33.234 - 33.235 - assert(proxy_set->length() <= _length, 33.236 - hrs_err_msg("[%s] proxy set length: %u should be <= length: %u", 33.237 - name(), proxy_set->length(), _length)); 33.238 - _length -= proxy_set->length(); 33.239 - 33.240 - assert(proxy_set->region_num() <= _region_num, 33.241 - hrs_err_msg("[%s] proxy set region num: %u should be <= region num: %u", 33.242 - name(), proxy_set->region_num(), _region_num)); 33.243 - _region_num -= proxy_set->region_num(); 33.244 - 33.245 - assert(proxy_set->total_used_bytes() <= _total_used_bytes, 33.246 - hrs_err_msg("[%s] proxy set used bytes: "SIZE_FORMAT" " 33.247 - "should be <= used bytes: "SIZE_FORMAT, 33.248 - name(), proxy_set->total_used_bytes(), 33.249 - _total_used_bytes)); 33.250 - _total_used_bytes -= proxy_set->total_used_bytes(); 33.251 - 33.252 - proxy_set->clear(); 33.253 - 33.254 - verify_optional(); 33.255 - proxy_set->verify_optional(); 33.256 -} 33.257 - 33.258 -//////////////////// HeapRegionLinkedList //////////////////// 33.259 - 33.260 -void HeapRegionLinkedList::fill_in_ext_msg_extra(hrs_ext_msg* msg) { 33.261 +void FreeRegionList::fill_in_ext_msg_extra(hrs_ext_msg* msg) { 33.262 msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail()); 33.263 } 33.264 33.265 -void HeapRegionLinkedList::add_as_head(HeapRegionLinkedList* from_list) { 33.266 - hrs_assert_mt_safety_ok(this); 33.267 - hrs_assert_mt_safety_ok(from_list); 33.268 +void FreeRegionList::add_as_head_or_tail(FreeRegionList* from_list, bool as_head) { 33.269 + check_mt_safety(); 33.270 + from_list->check_mt_safety(); 33.271 33.272 verify_optional(); 33.273 from_list->verify_optional(); 33.274 33.275 - if (from_list->is_empty()) return; 33.276 + if (from_list->is_empty()) { 33.277 + return; 33.278 + } 33.279 33.280 #ifdef ASSERT 33.281 - HeapRegionLinkedListIterator iter(from_list); 33.282 + FreeRegionListIterator iter(from_list); 33.283 while (iter.more_available()) { 33.284 HeapRegion* hr = iter.get_next(); 33.285 // In set_containing_set() we check that we either set the value 33.286 @@ -276,70 +127,43 @@ 33.287 } 33.288 #endif // ASSERT 33.289 33.290 - if (_head != NULL) { 33.291 - assert(length() > 0 && _tail != NULL, hrs_ext_msg(this, "invariant")); 33.292 - from_list->_tail->set_next(_head); 33.293 + if (_head == NULL) { 33.294 + assert(length() == 0 && _tail == NULL, hrs_ext_msg(this, "invariant")); 33.295 + _head = from_list->_head; 33.296 + _tail = from_list->_tail; 33.297 } else { 33.298 - assert(length() == 0 && _tail == NULL, hrs_ext_msg(this, "invariant")); 33.299 - _tail = from_list->_tail; 33.300 + assert(length() > 0 && _tail != NULL, hrs_ext_msg(this, "invariant")); 33.301 + if (as_head) { 33.302 + from_list->_tail->set_next(_head); 33.303 + _head = from_list->_head; 33.304 + } else { 33.305 + _tail->set_next(from_list->_head); 33.306 + _tail = from_list->_tail; 33.307 + } 33.308 } 33.309 - _head = from_list->_head; 33.310 33.311 - _length += from_list->length(); 33.312 - _region_num += from_list->region_num(); 33.313 - _total_used_bytes += from_list->total_used_bytes(); 33.314 + _count.increment(from_list->length(), from_list->total_capacity_bytes()); 33.315 from_list->clear(); 33.316 33.317 verify_optional(); 33.318 from_list->verify_optional(); 33.319 } 33.320 33.321 -void HeapRegionLinkedList::add_as_tail(HeapRegionLinkedList* from_list) { 33.322 - hrs_assert_mt_safety_ok(this); 33.323 - hrs_assert_mt_safety_ok(from_list); 33.324 - 33.325 - verify_optional(); 33.326 - from_list->verify_optional(); 33.327 - 33.328 - if (from_list->is_empty()) return; 33.329 - 33.330 -#ifdef ASSERT 33.331 - HeapRegionLinkedListIterator iter(from_list); 33.332 - while (iter.more_available()) { 33.333 - HeapRegion* hr = iter.get_next(); 33.334 - // In set_containing_set() we check that we either set the value 33.335 - // from NULL to non-NULL or vice versa to catch bugs. So, we have 33.336 - // to NULL it first before setting it to the value. 33.337 - hr->set_containing_set(NULL); 33.338 - hr->set_containing_set(this); 33.339 - } 33.340 -#endif // ASSERT 33.341 - 33.342 - if (_tail != NULL) { 33.343 - assert(length() > 0 && _head != NULL, hrs_ext_msg(this, "invariant")); 33.344 - _tail->set_next(from_list->_head); 33.345 - } else { 33.346 - assert(length() == 0 && _head == NULL, hrs_ext_msg(this, "invariant")); 33.347 - _head = from_list->_head; 33.348 - } 33.349 - _tail = from_list->_tail; 33.350 - 33.351 - _length += from_list->length(); 33.352 - _region_num += from_list->region_num(); 33.353 - _total_used_bytes += from_list->total_used_bytes(); 33.354 - from_list->clear(); 33.355 - 33.356 - verify_optional(); 33.357 - from_list->verify_optional(); 33.358 +void FreeRegionList::add_as_head(FreeRegionList* from_list) { 33.359 + add_as_head_or_tail(from_list, true /* as_head */); 33.360 } 33.361 33.362 -void HeapRegionLinkedList::remove_all() { 33.363 - hrs_assert_mt_safety_ok(this); 33.364 +void FreeRegionList::add_as_tail(FreeRegionList* from_list) { 33.365 + add_as_head_or_tail(from_list, false /* as_head */); 33.366 +} 33.367 + 33.368 +void FreeRegionList::remove_all() { 33.369 + check_mt_safety(); 33.370 verify_optional(); 33.371 33.372 HeapRegion* curr = _head; 33.373 while (curr != NULL) { 33.374 - hrs_assert_region_ok(this, curr, this); 33.375 + verify_region(curr); 33.376 33.377 HeapRegion* next = curr->next(); 33.378 curr->set_next(NULL); 33.379 @@ -351,8 +175,8 @@ 33.380 verify_optional(); 33.381 } 33.382 33.383 -void HeapRegionLinkedList::remove_all_pending(uint target_count) { 33.384 - hrs_assert_mt_safety_ok(this); 33.385 +void FreeRegionList::remove_all_pending(uint target_count) { 33.386 + check_mt_safety(); 33.387 assert(target_count > 1, hrs_ext_msg(this, "pre-condition")); 33.388 assert(!is_empty(), hrs_ext_msg(this, "pre-condition")); 33.389 33.390 @@ -363,7 +187,7 @@ 33.391 HeapRegion* prev = NULL; 33.392 uint count = 0; 33.393 while (curr != NULL) { 33.394 - hrs_assert_region_ok(this, curr, this); 33.395 + verify_region(curr); 33.396 HeapRegion* next = curr->next(); 33.397 33.398 if (curr->pending_removal()) { 33.399 @@ -387,7 +211,7 @@ 33.400 } 33.401 33.402 curr->set_next(NULL); 33.403 - remove_internal(curr); 33.404 + remove(curr); 33.405 curr->set_pending_removal(false); 33.406 33.407 count += 1; 33.408 @@ -414,46 +238,26 @@ 33.409 verify_optional(); 33.410 } 33.411 33.412 -void HeapRegionLinkedList::verify() { 33.413 +void FreeRegionList::verify() { 33.414 // See comment in HeapRegionSetBase::verify() about MT safety and 33.415 // verification. 33.416 - hrs_assert_mt_safety_ok(this); 33.417 + check_mt_safety(); 33.418 33.419 // This will also do the basic verification too. 33.420 verify_start(); 33.421 33.422 - HeapRegion* curr = _head; 33.423 - HeapRegion* prev1 = NULL; 33.424 - HeapRegion* prev0 = NULL; 33.425 - uint count = 0; 33.426 - while (curr != NULL) { 33.427 - verify_next_region(curr); 33.428 - 33.429 - count += 1; 33.430 - guarantee(count < _unrealistically_long_length, 33.431 - hrs_err_msg("[%s] the calculated length: %u " 33.432 - "seems very long, is there maybe a cycle? " 33.433 - "curr: "PTR_FORMAT" prev0: "PTR_FORMAT" " 33.434 - "prev1: "PTR_FORMAT" length: %u", 33.435 - name(), count, curr, prev0, prev1, length())); 33.436 - 33.437 - prev1 = prev0; 33.438 - prev0 = curr; 33.439 - curr = curr->next(); 33.440 - } 33.441 - 33.442 - guarantee(_tail == prev0, hrs_ext_msg(this, "post-condition")); 33.443 + verify_list(); 33.444 33.445 verify_end(); 33.446 } 33.447 33.448 -void HeapRegionLinkedList::clear() { 33.449 - HeapRegionSetBase::clear(); 33.450 +void FreeRegionList::clear() { 33.451 + _count = HeapRegionSetCount(); 33.452 _head = NULL; 33.453 _tail = NULL; 33.454 } 33.455 33.456 -void HeapRegionLinkedList::print_on(outputStream* out, bool print_contents) { 33.457 +void FreeRegionList::print_on(outputStream* out, bool print_contents) { 33.458 HeapRegionSetBase::print_on(out, print_contents); 33.459 out->print_cr(" Linking"); 33.460 out->print_cr(" head : "PTR_FORMAT, _head); 33.461 @@ -461,10 +265,115 @@ 33.462 33.463 if (print_contents) { 33.464 out->print_cr(" Contents"); 33.465 - HeapRegionLinkedListIterator iter(this); 33.466 + FreeRegionListIterator iter(this); 33.467 while (iter.more_available()) { 33.468 HeapRegion* hr = iter.get_next(); 33.469 hr->print_on(out); 33.470 } 33.471 } 33.472 } 33.473 + 33.474 +void FreeRegionList::verify_list() { 33.475 + HeapRegion* curr = head(); 33.476 + HeapRegion* prev1 = NULL; 33.477 + HeapRegion* prev0 = NULL; 33.478 + uint count = 0; 33.479 + size_t capacity = 0; 33.480 + while (curr != NULL) { 33.481 + verify_region(curr); 33.482 + 33.483 + count++; 33.484 + guarantee(count < _unrealistically_long_length, 33.485 + hrs_err_msg("[%s] the calculated length: %u seems very long, is there maybe a cycle? curr: "PTR_FORMAT" prev0: "PTR_FORMAT" " "prev1: "PTR_FORMAT" length: %u", name(), count, curr, prev0, prev1, length())); 33.486 + 33.487 + capacity += curr->capacity(); 33.488 + 33.489 + prev1 = prev0; 33.490 + prev0 = curr; 33.491 + curr = curr->next(); 33.492 + } 33.493 + 33.494 + guarantee(tail() == prev0, err_msg("Expected %s to end with %u but it ended with %u.", name(), tail()->hrs_index(), prev0->hrs_index())); 33.495 + 33.496 + guarantee(length() == count, err_msg("%s count mismatch. Expected %u, actual %u.", name(), length(), count)); 33.497 + guarantee(total_capacity_bytes() == capacity, err_msg("%s capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT, 33.498 + name(), total_capacity_bytes(), capacity)); 33.499 +} 33.500 + 33.501 +// Note on the check_mt_safety() methods below: 33.502 +// 33.503 +// Verification of the "master" heap region sets / lists that are 33.504 +// maintained by G1CollectedHeap is always done during a STW pause and 33.505 +// by the VM thread at the start / end of the pause. The standard 33.506 +// verification methods all assert check_mt_safety(). This is 33.507 +// important as it ensures that verification is done without 33.508 +// concurrent updates taking place at the same time. It follows, that, 33.509 +// for the "master" heap region sets / lists, the check_mt_safety() 33.510 +// method should include the VM thread / STW case. 33.511 + 33.512 +void MasterFreeRegionListMtSafeChecker::check() { 33.513 + // Master Free List MT safety protocol: 33.514 + // (a) If we're at a safepoint, operations on the master free list 33.515 + // should be invoked by either the VM thread (which will serialize 33.516 + // them) or by the GC workers while holding the 33.517 + // FreeList_lock. 33.518 + // (b) If we're not at a safepoint, operations on the master free 33.519 + // list should be invoked while holding the Heap_lock. 33.520 + 33.521 + if (SafepointSynchronize::is_at_safepoint()) { 33.522 + guarantee(Thread::current()->is_VM_thread() || 33.523 + FreeList_lock->owned_by_self(), "master free list MT safety protocol at a safepoint"); 33.524 + } else { 33.525 + guarantee(Heap_lock->owned_by_self(), "master free list MT safety protocol outside a safepoint"); 33.526 + } 33.527 +} 33.528 + 33.529 +void SecondaryFreeRegionListMtSafeChecker::check() { 33.530 + // Secondary Free List MT safety protocol: 33.531 + // Operations on the secondary free list should always be invoked 33.532 + // while holding the SecondaryFreeList_lock. 33.533 + 33.534 + guarantee(SecondaryFreeList_lock->owned_by_self(), "secondary free list MT safety protocol"); 33.535 +} 33.536 + 33.537 +void OldRegionSetMtSafeChecker::check() { 33.538 + // Master Old Set MT safety protocol: 33.539 + // (a) If we're at a safepoint, operations on the master old set 33.540 + // should be invoked: 33.541 + // - by the VM thread (which will serialize them), or 33.542 + // - by the GC workers while holding the FreeList_lock, if we're 33.543 + // at a safepoint for an evacuation pause (this lock is taken 33.544 + // anyway when an GC alloc region is retired so that a new one 33.545 + // is allocated from the free list), or 33.546 + // - by the GC workers while holding the OldSets_lock, if we're at a 33.547 + // safepoint for a cleanup pause. 33.548 + // (b) If we're not at a safepoint, operations on the master old set 33.549 + // should be invoked while holding the Heap_lock. 33.550 + 33.551 + if (SafepointSynchronize::is_at_safepoint()) { 33.552 + guarantee(Thread::current()->is_VM_thread() 33.553 + || FreeList_lock->owned_by_self() || OldSets_lock->owned_by_self(), 33.554 + "master old set MT safety protocol at a safepoint"); 33.555 + } else { 33.556 + guarantee(Heap_lock->owned_by_self(), "master old set MT safety protocol outside a safepoint"); 33.557 + } 33.558 +} 33.559 + 33.560 +void HumongousRegionSetMtSafeChecker::check() { 33.561 + // Humongous Set MT safety protocol: 33.562 + // (a) If we're at a safepoint, operations on the master humongous 33.563 + // set should be invoked by either the VM thread (which will 33.564 + // serialize them) or by the GC workers while holding the 33.565 + // OldSets_lock. 33.566 + // (b) If we're not at a safepoint, operations on the master 33.567 + // humongous set should be invoked while holding the Heap_lock. 33.568 + 33.569 + if (SafepointSynchronize::is_at_safepoint()) { 33.570 + guarantee(Thread::current()->is_VM_thread() || 33.571 + OldSets_lock->owned_by_self(), 33.572 + "master humongous set MT safety protocol at a safepoint"); 33.573 + } else { 33.574 + guarantee(Heap_lock->owned_by_self(), 33.575 + "master humongous set MT safety protocol outside a safepoint"); 33.576 + } 33.577 +}
34.1 --- a/src/share/vm/gc_implementation/g1/heapRegionSet.hpp Thu Mar 20 10:34:48 2014 -0700 34.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionSet.hpp Thu Mar 27 14:50:50 2014 -0700 34.3 @@ -38,135 +38,108 @@ 34.4 #define HEAP_REGION_SET_FORCE_VERIFY defined(ASSERT) 34.5 #endif // HEAP_REGION_SET_FORCE_VERIFY 34.6 34.7 -//////////////////// HeapRegionSetBase //////////////////// 34.8 +class hrs_ext_msg; 34.9 + 34.10 +class HRSMtSafeChecker : public CHeapObj<mtGC> { 34.11 +public: 34.12 + virtual void check() = 0; 34.13 +}; 34.14 + 34.15 +class MasterFreeRegionListMtSafeChecker : public HRSMtSafeChecker { public: void check(); }; 34.16 +class SecondaryFreeRegionListMtSafeChecker : public HRSMtSafeChecker { public: void check(); }; 34.17 +class HumongousRegionSetMtSafeChecker : public HRSMtSafeChecker { public: void check(); }; 34.18 +class OldRegionSetMtSafeChecker : public HRSMtSafeChecker { public: void check(); }; 34.19 + 34.20 +class HeapRegionSetCount VALUE_OBJ_CLASS_SPEC { 34.21 + friend class VMStructs; 34.22 + uint _length; 34.23 + size_t _capacity; 34.24 + 34.25 +public: 34.26 + HeapRegionSetCount() : _length(0), _capacity(0) { } 34.27 + 34.28 + const uint length() const { return _length; } 34.29 + const size_t capacity() const { return _capacity; } 34.30 + 34.31 + void increment(uint length_to_add, size_t capacity_to_add) { 34.32 + _length += length_to_add; 34.33 + _capacity += capacity_to_add; 34.34 + } 34.35 + 34.36 + void decrement(const uint length_to_remove, const size_t capacity_to_remove) { 34.37 + _length -= length_to_remove; 34.38 + _capacity -= capacity_to_remove; 34.39 + } 34.40 +}; 34.41 34.42 // Base class for all the classes that represent heap region sets. It 34.43 // contains the basic attributes that each set needs to maintain 34.44 // (e.g., length, region num, used bytes sum) plus any shared 34.45 // functionality (e.g., verification). 34.46 34.47 -class hrs_ext_msg; 34.48 - 34.49 -typedef enum { 34.50 - HRSPhaseNone, 34.51 - HRSPhaseEvacuation, 34.52 - HRSPhaseCleanup, 34.53 - HRSPhaseFullGC 34.54 -} HRSPhase; 34.55 - 34.56 -class HRSPhaseSetter; 34.57 - 34.58 class HeapRegionSetBase VALUE_OBJ_CLASS_SPEC { 34.59 - friend class hrs_ext_msg; 34.60 - friend class HRSPhaseSetter; 34.61 friend class VMStructs; 34.62 +private: 34.63 + bool _is_humongous; 34.64 + bool _is_empty; 34.65 + HRSMtSafeChecker* _mt_safety_checker; 34.66 34.67 protected: 34.68 - static uint _unrealistically_long_length; 34.69 - 34.70 // The number of regions added to the set. If the set contains 34.71 // only humongous regions, this reflects only 'starts humongous' 34.72 // regions and does not include 'continues humongous' ones. 34.73 - uint _length; 34.74 - 34.75 - // The total number of regions represented by the set. If the set 34.76 - // does not contain humongous regions, this should be the same as 34.77 - // _length. If the set contains only humongous regions, this will 34.78 - // include the 'continues humongous' regions. 34.79 - uint _region_num; 34.80 - 34.81 - // We don't keep track of the total capacity explicitly, we instead 34.82 - // recalculate it based on _region_num and the heap region size. 34.83 - 34.84 - // The sum of used bytes in the all the regions in the set. 34.85 - size_t _total_used_bytes; 34.86 + HeapRegionSetCount _count; 34.87 34.88 const char* _name; 34.89 34.90 - bool _verify_in_progress; 34.91 - uint _calc_length; 34.92 - uint _calc_region_num; 34.93 - size_t _calc_total_capacity_bytes; 34.94 - size_t _calc_total_used_bytes; 34.95 - 34.96 - // This is here so that it can be used in the subclasses to assert 34.97 - // something different depending on which phase the GC is in. This 34.98 - // can be particularly helpful in the check_mt_safety() methods. 34.99 - static HRSPhase _phase; 34.100 - 34.101 - // Only used by HRSPhaseSetter. 34.102 - static void clear_phase(); 34.103 - static void set_phase(HRSPhase phase); 34.104 + bool _verify_in_progress; 34.105 34.106 // verify_region() is used to ensure that the contents of a region 34.107 - // added to / removed from a set are consistent. Different sets 34.108 - // make different assumptions about the regions added to them. So 34.109 - // each set can override verify_region_extra(), which is called 34.110 - // from verify_region(), and do any extra verification it needs to 34.111 - // perform in that. 34.112 - virtual const char* verify_region_extra(HeapRegion* hr) { return NULL; } 34.113 - bool verify_region(HeapRegion* hr, 34.114 - HeapRegionSetBase* expected_containing_set); 34.115 + // added to / removed from a set are consistent. 34.116 + void verify_region(HeapRegion* hr) PRODUCT_RETURN; 34.117 34.118 // Indicates whether all regions in the set should be humongous or 34.119 // not. Only used during verification. 34.120 - virtual bool regions_humongous() = 0; 34.121 + bool regions_humongous() { return _is_humongous; } 34.122 34.123 // Indicates whether all regions in the set should be empty or 34.124 // not. Only used during verification. 34.125 - virtual bool regions_empty() = 0; 34.126 + bool regions_empty() { return _is_empty; } 34.127 34.128 - // Subclasses can optionally override this to do MT safety protocol 34.129 - // checks. It is called in an assert from all methods that perform 34.130 - // updates on the set (and subclasses should also call it too). 34.131 - virtual bool check_mt_safety() { return true; } 34.132 + void check_mt_safety() { 34.133 + if (_mt_safety_checker != NULL) { 34.134 + _mt_safety_checker->check(); 34.135 + } 34.136 + } 34.137 + 34.138 + virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg) { } 34.139 + 34.140 + HeapRegionSetBase(const char* name, bool humongous, bool empty, HRSMtSafeChecker* mt_safety_checker); 34.141 + 34.142 +public: 34.143 + const char* name() { return _name; } 34.144 + 34.145 + uint length() { return _count.length(); } 34.146 + 34.147 + bool is_empty() { return _count.length() == 0; } 34.148 + 34.149 + size_t total_capacity_bytes() { 34.150 + return _count.capacity(); 34.151 + } 34.152 + 34.153 + // It updates the fields of the set to reflect hr being added to 34.154 + // the set and tags the region appropriately. 34.155 + inline void add(HeapRegion* hr); 34.156 + 34.157 + // It updates the fields of the set to reflect hr being removed 34.158 + // from the set and tags the region appropriately. 34.159 + inline void remove(HeapRegion* hr); 34.160 34.161 // fill_in_ext_msg() writes the the values of the set's attributes 34.162 // in the custom err_msg (hrs_ext_msg). fill_in_ext_msg_extra() 34.163 // allows subclasses to append further information. 34.164 - virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg) { } 34.165 void fill_in_ext_msg(hrs_ext_msg* msg, const char* message); 34.166 34.167 - // It updates the fields of the set to reflect hr being added to 34.168 - // the set. 34.169 - inline void update_for_addition(HeapRegion* hr); 34.170 - 34.171 - // It updates the fields of the set to reflect hr being added to 34.172 - // the set and tags the region appropriately. 34.173 - inline void add_internal(HeapRegion* hr); 34.174 - 34.175 - // It updates the fields of the set to reflect hr being removed 34.176 - // from the set. 34.177 - inline void update_for_removal(HeapRegion* hr); 34.178 - 34.179 - // It updates the fields of the set to reflect hr being removed 34.180 - // from the set and tags the region appropriately. 34.181 - inline void remove_internal(HeapRegion* hr); 34.182 - 34.183 - // It clears all the fields of the sets. Note: it will not iterate 34.184 - // over the set and remove regions from it. It assumes that the 34.185 - // caller has already done so. It will literally just clear the fields. 34.186 - virtual void clear(); 34.187 - 34.188 - HeapRegionSetBase(const char* name); 34.189 - 34.190 -public: 34.191 - static void set_unrealistically_long_length(uint len); 34.192 - 34.193 - const char* name() { return _name; } 34.194 - 34.195 - uint length() { return _length; } 34.196 - 34.197 - bool is_empty() { return _length == 0; } 34.198 - 34.199 - uint region_num() { return _region_num; } 34.200 - 34.201 - size_t total_capacity_bytes() { 34.202 - return (size_t) region_num() << HeapRegion::LogOfHRGrainBytes; 34.203 - } 34.204 - 34.205 - size_t total_used_bytes() { return _total_used_bytes; } 34.206 - 34.207 virtual void verify(); 34.208 void verify_start(); 34.209 void verify_next_region(HeapRegion* hr); 34.210 @@ -187,7 +160,6 @@ 34.211 // assert/guarantee-specific message it also prints out the values of 34.212 // the fields of the associated set. This can be very helpful in 34.213 // diagnosing failures. 34.214 - 34.215 class hrs_ext_msg : public hrs_err_msg { 34.216 public: 34.217 hrs_ext_msg(HeapRegionSetBase* set, const char* message) : hrs_err_msg("") { 34.218 @@ -195,32 +167,6 @@ 34.219 } 34.220 }; 34.221 34.222 -class HRSPhaseSetter { 34.223 -public: 34.224 - HRSPhaseSetter(HRSPhase phase) { 34.225 - HeapRegionSetBase::set_phase(phase); 34.226 - } 34.227 - ~HRSPhaseSetter() { 34.228 - HeapRegionSetBase::clear_phase(); 34.229 - } 34.230 -}; 34.231 - 34.232 -// These two macros are provided for convenience, to keep the uses of 34.233 -// these two asserts a bit more concise. 34.234 - 34.235 -#define hrs_assert_mt_safety_ok(_set_) \ 34.236 - do { \ 34.237 - assert((_set_)->check_mt_safety(), hrs_ext_msg((_set_), "MT safety")); \ 34.238 - } while (0) 34.239 - 34.240 -#define hrs_assert_region_ok(_set_, _hr_, _expected_) \ 34.241 - do { \ 34.242 - assert((_set_)->verify_region((_hr_), (_expected_)), \ 34.243 - hrs_ext_msg((_set_), "region verification")); \ 34.244 - } while (0) 34.245 - 34.246 -//////////////////// HeapRegionSet //////////////////// 34.247 - 34.248 #define hrs_assert_sets_match(_set1_, _set2_) \ 34.249 do { \ 34.250 assert(((_set1_)->regions_humongous() == \ 34.251 @@ -236,63 +182,33 @@ 34.252 // the same interface (namely, the HeapRegionSetBase API). 34.253 34.254 class HeapRegionSet : public HeapRegionSetBase { 34.255 -protected: 34.256 - virtual const char* verify_region_extra(HeapRegion* hr) { 34.257 - if (hr->next() != NULL) { 34.258 - return "next() should always be NULL as we do not link the regions"; 34.259 - } 34.260 +public: 34.261 + HeapRegionSet(const char* name, bool humongous, HRSMtSafeChecker* mt_safety_checker): 34.262 + HeapRegionSetBase(name, humongous, false /* empty */, mt_safety_checker) { } 34.263 34.264 - return HeapRegionSetBase::verify_region_extra(hr); 34.265 + void bulk_remove(const HeapRegionSetCount& removed) { 34.266 + _count.decrement(removed.length(), removed.capacity()); 34.267 } 34.268 - 34.269 - HeapRegionSet(const char* name) : HeapRegionSetBase(name) { 34.270 - clear(); 34.271 - } 34.272 - 34.273 -public: 34.274 - // It adds hr to the set. The region should not be a member of 34.275 - // another set. 34.276 - inline void add(HeapRegion* hr); 34.277 - 34.278 - // It removes hr from the set. The region should be a member of 34.279 - // this set. 34.280 - inline void remove(HeapRegion* hr); 34.281 - 34.282 - // It removes a region from the set. Instead of updating the fields 34.283 - // of the set to reflect this removal, it accumulates the updates 34.284 - // in proxy_set. The idea is that proxy_set is thread-local to 34.285 - // avoid multiple threads updating the fields of the set 34.286 - // concurrently and having to synchronize. The method 34.287 - // update_from_proxy() will update the fields of the set from the 34.288 - // proxy_set. 34.289 - inline void remove_with_proxy(HeapRegion* hr, HeapRegionSet* proxy_set); 34.290 - 34.291 - // After multiple calls to remove_with_proxy() the updates to the 34.292 - // fields of the set are accumulated in proxy_set. This call 34.293 - // updates the fields of the set from proxy_set. 34.294 - void update_from_proxy(HeapRegionSet* proxy_set); 34.295 }; 34.296 34.297 -//////////////////// HeapRegionLinkedList //////////////////// 34.298 - 34.299 // A set that links all the regions added to it in a singly-linked 34.300 // list. We should try to avoid doing operations that iterate over 34.301 // such lists in performance critical paths. Typically we should 34.302 // add / remove one region at a time or concatenate two lists. All 34.303 // those operations are done in constant time. 34.304 34.305 -class HeapRegionLinkedListIterator; 34.306 +class FreeRegionListIterator; 34.307 34.308 -class HeapRegionLinkedList : public HeapRegionSetBase { 34.309 - friend class HeapRegionLinkedListIterator; 34.310 +class FreeRegionList : public HeapRegionSetBase { 34.311 + friend class FreeRegionListIterator; 34.312 34.313 private: 34.314 HeapRegion* _head; 34.315 HeapRegion* _tail; 34.316 34.317 - // These are provided for use by the friend classes. 34.318 - HeapRegion* head() { return _head; } 34.319 - HeapRegion* tail() { return _tail; } 34.320 + static uint _unrealistically_long_length; 34.321 + 34.322 + void add_as_head_or_tail(FreeRegionList* from_list, bool as_head); 34.323 34.324 protected: 34.325 virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg); 34.326 @@ -300,11 +216,19 @@ 34.327 // See the comment for HeapRegionSetBase::clear() 34.328 virtual void clear(); 34.329 34.330 - HeapRegionLinkedList(const char* name) : HeapRegionSetBase(name) { 34.331 +public: 34.332 + FreeRegionList(const char* name, HRSMtSafeChecker* mt_safety_checker = NULL): 34.333 + HeapRegionSetBase(name, false /* humongous */, true /* empty */, mt_safety_checker) { 34.334 clear(); 34.335 } 34.336 34.337 -public: 34.338 + void verify_list(); 34.339 + 34.340 + HeapRegion* head() { return _head; } 34.341 + HeapRegion* tail() { return _tail; } 34.342 + 34.343 + static void set_unrealistically_long_length(uint len); 34.344 + 34.345 // It adds hr to the list as the new head. The region should not be 34.346 // a member of another set. 34.347 inline void add_as_head(HeapRegion* hr); 34.348 @@ -323,12 +247,12 @@ 34.349 // It moves the regions from from_list to this list and empties 34.350 // from_list. The new regions will appear in the same order as they 34.351 // were in from_list and be linked in the beginning of this list. 34.352 - void add_as_head(HeapRegionLinkedList* from_list); 34.353 + void add_as_head(FreeRegionList* from_list); 34.354 34.355 // It moves the regions from from_list to this list and empties 34.356 // from_list. The new regions will appear in the same order as they 34.357 // were in from_list and be linked in the end of this list. 34.358 - void add_as_tail(HeapRegionLinkedList* from_list); 34.359 + void add_as_tail(FreeRegionList* from_list); 34.360 34.361 // It empties the list by removing all regions from it. 34.362 void remove_all(); 34.363 @@ -346,14 +270,12 @@ 34.364 virtual void print_on(outputStream* out, bool print_contents = false); 34.365 }; 34.366 34.367 -//////////////////// HeapRegionLinkedListIterator //////////////////// 34.368 - 34.369 // Iterator class that provides a convenient way to iterate over the 34.370 // regions of a HeapRegionLinkedList instance. 34.371 34.372 -class HeapRegionLinkedListIterator : public StackObj { 34.373 +class FreeRegionListIterator : public StackObj { 34.374 private: 34.375 - HeapRegionLinkedList* _list; 34.376 + FreeRegionList* _list; 34.377 HeapRegion* _curr; 34.378 34.379 public: 34.380 @@ -369,12 +291,12 @@ 34.381 // do the "cycle" check. 34.382 34.383 HeapRegion* hr = _curr; 34.384 - assert(_list->verify_region(hr, _list), "region verification"); 34.385 + _list->verify_region(hr); 34.386 _curr = hr->next(); 34.387 return hr; 34.388 } 34.389 34.390 - HeapRegionLinkedListIterator(HeapRegionLinkedList* list) 34.391 + FreeRegionListIterator(FreeRegionList* list) 34.392 : _curr(NULL), _list(list) { 34.393 _curr = list->head(); 34.394 }
35.1 --- a/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp Thu Mar 20 10:34:48 2014 -0700 35.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp Thu Mar 27 14:50:50 2014 -0700 35.3 @@ -27,87 +27,32 @@ 35.4 35.5 #include "gc_implementation/g1/heapRegionSet.hpp" 35.6 35.7 -//////////////////// HeapRegionSetBase //////////////////// 35.8 +inline void HeapRegionSetBase::add(HeapRegion* hr) { 35.9 + check_mt_safety(); 35.10 + assert(hr->containing_set() == NULL, hrs_ext_msg(this, "should not already have a containing set %u")); 35.11 + assert(hr->next() == NULL, hrs_ext_msg(this, "should not already be linked")); 35.12 35.13 -inline void HeapRegionSetBase::update_for_addition(HeapRegion* hr) { 35.14 - // Assumes the caller has already verified the region. 35.15 - 35.16 - _length += 1; 35.17 - _region_num += hr->region_num(); 35.18 - _total_used_bytes += hr->used(); 35.19 + _count.increment(1u, hr->capacity()); 35.20 + hr->set_containing_set(this); 35.21 + verify_region(hr); 35.22 } 35.23 35.24 -inline void HeapRegionSetBase::add_internal(HeapRegion* hr) { 35.25 - hrs_assert_region_ok(this, hr, NULL); 35.26 - assert(hr->next() == NULL, hrs_ext_msg(this, "should not already be linked")); 35.27 - 35.28 - update_for_addition(hr); 35.29 - hr->set_containing_set(this); 35.30 -} 35.31 - 35.32 -inline void HeapRegionSetBase::update_for_removal(HeapRegion* hr) { 35.33 - // Assumes the caller has already verified the region. 35.34 - assert(_length > 0, hrs_ext_msg(this, "pre-condition")); 35.35 - _length -= 1; 35.36 - 35.37 - uint region_num_diff = hr->region_num(); 35.38 - assert(region_num_diff <= _region_num, 35.39 - hrs_err_msg("[%s] region's region num: %u " 35.40 - "should be <= region num: %u", 35.41 - name(), region_num_diff, _region_num)); 35.42 - _region_num -= region_num_diff; 35.43 - 35.44 - size_t used_bytes = hr->used(); 35.45 - assert(used_bytes <= _total_used_bytes, 35.46 - hrs_err_msg("[%s] region's used bytes: "SIZE_FORMAT" " 35.47 - "should be <= used bytes: "SIZE_FORMAT, 35.48 - name(), used_bytes, _total_used_bytes)); 35.49 - _total_used_bytes -= used_bytes; 35.50 -} 35.51 - 35.52 -inline void HeapRegionSetBase::remove_internal(HeapRegion* hr) { 35.53 - hrs_assert_region_ok(this, hr, this); 35.54 +inline void HeapRegionSetBase::remove(HeapRegion* hr) { 35.55 + check_mt_safety(); 35.56 + verify_region(hr); 35.57 assert(hr->next() == NULL, hrs_ext_msg(this, "should already be unlinked")); 35.58 35.59 hr->set_containing_set(NULL); 35.60 - update_for_removal(hr); 35.61 + assert(_count.length() > 0, hrs_ext_msg(this, "pre-condition")); 35.62 + _count.decrement(1u, hr->capacity()); 35.63 } 35.64 35.65 -//////////////////// HeapRegionSet //////////////////// 35.66 - 35.67 -inline void HeapRegionSet::add(HeapRegion* hr) { 35.68 - hrs_assert_mt_safety_ok(this); 35.69 - // add_internal() will verify the region. 35.70 - add_internal(hr); 35.71 -} 35.72 - 35.73 -inline void HeapRegionSet::remove(HeapRegion* hr) { 35.74 - hrs_assert_mt_safety_ok(this); 35.75 - // remove_internal() will verify the region. 35.76 - remove_internal(hr); 35.77 -} 35.78 - 35.79 -inline void HeapRegionSet::remove_with_proxy(HeapRegion* hr, 35.80 - HeapRegionSet* proxy_set) { 35.81 - // No need to fo the MT safety check here given that this method 35.82 - // does not update the contents of the set but instead accumulates 35.83 - // the changes in proxy_set which is assumed to be thread-local. 35.84 - hrs_assert_sets_match(this, proxy_set); 35.85 - hrs_assert_region_ok(this, hr, this); 35.86 - 35.87 - hr->set_containing_set(NULL); 35.88 - proxy_set->update_for_addition(hr); 35.89 -} 35.90 - 35.91 -//////////////////// HeapRegionLinkedList //////////////////// 35.92 - 35.93 -inline void HeapRegionLinkedList::add_as_head(HeapRegion* hr) { 35.94 - hrs_assert_mt_safety_ok(this); 35.95 +inline void FreeRegionList::add_as_head(HeapRegion* hr) { 35.96 assert((length() == 0 && _head == NULL && _tail == NULL) || 35.97 (length() > 0 && _head != NULL && _tail != NULL), 35.98 hrs_ext_msg(this, "invariant")); 35.99 - // add_internal() will verify the region. 35.100 - add_internal(hr); 35.101 + // add() will verify the region and check mt safety. 35.102 + add(hr); 35.103 35.104 // Now link the region. 35.105 if (_head != NULL) { 35.106 @@ -118,13 +63,13 @@ 35.107 _head = hr; 35.108 } 35.109 35.110 -inline void HeapRegionLinkedList::add_as_tail(HeapRegion* hr) { 35.111 - hrs_assert_mt_safety_ok(this); 35.112 +inline void FreeRegionList::add_as_tail(HeapRegion* hr) { 35.113 + check_mt_safety(); 35.114 assert((length() == 0 && _head == NULL && _tail == NULL) || 35.115 (length() > 0 && _head != NULL && _tail != NULL), 35.116 hrs_ext_msg(this, "invariant")); 35.117 - // add_internal() will verify the region. 35.118 - add_internal(hr); 35.119 + // add() will verify the region and check mt safety 35.120 + add(hr); 35.121 35.122 // Now link the region. 35.123 if (_tail != NULL) { 35.124 @@ -135,8 +80,7 @@ 35.125 _tail = hr; 35.126 } 35.127 35.128 -inline HeapRegion* HeapRegionLinkedList::remove_head() { 35.129 - hrs_assert_mt_safety_ok(this); 35.130 +inline HeapRegion* FreeRegionList::remove_head() { 35.131 assert(!is_empty(), hrs_ext_msg(this, "the list should not be empty")); 35.132 assert(length() > 0 && _head != NULL && _tail != NULL, 35.133 hrs_ext_msg(this, "invariant")); 35.134 @@ -149,14 +93,13 @@ 35.135 } 35.136 hr->set_next(NULL); 35.137 35.138 - // remove_internal() will verify the region. 35.139 - remove_internal(hr); 35.140 + // remove() will verify the region and check mt safety 35.141 + remove(hr); 35.142 return hr; 35.143 } 35.144 35.145 -inline HeapRegion* HeapRegionLinkedList::remove_head_or_null() { 35.146 - hrs_assert_mt_safety_ok(this); 35.147 - 35.148 +inline HeapRegion* FreeRegionList::remove_head_or_null() { 35.149 + check_mt_safety(); 35.150 if (!is_empty()) { 35.151 return remove_head(); 35.152 } else {
36.1 --- a/src/share/vm/gc_implementation/g1/heapRegionSets.cpp Thu Mar 20 10:34:48 2014 -0700 36.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 36.3 @@ -1,175 +0,0 @@ 36.4 -/* 36.5 - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 36.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 36.7 - * 36.8 - * This code is free software; you can redistribute it and/or modify it 36.9 - * under the terms of the GNU General Public License version 2 only, as 36.10 - * published by the Free Software Foundation. 36.11 - * 36.12 - * This code is distributed in the hope that it will be useful, but WITHOUT 36.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 36.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 36.15 - * version 2 for more details (a copy is included in the LICENSE file that 36.16 - * accompanied this code). 36.17 - * 36.18 - * You should have received a copy of the GNU General Public License version 36.19 - * 2 along with this work; if not, write to the Free Software Foundation, 36.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 36.21 - * 36.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 36.23 - * or visit www.oracle.com if you need additional information or have any 36.24 - * questions. 36.25 - * 36.26 - */ 36.27 - 36.28 -#include "precompiled.hpp" 36.29 -#include "gc_implementation/g1/heapRegionRemSet.hpp" 36.30 -#include "gc_implementation/g1/heapRegionSets.hpp" 36.31 - 36.32 -// Note on the check_mt_safety() methods below: 36.33 -// 36.34 -// Verification of the "master" heap region sets / lists that are 36.35 -// maintained by G1CollectedHeap is always done during a STW pause and 36.36 -// by the VM thread at the start / end of the pause. The standard 36.37 -// verification methods all assert check_mt_safety(). This is 36.38 -// important as it ensures that verification is done without 36.39 -// concurrent updates taking place at the same time. It follows, that, 36.40 -// for the "master" heap region sets / lists, the check_mt_safety() 36.41 -// method should include the VM thread / STW case. 36.42 - 36.43 -//////////////////// FreeRegionList //////////////////// 36.44 - 36.45 -const char* FreeRegionList::verify_region_extra(HeapRegion* hr) { 36.46 - if (hr->is_young()) { 36.47 - return "the region should not be young"; 36.48 - } 36.49 - // The superclass will check that the region is empty and 36.50 - // not humongous. 36.51 - return HeapRegionLinkedList::verify_region_extra(hr); 36.52 -} 36.53 - 36.54 -//////////////////// MasterFreeRegionList //////////////////// 36.55 - 36.56 -const char* MasterFreeRegionList::verify_region_extra(HeapRegion* hr) { 36.57 - // We should reset the RSet for parallel iteration before we add it 36.58 - // to the master free list so that it is ready when the region is 36.59 - // re-allocated. 36.60 - if (!hr->rem_set()->verify_ready_for_par_iteration()) { 36.61 - return "the region's RSet should be ready for parallel iteration"; 36.62 - } 36.63 - return FreeRegionList::verify_region_extra(hr); 36.64 -} 36.65 - 36.66 -bool MasterFreeRegionList::check_mt_safety() { 36.67 - // Master Free List MT safety protocol: 36.68 - // (a) If we're at a safepoint, operations on the master free list 36.69 - // should be invoked by either the VM thread (which will serialize 36.70 - // them) or by the GC workers while holding the 36.71 - // FreeList_lock. 36.72 - // (b) If we're not at a safepoint, operations on the master free 36.73 - // list should be invoked while holding the Heap_lock. 36.74 - 36.75 - if (SafepointSynchronize::is_at_safepoint()) { 36.76 - guarantee(Thread::current()->is_VM_thread() || 36.77 - FreeList_lock->owned_by_self(), 36.78 - hrs_ext_msg(this, "master free list MT safety protocol " 36.79 - "at a safepoint")); 36.80 - } else { 36.81 - guarantee(Heap_lock->owned_by_self(), 36.82 - hrs_ext_msg(this, "master free list MT safety protocol " 36.83 - "outside a safepoint")); 36.84 - } 36.85 - 36.86 - return FreeRegionList::check_mt_safety(); 36.87 -} 36.88 - 36.89 -//////////////////// SecondaryFreeRegionList //////////////////// 36.90 - 36.91 -bool SecondaryFreeRegionList::check_mt_safety() { 36.92 - // Secondary Free List MT safety protocol: 36.93 - // Operations on the secondary free list should always be invoked 36.94 - // while holding the SecondaryFreeList_lock. 36.95 - 36.96 - guarantee(SecondaryFreeList_lock->owned_by_self(), 36.97 - hrs_ext_msg(this, "secondary free list MT safety protocol")); 36.98 - 36.99 - return FreeRegionList::check_mt_safety(); 36.100 -} 36.101 - 36.102 -//////////////////// OldRegionSet //////////////////// 36.103 - 36.104 -const char* OldRegionSet::verify_region_extra(HeapRegion* hr) { 36.105 - if (hr->is_young()) { 36.106 - return "the region should not be young"; 36.107 - } 36.108 - // The superclass will check that the region is not empty and not 36.109 - // humongous. 36.110 - return HeapRegionSet::verify_region_extra(hr); 36.111 -} 36.112 - 36.113 -//////////////////// MasterOldRegionSet //////////////////// 36.114 - 36.115 -bool MasterOldRegionSet::check_mt_safety() { 36.116 - // Master Old Set MT safety protocol: 36.117 - // (a) If we're at a safepoint, operations on the master old set 36.118 - // should be invoked: 36.119 - // - by the VM thread (which will serialize them), or 36.120 - // - by the GC workers while holding the FreeList_lock, if we're 36.121 - // at a safepoint for an evacuation pause (this lock is taken 36.122 - // anyway when an GC alloc region is retired so that a new one 36.123 - // is allocated from the free list), or 36.124 - // - by the GC workers while holding the OldSets_lock, if we're at a 36.125 - // safepoint for a cleanup pause. 36.126 - // (b) If we're not at a safepoint, operations on the master old set 36.127 - // should be invoked while holding the Heap_lock. 36.128 - 36.129 - if (SafepointSynchronize::is_at_safepoint()) { 36.130 - guarantee(Thread::current()->is_VM_thread() || 36.131 - _phase == HRSPhaseEvacuation && FreeList_lock->owned_by_self() || 36.132 - _phase == HRSPhaseCleanup && OldSets_lock->owned_by_self(), 36.133 - hrs_ext_msg(this, "master old set MT safety protocol " 36.134 - "at a safepoint")); 36.135 - } else { 36.136 - guarantee(Heap_lock->owned_by_self(), 36.137 - hrs_ext_msg(this, "master old set MT safety protocol " 36.138 - "outside a safepoint")); 36.139 - } 36.140 - 36.141 - return OldRegionSet::check_mt_safety(); 36.142 -} 36.143 - 36.144 -//////////////////// HumongousRegionSet //////////////////// 36.145 - 36.146 -const char* HumongousRegionSet::verify_region_extra(HeapRegion* hr) { 36.147 - if (hr->is_young()) { 36.148 - return "the region should not be young"; 36.149 - } 36.150 - // The superclass will check that the region is not empty and 36.151 - // humongous. 36.152 - return HeapRegionSet::verify_region_extra(hr); 36.153 -} 36.154 - 36.155 -//////////////////// MasterHumongousRegionSet //////////////////// 36.156 - 36.157 -bool MasterHumongousRegionSet::check_mt_safety() { 36.158 - // Master Humongous Set MT safety protocol: 36.159 - // (a) If we're at a safepoint, operations on the master humongous 36.160 - // set should be invoked by either the VM thread (which will 36.161 - // serialize them) or by the GC workers while holding the 36.162 - // OldSets_lock. 36.163 - // (b) If we're not at a safepoint, operations on the master 36.164 - // humongous set should be invoked while holding the Heap_lock. 36.165 - 36.166 - if (SafepointSynchronize::is_at_safepoint()) { 36.167 - guarantee(Thread::current()->is_VM_thread() || 36.168 - OldSets_lock->owned_by_self(), 36.169 - hrs_ext_msg(this, "master humongous set MT safety protocol " 36.170 - "at a safepoint")); 36.171 - } else { 36.172 - guarantee(Heap_lock->owned_by_self(), 36.173 - hrs_ext_msg(this, "master humongous set MT safety protocol " 36.174 - "outside a safepoint")); 36.175 - } 36.176 - 36.177 - return HumongousRegionSet::check_mt_safety(); 36.178 -}
37.1 --- a/src/share/vm/gc_implementation/g1/heapRegionSets.hpp Thu Mar 20 10:34:48 2014 -0700 37.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 37.3 @@ -1,111 +0,0 @@ 37.4 -/* 37.5 - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 37.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 37.7 - * 37.8 - * This code is free software; you can redistribute it and/or modify it 37.9 - * under the terms of the GNU General Public License version 2 only, as 37.10 - * published by the Free Software Foundation. 37.11 - * 37.12 - * This code is distributed in the hope that it will be useful, but WITHOUT 37.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 37.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 37.15 - * version 2 for more details (a copy is included in the LICENSE file that 37.16 - * accompanied this code). 37.17 - * 37.18 - * You should have received a copy of the GNU General Public License version 37.19 - * 2 along with this work; if not, write to the Free Software Foundation, 37.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 37.21 - * 37.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 37.23 - * or visit www.oracle.com if you need additional information or have any 37.24 - * questions. 37.25 - * 37.26 - */ 37.27 - 37.28 -#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSETS_HPP 37.29 -#define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSETS_HPP 37.30 - 37.31 -#include "gc_implementation/g1/heapRegionSet.inline.hpp" 37.32 - 37.33 -//////////////////// FreeRegionList //////////////////// 37.34 - 37.35 -class FreeRegionList : public HeapRegionLinkedList { 37.36 -protected: 37.37 - virtual const char* verify_region_extra(HeapRegion* hr); 37.38 - 37.39 - virtual bool regions_humongous() { return false; } 37.40 - virtual bool regions_empty() { return true; } 37.41 - 37.42 -public: 37.43 - FreeRegionList(const char* name) : HeapRegionLinkedList(name) { } 37.44 -}; 37.45 - 37.46 -//////////////////// MasterFreeRegionList //////////////////// 37.47 - 37.48 -class MasterFreeRegionList : public FreeRegionList { 37.49 -protected: 37.50 - virtual const char* verify_region_extra(HeapRegion* hr); 37.51 - virtual bool check_mt_safety(); 37.52 - 37.53 -public: 37.54 - MasterFreeRegionList(const char* name) : FreeRegionList(name) { } 37.55 -}; 37.56 - 37.57 -//////////////////// SecondaryFreeRegionList //////////////////// 37.58 - 37.59 -class SecondaryFreeRegionList : public FreeRegionList { 37.60 -protected: 37.61 - virtual bool check_mt_safety(); 37.62 - 37.63 -public: 37.64 - SecondaryFreeRegionList(const char* name) : FreeRegionList(name) { } 37.65 -}; 37.66 - 37.67 -//////////////////// OldRegionSet //////////////////// 37.68 - 37.69 -class OldRegionSet : public HeapRegionSet { 37.70 -protected: 37.71 - virtual const char* verify_region_extra(HeapRegion* hr); 37.72 - 37.73 - virtual bool regions_humongous() { return false; } 37.74 - virtual bool regions_empty() { return false; } 37.75 - 37.76 -public: 37.77 - OldRegionSet(const char* name) : HeapRegionSet(name) { } 37.78 -}; 37.79 - 37.80 -//////////////////// MasterOldRegionSet //////////////////// 37.81 - 37.82 -class MasterOldRegionSet : public OldRegionSet { 37.83 -private: 37.84 -protected: 37.85 - virtual bool check_mt_safety(); 37.86 - 37.87 -public: 37.88 - MasterOldRegionSet(const char* name) : OldRegionSet(name) { } 37.89 -}; 37.90 - 37.91 -//////////////////// HumongousRegionSet //////////////////// 37.92 - 37.93 -class HumongousRegionSet : public HeapRegionSet { 37.94 -protected: 37.95 - virtual const char* verify_region_extra(HeapRegion* hr); 37.96 - 37.97 - virtual bool regions_humongous() { return true; } 37.98 - virtual bool regions_empty() { return false; } 37.99 - 37.100 -public: 37.101 - HumongousRegionSet(const char* name) : HeapRegionSet(name) { } 37.102 -}; 37.103 - 37.104 -//////////////////// MasterHumongousRegionSet //////////////////// 37.105 - 37.106 -class MasterHumongousRegionSet : public HumongousRegionSet { 37.107 -protected: 37.108 - virtual bool check_mt_safety(); 37.109 - 37.110 -public: 37.111 - MasterHumongousRegionSet(const char* name) : HumongousRegionSet(name) { } 37.112 -}; 37.113 - 37.114 -#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSETS_HPP
38.1 --- a/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp Thu Mar 20 10:34:48 2014 -0700 38.2 +++ b/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp Thu Mar 27 14:50:50 2014 -0700 38.3 @@ -57,9 +57,10 @@ 38.4 nonstatic_field(G1MonitoringSupport, _old_committed, size_t) \ 38.5 nonstatic_field(G1MonitoringSupport, _old_used, size_t) \ 38.6 \ 38.7 - nonstatic_field(HeapRegionSetBase, _length, uint) \ 38.8 - nonstatic_field(HeapRegionSetBase, _region_num, uint) \ 38.9 - nonstatic_field(HeapRegionSetBase, _total_used_bytes, size_t) \ 38.10 + nonstatic_field(HeapRegionSetBase, _count, HeapRegionSetCount) \ 38.11 + \ 38.12 + nonstatic_field(HeapRegionSetCount, _length, uint) \ 38.13 + nonstatic_field(HeapRegionSetCount, _capacity, size_t) \ 38.14 38.15 38.16 #define VM_TYPES_G1(declare_type, declare_toplevel_type) \ 38.17 @@ -71,6 +72,7 @@ 38.18 declare_type(HeapRegion, ContiguousSpace) \ 38.19 declare_toplevel_type(HeapRegionSeq) \ 38.20 declare_toplevel_type(HeapRegionSetBase) \ 38.21 + declare_toplevel_type(HeapRegionSetCount) \ 38.22 declare_toplevel_type(G1MonitoringSupport) \ 38.23 \ 38.24 declare_toplevel_type(G1CollectedHeap*) \
39.1 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Thu Mar 20 10:34:48 2014 -0700 39.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Thu Mar 27 14:50:50 2014 -0700 39.3 @@ -492,6 +492,10 @@ 39.4 return young_gen()->eden_space()->tlab_capacity(thr); 39.5 } 39.6 39.7 +size_t ParallelScavengeHeap::tlab_used(Thread* thr) const { 39.8 + return young_gen()->eden_space()->tlab_used(thr); 39.9 +} 39.10 + 39.11 size_t ParallelScavengeHeap::unsafe_max_tlab_alloc(Thread* thr) const { 39.12 return young_gen()->eden_space()->unsafe_max_tlab_alloc(thr); 39.13 }
40.1 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Thu Mar 20 10:34:48 2014 -0700 40.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Thu Mar 27 14:50:50 2014 -0700 40.3 @@ -189,6 +189,7 @@ 40.4 bool supports_tlab_allocation() const { return true; } 40.5 40.6 size_t tlab_capacity(Thread* thr) const; 40.7 + size_t tlab_used(Thread* thr) const; 40.8 size_t unsafe_max_tlab_alloc(Thread* thr) const; 40.9 40.10 // Can a compiler initialize a new object without store barriers?
41.1 --- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Thu Mar 20 10:34:48 2014 -0700 41.2 +++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Thu Mar 27 14:50:50 2014 -0700 41.3 @@ -173,6 +173,26 @@ 41.4 return lgrp_spaces()->at(i)->space()->capacity_in_bytes(); 41.5 } 41.6 41.7 +size_t MutableNUMASpace::tlab_used(Thread *thr) const { 41.8 + // Please see the comments for tlab_capacity(). 41.9 + guarantee(thr != NULL, "No thread"); 41.10 + int lgrp_id = thr->lgrp_id(); 41.11 + if (lgrp_id == -1) { 41.12 + if (lgrp_spaces()->length() > 0) { 41.13 + return (used_in_bytes()) / lgrp_spaces()->length(); 41.14 + } else { 41.15 + assert(false, "There should be at least one locality group"); 41.16 + return 0; 41.17 + } 41.18 + } 41.19 + int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals); 41.20 + if (i == -1) { 41.21 + return 0; 41.22 + } 41.23 + return lgrp_spaces()->at(i)->space()->used_in_bytes(); 41.24 +} 41.25 + 41.26 + 41.27 size_t MutableNUMASpace::unsafe_max_tlab_alloc(Thread *thr) const { 41.28 // Please see the comments for tlab_capacity(). 41.29 guarantee(thr != NULL, "No thread");
42.1 --- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp Thu Mar 20 10:34:48 2014 -0700 42.2 +++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp Thu Mar 27 14:50:50 2014 -0700 42.3 @@ -217,6 +217,7 @@ 42.4 using MutableSpace::capacity_in_words; 42.5 virtual size_t capacity_in_words(Thread* thr) const; 42.6 virtual size_t tlab_capacity(Thread* thr) const; 42.7 + virtual size_t tlab_used(Thread* thr) const; 42.8 virtual size_t unsafe_max_tlab_alloc(Thread* thr) const; 42.9 42.10 // Allocation (return NULL if full)
43.1 --- a/src/share/vm/gc_implementation/shared/mutableSpace.hpp Thu Mar 20 10:34:48 2014 -0700 43.2 +++ b/src/share/vm/gc_implementation/shared/mutableSpace.hpp Thu Mar 27 14:50:50 2014 -0700 43.3 @@ -124,6 +124,7 @@ 43.4 virtual size_t used_in_words() const { return pointer_delta(top(), bottom()); } 43.5 virtual size_t free_in_words() const { return pointer_delta(end(), top()); } 43.6 virtual size_t tlab_capacity(Thread* thr) const { return capacity_in_bytes(); } 43.7 + virtual size_t tlab_used(Thread* thr) const { return used_in_bytes(); } 43.8 virtual size_t unsafe_max_tlab_alloc(Thread* thr) const { return free_in_bytes(); } 43.9 43.10 // Allocation (return NULL if full)
44.1 --- a/src/share/vm/gc_implementation/shared/parGCAllocBuffer.cpp Thu Mar 20 10:34:48 2014 -0700 44.2 +++ b/src/share/vm/gc_implementation/shared/parGCAllocBuffer.cpp Thu Mar 27 14:50:50 2014 -0700 44.3 @@ -89,6 +89,10 @@ 44.4 // scavenge; it clears the sensor accumulators. 44.5 void PLABStats::adjust_desired_plab_sz(uint no_of_gc_workers) { 44.6 assert(ResizePLAB, "Not set"); 44.7 + 44.8 + assert(is_object_aligned(max_size()) && min_size() <= max_size(), 44.9 + "PLAB clipping computation may be incorrect"); 44.10 + 44.11 if (_allocated == 0) { 44.12 assert(_unused == 0, 44.13 err_msg("Inconsistency in PLAB stats: "
45.1 --- a/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp Thu Mar 20 10:34:48 2014 -0700 45.2 +++ b/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp Thu Mar 27 14:50:50 2014 -0700 45.3 @@ -181,16 +181,7 @@ 45.4 _used(0), 45.5 _desired_plab_sz(desired_plab_sz_), 45.6 _filter(wt) 45.7 - { 45.8 - size_t min_sz = min_size(); 45.9 - size_t max_sz = max_size(); 45.10 - size_t aligned_min_sz = align_object_size(min_sz); 45.11 - size_t aligned_max_sz = align_object_size(max_sz); 45.12 - assert(min_sz <= aligned_min_sz && max_sz >= aligned_max_sz && 45.13 - min_sz <= max_sz, 45.14 - "PLAB clipping computation in adjust_desired_plab_sz()" 45.15 - " may be incorrect"); 45.16 - } 45.17 + { } 45.18 45.19 static const size_t min_size() { 45.20 return ParGCAllocBuffer::min_size();
46.1 --- a/src/share/vm/gc_interface/collectedHeap.cpp Thu Mar 20 10:34:48 2014 -0700 46.2 +++ b/src/share/vm/gc_interface/collectedHeap.cpp Thu Mar 27 14:50:50 2014 -0700 46.3 @@ -320,6 +320,21 @@ 46.4 assert(thread->deferred_card_mark().is_empty(), "invariant"); 46.5 } 46.6 46.7 +size_t CollectedHeap::max_tlab_size() const { 46.8 + // TLABs can't be bigger than we can fill with a int[Integer.MAX_VALUE]. 46.9 + // This restriction could be removed by enabling filling with multiple arrays. 46.10 + // If we compute that the reasonable way as 46.11 + // header_size + ((sizeof(jint) * max_jint) / HeapWordSize) 46.12 + // we'll overflow on the multiply, so we do the divide first. 46.13 + // We actually lose a little by dividing first, 46.14 + // but that just makes the TLAB somewhat smaller than the biggest array, 46.15 + // which is fine, since we'll be able to fill that. 46.16 + size_t max_int_size = typeArrayOopDesc::header_size(T_INT) + 46.17 + sizeof(jint) * 46.18 + ((juint) max_jint / (size_t) HeapWordSize); 46.19 + return align_size_down(max_int_size, MinObjAlignment); 46.20 +} 46.21 + 46.22 // Helper for ReduceInitialCardMarks. For performance, 46.23 // compiled code may elide card-marks for initializing stores 46.24 // to a newly allocated object along the fast-path. We
47.1 --- a/src/share/vm/gc_interface/collectedHeap.hpp Thu Mar 20 10:34:48 2014 -0700 47.2 +++ b/src/share/vm/gc_interface/collectedHeap.hpp Thu Mar 27 14:50:50 2014 -0700 47.3 @@ -403,14 +403,16 @@ 47.4 // the following methods: 47.5 // Returns "true" iff the heap supports thread-local allocation buffers. 47.6 // The default is "no". 47.7 - virtual bool supports_tlab_allocation() const { 47.8 - return false; 47.9 - } 47.10 + virtual bool supports_tlab_allocation() const = 0; 47.11 + 47.12 // The amount of space available for thread-local allocation buffers. 47.13 - virtual size_t tlab_capacity(Thread *thr) const { 47.14 - guarantee(false, "thread-local allocation buffers not supported"); 47.15 - return 0; 47.16 - } 47.17 + virtual size_t tlab_capacity(Thread *thr) const = 0; 47.18 + 47.19 + // The amount of used space for thread-local allocation buffers for the given thread. 47.20 + virtual size_t tlab_used(Thread *thr) const = 0; 47.21 + 47.22 + virtual size_t max_tlab_size() const; 47.23 + 47.24 // An estimate of the maximum allocation that could be performed 47.25 // for thread-local allocation buffers without triggering any 47.26 // collection or expansion activity.
48.1 --- a/src/share/vm/interpreter/bytecodeTracer.cpp Thu Mar 20 10:34:48 2014 -0700 48.2 +++ b/src/share/vm/interpreter/bytecodeTracer.cpp Thu Mar 27 14:50:50 2014 -0700 48.3 @@ -596,7 +596,7 @@ 48.4 if (data != NULL) { 48.5 st->print(" %d", mdo->dp_to_di(data->dp())); 48.6 st->fill_to(6); 48.7 - data->print_data_on(st); 48.8 + data->print_data_on(st, mdo); 48.9 } 48.10 } 48.11 }
49.1 --- a/src/share/vm/memory/defNewGeneration.cpp Thu Mar 20 10:34:48 2014 -0700 49.2 +++ b/src/share/vm/memory/defNewGeneration.cpp Thu Mar 27 14:50:50 2014 -0700 49.3 @@ -1086,6 +1086,10 @@ 49.4 return eden()->capacity(); 49.5 } 49.6 49.7 +size_t DefNewGeneration::tlab_used() const { 49.8 + return eden()->used(); 49.9 +} 49.10 + 49.11 size_t DefNewGeneration::unsafe_max_tlab_alloc() const { 49.12 return unsafe_max_alloc_nogc(); 49.13 }
50.1 --- a/src/share/vm/memory/defNewGeneration.hpp Thu Mar 20 10:34:48 2014 -0700 50.2 +++ b/src/share/vm/memory/defNewGeneration.hpp Thu Mar 27 14:50:50 2014 -0700 50.3 @@ -239,6 +239,7 @@ 50.4 // Thread-local allocation buffers 50.5 bool supports_tlab_allocation() const { return true; } 50.6 size_t tlab_capacity() const; 50.7 + size_t tlab_used() const; 50.8 size_t unsafe_max_tlab_alloc() const; 50.9 50.10 // Grow the generation by the specified number of bytes.
51.1 --- a/src/share/vm/memory/genCollectedHeap.cpp Thu Mar 20 10:34:48 2014 -0700 51.2 +++ b/src/share/vm/memory/genCollectedHeap.cpp Thu Mar 27 14:50:50 2014 -0700 51.3 @@ -937,6 +937,16 @@ 51.4 return result; 51.5 } 51.6 51.7 +size_t GenCollectedHeap::tlab_used(Thread* thr) const { 51.8 + size_t result = 0; 51.9 + for (int i = 0; i < _n_gens; i += 1) { 51.10 + if (_gens[i]->supports_tlab_allocation()) { 51.11 + result += _gens[i]->tlab_used(); 51.12 + } 51.13 + } 51.14 + return result; 51.15 +} 51.16 + 51.17 size_t GenCollectedHeap::unsafe_max_tlab_alloc(Thread* thr) const { 51.18 size_t result = 0; 51.19 for (int i = 0; i < _n_gens; i += 1) {
52.1 --- a/src/share/vm/memory/genCollectedHeap.hpp Thu Mar 20 10:34:48 2014 -0700 52.2 +++ b/src/share/vm/memory/genCollectedHeap.hpp Thu Mar 27 14:50:50 2014 -0700 52.3 @@ -256,6 +256,7 @@ 52.4 // Section on TLAB's. 52.5 virtual bool supports_tlab_allocation() const; 52.6 virtual size_t tlab_capacity(Thread* thr) const; 52.7 + virtual size_t tlab_used(Thread* thr) const; 52.8 virtual size_t unsafe_max_tlab_alloc(Thread* thr) const; 52.9 virtual HeapWord* allocate_new_tlab(size_t size); 52.10
53.1 --- a/src/share/vm/memory/generation.hpp Thu Mar 20 10:34:48 2014 -0700 53.2 +++ b/src/share/vm/memory/generation.hpp Thu Mar 27 14:50:50 2014 -0700 53.3 @@ -299,6 +299,10 @@ 53.4 guarantee(false, "Generation doesn't support thread local allocation buffers"); 53.5 return 0; 53.6 } 53.7 + virtual size_t tlab_used() const { 53.8 + guarantee(false, "Generation doesn't support thread local allocation buffers"); 53.9 + return 0; 53.10 + } 53.11 virtual size_t unsafe_max_tlab_alloc() const { 53.12 guarantee(false, "Generation doesn't support thread local allocation buffers"); 53.13 return 0;
54.1 --- a/src/share/vm/memory/threadLocalAllocBuffer.cpp Thu Mar 20 10:34:48 2014 -0700 54.2 +++ b/src/share/vm/memory/threadLocalAllocBuffer.cpp Thu Mar 27 14:50:50 2014 -0700 54.3 @@ -34,6 +34,7 @@ 54.4 // Thread-Local Edens support 54.5 54.6 // static member initialization 54.7 +size_t ThreadLocalAllocBuffer::_max_size = 0; 54.8 unsigned ThreadLocalAllocBuffer::_target_refills = 0; 54.9 GlobalTLABStats* ThreadLocalAllocBuffer::_global_stats = NULL; 54.10 54.11 @@ -45,7 +46,7 @@ 54.12 void ThreadLocalAllocBuffer::accumulate_statistics_before_gc() { 54.13 global_stats()->initialize(); 54.14 54.15 - for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) { 54.16 + for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) { 54.17 thread->tlab().accumulate_statistics(); 54.18 thread->tlab().initialize_statistics(); 54.19 } 54.20 @@ -60,28 +61,32 @@ 54.21 } 54.22 54.23 void ThreadLocalAllocBuffer::accumulate_statistics() { 54.24 - size_t capacity = Universe::heap()->tlab_capacity(myThread()) / HeapWordSize; 54.25 - size_t unused = Universe::heap()->unsafe_max_tlab_alloc(myThread()) / HeapWordSize; 54.26 - size_t used = capacity - unused; 54.27 - 54.28 - // Update allocation history if a reasonable amount of eden was allocated. 54.29 - bool update_allocation_history = used > 0.5 * capacity; 54.30 + Thread* thread = myThread(); 54.31 + size_t capacity = Universe::heap()->tlab_capacity(thread); 54.32 + size_t used = Universe::heap()->tlab_used(thread); 54.33 54.34 _gc_waste += (unsigned)remaining(); 54.35 + size_t total_allocated = thread->allocated_bytes(); 54.36 + size_t allocated_since_last_gc = total_allocated - _allocated_before_last_gc; 54.37 + _allocated_before_last_gc = total_allocated; 54.38 54.39 if (PrintTLAB && (_number_of_refills > 0 || Verbose)) { 54.40 print_stats("gc"); 54.41 } 54.42 54.43 if (_number_of_refills > 0) { 54.44 + // Update allocation history if a reasonable amount of eden was allocated. 54.45 + bool update_allocation_history = used > 0.5 * capacity; 54.46 54.47 if (update_allocation_history) { 54.48 // Average the fraction of eden allocated in a tlab by this 54.49 // thread for use in the next resize operation. 54.50 // _gc_waste is not subtracted because it's included in 54.51 // "used". 54.52 - size_t allocation = _number_of_refills * desired_size(); 54.53 - double alloc_frac = allocation / (double) used; 54.54 + // The result can be larger than 1.0 due to direct to old allocations. 54.55 + // These allocations should ideally not be counted but since it is not possible 54.56 + // to filter them out here we just cap the fraction to be at most 1.0. 54.57 + double alloc_frac = MIN2(1.0, (double) allocated_since_last_gc / used); 54.58 _allocation_fraction.sample(alloc_frac); 54.59 } 54.60 global_stats()->update_allocating_threads(); 54.61 @@ -126,33 +131,32 @@ 54.62 } 54.63 54.64 void ThreadLocalAllocBuffer::resize_all_tlabs() { 54.65 - for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) { 54.66 - thread->tlab().resize(); 54.67 + if (ResizeTLAB) { 54.68 + for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) { 54.69 + thread->tlab().resize(); 54.70 + } 54.71 } 54.72 } 54.73 54.74 void ThreadLocalAllocBuffer::resize() { 54.75 + // Compute the next tlab size using expected allocation amount 54.76 + assert(ResizeTLAB, "Should not call this otherwise"); 54.77 + size_t alloc = (size_t)(_allocation_fraction.average() * 54.78 + (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize)); 54.79 + size_t new_size = alloc / _target_refills; 54.80 54.81 - if (ResizeTLAB) { 54.82 - // Compute the next tlab size using expected allocation amount 54.83 - size_t alloc = (size_t)(_allocation_fraction.average() * 54.84 - (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize)); 54.85 - size_t new_size = alloc / _target_refills; 54.86 + new_size = MIN2(MAX2(new_size, min_size()), max_size()); 54.87 54.88 - new_size = MIN2(MAX2(new_size, min_size()), max_size()); 54.89 + size_t aligned_new_size = align_object_size(new_size); 54.90 54.91 - size_t aligned_new_size = align_object_size(new_size); 54.92 - 54.93 - if (PrintTLAB && Verbose) { 54.94 - gclog_or_tty->print("TLAB new size: thread: " INTPTR_FORMAT " [id: %2d]" 54.95 - " refills %d alloc: %8.6f desired_size: " SIZE_FORMAT " -> " SIZE_FORMAT "\n", 54.96 - myThread(), myThread()->osthread()->thread_id(), 54.97 - _target_refills, _allocation_fraction.average(), desired_size(), aligned_new_size); 54.98 - } 54.99 - set_desired_size(aligned_new_size); 54.100 - 54.101 - set_refill_waste_limit(initial_refill_waste_limit()); 54.102 + if (PrintTLAB && Verbose) { 54.103 + gclog_or_tty->print("TLAB new size: thread: " INTPTR_FORMAT " [id: %2d]" 54.104 + " refills %d alloc: %8.6f desired_size: " SIZE_FORMAT " -> " SIZE_FORMAT "\n", 54.105 + myThread(), myThread()->osthread()->thread_id(), 54.106 + _target_refills, _allocation_fraction.average(), desired_size(), aligned_new_size); 54.107 } 54.108 + set_desired_size(aligned_new_size); 54.109 + set_refill_waste_limit(initial_refill_waste_limit()); 54.110 } 54.111 54.112 void ThreadLocalAllocBuffer::initialize_statistics() { 54.113 @@ -248,31 +252,13 @@ 54.114 return init_sz; 54.115 } 54.116 54.117 -const size_t ThreadLocalAllocBuffer::max_size() { 54.118 - 54.119 - // TLABs can't be bigger than we can fill with a int[Integer.MAX_VALUE]. 54.120 - // This restriction could be removed by enabling filling with multiple arrays. 54.121 - // If we compute that the reasonable way as 54.122 - // header_size + ((sizeof(jint) * max_jint) / HeapWordSize) 54.123 - // we'll overflow on the multiply, so we do the divide first. 54.124 - // We actually lose a little by dividing first, 54.125 - // but that just makes the TLAB somewhat smaller than the biggest array, 54.126 - // which is fine, since we'll be able to fill that. 54.127 - 54.128 - size_t unaligned_max_size = typeArrayOopDesc::header_size(T_INT) + 54.129 - sizeof(jint) * 54.130 - ((juint) max_jint / (size_t) HeapWordSize); 54.131 - return align_size_down(unaligned_max_size, MinObjAlignment); 54.132 -} 54.133 - 54.134 void ThreadLocalAllocBuffer::print_stats(const char* tag) { 54.135 Thread* thrd = myThread(); 54.136 size_t waste = _gc_waste + _slow_refill_waste + _fast_refill_waste; 54.137 size_t alloc = _number_of_refills * _desired_size; 54.138 double waste_percent = alloc == 0 ? 0.0 : 54.139 100.0 * waste / alloc; 54.140 - size_t tlab_used = Universe::heap()->tlab_capacity(thrd) - 54.141 - Universe::heap()->unsafe_max_tlab_alloc(thrd); 54.142 + size_t tlab_used = Universe::heap()->tlab_used(thrd); 54.143 gclog_or_tty->print("TLAB: %s thread: " INTPTR_FORMAT " [id: %2d]" 54.144 " desired_size: " SIZE_FORMAT "KB" 54.145 " slow allocs: %d refill waste: " SIZE_FORMAT "B"
55.1 --- a/src/share/vm/memory/threadLocalAllocBuffer.hpp Thu Mar 20 10:34:48 2014 -0700 55.2 +++ b/src/share/vm/memory/threadLocalAllocBuffer.hpp Thu Mar 27 14:50:50 2014 -0700 55.3 @@ -45,7 +45,9 @@ 55.4 HeapWord* _end; // allocation end (excluding alignment_reserve) 55.5 size_t _desired_size; // desired size (including alignment_reserve) 55.6 size_t _refill_waste_limit; // hold onto tlab if free() is larger than this 55.7 + size_t _allocated_before_last_gc; // total bytes allocated up until the last gc 55.8 55.9 + static size_t _max_size; // maximum size of any TLAB 55.10 static unsigned _target_refills; // expected number of refills between GCs 55.11 55.12 unsigned _number_of_refills; 55.13 @@ -99,12 +101,13 @@ 55.14 static GlobalTLABStats* global_stats() { return _global_stats; } 55.15 55.16 public: 55.17 - ThreadLocalAllocBuffer() : _allocation_fraction(TLABAllocationWeight) { 55.18 + ThreadLocalAllocBuffer() : _allocation_fraction(TLABAllocationWeight), _allocated_before_last_gc(0) { 55.19 // do nothing. tlabs must be inited by initialize() calls 55.20 } 55.21 55.22 static const size_t min_size() { return align_object_size(MinTLABSize / HeapWordSize); } 55.23 - static const size_t max_size(); 55.24 + static const size_t max_size() { assert(_max_size != 0, "max_size not set up"); return _max_size; } 55.25 + static void set_max_size(size_t max_size) { _max_size = max_size; } 55.26 55.27 HeapWord* start() const { return _start; } 55.28 HeapWord* end() const { return _end; }
56.1 --- a/src/share/vm/memory/universe.cpp Thu Mar 20 10:34:48 2014 -0700 56.2 +++ b/src/share/vm/memory/universe.cpp Thu Mar 27 14:50:50 2014 -0700 56.3 @@ -816,6 +816,8 @@ 56.4 Universe::_collectedHeap = new GenCollectedHeap(gc_policy); 56.5 } 56.6 56.7 + ThreadLocalAllocBuffer::set_max_size(Universe::heap()->max_tlab_size()); 56.8 + 56.9 jint status = Universe::heap()->initialize(); 56.10 if (status != JNI_OK) { 56.11 return status;
57.1 --- a/src/share/vm/oops/instanceKlass.cpp Thu Mar 20 10:34:48 2014 -0700 57.2 +++ b/src/share/vm/oops/instanceKlass.cpp Thu Mar 27 14:50:50 2014 -0700 57.3 @@ -2234,15 +2234,7 @@ 57.4 for (int m = 0; m < methods()->length(); m++) { 57.5 MethodData* mdo = methods()->at(m)->method_data(); 57.6 if (mdo != NULL) { 57.7 - for (ProfileData* data = mdo->first_data(); 57.8 - mdo->is_valid(data); 57.9 - data = mdo->next_data(data)) { 57.10 - data->clean_weak_klass_links(is_alive); 57.11 - } 57.12 - ParametersTypeData* parameters = mdo->parameters_type_data(); 57.13 - if (parameters != NULL) { 57.14 - parameters->clean_weak_klass_links(is_alive); 57.15 - } 57.16 + mdo->clean_method_data(is_alive); 57.17 } 57.18 } 57.19 }
58.1 --- a/src/share/vm/oops/instanceKlass.hpp Thu Mar 20 10:34:48 2014 -0700 58.2 +++ b/src/share/vm/oops/instanceKlass.hpp Thu Mar 27 14:50:50 2014 -0700 58.3 @@ -306,7 +306,7 @@ 58.4 // three cases: 58.5 // NULL: no implementor. 58.6 // A Klass* that's not itself: one implementor. 58.7 - // Itsef: more than one implementors. 58.8 + // Itself: more than one implementors. 58.9 // embedded host klass follows here 58.10 // The embedded host klass only exists in an anonymous class for 58.11 // dynamic language support (JSR 292 enabled). The host class grants
59.1 --- a/src/share/vm/oops/methodData.cpp Thu Mar 20 10:34:48 2014 -0700 59.2 +++ b/src/share/vm/oops/methodData.cpp Thu Mar 27 14:50:50 2014 -0700 59.3 @@ -80,8 +80,42 @@ 59.4 _data = NULL; 59.5 } 59.6 59.7 +char* ProfileData::print_data_on_helper(const MethodData* md) const { 59.8 + DataLayout* dp = md->extra_data_base(); 59.9 + DataLayout* end = md->extra_data_limit(); 59.10 + stringStream ss; 59.11 + for (;; dp = MethodData::next_extra(dp)) { 59.12 + assert(dp < end, "moved past end of extra data"); 59.13 + switch(dp->tag()) { 59.14 + case DataLayout::speculative_trap_data_tag: 59.15 + if (dp->bci() == bci()) { 59.16 + SpeculativeTrapData* data = new SpeculativeTrapData(dp); 59.17 + int trap = data->trap_state(); 59.18 + char buf[100]; 59.19 + ss.print("trap/"); 59.20 + data->method()->print_short_name(&ss); 59.21 + ss.print("(%s) ", Deoptimization::format_trap_state(buf, sizeof(buf), trap)); 59.22 + } 59.23 + break; 59.24 + case DataLayout::bit_data_tag: 59.25 + break; 59.26 + case DataLayout::no_tag: 59.27 + case DataLayout::arg_info_data_tag: 59.28 + return ss.as_string(); 59.29 + break; 59.30 + default: 59.31 + fatal(err_msg("unexpected tag %d", dp->tag())); 59.32 + } 59.33 + } 59.34 + return NULL; 59.35 +} 59.36 + 59.37 +void ProfileData::print_data_on(outputStream* st, const MethodData* md) const { 59.38 + print_data_on(st, print_data_on_helper(md)); 59.39 +} 59.40 + 59.41 #ifndef PRODUCT 59.42 -void ProfileData::print_shared(outputStream* st, const char* name) const { 59.43 +void ProfileData::print_shared(outputStream* st, const char* name, const char* extra) const { 59.44 st->print("bci: %d", bci()); 59.45 st->fill_to(tab_width_one); 59.46 st->print("%s", name); 59.47 @@ -91,9 +125,13 @@ 59.48 char buf[100]; 59.49 st->print("trap(%s) ", Deoptimization::format_trap_state(buf, sizeof(buf), trap)); 59.50 } 59.51 + if (extra != NULL) { 59.52 + st->print(extra); 59.53 + } 59.54 int flags = data()->flags(); 59.55 - if (flags != 0) 59.56 + if (flags != 0) { 59.57 st->print("flags(%d) ", flags); 59.58 + } 59.59 } 59.60 59.61 void ProfileData::tab(outputStream* st, bool first) const { 59.62 @@ -109,8 +147,8 @@ 59.63 59.64 59.65 #ifndef PRODUCT 59.66 -void BitData::print_data_on(outputStream* st) const { 59.67 - print_shared(st, "BitData"); 59.68 +void BitData::print_data_on(outputStream* st, const char* extra) const { 59.69 + print_shared(st, "BitData", extra); 59.70 } 59.71 #endif // !PRODUCT 59.72 59.73 @@ -120,8 +158,8 @@ 59.74 // A CounterData corresponds to a simple counter. 59.75 59.76 #ifndef PRODUCT 59.77 -void CounterData::print_data_on(outputStream* st) const { 59.78 - print_shared(st, "CounterData"); 59.79 +void CounterData::print_data_on(outputStream* st, const char* extra) const { 59.80 + print_shared(st, "CounterData", extra); 59.81 st->print_cr("count(%u)", count()); 59.82 } 59.83 #endif // !PRODUCT 59.84 @@ -150,8 +188,8 @@ 59.85 } 59.86 59.87 #ifndef PRODUCT 59.88 -void JumpData::print_data_on(outputStream* st) const { 59.89 - print_shared(st, "JumpData"); 59.90 +void JumpData::print_data_on(outputStream* st, const char* extra) const { 59.91 + print_shared(st, "JumpData", extra); 59.92 st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); 59.93 } 59.94 #endif // !PRODUCT 59.95 @@ -332,8 +370,8 @@ 59.96 st->cr(); 59.97 } 59.98 59.99 -void CallTypeData::print_data_on(outputStream* st) const { 59.100 - CounterData::print_data_on(st); 59.101 +void CallTypeData::print_data_on(outputStream* st, const char* extra) const { 59.102 + CounterData::print_data_on(st, extra); 59.103 if (has_arguments()) { 59.104 tab(st, true); 59.105 st->print("argument types"); 59.106 @@ -346,8 +384,8 @@ 59.107 } 59.108 } 59.109 59.110 -void VirtualCallTypeData::print_data_on(outputStream* st) const { 59.111 - VirtualCallData::print_data_on(st); 59.112 +void VirtualCallTypeData::print_data_on(outputStream* st, const char* extra) const { 59.113 + VirtualCallData::print_data_on(st, extra); 59.114 if (has_arguments()) { 59.115 tab(st, true); 59.116 st->print("argument types"); 59.117 @@ -400,12 +438,12 @@ 59.118 } 59.119 } 59.120 } 59.121 -void ReceiverTypeData::print_data_on(outputStream* st) const { 59.122 - print_shared(st, "ReceiverTypeData"); 59.123 +void ReceiverTypeData::print_data_on(outputStream* st, const char* extra) const { 59.124 + print_shared(st, "ReceiverTypeData", extra); 59.125 print_receiver_data_on(st); 59.126 } 59.127 -void VirtualCallData::print_data_on(outputStream* st) const { 59.128 - print_shared(st, "VirtualCallData"); 59.129 +void VirtualCallData::print_data_on(outputStream* st, const char* extra) const { 59.130 + print_shared(st, "VirtualCallData", extra); 59.131 print_receiver_data_on(st); 59.132 } 59.133 #endif // !PRODUCT 59.134 @@ -456,8 +494,8 @@ 59.135 59.136 59.137 #ifndef PRODUCT 59.138 -void RetData::print_data_on(outputStream* st) const { 59.139 - print_shared(st, "RetData"); 59.140 +void RetData::print_data_on(outputStream* st, const char* extra) const { 59.141 + print_shared(st, "RetData", extra); 59.142 uint row; 59.143 int entries = 0; 59.144 for (row = 0; row < row_limit(); row++) { 59.145 @@ -491,8 +529,8 @@ 59.146 } 59.147 59.148 #ifndef PRODUCT 59.149 -void BranchData::print_data_on(outputStream* st) const { 59.150 - print_shared(st, "BranchData"); 59.151 +void BranchData::print_data_on(outputStream* st, const char* extra) const { 59.152 + print_shared(st, "BranchData", extra); 59.153 st->print_cr("taken(%u) displacement(%d)", 59.154 taken(), displacement()); 59.155 tab(st); 59.156 @@ -565,8 +603,8 @@ 59.157 } 59.158 59.159 #ifndef PRODUCT 59.160 -void MultiBranchData::print_data_on(outputStream* st) const { 59.161 - print_shared(st, "MultiBranchData"); 59.162 +void MultiBranchData::print_data_on(outputStream* st, const char* extra) const { 59.163 + print_shared(st, "MultiBranchData", extra); 59.164 st->print_cr("default_count(%u) displacement(%d)", 59.165 default_count(), default_displacement()); 59.166 int cases = number_of_cases(); 59.167 @@ -579,8 +617,8 @@ 59.168 #endif 59.169 59.170 #ifndef PRODUCT 59.171 -void ArgInfoData::print_data_on(outputStream* st) const { 59.172 - print_shared(st, "ArgInfoData"); 59.173 +void ArgInfoData::print_data_on(outputStream* st, const char* extra) const { 59.174 + print_shared(st, "ArgInfoData", extra); 59.175 int nargs = number_of_args(); 59.176 for (int i = 0; i < nargs; i++) { 59.177 st->print(" 0x%x", arg_modified(i)); 59.178 @@ -611,10 +649,17 @@ 59.179 } 59.180 59.181 #ifndef PRODUCT 59.182 -void ParametersTypeData::print_data_on(outputStream* st) const { 59.183 - st->print("parameter types"); 59.184 +void ParametersTypeData::print_data_on(outputStream* st, const char* extra) const { 59.185 + st->print("parameter types", extra); 59.186 _parameters.print_data_on(st); 59.187 } 59.188 + 59.189 +void SpeculativeTrapData::print_data_on(outputStream* st, const char* extra) const { 59.190 + print_shared(st, "SpeculativeTrapData", extra); 59.191 + tab(st); 59.192 + method()->print_short_name(st); 59.193 + st->cr(); 59.194 +} 59.195 #endif 59.196 59.197 // ================================================================== 59.198 @@ -740,7 +785,27 @@ 59.199 return DataLayout::compute_size_in_bytes(cell_count); 59.200 } 59.201 59.202 -int MethodData::compute_extra_data_count(int data_size, int empty_bc_count) { 59.203 +bool MethodData::is_speculative_trap_bytecode(Bytecodes::Code code) { 59.204 + // Bytecodes for which we may use speculation 59.205 + switch (code) { 59.206 + case Bytecodes::_checkcast: 59.207 + case Bytecodes::_instanceof: 59.208 + case Bytecodes::_aastore: 59.209 + case Bytecodes::_invokevirtual: 59.210 + case Bytecodes::_invokeinterface: 59.211 + case Bytecodes::_if_acmpeq: 59.212 + case Bytecodes::_if_acmpne: 59.213 + case Bytecodes::_invokestatic: 59.214 +#ifdef COMPILER2 59.215 + return UseTypeSpeculation; 59.216 +#endif 59.217 + default: 59.218 + return false; 59.219 + } 59.220 + return false; 59.221 +} 59.222 + 59.223 +int MethodData::compute_extra_data_count(int data_size, int empty_bc_count, bool needs_speculative_traps) { 59.224 if (ProfileTraps) { 59.225 // Assume that up to 3% of BCIs with no MDP will need to allocate one. 59.226 int extra_data_count = (uint)(empty_bc_count * 3) / 128 + 1; 59.227 @@ -751,7 +816,18 @@ 59.228 extra_data_count = one_percent_of_data; 59.229 if (extra_data_count > empty_bc_count) 59.230 extra_data_count = empty_bc_count; // no need for more 59.231 - return extra_data_count; 59.232 + 59.233 + // Make sure we have a minimum number of extra data slots to 59.234 + // allocate SpeculativeTrapData entries. We would want to have one 59.235 + // entry per compilation that inlines this method and for which 59.236 + // some type speculation assumption fails. So the room we need for 59.237 + // the SpeculativeTrapData entries doesn't directly depend on the 59.238 + // size of the method. Because it's hard to estimate, we reserve 59.239 + // space for an arbitrary number of entries. 59.240 + int spec_data_count = (needs_speculative_traps ? SpecTrapLimitExtraEntries : 0) * 59.241 + (SpeculativeTrapData::static_cell_count() + DataLayout::header_size_in_cells()); 59.242 + 59.243 + return MAX2(extra_data_count, spec_data_count); 59.244 } else { 59.245 return 0; 59.246 } 59.247 @@ -764,15 +840,17 @@ 59.248 BytecodeStream stream(method); 59.249 Bytecodes::Code c; 59.250 int empty_bc_count = 0; // number of bytecodes lacking data 59.251 + bool needs_speculative_traps = false; 59.252 while ((c = stream.next()) >= 0) { 59.253 int size_in_bytes = compute_data_size(&stream); 59.254 data_size += size_in_bytes; 59.255 if (size_in_bytes == 0) empty_bc_count += 1; 59.256 + needs_speculative_traps = needs_speculative_traps || is_speculative_trap_bytecode(c); 59.257 } 59.258 int object_size = in_bytes(data_offset()) + data_size; 59.259 59.260 // Add some extra DataLayout cells (at least one) to track stray traps. 59.261 - int extra_data_count = compute_extra_data_count(data_size, empty_bc_count); 59.262 + int extra_data_count = compute_extra_data_count(data_size, empty_bc_count, needs_speculative_traps); 59.263 object_size += extra_data_count * DataLayout::compute_size_in_bytes(0); 59.264 59.265 // Add a cell to record information about modified arguments. 59.266 @@ -988,7 +1066,8 @@ 59.267 } 59.268 59.269 // Initialize the MethodData* corresponding to a given method. 59.270 -MethodData::MethodData(methodHandle method, int size, TRAPS) { 59.271 +MethodData::MethodData(methodHandle method, int size, TRAPS) 59.272 + : _extra_data_lock(Monitor::leaf, "MDO extra data lock") { 59.273 No_Safepoint_Verifier no_safepoint; // init function atomic wrt GC 59.274 ResourceMark rm; 59.275 // Set the method back-pointer. 59.276 @@ -1004,18 +1083,23 @@ 59.277 _data[0] = 0; // apparently not set below. 59.278 BytecodeStream stream(method); 59.279 Bytecodes::Code c; 59.280 + bool needs_speculative_traps = false; 59.281 while ((c = stream.next()) >= 0) { 59.282 int size_in_bytes = initialize_data(&stream, data_size); 59.283 data_size += size_in_bytes; 59.284 if (size_in_bytes == 0) empty_bc_count += 1; 59.285 + needs_speculative_traps = needs_speculative_traps || is_speculative_trap_bytecode(c); 59.286 } 59.287 _data_size = data_size; 59.288 int object_size = in_bytes(data_offset()) + data_size; 59.289 59.290 // Add some extra DataLayout cells (at least one) to track stray traps. 59.291 - int extra_data_count = compute_extra_data_count(data_size, empty_bc_count); 59.292 + int extra_data_count = compute_extra_data_count(data_size, empty_bc_count, needs_speculative_traps); 59.293 int extra_size = extra_data_count * DataLayout::compute_size_in_bytes(0); 59.294 59.295 + // Let's zero the space for the extra data 59.296 + Copy::zero_to_bytes(((address)_data) + data_size, extra_size); 59.297 + 59.298 // Add a cell to record information about modified arguments. 59.299 // Set up _args_modified array after traps cells so that 59.300 // the code for traps cells works. 59.301 @@ -1027,17 +1111,17 @@ 59.302 int arg_data_size = DataLayout::compute_size_in_bytes(arg_size+1); 59.303 object_size += extra_size + arg_data_size; 59.304 59.305 - int args_cell = ParametersTypeData::compute_cell_count(method()); 59.306 + int parms_cell = ParametersTypeData::compute_cell_count(method()); 59.307 // If we are profiling parameters, we reserver an area near the end 59.308 // of the MDO after the slots for bytecodes (because there's no bci 59.309 // for method entry so they don't fit with the framework for the 59.310 // profiling of bytecodes). We store the offset within the MDO of 59.311 // this area (or -1 if no parameter is profiled) 59.312 - if (args_cell > 0) { 59.313 - object_size += DataLayout::compute_size_in_bytes(args_cell); 59.314 + if (parms_cell > 0) { 59.315 + object_size += DataLayout::compute_size_in_bytes(parms_cell); 59.316 _parameters_type_data_di = data_size + extra_size + arg_data_size; 59.317 DataLayout *dp = data_layout_at(data_size + extra_size + arg_data_size); 59.318 - dp->initialize(DataLayout::parameters_type_data_tag, 0, args_cell); 59.319 + dp->initialize(DataLayout::parameters_type_data_tag, 0, parms_cell); 59.320 } else { 59.321 _parameters_type_data_di = -1; 59.322 } 59.323 @@ -1128,39 +1212,114 @@ 59.324 break; 59.325 } 59.326 } 59.327 - return bci_to_extra_data(bci, false); 59.328 + return bci_to_extra_data(bci, NULL, false); 59.329 } 59.330 59.331 -// Translate a bci to its corresponding extra data, or NULL. 59.332 -ProfileData* MethodData::bci_to_extra_data(int bci, bool create_if_missing) { 59.333 - DataLayout* dp = extra_data_base(); 59.334 - DataLayout* end = extra_data_limit(); 59.335 - DataLayout* avail = NULL; 59.336 - for (; dp < end; dp = next_extra(dp)) { 59.337 +DataLayout* MethodData::next_extra(DataLayout* dp) { 59.338 + int nb_cells = 0; 59.339 + switch(dp->tag()) { 59.340 + case DataLayout::bit_data_tag: 59.341 + case DataLayout::no_tag: 59.342 + nb_cells = BitData::static_cell_count(); 59.343 + break; 59.344 + case DataLayout::speculative_trap_data_tag: 59.345 + nb_cells = SpeculativeTrapData::static_cell_count(); 59.346 + break; 59.347 + default: 59.348 + fatal(err_msg("unexpected tag %d", dp->tag())); 59.349 + } 59.350 + return (DataLayout*)((address)dp + DataLayout::compute_size_in_bytes(nb_cells)); 59.351 +} 59.352 + 59.353 +ProfileData* MethodData::bci_to_extra_data_helper(int bci, Method* m, DataLayout*& dp, bool concurrent) { 59.354 + DataLayout* end = extra_data_limit(); 59.355 + 59.356 + for (;; dp = next_extra(dp)) { 59.357 + assert(dp < end, "moved past end of extra data"); 59.358 // No need for "OrderAccess::load_acquire" ops, 59.359 // since the data structure is monotonic. 59.360 - if (dp->tag() == DataLayout::no_tag) break; 59.361 - if (dp->tag() == DataLayout::arg_info_data_tag) { 59.362 - dp = end; // ArgInfoData is at the end of extra data section. 59.363 + switch(dp->tag()) { 59.364 + case DataLayout::no_tag: 59.365 + return NULL; 59.366 + case DataLayout::arg_info_data_tag: 59.367 + dp = end; 59.368 + return NULL; // ArgInfoData is at the end of extra data section. 59.369 + case DataLayout::bit_data_tag: 59.370 + if (m == NULL && dp->bci() == bci) { 59.371 + return new BitData(dp); 59.372 + } 59.373 break; 59.374 - } 59.375 - if (dp->bci() == bci) { 59.376 - assert(dp->tag() == DataLayout::bit_data_tag, "sane"); 59.377 - return new BitData(dp); 59.378 + case DataLayout::speculative_trap_data_tag: 59.379 + if (m != NULL) { 59.380 + SpeculativeTrapData* data = new SpeculativeTrapData(dp); 59.381 + // data->method() may be null in case of a concurrent 59.382 + // allocation. Maybe it's for the same method. Try to use that 59.383 + // entry in that case. 59.384 + if (dp->bci() == bci) { 59.385 + if (data->method() == NULL) { 59.386 + assert(concurrent, "impossible because no concurrent allocation"); 59.387 + return NULL; 59.388 + } else if (data->method() == m) { 59.389 + return data; 59.390 + } 59.391 + } 59.392 + } 59.393 + break; 59.394 + default: 59.395 + fatal(err_msg("unexpected tag %d", dp->tag())); 59.396 } 59.397 } 59.398 + return NULL; 59.399 +} 59.400 + 59.401 + 59.402 +// Translate a bci to its corresponding extra data, or NULL. 59.403 +ProfileData* MethodData::bci_to_extra_data(int bci, Method* m, bool create_if_missing) { 59.404 + // This code assumes an entry for a SpeculativeTrapData is 2 cells 59.405 + assert(2*DataLayout::compute_size_in_bytes(BitData::static_cell_count()) == 59.406 + DataLayout::compute_size_in_bytes(SpeculativeTrapData::static_cell_count()), 59.407 + "code needs to be adjusted"); 59.408 + 59.409 + DataLayout* dp = extra_data_base(); 59.410 + DataLayout* end = extra_data_limit(); 59.411 + 59.412 + // Allocation in the extra data space has to be atomic because not 59.413 + // all entries have the same size and non atomic concurrent 59.414 + // allocation would result in a corrupted extra data space. 59.415 + ProfileData* result = bci_to_extra_data_helper(bci, m, dp, true); 59.416 + if (result != NULL) { 59.417 + return result; 59.418 + } 59.419 + 59.420 if (create_if_missing && dp < end) { 59.421 - // Allocate this one. There is no mutual exclusion, 59.422 - // so two threads could allocate different BCIs to the 59.423 - // same data layout. This means these extra data 59.424 - // records, like most other MDO contents, must not be 59.425 - // trusted too much. 59.426 + MutexLocker ml(&_extra_data_lock); 59.427 + // Check again now that we have the lock. Another thread may 59.428 + // have added extra data entries. 59.429 + ProfileData* result = bci_to_extra_data_helper(bci, m, dp, false); 59.430 + if (result != NULL || dp >= end) { 59.431 + return result; 59.432 + } 59.433 + 59.434 + assert(dp->tag() == DataLayout::no_tag || (dp->tag() == DataLayout::speculative_trap_data_tag && m != NULL), "should be free"); 59.435 + assert(next_extra(dp)->tag() == DataLayout::no_tag || next_extra(dp)->tag() == DataLayout::arg_info_data_tag, "should be free or arg info"); 59.436 + u1 tag = m == NULL ? DataLayout::bit_data_tag : DataLayout::speculative_trap_data_tag; 59.437 + // SpeculativeTrapData is 2 slots. Make sure we have room. 59.438 + if (m != NULL && next_extra(dp)->tag() != DataLayout::no_tag) { 59.439 + return NULL; 59.440 + } 59.441 DataLayout temp; 59.442 - temp.initialize(DataLayout::bit_data_tag, bci, 0); 59.443 - dp->release_set_header(temp.header()); 59.444 - assert(dp->tag() == DataLayout::bit_data_tag, "sane"); 59.445 - //NO: assert(dp->bci() == bci, "no concurrent allocation"); 59.446 - return new BitData(dp); 59.447 + temp.initialize(tag, bci, 0); 59.448 + 59.449 + dp->set_header(temp.header()); 59.450 + assert(dp->tag() == tag, "sane"); 59.451 + assert(dp->bci() == bci, "no concurrent allocation"); 59.452 + if (tag == DataLayout::bit_data_tag) { 59.453 + return new BitData(dp); 59.454 + } else { 59.455 + SpeculativeTrapData* data = new SpeculativeTrapData(dp); 59.456 + data->set_method(m); 59.457 + return data; 59.458 + } 59.459 } 59.460 return NULL; 59.461 } 59.462 @@ -1205,25 +1364,35 @@ 59.463 for ( ; is_valid(data); data = next_data(data)) { 59.464 st->print("%d", dp_to_di(data->dp())); 59.465 st->fill_to(6); 59.466 - data->print_data_on(st); 59.467 + data->print_data_on(st, this); 59.468 } 59.469 st->print_cr("--- Extra data:"); 59.470 DataLayout* dp = extra_data_base(); 59.471 DataLayout* end = extra_data_limit(); 59.472 - for (; dp < end; dp = next_extra(dp)) { 59.473 + for (;; dp = next_extra(dp)) { 59.474 + assert(dp < end, "moved past end of extra data"); 59.475 // No need for "OrderAccess::load_acquire" ops, 59.476 // since the data structure is monotonic. 59.477 - if (dp->tag() == DataLayout::no_tag) continue; 59.478 - if (dp->tag() == DataLayout::bit_data_tag) { 59.479 + switch(dp->tag()) { 59.480 + case DataLayout::no_tag: 59.481 + continue; 59.482 + case DataLayout::bit_data_tag: 59.483 data = new BitData(dp); 59.484 - } else { 59.485 - assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo"); 59.486 + break; 59.487 + case DataLayout::speculative_trap_data_tag: 59.488 + data = new SpeculativeTrapData(dp); 59.489 + break; 59.490 + case DataLayout::arg_info_data_tag: 59.491 data = new ArgInfoData(dp); 59.492 dp = end; // ArgInfoData is at the end of extra data section. 59.493 + break; 59.494 + default: 59.495 + fatal(err_msg("unexpected tag %d", dp->tag())); 59.496 } 59.497 st->print("%d", dp_to_di(data->dp())); 59.498 st->fill_to(6); 59.499 data->print_data_on(st); 59.500 + if (dp >= end) return; 59.501 } 59.502 } 59.503 #endif 59.504 @@ -1346,3 +1515,110 @@ 59.505 assert(profile_parameters_jsr292_only(), "inconsistent"); 59.506 return m->is_compiled_lambda_form(); 59.507 } 59.508 + 59.509 +void MethodData::clean_extra_data_helper(DataLayout* dp, int shift, bool reset) { 59.510 + if (shift == 0) { 59.511 + return; 59.512 + } 59.513 + if (!reset) { 59.514 + // Move all cells of trap entry at dp left by "shift" cells 59.515 + intptr_t* start = (intptr_t*)dp; 59.516 + intptr_t* end = (intptr_t*)next_extra(dp); 59.517 + for (intptr_t* ptr = start; ptr < end; ptr++) { 59.518 + *(ptr-shift) = *ptr; 59.519 + } 59.520 + } else { 59.521 + // Reset "shift" cells stopping at dp 59.522 + intptr_t* start = ((intptr_t*)dp) - shift; 59.523 + intptr_t* end = (intptr_t*)dp; 59.524 + for (intptr_t* ptr = start; ptr < end; ptr++) { 59.525 + *ptr = 0; 59.526 + } 59.527 + } 59.528 +} 59.529 + 59.530 +// Remove SpeculativeTrapData entries that reference an unloaded 59.531 +// method 59.532 +void MethodData::clean_extra_data(BoolObjectClosure* is_alive) { 59.533 + DataLayout* dp = extra_data_base(); 59.534 + DataLayout* end = extra_data_limit(); 59.535 + 59.536 + int shift = 0; 59.537 + for (; dp < end; dp = next_extra(dp)) { 59.538 + switch(dp->tag()) { 59.539 + case DataLayout::speculative_trap_data_tag: { 59.540 + SpeculativeTrapData* data = new SpeculativeTrapData(dp); 59.541 + Method* m = data->method(); 59.542 + assert(m != NULL, "should have a method"); 59.543 + if (!m->method_holder()->is_loader_alive(is_alive)) { 59.544 + // "shift" accumulates the number of cells for dead 59.545 + // SpeculativeTrapData entries that have been seen so 59.546 + // far. Following entries must be shifted left by that many 59.547 + // cells to remove the dead SpeculativeTrapData entries. 59.548 + shift += (int)((intptr_t*)next_extra(dp) - (intptr_t*)dp); 59.549 + } else { 59.550 + // Shift this entry left if it follows dead 59.551 + // SpeculativeTrapData entries 59.552 + clean_extra_data_helper(dp, shift); 59.553 + } 59.554 + break; 59.555 + } 59.556 + case DataLayout::bit_data_tag: 59.557 + // Shift this entry left if it follows dead SpeculativeTrapData 59.558 + // entries 59.559 + clean_extra_data_helper(dp, shift); 59.560 + continue; 59.561 + case DataLayout::no_tag: 59.562 + case DataLayout::arg_info_data_tag: 59.563 + // We are at end of the live trap entries. The previous "shift" 59.564 + // cells contain entries that are either dead or were shifted 59.565 + // left. They need to be reset to no_tag 59.566 + clean_extra_data_helper(dp, shift, true); 59.567 + return; 59.568 + default: 59.569 + fatal(err_msg("unexpected tag %d", dp->tag())); 59.570 + } 59.571 + } 59.572 +} 59.573 + 59.574 +// Verify there's no unloaded method referenced by a 59.575 +// SpeculativeTrapData entry 59.576 +void MethodData::verify_extra_data_clean(BoolObjectClosure* is_alive) { 59.577 +#ifdef ASSERT 59.578 + DataLayout* dp = extra_data_base(); 59.579 + DataLayout* end = extra_data_limit(); 59.580 + 59.581 + for (; dp < end; dp = next_extra(dp)) { 59.582 + switch(dp->tag()) { 59.583 + case DataLayout::speculative_trap_data_tag: { 59.584 + SpeculativeTrapData* data = new SpeculativeTrapData(dp); 59.585 + Method* m = data->method(); 59.586 + assert(m != NULL && m->method_holder()->is_loader_alive(is_alive), "Method should exist"); 59.587 + break; 59.588 + } 59.589 + case DataLayout::bit_data_tag: 59.590 + continue; 59.591 + case DataLayout::no_tag: 59.592 + case DataLayout::arg_info_data_tag: 59.593 + return; 59.594 + default: 59.595 + fatal(err_msg("unexpected tag %d", dp->tag())); 59.596 + } 59.597 + } 59.598 +#endif 59.599 +} 59.600 + 59.601 +void MethodData::clean_method_data(BoolObjectClosure* is_alive) { 59.602 + for (ProfileData* data = first_data(); 59.603 + is_valid(data); 59.604 + data = next_data(data)) { 59.605 + data->clean_weak_klass_links(is_alive); 59.606 + } 59.607 + ParametersTypeData* parameters = parameters_type_data(); 59.608 + if (parameters != NULL) { 59.609 + parameters->clean_weak_klass_links(is_alive); 59.610 + } 59.611 + 59.612 + clean_extra_data(is_alive); 59.613 + verify_extra_data_clean(is_alive); 59.614 +}
60.1 --- a/src/share/vm/oops/methodData.hpp Thu Mar 20 10:34:48 2014 -0700 60.2 +++ b/src/share/vm/oops/methodData.hpp Thu Mar 27 14:50:50 2014 -0700 60.3 @@ -120,7 +120,8 @@ 60.4 arg_info_data_tag, 60.5 call_type_data_tag, 60.6 virtual_call_type_data_tag, 60.7 - parameters_type_data_tag 60.8 + parameters_type_data_tag, 60.9 + speculative_trap_data_tag 60.10 }; 60.11 60.12 enum { 60.13 @@ -189,9 +190,6 @@ 60.14 void set_header(intptr_t value) { 60.15 _header._bits = value; 60.16 } 60.17 - void release_set_header(intptr_t value) { 60.18 - OrderAccess::release_store_ptr(&_header._bits, value); 60.19 - } 60.20 intptr_t header() { 60.21 return _header._bits; 60.22 } 60.23 @@ -266,6 +264,7 @@ 60.24 class MultiBranchData; 60.25 class ArgInfoData; 60.26 class ParametersTypeData; 60.27 +class SpeculativeTrapData; 60.28 60.29 // ProfileData 60.30 // 60.31 @@ -286,6 +285,8 @@ 60.32 // This is a pointer to a section of profiling data. 60.33 DataLayout* _data; 60.34 60.35 + char* print_data_on_helper(const MethodData* md) const; 60.36 + 60.37 protected: 60.38 DataLayout* data() { return _data; } 60.39 const DataLayout* data() const { return _data; } 60.40 @@ -400,6 +401,7 @@ 60.41 virtual bool is_CallTypeData() const { return false; } 60.42 virtual bool is_VirtualCallTypeData()const { return false; } 60.43 virtual bool is_ParametersTypeData() const { return false; } 60.44 + virtual bool is_SpeculativeTrapData()const { return false; } 60.45 60.46 60.47 BitData* as_BitData() const { 60.48 @@ -454,6 +456,10 @@ 60.49 assert(is_ParametersTypeData(), "wrong type"); 60.50 return is_ParametersTypeData() ? (ParametersTypeData*)this : NULL; 60.51 } 60.52 + SpeculativeTrapData* as_SpeculativeTrapData() const { 60.53 + assert(is_SpeculativeTrapData(), "wrong type"); 60.54 + return is_SpeculativeTrapData() ? (SpeculativeTrapData*)this : NULL; 60.55 + } 60.56 60.57 60.58 // Subclass specific initialization 60.59 @@ -469,12 +475,14 @@ 60.60 // translation here, and the required translators are in the ci subclasses. 60.61 virtual void translate_from(const ProfileData* data) {} 60.62 60.63 - virtual void print_data_on(outputStream* st) const { 60.64 + virtual void print_data_on(outputStream* st, const char* extra = NULL) const { 60.65 ShouldNotReachHere(); 60.66 } 60.67 60.68 + void print_data_on(outputStream* st, const MethodData* md) const; 60.69 + 60.70 #ifndef PRODUCT 60.71 - void print_shared(outputStream* st, const char* name) const; 60.72 + void print_shared(outputStream* st, const char* name, const char* extra) const; 60.73 void tab(outputStream* st, bool first = false) const; 60.74 #endif 60.75 }; 60.76 @@ -522,7 +530,7 @@ 60.77 } 60.78 60.79 #ifndef PRODUCT 60.80 - void print_data_on(outputStream* st) const; 60.81 + void print_data_on(outputStream* st, const char* extra = NULL) const; 60.82 #endif 60.83 }; 60.84 60.85 @@ -566,7 +574,7 @@ 60.86 } 60.87 60.88 #ifndef PRODUCT 60.89 - void print_data_on(outputStream* st) const; 60.90 + void print_data_on(outputStream* st, const char* extra = NULL) const; 60.91 #endif 60.92 }; 60.93 60.94 @@ -639,7 +647,7 @@ 60.95 void post_initialize(BytecodeStream* stream, MethodData* mdo); 60.96 60.97 #ifndef PRODUCT 60.98 - void print_data_on(outputStream* st) const; 60.99 + void print_data_on(outputStream* st, const char* extra = NULL) const; 60.100 #endif 60.101 }; 60.102 60.103 @@ -1050,7 +1058,7 @@ 60.104 } 60.105 60.106 #ifndef PRODUCT 60.107 - virtual void print_data_on(outputStream* st) const; 60.108 + virtual void print_data_on(outputStream* st, const char* extra = NULL) const; 60.109 #endif 60.110 }; 60.111 60.112 @@ -1158,7 +1166,7 @@ 60.113 60.114 #ifndef PRODUCT 60.115 void print_receiver_data_on(outputStream* st) const; 60.116 - void print_data_on(outputStream* st) const; 60.117 + void print_data_on(outputStream* st, const char* extra = NULL) const; 60.118 #endif 60.119 }; 60.120 60.121 @@ -1191,7 +1199,7 @@ 60.122 } 60.123 60.124 #ifndef PRODUCT 60.125 - void print_data_on(outputStream* st) const; 60.126 + void print_data_on(outputStream* st, const char* extra = NULL) const; 60.127 #endif 60.128 }; 60.129 60.130 @@ -1317,7 +1325,7 @@ 60.131 } 60.132 60.133 #ifndef PRODUCT 60.134 - virtual void print_data_on(outputStream* st) const; 60.135 + virtual void print_data_on(outputStream* st, const char* extra = NULL) const; 60.136 #endif 60.137 }; 60.138 60.139 @@ -1416,7 +1424,7 @@ 60.140 void post_initialize(BytecodeStream* stream, MethodData* mdo); 60.141 60.142 #ifndef PRODUCT 60.143 - void print_data_on(outputStream* st) const; 60.144 + void print_data_on(outputStream* st, const char* extra = NULL) const; 60.145 #endif 60.146 }; 60.147 60.148 @@ -1480,7 +1488,7 @@ 60.149 void post_initialize(BytecodeStream* stream, MethodData* mdo); 60.150 60.151 #ifndef PRODUCT 60.152 - void print_data_on(outputStream* st) const; 60.153 + void print_data_on(outputStream* st, const char* extra = NULL) const; 60.154 #endif 60.155 }; 60.156 60.157 @@ -1637,7 +1645,7 @@ 60.158 void post_initialize(BytecodeStream* stream, MethodData* mdo); 60.159 60.160 #ifndef PRODUCT 60.161 - void print_data_on(outputStream* st) const; 60.162 + void print_data_on(outputStream* st, const char* extra = NULL) const; 60.163 #endif 60.164 }; 60.165 60.166 @@ -1664,7 +1672,7 @@ 60.167 } 60.168 60.169 #ifndef PRODUCT 60.170 - void print_data_on(outputStream* st) const; 60.171 + void print_data_on(outputStream* st, const char* extra = NULL) const; 60.172 #endif 60.173 }; 60.174 60.175 @@ -1725,7 +1733,7 @@ 60.176 } 60.177 60.178 #ifndef PRODUCT 60.179 - virtual void print_data_on(outputStream* st) const; 60.180 + virtual void print_data_on(outputStream* st, const char* extra = NULL) const; 60.181 #endif 60.182 60.183 static ByteSize stack_slot_offset(int i) { 60.184 @@ -1737,6 +1745,54 @@ 60.185 } 60.186 }; 60.187 60.188 +// SpeculativeTrapData 60.189 +// 60.190 +// A SpeculativeTrapData is used to record traps due to type 60.191 +// speculation. It records the root of the compilation: that type 60.192 +// speculation is wrong in the context of one compilation (for 60.193 +// method1) doesn't mean it's wrong in the context of another one (for 60.194 +// method2). Type speculation could have more/different data in the 60.195 +// context of the compilation of method2 and it's worthwhile to try an 60.196 +// optimization that failed for compilation of method1 in the context 60.197 +// of compilation of method2. 60.198 +// Space for SpeculativeTrapData entries is allocated from the extra 60.199 +// data space in the MDO. If we run out of space, the trap data for 60.200 +// the ProfileData at that bci is updated. 60.201 +class SpeculativeTrapData : public ProfileData { 60.202 +protected: 60.203 + enum { 60.204 + method_offset, 60.205 + speculative_trap_cell_count 60.206 + }; 60.207 +public: 60.208 + SpeculativeTrapData(DataLayout* layout) : ProfileData(layout) { 60.209 + assert(layout->tag() == DataLayout::speculative_trap_data_tag, "wrong type"); 60.210 + } 60.211 + 60.212 + virtual bool is_SpeculativeTrapData() const { return true; } 60.213 + 60.214 + static int static_cell_count() { 60.215 + return speculative_trap_cell_count; 60.216 + } 60.217 + 60.218 + virtual int cell_count() const { 60.219 + return static_cell_count(); 60.220 + } 60.221 + 60.222 + // Direct accessor 60.223 + Method* method() const { 60.224 + return (Method*)intptr_at(method_offset); 60.225 + } 60.226 + 60.227 + void set_method(Method* m) { 60.228 + set_intptr_at(method_offset, (intptr_t)m); 60.229 + } 60.230 + 60.231 +#ifndef PRODUCT 60.232 + virtual void print_data_on(outputStream* st, const char* extra = NULL) const; 60.233 +#endif 60.234 +}; 60.235 + 60.236 // MethodData* 60.237 // 60.238 // A MethodData* holds information which has been collected about 60.239 @@ -1794,16 +1850,18 @@ 60.240 // Cached hint for bci_to_dp and bci_to_data 60.241 int _hint_di; 60.242 60.243 + Mutex _extra_data_lock; 60.244 + 60.245 MethodData(methodHandle method, int size, TRAPS); 60.246 public: 60.247 static MethodData* allocate(ClassLoaderData* loader_data, methodHandle method, TRAPS); 60.248 - MethodData() {}; // For ciMethodData 60.249 + MethodData() : _extra_data_lock(Monitor::leaf, "MDO extra data lock") {}; // For ciMethodData 60.250 60.251 bool is_methodData() const volatile { return true; } 60.252 60.253 // Whole-method sticky bits and flags 60.254 enum { 60.255 - _trap_hist_limit = 17, // decoupled from Deoptimization::Reason_LIMIT 60.256 + _trap_hist_limit = 18, // decoupled from Deoptimization::Reason_LIMIT 60.257 _trap_hist_mask = max_jubyte, 60.258 _extra_data_count = 4 // extra DataLayout headers, for trap history 60.259 }; // Public flag values 60.260 @@ -1858,6 +1916,7 @@ 60.261 // Helper for size computation 60.262 static int compute_data_size(BytecodeStream* stream); 60.263 static int bytecode_cell_count(Bytecodes::Code code); 60.264 + static bool is_speculative_trap_bytecode(Bytecodes::Code code); 60.265 enum { no_profile_data = -1, variable_cell_count = -2 }; 60.266 60.267 // Helper for initialization 60.268 @@ -1901,8 +1960,9 @@ 60.269 // What is the index of the first data entry? 60.270 int first_di() const { return 0; } 60.271 60.272 + ProfileData* bci_to_extra_data_helper(int bci, Method* m, DataLayout*& dp, bool concurrent); 60.273 // Find or create an extra ProfileData: 60.274 - ProfileData* bci_to_extra_data(int bci, bool create_if_missing); 60.275 + ProfileData* bci_to_extra_data(int bci, Method* m, bool create_if_missing); 60.276 60.277 // return the argument info cell 60.278 ArgInfoData *arg_info(); 60.279 @@ -1925,6 +1985,10 @@ 60.280 static bool profile_parameters_jsr292_only(); 60.281 static bool profile_all_parameters(); 60.282 60.283 + void clean_extra_data(BoolObjectClosure* is_alive); 60.284 + void clean_extra_data_helper(DataLayout* dp, int shift, bool reset = false); 60.285 + void verify_extra_data_clean(BoolObjectClosure* is_alive); 60.286 + 60.287 public: 60.288 static int header_size() { 60.289 return sizeof(MethodData)/wordSize; 60.290 @@ -1933,7 +1997,7 @@ 60.291 // Compute the size of a MethodData* before it is created. 60.292 static int compute_allocation_size_in_bytes(methodHandle method); 60.293 static int compute_allocation_size_in_words(methodHandle method); 60.294 - static int compute_extra_data_count(int data_size, int empty_bc_count); 60.295 + static int compute_extra_data_count(int data_size, int empty_bc_count, bool needs_speculative_traps); 60.296 60.297 // Determine if a given bytecode can have profile information. 60.298 static bool bytecode_has_profile(Bytecodes::Code code) { 60.299 @@ -2074,9 +2138,26 @@ 60.300 ProfileData* bci_to_data(int bci); 60.301 60.302 // Same, but try to create an extra_data record if one is needed: 60.303 - ProfileData* allocate_bci_to_data(int bci) { 60.304 - ProfileData* data = bci_to_data(bci); 60.305 - return (data != NULL) ? data : bci_to_extra_data(bci, true); 60.306 + ProfileData* allocate_bci_to_data(int bci, Method* m) { 60.307 + ProfileData* data = NULL; 60.308 + // If m not NULL, try to allocate a SpeculativeTrapData entry 60.309 + if (m == NULL) { 60.310 + data = bci_to_data(bci); 60.311 + } 60.312 + if (data != NULL) { 60.313 + return data; 60.314 + } 60.315 + data = bci_to_extra_data(bci, m, true); 60.316 + if (data != NULL) { 60.317 + return data; 60.318 + } 60.319 + // If SpeculativeTrapData allocation fails try to allocate a 60.320 + // regular entry 60.321 + data = bci_to_data(bci); 60.322 + if (data != NULL) { 60.323 + return data; 60.324 + } 60.325 + return bci_to_extra_data(bci, NULL, true); 60.326 } 60.327 60.328 // Add a handful of extra data records, for trap tracking. 60.329 @@ -2084,7 +2165,7 @@ 60.330 DataLayout* extra_data_limit() const { return (DataLayout*)((address)this + size_in_bytes()); } 60.331 int extra_data_size() const { return (address)extra_data_limit() 60.332 - (address)extra_data_base(); } 60.333 - static DataLayout* next_extra(DataLayout* dp) { return (DataLayout*)((address)dp + in_bytes(DataLayout::cell_offset(0))); } 60.334 + static DataLayout* next_extra(DataLayout* dp); 60.335 60.336 // Return (uint)-1 for overflow. 60.337 uint trap_count(int reason) const { 60.338 @@ -2184,6 +2265,8 @@ 60.339 static bool profile_return(); 60.340 static bool profile_parameters(); 60.341 static bool profile_return_jsr292_only(); 60.342 + 60.343 + void clean_method_data(BoolObjectClosure* is_alive); 60.344 }; 60.345 60.346 #endif // SHARE_VM_OOPS_METHODDATAOOP_HPP
61.1 --- a/src/share/vm/opto/c2_globals.hpp Thu Mar 20 10:34:48 2014 -0700 61.2 +++ b/src/share/vm/opto/c2_globals.hpp Thu Mar 27 14:50:50 2014 -0700 61.3 @@ -637,14 +637,19 @@ 61.4 diagnostic(bool, OptimizeExpensiveOps, true, \ 61.5 "Find best control for expensive operations") \ 61.6 \ 61.7 - experimental(bool, UseMathExactIntrinsics, false, \ 61.8 + product(bool, UseMathExactIntrinsics, true, \ 61.9 "Enables intrinsification of various java.lang.Math functions") \ 61.10 \ 61.11 experimental(bool, ReplaceInParentMaps, false, \ 61.12 "Propagate type improvements in callers of inlinee if possible") \ 61.13 \ 61.14 - experimental(bool, UseTypeSpeculation, false, \ 61.15 - "Speculatively propagate types from profiles") 61.16 + product(bool, UseTypeSpeculation, true, \ 61.17 + "Speculatively propagate types from profiles") \ 61.18 + \ 61.19 + diagnostic(bool, UseInlineDepthForSpeculativeTypes, true, \ 61.20 + "Carry inline depth of profile point with speculative type " \ 61.21 + "and give priority to profiling from lower inline depth") \ 61.22 + 61.23 61.24 C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG) 61.25
62.1 --- a/src/share/vm/opto/classes.hpp Thu Mar 20 10:34:48 2014 -0700 62.2 +++ b/src/share/vm/opto/classes.hpp Thu Mar 27 14:50:50 2014 -0700 62.3 @@ -29,8 +29,6 @@ 62.4 macro(AbsF) 62.5 macro(AbsI) 62.6 macro(AddD) 62.7 -macro(AddExactI) 62.8 -macro(AddExactL) 62.9 macro(AddF) 62.10 macro(AddI) 62.11 macro(AddL) 62.12 @@ -135,7 +133,6 @@ 62.13 macro(ExpD) 62.14 macro(FastLock) 62.15 macro(FastUnlock) 62.16 -macro(FlagsProj) 62.17 macro(Goto) 62.18 macro(Halt) 62.19 macro(If) 62.20 @@ -170,9 +167,6 @@ 62.21 macro(LoopLimit) 62.22 macro(Mach) 62.23 macro(MachProj) 62.24 -macro(MathExact) 62.25 -macro(MathExactI) 62.26 -macro(MathExactL) 62.27 macro(MaxI) 62.28 macro(MemBarAcquire) 62.29 macro(MemBarAcquireLock) 62.30 @@ -192,22 +186,24 @@ 62.31 macro(MoveL2D) 62.32 macro(MoveD2L) 62.33 macro(MulD) 62.34 -macro(MulExactI) 62.35 -macro(MulExactL) 62.36 macro(MulF) 62.37 macro(MulHiL) 62.38 macro(MulI) 62.39 macro(MulL) 62.40 macro(Multi) 62.41 macro(NegD) 62.42 -macro(NegExactI) 62.43 -macro(NegExactL) 62.44 macro(NegF) 62.45 macro(NeverBranch) 62.46 macro(Opaque1) 62.47 macro(Opaque2) 62.48 macro(OrI) 62.49 macro(OrL) 62.50 +macro(OverflowAddI) 62.51 +macro(OverflowSubI) 62.52 +macro(OverflowMulI) 62.53 +macro(OverflowAddL) 62.54 +macro(OverflowSubL) 62.55 +macro(OverflowMulL) 62.56 macro(PCTable) 62.57 macro(Parm) 62.58 macro(PartialSubtypeCheck) 62.59 @@ -251,8 +247,6 @@ 62.60 macro(StrEquals) 62.61 macro(StrIndexOf) 62.62 macro(SubD) 62.63 -macro(SubExactI) 62.64 -macro(SubExactL) 62.65 macro(SubF) 62.66 macro(SubI) 62.67 macro(SubL)
63.1 --- a/src/share/vm/opto/compile.cpp Thu Mar 20 10:34:48 2014 -0700 63.2 +++ b/src/share/vm/opto/compile.cpp Thu Mar 27 14:50:50 2014 -0700 63.3 @@ -3012,42 +3012,6 @@ 63.4 n->set_req(MemBarNode::Precedent, top()); 63.5 } 63.6 break; 63.7 - // Must set a control edge on all nodes that produce a FlagsProj 63.8 - // so they can't escape the block that consumes the flags. 63.9 - // Must also set the non throwing branch as the control 63.10 - // for all nodes that depends on the result. Unless the node 63.11 - // already have a control that isn't the control of the 63.12 - // flag producer 63.13 - case Op_FlagsProj: 63.14 - { 63.15 - MathExactNode* math = (MathExactNode*) n->in(0); 63.16 - Node* ctrl = math->control_node(); 63.17 - Node* non_throwing = math->non_throwing_branch(); 63.18 - math->set_req(0, ctrl); 63.19 - 63.20 - Node* result = math->result_node(); 63.21 - if (result != NULL) { 63.22 - for (DUIterator_Fast jmax, j = result->fast_outs(jmax); j < jmax; j++) { 63.23 - Node* out = result->fast_out(j); 63.24 - // Phi nodes shouldn't be moved. They would only match below if they 63.25 - // had the same control as the MathExactNode. The only time that 63.26 - // would happen is if the Phi is also an input to the MathExact 63.27 - // 63.28 - // Cmp nodes shouldn't have control set at all. 63.29 - if (out->is_Phi() || 63.30 - out->is_Cmp()) { 63.31 - continue; 63.32 - } 63.33 - 63.34 - if (out->in(0) == NULL) { 63.35 - out->set_req(0, non_throwing); 63.36 - } else if (out->in(0) == ctrl) { 63.37 - out->set_req(0, non_throwing); 63.38 - } 63.39 - } 63.40 - } 63.41 - } 63.42 - break; 63.43 default: 63.44 assert( !n->is_Call(), "" ); 63.45 assert( !n->is_Mem(), "" ); 63.46 @@ -3269,7 +3233,8 @@ 63.47 // because of a transient condition during start-up in the interpreter. 63.48 return false; 63.49 } 63.50 - if (md->has_trap_at(bci, reason) != 0) { 63.51 + ciMethod* m = Deoptimization::reason_is_speculate(reason) ? this->method() : NULL; 63.52 + if (md->has_trap_at(bci, m, reason) != 0) { 63.53 // Assume PerBytecodeTrapLimit==0, for a more conservative heuristic. 63.54 // Also, if there are multiple reasons, or if there is no per-BCI record, 63.55 // assume the worst. 63.56 @@ -3287,7 +3252,7 @@ 63.57 // Less-accurate variant which does not require a method and bci. 63.58 bool Compile::too_many_traps(Deoptimization::DeoptReason reason, 63.59 ciMethodData* logmd) { 63.60 - if (trap_count(reason) >= (uint)PerMethodTrapLimit) { 63.61 + if (trap_count(reason) >= Deoptimization::per_method_trap_limit(reason)) { 63.62 // Too many traps globally. 63.63 // Note that we use cumulative trap_count, not just md->trap_count. 63.64 if (log()) { 63.65 @@ -3322,10 +3287,11 @@ 63.66 uint m_cutoff = (uint) PerMethodRecompilationCutoff / 2 + 1; // not zero 63.67 Deoptimization::DeoptReason per_bc_reason 63.68 = Deoptimization::reason_recorded_per_bytecode_if_any(reason); 63.69 + ciMethod* m = Deoptimization::reason_is_speculate(reason) ? this->method() : NULL; 63.70 if ((per_bc_reason == Deoptimization::Reason_none 63.71 - || md->has_trap_at(bci, reason) != 0) 63.72 + || md->has_trap_at(bci, m, reason) != 0) 63.73 // The trap frequency measure we care about is the recompile count: 63.74 - && md->trap_recompiled_at(bci) 63.75 + && md->trap_recompiled_at(bci, m) 63.76 && md->overflow_recompile_count() >= bc_cutoff) { 63.77 // Do not emit a trap here if it has already caused recompilations. 63.78 // Also, if there are multiple reasons, or if there is no per-BCI record,
64.1 --- a/src/share/vm/opto/doCall.cpp Thu Mar 20 10:34:48 2014 -0700 64.2 +++ b/src/share/vm/opto/doCall.cpp Thu Mar 27 14:50:50 2014 -0700 64.3 @@ -250,7 +250,7 @@ 64.4 CallGenerator* miss_cg; 64.5 Deoptimization::DeoptReason reason = morphism == 2 ? 64.6 Deoptimization::Reason_bimorphic : 64.7 - Deoptimization::Reason_class_check; 64.8 + (speculative_receiver_type == NULL ? Deoptimization::Reason_class_check : Deoptimization::Reason_speculate_class_check); 64.9 if ((morphism == 1 || (morphism == 2 && next_hit_cg != NULL)) && 64.10 !too_many_traps(jvms->method(), jvms->bci(), reason) 64.11 ) {
65.1 --- a/src/share/vm/opto/graphKit.cpp Thu Mar 20 10:34:48 2014 -0700 65.2 +++ b/src/share/vm/opto/graphKit.cpp Thu Mar 27 14:50:50 2014 -0700 65.3 @@ -611,9 +611,10 @@ 65.4 // Usual case: Bail to interpreter. 65.5 // Reserve the right to recompile if we haven't seen anything yet. 65.6 65.7 + assert(!Deoptimization::reason_is_speculate(reason), "unsupported"); 65.8 Deoptimization::DeoptAction action = Deoptimization::Action_maybe_recompile; 65.9 if (treat_throw_as_hot 65.10 - && (method()->method_data()->trap_recompiled_at(bci()) 65.11 + && (method()->method_data()->trap_recompiled_at(bci(), NULL) 65.12 || C->too_many_traps(reason))) { 65.13 // We cannot afford to take more traps here. Suffer in the interpreter. 65.14 if (C->log() != NULL) 65.15 @@ -2108,30 +2109,33 @@ 65.16 * @return node with improved type 65.17 */ 65.18 Node* GraphKit::record_profile_for_speculation(Node* n, ciKlass* exact_kls) { 65.19 - const TypeOopPtr* current_type = _gvn.type(n)->isa_oopptr(); 65.20 + const Type* current_type = _gvn.type(n); 65.21 assert(UseTypeSpeculation, "type speculation must be on"); 65.22 - if (exact_kls != NULL && 65.23 - // nothing to improve if type is already exact 65.24 - (current_type == NULL || 65.25 - (!current_type->klass_is_exact() && 65.26 - (current_type->speculative() == NULL || 65.27 - !current_type->speculative()->klass_is_exact())))) { 65.28 + 65.29 + const TypeOopPtr* speculative = current_type->speculative(); 65.30 + 65.31 + if (current_type->would_improve_type(exact_kls, jvms()->depth())) { 65.32 const TypeKlassPtr* tklass = TypeKlassPtr::make(exact_kls); 65.33 const TypeOopPtr* xtype = tklass->as_instance_type(); 65.34 assert(xtype->klass_is_exact(), "Should be exact"); 65.35 - 65.36 + // record the new speculative type's depth 65.37 + speculative = xtype->with_inline_depth(jvms()->depth()); 65.38 + } 65.39 + 65.40 + if (speculative != current_type->speculative()) { 65.41 // Build a type with a speculative type (what we think we know 65.42 // about the type but will need a guard when we use it) 65.43 - const TypeOopPtr* spec_type = TypeOopPtr::make(TypePtr::BotPTR, Type::OffsetBot, TypeOopPtr::InstanceBot, xtype); 65.44 - // We're changing the type, we need a new cast node to carry the 65.45 - // new type. The new type depends on the control: what profiling 65.46 - // tells us is only valid from here as far as we can tell. 65.47 - Node* cast = new(C) CastPPNode(n, spec_type); 65.48 - cast->init_req(0, control()); 65.49 + const TypeOopPtr* spec_type = TypeOopPtr::make(TypePtr::BotPTR, Type::OffsetBot, TypeOopPtr::InstanceBot, speculative); 65.50 + // We're changing the type, we need a new CheckCast node to carry 65.51 + // the new type. The new type depends on the control: what 65.52 + // profiling tells us is only valid from here as far as we can 65.53 + // tell. 65.54 + Node* cast = new(C) CheckCastPPNode(control(), n, current_type->remove_speculative()->join_speculative(spec_type)); 65.55 cast = _gvn.transform(cast); 65.56 replace_in_map(n, cast); 65.57 n = cast; 65.58 } 65.59 + 65.60 return n; 65.61 } 65.62 65.63 @@ -2141,7 +2145,7 @@ 65.64 * 65.65 * @param n receiver node 65.66 * 65.67 - * @return node with improved type 65.68 + * @return node with improved type 65.69 */ 65.70 Node* GraphKit::record_profiled_receiver_for_speculation(Node* n) { 65.71 if (!UseTypeSpeculation) { 65.72 @@ -2734,12 +2738,14 @@ 65.73 // Subsequent type checks will always fold up. 65.74 Node* GraphKit::maybe_cast_profiled_receiver(Node* not_null_obj, 65.75 ciKlass* require_klass, 65.76 - ciKlass* spec_klass, 65.77 + ciKlass* spec_klass, 65.78 bool safe_for_replace) { 65.79 if (!UseTypeProfile || !TypeProfileCasts) return NULL; 65.80 65.81 + Deoptimization::DeoptReason reason = spec_klass == NULL ? Deoptimization::Reason_class_check : Deoptimization::Reason_speculate_class_check; 65.82 + 65.83 // Make sure we haven't already deoptimized from this tactic. 65.84 - if (too_many_traps(Deoptimization::Reason_class_check)) 65.85 + if (too_many_traps(reason)) 65.86 return NULL; 65.87 65.88 // (No, this isn't a call, but it's enough like a virtual call 65.89 @@ -2761,7 +2767,7 @@ 65.90 &exact_obj); 65.91 { PreserveJVMState pjvms(this); 65.92 set_control(slow_ctl); 65.93 - uncommon_trap(Deoptimization::Reason_class_check, 65.94 + uncommon_trap(reason, 65.95 Deoptimization::Action_maybe_recompile); 65.96 } 65.97 if (safe_for_replace) { 65.98 @@ -2788,8 +2794,10 @@ 65.99 bool not_null) { 65.100 // type == NULL if profiling tells us this object is always null 65.101 if (type != NULL) { 65.102 - if (!too_many_traps(Deoptimization::Reason_null_check) && 65.103 - !too_many_traps(Deoptimization::Reason_class_check)) { 65.104 + Deoptimization::DeoptReason class_reason = Deoptimization::Reason_speculate_class_check; 65.105 + Deoptimization::DeoptReason null_reason = Deoptimization::Reason_null_check; 65.106 + if (!too_many_traps(null_reason) && 65.107 + !too_many_traps(class_reason)) { 65.108 Node* not_null_obj = NULL; 65.109 // not_null is true if we know the object is not null and 65.110 // there's no need for a null check 65.111 @@ -2808,7 +2816,7 @@ 65.112 { 65.113 PreserveJVMState pjvms(this); 65.114 set_control(slow_ctl); 65.115 - uncommon_trap(Deoptimization::Reason_class_check, 65.116 + uncommon_trap(class_reason, 65.117 Deoptimization::Action_maybe_recompile); 65.118 } 65.119 replace_in_map(not_null_obj, exact_obj); 65.120 @@ -2877,7 +2885,7 @@ 65.121 } 65.122 65.123 if (known_statically && UseTypeSpeculation) { 65.124 - // If we know the type check always succeed then we don't use the 65.125 + // If we know the type check always succeeds then we don't use the 65.126 // profiling data at this bytecode. Don't lose it, feed it to the 65.127 // type system as a speculative type. 65.128 not_null_obj = record_profiled_receiver_for_speculation(not_null_obj);
66.1 --- a/src/share/vm/opto/graphKit.hpp Thu Mar 20 10:34:48 2014 -0700 66.2 +++ b/src/share/vm/opto/graphKit.hpp Thu Mar 27 14:50:50 2014 -0700 66.3 @@ -406,7 +406,7 @@ 66.4 // Use the type profile to narrow an object type. 66.5 Node* maybe_cast_profiled_receiver(Node* not_null_obj, 66.6 ciKlass* require_klass, 66.7 - ciKlass* spec, 66.8 + ciKlass* spec, 66.9 bool safe_for_replace); 66.10 66.11 // Cast obj to type and emit guard unless we had too many traps here already
67.1 --- a/src/share/vm/opto/ifnode.cpp Thu Mar 20 10:34:48 2014 -0700 67.2 +++ b/src/share/vm/opto/ifnode.cpp Thu Mar 27 14:50:50 2014 -0700 67.3 @@ -76,7 +76,6 @@ 67.4 if( !i1->is_Bool() ) return NULL; 67.5 BoolNode *b = i1->as_Bool(); 67.6 Node *cmp = b->in(1); 67.7 - if( cmp->is_FlagsProj() ) return NULL; 67.8 if( !cmp->is_Cmp() ) return NULL; 67.9 i1 = cmp->in(1); 67.10 if( i1 == NULL || !i1->is_Phi() ) return NULL;
68.1 --- a/src/share/vm/opto/lcm.cpp Thu Mar 20 10:34:48 2014 -0700 68.2 +++ b/src/share/vm/opto/lcm.cpp Thu Mar 27 14:50:50 2014 -0700 68.3 @@ -472,13 +472,6 @@ 68.4 break; 68.5 } 68.6 68.7 - // For nodes that produce a FlagsProj, make the node adjacent to the 68.8 - // use of the FlagsProj 68.9 - if (use->is_FlagsProj() && get_block_for_node(use) == block) { 68.10 - found_machif = true; 68.11 - break; 68.12 - } 68.13 - 68.14 // More than this instruction pending for successor to be ready, 68.15 // don't choose this if other opportunities are ready 68.16 if (ready_cnt.at(use->_idx) > 1)
69.1 --- a/src/share/vm/opto/library_call.cpp Thu Mar 20 10:34:48 2014 -0700 69.2 +++ b/src/share/vm/opto/library_call.cpp Thu Mar 27 14:50:50 2014 -0700 69.3 @@ -203,7 +203,9 @@ 69.4 bool inline_math_native(vmIntrinsics::ID id); 69.5 bool inline_trig(vmIntrinsics::ID id); 69.6 bool inline_math(vmIntrinsics::ID id); 69.7 - void inline_math_mathExact(Node* math); 69.8 + template <typename OverflowOp> 69.9 + bool inline_math_overflow(Node* arg1, Node* arg2); 69.10 + void inline_math_mathExact(Node* math, Node* test); 69.11 bool inline_math_addExactI(bool is_increment); 69.12 bool inline_math_addExactL(bool is_increment); 69.13 bool inline_math_multiplyExactI(); 69.14 @@ -517,31 +519,31 @@ 69.15 69.16 case vmIntrinsics::_incrementExactI: 69.17 case vmIntrinsics::_addExactI: 69.18 - if (!Matcher::match_rule_supported(Op_AddExactI) || !UseMathExactIntrinsics) return NULL; 69.19 + if (!Matcher::match_rule_supported(Op_OverflowAddI) || !UseMathExactIntrinsics) return NULL; 69.20 break; 69.21 case vmIntrinsics::_incrementExactL: 69.22 case vmIntrinsics::_addExactL: 69.23 - if (!Matcher::match_rule_supported(Op_AddExactL) || !UseMathExactIntrinsics) return NULL; 69.24 + if (!Matcher::match_rule_supported(Op_OverflowAddL) || !UseMathExactIntrinsics) return NULL; 69.25 break; 69.26 case vmIntrinsics::_decrementExactI: 69.27 case vmIntrinsics::_subtractExactI: 69.28 - if (!Matcher::match_rule_supported(Op_SubExactI) || !UseMathExactIntrinsics) return NULL; 69.29 + if (!Matcher::match_rule_supported(Op_OverflowSubI) || !UseMathExactIntrinsics) return NULL; 69.30 break; 69.31 case vmIntrinsics::_decrementExactL: 69.32 case vmIntrinsics::_subtractExactL: 69.33 - if (!Matcher::match_rule_supported(Op_SubExactL) || !UseMathExactIntrinsics) return NULL; 69.34 + if (!Matcher::match_rule_supported(Op_OverflowSubL) || !UseMathExactIntrinsics) return NULL; 69.35 break; 69.36 case vmIntrinsics::_negateExactI: 69.37 - if (!Matcher::match_rule_supported(Op_NegExactI) || !UseMathExactIntrinsics) return NULL; 69.38 + if (!Matcher::match_rule_supported(Op_OverflowSubI) || !UseMathExactIntrinsics) return NULL; 69.39 break; 69.40 case vmIntrinsics::_negateExactL: 69.41 - if (!Matcher::match_rule_supported(Op_NegExactL) || !UseMathExactIntrinsics) return NULL; 69.42 + if (!Matcher::match_rule_supported(Op_OverflowSubL) || !UseMathExactIntrinsics) return NULL; 69.43 break; 69.44 case vmIntrinsics::_multiplyExactI: 69.45 - if (!Matcher::match_rule_supported(Op_MulExactI) || !UseMathExactIntrinsics) return NULL; 69.46 + if (!Matcher::match_rule_supported(Op_OverflowMulI) || !UseMathExactIntrinsics) return NULL; 69.47 break; 69.48 case vmIntrinsics::_multiplyExactL: 69.49 - if (!Matcher::match_rule_supported(Op_MulExactL) || !UseMathExactIntrinsics) return NULL; 69.50 + if (!Matcher::match_rule_supported(Op_OverflowMulL) || !UseMathExactIntrinsics) return NULL; 69.51 break; 69.52 69.53 default: 69.54 @@ -1970,18 +1972,8 @@ 69.55 return true; 69.56 } 69.57 69.58 -void LibraryCallKit::inline_math_mathExact(Node* math) { 69.59 - // If we didn't get the expected opcode it means we have optimized 69.60 - // the node to something else and don't need the exception edge. 69.61 - if (!math->is_MathExact()) { 69.62 - set_result(math); 69.63 - return; 69.64 - } 69.65 - 69.66 - Node* result = _gvn.transform( new(C) ProjNode(math, MathExactNode::result_proj_node)); 69.67 - Node* flags = _gvn.transform( new(C) FlagsProjNode(math, MathExactNode::flags_proj_node)); 69.68 - 69.69 - Node* bol = _gvn.transform( new (C) BoolNode(flags, BoolTest::overflow) ); 69.70 +void LibraryCallKit::inline_math_mathExact(Node* math, Node *test) { 69.71 + Node* bol = _gvn.transform( new (C) BoolNode(test, BoolTest::overflow) ); 69.72 IfNode* check = create_and_map_if(control(), bol, PROB_UNLIKELY_MAG(3), COUNT_UNKNOWN); 69.73 Node* fast_path = _gvn.transform( new (C) IfFalseNode(check)); 69.74 Node* slow_path = _gvn.transform( new (C) IfTrueNode(check) ); 69.75 @@ -1999,108 +1991,50 @@ 69.76 } 69.77 69.78 set_control(fast_path); 69.79 - set_result(result); 69.80 + set_result(math); 69.81 } 69.82 69.83 -bool LibraryCallKit::inline_math_addExactI(bool is_increment) { 69.84 - Node* arg1 = argument(0); 69.85 - Node* arg2 = NULL; 69.86 - 69.87 - if (is_increment) { 69.88 - arg2 = intcon(1); 69.89 - } else { 69.90 - arg2 = argument(1); 69.91 - } 69.92 - 69.93 - Node* add = _gvn.transform( new(C) AddExactINode(NULL, arg1, arg2) ); 69.94 - inline_math_mathExact(add); 69.95 +template <typename OverflowOp> 69.96 +bool LibraryCallKit::inline_math_overflow(Node* arg1, Node* arg2) { 69.97 + typedef typename OverflowOp::MathOp MathOp; 69.98 + 69.99 + MathOp* mathOp = new(C) MathOp(arg1, arg2); 69.100 + Node* operation = _gvn.transform( mathOp ); 69.101 + Node* ofcheck = _gvn.transform( new(C) OverflowOp(arg1, arg2) ); 69.102 + inline_math_mathExact(operation, ofcheck); 69.103 return true; 69.104 } 69.105 69.106 +bool LibraryCallKit::inline_math_addExactI(bool is_increment) { 69.107 + return inline_math_overflow<OverflowAddINode>(argument(0), is_increment ? intcon(1) : argument(1)); 69.108 +} 69.109 + 69.110 bool LibraryCallKit::inline_math_addExactL(bool is_increment) { 69.111 - Node* arg1 = argument(0); // type long 69.112 - // argument(1) == TOP 69.113 - Node* arg2 = NULL; 69.114 - 69.115 - if (is_increment) { 69.116 - arg2 = longcon(1); 69.117 - } else { 69.118 - arg2 = argument(2); // type long 69.119 - // argument(3) == TOP 69.120 - } 69.121 - 69.122 - Node* add = _gvn.transform(new(C) AddExactLNode(NULL, arg1, arg2)); 69.123 - inline_math_mathExact(add); 69.124 - return true; 69.125 + return inline_math_overflow<OverflowAddLNode>(argument(0), is_increment ? longcon(1) : argument(2)); 69.126 } 69.127 69.128 bool LibraryCallKit::inline_math_subtractExactI(bool is_decrement) { 69.129 - Node* arg1 = argument(0); 69.130 - Node* arg2 = NULL; 69.131 - 69.132 - if (is_decrement) { 69.133 - arg2 = intcon(1); 69.134 - } else { 69.135 - arg2 = argument(1); 69.136 - } 69.137 - 69.138 - Node* sub = _gvn.transform(new(C) SubExactINode(NULL, arg1, arg2)); 69.139 - inline_math_mathExact(sub); 69.140 - return true; 69.141 + return inline_math_overflow<OverflowSubINode>(argument(0), is_decrement ? intcon(1) : argument(1)); 69.142 } 69.143 69.144 bool LibraryCallKit::inline_math_subtractExactL(bool is_decrement) { 69.145 - Node* arg1 = argument(0); // type long 69.146 - // argument(1) == TOP 69.147 - Node* arg2 = NULL; 69.148 - 69.149 - if (is_decrement) { 69.150 - arg2 = longcon(1); 69.151 - } else { 69.152 - arg2 = argument(2); // type long 69.153 - // argument(3) == TOP 69.154 - } 69.155 - 69.156 - Node* sub = _gvn.transform(new(C) SubExactLNode(NULL, arg1, arg2)); 69.157 - inline_math_mathExact(sub); 69.158 - return true; 69.159 + return inline_math_overflow<OverflowSubLNode>(argument(0), is_decrement ? longcon(1) : argument(2)); 69.160 } 69.161 69.162 bool LibraryCallKit::inline_math_negateExactI() { 69.163 - Node* arg1 = argument(0); 69.164 - 69.165 - Node* neg = _gvn.transform(new(C) NegExactINode(NULL, arg1)); 69.166 - inline_math_mathExact(neg); 69.167 - return true; 69.168 + return inline_math_overflow<OverflowSubINode>(intcon(0), argument(0)); 69.169 } 69.170 69.171 bool LibraryCallKit::inline_math_negateExactL() { 69.172 - Node* arg1 = argument(0); 69.173 - // argument(1) == TOP 69.174 - 69.175 - Node* neg = _gvn.transform(new(C) NegExactLNode(NULL, arg1)); 69.176 - inline_math_mathExact(neg); 69.177 - return true; 69.178 + return inline_math_overflow<OverflowSubLNode>(longcon(0), argument(0)); 69.179 } 69.180 69.181 bool LibraryCallKit::inline_math_multiplyExactI() { 69.182 - Node* arg1 = argument(0); 69.183 - Node* arg2 = argument(1); 69.184 - 69.185 - Node* mul = _gvn.transform(new(C) MulExactINode(NULL, arg1, arg2)); 69.186 - inline_math_mathExact(mul); 69.187 - return true; 69.188 + return inline_math_overflow<OverflowMulINode>(argument(0), argument(1)); 69.189 } 69.190 69.191 bool LibraryCallKit::inline_math_multiplyExactL() { 69.192 - Node* arg1 = argument(0); 69.193 - // argument(1) == TOP 69.194 - Node* arg2 = argument(2); 69.195 - // argument(3) == TOP 69.196 - 69.197 - Node* mul = _gvn.transform(new(C) MulExactLNode(NULL, arg1, arg2)); 69.198 - inline_math_mathExact(mul); 69.199 - return true; 69.200 + return inline_math_overflow<OverflowMulLNode>(argument(0), argument(2)); 69.201 } 69.202 69.203 Node*
70.1 --- a/src/share/vm/opto/loopTransform.cpp Thu Mar 20 10:34:48 2014 -0700 70.2 +++ b/src/share/vm/opto/loopTransform.cpp Thu Mar 27 14:50:50 2014 -0700 70.3 @@ -713,10 +713,6 @@ 70.4 case Op_ModL: body_size += 30; break; 70.5 case Op_DivL: body_size += 30; break; 70.6 case Op_MulL: body_size += 10; break; 70.7 - case Op_FlagsProj: 70.8 - // Can't handle unrolling of loops containing 70.9 - // nodes that generate a FlagsProj at the moment 70.10 - return false; 70.11 case Op_StrComp: 70.12 case Op_StrEquals: 70.13 case Op_StrIndexOf: 70.14 @@ -780,10 +776,6 @@ 70.15 continue; // not RC 70.16 70.17 Node *cmp = bol->in(1); 70.18 - if (cmp->is_FlagsProj()) { 70.19 - continue; 70.20 - } 70.21 - 70.22 Node *rc_exp = cmp->in(1); 70.23 Node *limit = cmp->in(2); 70.24
71.1 --- a/src/share/vm/opto/loopopts.cpp Thu Mar 20 10:34:48 2014 -0700 71.2 +++ b/src/share/vm/opto/loopopts.cpp Thu Mar 27 14:50:50 2014 -0700 71.3 @@ -43,12 +43,6 @@ 71.4 return NULL; 71.5 } 71.6 71.7 - if (n->is_MathExact()) { 71.8 - // MathExact has projections that are not correctly handled in the code 71.9 - // below. 71.10 - return NULL; 71.11 - } 71.12 - 71.13 int wins = 0; 71.14 assert(!n->is_CFG(), ""); 71.15 assert(region->is_Region(), ""); 71.16 @@ -2362,8 +2356,7 @@ 71.17 opc == Op_Catch || 71.18 opc == Op_CatchProj || 71.19 opc == Op_Jump || 71.20 - opc == Op_JumpProj || 71.21 - opc == Op_FlagsProj) { 71.22 + opc == Op_JumpProj) { 71.23 #if !defined(PRODUCT) 71.24 if (TracePartialPeeling) { 71.25 tty->print_cr("\nExit control too complex: lp: %d", head->_idx);
72.1 --- a/src/share/vm/opto/matcher.cpp Thu Mar 20 10:34:48 2014 -0700 72.2 +++ b/src/share/vm/opto/matcher.cpp Thu Mar 27 14:50:50 2014 -0700 72.3 @@ -1908,6 +1908,105 @@ 72.4 return OptoReg::as_OptoReg(regs.first()); 72.5 } 72.6 72.7 +// This function identifies sub-graphs in which a 'load' node is 72.8 +// input to two different nodes, and such that it can be matched 72.9 +// with BMI instructions like blsi, blsr, etc. 72.10 +// Example : for b = -a[i] & a[i] can be matched to blsi r32, m32. 72.11 +// The graph is (AndL (SubL Con0 LoadL*) LoadL*), where LoadL* 72.12 +// refers to the same node. 72.13 +#ifdef X86 72.14 +// Match the generic fused operations pattern (op1 (op2 Con{ConType} mop) mop) 72.15 +// This is a temporary solution until we make DAGs expressible in ADL. 72.16 +template<typename ConType> 72.17 +class FusedPatternMatcher { 72.18 + Node* _op1_node; 72.19 + Node* _mop_node; 72.20 + int _con_op; 72.21 + 72.22 + static int match_next(Node* n, int next_op, int next_op_idx) { 72.23 + if (n->in(1) == NULL || n->in(2) == NULL) { 72.24 + return -1; 72.25 + } 72.26 + 72.27 + if (next_op_idx == -1) { // n is commutative, try rotations 72.28 + if (n->in(1)->Opcode() == next_op) { 72.29 + return 1; 72.30 + } else if (n->in(2)->Opcode() == next_op) { 72.31 + return 2; 72.32 + } 72.33 + } else { 72.34 + assert(next_op_idx > 0 && next_op_idx <= 2, "Bad argument index"); 72.35 + if (n->in(next_op_idx)->Opcode() == next_op) { 72.36 + return next_op_idx; 72.37 + } 72.38 + } 72.39 + return -1; 72.40 + } 72.41 +public: 72.42 + FusedPatternMatcher(Node* op1_node, Node *mop_node, int con_op) : 72.43 + _op1_node(op1_node), _mop_node(mop_node), _con_op(con_op) { } 72.44 + 72.45 + bool match(int op1, int op1_op2_idx, // op1 and the index of the op1->op2 edge, -1 if op1 is commutative 72.46 + int op2, int op2_con_idx, // op2 and the index of the op2->con edge, -1 if op2 is commutative 72.47 + typename ConType::NativeType con_value) { 72.48 + if (_op1_node->Opcode() != op1) { 72.49 + return false; 72.50 + } 72.51 + if (_mop_node->outcnt() > 2) { 72.52 + return false; 72.53 + } 72.54 + op1_op2_idx = match_next(_op1_node, op2, op1_op2_idx); 72.55 + if (op1_op2_idx == -1) { 72.56 + return false; 72.57 + } 72.58 + // Memory operation must be the other edge 72.59 + int op1_mop_idx = (op1_op2_idx & 1) + 1; 72.60 + 72.61 + // Check that the mop node is really what we want 72.62 + if (_op1_node->in(op1_mop_idx) == _mop_node) { 72.63 + Node *op2_node = _op1_node->in(op1_op2_idx); 72.64 + if (op2_node->outcnt() > 1) { 72.65 + return false; 72.66 + } 72.67 + assert(op2_node->Opcode() == op2, "Should be"); 72.68 + op2_con_idx = match_next(op2_node, _con_op, op2_con_idx); 72.69 + if (op2_con_idx == -1) { 72.70 + return false; 72.71 + } 72.72 + // Memory operation must be the other edge 72.73 + int op2_mop_idx = (op2_con_idx & 1) + 1; 72.74 + // Check that the memory operation is the same node 72.75 + if (op2_node->in(op2_mop_idx) == _mop_node) { 72.76 + // Now check the constant 72.77 + const Type* con_type = op2_node->in(op2_con_idx)->bottom_type(); 72.78 + if (con_type != Type::TOP && ConType::as_self(con_type)->get_con() == con_value) { 72.79 + return true; 72.80 + } 72.81 + } 72.82 + } 72.83 + return false; 72.84 + } 72.85 +}; 72.86 + 72.87 + 72.88 +bool Matcher::is_bmi_pattern(Node *n, Node *m) { 72.89 + if (n != NULL && m != NULL) { 72.90 + if (m->Opcode() == Op_LoadI) { 72.91 + FusedPatternMatcher<TypeInt> bmii(n, m, Op_ConI); 72.92 + return bmii.match(Op_AndI, -1, Op_SubI, 1, 0) || 72.93 + bmii.match(Op_AndI, -1, Op_AddI, -1, -1) || 72.94 + bmii.match(Op_XorI, -1, Op_AddI, -1, -1); 72.95 + } else if (m->Opcode() == Op_LoadL) { 72.96 + FusedPatternMatcher<TypeLong> bmil(n, m, Op_ConL); 72.97 + return bmil.match(Op_AndL, -1, Op_SubL, 1, 0) || 72.98 + bmil.match(Op_AndL, -1, Op_AddL, -1, -1) || 72.99 + bmil.match(Op_XorL, -1, Op_AddL, -1, -1); 72.100 + } 72.101 + } 72.102 + return false; 72.103 +} 72.104 +#endif // X86 72.105 + 72.106 // A method-klass-holder may be passed in the inline_cache_reg 72.107 // and then expanded into the inline_cache_reg and a method_oop register 72.108 // defined in ad_<arch>.cpp 72.109 @@ -1984,7 +2083,6 @@ 72.110 case Op_Catch: 72.111 case Op_CatchProj: 72.112 case Op_CProj: 72.113 - case Op_FlagsProj: 72.114 case Op_JumpProj: 72.115 case Op_JProj: 72.116 case Op_NeverBranch: 72.117 @@ -2064,6 +2162,14 @@ 72.118 set_shared(m->in(AddPNode::Base)->in(1)); 72.119 } 72.120 72.121 + // if 'n' and 'm' are part of a graph for BMI instruction, clone this node. 72.122 +#ifdef X86 72.123 + if (UseBMI1Instructions && is_bmi_pattern(n, m)) { 72.124 + mstack.push(m, Visit); 72.125 + continue; 72.126 + } 72.127 +#endif 72.128 + 72.129 // Clone addressing expressions as they are "free" in memory access instructions 72.130 if( mem_op && i == MemNode::Address && mop == Op_AddP ) { 72.131 // Some inputs for address expression are not put on stack
73.1 --- a/src/share/vm/opto/matcher.hpp Thu Mar 20 10:34:48 2014 -0700 73.2 +++ b/src/share/vm/opto/matcher.hpp Thu Mar 27 14:50:50 2014 -0700 73.3 @@ -79,6 +79,9 @@ 73.4 73.5 // Find shared Nodes, or Nodes that otherwise are Matcher roots 73.6 void find_shared( Node *n ); 73.7 +#ifdef X86 73.8 + bool is_bmi_pattern(Node *n, Node *m); 73.9 +#endif 73.10 73.11 // Debug and profile information for nodes in old space: 73.12 GrowableArray<Node_Notes*>* _old_node_note_array; 73.13 @@ -340,10 +343,6 @@ 73.14 // Register for MODL projection of divmodL 73.15 static RegMask modL_proj_mask(); 73.16 73.17 - static const RegMask mathExactI_result_proj_mask(); 73.18 - static const RegMask mathExactL_result_proj_mask(); 73.19 - static const RegMask mathExactI_flags_proj_mask(); 73.20 - 73.21 // Use hardware DIV instruction when it is faster than 73.22 // a code which use multiply for division by constant. 73.23 static bool use_asm_for_ldiv_by_con( jlong divisor );
74.1 --- a/src/share/vm/opto/mathexactnode.cpp Thu Mar 20 10:34:48 2014 -0700 74.2 +++ b/src/share/vm/opto/mathexactnode.cpp Thu Mar 27 14:50:50 2014 -0700 74.3 @@ -31,358 +31,93 @@ 74.4 #include "opto/mathexactnode.hpp" 74.5 #include "opto/subnode.hpp" 74.6 74.7 -MathExactNode::MathExactNode(Node* ctrl, Node* in1) : MultiNode(2) { 74.8 - init_class_id(Class_MathExact); 74.9 - init_req(0, ctrl); 74.10 - init_req(1, in1); 74.11 +template <typename OverflowOp> 74.12 +class AddHelper { 74.13 +public: 74.14 + typedef typename OverflowOp::TypeClass TypeClass; 74.15 + typedef typename TypeClass::NativeType NativeType; 74.16 + 74.17 + static bool will_overflow(NativeType value1, NativeType value2) { 74.18 + NativeType result = value1 + value2; 74.19 + // Hacker's Delight 2-12 Overflow if both arguments have the opposite sign of the result 74.20 + if (((value1 ^ result) & (value2 ^ result)) >= 0) { 74.21 + return false; 74.22 + } 74.23 + return true; 74.24 + } 74.25 + 74.26 + static bool can_overflow(const Type* type1, const Type* type2) { 74.27 + if (type1 == TypeClass::ZERO || type2 == TypeClass::ZERO) { 74.28 + return false; 74.29 + } 74.30 + return true; 74.31 + } 74.32 +}; 74.33 + 74.34 +template <typename OverflowOp> 74.35 +class SubHelper { 74.36 +public: 74.37 + typedef typename OverflowOp::TypeClass TypeClass; 74.38 + typedef typename TypeClass::NativeType NativeType; 74.39 + 74.40 + static bool will_overflow(NativeType value1, NativeType value2) { 74.41 + NativeType result = value1 - value2; 74.42 + // hacker's delight 2-12 overflow iff the arguments have different signs and 74.43 + // the sign of the result is different than the sign of arg1 74.44 + if (((value1 ^ value2) & (value1 ^ result)) >= 0) { 74.45 + return false; 74.46 + } 74.47 + return true; 74.48 + } 74.49 + 74.50 + static bool can_overflow(const Type* type1, const Type* type2) { 74.51 + if (type2 == TypeClass::ZERO) { 74.52 + return false; 74.53 + } 74.54 + return true; 74.55 + } 74.56 +}; 74.57 + 74.58 +template <typename OverflowOp> 74.59 +class MulHelper { 74.60 +public: 74.61 + typedef typename OverflowOp::TypeClass TypeClass; 74.62 + 74.63 + static bool can_overflow(const Type* type1, const Type* type2) { 74.64 + if (type1 == TypeClass::ZERO || type2 == TypeClass::ZERO) { 74.65 + return false; 74.66 + } else if (type1 == TypeClass::ONE || type2 == TypeClass::ONE) { 74.67 + return false; 74.68 + } 74.69 + return true; 74.70 + } 74.71 +}; 74.72 + 74.73 +bool OverflowAddINode::will_overflow(jint v1, jint v2) const { 74.74 + return AddHelper<OverflowAddINode>::will_overflow(v1, v2); 74.75 } 74.76 74.77 -MathExactNode::MathExactNode(Node* ctrl, Node* in1, Node* in2) : MultiNode(3) { 74.78 - init_class_id(Class_MathExact); 74.79 - init_req(0, ctrl); 74.80 - init_req(1, in1); 74.81 - init_req(2, in2); 74.82 +bool OverflowSubINode::will_overflow(jint v1, jint v2) const { 74.83 + return SubHelper<OverflowSubINode>::will_overflow(v1, v2); 74.84 } 74.85 74.86 -BoolNode* MathExactNode::bool_node() const { 74.87 - Node* flags = flags_node(); 74.88 - BoolNode* boolnode = flags->unique_out()->as_Bool(); 74.89 - assert(boolnode != NULL, "must have BoolNode"); 74.90 - return boolnode; 74.91 +bool OverflowMulINode::will_overflow(jint v1, jint v2) const { 74.92 + jlong result = (jlong) v1 * (jlong) v2; 74.93 + if ((jint) result == result) { 74.94 + return false; 74.95 + } 74.96 + return true; 74.97 } 74.98 74.99 -IfNode* MathExactNode::if_node() const { 74.100 - BoolNode* boolnode = bool_node(); 74.101 - IfNode* ifnode = boolnode->unique_out()->as_If(); 74.102 - assert(ifnode != NULL, "must have IfNode"); 74.103 - return ifnode; 74.104 +bool OverflowAddLNode::will_overflow(jlong v1, jlong v2) const { 74.105 + return AddHelper<OverflowAddLNode>::will_overflow(v1, v2); 74.106 } 74.107 74.108 -Node* MathExactNode::control_node() const { 74.109 - IfNode* ifnode = if_node(); 74.110 - return ifnode->in(0); 74.111 +bool OverflowSubLNode::will_overflow(jlong v1, jlong v2) const { 74.112 + return SubHelper<OverflowSubLNode>::will_overflow(v1, v2); 74.113 } 74.114 74.115 -Node* MathExactNode::non_throwing_branch() const { 74.116 - IfNode* ifnode = if_node(); 74.117 - if (bool_node()->_test._test == BoolTest::overflow) { 74.118 - return ifnode->proj_out(0); 74.119 - } 74.120 - return ifnode->proj_out(1); 74.121 -} 74.122 - 74.123 -// If the MathExactNode won't overflow we have to replace the 74.124 -// FlagsProjNode and ProjNode that is generated by the MathExactNode 74.125 -Node* MathExactNode::no_overflow(PhaseGVN* phase, Node* new_result) { 74.126 - PhaseIterGVN* igvn = phase->is_IterGVN(); 74.127 - if (igvn) { 74.128 - ProjNode* result = result_node(); 74.129 - ProjNode* flags = flags_node(); 74.130 - 74.131 - if (result != NULL) { 74.132 - igvn->replace_node(result, new_result); 74.133 - } 74.134 - 74.135 - if (flags != NULL) { 74.136 - BoolNode* boolnode = bool_node(); 74.137 - switch (boolnode->_test._test) { 74.138 - case BoolTest::overflow: 74.139 - // if the check is for overflow - never taken 74.140 - igvn->replace_node(boolnode, phase->intcon(0)); 74.141 - break; 74.142 - case BoolTest::no_overflow: 74.143 - // if the check is for no overflow - always taken 74.144 - igvn->replace_node(boolnode, phase->intcon(1)); 74.145 - break; 74.146 - default: 74.147 - fatal("Unexpected value of BoolTest"); 74.148 - break; 74.149 - } 74.150 - flags->del_req(0); 74.151 - } 74.152 - } 74.153 - return new_result; 74.154 -} 74.155 - 74.156 -Node* MathExactINode::match(const ProjNode* proj, const Matcher* m) { 74.157 - uint ideal_reg = proj->ideal_reg(); 74.158 - RegMask rm; 74.159 - if (proj->_con == result_proj_node) { 74.160 - rm = m->mathExactI_result_proj_mask(); 74.161 - } else { 74.162 - assert(proj->_con == flags_proj_node, "must be result or flags"); 74.163 - assert(ideal_reg == Op_RegFlags, "sanity"); 74.164 - rm = m->mathExactI_flags_proj_mask(); 74.165 - } 74.166 - return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg); 74.167 -} 74.168 - 74.169 -Node* MathExactLNode::match(const ProjNode* proj, const Matcher* m) { 74.170 - uint ideal_reg = proj->ideal_reg(); 74.171 - RegMask rm; 74.172 - if (proj->_con == result_proj_node) { 74.173 - rm = m->mathExactL_result_proj_mask(); 74.174 - } else { 74.175 - assert(proj->_con == flags_proj_node, "must be result or flags"); 74.176 - assert(ideal_reg == Op_RegFlags, "sanity"); 74.177 - rm = m->mathExactI_flags_proj_mask(); 74.178 - } 74.179 - return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg); 74.180 -} 74.181 - 74.182 -Node* AddExactINode::Ideal(PhaseGVN* phase, bool can_reshape) { 74.183 - Node* arg1 = in(1); 74.184 - Node* arg2 = in(2); 74.185 - 74.186 - const Type* type1 = phase->type(arg1); 74.187 - const Type* type2 = phase->type(arg2); 74.188 - 74.189 - if (type1 != Type::TOP && type1->singleton() && 74.190 - type2 != Type::TOP && type2->singleton()) { 74.191 - jint val1 = arg1->get_int(); 74.192 - jint val2 = arg2->get_int(); 74.193 - jint result = val1 + val2; 74.194 - // Hacker's Delight 2-12 Overflow if both arguments have the opposite sign of the result 74.195 - if ( (((val1 ^ result) & (val2 ^ result)) >= 0)) { 74.196 - Node* con_result = ConINode::make(phase->C, result); 74.197 - return no_overflow(phase, con_result); 74.198 - } 74.199 - return NULL; 74.200 - } 74.201 - 74.202 - if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) { // (Add 0 x) == x 74.203 - Node* add_result = new (phase->C) AddINode(arg1, arg2); 74.204 - return no_overflow(phase, add_result); 74.205 - } 74.206 - 74.207 - if (type2->singleton()) { 74.208 - return NULL; // no change - keep constant on the right 74.209 - } 74.210 - 74.211 - if (type1->singleton()) { 74.212 - // Make it x + Constant - move constant to the right 74.213 - swap_edges(1, 2); 74.214 - return this; 74.215 - } 74.216 - 74.217 - if (arg2->is_Load()) { 74.218 - return NULL; // no change - keep load on the right 74.219 - } 74.220 - 74.221 - if (arg1->is_Load()) { 74.222 - // Make it x + Load - move load to the right 74.223 - swap_edges(1, 2); 74.224 - return this; 74.225 - } 74.226 - 74.227 - if (arg1->_idx > arg2->_idx) { 74.228 - // Sort the edges 74.229 - swap_edges(1, 2); 74.230 - return this; 74.231 - } 74.232 - 74.233 - return NULL; 74.234 -} 74.235 - 74.236 -Node* AddExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { 74.237 - Node* arg1 = in(1); 74.238 - Node* arg2 = in(2); 74.239 - 74.240 - const Type* type1 = phase->type(arg1); 74.241 - const Type* type2 = phase->type(arg2); 74.242 - 74.243 - if (type1 != Type::TOP && type1->singleton() && 74.244 - type2 != Type::TOP && type2->singleton()) { 74.245 - jlong val1 = arg1->get_long(); 74.246 - jlong val2 = arg2->get_long(); 74.247 - jlong result = val1 + val2; 74.248 - // Hacker's Delight 2-12 Overflow if both arguments have the opposite sign of the result 74.249 - if ( (((val1 ^ result) & (val2 ^ result)) >= 0)) { 74.250 - Node* con_result = ConLNode::make(phase->C, result); 74.251 - return no_overflow(phase, con_result); 74.252 - } 74.253 - return NULL; 74.254 - } 74.255 - 74.256 - if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) { // (Add 0 x) == x 74.257 - Node* add_result = new (phase->C) AddLNode(arg1, arg2); 74.258 - return no_overflow(phase, add_result); 74.259 - } 74.260 - 74.261 - if (type2->singleton()) { 74.262 - return NULL; // no change - keep constant on the right 74.263 - } 74.264 - 74.265 - if (type1->singleton()) { 74.266 - // Make it x + Constant - move constant to the right 74.267 - swap_edges(1, 2); 74.268 - return this; 74.269 - } 74.270 - 74.271 - if (arg2->is_Load()) { 74.272 - return NULL; // no change - keep load on the right 74.273 - } 74.274 - 74.275 - if (arg1->is_Load()) { 74.276 - // Make it x + Load - move load to the right 74.277 - swap_edges(1, 2); 74.278 - return this; 74.279 - } 74.280 - 74.281 - if (arg1->_idx > arg2->_idx) { 74.282 - // Sort the edges 74.283 - swap_edges(1, 2); 74.284 - return this; 74.285 - } 74.286 - 74.287 - return NULL; 74.288 -} 74.289 - 74.290 -Node* SubExactINode::Ideal(PhaseGVN* phase, bool can_reshape) { 74.291 - Node* arg1 = in(1); 74.292 - Node* arg2 = in(2); 74.293 - 74.294 - const Type* type1 = phase->type(arg1); 74.295 - const Type* type2 = phase->type(arg2); 74.296 - 74.297 - if (type1 != Type::TOP && type1->singleton() && 74.298 - type2 != Type::TOP && type2->singleton()) { 74.299 - jint val1 = arg1->get_int(); 74.300 - jint val2 = arg2->get_int(); 74.301 - jint result = val1 - val2; 74.302 - 74.303 - // Hacker's Delight 2-12 Overflow iff the arguments have different signs and 74.304 - // the sign of the result is different than the sign of arg1 74.305 - if (((val1 ^ val2) & (val1 ^ result)) >= 0) { 74.306 - Node* con_result = ConINode::make(phase->C, result); 74.307 - return no_overflow(phase, con_result); 74.308 - } 74.309 - return NULL; 74.310 - } 74.311 - 74.312 - if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) { 74.313 - // Sub with zero is the same as add with zero 74.314 - Node* add_result = new (phase->C) AddINode(arg1, arg2); 74.315 - return no_overflow(phase, add_result); 74.316 - } 74.317 - 74.318 - return NULL; 74.319 -} 74.320 - 74.321 -Node* SubExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { 74.322 - Node* arg1 = in(1); 74.323 - Node* arg2 = in(2); 74.324 - 74.325 - const Type* type1 = phase->type(arg1); 74.326 - const Type* type2 = phase->type(arg2); 74.327 - 74.328 - if (type1 != Type::TOP && type1->singleton() && 74.329 - type2 != Type::TOP && type2->singleton()) { 74.330 - jlong val1 = arg1->get_long(); 74.331 - jlong val2 = arg2->get_long(); 74.332 - jlong result = val1 - val2; 74.333 - 74.334 - // Hacker's Delight 2-12 Overflow iff the arguments have different signs and 74.335 - // the sign of the result is different than the sign of arg1 74.336 - if (((val1 ^ val2) & (val1 ^ result)) >= 0) { 74.337 - Node* con_result = ConLNode::make(phase->C, result); 74.338 - return no_overflow(phase, con_result); 74.339 - } 74.340 - return NULL; 74.341 - } 74.342 - 74.343 - if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) { 74.344 - // Sub with zero is the same as add with zero 74.345 - Node* add_result = new (phase->C) AddLNode(arg1, arg2); 74.346 - return no_overflow(phase, add_result); 74.347 - } 74.348 - 74.349 - return NULL; 74.350 -} 74.351 - 74.352 -Node* NegExactINode::Ideal(PhaseGVN* phase, bool can_reshape) { 74.353 - Node *arg = in(1); 74.354 - 74.355 - const Type* type = phase->type(arg); 74.356 - if (type != Type::TOP && type->singleton()) { 74.357 - jint value = arg->get_int(); 74.358 - if (value != min_jint) { 74.359 - Node* neg_result = ConINode::make(phase->C, -value); 74.360 - return no_overflow(phase, neg_result); 74.361 - } 74.362 - } 74.363 - return NULL; 74.364 -} 74.365 - 74.366 -Node* NegExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { 74.367 - Node *arg = in(1); 74.368 - 74.369 - const Type* type = phase->type(arg); 74.370 - if (type != Type::TOP && type->singleton()) { 74.371 - jlong value = arg->get_long(); 74.372 - if (value != min_jlong) { 74.373 - Node* neg_result = ConLNode::make(phase->C, -value); 74.374 - return no_overflow(phase, neg_result); 74.375 - } 74.376 - } 74.377 - return NULL; 74.378 -} 74.379 - 74.380 -Node* MulExactINode::Ideal(PhaseGVN* phase, bool can_reshape) { 74.381 - Node* arg1 = in(1); 74.382 - Node* arg2 = in(2); 74.383 - 74.384 - const Type* type1 = phase->type(arg1); 74.385 - const Type* type2 = phase->type(arg2); 74.386 - 74.387 - if (type1 != Type::TOP && type1->singleton() && 74.388 - type2 != Type::TOP && type2->singleton()) { 74.389 - jint val1 = arg1->get_int(); 74.390 - jint val2 = arg2->get_int(); 74.391 - jlong result = (jlong) val1 * (jlong) val2; 74.392 - if ((jint) result == result) { 74.393 - // no overflow 74.394 - Node* mul_result = ConINode::make(phase->C, result); 74.395 - return no_overflow(phase, mul_result); 74.396 - } 74.397 - } 74.398 - 74.399 - if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) { 74.400 - return no_overflow(phase, ConINode::make(phase->C, 0)); 74.401 - } 74.402 - 74.403 - if (type1 == TypeInt::ONE) { 74.404 - Node* mul_result = new (phase->C) AddINode(arg2, phase->intcon(0)); 74.405 - return no_overflow(phase, mul_result); 74.406 - } 74.407 - if (type2 == TypeInt::ONE) { 74.408 - Node* mul_result = new (phase->C) AddINode(arg1, phase->intcon(0)); 74.409 - return no_overflow(phase, mul_result); 74.410 - } 74.411 - 74.412 - if (type1 == TypeInt::MINUS_1) { 74.413 - return new (phase->C) NegExactINode(NULL, arg2); 74.414 - } 74.415 - 74.416 - if (type2 == TypeInt::MINUS_1) { 74.417 - return new (phase->C) NegExactINode(NULL, arg1); 74.418 - } 74.419 - 74.420 - return NULL; 74.421 -} 74.422 - 74.423 -Node* MulExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { 74.424 - Node* arg1 = in(1); 74.425 - Node* arg2 = in(2); 74.426 - 74.427 - const Type* type1 = phase->type(arg1); 74.428 - const Type* type2 = phase->type(arg2); 74.429 - 74.430 - if (type1 != Type::TOP && type1->singleton() && 74.431 - type2 != Type::TOP && type2->singleton()) { 74.432 - jlong val1 = arg1->get_long(); 74.433 - jlong val2 = arg2->get_long(); 74.434 - 74.435 +bool OverflowMulLNode::will_overflow(jlong val1, jlong val2) const { 74.436 jlong result = val1 * val2; 74.437 jlong ax = (val1 < 0 ? -val1 : val1); 74.438 jlong ay = (val2 < 0 ? -val2 : val2); 74.439 @@ -398,33 +133,125 @@ 74.440 } 74.441 } 74.442 74.443 - if (!overflow) { 74.444 - Node* mul_result = ConLNode::make(phase->C, result); 74.445 - return no_overflow(phase, mul_result); 74.446 + return overflow; 74.447 +} 74.448 + 74.449 +bool OverflowAddINode::can_overflow(const Type* t1, const Type* t2) const { 74.450 + return AddHelper<OverflowAddINode>::can_overflow(t1, t2); 74.451 +} 74.452 + 74.453 +bool OverflowSubINode::can_overflow(const Type* t1, const Type* t2) const { 74.454 + if (in(1) == in(2)) { 74.455 + return false; 74.456 + } 74.457 + return SubHelper<OverflowSubINode>::can_overflow(t1, t2); 74.458 +} 74.459 + 74.460 +bool OverflowMulINode::can_overflow(const Type* t1, const Type* t2) const { 74.461 + return MulHelper<OverflowMulINode>::can_overflow(t1, t2); 74.462 +} 74.463 + 74.464 +bool OverflowAddLNode::can_overflow(const Type* t1, const Type* t2) const { 74.465 + return AddHelper<OverflowAddLNode>::can_overflow(t1, t2); 74.466 +} 74.467 + 74.468 +bool OverflowSubLNode::can_overflow(const Type* t1, const Type* t2) const { 74.469 + if (in(1) == in(2)) { 74.470 + return false; 74.471 + } 74.472 + return SubHelper<OverflowSubLNode>::can_overflow(t1, t2); 74.473 +} 74.474 + 74.475 +bool OverflowMulLNode::can_overflow(const Type* t1, const Type* t2) const { 74.476 + return MulHelper<OverflowMulLNode>::can_overflow(t1, t2); 74.477 +} 74.478 + 74.479 +const Type* OverflowNode::sub(const Type* t1, const Type* t2) const { 74.480 + fatal(err_msg_res("sub() should not be called for '%s'", NodeClassNames[this->Opcode()])); 74.481 + return TypeInt::CC; 74.482 +} 74.483 + 74.484 +template <typename OverflowOp> 74.485 +struct IdealHelper { 74.486 + typedef typename OverflowOp::TypeClass TypeClass; // TypeInt, TypeLong 74.487 + typedef typename TypeClass::NativeType NativeType; 74.488 + 74.489 + static Node* Ideal(const OverflowOp* node, PhaseGVN* phase, bool can_reshape) { 74.490 + Node* arg1 = node->in(1); 74.491 + Node* arg2 = node->in(2); 74.492 + const Type* type1 = phase->type(arg1); 74.493 + const Type* type2 = phase->type(arg2); 74.494 + 74.495 + if (type1 == NULL || type2 == NULL) { 74.496 + return NULL; 74.497 } 74.498 + 74.499 + if (type1 != Type::TOP && type1->singleton() && 74.500 + type2 != Type::TOP && type2->singleton()) { 74.501 + NativeType val1 = TypeClass::as_self(type1)->get_con(); 74.502 + NativeType val2 = TypeClass::as_self(type2)->get_con(); 74.503 + if (node->will_overflow(val1, val2) == false) { 74.504 + Node* con_result = ConINode::make(phase->C, 0); 74.505 + return con_result; 74.506 + } 74.507 + return NULL; 74.508 + } 74.509 + return NULL; 74.510 } 74.511 74.512 - if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) { 74.513 - return no_overflow(phase, ConLNode::make(phase->C, 0)); 74.514 + static const Type* Value(const OverflowOp* node, PhaseTransform* phase) { 74.515 + const Type *t1 = phase->type( node->in(1) ); 74.516 + const Type *t2 = phase->type( node->in(2) ); 74.517 + if( t1 == Type::TOP ) return Type::TOP; 74.518 + if( t2 == Type::TOP ) return Type::TOP; 74.519 + 74.520 + const TypeClass* i1 = TypeClass::as_self(t1); 74.521 + const TypeClass* i2 = TypeClass::as_self(t2); 74.522 + 74.523 + if (i1 == NULL || i2 == NULL) { 74.524 + return TypeInt::CC; 74.525 + } 74.526 + 74.527 + if (t1->singleton() && t2->singleton()) { 74.528 + NativeType val1 = i1->get_con(); 74.529 + NativeType val2 = i2->get_con(); 74.530 + if (node->will_overflow(val1, val2)) { 74.531 + return TypeInt::CC; 74.532 + } 74.533 + return TypeInt::ZERO; 74.534 + } else if (i1 != TypeClass::TYPE_DOMAIN && i2 != TypeClass::TYPE_DOMAIN) { 74.535 + if (node->will_overflow(i1->_lo, i2->_lo)) { 74.536 + return TypeInt::CC; 74.537 + } else if (node->will_overflow(i1->_lo, i2->_hi)) { 74.538 + return TypeInt::CC; 74.539 + } else if (node->will_overflow(i1->_hi, i2->_lo)) { 74.540 + return TypeInt::CC; 74.541 + } else if (node->will_overflow(i1->_hi, i2->_hi)) { 74.542 + return TypeInt::CC; 74.543 + } 74.544 + return TypeInt::ZERO; 74.545 + } 74.546 + 74.547 + if (!node->can_overflow(t1, t2)) { 74.548 + return TypeInt::ZERO; 74.549 + } 74.550 + return TypeInt::CC; 74.551 } 74.552 +}; 74.553 74.554 - if (type1 == TypeLong::ONE) { 74.555 - Node* mul_result = new (phase->C) AddLNode(arg2, phase->longcon(0)); 74.556 - return no_overflow(phase, mul_result); 74.557 - } 74.558 - if (type2 == TypeLong::ONE) { 74.559 - Node* mul_result = new (phase->C) AddLNode(arg1, phase->longcon(0)); 74.560 - return no_overflow(phase, mul_result); 74.561 - } 74.562 - 74.563 - if (type1 == TypeLong::MINUS_1) { 74.564 - return new (phase->C) NegExactLNode(NULL, arg2); 74.565 - } 74.566 - 74.567 - if (type2 == TypeLong::MINUS_1) { 74.568 - return new (phase->C) NegExactLNode(NULL, arg1); 74.569 - } 74.570 - 74.571 - return NULL; 74.572 +Node* OverflowINode::Ideal(PhaseGVN* phase, bool can_reshape) { 74.573 + return IdealHelper<OverflowINode>::Ideal(this, phase, can_reshape); 74.574 } 74.575 74.576 +Node* OverflowLNode::Ideal(PhaseGVN* phase, bool can_reshape) { 74.577 + return IdealHelper<OverflowLNode>::Ideal(this, phase, can_reshape); 74.578 +} 74.579 + 74.580 +const Type* OverflowINode::Value(PhaseTransform* phase) const { 74.581 + return IdealHelper<OverflowINode>::Value(this, phase); 74.582 +} 74.583 + 74.584 +const Type* OverflowLNode::Value(PhaseTransform* phase) const { 74.585 + return IdealHelper<OverflowLNode>::Value(this, phase); 74.586 +} 74.587 +
75.1 --- a/src/share/vm/opto/mathexactnode.hpp Thu Mar 20 10:34:48 2014 -0700 75.2 +++ b/src/share/vm/opto/mathexactnode.hpp Thu Mar 27 14:50:50 2014 -0700 75.3 @@ -27,128 +27,111 @@ 75.4 75.5 #include "opto/multnode.hpp" 75.6 #include "opto/node.hpp" 75.7 +#include "opto/addnode.hpp" 75.8 #include "opto/subnode.hpp" 75.9 #include "opto/type.hpp" 75.10 75.11 -class BoolNode; 75.12 -class IfNode; 75.13 -class Node; 75.14 - 75.15 class PhaseGVN; 75.16 class PhaseTransform; 75.17 75.18 -class MathExactNode : public MultiNode { 75.19 +class OverflowNode : public CmpNode { 75.20 public: 75.21 - MathExactNode(Node* ctrl, Node* in1); 75.22 - MathExactNode(Node* ctrl, Node* in1, Node* in2); 75.23 - enum { 75.24 - result_proj_node = 0, 75.25 - flags_proj_node = 1 75.26 - }; 75.27 - virtual int Opcode() const; 75.28 - virtual Node* Identity(PhaseTransform* phase) { return this; } 75.29 - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape) { return NULL; } 75.30 - virtual const Type* Value(PhaseTransform* phase) const { return bottom_type(); } 75.31 - virtual uint hash() const { return NO_HASH; } 75.32 - virtual bool is_CFG() const { return false; } 75.33 - virtual uint ideal_reg() const { return NotAMachineReg; } 75.34 + OverflowNode(Node* in1, Node* in2) : CmpNode(in1, in2) {} 75.35 75.36 - ProjNode* result_node() const { return proj_out(result_proj_node); } 75.37 - ProjNode* flags_node() const { return proj_out(flags_proj_node); } 75.38 - Node* control_node() const; 75.39 - Node* non_throwing_branch() const; 75.40 -protected: 75.41 - IfNode* if_node() const; 75.42 - BoolNode* bool_node() const; 75.43 - Node* no_overflow(PhaseGVN *phase, Node* new_result); 75.44 + virtual uint ideal_reg() const { return Op_RegFlags; } 75.45 + virtual const Type* sub(const Type* t1, const Type* t2) const; 75.46 }; 75.47 75.48 -class MathExactINode : public MathExactNode { 75.49 - public: 75.50 - MathExactINode(Node* ctrl, Node* in1) : MathExactNode(ctrl, in1) {} 75.51 - MathExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactNode(ctrl, in1, in2) {} 75.52 - virtual int Opcode() const; 75.53 - virtual Node* match(const ProjNode* proj, const Matcher* m); 75.54 - virtual const Type* bottom_type() const { return TypeTuple::INT_CC_PAIR; } 75.55 +class OverflowINode : public OverflowNode { 75.56 +public: 75.57 + typedef TypeInt TypeClass; 75.58 + 75.59 + OverflowINode(Node* in1, Node* in2) : OverflowNode(in1, in2) {} 75.60 + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); 75.61 + virtual const Type* Value(PhaseTransform* phase) const; 75.62 + 75.63 + virtual bool will_overflow(jint v1, jint v2) const = 0; 75.64 + virtual bool can_overflow(const Type* t1, const Type* t2) const = 0; 75.65 }; 75.66 75.67 -class MathExactLNode : public MathExactNode { 75.68 + 75.69 +class OverflowLNode : public OverflowNode { 75.70 public: 75.71 - MathExactLNode(Node* ctrl, Node* in1) : MathExactNode(ctrl, in1) {} 75.72 - MathExactLNode(Node* ctrl, Node* in1, Node* in2) : MathExactNode(ctrl, in1, in2) {} 75.73 - virtual int Opcode() const; 75.74 - virtual Node* match(const ProjNode* proj, const Matcher* m); 75.75 - virtual const Type* bottom_type() const { return TypeTuple::LONG_CC_PAIR; } 75.76 + typedef TypeLong TypeClass; 75.77 + 75.78 + OverflowLNode(Node* in1, Node* in2) : OverflowNode(in1, in2) {} 75.79 + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); 75.80 + virtual const Type* Value(PhaseTransform* phase) const; 75.81 + 75.82 + virtual bool will_overflow(jlong v1, jlong v2) const = 0; 75.83 + virtual bool can_overflow(const Type* t1, const Type* t2) const = 0; 75.84 }; 75.85 75.86 -class AddExactINode : public MathExactINode { 75.87 +class OverflowAddINode : public OverflowINode { 75.88 public: 75.89 - AddExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactINode(ctrl, in1, in2) {} 75.90 + typedef AddINode MathOp; 75.91 + 75.92 + OverflowAddINode(Node* in1, Node* in2) : OverflowINode(in1, in2) {} 75.93 virtual int Opcode() const; 75.94 - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 75.95 + 75.96 + virtual bool will_overflow(jint v1, jint v2) const; 75.97 + virtual bool can_overflow(const Type* t1, const Type* t2) const; 75.98 }; 75.99 75.100 -class AddExactLNode : public MathExactLNode { 75.101 +class OverflowSubINode : public OverflowINode { 75.102 public: 75.103 - AddExactLNode(Node* ctrl, Node* in1, Node* in2) : MathExactLNode(ctrl, in1, in2) {} 75.104 + typedef SubINode MathOp; 75.105 + 75.106 + OverflowSubINode(Node* in1, Node* in2) : OverflowINode(in1, in2) {} 75.107 virtual int Opcode() const; 75.108 - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); 75.109 + 75.110 + virtual bool will_overflow(jint v1, jint v2) const; 75.111 + virtual bool can_overflow(const Type* t1, const Type* t2) const; 75.112 }; 75.113 75.114 -class SubExactINode : public MathExactINode { 75.115 +class OverflowMulINode : public OverflowINode { 75.116 public: 75.117 - SubExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactINode(ctrl, in1, in2) {} 75.118 + typedef MulINode MathOp; 75.119 + 75.120 + OverflowMulINode(Node* in1, Node* in2) : OverflowINode(in1, in2) {} 75.121 virtual int Opcode() const; 75.122 - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); 75.123 + 75.124 + virtual bool will_overflow(jint v1, jint v2) const; 75.125 + virtual bool can_overflow(const Type* t1, const Type* t2) const; 75.126 }; 75.127 75.128 -class SubExactLNode : public MathExactLNode { 75.129 +class OverflowAddLNode : public OverflowLNode { 75.130 public: 75.131 - SubExactLNode(Node* ctrl, Node* in1, Node* in2) : MathExactLNode(ctrl, in1, in2) {} 75.132 + typedef AddLNode MathOp; 75.133 + 75.134 + OverflowAddLNode(Node* in1, Node* in2) : OverflowLNode(in1, in2) {} 75.135 virtual int Opcode() const; 75.136 - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); 75.137 + 75.138 + virtual bool will_overflow(jlong v1, jlong v2) const; 75.139 + virtual bool can_overflow(const Type* t1, const Type* t2) const; 75.140 }; 75.141 75.142 -class NegExactINode : public MathExactINode { 75.143 +class OverflowSubLNode : public OverflowLNode { 75.144 public: 75.145 - NegExactINode(Node* ctrl, Node* in1) : MathExactINode(ctrl, in1) {} 75.146 + typedef SubLNode MathOp; 75.147 + 75.148 + OverflowSubLNode(Node* in1, Node* in2) : OverflowLNode(in1, in2) {} 75.149 virtual int Opcode() const; 75.150 - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); 75.151 + 75.152 + virtual bool will_overflow(jlong v1, jlong v2) const; 75.153 + virtual bool can_overflow(const Type* t1, const Type* t2) const; 75.154 }; 75.155 75.156 -class NegExactLNode : public MathExactLNode { 75.157 +class OverflowMulLNode : public OverflowLNode { 75.158 public: 75.159 - NegExactLNode(Node* ctrl, Node* in1) : MathExactLNode(ctrl, in1) {} 75.160 + typedef MulLNode MathOp; 75.161 + 75.162 + OverflowMulLNode(Node* in1, Node* in2) : OverflowLNode(in1, in2) {} 75.163 virtual int Opcode() const; 75.164 - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); 75.165 + 75.166 + virtual bool will_overflow(jlong v1, jlong v2) const; 75.167 + virtual bool can_overflow(const Type* t1, const Type* t2) const; 75.168 }; 75.169 75.170 -class MulExactINode : public MathExactINode { 75.171 -public: 75.172 - MulExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactINode(ctrl, in1, in2) {} 75.173 - virtual int Opcode() const; 75.174 - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); 75.175 -}; 75.176 - 75.177 -class MulExactLNode : public MathExactLNode { 75.178 -public: 75.179 - MulExactLNode(Node* ctrl, Node* in1, Node* in2) : MathExactLNode(ctrl, in1, in2) {} 75.180 - virtual int Opcode() const; 75.181 - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); 75.182 -}; 75.183 - 75.184 -class FlagsProjNode : public ProjNode { 75.185 -public: 75.186 - FlagsProjNode(Node* src, uint con) : ProjNode(src, con) { 75.187 - init_class_id(Class_FlagsProj); 75.188 - } 75.189 - 75.190 - virtual int Opcode() const; 75.191 - virtual bool is_CFG() const { return false; } 75.192 - virtual const Type* bottom_type() const { return TypeInt::CC; } 75.193 - virtual uint ideal_reg() const { return Op_RegFlags; } 75.194 -}; 75.195 - 75.196 - 75.197 #endif 75.198
76.1 --- a/src/share/vm/opto/multnode.cpp Thu Mar 20 10:34:48 2014 -0700 76.2 +++ b/src/share/vm/opto/multnode.cpp Thu Mar 27 14:50:50 2014 -0700 76.3 @@ -54,11 +54,6 @@ 76.4 assert(Opcode() != Op_If || proj->Opcode() == (which_proj?Op_IfTrue:Op_IfFalse), "bad if #2"); 76.5 return proj; 76.6 } 76.7 - } else if (p->is_FlagsProj()) { 76.8 - FlagsProjNode *proj = p->as_FlagsProj(); 76.9 - if (proj->_con == which_proj) { 76.10 - return proj; 76.11 - } 76.12 } else { 76.13 assert(p == this && this->is_Start(), "else must be proj"); 76.14 continue;
77.1 --- a/src/share/vm/opto/node.hpp Thu Mar 20 10:34:48 2014 -0700 77.2 +++ b/src/share/vm/opto/node.hpp Thu Mar 27 14:50:50 2014 -0700 77.3 @@ -69,7 +69,6 @@ 77.4 class EncodePKlassNode; 77.5 class FastLockNode; 77.6 class FastUnlockNode; 77.7 -class FlagsProjNode; 77.8 class IfNode; 77.9 class IfFalseNode; 77.10 class IfTrueNode; 77.11 @@ -100,7 +99,6 @@ 77.12 class MachSpillCopyNode; 77.13 class MachTempNode; 77.14 class Matcher; 77.15 -class MathExactNode; 77.16 class MemBarNode; 77.17 class MemBarStoreStoreNode; 77.18 class MemNode; 77.19 @@ -569,7 +567,6 @@ 77.20 DEFINE_CLASS_ID(MemBar, Multi, 3) 77.21 DEFINE_CLASS_ID(Initialize, MemBar, 0) 77.22 DEFINE_CLASS_ID(MemBarStoreStore, MemBar, 1) 77.23 - DEFINE_CLASS_ID(MathExact, Multi, 4) 77.24 77.25 DEFINE_CLASS_ID(Mach, Node, 1) 77.26 DEFINE_CLASS_ID(MachReturn, Mach, 0) 77.27 @@ -626,7 +623,6 @@ 77.28 DEFINE_CLASS_ID(Cmp, Sub, 0) 77.29 DEFINE_CLASS_ID(FastLock, Cmp, 0) 77.30 DEFINE_CLASS_ID(FastUnlock, Cmp, 1) 77.31 - DEFINE_CLASS_ID(FlagsProj, Cmp, 2) 77.32 77.33 DEFINE_CLASS_ID(MergeMem, Node, 7) 77.34 DEFINE_CLASS_ID(Bool, Node, 8) 77.35 @@ -730,7 +726,6 @@ 77.36 DEFINE_CLASS_QUERY(EncodePKlass) 77.37 DEFINE_CLASS_QUERY(FastLock) 77.38 DEFINE_CLASS_QUERY(FastUnlock) 77.39 - DEFINE_CLASS_QUERY(FlagsProj) 77.40 DEFINE_CLASS_QUERY(If) 77.41 DEFINE_CLASS_QUERY(IfFalse) 77.42 DEFINE_CLASS_QUERY(IfTrue) 77.43 @@ -759,7 +754,6 @@ 77.44 DEFINE_CLASS_QUERY(MachSafePoint) 77.45 DEFINE_CLASS_QUERY(MachSpillCopy) 77.46 DEFINE_CLASS_QUERY(MachTemp) 77.47 - DEFINE_CLASS_QUERY(MathExact) 77.48 DEFINE_CLASS_QUERY(Mem) 77.49 DEFINE_CLASS_QUERY(MemBar) 77.50 DEFINE_CLASS_QUERY(MemBarStoreStore)
78.1 --- a/src/share/vm/opto/subnode.cpp Thu Mar 20 10:34:48 2014 -0700 78.2 +++ b/src/share/vm/opto/subnode.cpp Thu Mar 27 14:50:50 2014 -0700 78.3 @@ -1126,11 +1126,15 @@ 78.4 Node *cmp = in(1); 78.5 if( !cmp->is_Sub() ) return NULL; 78.6 int cop = cmp->Opcode(); 78.7 - if( cop == Op_FastLock || cop == Op_FastUnlock || cop == Op_FlagsProj) return NULL; 78.8 + if( cop == Op_FastLock || cop == Op_FastUnlock) return NULL; 78.9 Node *cmp1 = cmp->in(1); 78.10 Node *cmp2 = cmp->in(2); 78.11 if( !cmp1 ) return NULL; 78.12 78.13 + if (_test._test == BoolTest::overflow || _test._test == BoolTest::no_overflow) { 78.14 + return NULL; 78.15 + } 78.16 + 78.17 // Constant on left? 78.18 Node *con = cmp1; 78.19 uint op2 = cmp2->Opcode();
79.1 --- a/src/share/vm/opto/type.cpp Thu Mar 20 10:34:48 2014 -0700 79.2 +++ b/src/share/vm/opto/type.cpp Thu Mar 27 14:50:50 2014 -0700 79.3 @@ -301,6 +301,7 @@ 79.4 TypeInt::POS1 = TypeInt::make(1,max_jint, WidenMin); // Positive values 79.5 TypeInt::INT = TypeInt::make(min_jint,max_jint, WidenMax); // 32-bit integers 79.6 TypeInt::SYMINT = TypeInt::make(-max_jint,max_jint,WidenMin); // symmetric range 79.7 + TypeInt::TYPE_DOMAIN = TypeInt::INT; 79.8 // CmpL is overloaded both as the bytecode computation returning 79.9 // a trinary (-1,0,+1) integer result AND as an efficient long 79.10 // compare returning optimizer ideal-type flags. 79.11 @@ -317,6 +318,7 @@ 79.12 TypeLong::LONG = TypeLong::make(min_jlong,max_jlong,WidenMax); // 64-bit integers 79.13 TypeLong::INT = TypeLong::make((jlong)min_jint,(jlong)max_jint,WidenMin); 79.14 TypeLong::UINT = TypeLong::make(0,(jlong)max_juint,WidenMin); 79.15 + TypeLong::TYPE_DOMAIN = TypeLong::LONG; 79.16 79.17 const Type **fboth =(const Type**)shared_type_arena->Amalloc_4(2*sizeof(Type*)); 79.18 fboth[0] = Type::CONTROL; 79.19 @@ -1156,6 +1158,7 @@ 79.20 const TypeInt *TypeInt::POS1; // Positive 32-bit integers 79.21 const TypeInt *TypeInt::INT; // 32-bit integers 79.22 const TypeInt *TypeInt::SYMINT; // symmetric range [-max_jint..max_jint] 79.23 +const TypeInt *TypeInt::TYPE_DOMAIN; // alias for TypeInt::INT 79.24 79.25 //------------------------------TypeInt---------------------------------------- 79.26 TypeInt::TypeInt( jint lo, jint hi, int w ) : Type(Int), _lo(lo), _hi(hi), _widen(w) { 79.27 @@ -1413,6 +1416,7 @@ 79.28 const TypeLong *TypeLong::LONG; // 64-bit integers 79.29 const TypeLong *TypeLong::INT; // 32-bit subrange 79.30 const TypeLong *TypeLong::UINT; // 32-bit unsigned subrange 79.31 +const TypeLong *TypeLong::TYPE_DOMAIN; // alias for TypeLong::LONG 79.32 79.33 //------------------------------TypeLong--------------------------------------- 79.34 TypeLong::TypeLong( jlong lo, jlong hi, int w ) : Type(Long), _lo(lo), _hi(hi), _widen(w) { 79.35 @@ -2453,7 +2457,7 @@ 79.36 const TypeOopPtr *TypeOopPtr::BOTTOM; 79.37 79.38 //------------------------------TypeOopPtr------------------------------------- 79.39 -TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative) 79.40 +TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth) 79.41 : TypePtr(t, ptr, offset), 79.42 _const_oop(o), _klass(k), 79.43 _klass_is_exact(xk), 79.44 @@ -2461,7 +2465,8 @@ 79.45 _is_ptr_to_narrowklass(false), 79.46 _is_ptr_to_boxed_value(false), 79.47 _instance_id(instance_id), 79.48 - _speculative(speculative) { 79.49 + _speculative(speculative), 79.50 + _inline_depth(inline_depth){ 79.51 if (Compile::current()->eliminate_boxing() && (t == InstPtr) && 79.52 (offset > 0) && xk && (k != 0) && k->is_instance_klass()) { 79.53 _is_ptr_to_boxed_value = k->as_instance_klass()->is_boxed_value_offset(offset); 79.54 @@ -2528,12 +2533,12 @@ 79.55 79.56 //------------------------------make------------------------------------------- 79.57 const TypeOopPtr *TypeOopPtr::make(PTR ptr, 79.58 - int offset, int instance_id, const TypeOopPtr* speculative) { 79.59 + int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth) { 79.60 assert(ptr != Constant, "no constant generic pointers"); 79.61 ciKlass* k = Compile::current()->env()->Object_klass(); 79.62 bool xk = false; 79.63 ciObject* o = NULL; 79.64 - return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, instance_id, speculative))->hashcons(); 79.65 + return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, instance_id, speculative, inline_depth))->hashcons(); 79.66 } 79.67 79.68 79.69 @@ -2541,7 +2546,7 @@ 79.70 const Type *TypeOopPtr::cast_to_ptr_type(PTR ptr) const { 79.71 assert(_base == OopPtr, "subclass must override cast_to_ptr_type"); 79.72 if( ptr == _ptr ) return this; 79.73 - return make(ptr, _offset, _instance_id, _speculative); 79.74 + return make(ptr, _offset, _instance_id, _speculative, _inline_depth); 79.75 } 79.76 79.77 //-----------------------------cast_to_instance_id---------------------------- 79.78 @@ -2638,7 +2643,7 @@ 79.79 case AnyNull: { 79.80 int instance_id = meet_instance_id(InstanceTop); 79.81 const TypeOopPtr* speculative = _speculative; 79.82 - return make(ptr, offset, instance_id, speculative); 79.83 + return make(ptr, offset, instance_id, speculative, _inline_depth); 79.84 } 79.85 case BotPTR: 79.86 case NotNull: 79.87 @@ -2651,7 +2656,8 @@ 79.88 const TypeOopPtr *tp = t->is_oopptr(); 79.89 int instance_id = meet_instance_id(tp->instance_id()); 79.90 const TypeOopPtr* speculative = xmeet_speculative(tp); 79.91 - return make(meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id, speculative); 79.92 + int depth = meet_inline_depth(tp->inline_depth()); 79.93 + return make(meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id, speculative, depth); 79.94 } 79.95 79.96 case InstPtr: // For these, flip the call around to cut down 79.97 @@ -2668,7 +2674,7 @@ 79.98 const Type *TypeOopPtr::xdual() const { 79.99 assert(klass() == Compile::current()->env()->Object_klass(), "no klasses here"); 79.100 assert(const_oop() == NULL, "no constants here"); 79.101 - return new TypeOopPtr(_base, dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative()); 79.102 + return new TypeOopPtr(_base, dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative(), dual_inline_depth()); 79.103 } 79.104 79.105 //--------------------------make_from_klass_common----------------------------- 79.106 @@ -2759,7 +2765,7 @@ 79.107 } else if (!o->should_be_constant()) { 79.108 return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0); 79.109 } 79.110 - const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0, InstanceBot, NULL, is_autobox_cache); 79.111 + const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0, InstanceBot, NULL, InlineDepthBottom, is_autobox_cache); 79.112 return arr; 79.113 } else if (klass->is_type_array_klass()) { 79.114 // Element is an typeArray 79.115 @@ -2848,7 +2854,8 @@ 79.116 const TypeOopPtr *a = (const TypeOopPtr*)t; 79.117 if (_klass_is_exact != a->_klass_is_exact || 79.118 _instance_id != a->_instance_id || 79.119 - !eq_speculative(a)) return false; 79.120 + !eq_speculative(a) || 79.121 + _inline_depth != a->_inline_depth) return false; 79.122 ciObject* one = const_oop(); 79.123 ciObject* two = a->const_oop(); 79.124 if (one == NULL || two == NULL) { 79.125 @@ -2866,6 +2873,7 @@ 79.126 _klass_is_exact + 79.127 _instance_id + 79.128 hash_speculative() + 79.129 + _inline_depth + 79.130 TypePtr::hash(); 79.131 } 79.132 79.133 @@ -2886,6 +2894,7 @@ 79.134 else if (_instance_id != InstanceBot) 79.135 st->print(",iid=%d",_instance_id); 79.136 79.137 + dump_inline_depth(st); 79.138 dump_speculative(st); 79.139 } 79.140 79.141 @@ -2899,6 +2908,16 @@ 79.142 st->print(")"); 79.143 } 79.144 } 79.145 + 79.146 +void TypeOopPtr::dump_inline_depth(outputStream *st) const { 79.147 + if (_inline_depth != InlineDepthBottom) { 79.148 + if (_inline_depth == InlineDepthTop) { 79.149 + st->print(" (inline_depth=InlineDepthTop)"); 79.150 + } else { 79.151 + st->print(" (inline_depth=%d)", _inline_depth); 79.152 + } 79.153 + } 79.154 +} 79.155 #endif 79.156 79.157 //------------------------------singleton-------------------------------------- 79.158 @@ -2912,7 +2931,7 @@ 79.159 79.160 //------------------------------add_offset------------------------------------- 79.161 const TypePtr *TypeOopPtr::add_offset(intptr_t offset) const { 79.162 - return make(_ptr, xadd_offset(offset), _instance_id, add_offset_speculative(offset)); 79.163 + return make(_ptr, xadd_offset(offset), _instance_id, add_offset_speculative(offset), _inline_depth); 79.164 } 79.165 79.166 /** 79.167 @@ -2922,7 +2941,52 @@ 79.168 if (_speculative == NULL) { 79.169 return this; 79.170 } 79.171 - return make(_ptr, _offset, _instance_id, NULL); 79.172 + assert(_inline_depth == InlineDepthTop || _inline_depth == InlineDepthBottom, "non speculative type shouldn't have inline depth"); 79.173 + return make(_ptr, _offset, _instance_id, NULL, _inline_depth); 79.174 +} 79.175 + 79.176 +/** 79.177 + * Return same type but with a different inline depth (used for speculation) 79.178 + * 79.179 + * @param depth depth to meet with 79.180 + */ 79.181 +const TypeOopPtr* TypeOopPtr::with_inline_depth(int depth) const { 79.182 + if (!UseInlineDepthForSpeculativeTypes) { 79.183 + return this; 79.184 + } 79.185 + return make(_ptr, _offset, _instance_id, _speculative, depth); 79.186 +} 79.187 + 79.188 +/** 79.189 + * Check whether new profiling would improve speculative type 79.190 + * 79.191 + * @param exact_kls class from profiling 79.192 + * @param inline_depth inlining depth of profile point 79.193 + * 79.194 + * @return true if type profile is valuable 79.195 + */ 79.196 +bool TypeOopPtr::would_improve_type(ciKlass* exact_kls, int inline_depth) const { 79.197 + // no way to improve an already exact type 79.198 + if (klass_is_exact()) { 79.199 + return false; 79.200 + } 79.201 + // no profiling? 79.202 + if (exact_kls == NULL) { 79.203 + return false; 79.204 + } 79.205 + // no speculative type or non exact speculative type? 79.206 + if (speculative_type() == NULL) { 79.207 + return true; 79.208 + } 79.209 + // If the node already has an exact speculative type keep it, 79.210 + // unless it was provided by profiling that is at a deeper 79.211 + // inlining level. Profiling at a higher inlining depth is 79.212 + // expected to be less accurate. 79.213 + if (_speculative->inline_depth() == InlineDepthBottom) { 79.214 + return false; 79.215 + } 79.216 + assert(_speculative->inline_depth() != InlineDepthTop, "can't do the comparison"); 79.217 + return inline_depth < _speculative->inline_depth(); 79.218 } 79.219 79.220 //------------------------------meet_instance_id-------------------------------- 79.221 @@ -3025,6 +3089,21 @@ 79.222 return _speculative->hash(); 79.223 } 79.224 79.225 +/** 79.226 + * dual of the inline depth for this type (used for speculation) 79.227 + */ 79.228 +int TypeOopPtr::dual_inline_depth() const { 79.229 + return -inline_depth(); 79.230 +} 79.231 + 79.232 +/** 79.233 + * meet of 2 inline depth (used for speculation) 79.234 + * 79.235 + * @param depth depth to meet with 79.236 + */ 79.237 +int TypeOopPtr::meet_inline_depth(int depth) const { 79.238 + return MAX2(inline_depth(), depth); 79.239 +} 79.240 79.241 //============================================================================= 79.242 // Convenience common pre-built types. 79.243 @@ -3035,8 +3114,8 @@ 79.244 const TypeInstPtr *TypeInstPtr::KLASS; 79.245 79.246 //------------------------------TypeInstPtr------------------------------------- 79.247 -TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off, int instance_id, const TypeOopPtr* speculative) 79.248 - : TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative), _name(k->name()) { 79.249 +TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off, int instance_id, const TypeOopPtr* speculative, int inline_depth) 79.250 + : TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative, inline_depth), _name(k->name()) { 79.251 assert(k != NULL && 79.252 (k->is_loaded() || o == NULL), 79.253 "cannot have constants with non-loaded klass"); 79.254 @@ -3049,7 +3128,8 @@ 79.255 ciObject* o, 79.256 int offset, 79.257 int instance_id, 79.258 - const TypeOopPtr* speculative) { 79.259 + const TypeOopPtr* speculative, 79.260 + int inline_depth) { 79.261 assert( !k->is_loaded() || k->is_instance_klass(), "Must be for instance"); 79.262 // Either const_oop() is NULL or else ptr is Constant 79.263 assert( (!o && ptr != Constant) || (o && ptr == Constant), 79.264 @@ -3070,7 +3150,7 @@ 79.265 79.266 // Now hash this baby 79.267 TypeInstPtr *result = 79.268 - (TypeInstPtr*)(new TypeInstPtr(ptr, k, xk, o ,offset, instance_id, speculative))->hashcons(); 79.269 + (TypeInstPtr*)(new TypeInstPtr(ptr, k, xk, o ,offset, instance_id, speculative, inline_depth))->hashcons(); 79.270 79.271 return result; 79.272 } 79.273 @@ -3103,7 +3183,7 @@ 79.274 if( ptr == _ptr ) return this; 79.275 // Reconstruct _sig info here since not a problem with later lazy 79.276 // construction, _sig will show up on demand. 79.277 - return make(ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, _speculative); 79.278 + return make(ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, _speculative, _inline_depth); 79.279 } 79.280 79.281 79.282 @@ -3115,13 +3195,13 @@ 79.283 ciInstanceKlass* ik = _klass->as_instance_klass(); 79.284 if( (ik->is_final() || _const_oop) ) return this; // cannot clear xk 79.285 if( ik->is_interface() ) return this; // cannot set xk 79.286 - return make(ptr(), klass(), klass_is_exact, const_oop(), _offset, _instance_id, _speculative); 79.287 + return make(ptr(), klass(), klass_is_exact, const_oop(), _offset, _instance_id, _speculative, _inline_depth); 79.288 } 79.289 79.290 //-----------------------------cast_to_instance_id---------------------------- 79.291 const TypeOopPtr *TypeInstPtr::cast_to_instance_id(int instance_id) const { 79.292 if( instance_id == _instance_id ) return this; 79.293 - return make(_ptr, klass(), _klass_is_exact, const_oop(), _offset, instance_id, _speculative); 79.294 + return make(_ptr, klass(), _klass_is_exact, const_oop(), _offset, instance_id, _speculative, _inline_depth); 79.295 } 79.296 79.297 //------------------------------xmeet_unloaded--------------------------------- 79.298 @@ -3132,6 +3212,7 @@ 79.299 PTR ptr = meet_ptr(tinst->ptr()); 79.300 int instance_id = meet_instance_id(tinst->instance_id()); 79.301 const TypeOopPtr* speculative = xmeet_speculative(tinst); 79.302 + int depth = meet_inline_depth(tinst->inline_depth()); 79.303 79.304 const TypeInstPtr *loaded = is_loaded() ? this : tinst; 79.305 const TypeInstPtr *unloaded = is_loaded() ? tinst : this; 79.306 @@ -3152,7 +3233,7 @@ 79.307 assert(loaded->ptr() != TypePtr::Null, "insanity check"); 79.308 // 79.309 if( loaded->ptr() == TypePtr::TopPTR ) { return unloaded; } 79.310 - else if (loaded->ptr() == TypePtr::AnyNull) { return TypeInstPtr::make(ptr, unloaded->klass(), false, NULL, off, instance_id, speculative); } 79.311 + else if (loaded->ptr() == TypePtr::AnyNull) { return TypeInstPtr::make(ptr, unloaded->klass(), false, NULL, off, instance_id, speculative, depth); } 79.312 else if (loaded->ptr() == TypePtr::BotPTR ) { return TypeInstPtr::BOTTOM; } 79.313 else if (loaded->ptr() == TypePtr::Constant || loaded->ptr() == TypePtr::NotNull) { 79.314 if (unloaded->ptr() == TypePtr::BotPTR ) { return TypeInstPtr::BOTTOM; } 79.315 @@ -3209,6 +3290,7 @@ 79.316 PTR ptr = meet_ptr(tp->ptr()); 79.317 int instance_id = meet_instance_id(tp->instance_id()); 79.318 const TypeOopPtr* speculative = xmeet_speculative(tp); 79.319 + int depth = meet_inline_depth(tp->inline_depth()); 79.320 switch (ptr) { 79.321 case TopPTR: 79.322 case AnyNull: // Fall 'down' to dual of object klass 79.323 @@ -3216,12 +3298,12 @@ 79.324 // below the centerline when the superclass is exact. We need to 79.325 // do the same here. 79.326 if (klass()->equals(ciEnv::current()->Object_klass()) && !klass_is_exact()) { 79.327 - return TypeAryPtr::make(ptr, tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative); 79.328 + return TypeAryPtr::make(ptr, tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative, depth); 79.329 } else { 79.330 // cannot subclass, so the meet has to fall badly below the centerline 79.331 ptr = NotNull; 79.332 instance_id = InstanceBot; 79.333 - return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative); 79.334 + return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative, depth); 79.335 } 79.336 case Constant: 79.337 case NotNull: 79.338 @@ -3236,7 +3318,7 @@ 79.339 if (klass()->equals(ciEnv::current()->Object_klass()) && !klass_is_exact()) { 79.340 // that is, tp's array type is a subtype of my klass 79.341 return TypeAryPtr::make(ptr, (ptr == Constant ? tp->const_oop() : NULL), 79.342 - tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative); 79.343 + tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative, depth); 79.344 } 79.345 } 79.346 // The other case cannot happen, since I cannot be a subtype of an array. 79.347 @@ -3244,7 +3326,7 @@ 79.348 if( ptr == Constant ) 79.349 ptr = NotNull; 79.350 instance_id = InstanceBot; 79.351 - return make(ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative); 79.352 + return make(ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative, depth); 79.353 default: typerr(t); 79.354 } 79.355 } 79.356 @@ -3259,14 +3341,16 @@ 79.357 case AnyNull: { 79.358 int instance_id = meet_instance_id(InstanceTop); 79.359 const TypeOopPtr* speculative = xmeet_speculative(tp); 79.360 + int depth = meet_inline_depth(tp->inline_depth()); 79.361 return make(ptr, klass(), klass_is_exact(), 79.362 - (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative); 79.363 + (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative, depth); 79.364 } 79.365 case NotNull: 79.366 case BotPTR: { 79.367 int instance_id = meet_instance_id(tp->instance_id()); 79.368 const TypeOopPtr* speculative = xmeet_speculative(tp); 79.369 - return TypeOopPtr::make(ptr, offset, instance_id, speculative); 79.370 + int depth = meet_inline_depth(tp->inline_depth()); 79.371 + return TypeOopPtr::make(ptr, offset, instance_id, speculative, depth); 79.372 } 79.373 default: typerr(t); 79.374 } 79.375 @@ -3286,7 +3370,7 @@ 79.376 int instance_id = meet_instance_id(InstanceTop); 79.377 const TypeOopPtr* speculative = _speculative; 79.378 return make(ptr, klass(), klass_is_exact(), 79.379 - (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative); 79.380 + (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative, _inline_depth); 79.381 } 79.382 case NotNull: 79.383 case BotPTR: 79.384 @@ -3318,13 +3402,14 @@ 79.385 PTR ptr = meet_ptr( tinst->ptr() ); 79.386 int instance_id = meet_instance_id(tinst->instance_id()); 79.387 const TypeOopPtr* speculative = xmeet_speculative(tinst); 79.388 + int depth = meet_inline_depth(tinst->inline_depth()); 79.389 79.390 // Check for easy case; klasses are equal (and perhaps not loaded!) 79.391 // If we have constants, then we created oops so classes are loaded 79.392 // and we can handle the constants further down. This case handles 79.393 // both-not-loaded or both-loaded classes 79.394 if (ptr != Constant && klass()->equals(tinst->klass()) && klass_is_exact() == tinst->klass_is_exact()) { 79.395 - return make(ptr, klass(), klass_is_exact(), NULL, off, instance_id, speculative); 79.396 + return make(ptr, klass(), klass_is_exact(), NULL, off, instance_id, speculative, depth); 79.397 } 79.398 79.399 // Classes require inspection in the Java klass hierarchy. Must be loaded. 79.400 @@ -3388,7 +3473,7 @@ 79.401 // Find out which constant. 79.402 o = (this_klass == klass()) ? const_oop() : tinst->const_oop(); 79.403 } 79.404 - return make(ptr, k, xk, o, off, instance_id, speculative); 79.405 + return make(ptr, k, xk, o, off, instance_id, speculative, depth); 79.406 } 79.407 79.408 // Either oop vs oop or interface vs interface or interface vs Object 79.409 @@ -3465,7 +3550,7 @@ 79.410 else 79.411 ptr = NotNull; 79.412 } 79.413 - return make(ptr, this_klass, this_xk, o, off, instance_id, speculative); 79.414 + return make(ptr, this_klass, this_xk, o, off, instance_id, speculative, depth); 79.415 } // Else classes are not equal 79.416 79.417 // Since klasses are different, we require a LCA in the Java 79.418 @@ -3476,7 +3561,7 @@ 79.419 79.420 // Now we find the LCA of Java classes 79.421 ciKlass* k = this_klass->least_common_ancestor(tinst_klass); 79.422 - return make(ptr, k, false, NULL, off, instance_id, speculative); 79.423 + return make(ptr, k, false, NULL, off, instance_id, speculative, depth); 79.424 } // End of case InstPtr 79.425 79.426 } // End of switch 79.427 @@ -3500,7 +3585,7 @@ 79.428 // Dual: do NOT dual on klasses. This means I do NOT understand the Java 79.429 // inheritance mechanism. 79.430 const Type *TypeInstPtr::xdual() const { 79.431 - return new TypeInstPtr(dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative()); 79.432 + return new TypeInstPtr(dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative(), dual_inline_depth()); 79.433 } 79.434 79.435 //------------------------------eq--------------------------------------------- 79.436 @@ -3557,6 +3642,7 @@ 79.437 else if (_instance_id != InstanceBot) 79.438 st->print(",iid=%d",_instance_id); 79.439 79.440 + dump_inline_depth(st); 79.441 dump_speculative(st); 79.442 } 79.443 #endif 79.444 @@ -3570,7 +3656,15 @@ 79.445 if (_speculative == NULL) { 79.446 return this; 79.447 } 79.448 - return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, NULL); 79.449 + assert(_inline_depth == InlineDepthTop || _inline_depth == InlineDepthBottom, "non speculative type shouldn't have inline depth"); 79.450 + return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, NULL, _inline_depth); 79.451 +} 79.452 + 79.453 +const TypeOopPtr *TypeInstPtr::with_inline_depth(int depth) const { 79.454 + if (!UseInlineDepthForSpeculativeTypes) { 79.455 + return this; 79.456 + } 79.457 + return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, _speculative, depth); 79.458 } 79.459 79.460 //============================================================================= 79.461 @@ -3587,30 +3681,30 @@ 79.462 const TypeAryPtr *TypeAryPtr::DOUBLES; 79.463 79.464 //------------------------------make------------------------------------------- 79.465 -const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative) { 79.466 +const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth) { 79.467 assert(!(k == NULL && ary->_elem->isa_int()), 79.468 "integral arrays must be pre-equipped with a class"); 79.469 if (!xk) xk = ary->ary_must_be_exact(); 79.470 assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed"); 79.471 if (!UseExactTypes) xk = (ptr == Constant); 79.472 - return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, instance_id, false, speculative))->hashcons(); 79.473 + return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, instance_id, false, speculative, inline_depth))->hashcons(); 79.474 } 79.475 79.476 //------------------------------make------------------------------------------- 79.477 -const TypeAryPtr *TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative, bool is_autobox_cache) { 79.478 +const TypeAryPtr *TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth, bool is_autobox_cache) { 79.479 assert(!(k == NULL && ary->_elem->isa_int()), 79.480 "integral arrays must be pre-equipped with a class"); 79.481 assert( (ptr==Constant && o) || (ptr!=Constant && !o), "" ); 79.482 if (!xk) xk = (o != NULL) || ary->ary_must_be_exact(); 79.483 assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed"); 79.484 if (!UseExactTypes) xk = (ptr == Constant); 79.485 - return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, instance_id, is_autobox_cache, speculative))->hashcons(); 79.486 + return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, instance_id, is_autobox_cache, speculative, inline_depth))->hashcons(); 79.487 } 79.488 79.489 //------------------------------cast_to_ptr_type------------------------------- 79.490 const Type *TypeAryPtr::cast_to_ptr_type(PTR ptr) const { 79.491 if( ptr == _ptr ) return this; 79.492 - return make(ptr, const_oop(), _ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative); 79.493 + return make(ptr, const_oop(), _ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth); 79.494 } 79.495 79.496 79.497 @@ -3619,13 +3713,13 @@ 79.498 if( klass_is_exact == _klass_is_exact ) return this; 79.499 if (!UseExactTypes) return this; 79.500 if (_ary->ary_must_be_exact()) return this; // cannot clear xk 79.501 - return make(ptr(), const_oop(), _ary, klass(), klass_is_exact, _offset, _instance_id, _speculative); 79.502 + return make(ptr(), const_oop(), _ary, klass(), klass_is_exact, _offset, _instance_id, _speculative, _inline_depth); 79.503 } 79.504 79.505 //-----------------------------cast_to_instance_id---------------------------- 79.506 const TypeOopPtr *TypeAryPtr::cast_to_instance_id(int instance_id) const { 79.507 if( instance_id == _instance_id ) return this; 79.508 - return make(_ptr, const_oop(), _ary, klass(), _klass_is_exact, _offset, instance_id, _speculative); 79.509 + return make(_ptr, const_oop(), _ary, klass(), _klass_is_exact, _offset, instance_id, _speculative, _inline_depth); 79.510 } 79.511 79.512 //-----------------------------narrow_size_type------------------------------- 79.513 @@ -3688,7 +3782,7 @@ 79.514 new_size = narrow_size_type(new_size); 79.515 if (new_size == size()) return this; 79.516 const TypeAry* new_ary = TypeAry::make(elem(), new_size, is_stable()); 79.517 - return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative); 79.518 + return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth); 79.519 } 79.520 79.521 79.522 @@ -3767,19 +3861,20 @@ 79.523 const TypeOopPtr *tp = t->is_oopptr(); 79.524 int offset = meet_offset(tp->offset()); 79.525 PTR ptr = meet_ptr(tp->ptr()); 79.526 + int depth = meet_inline_depth(tp->inline_depth()); 79.527 switch (tp->ptr()) { 79.528 case TopPTR: 79.529 case AnyNull: { 79.530 int instance_id = meet_instance_id(InstanceTop); 79.531 const TypeOopPtr* speculative = xmeet_speculative(tp); 79.532 return make(ptr, (ptr == Constant ? const_oop() : NULL), 79.533 - _ary, _klass, _klass_is_exact, offset, instance_id, speculative); 79.534 + _ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth); 79.535 } 79.536 case BotPTR: 79.537 case NotNull: { 79.538 int instance_id = meet_instance_id(tp->instance_id()); 79.539 const TypeOopPtr* speculative = xmeet_speculative(tp); 79.540 - return TypeOopPtr::make(ptr, offset, instance_id, speculative); 79.541 + return TypeOopPtr::make(ptr, offset, instance_id, speculative, depth); 79.542 } 79.543 default: ShouldNotReachHere(); 79.544 } 79.545 @@ -3803,7 +3898,7 @@ 79.546 int instance_id = meet_instance_id(InstanceTop); 79.547 const TypeOopPtr* speculative = _speculative; 79.548 return make(ptr, (ptr == Constant ? const_oop() : NULL), 79.549 - _ary, _klass, _klass_is_exact, offset, instance_id, speculative); 79.550 + _ary, _klass, _klass_is_exact, offset, instance_id, speculative, _inline_depth); 79.551 } 79.552 default: ShouldNotReachHere(); 79.553 } 79.554 @@ -3820,6 +3915,7 @@ 79.555 PTR ptr = meet_ptr(tap->ptr()); 79.556 int instance_id = meet_instance_id(tap->instance_id()); 79.557 const TypeOopPtr* speculative = xmeet_speculative(tap); 79.558 + int depth = meet_inline_depth(tap->inline_depth()); 79.559 ciKlass* lazy_klass = NULL; 79.560 if (tary->_elem->isa_int()) { 79.561 // Integral array element types have irrelevant lattice relations. 79.562 @@ -3860,7 +3956,7 @@ 79.563 } else { 79.564 xk = (tap->_klass_is_exact | this->_klass_is_exact); 79.565 } 79.566 - return make(ptr, const_oop(), tary, lazy_klass, xk, off, instance_id, speculative); 79.567 + return make(ptr, const_oop(), tary, lazy_klass, xk, off, instance_id, speculative, depth); 79.568 case Constant: { 79.569 ciObject* o = const_oop(); 79.570 if( _ptr == Constant ) { 79.571 @@ -3879,7 +3975,7 @@ 79.572 // Only precise for identical arrays 79.573 xk = this->_klass_is_exact && (klass() == tap->klass()); 79.574 } 79.575 - return TypeAryPtr::make(ptr, o, tary, lazy_klass, xk, off, instance_id, speculative); 79.576 + return TypeAryPtr::make(ptr, o, tary, lazy_klass, xk, off, instance_id, speculative, depth); 79.577 } 79.578 case NotNull: 79.579 case BotPTR: 79.580 @@ -3888,7 +3984,7 @@ 79.581 xk = tap->_klass_is_exact; 79.582 else xk = (tap->_klass_is_exact & this->_klass_is_exact) && 79.583 (klass() == tap->klass()); // Only precise for identical arrays 79.584 - return TypeAryPtr::make(ptr, NULL, tary, lazy_klass, xk, off, instance_id, speculative); 79.585 + return TypeAryPtr::make(ptr, NULL, tary, lazy_klass, xk, off, instance_id, speculative, depth); 79.586 default: ShouldNotReachHere(); 79.587 } 79.588 } 79.589 @@ -3900,6 +3996,7 @@ 79.590 PTR ptr = meet_ptr(tp->ptr()); 79.591 int instance_id = meet_instance_id(tp->instance_id()); 79.592 const TypeOopPtr* speculative = xmeet_speculative(tp); 79.593 + int depth = meet_inline_depth(tp->inline_depth()); 79.594 switch (ptr) { 79.595 case TopPTR: 79.596 case AnyNull: // Fall 'down' to dual of object klass 79.597 @@ -3907,12 +4004,12 @@ 79.598 // below the centerline when the superclass is exact. We need to 79.599 // do the same here. 79.600 if (tp->klass()->equals(ciEnv::current()->Object_klass()) && !tp->klass_is_exact()) { 79.601 - return TypeAryPtr::make(ptr, _ary, _klass, _klass_is_exact, offset, instance_id, speculative); 79.602 + return TypeAryPtr::make(ptr, _ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth); 79.603 } else { 79.604 // cannot subclass, so the meet has to fall badly below the centerline 79.605 ptr = NotNull; 79.606 instance_id = InstanceBot; 79.607 - return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative); 79.608 + return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative, depth); 79.609 } 79.610 case Constant: 79.611 case NotNull: 79.612 @@ -3927,7 +4024,7 @@ 79.613 if (tp->klass()->equals(ciEnv::current()->Object_klass()) && !tp->klass_is_exact()) { 79.614 // that is, my array type is a subtype of 'tp' klass 79.615 return make(ptr, (ptr == Constant ? const_oop() : NULL), 79.616 - _ary, _klass, _klass_is_exact, offset, instance_id, speculative); 79.617 + _ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth); 79.618 } 79.619 } 79.620 // The other case cannot happen, since t cannot be a subtype of an array. 79.621 @@ -3935,7 +4032,7 @@ 79.622 if( ptr == Constant ) 79.623 ptr = NotNull; 79.624 instance_id = InstanceBot; 79.625 - return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative); 79.626 + return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative, depth); 79.627 default: typerr(t); 79.628 } 79.629 } 79.630 @@ -3946,7 +4043,7 @@ 79.631 //------------------------------xdual------------------------------------------ 79.632 // Dual: compute field-by-field dual 79.633 const Type *TypeAryPtr::xdual() const { 79.634 - return new TypeAryPtr(dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id(), is_autobox_cache(), dual_speculative()); 79.635 + return new TypeAryPtr(dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id(), is_autobox_cache(), dual_speculative(), dual_inline_depth()); 79.636 } 79.637 79.638 //----------------------interface_vs_oop--------------------------------------- 79.639 @@ -3999,6 +4096,7 @@ 79.640 else if (_instance_id != InstanceBot) 79.641 st->print(",iid=%d",_instance_id); 79.642 79.643 + dump_inline_depth(st); 79.644 dump_speculative(st); 79.645 } 79.646 #endif 79.647 @@ -4010,11 +4108,22 @@ 79.648 79.649 //------------------------------add_offset------------------------------------- 79.650 const TypePtr *TypeAryPtr::add_offset(intptr_t offset) const { 79.651 - return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, xadd_offset(offset), _instance_id, add_offset_speculative(offset)); 79.652 + return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, xadd_offset(offset), _instance_id, add_offset_speculative(offset), _inline_depth); 79.653 } 79.654 79.655 const Type *TypeAryPtr::remove_speculative() const { 79.656 - return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _instance_id, NULL); 79.657 + if (_speculative == NULL) { 79.658 + return this; 79.659 + } 79.660 + assert(_inline_depth == InlineDepthTop || _inline_depth == InlineDepthBottom, "non speculative type shouldn't have inline depth"); 79.661 + return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _instance_id, NULL, _inline_depth); 79.662 +} 79.663 + 79.664 +const TypeOopPtr *TypeAryPtr::with_inline_depth(int depth) const { 79.665 + if (!UseInlineDepthForSpeculativeTypes) { 79.666 + return this; 79.667 + } 79.668 + return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _instance_id, _speculative, depth); 79.669 } 79.670 79.671 //=============================================================================
80.1 --- a/src/share/vm/opto/type.hpp Thu Mar 20 10:34:48 2014 -0700 80.2 +++ b/src/share/vm/opto/type.hpp Thu Mar 27 14:50:50 2014 -0700 80.3 @@ -415,10 +415,15 @@ 80.4 bool is_autobox_cache = false); 80.5 80.6 // Speculative type. See TypeInstPtr 80.7 + virtual const TypeOopPtr* speculative() const { return NULL; } 80.8 virtual ciKlass* speculative_type() const { return NULL; } 80.9 const Type* maybe_remove_speculative(bool include_speculative) const; 80.10 virtual const Type* remove_speculative() const { return this; } 80.11 80.12 + virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const { 80.13 + return exact_kls != NULL; 80.14 + } 80.15 + 80.16 private: 80.17 // support arrays 80.18 static const BasicType _basic_type[]; 80.19 @@ -489,6 +494,7 @@ 80.20 virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; 80.21 80.22 public: 80.23 + typedef jint NativeType; 80.24 virtual bool eq( const Type *t ) const; 80.25 virtual int hash() const; // Type specific hashing 80.26 virtual bool singleton(void) const; // TRUE if type is a singleton 80.27 @@ -531,6 +537,9 @@ 80.28 static const TypeInt *POS1; 80.29 static const TypeInt *INT; 80.30 static const TypeInt *SYMINT; // symmetric range [-max_jint..max_jint] 80.31 + static const TypeInt *TYPE_DOMAIN; // alias for TypeInt::INT 80.32 + 80.33 + static const TypeInt *as_self(const Type *t) { return t->is_int(); } 80.34 #ifndef PRODUCT 80.35 virtual void dump2( Dict &d, uint depth, outputStream *st ) const; 80.36 #endif 80.37 @@ -546,6 +555,7 @@ 80.38 // Do not kill _widen bits. 80.39 virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; 80.40 public: 80.41 + typedef jlong NativeType; 80.42 virtual bool eq( const Type *t ) const; 80.43 virtual int hash() const; // Type specific hashing 80.44 virtual bool singleton(void) const; // TRUE if type is a singleton 80.45 @@ -565,6 +575,7 @@ 80.46 80.47 virtual bool is_finite() const; // Has a finite value 80.48 80.49 + 80.50 virtual const Type *xmeet( const Type *t ) const; 80.51 virtual const Type *xdual() const; // Compute dual right now. 80.52 virtual const Type *widen( const Type *t, const Type* limit_type ) const; 80.53 @@ -577,6 +588,11 @@ 80.54 static const TypeLong *LONG; 80.55 static const TypeLong *INT; // 32-bit subrange [min_jint..max_jint] 80.56 static const TypeLong *UINT; // 32-bit unsigned [0..max_juint] 80.57 + static const TypeLong *TYPE_DOMAIN; // alias for TypeLong::LONG 80.58 + 80.59 + // static convenience methods. 80.60 + static const TypeLong *as_self(const Type *t) { return t->is_long(); } 80.61 + 80.62 #ifndef PRODUCT 80.63 virtual void dump2( Dict &d, uint, outputStream *st ) const;// Specialized per-Type dumping 80.64 #endif 80.65 @@ -831,7 +847,7 @@ 80.66 // Some kind of oop (Java pointer), either klass or instance or array. 80.67 class TypeOopPtr : public TypePtr { 80.68 protected: 80.69 - TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative); 80.70 + TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth); 80.71 public: 80.72 virtual bool eq( const Type *t ) const; 80.73 virtual int hash() const; // Type specific hashing 80.74 @@ -842,6 +858,10 @@ 80.75 }; 80.76 protected: 80.77 80.78 + enum { 80.79 + InlineDepthBottom = INT_MAX, 80.80 + InlineDepthTop = -InlineDepthBottom 80.81 + }; 80.82 // Oop is NULL, unless this is a constant oop. 80.83 ciObject* _const_oop; // Constant oop 80.84 // If _klass is NULL, then so is _sig. This is an unloaded klass. 80.85 @@ -862,6 +882,11 @@ 80.86 // use it, then we have to emit a guard: this part of the type is 80.87 // not something we know but something we speculate about the type. 80.88 const TypeOopPtr* _speculative; 80.89 + // For speculative types, we record at what inlining depth the 80.90 + // profiling point that provided the data is. We want to favor 80.91 + // profile data coming from outer scopes which are likely better for 80.92 + // the current compilation. 80.93 + int _inline_depth; 80.94 80.95 static const TypeOopPtr* make_from_klass_common(ciKlass* klass, bool klass_change, bool try_for_exact); 80.96 80.97 @@ -877,6 +902,12 @@ 80.98 #ifndef PRODUCT 80.99 void dump_speculative(outputStream *st) const; 80.100 #endif 80.101 + // utility methods to work on the inline depth of the type 80.102 + int dual_inline_depth() const; 80.103 + int meet_inline_depth(int depth) const; 80.104 +#ifndef PRODUCT 80.105 + void dump_inline_depth(outputStream *st) const; 80.106 +#endif 80.107 80.108 // Do not allow interface-vs.-noninterface joins to collapse to top. 80.109 virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; 80.110 @@ -907,7 +938,7 @@ 80.111 bool not_null_elements = false); 80.112 80.113 // Make a generic (unclassed) pointer to an oop. 80.114 - static const TypeOopPtr* make(PTR ptr, int offset, int instance_id, const TypeOopPtr* speculative); 80.115 + static const TypeOopPtr* make(PTR ptr, int offset, int instance_id, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom); 80.116 80.117 ciObject* const_oop() const { return _const_oop; } 80.118 virtual ciKlass* klass() const { return _klass; } 80.119 @@ -921,7 +952,7 @@ 80.120 bool is_known_instance() const { return _instance_id > 0; } 80.121 int instance_id() const { return _instance_id; } 80.122 bool is_known_instance_field() const { return is_known_instance() && _offset >= 0; } 80.123 - const TypeOopPtr* speculative() const { return _speculative; } 80.124 + virtual const TypeOopPtr* speculative() const { return _speculative; } 80.125 80.126 virtual intptr_t get_con() const; 80.127 80.128 @@ -954,18 +985,23 @@ 80.129 if (_speculative != NULL) { 80.130 const TypeOopPtr* speculative = _speculative->join(this)->is_oopptr(); 80.131 if (speculative->klass_is_exact()) { 80.132 - return speculative->klass(); 80.133 + return speculative->klass(); 80.134 } 80.135 } 80.136 return NULL; 80.137 } 80.138 + int inline_depth() const { 80.139 + return _inline_depth; 80.140 + } 80.141 + virtual const TypeOopPtr* with_inline_depth(int depth) const; 80.142 + virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const; 80.143 }; 80.144 80.145 //------------------------------TypeInstPtr------------------------------------ 80.146 // Class of Java object pointers, pointing either to non-array Java instances 80.147 // or to a Klass* (including array klasses). 80.148 class TypeInstPtr : public TypeOopPtr { 80.149 - TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative); 80.150 + TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth); 80.151 virtual bool eq( const Type *t ) const; 80.152 virtual int hash() const; // Type specific hashing 80.153 80.154 @@ -1001,7 +1037,7 @@ 80.155 } 80.156 80.157 // Make a pointer to an oop. 80.158 - static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL); 80.159 + static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom); 80.160 80.161 /** Create constant type for a constant boxed value */ 80.162 const Type* get_const_boxed_value() const; 80.163 @@ -1020,6 +1056,7 @@ 80.164 virtual const TypePtr *add_offset( intptr_t offset ) const; 80.165 // Return same type without a speculative part 80.166 virtual const Type* remove_speculative() const; 80.167 + virtual const TypeOopPtr* with_inline_depth(int depth) const; 80.168 80.169 // the core of the computation of the meet of 2 types 80.170 virtual const Type *xmeet_helper(const Type *t) const; 80.171 @@ -1041,8 +1078,8 @@ 80.172 // Class of Java array pointers 80.173 class TypeAryPtr : public TypeOopPtr { 80.174 TypeAryPtr( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, 80.175 - int offset, int instance_id, bool is_autobox_cache, const TypeOopPtr* speculative) 80.176 - : TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id, speculative), 80.177 + int offset, int instance_id, bool is_autobox_cache, const TypeOopPtr* speculative, int inline_depth) 80.178 + : TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id, speculative, inline_depth), 80.179 _ary(ary), 80.180 _is_autobox_cache(is_autobox_cache) 80.181 { 80.182 @@ -1080,9 +1117,9 @@ 80.183 80.184 bool is_autobox_cache() const { return _is_autobox_cache; } 80.185 80.186 - static const TypeAryPtr *make( PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL); 80.187 + static const TypeAryPtr *make( PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom); 80.188 // Constant pointer to array 80.189 - static const TypeAryPtr *make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, bool is_autobox_cache = false); 80.190 + static const TypeAryPtr *make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom, bool is_autobox_cache= false); 80.191 80.192 // Return a 'ptr' version of this type 80.193 virtual const Type *cast_to_ptr_type(PTR ptr) const; 80.194 @@ -1098,6 +1135,7 @@ 80.195 virtual const TypePtr *add_offset( intptr_t offset ) const; 80.196 // Return same type without a speculative part 80.197 virtual const Type* remove_speculative() const; 80.198 + virtual const TypeOopPtr* with_inline_depth(int depth) const; 80.199 80.200 // the core of the computation of the meet of 2 types 80.201 virtual const Type *xmeet_helper(const Type *t) const;
81.1 --- a/src/share/vm/runtime/deoptimization.cpp Thu Mar 20 10:34:48 2014 -0700 81.2 +++ b/src/share/vm/runtime/deoptimization.cpp Thu Mar 27 14:50:50 2014 -0700 81.3 @@ -1486,6 +1486,7 @@ 81.4 bool maybe_prior_trap = false; 81.5 bool maybe_prior_recompile = false; 81.6 pdata = query_update_method_data(trap_mdo, trap_bci, reason, 81.7 + nm->method(), 81.8 //outputs: 81.9 this_trap_count, 81.10 maybe_prior_trap, 81.11 @@ -1531,7 +1532,7 @@ 81.12 } 81.13 81.14 // Go back to the compiler if there are too many traps in this method. 81.15 - if (this_trap_count >= (uint)PerMethodTrapLimit) { 81.16 + if (this_trap_count >= per_method_trap_limit(reason)) { 81.17 // If there are too many traps in this method, force a recompile. 81.18 // This will allow the compiler to see the limit overflow, and 81.19 // take corrective action, if possible. 81.20 @@ -1619,6 +1620,7 @@ 81.21 Deoptimization::query_update_method_data(MethodData* trap_mdo, 81.22 int trap_bci, 81.23 Deoptimization::DeoptReason reason, 81.24 + Method* compiled_method, 81.25 //outputs: 81.26 uint& ret_this_trap_count, 81.27 bool& ret_maybe_prior_trap, 81.28 @@ -1642,9 +1644,16 @@ 81.29 // Find the profile data for this BCI. If there isn't one, 81.30 // try to allocate one from the MDO's set of spares. 81.31 // This will let us detect a repeated trap at this point. 81.32 - pdata = trap_mdo->allocate_bci_to_data(trap_bci); 81.33 + pdata = trap_mdo->allocate_bci_to_data(trap_bci, reason_is_speculate(reason) ? compiled_method : NULL); 81.34 81.35 if (pdata != NULL) { 81.36 + if (reason_is_speculate(reason) && !pdata->is_SpeculativeTrapData()) { 81.37 + if (LogCompilation && xtty != NULL) { 81.38 + ttyLocker ttyl; 81.39 + // no more room for speculative traps in this MDO 81.40 + xtty->elem("speculative_traps_oom"); 81.41 + } 81.42 + } 81.43 // Query the trap state of this profile datum. 81.44 int tstate0 = pdata->trap_state(); 81.45 if (!trap_state_has_reason(tstate0, per_bc_reason)) 81.46 @@ -1682,8 +1691,10 @@ 81.47 uint ignore_this_trap_count; 81.48 bool ignore_maybe_prior_trap; 81.49 bool ignore_maybe_prior_recompile; 81.50 + assert(!reason_is_speculate(reason), "reason speculate only used by compiler"); 81.51 query_update_method_data(trap_mdo, trap_bci, 81.52 (DeoptReason)reason, 81.53 + NULL, 81.54 ignore_this_trap_count, 81.55 ignore_maybe_prior_trap, 81.56 ignore_maybe_prior_recompile); 81.57 @@ -1811,7 +1822,8 @@ 81.58 "div0_check", 81.59 "age", 81.60 "predicate", 81.61 - "loop_limit_check" 81.62 + "loop_limit_check", 81.63 + "speculate_class_check" 81.64 }; 81.65 const char* Deoptimization::_trap_action_name[Action_LIMIT] = { 81.66 // Note: Keep this in sync. with enum DeoptAction.
82.1 --- a/src/share/vm/runtime/deoptimization.hpp Thu Mar 20 10:34:48 2014 -0700 82.2 +++ b/src/share/vm/runtime/deoptimization.hpp Thu Mar 27 14:50:50 2014 -0700 82.3 @@ -59,6 +59,7 @@ 82.4 Reason_age, // nmethod too old; tier threshold reached 82.5 Reason_predicate, // compiler generated predicate failed 82.6 Reason_loop_limit_check, // compiler generated loop limits check failed 82.7 + Reason_speculate_class_check, // saw unexpected object class from type speculation 82.8 Reason_LIMIT, 82.9 // Note: Keep this enum in sync. with _trap_reason_name. 82.10 Reason_RECORDED_LIMIT = Reason_bimorphic // some are not recorded per bc 82.11 @@ -311,10 +312,23 @@ 82.12 return reason; 82.13 else if (reason == Reason_div0_check) // null check due to divide-by-zero? 82.14 return Reason_null_check; // recorded per BCI as a null check 82.15 + else if (reason == Reason_speculate_class_check) 82.16 + return Reason_class_check; 82.17 else 82.18 return Reason_none; 82.19 } 82.20 82.21 + static bool reason_is_speculate(int reason) { 82.22 + if (reason == Reason_speculate_class_check) { 82.23 + return true; 82.24 + } 82.25 + return false; 82.26 + } 82.27 + 82.28 + static uint per_method_trap_limit(int reason) { 82.29 + return reason_is_speculate(reason) ? (uint)PerMethodSpecTrapLimit : (uint)PerMethodTrapLimit; 82.30 + } 82.31 + 82.32 static const char* trap_reason_name(int reason); 82.33 static const char* trap_action_name(int action); 82.34 // Format like reason='foo' action='bar' index='123'. 82.35 @@ -337,6 +351,7 @@ 82.36 static ProfileData* query_update_method_data(MethodData* trap_mdo, 82.37 int trap_bci, 82.38 DeoptReason reason, 82.39 + Method* compiled_method, 82.40 //outputs: 82.41 uint& ret_this_trap_count, 82.42 bool& ret_maybe_prior_trap,
83.1 --- a/src/share/vm/runtime/globals.hpp Thu Mar 20 10:34:48 2014 -0700 83.2 +++ b/src/share/vm/runtime/globals.hpp Thu Mar 27 14:50:50 2014 -0700 83.3 @@ -3055,9 +3055,15 @@ 83.4 product(intx, PerMethodTrapLimit, 100, \ 83.5 "Limit on traps (of one kind) in a method (includes inlines)") \ 83.6 \ 83.7 + experimental(intx, PerMethodSpecTrapLimit, 5000, \ 83.8 + "Limit on speculative traps (of one kind) in a method (includes inlines)") \ 83.9 + \ 83.10 product(intx, PerBytecodeTrapLimit, 4, \ 83.11 "Limit on traps (of one kind) at a particular BCI") \ 83.12 \ 83.13 + experimental(intx, SpecTrapLimitExtraEntries, 3, \ 83.14 + "Extra method data trap entries for speculation") \ 83.15 + \ 83.16 develop(intx, InlineFrequencyRatio, 20, \ 83.17 "Ratio of call site execution to caller method invocation") \ 83.18 \
84.1 --- a/src/share/vm/runtime/vmStructs.cpp Thu Mar 20 10:34:48 2014 -0700 84.2 +++ b/src/share/vm/runtime/vmStructs.cpp Thu Mar 27 14:50:50 2014 -0700 84.3 @@ -1938,15 +1938,6 @@ 84.4 declare_c2_type(CmpF3Node, CmpFNode) \ 84.5 declare_c2_type(CmpDNode, CmpNode) \ 84.6 declare_c2_type(CmpD3Node, CmpDNode) \ 84.7 - declare_c2_type(MathExactNode, MultiNode) \ 84.8 - declare_c2_type(MathExactINode, MathExactNode) \ 84.9 - declare_c2_type(AddExactINode, MathExactINode) \ 84.10 - declare_c2_type(AddExactLNode, MathExactLNode) \ 84.11 - declare_c2_type(SubExactINode, MathExactINode) \ 84.12 - declare_c2_type(SubExactLNode, MathExactLNode) \ 84.13 - declare_c2_type(NegExactINode, MathExactINode) \ 84.14 - declare_c2_type(MulExactINode, MathExactINode) \ 84.15 - declare_c2_type(FlagsProjNode, ProjNode) \ 84.16 declare_c2_type(BoolNode, Node) \ 84.17 declare_c2_type(AbsNode, Node) \ 84.18 declare_c2_type(AbsINode, AbsNode) \ 84.19 @@ -2027,6 +2018,15 @@ 84.20 declare_c2_type(ExtractLNode, ExtractNode) \ 84.21 declare_c2_type(ExtractFNode, ExtractNode) \ 84.22 declare_c2_type(ExtractDNode, ExtractNode) \ 84.23 + declare_c2_type(OverflowNode, CmpNode) \ 84.24 + declare_c2_type(OverflowINode, OverflowNode) \ 84.25 + declare_c2_type(OverflowAddINode, OverflowINode) \ 84.26 + declare_c2_type(OverflowSubINode, OverflowINode) \ 84.27 + declare_c2_type(OverflowMulINode, OverflowINode) \ 84.28 + declare_c2_type(OverflowLNode, OverflowNode) \ 84.29 + declare_c2_type(OverflowAddLNode, OverflowLNode) \ 84.30 + declare_c2_type(OverflowSubLNode, OverflowLNode) \ 84.31 + declare_c2_type(OverflowMulLNode, OverflowLNode) \ 84.32 \ 84.33 /*********************/ \ 84.34 /* Adapter Blob Entries */ \
85.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 85.2 +++ b/test/compiler/codegen/BMI1.java Thu Mar 27 14:50:50 2014 -0700 85.3 @@ -0,0 +1,301 @@ 85.4 +/* 85.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 85.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 85.7 + * 85.8 + * This code is free software; you can redistribute it and/or modify it 85.9 + * under the terms of the GNU General Public License version 2 only, as 85.10 + * published by the Free Software Foundation. 85.11 + * 85.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 85.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 85.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 85.15 + * version 2 for more details (a copy is included in the LICENSE file that 85.16 + * accompanied this code). 85.17 + * 85.18 + * You should have received a copy of the GNU General Public License version 85.19 + * 2 along with this work; if not, write to the Free Software Foundation, 85.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 85.21 + * 85.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 85.23 + * or visit www.oracle.com if you need additional information or have any 85.24 + * questions. 85.25 + */ 85.26 + 85.27 +/* 85.28 + * @test 85.29 + * @bug 8031321 85.30 + * @summary Support BMI1 instructions on x86/x64 85.31 + * @run main/othervm -Xbatch -XX:-TieredCompilation -XX:CompileCommand=compileonly,BMITests.* BMI1 85.32 + * 85.33 + */ 85.34 + 85.35 +class MemI { 85.36 + public int x; 85.37 + public MemI(int x) { this.x = x; } 85.38 +} 85.39 + 85.40 +class MemL { 85.41 + public long x; 85.42 + public MemL(long x) { this.x = x; } 85.43 +} 85.44 + 85.45 +class BMITests { 85.46 + static int andnl(int src1, int src2) { 85.47 + return ~src1 & src2; 85.48 + } 85.49 + static long andnq(long src1, long src2) { 85.50 + return ~src1 & src2; 85.51 + } 85.52 + static int andnl(int src1, MemI src2) { 85.53 + return ~src1 & src2.x; 85.54 + } 85.55 + static long andnq(long src1, MemL src2) { 85.56 + return ~src1 & src2.x; 85.57 + } 85.58 + static int blsil(int src1) { 85.59 + return src1 & -src1; 85.60 + } 85.61 + static long blsiq(long src1) { 85.62 + return src1 & -src1; 85.63 + } 85.64 + static int blsil(MemI src1) { 85.65 + return src1.x & -src1.x; 85.66 + } 85.67 + static long blsiq(MemL src1) { 85.68 + return src1.x & -src1.x; 85.69 + } 85.70 + static int blsmskl(int src1) { 85.71 + return (src1 - 1) ^ src1; 85.72 + } 85.73 + static long blsmskq(long src1) { 85.74 + return (src1 - 1) ^ src1; 85.75 + } 85.76 + static int blsmskl(MemI src1) { 85.77 + return (src1.x - 1) ^ src1.x; 85.78 + } 85.79 + static long blsmskq(MemL src1) { 85.80 + return (src1.x - 1) ^ src1.x; 85.81 + } 85.82 + static int blsrl(int src1) { 85.83 + return (src1 - 1) & src1; 85.84 + } 85.85 + static long blsrq(long src1) { 85.86 + return (src1 - 1) & src1; 85.87 + } 85.88 + static int blsrl(MemI src1) { 85.89 + return (src1.x - 1) & src1.x; 85.90 + } 85.91 + static long blsrq(MemL src1) { 85.92 + return (src1.x - 1) & src1.x; 85.93 + } 85.94 + static int lzcntl(int src1) { 85.95 + return Integer.numberOfLeadingZeros(src1); 85.96 + } 85.97 + static int lzcntq(long src1) { 85.98 + return Long.numberOfLeadingZeros(src1); 85.99 + } 85.100 + static int tzcntl(int src1) { 85.101 + return Integer.numberOfTrailingZeros(src1); 85.102 + } 85.103 + static int tzcntq(long src1) { 85.104 + return Long.numberOfTrailingZeros(src1); 85.105 + } 85.106 +} 85.107 + 85.108 +public class BMI1 { 85.109 + private final static int ITERATIONS = 1000000; 85.110 + 85.111 + public static void main(String[] args) { 85.112 + int ix = 0x01234567; 85.113 + int iy = 0x89abcdef; 85.114 + MemI imy = new MemI(iy); 85.115 + long lx = 0x0123456701234567L; 85.116 + long ly = 0x89abcdef89abcdefL; 85.117 + MemL lmy = new MemL(ly); 85.118 + 85.119 + { // match(Set dst (AndI (XorI src1 minus_1) src2)) 85.120 + int z = BMITests.andnl(ix, iy); 85.121 + for (int i = 0; i < ITERATIONS; i++) { 85.122 + int ii = BMITests.andnl(ix, iy); 85.123 + if (ii != z) { 85.124 + throw new Error("andnl with register failed"); 85.125 + } 85.126 + } 85.127 + } 85.128 + { // match(Set dst (AndL (XorL src1 minus_1) src2)) 85.129 + long z = BMITests.andnq(lx, ly); 85.130 + for (int i = 0; i < ITERATIONS; i++) { 85.131 + long ll = BMITests.andnq(lx, ly); 85.132 + if (ll != z) { 85.133 + throw new Error("andnq with register failed"); 85.134 + } 85.135 + } 85.136 + } 85.137 + { // match(Set dst (AndI (XorI src1 minus_1) (LoadI src2))) 85.138 + int z = BMITests.andnl(ix, imy); 85.139 + for (int i = 0; i < ITERATIONS; i++) { 85.140 + int ii = BMITests.andnl(ix, imy); 85.141 + if (ii != z) { 85.142 + throw new Error("andnl with memory failed"); 85.143 + } 85.144 + } 85.145 + } 85.146 + { // match(Set dst (AndL (XorL src1 minus_1) (LoadL src2))) 85.147 + long z = BMITests.andnq(lx, lmy); 85.148 + for (int i = 0; i < ITERATIONS; i++) { 85.149 + long ll = BMITests.andnq(lx, lmy); 85.150 + if (ll != z) { 85.151 + throw new Error("andnq with memory failed"); 85.152 + } 85.153 + } 85.154 + } 85.155 + { // match(Set dst (AndI (SubI imm_zero src) src)) 85.156 + int z = BMITests.blsil(ix); 85.157 + for (int i = 0; i < ITERATIONS; i++) { 85.158 + int ii = BMITests.blsil(ix); 85.159 + if (ii != z) { 85.160 + throw new Error("blsil with register failed"); 85.161 + } 85.162 + } 85.163 + } 85.164 + { // match(Set dst (AndL (SubL imm_zero src) src)) 85.165 + long z = BMITests.blsiq(lx); 85.166 + for (int i = 0; i < ITERATIONS; i++) { 85.167 + long ll = BMITests.blsiq(lx); 85.168 + if (ll != z) { 85.169 + throw new Error("blsiq with register failed"); 85.170 + } 85.171 + } 85.172 + } 85.173 + { // match(Set dst (AndI (SubI imm_zero (LoadI src) ) (LoadI src) )) 85.174 + int z = BMITests.blsil(imy); 85.175 + for (int i = 0; i < ITERATIONS; i++) { 85.176 + int ii = BMITests.blsil(imy); 85.177 + if (ii != z) { 85.178 + throw new Error("blsil with memory failed"); 85.179 + } 85.180 + } 85.181 + } 85.182 + { // match(Set dst (AndL (SubL imm_zero (LoadL src) ) (LoadL src) )) 85.183 + long z = BMITests.blsiq(lmy); 85.184 + for (int i = 0; i < ITERATIONS; i++) { 85.185 + long ll = BMITests.blsiq(lmy); 85.186 + if (ll != z) { 85.187 + throw new Error("blsiq with memory failed"); 85.188 + } 85.189 + } 85.190 + } 85.191 + 85.192 + { // match(Set dst (XorI (AddI src minus_1) src)) 85.193 + int z = BMITests.blsmskl(ix); 85.194 + for (int i = 0; i < ITERATIONS; i++) { 85.195 + int ii = BMITests.blsmskl(ix); 85.196 + if (ii != z) { 85.197 + throw new Error("blsmskl with register failed"); 85.198 + } 85.199 + } 85.200 + } 85.201 + { // match(Set dst (XorL (AddL src minus_1) src)) 85.202 + long z = BMITests.blsmskq(lx); 85.203 + for (int i = 0; i < ITERATIONS; i++) { 85.204 + long ll = BMITests.blsmskq(lx); 85.205 + if (ll != z) { 85.206 + throw new Error("blsmskq with register failed"); 85.207 + } 85.208 + } 85.209 + } 85.210 + { // match(Set dst (XorI (AddI (LoadI src) minus_1) (LoadI src) ) ) 85.211 + int z = BMITests.blsmskl(imy); 85.212 + for (int i = 0; i < ITERATIONS; i++) { 85.213 + int ii = BMITests.blsmskl(imy); 85.214 + if (ii != z) { 85.215 + throw new Error("blsmskl with memory failed"); 85.216 + } 85.217 + } 85.218 + } 85.219 + { // match(Set dst (XorL (AddL (LoadL src) minus_1) (LoadL src) ) ) 85.220 + long z = BMITests.blsmskq(lmy); 85.221 + for (int i = 0; i < ITERATIONS; i++) { 85.222 + long ll = BMITests.blsmskq(lmy); 85.223 + if (ll != z) { 85.224 + throw new Error("blsmskq with memory failed"); 85.225 + } 85.226 + } 85.227 + } 85.228 + 85.229 + { // match(Set dst (AndI (AddI src minus_1) src) ) 85.230 + int z = BMITests.blsrl(ix); 85.231 + for (int i = 0; i < ITERATIONS; i++) { 85.232 + int ii = BMITests.blsrl(ix); 85.233 + if (ii != z) { 85.234 + throw new Error("blsrl with register failed"); 85.235 + } 85.236 + } 85.237 + } 85.238 + { // match(Set dst (AndL (AddL src minus_1) src) ) 85.239 + long z = BMITests.blsrq(lx); 85.240 + for (int i = 0; i < ITERATIONS; i++) { 85.241 + long ll = BMITests.blsrq(lx); 85.242 + if (ll != z) { 85.243 + throw new Error("blsrq with register failed"); 85.244 + } 85.245 + } 85.246 + } 85.247 + { // match(Set dst (AndI (AddI (LoadI src) minus_1) (LoadI src) ) ) 85.248 + int z = BMITests.blsrl(imy); 85.249 + for (int i = 0; i < ITERATIONS; i++) { 85.250 + int ii = BMITests.blsrl(imy); 85.251 + if (ii != z) { 85.252 + throw new Error("blsrl with memory failed"); 85.253 + } 85.254 + } 85.255 + } 85.256 + { // match(Set dst (AndL (AddL (LoadL src) minus_1) (LoadL src)) ) 85.257 + long z = BMITests.blsrq(lmy); 85.258 + for (int i = 0; i < ITERATIONS; i++) { 85.259 + long ll = BMITests.blsrq(lmy); 85.260 + if (ll != z) { 85.261 + throw new Error("blsrq with memory failed"); 85.262 + } 85.263 + } 85.264 + } 85.265 + 85.266 + { 85.267 + int z = BMITests.lzcntl(ix); 85.268 + for (int i = 0; i < ITERATIONS; i++) { 85.269 + int ii = BMITests.lzcntl(ix); 85.270 + if (ii != z) { 85.271 + throw new Error("lzcntl failed"); 85.272 + } 85.273 + } 85.274 + } 85.275 + { 85.276 + int z = BMITests.lzcntq(lx); 85.277 + for (int i = 0; i < ITERATIONS; i++) { 85.278 + int ii = BMITests.lzcntq(lx); 85.279 + if (ii != z) { 85.280 + throw new Error("lzcntq failed"); 85.281 + } 85.282 + } 85.283 + } 85.284 + 85.285 + { 85.286 + int z = BMITests.tzcntl(ix); 85.287 + for (int i = 0; i < ITERATIONS; i++) { 85.288 + int ii = BMITests.tzcntl(ix); 85.289 + if (ii != z) { 85.290 + throw new Error("tzcntl failed"); 85.291 + } 85.292 + } 85.293 + } 85.294 + { 85.295 + int z = BMITests.tzcntq(lx); 85.296 + for (int i = 0; i < ITERATIONS; i++) { 85.297 + int ii = BMITests.tzcntq(lx); 85.298 + if (ii != z) { 85.299 + throw new Error("tzcntq failed"); 85.300 + } 85.301 + } 85.302 + } 85.303 + } 85.304 +}
86.1 --- a/test/compiler/intrinsics/mathexact/AddExactICondTest.java Thu Mar 20 10:34:48 2014 -0700 86.2 +++ b/test/compiler/intrinsics/mathexact/AddExactICondTest.java Thu Mar 27 14:50:50 2014 -0700 86.3 @@ -26,7 +26,7 @@ 86.4 * @bug 8024924 86.5 * @summary Test non constant addExact 86.6 * @compile AddExactICondTest.java 86.7 - * @run main AddExactICondTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 86.8 + * @run main AddExactICondTest 86.9 * 86.10 */ 86.11
87.1 --- a/test/compiler/intrinsics/mathexact/AddExactIConstantTest.java Thu Mar 20 10:34:48 2014 -0700 87.2 +++ b/test/compiler/intrinsics/mathexact/AddExactIConstantTest.java Thu Mar 27 14:50:50 2014 -0700 87.3 @@ -26,7 +26,7 @@ 87.4 * @bug 8024924 87.5 * @summary Test constant addExact 87.6 * @compile AddExactIConstantTest.java Verify.java 87.7 - * @run main AddExactIConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 87.8 + * @run main AddExactIConstantTest 87.9 * 87.10 */ 87.11
88.1 --- a/test/compiler/intrinsics/mathexact/AddExactILoadTest.java Thu Mar 20 10:34:48 2014 -0700 88.2 +++ b/test/compiler/intrinsics/mathexact/AddExactILoadTest.java Thu Mar 27 14:50:50 2014 -0700 88.3 @@ -26,7 +26,7 @@ 88.4 * @bug 8024924 88.5 * @summary Test non constant addExact 88.6 * @compile AddExactILoadTest.java Verify.java 88.7 - * @run main AddExactILoadTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 88.8 + * @run main AddExactILoadTest 88.9 * 88.10 */ 88.11
89.1 --- a/test/compiler/intrinsics/mathexact/AddExactILoopDependentTest.java Thu Mar 20 10:34:48 2014 -0700 89.2 +++ b/test/compiler/intrinsics/mathexact/AddExactILoopDependentTest.java Thu Mar 27 14:50:50 2014 -0700 89.3 @@ -26,7 +26,7 @@ 89.4 * @bug 8024924 89.5 * @summary Test non constant addExact 89.6 * @compile AddExactILoopDependentTest.java Verify.java 89.7 - * @run main AddExactILoopDependentTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 89.8 + * @run main AddExactILoopDependentTest 89.9 * 89.10 */ 89.11
90.1 --- a/test/compiler/intrinsics/mathexact/AddExactINonConstantTest.java Thu Mar 20 10:34:48 2014 -0700 90.2 +++ b/test/compiler/intrinsics/mathexact/AddExactINonConstantTest.java Thu Mar 27 14:50:50 2014 -0700 90.3 @@ -26,7 +26,7 @@ 90.4 * @bug 8024924 90.5 * @summary Test non constant addExact 90.6 * @compile AddExactINonConstantTest.java Verify.java 90.7 - * @run main AddExactINonConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 90.8 + * @run main AddExactINonConstantTest 90.9 * 90.10 */ 90.11
91.1 --- a/test/compiler/intrinsics/mathexact/AddExactIRepeatTest.java Thu Mar 20 10:34:48 2014 -0700 91.2 +++ b/test/compiler/intrinsics/mathexact/AddExactIRepeatTest.java Thu Mar 27 14:50:50 2014 -0700 91.3 @@ -26,7 +26,7 @@ 91.4 * @bug 8025657 91.5 * @summary Test repeating addExact 91.6 * @compile AddExactIRepeatTest.java Verify.java 91.7 - * @run main AddExactIRepeatTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 91.8 + * @run main AddExactIRepeatTest 91.9 * 91.10 */ 91.11
92.1 --- a/test/compiler/intrinsics/mathexact/AddExactLConstantTest.java Thu Mar 20 10:34:48 2014 -0700 92.2 +++ b/test/compiler/intrinsics/mathexact/AddExactLConstantTest.java Thu Mar 27 14:50:50 2014 -0700 92.3 @@ -26,7 +26,7 @@ 92.4 * @bug 8026844 92.5 * @summary Test constant addExact 92.6 * @compile AddExactLConstantTest.java Verify.java 92.7 - * @run main AddExactLConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 92.8 + * @run main AddExactLConstantTest 92.9 * 92.10 */ 92.11
93.1 --- a/test/compiler/intrinsics/mathexact/AddExactLNonConstantTest.java Thu Mar 20 10:34:48 2014 -0700 93.2 +++ b/test/compiler/intrinsics/mathexact/AddExactLNonConstantTest.java Thu Mar 27 14:50:50 2014 -0700 93.3 @@ -26,7 +26,7 @@ 93.4 * @bug 8026844 93.5 * @summary Test non constant addExact 93.6 * @compile AddExactLNonConstantTest.java Verify.java 93.7 - * @run main AddExactLNonConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 93.8 + * @run main AddExactLNonConstantTest 93.9 * 93.10 */ 93.11
94.1 --- a/test/compiler/intrinsics/mathexact/CompareTest.java Thu Mar 20 10:34:48 2014 -0700 94.2 +++ b/test/compiler/intrinsics/mathexact/CompareTest.java Thu Mar 27 14:50:50 2014 -0700 94.3 @@ -26,7 +26,7 @@ 94.4 * @bug 8026722 94.5 * @summary Verify that the compare after addExact is a signed compare 94.6 * @compile CompareTest.java 94.7 - * @run main CompareTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 94.8 + * @run main CompareTest 94.9 * 94.10 */ 94.11
95.1 --- a/test/compiler/intrinsics/mathexact/DecExactITest.java Thu Mar 20 10:34:48 2014 -0700 95.2 +++ b/test/compiler/intrinsics/mathexact/DecExactITest.java Thu Mar 27 14:50:50 2014 -0700 95.3 @@ -26,7 +26,7 @@ 95.4 * @bug 8026844 95.5 * @summary Test decrementExact 95.6 * @compile DecExactITest.java Verify.java 95.7 - * @run main DecExactITest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 95.8 + * @run main DecExactITest 95.9 * 95.10 */ 95.11
96.1 --- a/test/compiler/intrinsics/mathexact/DecExactLTest.java Thu Mar 20 10:34:48 2014 -0700 96.2 +++ b/test/compiler/intrinsics/mathexact/DecExactLTest.java Thu Mar 27 14:50:50 2014 -0700 96.3 @@ -26,7 +26,7 @@ 96.4 * @bug 8026844 96.5 * @summary Test decrementExact 96.6 * @compile DecExactLTest.java Verify.java 96.7 - * @run main DecExactLTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 96.8 + * @run main DecExactLTest 96.9 * 96.10 */ 96.11
97.1 --- a/test/compiler/intrinsics/mathexact/GVNTest.java Thu Mar 20 10:34:48 2014 -0700 97.2 +++ b/test/compiler/intrinsics/mathexact/GVNTest.java Thu Mar 27 14:50:50 2014 -0700 97.3 @@ -26,7 +26,7 @@ 97.4 * @bug 8028207 97.5 * @summary Verify that GVN doesn't mess up the two addExacts 97.6 * @compile GVNTest.java 97.7 - * @run main GVNTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 97.8 + * @run main GVNTest 97.9 * 97.10 */ 97.11
98.1 --- a/test/compiler/intrinsics/mathexact/IncExactITest.java Thu Mar 20 10:34:48 2014 -0700 98.2 +++ b/test/compiler/intrinsics/mathexact/IncExactITest.java Thu Mar 27 14:50:50 2014 -0700 98.3 @@ -26,7 +26,7 @@ 98.4 * @bug 8026844 98.5 * @summary Test incrementExact 98.6 * @compile IncExactITest.java Verify.java 98.7 - * @run main IncExactITest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 98.8 + * @run main IncExactITest 98.9 * 98.10 */ 98.11
99.1 --- a/test/compiler/intrinsics/mathexact/IncExactLTest.java Thu Mar 20 10:34:48 2014 -0700 99.2 +++ b/test/compiler/intrinsics/mathexact/IncExactLTest.java Thu Mar 27 14:50:50 2014 -0700 99.3 @@ -26,7 +26,7 @@ 99.4 * @bug 8026844 99.5 * @summary Test incrementExact 99.6 * @compile IncExactLTest.java Verify.java 99.7 - * @run main IncExactLTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 99.8 + * @run main IncExactLTest 99.9 * 99.10 */ 99.11
100.1 --- a/test/compiler/intrinsics/mathexact/MulExactICondTest.java Thu Mar 20 10:34:48 2014 -0700 100.2 +++ b/test/compiler/intrinsics/mathexact/MulExactICondTest.java Thu Mar 27 14:50:50 2014 -0700 100.3 @@ -26,7 +26,7 @@ 100.4 * @bug 8026844 100.5 * @summary Test multiplyExact as condition 100.6 * @compile MulExactICondTest.java 100.7 - * @run main MulExactICondTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 100.8 + * @run main MulExactICondTest 100.9 * 100.10 */ 100.11
101.1 --- a/test/compiler/intrinsics/mathexact/MulExactIConstantTest.java Thu Mar 20 10:34:48 2014 -0700 101.2 +++ b/test/compiler/intrinsics/mathexact/MulExactIConstantTest.java Thu Mar 27 14:50:50 2014 -0700 101.3 @@ -26,7 +26,7 @@ 101.4 * @bug 8026844 101.5 * @summary Test constant multiplyExact 101.6 * @compile MulExactIConstantTest.java Verify.java 101.7 - * @run main MulExactIConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 101.8 + * @run main MulExactIConstantTest 101.9 * 101.10 */ 101.11
102.1 --- a/test/compiler/intrinsics/mathexact/MulExactILoadTest.java Thu Mar 20 10:34:48 2014 -0700 102.2 +++ b/test/compiler/intrinsics/mathexact/MulExactILoadTest.java Thu Mar 27 14:50:50 2014 -0700 102.3 @@ -26,7 +26,7 @@ 102.4 * @bug 8026844 102.5 * @summary Test multiplyExact 102.6 * @compile MulExactILoadTest.java Verify.java 102.7 - * @run main MulExactILoadTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 102.8 + * @run main MulExactILoadTest 102.9 * 102.10 */ 102.11
103.1 --- a/test/compiler/intrinsics/mathexact/MulExactILoopDependentTest.java Thu Mar 20 10:34:48 2014 -0700 103.2 +++ b/test/compiler/intrinsics/mathexact/MulExactILoopDependentTest.java Thu Mar 27 14:50:50 2014 -0700 103.3 @@ -26,7 +26,7 @@ 103.4 * @bug 8026844 103.5 * @summary Test loop dependent multiplyExact 103.6 * @compile MulExactILoopDependentTest.java Verify.java 103.7 - * @run main MulExactILoopDependentTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 103.8 + * @run main MulExactILoopDependentTest 103.9 * 103.10 */ 103.11 public class MulExactILoopDependentTest {
104.1 --- a/test/compiler/intrinsics/mathexact/MulExactINonConstantTest.java Thu Mar 20 10:34:48 2014 -0700 104.2 +++ b/test/compiler/intrinsics/mathexact/MulExactINonConstantTest.java Thu Mar 27 14:50:50 2014 -0700 104.3 @@ -26,7 +26,7 @@ 104.4 * @bug 8026844 104.5 * @summary Test non constant multiplyExact 104.6 * @compile MulExactINonConstantTest.java Verify.java 104.7 - * @run main MulExactINonConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 104.8 + * @run main MulExactINonConstantTest 104.9 * 104.10 */ 104.11
105.1 --- a/test/compiler/intrinsics/mathexact/MulExactIRepeatTest.java Thu Mar 20 10:34:48 2014 -0700 105.2 +++ b/test/compiler/intrinsics/mathexact/MulExactIRepeatTest.java Thu Mar 27 14:50:50 2014 -0700 105.3 @@ -26,7 +26,7 @@ 105.4 * @bug 8026844 105.5 * @summary Test repeating multiplyExact 105.6 * @compile MulExactIRepeatTest.java Verify.java 105.7 - * @run main MulExactIRepeatTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 105.8 + * @run main MulExactIRepeatTest 105.9 * 105.10 */ 105.11
106.1 --- a/test/compiler/intrinsics/mathexact/MulExactLConstantTest.java Thu Mar 20 10:34:48 2014 -0700 106.2 +++ b/test/compiler/intrinsics/mathexact/MulExactLConstantTest.java Thu Mar 27 14:50:50 2014 -0700 106.3 @@ -26,7 +26,7 @@ 106.4 * @bug 8026844 106.5 * @summary Test constant mulExact 106.6 * @compile MulExactLConstantTest.java Verify.java 106.7 - * @run main MulExactLConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 106.8 + * @run main MulExactLConstantTest 106.9 * 106.10 */ 106.11
107.1 --- a/test/compiler/intrinsics/mathexact/MulExactLNonConstantTest.java Thu Mar 20 10:34:48 2014 -0700 107.2 +++ b/test/compiler/intrinsics/mathexact/MulExactLNonConstantTest.java Thu Mar 27 14:50:50 2014 -0700 107.3 @@ -26,7 +26,7 @@ 107.4 * @bug 8026844 107.5 * @summary Test non constant mulExact 107.6 * @compile MulExactLNonConstantTest.java Verify.java 107.7 - * @run main MulExactLNonConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 107.8 + * @run main MulExactLNonConstantTest 107.9 * 107.10 */ 107.11
108.1 --- a/test/compiler/intrinsics/mathexact/NegExactIConstantTest.java Thu Mar 20 10:34:48 2014 -0700 108.2 +++ b/test/compiler/intrinsics/mathexact/NegExactIConstantTest.java Thu Mar 27 14:50:50 2014 -0700 108.3 @@ -26,7 +26,7 @@ 108.4 * @bug 8026844 108.5 * @summary Test constant negExact 108.6 * @compile NegExactIConstantTest.java Verify.java 108.7 - * @run main NegExactIConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 108.8 + * @run main NegExactIConstantTest 108.9 * 108.10 */ 108.11
109.1 --- a/test/compiler/intrinsics/mathexact/NegExactILoadTest.java Thu Mar 20 10:34:48 2014 -0700 109.2 +++ b/test/compiler/intrinsics/mathexact/NegExactILoadTest.java Thu Mar 27 14:50:50 2014 -0700 109.3 @@ -26,14 +26,14 @@ 109.4 * @bug 8026844 109.5 * @summary Test negExact 109.6 * @compile NegExactILoadTest.java Verify.java 109.7 - * @run main NegExactILoadTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 109.8 + * @run main NegExactILoadTest 109.9 * 109.10 */ 109.11 109.12 public class NegExactILoadTest { 109.13 public static void main(String[] args) { 109.14 - Verify.LoadTest.init(); 109.15 - Verify.LoadTest.verify(new Verify.UnaryToBinary(new Verify.NegExactI())); 109.16 + Verify.LoadTest.init(); 109.17 + Verify.LoadTest.verify(new Verify.UnaryToBinary(new Verify.NegExactI())); 109.18 } 109.19 109.20 }
110.1 --- a/test/compiler/intrinsics/mathexact/NegExactILoopDependentTest.java Thu Mar 20 10:34:48 2014 -0700 110.2 +++ b/test/compiler/intrinsics/mathexact/NegExactILoopDependentTest.java Thu Mar 27 14:50:50 2014 -0700 110.3 @@ -26,7 +26,7 @@ 110.4 * @bug 8026844 110.5 * @summary Test negExact loop dependent 110.6 * @compile NegExactILoopDependentTest.java Verify.java 110.7 - * @run main NegExactILoopDependentTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 110.8 + * @run main NegExactILoopDependentTest 110.9 * 110.10 */ 110.11 public class NegExactILoopDependentTest {
111.1 --- a/test/compiler/intrinsics/mathexact/NegExactINonConstantTest.java Thu Mar 20 10:34:48 2014 -0700 111.2 +++ b/test/compiler/intrinsics/mathexact/NegExactINonConstantTest.java Thu Mar 27 14:50:50 2014 -0700 111.3 @@ -26,7 +26,7 @@ 111.4 * @bug 8026844 111.5 * @summary Test non constant negExact 111.6 * @compile NegExactINonConstantTest.java Verify.java 111.7 - * @run main NegExactINonConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 111.8 + * @run main NegExactINonConstantTest 111.9 * 111.10 */ 111.11
112.1 --- a/test/compiler/intrinsics/mathexact/NegExactLConstantTest.java Thu Mar 20 10:34:48 2014 -0700 112.2 +++ b/test/compiler/intrinsics/mathexact/NegExactLConstantTest.java Thu Mar 27 14:50:50 2014 -0700 112.3 @@ -26,7 +26,7 @@ 112.4 * @bug 8026844 112.5 * @summary Test constant negExact 112.6 * @compile NegExactLConstantTest.java Verify.java 112.7 - * @run main NegExactLConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 112.8 + * @run main NegExactLConstantTest 112.9 * 112.10 */ 112.11
113.1 --- a/test/compiler/intrinsics/mathexact/NegExactLNonConstantTest.java Thu Mar 20 10:34:48 2014 -0700 113.2 +++ b/test/compiler/intrinsics/mathexact/NegExactLNonConstantTest.java Thu Mar 27 14:50:50 2014 -0700 113.3 @@ -26,7 +26,7 @@ 113.4 * @bug 8026844 113.5 * @summary Test constant negExact 113.6 * @compile NegExactLNonConstantTest.java Verify.java 113.7 - * @run main NegExactLNonConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 113.8 + * @run main NegExactLNonConstantTest 113.9 * 113.10 */ 113.11
114.1 --- a/test/compiler/intrinsics/mathexact/NestedMathExactTest.java Thu Mar 20 10:34:48 2014 -0700 114.2 +++ b/test/compiler/intrinsics/mathexact/NestedMathExactTest.java Thu Mar 27 14:50:50 2014 -0700 114.3 @@ -26,7 +26,7 @@ 114.4 * @bug 8027444 114.5 * @summary Test nested loops 114.6 * @compile NestedMathExactTest.java 114.7 - * @run main NestedMathExactTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 114.8 + * @run main NestedMathExactTest 114.9 * 114.10 */ 114.11
115.1 --- a/test/compiler/intrinsics/mathexact/SplitThruPhiTest.java Thu Mar 20 10:34:48 2014 -0700 115.2 +++ b/test/compiler/intrinsics/mathexact/SplitThruPhiTest.java Thu Mar 27 14:50:50 2014 -0700 115.3 @@ -26,7 +26,7 @@ 115.4 * @bug 8028198 115.5 * @summary Verify that split through phi does the right thing 115.6 * @compile SplitThruPhiTest.java 115.7 - * @run main SplitThruPhiTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 115.8 + * @run main SplitThruPhiTest 115.9 * 115.10 */ 115.11
116.1 --- a/test/compiler/intrinsics/mathexact/SubExactICondTest.java Thu Mar 20 10:34:48 2014 -0700 116.2 +++ b/test/compiler/intrinsics/mathexact/SubExactICondTest.java Thu Mar 27 14:50:50 2014 -0700 116.3 @@ -26,7 +26,7 @@ 116.4 * @bug 8026844 116.5 * @summary Test subtractExact as condition 116.6 * @compile SubExactICondTest.java Verify.java 116.7 - * @run main SubExactICondTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 116.8 + * @run main SubExactICondTest 116.9 * 116.10 */ 116.11
117.1 --- a/test/compiler/intrinsics/mathexact/SubExactIConstantTest.java Thu Mar 20 10:34:48 2014 -0700 117.2 +++ b/test/compiler/intrinsics/mathexact/SubExactIConstantTest.java Thu Mar 27 14:50:50 2014 -0700 117.3 @@ -26,7 +26,7 @@ 117.4 * @bug 8026844 117.5 * @summary Test constant subtractExact 117.6 * @compile SubExactIConstantTest.java Verify.java 117.7 - * @run main SubExactIConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 117.8 + * @run main SubExactIConstantTest 117.9 * 117.10 */ 117.11
118.1 --- a/test/compiler/intrinsics/mathexact/SubExactILoadTest.java Thu Mar 20 10:34:48 2014 -0700 118.2 +++ b/test/compiler/intrinsics/mathexact/SubExactILoadTest.java Thu Mar 27 14:50:50 2014 -0700 118.3 @@ -26,7 +26,7 @@ 118.4 * @bug 8026844 118.5 * @summary Test non constant subtractExact 118.6 * @compile SubExactILoadTest.java Verify.java 118.7 - * @run main SubExactILoadTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 118.8 + * @run main SubExactILoadTest 118.9 * 118.10 */ 118.11
119.1 --- a/test/compiler/intrinsics/mathexact/SubExactILoopDependentTest.java Thu Mar 20 10:34:48 2014 -0700 119.2 +++ b/test/compiler/intrinsics/mathexact/SubExactILoopDependentTest.java Thu Mar 27 14:50:50 2014 -0700 119.3 @@ -26,7 +26,7 @@ 119.4 * @bug 8026844 119.5 * @summary Test non constant subtractExact 119.6 * @compile SubExactILoopDependentTest.java Verify.java 119.7 - * @run main SubExactILoopDependentTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 119.8 + * @run main SubExactILoopDependentTest 119.9 * 119.10 */ 119.11
120.1 --- a/test/compiler/intrinsics/mathexact/SubExactINonConstantTest.java Thu Mar 20 10:34:48 2014 -0700 120.2 +++ b/test/compiler/intrinsics/mathexact/SubExactINonConstantTest.java Thu Mar 27 14:50:50 2014 -0700 120.3 @@ -26,7 +26,7 @@ 120.4 * @bug 8026844 120.5 * @summary Test non constant subtractExact 120.6 * @compile SubExactINonConstantTest.java Verify.java 120.7 - * @run main SubExactINonConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 120.8 + * @run main SubExactINonConstantTest 120.9 * 120.10 */ 120.11
121.1 --- a/test/compiler/intrinsics/mathexact/SubExactIRepeatTest.java Thu Mar 20 10:34:48 2014 -0700 121.2 +++ b/test/compiler/intrinsics/mathexact/SubExactIRepeatTest.java Thu Mar 27 14:50:50 2014 -0700 121.3 @@ -26,7 +26,7 @@ 121.4 * @bug 8026844 121.5 * @summary Test repeating subtractExact 121.6 * @compile SubExactIRepeatTest.java Verify.java 121.7 - * @run main SubExactIRepeatTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 121.8 + * @run main SubExactIRepeatTest 121.9 * 121.10 */ 121.11
122.1 --- a/test/compiler/intrinsics/mathexact/SubExactLConstantTest.java Thu Mar 20 10:34:48 2014 -0700 122.2 +++ b/test/compiler/intrinsics/mathexact/SubExactLConstantTest.java Thu Mar 27 14:50:50 2014 -0700 122.3 @@ -27,7 +27,7 @@ 122.4 * @bug 8027353 122.5 * @summary Test constant subtractExact 122.6 * @compile SubExactLConstantTest.java Verify.java 122.7 - * @run main SubExactLConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 122.8 + * @run main SubExactLConstantTest 122.9 * 122.10 */ 122.11
123.1 --- a/test/compiler/intrinsics/mathexact/SubExactLNonConstantTest.java Thu Mar 20 10:34:48 2014 -0700 123.2 +++ b/test/compiler/intrinsics/mathexact/SubExactLNonConstantTest.java Thu Mar 27 14:50:50 2014 -0700 123.3 @@ -27,7 +27,7 @@ 123.4 * @bug 8027353 123.5 * @summary Test non constant subtractExact 123.6 * @compile SubExactLNonConstantTest.java Verify.java 123.7 - * @run main SubExactLNonConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics 123.8 + * @run main SubExactLNonConstantTest 123.9 * 123.10 */ 123.11
124.1 --- a/test/compiler/intrinsics/mathexact/Verify.java Thu Mar 20 10:34:48 2014 -0700 124.2 +++ b/test/compiler/intrinsics/mathexact/Verify.java Thu Mar 27 14:50:50 2014 -0700 124.3 @@ -160,6 +160,7 @@ 124.4 124.5 public static class NonConstantTest { 124.6 public static java.util.Random rnd = new java.util.Random(); 124.7 + public static int[] values = new int[] { Integer.MAX_VALUE, Integer.MIN_VALUE }; 124.8 124.9 public static void verify(BinaryMethod method) { 124.10 for (int i = 0; i < 50000; ++i) { 124.11 @@ -169,6 +170,10 @@ 124.12 Verify.verifyBinary(rnd1 + 1, rnd2, method); 124.13 Verify.verifyBinary(rnd1 - 1, rnd2, method); 124.14 Verify.verifyBinary(rnd1, rnd2 - 1, method); 124.15 + Verify.verifyBinary(0, values[0], method); 124.16 + Verify.verifyBinary(values[0], 0, method); 124.17 + Verify.verifyBinary(0, values[1], method); 124.18 + Verify.verifyBinary(values[1], 0, method); 124.19 } 124.20 } 124.21 }
125.1 --- a/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java Thu Mar 20 10:34:48 2014 -0700 125.2 +++ b/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java Thu Mar 27 14:50:50 2014 -0700 125.3 @@ -26,11 +26,11 @@ 125.4 * @library /testlibrary /testlibrary/whitebox /compiler/whitebox 125.5 * @build AddExactIntTest 125.6 * @run main ClassFileInstaller sun.hotspot.WhiteBox 125.7 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 125.8 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 125.9 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 125.10 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 125.11 * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics AddExactIntTest 125.12 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 125.13 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 125.14 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 125.15 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 125.16 * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics AddExactIntTest
126.1 --- a/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java Thu Mar 20 10:34:48 2014 -0700 126.2 +++ b/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java Thu Mar 27 14:50:50 2014 -0700 126.3 @@ -26,11 +26,11 @@ 126.4 * @library /testlibrary /testlibrary/whitebox /compiler/whitebox 126.5 * @build AddExactLongTest 126.6 * @run main ClassFileInstaller sun.hotspot.WhiteBox 126.7 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 126.8 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 126.9 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 126.10 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 126.11 * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics AddExactLongTest 126.12 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 126.13 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 126.14 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 126.15 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 126.16 * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics AddExactLongTest
127.1 --- a/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java Thu Mar 20 10:34:48 2014 -0700 127.2 +++ b/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java Thu Mar 27 14:50:50 2014 -0700 127.3 @@ -26,11 +26,11 @@ 127.4 * @library /testlibrary /testlibrary/whitebox /compiler/whitebox 127.5 * @build DecrementExactIntTest 127.6 * @run main ClassFileInstaller sun.hotspot.WhiteBox 127.7 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 127.8 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 127.9 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 127.10 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 127.11 * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics DecrementExactIntTest 127.12 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 127.13 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 127.14 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 127.15 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 127.16 * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics DecrementExactIntTest
128.1 --- a/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java Thu Mar 20 10:34:48 2014 -0700 128.2 +++ b/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java Thu Mar 27 14:50:50 2014 -0700 128.3 @@ -26,11 +26,11 @@ 128.4 * @library /testlibrary /testlibrary/whitebox /compiler/whitebox 128.5 * @build DecrementExactLongTest 128.6 * @run main ClassFileInstaller sun.hotspot.WhiteBox 128.7 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 128.8 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 128.9 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 128.10 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 128.11 * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics DecrementExactLongTest 128.12 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 128.13 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 128.14 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 128.15 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 128.16 * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics DecrementExactLongTest 128.17 @@ -42,4 +42,4 @@ 128.18 public static void main(String[] args) throws Exception { 128.19 new IntrinsicBase.LongTest(MathIntrinsic.LongIntrinsic.Decrement).test(); 128.20 } 128.21 -} 128.22 \ No newline at end of file 128.23 +}
129.1 --- a/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java Thu Mar 20 10:34:48 2014 -0700 129.2 +++ b/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java Thu Mar 27 14:50:50 2014 -0700 129.3 @@ -26,11 +26,11 @@ 129.4 * @library /testlibrary /testlibrary/whitebox /compiler/whitebox 129.5 * @build IncrementExactIntTest 129.6 * @run main ClassFileInstaller sun.hotspot.WhiteBox 129.7 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 129.8 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 129.9 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 129.10 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 129.11 * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics IncrementExactIntTest 129.12 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 129.13 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 129.14 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 129.15 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 129.16 * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics IncrementExactIntTest
130.1 --- a/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java Thu Mar 20 10:34:48 2014 -0700 130.2 +++ b/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java Thu Mar 27 14:50:50 2014 -0700 130.3 @@ -26,11 +26,11 @@ 130.4 * @library /testlibrary /testlibrary/whitebox /compiler/whitebox 130.5 * @build IncrementExactLongTest 130.6 * @run main ClassFileInstaller sun.hotspot.WhiteBox 130.7 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 130.8 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 130.9 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 130.10 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 130.11 * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics IncrementExactLongTest 130.12 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 130.13 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 130.14 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 130.15 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 130.16 * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics IncrementExactLongTest
131.1 --- a/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java Thu Mar 20 10:34:48 2014 -0700 131.2 +++ b/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java Thu Mar 27 14:50:50 2014 -0700 131.3 @@ -26,11 +26,11 @@ 131.4 * @library /testlibrary /testlibrary/whitebox /compiler/whitebox 131.5 * @build MultiplyExactIntTest 131.6 * @run main ClassFileInstaller sun.hotspot.WhiteBox 131.7 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 131.8 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 131.9 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 131.10 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 131.11 * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics MultiplyExactIntTest 131.12 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 131.13 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 131.14 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 131.15 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 131.16 * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics MultiplyExactIntTest
132.1 --- a/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java Thu Mar 20 10:34:48 2014 -0700 132.2 +++ b/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java Thu Mar 27 14:50:50 2014 -0700 132.3 @@ -26,11 +26,11 @@ 132.4 * @library /testlibrary /testlibrary/whitebox /compiler/whitebox 132.5 * @build MultiplyExactLongTest 132.6 * @run main ClassFileInstaller sun.hotspot.WhiteBox 132.7 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 132.8 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 132.9 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 132.10 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 132.11 * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics MultiplyExactLongTest 132.12 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 132.13 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 132.14 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 132.15 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 132.16 * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics MultiplyExactLongTest
133.1 --- a/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java Thu Mar 20 10:34:48 2014 -0700 133.2 +++ b/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java Thu Mar 27 14:50:50 2014 -0700 133.3 @@ -26,11 +26,11 @@ 133.4 * @library /testlibrary /testlibrary/whitebox /compiler/whitebox 133.5 * @build NegateExactIntTest 133.6 * @run main ClassFileInstaller sun.hotspot.WhiteBox 133.7 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 133.8 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 133.9 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 133.10 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 133.11 * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics NegateExactIntTest 133.12 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 133.13 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 133.14 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 133.15 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 133.16 * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics NegateExactIntTest
134.1 --- a/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java Thu Mar 20 10:34:48 2014 -0700 134.2 +++ b/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java Thu Mar 27 14:50:50 2014 -0700 134.3 @@ -26,11 +26,11 @@ 134.4 * @library /testlibrary /testlibrary/whitebox /compiler/whitebox 134.5 * @build NegateExactLongTest 134.6 * @run main ClassFileInstaller sun.hotspot.WhiteBox 134.7 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 134.8 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 134.9 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 134.10 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 134.11 * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics NegateExactLongTest 134.12 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 134.13 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 134.14 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 134.15 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 134.16 * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics NegateExactLongTest
135.1 --- a/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java Thu Mar 20 10:34:48 2014 -0700 135.2 +++ b/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java Thu Mar 27 14:50:50 2014 -0700 135.3 @@ -26,11 +26,11 @@ 135.4 * @library /testlibrary /testlibrary/whitebox /compiler/whitebox 135.5 * @build SubtractExactIntTest 135.6 * @run main ClassFileInstaller sun.hotspot.WhiteBox 135.7 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 135.8 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 135.9 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 135.10 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 135.11 * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics SubtractExactIntTest 135.12 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 135.13 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 135.14 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 135.15 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 135.16 * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics SubtractExactIntTest
136.1 --- a/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java Thu Mar 20 10:34:48 2014 -0700 136.2 +++ b/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java Thu Mar 27 14:50:50 2014 -0700 136.3 @@ -26,11 +26,11 @@ 136.4 * @library /testlibrary /testlibrary/whitebox /compiler/whitebox 136.5 * @build SubtractExactLongTest 136.6 * @run main ClassFileInstaller sun.hotspot.WhiteBox 136.7 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 136.8 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 136.9 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 136.10 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 136.11 * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics SubtractExactLongTest 136.12 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions 136.13 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 136.14 * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation 136.15 * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod 136.16 * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics SubtractExactLongTest
137.1 --- a/test/compiler/types/TestMeetTopArrayExactConstantArray.java Thu Mar 20 10:34:48 2014 -0700 137.2 +++ b/test/compiler/types/TestMeetTopArrayExactConstantArray.java Thu Mar 27 14:50:50 2014 -0700 137.3 @@ -25,7 +25,7 @@ 137.4 * @test 137.5 * @bug 8027571 137.6 * @summary meet of TopPTR exact array with constant array is not symmetric 137.7 - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -XX:+UnlockExperimentalVMOptions -XX:+UseTypeSpeculation -XX:-BackgroundCompilation TestMeetTopArrayExactConstantArray 137.8 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -XX:+UseTypeSpeculation -XX:-BackgroundCompilation TestMeetTopArrayExactConstantArray 137.9 * 137.10 */ 137.11
138.1 --- a/test/compiler/types/TestSpeculationFailedHigherEqual.java Thu Mar 20 10:34:48 2014 -0700 138.2 +++ b/test/compiler/types/TestSpeculationFailedHigherEqual.java Thu Mar 27 14:50:50 2014 -0700 138.3 @@ -25,7 +25,7 @@ 138.4 * @test 138.5 * @bug 8027422 138.6 * @summary type methods shouldn't always operate on speculative part 138.7 - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:TypeProfileLevel=222 -XX:+UnlockExperimentalVMOptions -XX:+UseTypeSpeculation -XX:-BackgroundCompilation TestSpeculationFailedHigherEqual 138.8 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:TypeProfileLevel=222 -XX:+UseTypeSpeculation -XX:-BackgroundCompilation TestSpeculationFailedHigherEqual 138.9 * 138.10 */ 138.11
139.1 --- a/test/compiler/types/TypeSpeculation.java Thu Mar 20 10:34:48 2014 -0700 139.2 +++ b/test/compiler/types/TypeSpeculation.java Thu Mar 27 14:50:50 2014 -0700 139.3 @@ -25,7 +25,7 @@ 139.4 * @test 139.5 * @bug 8024070 139.6 * @summary Test that type speculation doesn't cause incorrect execution 139.7 - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:TypeProfileLevel=222 -XX:+UnlockExperimentalVMOptions -XX:+UseTypeSpeculation TypeSpeculation 139.8 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:TypeProfileLevel=222 -XX:+UseTypeSpeculation TypeSpeculation 139.9 * 139.10 */ 139.11
140.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 140.2 +++ b/test/compiler/uncommontrap/TestSpecTrapClassUnloading.java Thu Mar 27 14:50:50 2014 -0700 140.3 @@ -0,0 +1,97 @@ 140.4 +/* 140.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 140.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 140.7 + * 140.8 + * This code is free software; you can redistribute it and/or modify it 140.9 + * under the terms of the GNU General Public License version 2 only, as 140.10 + * published by the Free Software Foundation. 140.11 + * 140.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 140.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 140.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 140.15 + * version 2 for more details (a copy is included in the LICENSE file that 140.16 + * accompanied this code). 140.17 + * 140.18 + * You should have received a copy of the GNU General Public License version 140.19 + * 2 along with this work; if not, write to the Free Software Foundation, 140.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 140.21 + * 140.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 140.23 + * or visit www.oracle.com if you need additional information or have any 140.24 + * questions. 140.25 + */ 140.26 + 140.27 +/* 140.28 + * @test 140.29 + * @bug 8031752 140.30 + * @summary speculative traps need to be cleaned up at GC 140.31 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:+UseTypeSpeculation -XX:TypeProfileLevel=222 -XX:CompileCommand=exclude,java.lang.reflect.Method::invoke -XX:CompileCommand=exclude,sun.reflect.DelegatingMethodAccessorImpl::invoke -Xmx1M TestSpecTrapClassUnloading 140.32 + * 140.33 + */ 140.34 + 140.35 +import java.lang.reflect.Method; 140.36 + 140.37 +public class TestSpecTrapClassUnloading { 140.38 + static class B { 140.39 + final public boolean m(Object o) { 140.40 + if (o.getClass() == B.class) { 140.41 + return true; 140.42 + } 140.43 + return false; 140.44 + } 140.45 + } 140.46 + 140.47 + static class MemoryChunk { 140.48 + MemoryChunk other; 140.49 + long[] array; 140.50 + MemoryChunk(MemoryChunk other) { 140.51 + other = other; 140.52 + array = new long[1024 * 1024 * 1024]; 140.53 + } 140.54 + } 140.55 + 140.56 + static void m1(B b, Object o) { 140.57 + b.m(o); 140.58 + } 140.59 + 140.60 + static void m2(B b, Object o) { 140.61 + b.m(o); 140.62 + } 140.63 + 140.64 + public static void main(String[] args) throws Exception { 140.65 + Method m = B.class.getMethod("m", Object.class); 140.66 + Object o = new Object(); 140.67 + B b = new B(); 140.68 + 140.69 + // add speculative trap in B.m() for m1 140.70 + for (int i = 0; i < 20000; i++) { 140.71 + m1(b, b); 140.72 + } 140.73 + m1(b, o); 140.74 + 140.75 + // add speculative trap in B.m() for code generated by reflection 140.76 + for (int i = 0; i < 20000; i++) { 140.77 + m.invoke(b, b); 140.78 + } 140.79 + m.invoke(b, o); 140.80 + 140.81 + m = null; 140.82 + 140.83 + // add speculative trap in B.m() for m2 140.84 + for (int i = 0; i < 20000; i++) { 140.85 + m2(b, b); 140.86 + } 140.87 + m2(b, o); 140.88 + 140.89 + // Exhaust memory which causes the code generated by 140.90 + // reflection to be unloaded but B.m() is not. 140.91 + MemoryChunk root = null; 140.92 + try { 140.93 + while (true) { 140.94 + root = new MemoryChunk(root); 140.95 + } 140.96 + } catch(OutOfMemoryError e) { 140.97 + root = null; 140.98 + } 140.99 + } 140.100 +}