Merge

Thu, 29 Oct 2009 08:49:31 -0700

author
cfang
date
Thu, 29 Oct 2009 08:49:31 -0700
changeset 1477
4926bf2d292f
parent 1471
d912f17c1ae4
parent 1476
f875b4f472f7
child 1483
29adffcb6a61
child 1492
f334aec453a1

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&lt;MonitorValue&gt; */
    7.22 +  /** Returns a List&lt;ObjectValue&gt; */
    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 +}

mercurial