Thu, 29 Oct 2009 08:49:31 -0700
Merge
1.1 --- a/agent/make/saenv.sh Wed Oct 28 10:37:17 2009 -0700 1.2 +++ b/agent/make/saenv.sh Thu Oct 29 08:49:31 2009 -0700 1.3 @@ -48,8 +48,16 @@ 1.4 CPU=i386 1.5 fi 1.6 else 1.7 - LD_AUDIT_32=$STARTDIR/../src/os/solaris/proc/`uname -p`/libsaproc_audit.so 1.8 - export LD_AUDIT_32 1.9 + # configure audit helper library if SA_ALTROOT is set 1.10 + if [ -n "$SA_ALTROOT" ]; then 1.11 + LD_AUDIT_32=$STARTDIR/../src/os/solaris/proc/`uname -p`/libsaproc_audit.so 1.12 + export LD_AUDIT_32 1.13 + if [ ! -f $LD_AUDIT_32 ]; then 1.14 + echo "SA_ALTROOT is set and can't find libsaproc_audit.so." 1.15 + echo "Make sure to build it with 'make natives'." 1.16 + exit 1 1.17 + fi 1.18 + fi 1.19 SA_LIBPATH=$STARTDIR/../src/os/solaris/proc/`uname -p`:$STARTDIR/solaris/`uname -p` 1.20 OPTIONS="-Dsa.library.path=$SA_LIBPATH -Dsun.jvm.hotspot.debugger.useProcDebugger" 1.21 CPU=sparc
2.1 --- a/agent/make/saenv64.sh Wed Oct 28 10:37:17 2009 -0700 2.2 +++ b/agent/make/saenv64.sh Thu Oct 29 08:49:31 2009 -0700 2.3 @@ -43,8 +43,16 @@ 2.4 fi 2.5 fi 2.6 2.7 -LD_AUDIT_64=$STARTDIR/../src/os/solaris/proc/$CPU/libsaproc_audit.so 2.8 -export LD_AUDIT_64 2.9 +# configure audit helper library if SA_ALTROOT is set 2.10 +if [ -n "$SA_ALTROOT" ]; then 2.11 + LD_AUDIT_64=$STARTDIR/../src/os/solaris/proc/$CPU/libsaproc_audit.so 2.12 + export LD_AUDIT_64 2.13 + if [ ! -f $LD_AUDIT_64 ]; then 2.14 + echo "SA_ALTROOT is set and can't find libsaproc_audit.so." 2.15 + echo "Make sure to build it with 'make natives'." 2.16 + exit 1 2.17 + fi 2.18 +fi 2.19 SA_LIBPATH=$STARTDIR/../src/os/solaris/proc/$CPU:$STARTDIR/solaris/$CPU 2.20 2.21 OPTIONS="-Dsa.library.path=$SA_LIBPATH -Dsun.jvm.hotspot.debugger.useProcDebugger"
3.1 --- a/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java Wed Oct 28 10:37:17 2009 -0700 3.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java Thu Oct 29 08:49:31 2009 -0700 3.3 @@ -926,6 +926,28 @@ 3.4 } 3.5 } 3.6 }, 3.7 + new Command("dumpcodecache", "dumpcodecache", false) { 3.8 + public void doit(Tokens t) { 3.9 + if (t.countTokens() != 0) { 3.10 + usage(); 3.11 + } else { 3.12 + final PrintStream fout = out; 3.13 + final HTMLGenerator gen = new HTMLGenerator(false); 3.14 + CodeCacheVisitor v = new CodeCacheVisitor() { 3.15 + public void prologue(Address start, Address end) { 3.16 + } 3.17 + public void visit(CodeBlob blob) { 3.18 + fout.println(gen.genHTML(blob.instructionsBegin())); 3.19 + } 3.20 + public void epilogue() { 3.21 + } 3.22 + 3.23 + 3.24 + }; 3.25 + VM.getVM().getCodeCache().iterate(v); 3.26 + } 3.27 + } 3.28 + }, 3.29 new Command("where", "where { -a | id }", false) { 3.30 public void doit(Tokens t) { 3.31 if (t.countTokens() != 1) {
4.1 --- a/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java Wed Oct 28 10:37:17 2009 -0700 4.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java Thu Oct 29 08:49:31 2009 -0700 4.3 @@ -173,7 +173,8 @@ 4.4 CodeBlob lastBlob = null; 4.5 while (ptr != null && ptr.lessThan(end)) { 4.6 try { 4.7 - CodeBlob blob = findBlobUnsafe(ptr); 4.8 + // Use findStart to get a pointer inside blob other findBlob asserts 4.9 + CodeBlob blob = findBlobUnsafe(heap.findStart(ptr)); 4.10 if (blob != null) { 4.11 visitor.visit(blob); 4.12 if (blob == lastBlob) {
5.1 --- a/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Wed Oct 28 10:37:17 2009 -0700 5.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Thu Oct 29 08:49:31 2009 -0700 5.3 @@ -42,7 +42,7 @@ 5.4 /** To support simple linked-list chaining of nmethods */ 5.5 private static AddressField osrLinkField; 5.6 private static AddressField scavengeRootLinkField; 5.7 - private static CIntegerField scavengeRootStateField; 5.8 + private static JByteField scavengeRootStateField; 5.9 5.10 /** Offsets for different nmethod parts */ 5.11 private static CIntegerField exceptionOffsetField; 5.12 @@ -92,7 +92,7 @@ 5.13 entryBCIField = type.getCIntegerField("_entry_bci"); 5.14 osrLinkField = type.getAddressField("_osr_link"); 5.15 scavengeRootLinkField = type.getAddressField("_scavenge_root_link"); 5.16 - scavengeRootStateField = type.getCIntegerField("_scavenge_root_state"); 5.17 + scavengeRootStateField = type.getJByteField("_scavenge_root_state"); 5.18 5.19 exceptionOffsetField = type.getCIntegerField("_exception_offset"); 5.20 deoptOffsetField = type.getCIntegerField("_deoptimize_offset"); 5.21 @@ -274,7 +274,7 @@ 5.22 if (Assert.ASSERTS_ENABLED) { 5.23 Assert.that(pd != null, "scope must be present"); 5.24 } 5.25 - return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getReexecute()); 5.26 + return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getObjDecodeOffset(), pd.getReexecute()); 5.27 } 5.28 5.29 /** This is only for use by the debugging system, and is only 5.30 @@ -306,11 +306,11 @@ 5.31 public ScopeDesc getScopeDescNearDbg(Address pc) { 5.32 PCDesc pd = getPCDescNearDbg(pc); 5.33 if (pd == null) return null; 5.34 - return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getReexecute()); 5.35 + return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getObjDecodeOffset(), pd.getReexecute()); 5.36 } 5.37 5.38 - public Map/*<Address, PcDesc>*/ getSafepoints() { 5.39 - Map safepoints = new HashMap(); // Map<Address, PcDesc> 5.40 + public Map/*<Address, PCDesc>*/ getSafepoints() { 5.41 + Map safepoints = new HashMap(); // Map<Address, PCDesc> 5.42 sun.jvm.hotspot.debugger.Address p = null; 5.43 for (p = scopesPCsBegin(); p.lessThan(scopesPCsEnd()); 5.44 p = p.addOffsetTo(pcDescSize)) {
6.1 --- a/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java Wed Oct 28 10:37:17 2009 -0700 6.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java Thu Oct 29 08:49:31 2009 -0700 6.3 @@ -36,6 +36,7 @@ 6.4 public class PCDesc extends VMObject { 6.5 private static CIntegerField pcOffsetField; 6.6 private static CIntegerField scopeDecodeOffsetField; 6.7 + private static CIntegerField objDecodeOffsetField; 6.8 private static CIntegerField pcFlagsField; 6.9 6.10 static { 6.11 @@ -51,6 +52,7 @@ 6.12 6.13 pcOffsetField = type.getCIntegerField("_pc_offset"); 6.14 scopeDecodeOffsetField = type.getCIntegerField("_scope_decode_offset"); 6.15 + objDecodeOffsetField = type.getCIntegerField("_obj_decode_offset"); 6.16 pcFlagsField = type.getCIntegerField("_flags"); 6.17 } 6.18 6.19 @@ -68,6 +70,10 @@ 6.20 return ((int) scopeDecodeOffsetField.getValue(addr)); 6.21 } 6.22 6.23 + public int getObjDecodeOffset() { 6.24 + return ((int) objDecodeOffsetField.getValue(addr)); 6.25 + } 6.26 + 6.27 public Address getRealPC(NMethod code) { 6.28 return code.instructionsBegin().addOffsetTo(getPCOffset()); 6.29 }
7.1 --- a/agent/src/share/classes/sun/jvm/hotspot/code/ScopeDesc.java Wed Oct 28 10:37:17 2009 -0700 7.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/code/ScopeDesc.java Thu Oct 29 08:49:31 2009 -0700 7.3 @@ -51,11 +51,10 @@ 7.4 /** Scalar replaced bjects pool */ 7.5 private List objects; // ArrayList<ScopeValue> 7.6 7.7 - 7.8 - public ScopeDesc(NMethod code, int decodeOffset, boolean reexecute) { 7.9 + private ScopeDesc(NMethod code, int decodeOffset, List objects, boolean reexecute) { 7.10 this.code = code; 7.11 this.decodeOffset = decodeOffset; 7.12 - this.objects = decodeObjectValues(DebugInformationRecorder.SERIALIZED_NULL); 7.13 + this.objects = objects; 7.14 this.reexecute = reexecute; 7.15 7.16 // Decode header 7.17 @@ -108,7 +107,7 @@ 7.18 return decodeMonitorValues(monitorsDecodeOffset); 7.19 } 7.20 7.21 - /** Returns a List<MonitorValue> */ 7.22 + /** Returns a List<ObjectValue> */ 7.23 public List getObjects() { 7.24 return objects; 7.25 } 7.26 @@ -119,7 +118,7 @@ 7.27 return null; 7.28 } 7.29 7.30 - return new ScopeDesc(code, senderDecodeOffset, false); 7.31 + return new ScopeDesc(code, senderDecodeOffset, objects, false); 7.32 } 7.33 7.34 /** Returns where the scope was decoded */
8.1 --- a/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Wed Oct 28 10:37:17 2009 -0700 8.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Thu Oct 29 08:49:31 2009 -0700 8.3 @@ -807,6 +807,9 @@ 8.4 Interpreter interp = VM.getVM().getInterpreter(); 8.5 if (interp.contains(pc)) { 8.6 InterpreterCodelet codelet = interp.getCodeletContaining(pc); 8.7 + if (codelet == null) { 8.8 + return "Unknown location in the Interpreter: " + pc; 8.9 + } 8.10 return genHTML(codelet); 8.11 } 8.12 return genHTML(blob); 8.13 @@ -969,16 +972,24 @@ 8.14 } 8.15 8.16 protected String genSafepointInfo(NMethod nm, PCDesc pcDesc) { 8.17 - ScopeDesc sd = nm.getScopeDescAt(pcDesc.getRealPC(nm)); 8.18 - Formatter buf = new Formatter(genHTML); 8.19 - Formatter tabs = new Formatter(genHTML); 8.20 + ScopeDesc sd = nm.getScopeDescAt(pcDesc.getRealPC(nm)); 8.21 + Formatter buf = new Formatter(genHTML); 8.22 + Formatter tabs = new Formatter(genHTML); 8.23 + tabs.append(tab + tab + tab); // Initial indent for debug info 8.24 8.25 - buf.beginTag("pre"); 8.26 - genScope(buf, tabs, sd); 8.27 - buf.endTag("pre"); 8.28 - buf.append(genOopMapInfo(nm, pcDesc)); 8.29 + buf.beginTag("pre"); 8.30 + genScope(buf, tabs, sd); 8.31 8.32 - return buf.toString(); 8.33 + // Reset indent for scalar replaced objects 8.34 + tabs = new Formatter(genHTML); 8.35 + tabs.append(tab + tab + tab); // Initial indent for debug info 8.36 + 8.37 + genScObjInfo(buf, tabs, sd); 8.38 + buf.endTag("pre"); 8.39 + 8.40 + buf.append(genOopMapInfo(nm, pcDesc)); 8.41 + 8.42 + return buf.toString(); 8.43 } 8.44 8.45 protected void genScope(Formatter buf, Formatter tabs, ScopeDesc sd) { 8.46 @@ -1022,8 +1033,95 @@ 8.47 buf.append(genHTMLForMonitors(sd, monitors)); 8.48 } 8.49 8.50 + buf.br(); 8.51 tabs.append(tab); 8.52 - buf.br(); 8.53 + } 8.54 + 8.55 + protected void genScObjInfo(Formatter buf, Formatter tabs, ScopeDesc sd) { 8.56 + if (sd == null) { 8.57 + return; 8.58 + } 8.59 + 8.60 + List objects = sd.getObjects(); 8.61 + if (objects == null) { 8.62 + return; 8.63 + } 8.64 + int length = objects.size(); 8.65 + for (int i = 0; i < length; i++) { 8.66 + buf.append(tabs); 8.67 + ObjectValue ov = (ObjectValue)objects.get(i); 8.68 + buf.append("ScObj" + i); 8.69 + ScopeValue sv = ov.getKlass(); 8.70 + if (Assert.ASSERTS_ENABLED) { 8.71 + Assert.that(sv.isConstantOop(), "scalar replaced object klass must be constant oop"); 8.72 + } 8.73 + ConstantOopReadValue klv = (ConstantOopReadValue)sv; 8.74 + OopHandle klHandle = klv.getValue(); 8.75 + if (Assert.ASSERTS_ENABLED) { 8.76 + Assert.that(klHandle != null, "scalar replaced object klass must be not NULL"); 8.77 + } 8.78 + Oop obj = VM.getVM().getObjectHeap().newOop(klHandle); 8.79 + if (obj instanceof InstanceKlass) { 8.80 + InstanceKlass kls = (InstanceKlass) obj; 8.81 + buf.append(" " + kls.getName().asString() + "={"); 8.82 + int flen = ov.fieldsSize(); 8.83 + 8.84 + TypeArray klfields = kls.getFields(); 8.85 + int klen = (int) klfields.getLength(); 8.86 + 8.87 + ConstantPool cp = kls.getConstants(); 8.88 + int findex = 0; 8.89 + for (int index = 0; index < klen; index += kls.NEXT_OFFSET) { 8.90 + int accsFlags = klfields.getShortAt(index + kls.ACCESS_FLAGS_OFFSET); 8.91 + int nameIndex = klfields.getShortAt(index + kls.NAME_INDEX_OFFSET); 8.92 + AccessFlags access = new AccessFlags(accsFlags); 8.93 + if (!access.isStatic()) { 8.94 + ScopeValue svf = ov.getFieldAt(findex++); 8.95 + String fstr = scopeValueAsString(sd, svf); 8.96 + Symbol f_name = cp.getSymbolAt(nameIndex); 8.97 + buf.append(" [" + f_name.asString() + " :"+ index + "]=(#" + fstr + ")"); 8.98 + } 8.99 + } 8.100 + buf.append(" }"); 8.101 + } else { 8.102 + buf.append(" "); 8.103 + int flen = ov.fieldsSize(); 8.104 + if (obj instanceof TypeArrayKlass) { 8.105 + TypeArrayKlass kls = (TypeArrayKlass) obj; 8.106 + buf.append(kls.getElementTypeName() + "[" + flen + "]"); 8.107 + } else if (obj instanceof ObjArrayKlass) { 8.108 + ObjArrayKlass kls = (ObjArrayKlass) obj; 8.109 + Klass elobj = kls.getBottomKlass(); 8.110 + if (elobj instanceof InstanceKlass) { 8.111 + buf.append(elobj.getName().asString()); 8.112 + } else if (elobj instanceof TypeArrayKlass) { 8.113 + TypeArrayKlass elkls = (TypeArrayKlass) elobj; 8.114 + buf.append(elkls.getElementTypeName()); 8.115 + } else { 8.116 + if (Assert.ASSERTS_ENABLED) { 8.117 + Assert.that(false, "unknown scalar replaced object klass!"); 8.118 + } 8.119 + } 8.120 + buf.append("[" + flen + "]"); 8.121 + int ndim = (int) kls.getDimension(); 8.122 + while (--ndim > 0) { 8.123 + buf.append("[]"); 8.124 + } 8.125 + } else { 8.126 + if (Assert.ASSERTS_ENABLED) { 8.127 + Assert.that(false, "unknown scalar replaced object klass!"); 8.128 + } 8.129 + } 8.130 + buf.append("={"); 8.131 + for (int findex = 0; findex < flen; findex++) { 8.132 + ScopeValue svf = ov.getFieldAt(findex); 8.133 + String fstr = scopeValueAsString(sd, svf); 8.134 + buf.append(" [" + findex + "]=(#" + fstr + ")"); 8.135 + } 8.136 + buf.append(" }"); 8.137 + } 8.138 + buf.br(); 8.139 + } 8.140 } 8.141 8.142 protected String genHTMLForOopMap(OopMap map) { 8.143 @@ -1037,8 +1135,6 @@ 8.144 tmpBuf.beginTag("tr"); 8.145 tmpBuf.beginTag("td"); 8.146 tmpBuf.append(type); 8.147 - tmpBuf.endTag("td"); 8.148 - tmpBuf.endTag("tr"); 8.149 for (; ! oms.isDone(); oms.next()) { 8.150 OopMapValue omv = oms.getCurrent(); 8.151 if (omv == null) { 8.152 @@ -1048,7 +1144,7 @@ 8.153 VMReg vmReg = omv.getReg(); 8.154 int reg = vmReg.getValue(); 8.155 if (reg < stack0) { 8.156 - tmpBuf.append(VMRegImpl.getRegisterName(vmReg.getValue())); 8.157 + tmpBuf.append(VMRegImpl.getRegisterName(reg)); 8.158 } else { 8.159 tmpBuf.append('['); 8.160 tmpBuf.append(Integer.toString((reg - stack0) * 4)); 8.161 @@ -1058,7 +1154,13 @@ 8.162 tmpBuf.append(" = "); 8.163 VMReg vmContentReg = omv.getContentReg(); 8.164 int contentReg = vmContentReg.getValue(); 8.165 - tmpBuf.append(VMRegImpl.getRegisterName(vmContentReg.getValue())); 8.166 + if (contentReg < stack0) { 8.167 + tmpBuf.append(VMRegImpl.getRegisterName(contentReg)); 8.168 + } else { 8.169 + tmpBuf.append('['); 8.170 + tmpBuf.append(Integer.toString((contentReg - stack0) * 4)); 8.171 + tmpBuf.append(']'); 8.172 + } 8.173 } 8.174 tmpBuf.append(spaces); 8.175 } 8.176 @@ -1072,19 +1174,19 @@ 8.177 8.178 OopMapValueIterator omvIterator = new OopMapValueIterator(); 8.179 OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.OOP_VALUE); 8.180 - buf.append(omvIterator.iterate(oms, "Oop:", false)); 8.181 + buf.append(omvIterator.iterate(oms, "Oops:", false)); 8.182 + 8.183 + oms = new OopMapStream(map, OopMapValue.OopTypes.NARROWOOP_VALUE); 8.184 + buf.append(omvIterator.iterate(oms, "narrowOops:", false)); 8.185 8.186 oms = new OopMapStream(map, OopMapValue.OopTypes.VALUE_VALUE); 8.187 - buf.append(omvIterator.iterate(oms, "Value:", false)); 8.188 - 8.189 - oms = new OopMapStream(map, OopMapValue.OopTypes.NARROWOOP_VALUE); 8.190 - buf.append(omvIterator.iterate(oms, "Oop:", false)); 8.191 + buf.append(omvIterator.iterate(oms, "Values:", false)); 8.192 8.193 oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE); 8.194 buf.append(omvIterator.iterate(oms, "Callee saved:", true)); 8.195 8.196 oms = new OopMapStream(map, OopMapValue.OopTypes.DERIVED_OOP_VALUE); 8.197 - buf.append(omvIterator.iterate(oms, "Derived oop:", true)); 8.198 + buf.append(omvIterator.iterate(oms, "Derived oops:", true)); 8.199 8.200 buf.endTag("table"); 8.201 return buf.toString(); 8.202 @@ -1093,6 +1195,8 @@ 8.203 8.204 protected String genOopMapInfo(NMethod nmethod, PCDesc pcDesc) { 8.205 OopMapSet mapSet = nmethod.getOopMaps(); 8.206 + if (mapSet == null || (mapSet.getSize() <= 0)) 8.207 + return ""; 8.208 int pcOffset = pcDesc.getPCOffset(); 8.209 OopMap map = mapSet.findMapAtOffset(pcOffset, VM.getVM().isDebugging()); 8.210 if (map == null) { 8.211 @@ -1106,6 +1210,7 @@ 8.212 Formatter buf = new Formatter(genHTML); 8.213 buf.beginTag("pre"); 8.214 buf.append("OopMap: "); 8.215 + buf.br(); 8.216 buf.append(genHTMLForOopMap(map)); 8.217 buf.endTag("pre"); 8.218 8.219 @@ -1154,7 +1259,7 @@ 8.220 return buf.toString(); 8.221 } 8.222 8.223 - private String scopeValueAsString(ScopeValue sv) { 8.224 + private String scopeValueAsString(ScopeDesc sd, ScopeValue sv) { 8.225 Formatter buf = new Formatter(genHTML); 8.226 if (sv.isConstantInt()) { 8.227 buf.append("int "); 8.228 @@ -1187,6 +1292,11 @@ 8.229 } else { 8.230 buf.append("null"); 8.231 } 8.232 + } else if (sv.isObject()) { 8.233 + ObjectValue ov = (ObjectValue)sv; 8.234 + buf.append("#ScObj" + sd.getObjects().indexOf(ov)); 8.235 + } else { 8.236 + buf.append("unknown scope value " + sv); 8.237 } 8.238 return buf.toString(); 8.239 } 8.240 @@ -1219,7 +1329,7 @@ 8.241 } 8.242 8.243 buf.append(", "); 8.244 - buf.append(scopeValueAsString(sv)); 8.245 + buf.append(scopeValueAsString(sd, sv)); 8.246 buf.append(") "); 8.247 } 8.248 8.249 @@ -1246,7 +1356,7 @@ 8.250 buf.append("(owner = "); 8.251 ScopeValue owner = mv.owner(); 8.252 if (owner != null) { 8.253 - buf.append(scopeValueAsString(owner)); 8.254 + buf.append(scopeValueAsString(sd, owner)); 8.255 } else { 8.256 buf.append("null"); 8.257 } 8.258 @@ -1324,11 +1434,11 @@ 8.259 buf.append(instr.asString(currentPc, symFinder)); 8.260 } 8.261 8.262 + buf.br(); 8.263 if (isSafepoint && !prevWasCall) { 8.264 - buf.append(genSafepointInfo(nmethod, pcDesc)); 8.265 + buf.append(genSafepointInfo(nmethod, pcDesc)); 8.266 } 8.267 8.268 - buf.br(); 8.269 prevWasCall = instr.isCall(); 8.270 } 8.271
9.1 --- a/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Wed Oct 28 10:37:17 2009 -0700 9.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Thu Oct 29 08:49:31 2009 -0700 9.3 @@ -1047,7 +1047,7 @@ 9.4 } else { 9.5 // some type names have ':'. replace to make it as a 9.6 // JavaScript identifier 9.7 - tmp.name = tmp.name.replace(':', '_'); 9.8 + tmp.name = tmp.name.replace(':', '_').replace('<', '_').replace('>', '_').replace('*', '_').replace(' ', '_'); 9.9 eval("function read" + tmp.name + "(addr) {" + 9.10 " return readVMType('" + tmp.name + "', addr);}"); 9.11 eval("function print" + tmp.name + "(addr) {" +
10.1 --- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Wed Oct 28 10:37:17 2009 -0700 10.2 +++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Oct 29 08:49:31 2009 -0700 10.3 @@ -3213,9 +3213,8 @@ 10.4 Register Oreturn0 = O0; 10.5 Register Oreturn1 = O1; 10.6 Register O2UnrollBlock = O2; 10.7 - Register O3tmp = O3; 10.8 - Register I5exception_tmp = I5; 10.9 - Register G4exception_tmp = G4_scratch; 10.10 + Register L0deopt_mode = L0; 10.11 + Register G4deopt_mode = G4_scratch; 10.12 int frame_size_words; 10.13 Address saved_Freturn0_addr(FP, -sizeof(double) + STACK_BIAS); 10.14 #if !defined(_LP64) && defined(COMPILER2) 10.15 @@ -3265,7 +3264,7 @@ 10.16 10.17 map = RegisterSaver::save_live_registers(masm, 0, &frame_size_words); 10.18 __ ba(false, cont); 10.19 - __ delayed()->mov(Deoptimization::Unpack_deopt, I5exception_tmp); 10.20 + __ delayed()->mov(Deoptimization::Unpack_deopt, L0deopt_mode); 10.21 10.22 int exception_offset = __ offset() - start; 10.23 10.24 @@ -3316,7 +3315,7 @@ 10.25 #endif 10.26 10.27 __ ba(false, cont); 10.28 - __ delayed()->mov(Deoptimization::Unpack_exception, I5exception_tmp);; 10.29 + __ delayed()->mov(Deoptimization::Unpack_exception, L0deopt_mode);; 10.30 10.31 // 10.32 // Reexecute entry, similar to c2 uncommon trap 10.33 @@ -3326,7 +3325,7 @@ 10.34 // No need to update oop_map as each call to save_live_registers will produce identical oopmap 10.35 (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words); 10.36 10.37 - __ mov(Deoptimization::Unpack_reexecute, I5exception_tmp); 10.38 + __ mov(Deoptimization::Unpack_reexecute, L0deopt_mode); 10.39 10.40 __ bind(cont); 10.41 10.42 @@ -3349,14 +3348,14 @@ 10.43 // NOTE: we know that only O0/O1 will be reloaded by restore_result_registers 10.44 // so this move will survive 10.45 10.46 - __ mov(I5exception_tmp, G4exception_tmp); 10.47 + __ mov(L0deopt_mode, G4deopt_mode); 10.48 10.49 __ mov(O0, O2UnrollBlock->after_save()); 10.50 10.51 RegisterSaver::restore_result_registers(masm); 10.52 10.53 Label noException; 10.54 - __ cmp(G4exception_tmp, Deoptimization::Unpack_exception); // Was exception pending? 10.55 + __ cmp(G4deopt_mode, Deoptimization::Unpack_exception); // Was exception pending? 10.56 __ br(Assembler::notEqual, false, Assembler::pt, noException); 10.57 __ delayed()->nop(); 10.58 10.59 @@ -3390,10 +3389,10 @@ 10.60 } 10.61 #endif 10.62 __ set_last_Java_frame(SP, noreg); 10.63 - __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), G2_thread, G4exception_tmp); 10.64 + __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), G2_thread, G4deopt_mode); 10.65 #else 10.66 // LP64 uses g4 in set_last_Java_frame 10.67 - __ mov(G4exception_tmp, O1); 10.68 + __ mov(G4deopt_mode, O1); 10.69 __ set_last_Java_frame(SP, G0); 10.70 __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), G2_thread, O1); 10.71 #endif 10.72 @@ -3446,7 +3445,6 @@ 10.73 #endif 10.74 MacroAssembler* masm = new MacroAssembler(&buffer); 10.75 Register O2UnrollBlock = O2; 10.76 - Register O3tmp = O3; 10.77 Register O2klass_index = O2; 10.78 10.79 //
11.1 --- a/src/cpu/sparc/vm/sparc.ad Wed Oct 28 10:37:17 2009 -0700 11.2 +++ b/src/cpu/sparc/vm/sparc.ad Thu Oct 29 08:49:31 2009 -0700 11.3 @@ -9419,8 +9419,9 @@ 11.4 // x |= (x >> 8); 11.5 // x |= (x >> 16); 11.6 // return (WORDBITS - popc(x)); 11.7 - format %{ "SRL $src,1,$dst\t! count leading zeros (int)\n\t" 11.8 - "OR $src,$tmp,$dst\n\t" 11.9 + format %{ "SRL $src,1,$tmp\t! count leading zeros (int)\n\t" 11.10 + "SRL $src,0,$dst\t! 32-bit zero extend\n\t" 11.11 + "OR $dst,$tmp,$dst\n\t" 11.12 "SRL $dst,2,$tmp\n\t" 11.13 "OR $dst,$tmp,$dst\n\t" 11.14 "SRL $dst,4,$tmp\n\t" 11.15 @@ -9437,7 +9438,8 @@ 11.16 Register Rsrc = $src$$Register; 11.17 Register Rtmp = $tmp$$Register; 11.18 __ srl(Rsrc, 1, Rtmp); 11.19 - __ or3(Rsrc, Rtmp, Rdst); 11.20 + __ srl(Rsrc, 0, Rdst); 11.21 + __ or3(Rdst, Rtmp, Rdst); 11.22 __ srl(Rdst, 2, Rtmp); 11.23 __ or3(Rdst, Rtmp, Rdst); 11.24 __ srl(Rdst, 4, Rtmp); 11.25 @@ -9465,7 +9467,7 @@ 11.26 // x |= (x >> 16); 11.27 // x |= (x >> 32); 11.28 // return (WORDBITS - popc(x)); 11.29 - format %{ "SRLX $src,1,$dst\t! count leading zeros (long)\n\t" 11.30 + format %{ "SRLX $src,1,$tmp\t! count leading zeros (long)\n\t" 11.31 "OR $src,$tmp,$dst\n\t" 11.32 "SRLX $dst,2,$tmp\n\t" 11.33 "OR $dst,$tmp,$dst\n\t"
12.1 --- a/src/cpu/x86/vm/methodHandles_x86.cpp Wed Oct 28 10:37:17 2009 -0700 12.2 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp Thu Oct 29 08:49:31 2009 -0700 12.3 @@ -271,9 +271,15 @@ 12.4 void trace_method_handle_stub(const char* adaptername, 12.5 oopDesc* mh, 12.6 intptr_t* entry_sp, 12.7 - intptr_t* saved_sp) { 12.8 + intptr_t* saved_sp, 12.9 + intptr_t* saved_bp) { 12.10 // called as a leaf from native code: do not block the JVM! 12.11 - printf("MH %s "PTR_FORMAT" "PTR_FORMAT" "INTX_FORMAT"\n", adaptername, (void*)mh, entry_sp, entry_sp - saved_sp); 12.12 + intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset]; 12.13 + intptr_t* base_sp = (intptr_t*) saved_bp[frame::interpreter_frame_monitor_block_top_offset]; 12.14 + printf("MH %s mh="INTPTR_FORMAT" sp=("INTPTR_FORMAT"+"INTX_FORMAT") stack_size="INTX_FORMAT" bp="INTPTR_FORMAT"\n", 12.15 + adaptername, (intptr_t)mh, (intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp); 12.16 + if (last_sp != saved_sp) 12.17 + printf("*** last_sp="INTPTR_FORMAT"\n", (intptr_t)last_sp); 12.18 } 12.19 #endif //PRODUCT 12.20 12.21 @@ -293,6 +299,10 @@ 12.22 Register rbx_temp = rbx; 12.23 Register rdx_temp = rdx; 12.24 12.25 + // This guy is set up by prepare_to_jump_from_interpreted (from interpreted calls) 12.26 + // and gen_c2i_adapter (from compiled calls): 12.27 + Register saved_last_sp = LP64_ONLY(r13) NOT_LP64(rsi); 12.28 + 12.29 guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); 12.30 12.31 // some handy addresses 12.32 @@ -315,6 +325,8 @@ 12.33 assert(tag_offset = wordSize, "stack grows as expected"); 12.34 } 12.35 12.36 + const int java_mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes(); 12.37 + 12.38 if (have_entry(ek)) { 12.39 __ nop(); // empty stubs make SG sick 12.40 return; 12.41 @@ -328,45 +340,65 @@ 12.42 __ push(rax); __ push(rbx); __ push(rcx); __ push(rdx); __ push(rsi); __ push(rdi); 12.43 __ lea(rax, Address(rsp, wordSize*6)); // entry_sp 12.44 // arguments: 12.45 + __ push(rbp); // interpreter frame pointer 12.46 __ push(rsi); // saved_sp 12.47 __ push(rax); // entry_sp 12.48 __ push(rcx); // mh 12.49 __ push(rcx); 12.50 __ movptr(Address(rsp, 0), (intptr_t)entry_name(ek)); 12.51 - __ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub), 4); 12.52 + __ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub), 5); 12.53 __ pop(rdi); __ pop(rsi); __ pop(rdx); __ pop(rcx); __ pop(rbx); __ pop(rax); 12.54 } 12.55 #endif //PRODUCT 12.56 12.57 switch ((int) ek) { 12.58 - case _check_mtype: 12.59 + case _raise_exception: 12.60 { 12.61 - // this stub is special, because it requires a live mtype argument 12.62 - Register rax_mtype = rax; 12.63 + // Not a real MH entry, but rather shared code for raising an exception. 12.64 + // Extra local arguments are pushed on stack, as required type at TOS+8, 12.65 + // failing object (or NULL) at TOS+4, failing bytecode type at TOS. 12.66 + // Beyond those local arguments are the PC, of course. 12.67 + Register rdx_code = rdx_temp; 12.68 + Register rcx_fail = rcx_recv; 12.69 + Register rax_want = rax_argslot; 12.70 + Register rdi_pc = rdi; 12.71 + __ pop(rdx_code); // TOS+0 12.72 + __ pop(rcx_fail); // TOS+4 12.73 + __ pop(rax_want); // TOS+8 12.74 + __ pop(rdi_pc); // caller PC 12.75 12.76 - // emit WrongMethodType path first, to enable jccb back-branch 12.77 - Label wrong_method_type; 12.78 - __ bind(wrong_method_type); 12.79 - __ movptr(rdx_temp, ExternalAddress((address) &_entries[_wrong_method_type])); 12.80 - __ jmp(Address(rdx_temp, MethodHandleEntry::from_interpreted_entry_offset_in_bytes())); 12.81 - __ hlt(); 12.82 + __ mov(rsp, rsi); // cut the stack back to where the caller started 12.83 12.84 - interp_entry = __ pc(); 12.85 - __ check_method_handle_type(rax_mtype, rcx_recv, rdx_temp, wrong_method_type); 12.86 - // now rax_mtype is dead; subsequent stubs will use it as a temp 12.87 + // Repush the arguments as if coming from the interpreter. 12.88 + if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_INT)); 12.89 + __ push(rdx_code); 12.90 + if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_OBJECT)); 12.91 + __ push(rcx_fail); 12.92 + if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_OBJECT)); 12.93 + __ push(rax_want); 12.94 12.95 - __ jump_to_method_handle_entry(rcx_recv, rdx_temp); 12.96 - } 12.97 - break; 12.98 + Register rbx_method = rbx_temp; 12.99 + Label no_method; 12.100 + // FIXME: fill in _raise_exception_method with a suitable sun.dyn method 12.101 + __ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method)); 12.102 + __ testptr(rbx_method, rbx_method); 12.103 + __ jcc(Assembler::zero, no_method); 12.104 + int jobject_oop_offset = 0; 12.105 + __ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject 12.106 + __ testptr(rbx_method, rbx_method); 12.107 + __ jcc(Assembler::zero, no_method); 12.108 + __ verify_oop(rbx_method); 12.109 + __ push(rdi_pc); // and restore caller PC 12.110 + __ jmp(rbx_method_fie); 12.111 12.112 - case _wrong_method_type: 12.113 - { 12.114 - // this stub is special, because it requires a live mtype argument 12.115 - Register rax_mtype = rax; 12.116 - 12.117 - interp_entry = __ pc(); 12.118 - __ push(rax_mtype); // required mtype 12.119 - __ push(rcx_recv); // random mh (1st stacked argument) 12.120 + // If we get here, the Java runtime did not do its job of creating the exception. 12.121 + // Do something that is at least causes a valid throw from the interpreter. 12.122 + __ bind(no_method); 12.123 + __ pop(rax_want); 12.124 + if (TaggedStackInterpreter) __ pop(rcx_fail); 12.125 + __ pop(rcx_fail); 12.126 + __ push(rax_want); 12.127 + __ push(rcx_fail); 12.128 __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry())); 12.129 } 12.130 break; 12.131 @@ -442,7 +474,7 @@ 12.132 __ load_klass(rax_klass, rcx_recv); 12.133 __ verify_oop(rax_klass); 12.134 12.135 - Register rcx_temp = rcx_recv; 12.136 + Register rdi_temp = rdi; 12.137 Register rbx_method = rbx_index; 12.138 12.139 // get interface klass 12.140 @@ -451,7 +483,7 @@ 12.141 __ lookup_interface_method(rax_klass, rdx_intf, 12.142 // note: next two args must be the same: 12.143 rbx_index, rbx_method, 12.144 - rcx_temp, 12.145 + rdi_temp, 12.146 no_such_interface); 12.147 12.148 __ verify_oop(rbx_method); 12.149 @@ -461,7 +493,10 @@ 12.150 __ bind(no_such_interface); 12.151 // Throw an exception. 12.152 // For historical reasons, it will be IncompatibleClassChangeError. 12.153 - __ should_not_reach_here(); // %%% FIXME NYI 12.154 + __ pushptr(Address(rdx_intf, java_mirror_offset)); // required interface 12.155 + __ push(rcx_recv); // bad receiver 12.156 + __ push((int)Bytecodes::_invokeinterface); // who is complaining? 12.157 + __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); 12.158 } 12.159 break; 12.160 12.161 @@ -524,6 +559,7 @@ 12.162 break; 12.163 12.164 case _adapter_retype_only: 12.165 + case _adapter_retype_raw: 12.166 // immediately jump to the next MH layer: 12.167 __ movptr(rcx_recv, rcx_mh_vmtarget); 12.168 __ verify_oop(rcx_recv); 12.169 @@ -545,10 +581,6 @@ 12.170 __ movptr(rbx_klass, rcx_amh_argument); // this is a Class object! 12.171 __ movptr(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes())); 12.172 12.173 - // get the new MH: 12.174 - __ movptr(rcx_recv, rcx_mh_vmtarget); 12.175 - // (now we are done with the old MH) 12.176 - 12.177 Label done; 12.178 __ movptr(rdx_temp, vmarg); 12.179 __ testl(rdx_temp, rdx_temp); 12.180 @@ -558,17 +590,23 @@ 12.181 // live at this point: 12.182 // - rbx_klass: klass required by the target method 12.183 // - rdx_temp: argument klass to test 12.184 - // - rcx_recv: method handle to invoke (after cast succeeds) 12.185 + // - rcx_recv: adapter method handle 12.186 __ check_klass_subtype(rdx_temp, rbx_klass, rax_argslot, done); 12.187 12.188 // If we get here, the type check failed! 12.189 // Call the wrong_method_type stub, passing the failing argument type in rax. 12.190 Register rax_mtype = rax_argslot; 12.191 - __ push(rbx_klass); // missed klass (required type) 12.192 - __ push(rdx_temp); // bad actual type (1st stacked argument) 12.193 - __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry())); 12.194 + __ movl(rax_argslot, rcx_amh_vmargslot); // reload argslot field 12.195 + __ movptr(rdx_temp, vmarg); 12.196 + 12.197 + __ pushptr(rcx_amh_argument); // required class 12.198 + __ push(rdx_temp); // bad object 12.199 + __ push((int)Bytecodes::_checkcast); // who is complaining? 12.200 + __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); 12.201 12.202 __ bind(done); 12.203 + // get the new MH: 12.204 + __ movptr(rcx_recv, rcx_mh_vmtarget); 12.205 __ jump_to_method_handle_entry(rcx_recv, rdx_temp); 12.206 } 12.207 break; 12.208 @@ -1107,11 +1145,17 @@ 12.209 12.210 __ bind(bad_array_klass); 12.211 UNPUSH_RSI_RDI; 12.212 - __ stop("bad array klass NYI"); 12.213 + __ pushptr(Address(rdx_array_klass, java_mirror_offset)); // required type 12.214 + __ pushptr(vmarg); // bad array 12.215 + __ push((int)Bytecodes::_aaload); // who is complaining? 12.216 + __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); 12.217 12.218 __ bind(bad_array_length); 12.219 UNPUSH_RSI_RDI; 12.220 - __ stop("bad array length NYI"); 12.221 + __ push(rcx_recv); // AMH requiring a certain length 12.222 + __ pushptr(vmarg); // bad array 12.223 + __ push((int)Bytecodes::_arraylength); // who is complaining? 12.224 + __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); 12.225 12.226 #undef UNPUSH_RSI_RDI 12.227 }
13.1 --- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Wed Oct 28 10:37:17 2009 -0700 13.2 +++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Thu Oct 29 08:49:31 2009 -0700 13.3 @@ -92,8 +92,7 @@ 13.4 return entry; 13.5 } 13.6 13.7 -// Arguments are: required type at TOS+8, failing object (or NULL) at TOS+4. 13.8 -// pc at TOS (just for debugging) 13.9 +// Arguments are: required type at TOS+4, failing object (or NULL) at TOS. 13.10 address TemplateInterpreterGenerator::generate_WrongMethodType_handler() { 13.11 address entry = __ pc(); 13.12
14.1 --- a/src/share/vm/classfile/javaClasses.hpp Wed Oct 28 10:37:17 2009 -0700 14.2 +++ b/src/share/vm/classfile/javaClasses.hpp Thu Oct 29 08:49:31 2009 -0700 14.3 @@ -903,19 +903,20 @@ 14.4 // Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants): 14.5 enum { 14.6 OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype 14.7 - OP_CHECK_CAST = 0x1, // ref-to-ref conversion; requires a Class argument 14.8 - OP_PRIM_TO_PRIM = 0x2, // converts from one primitive to another 14.9 - OP_REF_TO_PRIM = 0x3, // unboxes a wrapper to produce a primitive 14.10 - OP_PRIM_TO_REF = 0x4, // boxes a primitive into a wrapper (NYI) 14.11 - OP_SWAP_ARGS = 0x5, // swap arguments (vminfo is 2nd arg) 14.12 - OP_ROT_ARGS = 0x6, // rotate arguments (vminfo is displaced arg) 14.13 - OP_DUP_ARGS = 0x7, // duplicates one or more arguments (at TOS) 14.14 - OP_DROP_ARGS = 0x8, // remove one or more argument slots 14.15 - OP_COLLECT_ARGS = 0x9, // combine one or more arguments into a varargs (NYI) 14.16 - OP_SPREAD_ARGS = 0xA, // expand in place a varargs array (of known size) 14.17 - OP_FLYBY = 0xB, // operate first on reified argument list (NYI) 14.18 - OP_RICOCHET = 0xC, // run an adapter chain on the return value (NYI) 14.19 - CONV_OP_LIMIT = 0xD, // limit of CONV_OP enumeration 14.20 + OP_RETYPE_RAW = 0x1, // straight retype, trusted (void->int, Object->T) 14.21 + OP_CHECK_CAST = 0x2, // ref-to-ref conversion; requires a Class argument 14.22 + OP_PRIM_TO_PRIM = 0x3, // converts from one primitive to another 14.23 + OP_REF_TO_PRIM = 0x4, // unboxes a wrapper to produce a primitive 14.24 + OP_PRIM_TO_REF = 0x5, // boxes a primitive into a wrapper (NYI) 14.25 + OP_SWAP_ARGS = 0x6, // swap arguments (vminfo is 2nd arg) 14.26 + OP_ROT_ARGS = 0x7, // rotate arguments (vminfo is displaced arg) 14.27 + OP_DUP_ARGS = 0x8, // duplicates one or more arguments (at TOS) 14.28 + OP_DROP_ARGS = 0x9, // remove one or more argument slots 14.29 + OP_COLLECT_ARGS = 0xA, // combine one or more arguments into a varargs (NYI) 14.30 + OP_SPREAD_ARGS = 0xB, // expand in place a varargs array (of known size) 14.31 + OP_FLYBY = 0xC, // operate first on reified argument list (NYI) 14.32 + OP_RICOCHET = 0xD, // run an adapter chain on the return value (NYI) 14.33 + CONV_OP_LIMIT = 0xE, // limit of CONV_OP enumeration 14.34 14.35 CONV_OP_MASK = 0xF00, // this nybble contains the conversion op field 14.36 CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use
15.1 --- a/src/share/vm/classfile/systemDictionary.cpp Wed Oct 28 10:37:17 2009 -0700 15.2 +++ b/src/share/vm/classfile/systemDictionary.cpp Thu Oct 29 08:49:31 2009 -0700 15.3 @@ -1963,7 +1963,7 @@ 15.4 WKID meth_group_end = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass); 15.5 initialize_wk_klasses_until(meth_group_start, scan, CHECK); 15.6 if (EnableMethodHandles) { 15.7 - initialize_wk_klasses_through(meth_group_start, scan, CHECK); 15.8 + initialize_wk_klasses_through(meth_group_end, scan, CHECK); 15.9 } 15.10 if (_well_known_klasses[meth_group_start] == NULL) { 15.11 // Skip the rest of the method handle classes, if MethodHandle is not loaded.
16.1 --- a/src/share/vm/oops/instanceKlass.cpp Wed Oct 28 10:37:17 2009 -0700 16.2 +++ b/src/share/vm/oops/instanceKlass.cpp Thu Oct 29 08:49:31 2009 -0700 16.3 @@ -1900,7 +1900,7 @@ 16.4 } 16.5 } 16.6 16.7 -char* instanceKlass::signature_name() const { 16.8 +const char* instanceKlass::signature_name() const { 16.9 const char* src = (const char*) (name()->as_C_string()); 16.10 const int src_length = (int)strlen(src); 16.11 char* dest = NEW_RESOURCE_ARRAY(char, src_length + 3); 16.12 @@ -2259,6 +2259,10 @@ 16.13 st->print(BULLET"fake entry for array: "); 16.14 array_klass->print_value_on(st); 16.15 st->cr(); 16.16 + } else if (as_klassOop() == SystemDictionary::MethodType_klass()) { 16.17 + st->print(BULLET"signature: "); 16.18 + java_dyn_MethodType::print_signature(obj, st); 16.19 + st->cr(); 16.20 } 16.21 } 16.22 16.23 @@ -2284,6 +2288,9 @@ 16.24 const char* tname = type2name(java_lang_Class::primitive_type(obj)); 16.25 st->print("%s", tname ? tname : "type?"); 16.26 } 16.27 + } else if (as_klassOop() == SystemDictionary::MethodType_klass()) { 16.28 + st->print(" = "); 16.29 + java_dyn_MethodType::print_signature(obj, st); 16.30 } else if (java_lang_boxing_object::is_instance(obj)) { 16.31 st->print(" = "); 16.32 java_lang_boxing_object::print(obj, st);
17.1 --- a/src/share/vm/oops/instanceKlass.hpp Wed Oct 28 10:37:17 2009 -0700 17.2 +++ b/src/share/vm/oops/instanceKlass.hpp Thu Oct 29 08:49:31 2009 -0700 17.3 @@ -722,7 +722,7 @@ 17.4 #endif // SERIALGC 17.5 17.6 // Naming 17.7 - char* signature_name() const; 17.8 + const char* signature_name() const; 17.9 17.10 // Iterators 17.11 int oop_oop_iterate(oop obj, OopClosure* blk) {
18.1 --- a/src/share/vm/oops/klass.cpp Wed Oct 28 10:37:17 2009 -0700 18.2 +++ b/src/share/vm/oops/klass.cpp Thu Oct 29 08:49:31 2009 -0700 18.3 @@ -496,11 +496,13 @@ 18.4 return result; 18.5 } 18.6 } 18.7 + if (name() == NULL) return "<unknown>"; 18.8 return name()->as_klass_external_name(); 18.9 } 18.10 18.11 18.12 -char* Klass::signature_name() const { 18.13 +const char* Klass::signature_name() const { 18.14 + if (name() == NULL) return "<unknown>"; 18.15 return name()->as_C_string(); 18.16 } 18.17
19.1 --- a/src/share/vm/oops/klass.hpp Wed Oct 28 10:37:17 2009 -0700 19.2 +++ b/src/share/vm/oops/klass.hpp Thu Oct 29 08:49:31 2009 -0700 19.3 @@ -546,7 +546,7 @@ 19.4 // For arrays, this returns the name of the element with a leading '['. 19.5 // For classes, this returns the name with a leading 'L' and a trailing ';' 19.6 // and the package separators as '/'. 19.7 - virtual char* signature_name() const; 19.8 + virtual const char* signature_name() const; 19.9 19.10 // garbage collection support 19.11 virtual void oop_follow_contents(oop obj) = 0;
20.1 --- a/src/share/vm/oops/markOop.cpp Wed Oct 28 10:37:17 2009 -0700 20.2 +++ b/src/share/vm/oops/markOop.cpp Thu Oct 29 08:49:31 2009 -0700 20.3 @@ -31,8 +31,9 @@ 20.4 st->print("locked(0x%lx)->", value()); 20.5 markOop(*(markOop*)value())->print_on(st); 20.6 } else { 20.7 - assert(is_unlocked(), "just checking"); 20.8 + assert(is_unlocked() || has_bias_pattern(), "just checking"); 20.9 st->print("mark("); 20.10 + if (has_bias_pattern()) st->print("biased,"); 20.11 st->print("hash %#lx,", hash()); 20.12 st->print("age %d)", age()); 20.13 }
21.1 --- a/src/share/vm/oops/methodOop.cpp Wed Oct 28 10:37:17 2009 -0700 21.2 +++ b/src/share/vm/oops/methodOop.cpp Thu Oct 29 08:49:31 2009 -0700 21.3 @@ -881,7 +881,7 @@ 21.4 assert((oop)p == method_type(), "pointer chase is correct"); 21.5 #endif 21.6 21.7 - if (TraceMethodHandles) 21.8 + if (TraceMethodHandles && (Verbose || WizardMode)) 21.9 m->print_on(tty); 21.10 21.11 return m;
22.1 --- a/src/share/vm/opto/callnode.cpp Wed Oct 28 10:37:17 2009 -0700 22.2 +++ b/src/share/vm/opto/callnode.cpp Thu Oct 29 08:49:31 2009 -0700 22.3 @@ -421,21 +421,23 @@ 22.4 iklass = cik->as_instance_klass(); 22.5 } else if (cik->is_type_array_klass()) { 22.6 cik->as_array_klass()->base_element_type()->print_name_on(st); 22.7 - st->print("[%d]=", spobj->n_fields()); 22.8 + st->print("[%d]", spobj->n_fields()); 22.9 } else if (cik->is_obj_array_klass()) { 22.10 - ciType* cie = cik->as_array_klass()->base_element_type(); 22.11 - int ndim = 1; 22.12 - while (cie->is_obj_array_klass()) { 22.13 - ndim += 1; 22.14 - cie = cie->as_array_klass()->base_element_type(); 22.15 + ciKlass* cie = cik->as_obj_array_klass()->base_element_klass(); 22.16 + if (cie->is_instance_klass()) { 22.17 + cie->print_name_on(st); 22.18 + } else if (cie->is_type_array_klass()) { 22.19 + cie->as_array_klass()->base_element_type()->print_name_on(st); 22.20 + } else { 22.21 + ShouldNotReachHere(); 22.22 } 22.23 - cie->print_name_on(st); 22.24 + st->print("[%d]", spobj->n_fields()); 22.25 + int ndim = cik->as_array_klass()->dimension() - 1; 22.26 while (ndim-- > 0) { 22.27 st->print("[]"); 22.28 } 22.29 - st->print("[%d]=", spobj->n_fields()); 22.30 } 22.31 - st->print("{"); 22.32 + st->print("={"); 22.33 uint nf = spobj->n_fields(); 22.34 if (nf > 0) { 22.35 uint first_ind = spobj->first_index();
23.1 --- a/src/share/vm/prims/methodHandles.cpp Wed Oct 28 10:37:17 2009 -0700 23.2 +++ b/src/share/vm/prims/methodHandles.cpp Thu Oct 29 08:49:31 2009 -0700 23.3 @@ -33,8 +33,7 @@ 23.4 23.5 MethodHandleEntry* MethodHandles::_entries[MethodHandles::_EK_LIMIT] = {NULL}; 23.6 const char* MethodHandles::_entry_names[_EK_LIMIT+1] = { 23.7 - "check_mtype", 23.8 - "wrong_method_type", // what happens when there is a type mismatch 23.9 + "raise_exception", 23.10 "invokestatic", // how a MH emulates invokestatic 23.11 "invokespecial", // ditto for the other invokes... 23.12 "invokevirtual", 23.13 @@ -48,6 +47,7 @@ 23.14 23.15 // starting at _adapter_mh_first: 23.16 "adapter_retype_only", // these are for AMH... 23.17 + "adapter_retype_raw", 23.18 "adapter_check_cast", 23.19 "adapter_prim_to_prim", 23.20 "adapter_ref_to_prim", 23.21 @@ -82,6 +82,8 @@ 23.22 NULL 23.23 }; 23.24 23.25 +jobject MethodHandles::_raise_exception_method; 23.26 + 23.27 #ifdef ASSERT 23.28 bool MethodHandles::spot_check_entry_names() { 23.29 assert(!strcmp(entry_name(_invokestatic_mh), "invokestatic"), ""); 23.30 @@ -157,7 +159,8 @@ 23.31 } 23.32 23.33 methodOop MethodHandles::decode_BoundMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) { 23.34 - assert(mh->klass() == SystemDictionary::BoundMethodHandle_klass(), ""); 23.35 + assert(sun_dyn_BoundMethodHandle::is_instance(mh), ""); 23.36 + assert(mh->klass() != SystemDictionary::AdapterMethodHandle_klass(), ""); 23.37 for (oop bmh = mh;;) { 23.38 // Bound MHs can be stacked to bind several arguments. 23.39 oop target = java_dyn_MethodHandle::vmtarget(bmh); 23.40 @@ -174,10 +177,9 @@ 23.41 } else { 23.42 // Optimized case: binding a receiver to a non-dispatched DMH 23.43 // short-circuits directly to the methodOop. 23.44 + // (It might be another argument besides a receiver also.) 23.45 assert(target->is_method(), "must be a simple method"); 23.46 methodOop m = (methodOop) target; 23.47 - DEBUG_ONLY(int argslot = sun_dyn_BoundMethodHandle::vmargslot(bmh)); 23.48 - assert(argslot == m->size_of_parameters() - 1, "must be initial argument (receiver)"); 23.49 decode_flags_result |= MethodHandles::_dmf_binds_method; 23.50 return m; 23.51 } 23.52 @@ -214,6 +216,9 @@ 23.53 return decode_BoundMethodHandle(mh, receiver_limit_result, decode_flags_result); 23.54 } else if (mhk == SystemDictionary::AdapterMethodHandle_klass()) { 23.55 return decode_AdapterMethodHandle(mh, receiver_limit_result, decode_flags_result); 23.56 + } else if (sun_dyn_BoundMethodHandle::is_subclass(mhk)) { 23.57 + // could be a JavaMethodHandle (but not an adapter MH) 23.58 + return decode_BoundMethodHandle(mh, receiver_limit_result, decode_flags_result); 23.59 } else { 23.60 assert(false, "cannot parse this MH"); 23.61 return NULL; // random MH? 23.62 @@ -366,7 +371,13 @@ 23.63 oop vmtarget = sun_dyn_MemberName::vmtarget(mname); 23.64 int vmindex = sun_dyn_MemberName::vmindex(mname); 23.65 if (vmindex == VM_INDEX_UNINITIALIZED) return NULL; // not resolved 23.66 - return decode_vmtarget(vmtarget, vmindex, NULL, receiver_limit_result, decode_flags_result); 23.67 + methodOop m = decode_vmtarget(vmtarget, vmindex, NULL, receiver_limit_result, decode_flags_result); 23.68 + oop clazz = sun_dyn_MemberName::clazz(mname); 23.69 + if (clazz != NULL && java_lang_Class::is_instance(clazz)) { 23.70 + klassOop klass = java_lang_Class::as_klassOop(clazz); 23.71 + if (klass != NULL) receiver_limit_result = klass; 23.72 + } 23.73 + return m; 23.74 } 23.75 23.76 // An unresolved member name is a mere symbolic reference. 23.77 @@ -789,6 +800,30 @@ 23.78 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), msg); 23.79 } 23.80 23.81 +static const char* always_null_names[] = { 23.82 + "java/lang/Void", 23.83 + "java/lang/Null", 23.84 + //"java/lang/Nothing", 23.85 + "sun/dyn/empty/Empty", 23.86 + NULL 23.87 +}; 23.88 + 23.89 +static bool is_always_null_type(klassOop klass) { 23.90 + if (!Klass::cast(klass)->oop_is_instance()) return false; 23.91 + instanceKlass* ik = instanceKlass::cast(klass); 23.92 + // Must be on the boot class path: 23.93 + if (ik->class_loader() != NULL) return false; 23.94 + // Check the name. 23.95 + symbolOop name = ik->name(); 23.96 + for (int i = 0; ; i++) { 23.97 + const char* test_name = always_null_names[i]; 23.98 + if (test_name == NULL) break; 23.99 + if (name->equals(test_name, (int) strlen(test_name))) 23.100 + return true; 23.101 + } 23.102 + return false; 23.103 +} 23.104 + 23.105 bool MethodHandles::class_cast_needed(klassOop src, klassOop dst) { 23.106 if (src == dst || dst == SystemDictionary::object_klass()) 23.107 return false; // quickest checks 23.108 @@ -805,6 +840,12 @@ 23.109 //srck = Klass::cast(SystemDictionary::object_klass()); 23.110 return true; 23.111 } 23.112 + if (is_always_null_type(src)) { 23.113 + // some source types are known to be never instantiated; 23.114 + // they represent references which are always null 23.115 + // such null references never fail to convert safely 23.116 + return false; 23.117 + } 23.118 return !srck->is_subclass_of(dstk->as_klassOop()); 23.119 } 23.120 23.121 @@ -814,9 +855,15 @@ 23.122 23.123 bool MethodHandles::same_basic_type_for_arguments(BasicType src, 23.124 BasicType dst, 23.125 + bool raw, 23.126 bool for_return) { 23.127 - // return values can always be forgotten: 23.128 - if (for_return && dst == T_VOID) return true; 23.129 + if (for_return) { 23.130 + // return values can always be forgotten: 23.131 + if (dst == T_VOID) return true; 23.132 + if (src == T_VOID) return raw && (dst == T_INT); 23.133 + // We allow caller to receive a garbage int, which is harmless. 23.134 + // This trick is pulled by trusted code (see VerifyType.canPassRaw). 23.135 + } 23.136 assert(src != T_VOID && dst != T_VOID, "should not be here"); 23.137 if (src == dst) return true; 23.138 if (type2size[src] != type2size[dst]) return false; 23.139 @@ -929,8 +976,8 @@ 23.140 const char* err = NULL; 23.141 23.142 int first_ptype_pos = m_needs_receiver ? 1 : 0; 23.143 - if (has_bound_recv && err == NULL) { 23.144 - first_ptype_pos -= 1; 23.145 + if (has_bound_recv) { 23.146 + first_ptype_pos -= 1; // ptypes do not include the bound argument; start earlier in them 23.147 if (m_needs_receiver && bound_recv_type.is_null()) 23.148 { err = "bound receiver is not an object"; goto die; } 23.149 } 23.150 @@ -939,10 +986,10 @@ 23.151 objArrayOop ptypes = java_dyn_MethodType::ptypes(mtype()); 23.152 if (ptypes->length() < first_ptype_pos) 23.153 { err = "receiver argument is missing"; goto die; } 23.154 - if (first_ptype_pos == -1) 23.155 + if (has_bound_recv) 23.156 err = check_method_receiver(m(), bound_recv_type->as_klassOop()); 23.157 else 23.158 - err = check_method_receiver(m(), java_lang_Class::as_klassOop(ptypes->obj_at(0))); 23.159 + err = check_method_receiver(m(), java_lang_Class::as_klassOop(ptypes->obj_at(first_ptype_pos-1))); 23.160 if (err != NULL) goto die; 23.161 } 23.162 23.163 @@ -983,7 +1030,8 @@ 23.164 int insert_argnum, oop insert_type, 23.165 int change_argnum, oop change_type, 23.166 int delete_argnum, 23.167 - oop dst_mtype, int dst_beg, int dst_end) { 23.168 + oop dst_mtype, int dst_beg, int dst_end, 23.169 + bool raw) { 23.170 objArrayOop src_ptypes = java_dyn_MethodType::ptypes(src_mtype); 23.171 objArrayOop dst_ptypes = java_dyn_MethodType::ptypes(dst_mtype); 23.172 23.173 @@ -1042,7 +1090,7 @@ 23.174 if (src_type != dst_type) { 23.175 if (src_type == NULL) return "not enough arguments"; 23.176 if (dst_type == NULL) return "too many arguments"; 23.177 - err = check_argument_type_change(src_type, dst_type, dst_idx); 23.178 + err = check_argument_type_change(src_type, dst_type, dst_idx, raw); 23.179 if (err != NULL) return err; 23.180 } 23.181 } 23.182 @@ -1051,7 +1099,7 @@ 23.183 oop src_rtype = java_dyn_MethodType::rtype(src_mtype); 23.184 oop dst_rtype = java_dyn_MethodType::rtype(dst_mtype); 23.185 if (src_rtype != dst_rtype) { 23.186 - err = check_return_type_change(dst_rtype, src_rtype); // note reversal! 23.187 + err = check_return_type_change(dst_rtype, src_rtype, raw); // note reversal! 23.188 if (err != NULL) return err; 23.189 } 23.190 23.191 @@ -1061,38 +1109,45 @@ 23.192 23.193 23.194 const char* MethodHandles::check_argument_type_change(BasicType src_type, 23.195 - klassOop src_klass, 23.196 - BasicType dst_type, 23.197 - klassOop dst_klass, 23.198 - int argnum) { 23.199 + klassOop src_klass, 23.200 + BasicType dst_type, 23.201 + klassOop dst_klass, 23.202 + int argnum, 23.203 + bool raw) { 23.204 const char* err = NULL; 23.205 + bool for_return = (argnum < 0); 23.206 23.207 // just in case: 23.208 if (src_type == T_ARRAY) src_type = T_OBJECT; 23.209 if (dst_type == T_ARRAY) dst_type = T_OBJECT; 23.210 23.211 // Produce some nice messages if VerifyMethodHandles is turned on: 23.212 - if (!same_basic_type_for_arguments(src_type, dst_type, (argnum < 0))) { 23.213 + if (!same_basic_type_for_arguments(src_type, dst_type, raw, for_return)) { 23.214 if (src_type == T_OBJECT) { 23.215 + if (raw && dst_type == T_INT && is_always_null_type(src_klass)) 23.216 + return NULL; // OK to convert a null pointer to a garbage int 23.217 err = ((argnum >= 0) 23.218 ? "type mismatch: passing a %s for method argument #%d, which expects primitive %s" 23.219 : "type mismatch: returning a %s, but caller expects primitive %s"); 23.220 } else if (dst_type == T_OBJECT) { 23.221 - err = ((argnum < 0) 23.222 + err = ((argnum >= 0) 23.223 ? "type mismatch: passing a primitive %s for method argument #%d, which expects %s" 23.224 : "type mismatch: returning a primitive %s, but caller expects %s"); 23.225 } else { 23.226 - err = ((argnum < 0) 23.227 + err = ((argnum >= 0) 23.228 ? "type mismatch: passing a %s for method argument #%d, which expects %s" 23.229 : "type mismatch: returning a %s, but caller expects %s"); 23.230 } 23.231 - } else if (src_type == T_OBJECT && class_cast_needed(src_klass, dst_klass)) { 23.232 + } else if (src_type == T_OBJECT && dst_type == T_OBJECT && 23.233 + class_cast_needed(src_klass, dst_klass)) { 23.234 if (!class_cast_needed(dst_klass, src_klass)) { 23.235 - err = ((argnum < 0) 23.236 + if (raw) 23.237 + return NULL; // reverse cast is OK; the MH target is trusted to enforce it 23.238 + err = ((argnum >= 0) 23.239 ? "cast required: passing a %s for method argument #%d, which expects %s" 23.240 : "cast required: returning a %s, but caller expects %s"); 23.241 } else { 23.242 - err = ((argnum < 0) 23.243 + err = ((argnum >= 0) 23.244 ? "reference mismatch: passing a %s for method argument #%d, which expects %s" 23.245 : "reference mismatch: returning a %s, but caller expects %s"); 23.246 } 23.247 @@ -1429,10 +1484,10 @@ 23.248 assert(this_pushes == slots_pushed, "BMH pushes one or two stack slots"); 23.249 assert(slots_pushed <= MethodHandlePushLimit, ""); 23.250 } else { 23.251 - int prev_pushes = decode_MethodHandle_stack_pushes(target()); 23.252 - assert(this_pushes == slots_pushed + prev_pushes, "BMH stack motion must be correct"); 23.253 + int target_pushes = decode_MethodHandle_stack_pushes(target()); 23.254 + assert(this_pushes == slots_pushed + target_pushes, "BMH stack motion must be correct"); 23.255 // do not blow the stack; use a Java-based adapter if this limit is exceeded 23.256 - if (slots_pushed + prev_pushes > MethodHandlePushLimit) 23.257 + if (slots_pushed + target_pushes > MethodHandlePushLimit) 23.258 err = "too many bound parameters"; 23.259 } 23.260 } 23.261 @@ -1588,6 +1643,11 @@ 23.262 if (err == NULL) { 23.263 // Check that the src/dest types are supplied if needed. 23.264 switch (ek) { 23.265 + case _adapter_check_cast: 23.266 + if (src != T_OBJECT || dest != T_OBJECT) { 23.267 + err = "adapter requires object src/dest conversion subfields"; 23.268 + } 23.269 + break; 23.270 case _adapter_prim_to_prim: 23.271 if (!is_java_primitive(src) || !is_java_primitive(dest) || src == dest) { 23.272 err = "adapter requires primitive src/dest conversion subfields"; break; 23.273 @@ -1616,9 +1676,9 @@ 23.274 err = "adapter requires src/dest conversion subfields for swap"; break; 23.275 } 23.276 int swap_size = type2size[src]; 23.277 - oop src_mtype = sun_dyn_AdapterMethodHandle::type(target()); 23.278 - oop dest_mtype = sun_dyn_AdapterMethodHandle::type(mh()); 23.279 - int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(src_mtype); 23.280 + oop src_mtype = sun_dyn_AdapterMethodHandle::type(mh()); 23.281 + oop dest_mtype = sun_dyn_AdapterMethodHandle::type(target()); 23.282 + int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(target()); 23.283 int src_slot = argslot; 23.284 int dest_slot = vminfo; 23.285 bool rotate_up = (src_slot > dest_slot); // upward rotation 23.286 @@ -1729,22 +1789,22 @@ 23.287 // Make sure this adapter does not push too deeply. 23.288 int slots_pushed = stack_move / stack_move_unit(); 23.289 int this_vmslots = java_dyn_MethodHandle::vmslots(mh()); 23.290 - int prev_vmslots = java_dyn_MethodHandle::vmslots(target()); 23.291 - if (slots_pushed != (this_vmslots - prev_vmslots)) { 23.292 + int target_vmslots = java_dyn_MethodHandle::vmslots(target()); 23.293 + if (slots_pushed != (target_vmslots - this_vmslots)) { 23.294 err = "stack_move inconsistent with previous and current MethodType vmslots"; 23.295 } else if (slots_pushed > 0) { 23.296 // verify stack_move against MethodHandlePushLimit 23.297 - int prev_pushes = decode_MethodHandle_stack_pushes(target()); 23.298 + int target_pushes = decode_MethodHandle_stack_pushes(target()); 23.299 // do not blow the stack; use a Java-based adapter if this limit is exceeded 23.300 - if (slots_pushed + prev_pushes > MethodHandlePushLimit) { 23.301 + if (slots_pushed + target_pushes > MethodHandlePushLimit) { 23.302 err = "adapter pushes too many parameters"; 23.303 } 23.304 } 23.305 23.306 // While we're at it, check that the stack motion decoder works: 23.307 - DEBUG_ONLY(int prev_pushes = decode_MethodHandle_stack_pushes(target())); 23.308 + DEBUG_ONLY(int target_pushes = decode_MethodHandle_stack_pushes(target())); 23.309 DEBUG_ONLY(int this_pushes = decode_MethodHandle_stack_pushes(mh())); 23.310 - assert(this_pushes == slots_pushed + prev_pushes, "AMH stack motion must be correct"); 23.311 + assert(this_pushes == slots_pushed + target_pushes, "AMH stack motion must be correct"); 23.312 } 23.313 23.314 if (err == NULL && vminfo != 0) { 23.315 @@ -1761,7 +1821,11 @@ 23.316 if (err == NULL) { 23.317 switch (ek) { 23.318 case _adapter_retype_only: 23.319 - err = check_method_type_passthrough(src_mtype(), dst_mtype()); 23.320 + err = check_method_type_passthrough(src_mtype(), dst_mtype(), false); 23.321 + break; 23.322 + 23.323 + case _adapter_retype_raw: 23.324 + err = check_method_type_passthrough(src_mtype(), dst_mtype(), true); 23.325 break; 23.326 23.327 case _adapter_check_cast: 23.328 @@ -1821,6 +1885,7 @@ 23.329 // Now it's time to finish the case analysis and pick a MethodHandleEntry. 23.330 switch (ek_orig) { 23.331 case _adapter_retype_only: 23.332 + case _adapter_retype_raw: 23.333 case _adapter_check_cast: 23.334 case _adapter_dup_args: 23.335 case _adapter_drop_args: 23.336 @@ -1888,8 +1953,7 @@ 23.337 case _adapter_rot_args: 23.338 { 23.339 int swap_slots = type2size[src]; 23.340 - oop mtype = sun_dyn_AdapterMethodHandle::type(mh()); 23.341 - int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(mtype); 23.342 + int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(mh()); 23.343 int src_slot = argslot; 23.344 int dest_slot = vminfo; 23.345 int rotate = (ek_orig == _adapter_swap_args) ? 0 : (src_slot > dest_slot) ? 1 : -1; 23.346 @@ -2133,7 +2197,7 @@ 23.347 guarantee(MethodHandlePushLimit >= 2 && MethodHandlePushLimit <= 0xFF, 23.348 "MethodHandlePushLimit parameter must be in valid range"); 23.349 return MethodHandlePushLimit; 23.350 - case MethodHandles::GC_JVM_STACK_MOVE_LIMIT: 23.351 + case MethodHandles::GC_JVM_STACK_MOVE_UNIT: 23.352 // return number of words per slot, signed according to stack direction 23.353 return MethodHandles::stack_move_unit(); 23.354 } 23.355 @@ -2144,7 +2208,7 @@ 23.356 #ifndef PRODUCT 23.357 #define EACH_NAMED_CON(template) \ 23.358 template(MethodHandles,GC_JVM_PUSH_LIMIT) \ 23.359 - template(MethodHandles,GC_JVM_STACK_MOVE_LIMIT) \ 23.360 + template(MethodHandles,GC_JVM_STACK_MOVE_UNIT) \ 23.361 template(MethodHandles,ETF_HANDLE_OR_METHOD_NAME) \ 23.362 template(MethodHandles,ETF_DIRECT_HANDLE) \ 23.363 template(MethodHandles,ETF_METHOD_NAME) \ 23.364 @@ -2157,6 +2221,7 @@ 23.365 template(sun_dyn_MemberName,MN_SEARCH_INTERFACES) \ 23.366 template(sun_dyn_MemberName,VM_INDEX_UNINITIALIZED) \ 23.367 template(sun_dyn_AdapterMethodHandle,OP_RETYPE_ONLY) \ 23.368 + template(sun_dyn_AdapterMethodHandle,OP_RETYPE_RAW) \ 23.369 template(sun_dyn_AdapterMethodHandle,OP_CHECK_CAST) \ 23.370 template(sun_dyn_AdapterMethodHandle,OP_PRIM_TO_PRIM) \ 23.371 template(sun_dyn_AdapterMethodHandle,OP_REF_TO_PRIM) \ 23.372 @@ -2345,10 +2410,12 @@ 23.373 // note: this explicit warning-producing stuff will be replaced by auto-detection of the JSR 292 classes 23.374 23.375 if (!EnableMethodHandles) { 23.376 - warning("JSR 292 method handles are disabled in this JVM. Use -XX:+EnableMethodHandles to enable."); 23.377 + warning("JSR 292 method handles are disabled in this JVM. Use -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles to enable."); 23.378 return; // bind nothing 23.379 } 23.380 23.381 + bool enable_MH = true; 23.382 + 23.383 { 23.384 ThreadToNativeFromVM ttnfv(thread); 23.385 23.386 @@ -2356,14 +2423,33 @@ 23.387 if (env->ExceptionOccurred()) { 23.388 MethodHandles::set_enabled(false); 23.389 warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); 23.390 + enable_MH = false; 23.391 env->ExceptionClear(); 23.392 - } else { 23.393 - MethodHandles::set_enabled(true); 23.394 } 23.395 } 23.396 23.397 + if (enable_MH) { 23.398 + KlassHandle MHI_klass = SystemDictionaryHandles::MethodHandleImpl_klass(); 23.399 + if (MHI_klass.not_null()) { 23.400 + symbolHandle raiseException_name = oopFactory::new_symbol_handle("raiseException", CHECK); 23.401 + symbolHandle raiseException_sig = oopFactory::new_symbol_handle("(ILjava/lang/Object;Ljava/lang/Object;)V", CHECK); 23.402 + methodOop raiseException_method = instanceKlass::cast(MHI_klass->as_klassOop()) 23.403 + ->find_method(raiseException_name(), raiseException_sig()); 23.404 + if (raiseException_method != NULL && raiseException_method->is_static()) { 23.405 + MethodHandles::set_raise_exception_method(raiseException_method); 23.406 + } else { 23.407 + warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); 23.408 + enable_MH = false; 23.409 + } 23.410 + } 23.411 + } 23.412 + 23.413 + if (enable_MH) { 23.414 + MethodHandles::set_enabled(true); 23.415 + } 23.416 + 23.417 if (!EnableInvokeDynamic) { 23.418 - warning("JSR 292 invokedynamic is disabled in this JVM. Use -XX:+EnableInvokeDynamic to enable."); 23.419 + warning("JSR 292 invokedynamic is disabled in this JVM. Use -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic to enable."); 23.420 return; // bind nothing 23.421 } 23.422
24.1 --- a/src/share/vm/prims/methodHandles.hpp Wed Oct 28 10:37:17 2009 -0700 24.2 +++ b/src/share/vm/prims/methodHandles.hpp Thu Oct 29 08:49:31 2009 -0700 24.3 @@ -32,8 +32,7 @@ 24.4 // See also javaClasses for layouts java_dyn_Method{Handle,Type,Type::Form}. 24.5 public: 24.6 enum EntryKind { 24.7 - _check_mtype, // how a caller calls a MH 24.8 - _wrong_method_type, // what happens when there is a type mismatch 24.9 + _raise_exception, // stub for error generation from other stubs 24.10 _invokestatic_mh, // how a MH emulates invokestatic 24.11 _invokespecial_mh, // ditto for the other invokes... 24.12 _invokevirtual_mh, 24.13 @@ -47,6 +46,7 @@ 24.14 24.15 _adapter_mh_first, // adapter sequence goes here... 24.16 _adapter_retype_only = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY, 24.17 + _adapter_retype_raw = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW, 24.18 _adapter_check_cast = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_CHECK_CAST, 24.19 _adapter_prim_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM, 24.20 _adapter_ref_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM, 24.21 @@ -113,6 +113,8 @@ 24.22 static bool _enabled; 24.23 static MethodHandleEntry* _entries[_EK_LIMIT]; 24.24 static const char* _entry_names[_EK_LIMIT+1]; 24.25 + static jobject _raise_exception_method; 24.26 + 24.27 static bool ek_valid(EntryKind ek) { return (uint)ek < (uint)_EK_LIMIT; } 24.28 static bool conv_op_valid(int op) { return (uint)op < (uint)CONV_OP_LIMIT; } 24.29 24.30 @@ -131,6 +133,16 @@ 24.31 _entries[ek] = me; 24.32 } 24.33 24.34 + static methodOop raise_exception_method() { 24.35 + oop rem = JNIHandles::resolve(_raise_exception_method); 24.36 + assert(rem == NULL || rem->is_method(), ""); 24.37 + return (methodOop) rem; 24.38 + } 24.39 + static void set_raise_exception_method(methodOop rem) { 24.40 + assert(_raise_exception_method == NULL, ""); 24.41 + _raise_exception_method = JNIHandles::make_global(Handle(rem)); 24.42 + } 24.43 + 24.44 static jint adapter_conversion(int conv_op, BasicType src, BasicType dest, 24.45 int stack_move = 0, int vminfo = 0) { 24.46 assert(conv_op_valid(conv_op), "oob"); 24.47 @@ -243,7 +255,7 @@ 24.48 enum { 24.49 // format of query to getConstant: 24.50 GC_JVM_PUSH_LIMIT = 0, 24.51 - GC_JVM_STACK_MOVE_LIMIT = 1, 24.52 + GC_JVM_STACK_MOVE_UNIT = 1, 24.53 24.54 // format of result from getTarget / encode_target: 24.55 ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method) 24.56 @@ -261,7 +273,8 @@ 24.57 int insert_argnum, oop insert_type, 24.58 int change_argnum, oop change_type, 24.59 int delete_argnum, 24.60 - oop dst_mtype, int dst_beg, int dst_end); 24.61 + oop dst_mtype, int dst_beg, int dst_end, 24.62 + bool raw = false); 24.63 static const char* check_method_type_insertion(oop src_mtype, 24.64 int insert_argnum, oop insert_type, 24.65 oop dst_mtype) { 24.66 @@ -278,29 +291,29 @@ 24.67 change_argnum, change_type, 24.68 -1, dst_mtype, 0, -1); 24.69 } 24.70 - static const char* check_method_type_passthrough(oop src_mtype, oop dst_mtype) { 24.71 + static const char* check_method_type_passthrough(oop src_mtype, oop dst_mtype, bool raw) { 24.72 oop no_ref = NULL; 24.73 return check_method_type_change(src_mtype, 0, -1, 24.74 -1, no_ref, -1, no_ref, -1, 24.75 - dst_mtype, 0, -1); 24.76 + dst_mtype, 0, -1, raw); 24.77 } 24.78 24.79 // These checkers operate on pairs of argument or return types: 24.80 static const char* check_argument_type_change(BasicType src_type, klassOop src_klass, 24.81 BasicType dst_type, klassOop dst_klass, 24.82 - int argnum); 24.83 + int argnum, bool raw = false); 24.84 24.85 static const char* check_argument_type_change(oop src_type, oop dst_type, 24.86 - int argnum) { 24.87 + int argnum, bool raw = false) { 24.88 klassOop src_klass = NULL, dst_klass = NULL; 24.89 BasicType src_bt = java_lang_Class::as_BasicType(src_type, &src_klass); 24.90 BasicType dst_bt = java_lang_Class::as_BasicType(dst_type, &dst_klass); 24.91 return check_argument_type_change(src_bt, src_klass, 24.92 - dst_bt, dst_klass, argnum); 24.93 + dst_bt, dst_klass, argnum, raw); 24.94 } 24.95 24.96 - static const char* check_return_type_change(oop src_type, oop dst_type) { 24.97 - return check_argument_type_change(src_type, dst_type, -1); 24.98 + static const char* check_return_type_change(oop src_type, oop dst_type, bool raw = false) { 24.99 + return check_argument_type_change(src_type, dst_type, -1, raw); 24.100 } 24.101 24.102 static const char* check_return_type_change(BasicType src_type, klassOop src_klass, 24.103 @@ -357,9 +370,10 @@ 24.104 TRAPS); 24.105 24.106 static bool same_basic_type_for_arguments(BasicType src, BasicType dst, 24.107 + bool raw = false, 24.108 bool for_return = false); 24.109 - static bool same_basic_type_for_returns(BasicType src, BasicType dst) { 24.110 - return same_basic_type_for_arguments(src, dst, true); 24.111 + static bool same_basic_type_for_returns(BasicType src, BasicType dst, bool raw = false) { 24.112 + return same_basic_type_for_arguments(src, dst, raw, true); 24.113 } 24.114 24.115 enum { // arg_mask values
25.1 --- a/src/share/vm/runtime/vmStructs.cpp Wed Oct 28 10:37:17 2009 -0700 25.2 +++ b/src/share/vm/runtime/vmStructs.cpp Thu Oct 29 08:49:31 2009 -0700 25.3 @@ -594,6 +594,7 @@ 25.4 \ 25.5 nonstatic_field(PcDesc, _pc_offset, int) \ 25.6 nonstatic_field(PcDesc, _scope_decode_offset, int) \ 25.7 + nonstatic_field(PcDesc, _obj_decode_offset, int) \ 25.8 nonstatic_field(PcDesc, _flags, PcDesc::PcDescFlags) \ 25.9 \ 25.10 /***************************************************/ \
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/test/compiler/6891750/Test6891750.java Thu Oct 29 08:49:31 2009 -0700 26.3 @@ -0,0 +1,108 @@ 26.4 +/* 26.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 26.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 26.7 + * 26.8 + * This code is free software; you can redistribute it and/or modify it 26.9 + * under the terms of the GNU General Public License version 2 only, as 26.10 + * published by the Free Software Foundation. 26.11 + * 26.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 26.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 26.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 26.15 + * version 2 for more details (a copy is included in the LICENSE file that 26.16 + * accompanied this code). 26.17 + * 26.18 + * You should have received a copy of the GNU General Public License version 26.19 + * 2 along with this work; if not, write to the Free Software Foundation, 26.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 26.21 + * 26.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 26.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 26.24 + * have any questions. 26.25 + * 26.26 + */ 26.27 + 26.28 +/** 26.29 + * @test 26.30 + * @bug 6891750 26.31 + * @summary deopt blob kills values in O5 26.32 + * 26.33 + * @run main Test6891750 26.34 + */ 26.35 + 26.36 +abstract class Base6891750 extends Thread { 26.37 + abstract public long m(); 26.38 +} 26.39 +class Other6891750 extends Base6891750 { 26.40 + public long m() { 26.41 + return 0; 26.42 + } 26.43 +} 26.44 + 26.45 +public class Test6891750 extends Base6891750 { 26.46 + Base6891750 d; 26.47 + volatile long value = 9; 26.48 + 26.49 + static int limit = 400000; 26.50 + 26.51 + Test6891750() { 26.52 + d = this; 26.53 + 26.54 + } 26.55 + public long m() { 26.56 + return value; 26.57 + } 26.58 + 26.59 + public long test(boolean doit) { 26.60 + if (doit) { 26.61 + long total0 = 0; 26.62 + long total1 = 0; 26.63 + long total2 = 0; 26.64 + long total3 = 0; 26.65 + long total4 = 0; 26.66 + long total5 = 0; 26.67 + long total6 = 0; 26.68 + long total7 = 0; 26.69 + long total8 = 0; 26.70 + long total9 = 0; 26.71 + for (int i = 0; i < limit; i++) { 26.72 + total0 += d.m(); 26.73 + total1 += d.m(); 26.74 + total2 += d.m(); 26.75 + total3 += d.m(); 26.76 + total4 += d.m(); 26.77 + total5 += d.m(); 26.78 + total6 += d.m(); 26.79 + total7 += d.m(); 26.80 + total8 += d.m(); 26.81 + total9 += d.m(); 26.82 + } 26.83 + return total0 + total1 + total2 + total3 + total4 + total5 + total6 + total7 + total8 + total9; 26.84 + } 26.85 + return 0; 26.86 + } 26.87 + 26.88 + public void run() { 26.89 + long result = test(true); 26.90 + for (int i = 0; i < 300; i++) { 26.91 + long result2 = test(true); 26.92 + if (result != result2) { 26.93 + throw new InternalError(result + " != " + result2); 26.94 + } 26.95 + } 26.96 + } 26.97 + 26.98 + public static void main(String[] args) throws Exception { 26.99 + Test6891750 Test6891750 = new Test6891750(); 26.100 + // warm it up 26.101 + for (int i = 0; i < 200000; i++) { 26.102 + Test6891750.test(false); 26.103 + } 26.104 + // set in off running 26.105 + Test6891750.start(); 26.106 + Thread.sleep(2000); 26.107 + 26.108 + // Load a class to invalidate CHA 26.109 + new Other6891750(); 26.110 + } 26.111 +}