changeset 2673:7588156f5cf9

7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244) Reviewed-by: kvn
author never
date Mon, 05 Sep 2011 17:09:05 -0700
parents 7b5c767f229c
children c2d3caa64b3e
files agent/src/share/classes/sun/jvm/hotspot/HSDB.java agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java agent/src/share/classes/sun/jvm/hotspot/code/MethodHandlesAdapterBlob.java agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java agent/src/share/classes/sun/jvm/hotspot/code/RuntimeStub.java agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java agent/src/share/classes/sun/jvm/hotspot/jdi/StackFrameImpl.java agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java agent/src/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java agent/src/share/classes/sun/jvm/hotspot/runtime/VFrame.java agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64Frame.java agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64RegisterMap.java agent/src/share/classes/sun/jvm/hotspot/runtime/linux_amd64/LinuxAMD64JavaThreadPDAccess.java agent/src/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCRicochetFrame.java agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86RicochetFrame.java src/cpu/x86/vm/methodHandles_x86.hpp src/share/vm/c1/c1_LinearScan.cpp src/share/vm/c1/c1_LinearScan.hpp src/share/vm/code/pcDesc.cpp src/share/vm/code/pcDesc.hpp src/share/vm/runtime/sharedRuntime.hpp src/share/vm/runtime/thread.cpp src/share/vm/runtime/thread.hpp src/share/vm/runtime/vmStructs.cpp
diffstat 37 files changed, 714 insertions(+), 765 deletions(-) [+]
line wrap: on
line diff
--- a/agent/src/share/classes/sun/jvm/hotspot/HSDB.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/HSDB.java	Mon Sep 05 17:09:05 2011 -0700
@@ -1740,7 +1740,7 @@
       else if (f.isCompiledFrame())    { tty.print("compiled"); }
       else if (f.isEntryFrame())       { tty.print("entry"); }
       else if (f.isNativeFrame())      { tty.print("native"); }
-      else if (f.isGlueFrame())        { tty.print("glue"); }
+      else if (f.isRuntimeFrame())     { tty.print("runtime"); }
       else { tty.print("external"); }
       tty.print(" frame with PC = " + f.getPC() + ", SP = " + f.getSP() + ", FP = " + f.getFP());
       if (f.isSignalHandlerFrameDbg()) {
--- a/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java	Mon Sep 05 17:09:05 2011 -0700
@@ -102,6 +102,11 @@
   /** On-Stack Replacement method */
   public boolean isOSRMethod()          { return false; }
 
+  public NMethod asNMethodOrNull() {
+    if (isNMethod()) return (NMethod)this;
+    return null;
+  }
+
   // Boundaries
   public Address headerBegin() {
     return addr;
@@ -195,7 +200,7 @@
   }
 
   // Returns true, if the next frame is responsible for GC'ing oops passed as arguments
-  public boolean callerMustGCArguments(JavaThread thread) { return false; }
+  public boolean callerMustGCArguments() { return false; }
 
   public String getName() {
     return CStringUtilities.getString(nameField.getValue(addr));
--- a/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java	Mon Sep 05 17:09:05 2011 -0700
@@ -59,6 +59,7 @@
     virtualConstructor.addMapping("RuntimeStub", RuntimeStub.class);
     virtualConstructor.addMapping("RicochetBlob", RicochetBlob.class);
     virtualConstructor.addMapping("AdapterBlob", AdapterBlob.class);
+    virtualConstructor.addMapping("MethodHandlesAdapterBlob", MethodHandlesAdapterBlob.class);
     virtualConstructor.addMapping("SafepointBlob", SafepointBlob.class);
     virtualConstructor.addMapping("DeoptimizationBlob", DeoptimizationBlob.class);
     if (VM.getVM().isServerCompiler()) {
@@ -126,6 +127,10 @@
       Assert.that(result.blobContains(start) || result.blobContains(start.addOffsetTo(8)),
                                                                     "found wrong CodeBlob");
     }
+    if (result.isRicochetBlob()) {
+      // This should probably be done for other SingletonBlobs
+      return VM.getVM().ricochetBlob();
+    }
     return result;
   }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/code/MethodHandlesAdapterBlob.java	Mon Sep 05 17:09:05 2011 -0700
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.code;
+
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.types.*;
+
+public class MethodHandlesAdapterBlob extends AdapterBlob {
+  static {
+    VM.registerVMInitializedObserver(new Observer() {
+        public void update(Observable o, Object data) {
+          initialize(VM.getVM().getTypeDataBase());
+        }
+      });
+  }
+
+  private static void initialize(TypeDataBase db) {
+    Type type = db.lookupType("MethodHandlesAdapterBlob");
+
+    // FIXME: add any needed fields
+  }
+
+  public MethodHandlesAdapterBlob(Address addr) {
+    super(addr);
+  }
+
+  public boolean isMethodHandlesAdapterBlob() {
+    return true;
+  }
+
+  public String getName() {
+    return "MethodHandlesAdapterBlob: " + super.getName();
+  }
+}
--- a/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java	Mon Sep 05 17:09:05 2011 -0700
@@ -46,6 +46,7 @@
   /** Offsets for different nmethod parts */
   private static CIntegerField exceptionOffsetField;
   private static CIntegerField deoptOffsetField;
+  private static CIntegerField deoptMhOffsetField;
   private static CIntegerField origPCOffsetField;
   private static CIntegerField stubOffsetField;
   private static CIntegerField oopsOffsetField;
@@ -95,6 +96,7 @@
 
     exceptionOffsetField        = type.getCIntegerField("_exception_offset");
     deoptOffsetField            = type.getCIntegerField("_deoptimize_offset");
+    deoptMhOffsetField          = type.getCIntegerField("_deoptimize_mh_offset");
     origPCOffsetField           = type.getCIntegerField("_orig_pc_offset");
     stubOffsetField             = type.getCIntegerField("_stub_offset");
     oopsOffsetField             = type.getCIntegerField("_oops_offset");
@@ -136,10 +138,11 @@
   /** Boundaries for different parts */
   public Address constantsBegin()       { return contentBegin();                                     }
   public Address constantsEnd()         { return getEntryPoint();                                    }
-  public Address instsBegin()           { return codeBegin();                                       }
+  public Address instsBegin()           { return codeBegin();                                        }
   public Address instsEnd()             { return headerBegin().addOffsetTo(getStubOffset());         }
   public Address exceptionBegin()       { return headerBegin().addOffsetTo(getExceptionOffset());    }
-  public Address deoptBegin()           { return headerBegin().addOffsetTo(getDeoptOffset());        }
+  public Address deoptHandlerBegin()    { return headerBegin().addOffsetTo(getDeoptOffset());        }
+  public Address deoptMhHandlerBegin()  { return headerBegin().addOffsetTo(getDeoptMhOffset());      }
   public Address stubBegin()            { return headerBegin().addOffsetTo(getStubOffset());         }
   public Address stubEnd()              { return headerBegin().addOffsetTo(getOopsOffset());         }
   public Address oopsBegin()            { return headerBegin().addOffsetTo(getOopsOffset());         }
@@ -250,6 +253,22 @@
     return (int) scavengeRootStateField.getValue(addr);
   }
 
+  // MethodHandle
+  public boolean isMethodHandleReturn(Address returnPc) {
+    // Hard to read a bit fields from Java and it's only there for performance
+    // so just go directly to the PCDesc
+    // if (!hasMethodHandleInvokes())  return false;
+    PCDesc pd = getPCDescAt(returnPc);
+    if (pd == null)
+      return false;
+    return pd.isMethodHandleInvoke();
+  }
+
+  // Deopt
+  // Return true is the PC is one would expect if the frame is being deopted.
+  public boolean isDeoptPc      (Address pc) { return isDeoptEntry(pc) || isDeoptMhEntry(pc); }
+  public boolean isDeoptEntry   (Address pc) { return pc == deoptHandlerBegin(); }
+  public boolean isDeoptMhEntry (Address pc) { return pc == deoptMhHandlerBegin(); }
 
   /** Tells whether frames described by this nmethod can be
       deoptimized. Note: native wrappers cannot be deoptimized. */
@@ -388,6 +407,7 @@
   private int getEntryBCI()           { return (int) entryBCIField          .getValue(addr); }
   private int getExceptionOffset()    { return (int) exceptionOffsetField   .getValue(addr); }
   private int getDeoptOffset()        { return (int) deoptOffsetField       .getValue(addr); }
+  private int getDeoptMhOffset()      { return (int) deoptMhOffsetField     .getValue(addr); }
   private int getStubOffset()         { return (int) stubOffsetField        .getValue(addr); }
   private int getOopsOffset()         { return (int) oopsOffsetField        .getValue(addr); }
   private int getScopesDataOffset()   { return (int) scopesDataOffsetField  .getValue(addr); }
--- a/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java	Mon Sep 05 17:09:05 2011 -0700
@@ -38,6 +38,9 @@
   private static CIntegerField scopeDecodeOffsetField;
   private static CIntegerField objDecodeOffsetField;
   private static CIntegerField pcFlagsField;
+  private static int reexecuteMask;
+  private static int isMethodHandleInvokeMask;
+  private static int returnOopMask;
 
   static {
     VM.registerVMInitializedObserver(new Observer() {
@@ -54,6 +57,10 @@
     scopeDecodeOffsetField = type.getCIntegerField("_scope_decode_offset");
     objDecodeOffsetField   = type.getCIntegerField("_obj_decode_offset");
     pcFlagsField           = type.getCIntegerField("_flags");
+
+    reexecuteMask            = db.lookupIntConstant("PcDesc::PCDESC_reexecute");
+    isMethodHandleInvokeMask = db.lookupIntConstant("PcDesc::PCDESC_is_method_handle_invoke");
+    returnOopMask            = db.lookupIntConstant("PcDesc::PCDESC_return_oop");
   }
 
   public PCDesc(Address addr) {
@@ -81,7 +88,12 @@
 
   public boolean getReexecute() {
     int flags = (int)pcFlagsField.getValue(addr);
-    return ((flags & 0x1)== 1); //first is the reexecute bit
+    return (flags & reexecuteMask) != 0;
+  }
+
+  public boolean isMethodHandleInvoke() {
+    int flags = (int)pcFlagsField.getValue(addr);
+    return (flags & isMethodHandleInvokeMask) != 0;
   }
 
   public void print(NMethod code) {
--- a/agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java	Mon Sep 05 17:09:05 2011 -0700
@@ -41,11 +41,15 @@
   }
 
   private static void initialize(TypeDataBase db) {
-    // Type type = db.lookupType("RicochetBlob");
+    Type type = db.lookupType("RicochetBlob");
 
-    // FIXME: add any needed fields
+    bounceOffsetField                = type.getCIntegerField("_bounce_offset");
+    exceptionOffsetField             = type.getCIntegerField("_exception_offset");
   }
 
+  private static CIntegerField bounceOffsetField;
+  private static CIntegerField exceptionOffsetField;
+
   public RicochetBlob(Address addr) {
     super(addr);
   }
@@ -53,4 +57,14 @@
   public boolean isRicochetBlob() {
     return true;
   }
+
+  public Address bounceAddr() {
+    return codeBegin().addOffsetTo(bounceOffsetField.getValue(addr));
+  }
+
+  public boolean returnsToBounceAddr(Address pc) {
+    Address bouncePc = bounceAddr();
+    return (pc.equals(bouncePc) || pc.addOffsetTo(Frame.pcReturnOffset()).equals(bouncePc));
+  }
+
 }
--- a/agent/src/share/classes/sun/jvm/hotspot/code/RuntimeStub.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/code/RuntimeStub.java	Mon Sep 05 17:09:05 2011 -0700
@@ -30,6 +30,8 @@
 import sun.jvm.hotspot.types.*;
 
 public class RuntimeStub extends CodeBlob {
+  private static CIntegerField callerMustGCArgumentsField;
+
   static {
     VM.registerVMInitializedObserver(new Observer() {
         public void update(Observable o, Object data) {
@@ -40,6 +42,7 @@
 
   private static void initialize(TypeDataBase db) {
     Type type = db.lookupType("RuntimeStub");
+    callerMustGCArgumentsField                = type.getCIntegerField("_caller_must_gc_arguments");
 
     // FIXME: add any needed fields
   }
@@ -52,6 +55,11 @@
     return true;
   }
 
+  public boolean callerMustGCArguments() {
+    return callerMustGCArgumentsField.getValue(addr) != 0;
+  }
+
+
   public String getName() {
     return "RuntimeStub: " + super.getName();
   }
--- a/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java	Mon Sep 05 17:09:05 2011 -0700
@@ -246,7 +246,7 @@
     }
 
     // Check if caller must update oop argument
-    regMap.setIncludeArgumentOops(cb.callerMustGCArguments(regMap.getThread()));
+    regMap.setIncludeArgumentOops(cb.callerMustGCArguments());
 
     int nofCallee = 0;
     Address[] locs = new Address[2 * REG_COUNT + 1];
--- a/agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java	Mon Sep 05 17:09:05 2011 -0700
@@ -28,11 +28,13 @@
 
 import com.sun.jdi.*;
 
+import sun.jvm.hotspot.memory.SystemDictionary;
 import sun.jvm.hotspot.oops.Instance;
 import sun.jvm.hotspot.oops.InstanceKlass;
 import sun.jvm.hotspot.oops.ArrayKlass;
 import sun.jvm.hotspot.oops.JVMDIClassStatus;
 import sun.jvm.hotspot.oops.Klass;
+import sun.jvm.hotspot.oops.ObjArray;
 import sun.jvm.hotspot.oops.Oop;
 import sun.jvm.hotspot.oops.Symbol;
 import sun.jvm.hotspot.oops.DefaultHeapVisitor;
@@ -53,6 +55,7 @@
     private SoftReference methodsCache;
     private SoftReference allMethodsCache;
     private SoftReference nestedTypesCache;
+    private SoftReference methodInvokesCache;
 
     /* to mark when no info available */
     static final SDE NO_SDE_INFO_MARK = new SDE();
@@ -82,6 +85,27 @@
                 return method;
             }
         }
+        if (ref.getMethodHolder().equals(SystemDictionary.getMethodHandleKlass())) {
+          // invoke methods are generated as needed, so make mirrors as needed
+          List mis = null;
+          if (methodInvokesCache == null) {
+            mis = new ArrayList();
+            methodInvokesCache = new SoftReference(mis);
+          } else {
+            mis = (List)methodInvokesCache.get();
+          }
+          it = mis.iterator();
+          while (it.hasNext()) {
+            MethodImpl method = (MethodImpl)it.next();
+            if (ref.equals(method.ref())) {
+              return method;
+            }
+          }
+
+          MethodImpl method = MethodImpl.createMethodImpl(vm, this, ref);
+          mis.add(method);
+          return method;
+        }
         throw new IllegalArgumentException("Invalid method id: " + ref);
     }
 
--- a/agent/src/share/classes/sun/jvm/hotspot/jdi/StackFrameImpl.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/jdi/StackFrameImpl.java	Mon Sep 05 17:09:05 2011 -0700
@@ -123,6 +123,9 @@
                 Assert.that(values.size() > 0, "this is missing");
             }
             // 'this' at index 0.
+            if (values.get(0).getType() == BasicType.getTConflict()) {
+              return null;
+            }
             OopHandle handle = values.oopHandleAt(0);
             ObjectHeap heap = vm.saObjectHeap();
             thisObject = vm.objectMirror(heap.newOop(handle));
@@ -210,6 +213,8 @@
         validateStackFrame();
         StackValueCollection values = saFrame.getLocals();
         MethodImpl mmm = (MethodImpl)location.method();
+        if (mmm.isNative())
+            return null;
         List argSigs = mmm.argumentSignatures();
         int count = argSigs.size();
         List res = new ArrayList(0);
@@ -231,34 +236,67 @@
         ValueImpl valueImpl = null;
         OopHandle handle = null;
         ObjectHeap heap = vm.saObjectHeap();
-        if (variableType == BasicType.T_BOOLEAN) {
+        if (values.get(ss).getType() == BasicType.getTConflict()) {
+          // Dead locals, so just represent them as a zero of the appropriate type
+          if (variableType == BasicType.T_BOOLEAN) {
+            valueImpl = (BooleanValueImpl) vm.mirrorOf(false);
+          } else if (variableType == BasicType.T_CHAR) {
+            valueImpl = (CharValueImpl) vm.mirrorOf((char)0);
+          } else if (variableType == BasicType.T_FLOAT) {
+            valueImpl = (FloatValueImpl) vm.mirrorOf((float)0);
+          } else if (variableType == BasicType.T_DOUBLE) {
+            valueImpl = (DoubleValueImpl) vm.mirrorOf((double)0);
+          } else if (variableType == BasicType.T_BYTE) {
+            valueImpl = (ByteValueImpl) vm.mirrorOf((byte)0);
+          } else if (variableType == BasicType.T_SHORT) {
+            valueImpl = (ShortValueImpl) vm.mirrorOf((short)0);
+          } else if (variableType == BasicType.T_INT) {
+            valueImpl = (IntegerValueImpl) vm.mirrorOf((int)0);
+          } else if (variableType == BasicType.T_LONG) {
+            valueImpl = (LongValueImpl) vm.mirrorOf((long)0);
+          } else if (variableType == BasicType.T_OBJECT) {
+            // we may have an [Ljava/lang/Object; - i.e., Object[] with the
+            // elements themselves may be arrays because every array is an Object.
+            handle = null;
+            valueImpl = (ObjectReferenceImpl) vm.objectMirror(heap.newOop(handle));
+          } else if (variableType == BasicType.T_ARRAY) {
+            handle = null;
+            valueImpl = vm.arrayMirror((Array)heap.newOop(handle));
+          } else if (variableType == BasicType.T_VOID) {
+            valueImpl = new VoidValueImpl(vm);
+          } else {
+            throw new RuntimeException("Should not read here");
+          }
+        } else {
+          if (variableType == BasicType.T_BOOLEAN) {
             valueImpl = (BooleanValueImpl) vm.mirrorOf(values.booleanAt(ss));
-        } else if (variableType == BasicType.T_CHAR) {
+          } else if (variableType == BasicType.T_CHAR) {
             valueImpl = (CharValueImpl) vm.mirrorOf(values.charAt(ss));
-        } else if (variableType == BasicType.T_FLOAT) {
+          } else if (variableType == BasicType.T_FLOAT) {
             valueImpl = (FloatValueImpl) vm.mirrorOf(values.floatAt(ss));
-        } else if (variableType == BasicType.T_DOUBLE) {
+          } else if (variableType == BasicType.T_DOUBLE) {
             valueImpl = (DoubleValueImpl) vm.mirrorOf(values.doubleAt(ss));
-        } else if (variableType == BasicType.T_BYTE) {
+          } else if (variableType == BasicType.T_BYTE) {
             valueImpl = (ByteValueImpl) vm.mirrorOf(values.byteAt(ss));
-        } else if (variableType == BasicType.T_SHORT) {
+          } else if (variableType == BasicType.T_SHORT) {
             valueImpl = (ShortValueImpl) vm.mirrorOf(values.shortAt(ss));
-        } else if (variableType == BasicType.T_INT) {
+          } else if (variableType == BasicType.T_INT) {
             valueImpl = (IntegerValueImpl) vm.mirrorOf(values.intAt(ss));
-        } else if (variableType == BasicType.T_LONG) {
+          } else if (variableType == BasicType.T_LONG) {
             valueImpl = (LongValueImpl) vm.mirrorOf(values.longAt(ss));
-        } else if (variableType == BasicType.T_OBJECT) {
+          } else if (variableType == BasicType.T_OBJECT) {
             // we may have an [Ljava/lang/Object; - i.e., Object[] with the
             // elements themselves may be arrays because every array is an Object.
             handle = values.oopHandleAt(ss);
             valueImpl = (ObjectReferenceImpl) vm.objectMirror(heap.newOop(handle));
-        } else if (variableType == BasicType.T_ARRAY) {
+          } else if (variableType == BasicType.T_ARRAY) {
             handle = values.oopHandleAt(ss);
             valueImpl = vm.arrayMirror((Array)heap.newOop(handle));
-        } else if (variableType == BasicType.T_VOID) {
+          } else if (variableType == BasicType.T_VOID) {
             valueImpl = new VoidValueImpl(vm);
-        } else {
+          } else {
             throw new RuntimeException("Should not read here");
+          }
         }
 
         return valueImpl;
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java	Mon Sep 05 17:09:05 2011 -0700
@@ -44,6 +44,7 @@
   private static sun.jvm.hotspot.types.OopField systemKlassField;
   private static sun.jvm.hotspot.types.OopField threadKlassField;
   private static sun.jvm.hotspot.types.OopField threadGroupKlassField;
+  private static sun.jvm.hotspot.types.OopField methodHandleKlassField;
 
   static {
     VM.registerVMInitializedObserver(new Observer() {
@@ -69,6 +70,7 @@
     systemKlassField = type.getOopField(WK_KLASS("System_klass"));
     threadKlassField = type.getOopField(WK_KLASS("Thread_klass"));
     threadGroupKlassField = type.getOopField(WK_KLASS("ThreadGroup_klass"));
+    methodHandleKlassField = type.getOopField(WK_KLASS("MethodHandle_klass"));
   }
 
   // This WK functions must follow the definitions in systemDictionary.hpp:
@@ -127,6 +129,10 @@
     return (InstanceKlass) newOop(systemKlassField.getValue());
   }
 
+  public static InstanceKlass getMethodHandleKlass() {
+    return (InstanceKlass) newOop(methodHandleKlassField.getValue());
+  }
+
   public InstanceKlass getAbstractOwnableSynchronizerKlass() {
     return (InstanceKlass) find("java/util/concurrent/locks/AbstractOwnableSynchronizer",
                                 null, null);
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java	Mon Sep 05 17:09:05 2011 -0700
@@ -93,6 +93,8 @@
   }
 
   public StackValueCollection getLocals() {
+    if (getScope() == null)
+      return new StackValueCollection();
     List scvList = getScope().getLocals();
     if (scvList == null)
       return new StackValueCollection();
@@ -108,6 +110,8 @@
   }
 
   public StackValueCollection getExpressions() {
+    if (getScope() == null)
+      return new StackValueCollection();
     List scvList = getScope().getExpressions();
     if (scvList == null)
       return new StackValueCollection();
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java	Mon Sep 05 17:09:05 2011 -0700
@@ -33,6 +33,7 @@
 import sun.jvm.hotspot.debugger.*;
 import sun.jvm.hotspot.interpreter.*;
 import sun.jvm.hotspot.oops.*;
+import sun.jvm.hotspot.runtime.sparc.SPARCFrame;
 import sun.jvm.hotspot.types.*;
 import sun.jvm.hotspot.utilities.*;
 
@@ -74,11 +75,19 @@
   /** Size of constMethodOopDesc for computing BCI from BCP (FIXME: hack) */
   private static long    constMethodOopDescSize;
 
+  private static int pcReturnOffset;
+
+  public static int pcReturnOffset() {
+    return pcReturnOffset;
+  }
+
   private static synchronized void initialize(TypeDataBase db) {
     Type constMethodOopType = db.lookupType("constMethodOopDesc");
     // FIXME: not sure whether alignment here is correct or how to
     // force it (round up to address size?)
     constMethodOopDescSize = constMethodOopType.getSize();
+
+    pcReturnOffset = db.lookupIntConstant("frame::pc_return_offset").intValue();
   }
 
   protected int bcpToBci(Address bcp, ConstMethod cm) {
@@ -106,6 +115,10 @@
   public void    setPC(Address newpc) { pc = newpc; }
   public boolean isDeoptimized()      { return deoptimized; }
 
+  public CodeBlob cb() {
+    return VM.getVM().getCodeCache().findBlob(getPC());
+  }
+
   public abstract Address getSP();
   public abstract Address getID();
   public abstract Address getFP();
@@ -134,6 +147,12 @@
     }
   }
 
+  public boolean isRicochetFrame() {
+    CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC());
+    RicochetBlob rcb = VM.getVM().ricochetBlob();
+    return (cb == rcb && rcb != null && rcb.returnsToBounceAddr(getPC()));
+  }
+
   public boolean isCompiledFrame() {
     if (Assert.ASSERTS_ENABLED) {
       Assert.that(!VM.getVM().isCore(), "noncore builds only");
@@ -142,7 +161,7 @@
     return (cb != null && cb.isJavaMethod());
   }
 
-  public boolean isGlueFrame() {
+  public boolean isRuntimeFrame() {
     if (Assert.ASSERTS_ENABLED) {
       Assert.that(!VM.getVM().isCore(), "noncore builds only");
     }
@@ -197,7 +216,8 @@
   public Frame realSender(RegisterMap map) {
     if (!VM.getVM().isCore()) {
       Frame result = sender(map);
-      while (result.isGlueFrame()) {
+      while (result.isRuntimeFrame() ||
+             result.isRicochetFrame()) {
         result = result.sender(map);
       }
       return result;
@@ -611,6 +631,9 @@
     if (Assert.ASSERTS_ENABLED) {
       Assert.that(cb != null, "sanity check");
     }
+    if (cb == VM.getVM().ricochetBlob()) {
+      oopsRicochetDo(oopVisitor, regMap);
+    }
     if (cb.getOopMaps() != null) {
       OopMapSet.oopsDo(this, cb, regMap, oopVisitor, VM.getVM().isDebugging());
 
@@ -627,6 +650,10 @@
     //    }
   }
 
+  private void oopsRicochetDo      (AddressVisitor oopVisitor, RegisterMap regMap) {
+    // XXX Empty for now
+  }
+
   // FIXME: implement the above routines, plus add
   // oops_interpreted_arguments_do and oops_compiled_arguments_do
 }
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java	Mon Sep 05 17:09:05 2011 -0700
@@ -128,14 +128,14 @@
       }
 
       // dynamic part - we just compare the frame pointer
-      if (! getFrame().getFP().equals(other.getFrame().getFP())) {
+      if (! getFrame().equals(other.getFrame())) {
           return false;
       }
       return true;
   }
 
   public int hashCode() {
-      return getMethod().hashCode() ^ getBCI() ^ getFrame().getFP().hashCode();
+      return getMethod().hashCode() ^ getBCI() ^ getFrame().hashCode();
   }
 
   /** Structural compare */
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java	Mon Sep 05 17:09:05 2011 -0700
@@ -100,7 +100,7 @@
 
   public int hashCode() {
     if (type == BasicType.getTObject()) {
-      return handleValue.hashCode();
+      return handleValue != null ? handleValue.hashCode() : 5;
     } else {
       // Returns 0 for conflict type
       return (int) integerValue;
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/VFrame.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/VFrame.java	Mon Sep 05 17:09:05 2011 -0700
@@ -77,7 +77,7 @@
           return new CompiledVFrame(f, regMap, thread, scope, mayBeImprecise);
         }
 
-        if (f.isGlueFrame()) {
+        if (f.isRuntimeFrame()) {
           // This is a conversion frame. Skip this frame and try again.
           RegisterMap tempMap = regMap.copy();
           Frame s = f.sender(tempMap);
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java	Mon Sep 05 17:09:05 2011 -0700
@@ -30,6 +30,7 @@
 import java.util.regex.*;
 import sun.jvm.hotspot.code.*;
 import sun.jvm.hotspot.c1.*;
+import sun.jvm.hotspot.code.*;
 import sun.jvm.hotspot.debugger.*;
 import sun.jvm.hotspot.interpreter.*;
 import sun.jvm.hotspot.memory.*;
@@ -85,6 +86,9 @@
   private Interpreter  interpreter;
   private StubRoutines stubRoutines;
   private Bytes        bytes;
+
+  private RicochetBlob ricochetBlob;
+
   /** Flags indicating whether we are attached to a core, C1, or C2 build */
   private boolean      usingClientCompiler;
   private boolean      usingServerCompiler;
@@ -618,6 +622,18 @@
     return stubRoutines;
   }
 
+  public RicochetBlob ricochetBlob() {
+    if (ricochetBlob == null) {
+      Type ricochetType  = db.lookupType("SharedRuntime");
+      AddressField ricochetBlobAddress = ricochetType.getAddressField("_ricochet_blob");
+      Address addr = ricochetBlobAddress.getValue();
+      if (addr != null) {
+        ricochetBlob = new RicochetBlob(addr);
+      }
+    }
+    return ricochetBlob;
+  }
+
   public VMRegImpl getVMRegImplInfo() {
     if (vmregImpl == null) {
       vmregImpl = new VMRegImpl();
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java	Mon Sep 05 17:09:05 2011 -0700
@@ -29,6 +29,7 @@
 import sun.jvm.hotspot.code.*;
 import sun.jvm.hotspot.interpreter.*;
 import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.runtime.x86.*;
 
 /** <P> Should be able to be used on all amd64 platforms we support
     (Linux/amd64) to implement JavaThread's
@@ -123,7 +124,7 @@
              offset += vm.getAddressSize()) {
           try {
             Address curSP = sp.addOffsetTo(offset);
-            Frame frame = new AMD64Frame(curSP, null, pc);
+            Frame frame = new X86Frame(curSP, null, pc);
             RegisterMap map = thread.newRegisterMap(false);
             while (frame != null) {
               if (frame.isEntryFrame() && frame.entryFrameIsFirst()) {
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64Frame.java	Sat Sep 03 14:03:54 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,528 +0,0 @@
-/*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.runtime.amd64;
-
-import java.util.*;
-import sun.jvm.hotspot.code.*;
-import sun.jvm.hotspot.compiler.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.types.*;
-import sun.jvm.hotspot.utilities.*;
-
-/** Specialization of and implementation of abstract methods of the
-    Frame class for the amd64 CPU. */
-
-public class AMD64Frame extends Frame {
-  private static final boolean DEBUG;
-  static {
-    DEBUG = System.getProperty("sun.jvm.hotspot.runtime.amd64.AMD64Frame.DEBUG") != null;
-  }
-
-  // refer to frame_amd64.hpp
-  private static final int PC_RETURN_OFFSET           =  0;
-  // All frames
-  private static final int LINK_OFFSET                =  0;
-  private static final int RETURN_ADDR_OFFSET         =  1;
-  private static final int SENDER_SP_OFFSET           =  2;
-
-  // Interpreter frames
-  private static final int INTERPRETER_FRAME_MIRROR_OFFSET    =  2; // for native calls only
-  private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -1;
-  private static final int INTERPRETER_FRAME_LAST_SP_OFFSET   = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1;
-  private static final int INTERPRETER_FRAME_METHOD_OFFSET    = INTERPRETER_FRAME_LAST_SP_OFFSET - 1;
-  private static       int INTERPRETER_FRAME_MDX_OFFSET;         // Non-core builds only
-  private static       int INTERPRETER_FRAME_CACHE_OFFSET;
-  private static       int INTERPRETER_FRAME_LOCALS_OFFSET;
-  private static       int INTERPRETER_FRAME_BCX_OFFSET;
-  private static       int INTERPRETER_FRAME_INITIAL_SP_OFFSET;
-  private static       int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET;
-  private static       int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET;
-
-  // Entry frames
-  private static final int ENTRY_FRAME_CALL_WRAPPER_OFFSET   =  -6;
-
-  // Native frames
-  private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET =  2;
-
-  static {
-    VM.registerVMInitializedObserver(new Observer() {
-        public void update(Observable o, Object data) {
-          initialize(VM.getVM().getTypeDataBase());
-        }
-      });
-  }
-
-  private static synchronized void initialize(TypeDataBase db) {
-    if (VM.getVM().isCore()) {
-      INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1;
-    } else {
-      INTERPRETER_FRAME_MDX_OFFSET   = INTERPRETER_FRAME_METHOD_OFFSET - 1;
-      INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1;
-    }
-    INTERPRETER_FRAME_LOCALS_OFFSET               = INTERPRETER_FRAME_CACHE_OFFSET - 1;
-    INTERPRETER_FRAME_BCX_OFFSET                  = INTERPRETER_FRAME_LOCALS_OFFSET - 1;
-    INTERPRETER_FRAME_INITIAL_SP_OFFSET           = INTERPRETER_FRAME_BCX_OFFSET - 1;
-    INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET    = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
-    INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
-  }
-
-  // an additional field beyond sp and pc:
-  Address raw_fp; // frame pointer
-  private Address raw_unextendedSP;
-
-  private AMD64Frame() {
-  }
-
-  private void adjustForDeopt() {
-    if ( pc != null) {
-      // Look for a deopt pc and if it is deopted convert to original pc
-      CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
-      if (cb != null && cb.isJavaMethod()) {
-        NMethod nm = (NMethod) cb;
-        if (pc.equals(nm.deoptBegin())) {
-          // adjust pc if frame is deoptimized.
-          if (Assert.ASSERTS_ENABLED) {
-            Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
-          }
-          pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
-          deoptimized = true;
-        }
-      }
-    }
-  }
-
-  public AMD64Frame(Address raw_sp, Address raw_fp, Address pc) {
-    this.raw_sp = raw_sp;
-    this.raw_unextendedSP = raw_sp;
-    this.raw_fp = raw_fp;
-    this.pc = pc;
-
-    // Frame must be fully constructed before this call
-    adjustForDeopt();
-
-    if (DEBUG) {
-      System.out.println("AMD64Frame(sp, fp, pc): " + this);
-      dumpStack();
-    }
-  }
-
-  public AMD64Frame(Address raw_sp, Address raw_fp) {
-    this.raw_sp = raw_sp;
-    this.raw_unextendedSP = raw_sp;
-    this.raw_fp = raw_fp;
-    this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
-
-    // Frame must be fully constructed before this call
-    adjustForDeopt();
-
-    if (DEBUG) {
-      System.out.println("AMD64Frame(sp, fp): " + this);
-      dumpStack();
-    }
-  }
-
-  // This constructor should really take the unextended SP as an arg
-  // but then the constructor is ambiguous with constructor that takes
-  // a PC so take an int and convert it.
-  public AMD64Frame(Address raw_sp, Address raw_fp, long extension) {
-    this.raw_sp = raw_sp;
-    if ( raw_sp == null) {
-      this.raw_unextendedSP = null;
-    } else {
-      this.raw_unextendedSP = raw_sp.addOffsetTo(extension);
-    }
-    this.raw_fp = raw_fp;
-    this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
-
-    // Frame must be fully constructed before this call
-    adjustForDeopt();
-
-    if (DEBUG) {
-      System.out.println("AMD64Frame(sp, fp, extension): " + this);
-      dumpStack();
-    }
-
-  }
-
-  public Object clone() {
-    AMD64Frame frame = new AMD64Frame();
-    frame.raw_sp = raw_sp;
-    frame.raw_unextendedSP = raw_unextendedSP;
-    frame.raw_fp = raw_fp;
-    frame.pc = pc;
-    frame.deoptimized = deoptimized;
-    return frame;
-  }
-
-  public boolean equals(Object arg) {
-    if (arg == null) {
-      return false;
-    }
-
-    if (!(arg instanceof AMD64Frame)) {
-      return false;
-    }
-
-    AMD64Frame other = (AMD64Frame) arg;
-
-    return (AddressOps.equal(getSP(), other.getSP()) &&
-            AddressOps.equal(getFP(), other.getFP()) &&
-            AddressOps.equal(getUnextendedSP(), other.getUnextendedSP()) &&
-            AddressOps.equal(getPC(), other.getPC()));
-  }
-
-  public int hashCode() {
-    if (raw_sp == null) {
-      return 0;
-    }
-
-    return raw_sp.hashCode();
-  }
-
-  public String toString() {
-    return "sp: " + (getSP() == null? "null" : getSP().toString()) +
-         ", unextendedSP: " + (getUnextendedSP() == null? "null" : getUnextendedSP().toString()) +
-         ", fp: " + (getFP() == null? "null" : getFP().toString()) +
-         ", pc: " + (pc == null? "null" : pc.toString());
-  }
-
-  // accessors for the instance variables
-  public Address getFP() { return raw_fp; }
-  public Address getSP() { return raw_sp; }
-  public Address getID() { return raw_sp; }
-
-  // FIXME: not implemented yet (should be done for Solaris/AMD64)
-  public boolean isSignalHandlerFrameDbg() { return false; }
-  public int     getSignalNumberDbg()      { return 0;     }
-  public String  getSignalNameDbg()        { return null;  }
-
-  public boolean isInterpretedFrameValid() {
-    if (Assert.ASSERTS_ENABLED) {
-      Assert.that(isInterpretedFrame(), "Not an interpreted frame");
-    }
-
-    // These are reasonable sanity checks
-    if (getFP() == null || getFP().andWithMask(0x3) != null) {
-      return false;
-    }
-
-    if (getSP() == null || getSP().andWithMask(0x3) != null) {
-      return false;
-    }
-
-    if (getFP().addOffsetTo(INTERPRETER_FRAME_INITIAL_SP_OFFSET * VM.getVM().getAddressSize()).lessThan(getSP())) {
-      return false;
-    }
-
-    // These are hacks to keep us out of trouble.
-    // The problem with these is that they mask other problems
-    if (getFP().lessThanOrEqual(getSP())) {
-      // this attempts to deal with unsigned comparison above
-      return false;
-    }
-
-    if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) {
-      // stack frames shouldn't be large.
-      return false;
-    }
-
-    return true;
-  }
-
-  // FIXME: not applicable in current system
-  //  void    patch_pc(Thread* thread, address pc);
-
-  public Frame sender(RegisterMap regMap, CodeBlob cb) {
-    AMD64RegisterMap map = (AMD64RegisterMap) regMap;
-
-    if (Assert.ASSERTS_ENABLED) {
-      Assert.that(map != null, "map must be set");
-    }
-
-    // Default is we done have to follow them. The sender_for_xxx will
-    // update it accordingly
-    map.setIncludeArgumentOops(false);
-
-    if (isEntryFrame())       return senderForEntryFrame(map);
-    if (isInterpretedFrame()) return senderForInterpreterFrame(map);
-
-
-    if (!VM.getVM().isCore()) {
-      if(cb == null) {
-        cb = VM.getVM().getCodeCache().findBlob(getPC());
-      } else {
-        if (Assert.ASSERTS_ENABLED) {
-          Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same");
-        }
-      }
-
-      if (cb != null) {
-         return senderForCompiledFrame(map, cb);
-      }
-    }
-
-    // Must be native-compiled frame, i.e. the marshaling code for native
-    // methods that exists in the core system.
-    return new AMD64Frame(getSenderSP(), getLink(), getSenderPC());
-  }
-
-  private Frame senderForEntryFrame(AMD64RegisterMap map) {
-    if (Assert.ASSERTS_ENABLED) {
-      Assert.that(map != null, "map must be set");
-    }
-    // Java frame called from C; skip all C frames and return top C
-    // frame of that chunk as the sender
-    AMD64JavaCallWrapper jcw = (AMD64JavaCallWrapper) getEntryFrameCallWrapper();
-    if (Assert.ASSERTS_ENABLED) {
-      Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero");
-      Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack");
-    }
-    AMD64Frame fr;
-    if (jcw.getLastJavaPC() != null) {
-      fr = new AMD64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC());
-    } else {
-      fr = new AMD64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP());
-    }
-    map.clear();
-    if (Assert.ASSERTS_ENABLED) {
-      Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
-    }
-    return fr;
-  }
-
-  private Frame senderForInterpreterFrame(AMD64RegisterMap map) {
-    Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
-    Address sp = addressOfStackSlot(SENDER_SP_OFFSET);
-    // We do not need to update the callee-save register mapping because above
-    // us is either another interpreter frame or a converter-frame, but never
-    // directly a compiled frame.
-    // 11/24/04 SFG. This is no longer true after adapter were removed. However at the moment
-    // C2 no longer uses callee save register for java calls so there are no callee register
-    // to find.
-    return new AMD64Frame(sp, getLink(), unextendedSP.minus(sp));
-  }
-
-  private Frame senderForCompiledFrame(AMD64RegisterMap map, CodeBlob cb) {
-    //
-    // NOTE: some of this code is (unfortunately) duplicated in AMD64CurrentFrameGuess
-    //
-
-    if (Assert.ASSERTS_ENABLED) {
-      Assert.that(map != null, "map must be set");
-    }
-
-    // frame owned by optimizing compiler
-    Address        sender_sp = null;
-
-
-    if (VM.getVM().isClientCompiler()) {
-      sender_sp        = addressOfStackSlot(SENDER_SP_OFFSET);
-    } else {
-      if (Assert.ASSERTS_ENABLED) {
-        Assert.that(cb.getFrameSize() >= 0, "Compiled by Compiler1: do not use");
-      }
-      sender_sp = getUnextendedSP().addOffsetTo(cb.getFrameSize());
-    }
-
-    // On Intel the return_address is always the word on the stack
-    Address sender_pc = sender_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
-
-    if (map.getUpdateMap() && cb.getOopMaps() != null) {
-      OopMapSet.updateRegisterMap(this, cb, map, true);
-    }
-
-    if (VM.getVM().isClientCompiler()) {
-      // Move this here for C1 and collecting oops in arguments (According to Rene)
-      map.setIncludeArgumentOops(cb.callerMustGCArguments(map.getThread()));
-    }
-
-    Address saved_fp = null;
-    if (VM.getVM().isClientCompiler()) {
-      saved_fp = getFP().getAddressAt(0);
-    } else if (VM.getVM().isServerCompiler() &&
-               (VM.getVM().getInterpreter().contains(sender_pc) ||
-               VM.getVM().getStubRoutines().returnsToCallStub(sender_pc))) {
-      // C2 prologue saves EBP in the usual place.
-      // however only use it if the sender had link infomration in it.
-      saved_fp = sender_sp.getAddressAt(-2 * VM.getVM().getAddressSize());
-    }
-
-    return new AMD64Frame(sender_sp, saved_fp, sender_pc);
-  }
-
-  protected boolean hasSenderPD() {
-    // FIXME
-    // Check for null ebp? Need to do some tests.
-    return true;
-  }
-
-  public long frameSize() {
-    return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize());
-  }
-
-  public Address getLink() {
-    return addressOfStackSlot(LINK_OFFSET).getAddressAt(0);
-  }
-
-  // FIXME: not implementable yet
-  //inline void      frame::set_link(intptr_t* addr)  { *(intptr_t **)addr_at(link_offset) = addr; }
-
-  public Address getUnextendedSP() { return raw_unextendedSP; }
-
-  // Return address:
-  public Address getSenderPCAddr() { return addressOfStackSlot(RETURN_ADDR_OFFSET); }
-  public Address getSenderPC()     { return getSenderPCAddr().getAddressAt(0);      }
-
-  // return address of param, zero origin index.
-  public Address getNativeParamAddr(int idx) {
-    return addressOfStackSlot(NATIVE_FRAME_INITIAL_PARAM_OFFSET + idx);
-  }
-
-  public Address getSenderSP()     { return addressOfStackSlot(SENDER_SP_OFFSET); }
-
-  public Address compiledArgumentToLocationPD(VMReg reg, RegisterMap regMap, int argSize) {
-    if (VM.getVM().isCore() || VM.getVM().isClientCompiler()) {
-      throw new RuntimeException("Should not reach here");
-    }
-
-    return oopMapRegToLocation(reg, regMap);
-  }
-
-  public Address addressOfInterpreterFrameLocals() {
-    return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET);
-  }
-
-  private Address addressOfInterpreterFrameBCX() {
-    return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET);
-  }
-
-  public int getInterpreterFrameBCI() {
-    // FIXME: this is not atomic with respect to GC and is unsuitable
-    // for use in a non-debugging, or reflective, system. Need to
-    // figure out how to express this.
-    Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0);
-    OopHandle methodHandle = addressOfInterpreterFrameMethod().getOopHandleAt(0);
-    Method method = (Method) VM.getVM().getObjectHeap().newOop(methodHandle);
-    return (int) bcpToBci(bcp, method);
-  }
-
-  public Address addressOfInterpreterFrameMDX() {
-    return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET);
-  }
-
-  // FIXME
-  //inline int frame::interpreter_frame_monitor_size() {
-  //  return BasicObjectLock::size();
-  //}
-
-  // expression stack
-  // (the max_stack arguments are used by the GC; see class FrameClosure)
-
-  public Address addressOfInterpreterFrameExpressionStack() {
-    Address monitorEnd = interpreterFrameMonitorEnd().address();
-    return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize());
-  }
-
-  public int getInterpreterFrameExpressionStackDirection() { return -1; }
-
-  // top of expression stack
-  public Address addressOfInterpreterFrameTOS() {
-    return getSP();
-  }
-
-  /** Expression stack from top down */
-  public Address addressOfInterpreterFrameTOSAt(int slot) {
-    return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize());
-  }
-
-  public Address getInterpreterFrameSenderSP() {
-    if (Assert.ASSERTS_ENABLED) {
-      Assert.that(isInterpretedFrame(), "interpreted frame expected");
-    }
-    return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
-  }
-
-  // Monitors
-  public BasicObjectLock interpreterFrameMonitorBegin() {
-    return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET));
-  }
-
-  public BasicObjectLock interpreterFrameMonitorEnd() {
-    Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0);
-    if (Assert.ASSERTS_ENABLED) {
-      // make sure the pointer points inside the frame
-      Assert.that(AddressOps.gt(getFP(), result), "result must <  than frame pointer");
-      Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer");
-    }
-    return new BasicObjectLock(result);
-  }
-
-  public int interpreterFrameMonitorSize() {
-    return BasicObjectLock.size();
-  }
-
-  // Method
-  public Address addressOfInterpreterFrameMethod() {
-    return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET);
-  }
-
-  // Constant pool cache
-  public Address addressOfInterpreterFrameCPCache() {
-    return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET);
-  }
-
-  // Entry frames
-  public JavaCallWrapper getEntryFrameCallWrapper() {
-    return new AMD64JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0));
-  }
-
-  protected Address addressOfSavedOopResult() {
-    // offset is 2 for compiler2 and 3 for compiler1
-    return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) *
-                               VM.getVM().getAddressSize());
-  }
-
-  protected Address addressOfSavedReceiver() {
-    return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize());
-  }
-
-  private void dumpStack() {
-    if (getFP() != null) {
-      for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize());
-           AddressOps.lte(addr, getFP().addOffsetTo(5 * VM.getVM().getAddressSize()));
-           addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
-        System.out.println(addr + ": " + addr.getAddressAt(0));
-      }
-    } else {
-      for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize());
-           AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize()));
-           addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
-        System.out.println(addr + ": " + addr.getAddressAt(0));
-      }
-    }
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64RegisterMap.java	Sat Sep 03 14:03:54 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.runtime.amd64;
-
-import sun.jvm.hotspot.asm.amd64.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.runtime.*;
-
-public class AMD64RegisterMap extends RegisterMap {
-
-  /** This is the only public constructor */
-  public AMD64RegisterMap(JavaThread thread, boolean updateMap) {
-    super(thread, updateMap);
-  }
-
-  protected AMD64RegisterMap(RegisterMap map) {
-    super(map);
-  }
-
-  public Object clone() {
-    AMD64RegisterMap retval = new AMD64RegisterMap(this);
-    return retval;
-  }
-
-  // no PD state to clear or copy:
-  protected void clearPD() {}
-  protected void initializePD() {}
-  protected void initializeFromPD(RegisterMap map) {}
-  protected Address getLocationPD(VMReg reg) { return null; }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/linux_amd64/LinuxAMD64JavaThreadPDAccess.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/linux_amd64/LinuxAMD64JavaThreadPDAccess.java	Mon Sep 05 17:09:05 2011 -0700
@@ -30,6 +30,7 @@
 import sun.jvm.hotspot.debugger.amd64.*;
 import sun.jvm.hotspot.runtime.*;
 import sun.jvm.hotspot.runtime.amd64.*;
+import sun.jvm.hotspot.runtime.x86.*;
 import sun.jvm.hotspot.types.*;
 import sun.jvm.hotspot.utilities.*;
 
@@ -80,11 +81,11 @@
     if (fp == null) {
       return null; // no information
     }
-    return new AMD64Frame(thread.getLastJavaSP(), fp);
+    return new X86Frame(thread.getLastJavaSP(), fp);
   }
 
   public    RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
-    return new AMD64RegisterMap(thread, updateMap);
+    return new X86RegisterMap(thread, updateMap);
   }
 
   public    Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
@@ -95,9 +96,9 @@
       return null;
     }
     if (guesser.getPC() == null) {
-      return new AMD64Frame(guesser.getSP(), guesser.getFP());
+      return new X86Frame(guesser.getSP(), guesser.getFP());
     } else {
-      return new AMD64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
+      return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
     }
   }
 
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java	Mon Sep 05 17:09:05 2011 -0700
@@ -30,6 +30,7 @@
 import sun.jvm.hotspot.debugger.amd64.*;
 import sun.jvm.hotspot.runtime.*;
 import sun.jvm.hotspot.runtime.amd64.*;
+import sun.jvm.hotspot.runtime.x86.*;
 import sun.jvm.hotspot.types.*;
 import sun.jvm.hotspot.utilities.*;
 
@@ -84,14 +85,14 @@
         }
         Address pc =  thread.getLastJavaPC();
         if ( pc != null ) {
-            return new AMD64Frame(thread.getLastJavaSP(), fp, pc);
+            return new X86Frame(thread.getLastJavaSP(), fp, pc);
         } else {
-            return new AMD64Frame(thread.getLastJavaSP(), fp);
+            return new X86Frame(thread.getLastJavaSP(), fp);
         }
     }
 
     public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
-        return new AMD64RegisterMap(thread, updateMap);
+        return new X86RegisterMap(thread, updateMap);
     }
 
     public Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
@@ -102,9 +103,9 @@
             return null;
         }
         if (guesser.getPC() == null) {
-            return new AMD64Frame(guesser.getSP(), guesser.getFP());
+            return new X86Frame(guesser.getSP(), guesser.getFP());
         } else {
-            return new AMD64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
+            return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
         }
     }
 
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java	Mon Sep 05 17:09:05 2011 -0700
@@ -236,7 +236,7 @@
       CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
       if (cb != null && cb.isJavaMethod()) {
         NMethod nm = (NMethod) cb;
-        if (pc.equals(nm.deoptBegin())) {
+        if (pc.equals(nm.deoptHandlerBegin())) {
           // adjust pc if frame is deoptimized.
           pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
           deoptimized = true;
@@ -559,49 +559,46 @@
       }
     }
 
-    if (!VM.getVM().isCore()) {
-      // Note:  The version of this operation on any platform with callee-save
-      //        registers must update the register map (if not null).
-      //        In order to do this correctly, the various subtypes of
-      //        of frame (interpreted, compiled, glue, native),
-      //        must be distinguished.  There is no need on SPARC for
-      //        such distinctions, because all callee-save registers are
-      //        preserved for all frames via SPARC-specific mechanisms.
-      //
-      //        *** HOWEVER, *** if and when we make any floating-point
-      //        registers callee-saved, then we will have to copy over
-      //        the RegisterMap update logic from the Intel code.
+    // Note:  The version of this operation on any platform with callee-save
+    //        registers must update the register map (if not null).
+    //        In order to do this correctly, the various subtypes of
+    //        of frame (interpreted, compiled, glue, native),
+    //        must be distinguished.  There is no need on SPARC for
+    //        such distinctions, because all callee-save registers are
+    //        preserved for all frames via SPARC-specific mechanisms.
+    //
+    //        *** HOWEVER, *** if and when we make any floating-point
+    //        registers callee-saved, then we will have to copy over
+    //        the RegisterMap update logic from the Intel code.
 
+    if (isRicochetFrame()) return senderForRicochetFrame(map);
 
-      // The constructor of the sender must know whether this frame is interpreted so it can set the
-      // sender's _interpreter_sp_adjustment field.
-      if (VM.getVM().getInterpreter().contains(pc)) {
-        isInterpreted = true;
-        map.makeIntegerRegsUnsaved();
+    // The constructor of the sender must know whether this frame is interpreted so it can set the
+    // sender's _interpreter_sp_adjustment field.
+    if (VM.getVM().getInterpreter().contains(pc)) {
+      isInterpreted = true;
+      map.makeIntegerRegsUnsaved();
+      map.shiftWindow(sp, youngerSP);
+    } else {
+      // Find a CodeBlob containing this frame's pc or elide the lookup and use the
+      // supplied blob which is already known to be associated with this frame.
+      cb = VM.getVM().getCodeCache().findBlob(pc);
+      if (cb != null) {
+        // Update the location of all implicitly saved registers
+        // as the address of these registers in the register save
+        // area (for %o registers we use the address of the %i
+        // register in the next younger frame)
         map.shiftWindow(sp, youngerSP);
-      } else {
-        // Find a CodeBlob containing this frame's pc or elide the lookup and use the
-        // supplied blob which is already known to be associated with this frame.
-        cb = VM.getVM().getCodeCache().findBlob(pc);
-        if (cb != null) {
-
-          if (cb.callerMustGCArguments(map.getThread())) {
+        if (map.getUpdateMap()) {
+          if (cb.callerMustGCArguments()) {
             map.setIncludeArgumentOops(true);
           }
-
-          // Update the location of all implicitly saved registers
-          // as the address of these registers in the register save
-          // area (for %o registers we use the address of the %i
-          // register in the next younger frame)
-          map.shiftWindow(sp, youngerSP);
-          if (map.getUpdateMap()) {
-            if (cb.getOopMaps() != null) {
-              OopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging());
-            }
+          if (cb.getOopMaps() != null) {
+            OopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging());
           }
         }
       }
-    } // #ifndef CORE
+    }
 
     return new SPARCFrame(biasSP(sp), biasSP(youngerSP), isInterpreted);
   }
@@ -948,6 +945,20 @@
   }
 
 
+  private Frame senderForRicochetFrame(SPARCRegisterMap map) {
+    if (DEBUG) {
+      System.out.println("senderForRicochetFrame");
+    }
+    //RicochetFrame* f = RicochetFrame::from_frame(fr);
+    // Cf. is_interpreted_frame path of frame::sender
+    Address youngerSP = getSP();
+    Address sp        = getSenderSP();
+    map.makeIntegerRegsUnsaved();
+    map.shiftWindow(sp, youngerSP);
+    boolean thisFrameAdjustedStack = true;  // I5_savedSP is live in this RF
+    return new SPARCFrame(sp, youngerSP, thisFrameAdjustedStack);
+  }
+
   private Frame senderForEntryFrame(RegisterMap regMap) {
     SPARCRegisterMap map = (SPARCRegisterMap) regMap;
 
@@ -965,10 +976,8 @@
     Address lastJavaPC = jcw.getLastJavaPC();
     map.clear();
 
-    if (!VM.getVM().isCore()) {
-      map.makeIntegerRegsUnsaved();
-      map.shiftWindow(lastJavaSP, null);
-    }
+    map.makeIntegerRegsUnsaved();
+    map.shiftWindow(lastJavaSP, null);
 
     if (Assert.ASSERTS_ENABLED) {
       Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCRicochetFrame.java	Mon Sep 05 17:09:05 2011 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.runtime.sparc;
+
+import java.util.*;
+import sun.jvm.hotspot.asm.sparc.SPARCRegister;
+import sun.jvm.hotspot.asm.sparc.SPARCRegisters;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.types.*;
+
+public class SPARCRicochetFrame {
+  static {
+    VM.registerVMInitializedObserver(new Observer() {
+        public void update(Observable o, Object data) {
+          initialize(VM.getVM().getTypeDataBase());
+        }
+      });
+  }
+
+  private SPARCFrame frame;
+
+  private static void initialize(TypeDataBase db) {
+    // Type type = db.lookupType("MethodHandles::RicochetFrame");
+
+  }
+
+  static SPARCRicochetFrame fromFrame(SPARCFrame f) {
+    return new SPARCRicochetFrame(f);
+  }
+
+  private SPARCRicochetFrame(SPARCFrame f) {
+    frame = f;
+  }
+
+  private Address registerValue(SPARCRegister reg) {
+    return frame.getSP().addOffsetTo(reg.spOffsetInSavedWindow()).getAddressAt(0);
+  }
+
+  public Address savedArgsBase() {
+    return registerValue(SPARCRegisters.L4);
+  }
+  public Address exactSenderSP() {
+    return registerValue(SPARCRegisters.I5);
+  }
+  public Address senderLink() {
+    return frame.getSenderSP();
+  }
+  public Address senderPC() {
+    return frame.getSenderPC();
+  }
+  public Address extendedSenderSP() {
+    return savedArgsBase();
+  }
+}
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java	Mon Sep 05 17:09:05 2011 -0700
@@ -31,6 +31,7 @@
 import sun.jvm.hotspot.debugger.amd64.*;
 import sun.jvm.hotspot.runtime.*;
 import sun.jvm.hotspot.runtime.amd64.*;
+import sun.jvm.hotspot.runtime.x86.*;
 import sun.jvm.hotspot.types.*;
 import sun.jvm.hotspot.utilities.*;
 
@@ -86,14 +87,14 @@
     }
     Address pc =  thread.getLastJavaPC();
     if ( pc != null ) {
-      return new AMD64Frame(thread.getLastJavaSP(), fp, pc);
+      return new X86Frame(thread.getLastJavaSP(), fp, pc);
     } else {
-      return new AMD64Frame(thread.getLastJavaSP(), fp);
+      return new X86Frame(thread.getLastJavaSP(), fp);
     }
   }
 
   public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
-    return new AMD64RegisterMap(thread, updateMap);
+    return new X86RegisterMap(thread, updateMap);
   }
 
   public Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
@@ -104,9 +105,9 @@
       return null;
     }
     if (guesser.getPC() == null) {
-      return new AMD64Frame(guesser.getSP(), guesser.getFP());
+      return new X86Frame(guesser.getSP(), guesser.getFP());
     } else {
-      return new AMD64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
+      return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
     }
   }
 
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java	Sat Sep 03 14:03:54 2011 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java	Mon Sep 05 17:09:05 2011 -0700
@@ -25,7 +25,6 @@
 package sun.jvm.hotspot.runtime.x86;
 
 import java.util.*;
-import sun.jvm.hotspot.asm.x86.*;
 import sun.jvm.hotspot.code.*;
 import sun.jvm.hotspot.compiler.*;
 import sun.jvm.hotspot.debugger.*;
@@ -62,11 +61,13 @@
   private static       int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET;
 
   // Entry frames
-  private static final int ENTRY_FRAME_CALL_WRAPPER_OFFSET   =  2;
+  private static       int ENTRY_FRAME_CALL_WRAPPER_OFFSET;
 
   // Native frames
   private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET =  2;
 
+  private static VMReg rbp;
+
   static {
     VM.registerVMInitializedObserver(new Observer() {
         public void update(Observable o, Object data) {
@@ -76,19 +77,23 @@
   }
 
   private static synchronized void initialize(TypeDataBase db) {
-    if (VM.getVM().isCore()) {
-      INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1;
-    } else {
-      INTERPRETER_FRAME_MDX_OFFSET   = INTERPRETER_FRAME_METHOD_OFFSET - 1;
-      INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1;
-    }
+    INTERPRETER_FRAME_MDX_OFFSET                  = INTERPRETER_FRAME_METHOD_OFFSET - 1;
+    INTERPRETER_FRAME_CACHE_OFFSET                = INTERPRETER_FRAME_MDX_OFFSET - 1;
     INTERPRETER_FRAME_LOCALS_OFFSET               = INTERPRETER_FRAME_CACHE_OFFSET - 1;
     INTERPRETER_FRAME_BCX_OFFSET                  = INTERPRETER_FRAME_LOCALS_OFFSET - 1;
     INTERPRETER_FRAME_INITIAL_SP_OFFSET           = INTERPRETER_FRAME_BCX_OFFSET - 1;
     INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET    = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
     INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
+
+    ENTRY_FRAME_CALL_WRAPPER_OFFSET = db.lookupIntConstant("frame::entry_frame_call_wrapper_offset");
+    if (VM.getVM().getAddressSize() == 4) {
+      rbp = new VMReg(5);
+    } else {
+      rbp = new VMReg(5 << 1);
+    }
   }
 
+
   // an additional field beyond sp and pc:
   Address raw_fp; // frame pointer
   private Address raw_unextendedSP;
@@ -102,7 +107,7 @@
       CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
       if (cb != null && cb.isJavaMethod()) {
         NMethod nm = (NMethod) cb;
-        if (pc.equals(nm.deoptBegin())) {
+        if (pc.equals(nm.deoptHandlerBegin())) {
           if (Assert.ASSERTS_ENABLED) {
             Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
           }
@@ -119,6 +124,7 @@
     this.raw_unextendedSP = raw_sp;
     this.raw_fp = raw_fp;
     this.pc = pc;
+    adjustUnextendedSP();
 
     // Frame must be fully constructed before this call
     adjustForDeopt();
@@ -134,6 +140,7 @@
     this.raw_unextendedSP = raw_sp;
     this.raw_fp = raw_fp;
     this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
+    adjustUnextendedSP();
 
     // Frame must be fully constructed before this call
     adjustForDeopt();
@@ -144,24 +151,18 @@
     }
   }
 
-  // This constructor should really take the unextended SP as an arg
-  // but then the constructor is ambiguous with constructor that takes
-  // a PC so take an int and convert it.
-  public X86Frame(Address raw_sp, Address raw_fp, long extension) {
+  public X86Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) {
     this.raw_sp = raw_sp;
-    if (raw_sp == null) {
-      this.raw_unextendedSP = null;
-    } else {
-      this.raw_unextendedSP = raw_sp.addOffsetTo(extension);
-    }
+    this.raw_unextendedSP = raw_unextendedSp;
     this.raw_fp = raw_fp;
-    this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
+    this.pc = pc;
+    adjustUnextendedSP();
 
     // Frame must be fully constructed before this call
     adjustForDeopt();
 
     if (DEBUG) {
-      System.out.println("X86Frame(sp, fp): " + this);
+      System.out.println("X86Frame(sp, unextendedSP, fp, pc): " + this);
       dumpStack();
     }
 
@@ -172,7 +173,6 @@
     frame.raw_sp = raw_sp;
     frame.raw_unextendedSP = raw_unextendedSP;
     frame.raw_fp = raw_fp;
-    frame.raw_fp = raw_fp;
     frame.pc = pc;
     frame.deoptimized = deoptimized;
     return frame;
@@ -269,19 +269,18 @@
 
     if (isEntryFrame())       return senderForEntryFrame(map);
     if (isInterpretedFrame()) return senderForInterpreterFrame(map);
+    if (isRicochetFrame())    return senderForRicochetFrame(map);
 
-    if (!VM.getVM().isCore()) {
-      if(cb == null) {
-        cb = VM.getVM().getCodeCache().findBlob(getPC());
-      } else {
-        if (Assert.ASSERTS_ENABLED) {
-          Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same");
-        }
+    if(cb == null) {
+      cb = VM.getVM().getCodeCache().findBlob(getPC());
+    } else {
+      if (Assert.ASSERTS_ENABLED) {
+        Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same");
       }
+    }
 
-      if (cb != null) {
-         return senderForCompiledFrame(map, cb);
-      }
+    if (cb != null) {
+      return senderForCompiledFrame(map, cb);
     }
 
     // Must be native-compiled frame, i.e. the marshaling code for native
@@ -289,7 +288,20 @@
     return new X86Frame(getSenderSP(), getLink(), getSenderPC());
   }
 
+  private Frame senderForRicochetFrame(X86RegisterMap map) {
+    if (DEBUG) {
+      System.out.println("senderForRicochetFrame");
+    }
+    X86RicochetFrame f = X86RicochetFrame.fromFrame(this);
+    if (map.getUpdateMap())
+      updateMapWithSavedLink(map, f.senderLinkAddress());
+    return new X86Frame(f.extendedSenderSP(), f.exactSenderSP(), f.senderLink(), f.senderPC());
+  }
+
   private Frame senderForEntryFrame(X86RegisterMap map) {
+    if (DEBUG) {
+      System.out.println("senderForEntryFrame");
+    }
     if (Assert.ASSERTS_ENABLED) {
       Assert.that(map != null, "map must be set");
     }
@@ -313,7 +325,37 @@
     return fr;
   }
 
+  //------------------------------------------------------------------------------
+  // frame::adjust_unextended_sp
+  private void adjustUnextendedSP() {
+    // If we are returning to a compiled MethodHandle call site, the
+    // saved_fp will in fact be a saved value of the unextended SP.  The
+    // simplest way to tell whether we are returning to such a call site
+    // is as follows:
+
+    CodeBlob cb = cb();
+    NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull();
+    if (senderNm != null) {
+      // If the sender PC is a deoptimization point, get the original
+      // PC.  For MethodHandle call site the unextended_sp is stored in
+      // saved_fp.
+      if (senderNm.isDeoptMhEntry(getPC())) {
+        // DEBUG_ONLY(verifyDeoptMhOriginalPc(senderNm, getFP()));
+        raw_unextendedSP = getFP();
+      }
+      else if (senderNm.isDeoptEntry(getPC())) {
+        // DEBUG_ONLY(verifyDeoptOriginalPc(senderNm, raw_unextendedSp));
+      }
+      else if (senderNm.isMethodHandleReturn(getPC())) {
+        raw_unextendedSP = getFP();
+      }
+    }
+  }
+
   private Frame senderForInterpreterFrame(X86RegisterMap map) {
+    if (DEBUG) {
+      System.out.println("senderForInterpreterFrame");
+    }
     Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
     Address sp = addressOfStackSlot(SENDER_SP_OFFSET);
     // We do not need to update the callee-save register mapping because above
@@ -323,10 +365,21 @@
     // However c2 no longer uses callee save register for java calls so there
     // are no callee register to find.
 
-    return new X86Frame(sp, getLink(), unextendedSP.minus(sp));
+    if (map.getUpdateMap())
+      updateMapWithSavedLink(map, addressOfStackSlot(LINK_OFFSET));
+
+    return new X86Frame(sp, unextendedSP, getLink(), getSenderPC());
+  }
+
+  private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) {
+    map.setLocation(rbp, savedFPAddr);
   }
 
   private Frame senderForCompiledFrame(X86RegisterMap map, CodeBlob cb) {
+    if (DEBUG) {
+      System.out.println("senderForCompiledFrame");
+    }
+
     //
     // NOTE: some of this code is (unfortunately) duplicated in X86CurrentFrameGuess
     //
@@ -336,41 +389,35 @@
     }
 
     // frame owned by optimizing compiler
-    Address        sender_sp = null;
+    if (Assert.ASSERTS_ENABLED) {
+        Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size");
+    }
+    Address senderSP = getUnextendedSP().addOffsetTo(cb.getFrameSize());
 
-    if (VM.getVM().isClientCompiler()) {
-      sender_sp        = addressOfStackSlot(SENDER_SP_OFFSET);
-    } else {
-      if (Assert.ASSERTS_ENABLED) {
-        Assert.that(cb.getFrameSize() >= 0, "Compiled by Compiler1: do not use");
+    // On Intel the return_address is always the word on the stack
+    Address senderPC = senderSP.getAddressAt(-1 * VM.getVM().getAddressSize());
+
+    // This is the saved value of EBP which may or may not really be an FP.
+    // It is only an FP if the sender is an interpreter frame (or C1?).
+    Address savedFPAddr = senderSP.addOffsetTo(- SENDER_SP_OFFSET * VM.getVM().getAddressSize());
+
+    if (map.getUpdateMap()) {
+      // Tell GC to use argument oopmaps for some runtime stubs that need it.
+      // For C1, the runtime stub might not have oop maps, so set this flag
+      // outside of update_register_map.
+      map.setIncludeArgumentOops(cb.callerMustGCArguments());
+
+      if (cb.getOopMaps() != null) {
+        OopMapSet.updateRegisterMap(this, cb, map, true);
       }
-      sender_sp = getUnextendedSP().addOffsetTo(cb.getFrameSize());
+
+      // Since the prolog does the save and restore of EBP there is no oopmap
+      // for it so we must fill in its location as if there was an oopmap entry
+      // since if our caller was compiled code there could be live jvm state in it.
+      updateMapWithSavedLink(map, savedFPAddr);
     }
 
-    // On Intel the return_address is always the word on the stack
-    Address sender_pc = sender_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
-
-    if (map.getUpdateMap() && cb.getOopMaps() != null) {
-      OopMapSet.updateRegisterMap(this, cb, map, true);
-    }
-
-    if (VM.getVM().isClientCompiler()) {
-      // Move this here for C1 and collecting oops in arguments (According to Rene)
-      map.setIncludeArgumentOops(cb.callerMustGCArguments(map.getThread()));
-    }
-
-    Address saved_fp = null;
-    if (VM.getVM().isClientCompiler()) {
-      saved_fp = getFP().getAddressAt(0);
-    } else if (VM.getVM().isServerCompiler() &&
-               (VM.getVM().getInterpreter().contains(sender_pc) ||
-               VM.getVM().getStubRoutines().returnsToCallStub(sender_pc))) {
-      // C2 prologue saves EBP in the usual place.
-      // however only use it if the sender had link infomration in it.
-      saved_fp = sender_sp.getAddressAt(-2 * VM.getVM().getAddressSize());
-    }
-
-    return new X86Frame(sender_sp, saved_fp, sender_pc);
+    return new X86Frame(senderSP, savedFPAddr.getAddressAt(0), senderPC);
   }
 
   protected boolean hasSenderPD() {
@@ -403,14 +450,6 @@
 
   public Address getSenderSP()     { return addressOfStackSlot(SENDER_SP_OFFSET); }
 
-  public Address compiledArgumentToLocationPD(VMReg reg, RegisterMap regMap, int argSize) {
-    if (VM.getVM().isCore() || VM.getVM().isClientCompiler()) {
-      throw new RuntimeException("Should not reach here");
-    }
-
-    return oopMapRegToLocation(reg, regMap);
-  }
-
   public Address addressOfInterpreterFrameLocals() {
     return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET);
   }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86RicochetFrame.java	Mon Sep 05 17:09:05 2011 -0700
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.runtime.x86;
+
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.types.*;
+
+public class X86RicochetFrame extends VMObject {
+  static {
+    VM.registerVMInitializedObserver(new Observer() {
+        public void update(Observable o, Object data) {
+          initialize(VM.getVM().getTypeDataBase());
+        }
+      });
+  }
+
+  private static void initialize(TypeDataBase db) {
+    Type type = db.lookupType("MethodHandles::RicochetFrame");
+
+    senderLinkField    = type.getAddressField("_sender_link");
+    savedArgsBaseField = type.getAddressField("_saved_args_base");
+    exactSenderSPField = type.getAddressField("_exact_sender_sp");
+    senderPCField      = type.getAddressField("_sender_pc");
+  }
+
+  private static AddressField senderLinkField;
+  private static AddressField savedArgsBaseField;
+  private static AddressField exactSenderSPField;
+  private static AddressField senderPCField;
+
+  static X86RicochetFrame fromFrame(X86Frame f) {
+    return new X86RicochetFrame(f.getFP().addOffsetTo(- senderLinkField.getOffset()));
+  }
+
+  private X86RicochetFrame(Address addr) {
+    super(addr);
+  }
+
+  public Address senderLink() {
+    return senderLinkField.getValue(addr);
+  }
+  public Address senderLinkAddress() {
+    return addr.addOffsetTo(senderLinkField.getOffset());
+  }
+  public Address savedArgsBase() {
+    return savedArgsBaseField.getValue(addr);
+  }
+  public Address extendedSenderSP() {
+    return savedArgsBase();
+  }
+  public Address exactSenderSP() {
+    return exactSenderSPField.getValue(addr);
+  }
+  public Address senderPC() {
+    return senderPCField.getValue(addr);
+  }
+}
--- a/src/cpu/x86/vm/methodHandles_x86.hpp	Sat Sep 03 14:03:54 2011 -0700
+++ b/src/cpu/x86/vm/methodHandles_x86.hpp	Mon Sep 05 17:09:05 2011 -0700
@@ -110,6 +110,7 @@
 
 class RicochetFrame {
   friend class MethodHandles;
+  friend class VMStructs;
 
  private:
   intptr_t* _continuation;          // what to do when control gets back here
--- a/src/share/vm/c1/c1_LinearScan.cpp	Sat Sep 03 14:03:54 2011 -0700
+++ b/src/share/vm/c1/c1_LinearScan.cpp	Mon Sep 05 17:09:05 2011 -0700
@@ -2404,7 +2404,7 @@
       assert(!is_call_site || assigned_reg >= nof_regs || !is_caller_save(assigned_reg), "interval is in a caller-save register at a call -> register will be overwritten");
 
       VMReg name = vm_reg_for_interval(interval);
-      map->set_oop(name);
+      set_oop(map, name);
 
       // Spill optimization: when the stack value is guaranteed to be always correct,
       // then it must be added to the oop map even if the interval is currently in a register
@@ -2415,7 +2415,7 @@
         assert(interval->canonical_spill_slot() >= LinearScan::nof_regs, "no spill slot assigned");
         assert(interval->assigned_reg() < LinearScan::nof_regs, "interval is on stack, so stack slot is registered twice");
 
-        map->set_oop(frame_map()->slot_regname(interval->canonical_spill_slot() - LinearScan::nof_regs));
+        set_oop(map, frame_map()->slot_regname(interval->canonical_spill_slot() - LinearScan::nof_regs));
       }
     }
   }
@@ -2424,7 +2424,7 @@
   assert(info->stack() != NULL, "CodeEmitInfo must always have a stack");
   int locks_count = info->stack()->total_locks_size();
   for (int i = 0; i < locks_count; i++) {
-    map->set_oop(frame_map()->monitor_object_regname(i));
+    set_oop(map, frame_map()->monitor_object_regname(i));
   }
 
   return map;
--- a/src/share/vm/c1/c1_LinearScan.hpp	Sat Sep 03 14:03:54 2011 -0700
+++ b/src/share/vm/c1/c1_LinearScan.hpp	Mon Sep 05 17:09:05 2011 -0700
@@ -352,6 +352,13 @@
 
   MonitorValue*  location_for_monitor_index(int monitor_index);
   LocationValue* location_for_name(int name, Location::Type loc_type);
+  void set_oop(OopMap* map, VMReg name) {
+    if (map->legal_vm_reg_name(name)) {
+      map->set_oop(name);
+    } else {
+      bailout("illegal oopMap register name");
+    }
+  }
 
   int append_scope_value_for_constant(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values);
   int append_scope_value_for_operand(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values);
--- a/src/share/vm/code/pcDesc.cpp	Sat Sep 03 14:03:54 2011 -0700
+++ b/src/share/vm/code/pcDesc.cpp	Mon Sep 05 17:09:05 2011 -0700
@@ -30,11 +30,10 @@
 #include "memory/resourceArea.hpp"
 
 PcDesc::PcDesc(int pc_offset, int scope_decode_offset, int obj_decode_offset) {
-  assert(sizeof(PcDescFlags) <= 4, "occupies more than a word");
   _pc_offset           = pc_offset;
   _scope_decode_offset = scope_decode_offset;
   _obj_decode_offset   = obj_decode_offset;
-  _flags.word          = 0;
+  _flags               = 0;
 }
 
 address PcDesc::real_pc(const nmethod* code) const {
@@ -44,7 +43,7 @@
 void PcDesc::print(nmethod* code) {
 #ifndef PRODUCT
   ResourceMark rm;
-  tty->print_cr("PcDesc(pc=0x%lx offset=%x bits=%x):", real_pc(code), pc_offset(), _flags.bits);
+  tty->print_cr("PcDesc(pc=0x%lx offset=%x bits=%x):", real_pc(code), pc_offset(), _flags);
 
   if (scope_decode_offset() == DebugInformationRecorder::serialized_null) {
     return;
--- a/src/share/vm/code/pcDesc.hpp	Sat Sep 03 14:03:54 2011 -0700
+++ b/src/share/vm/code/pcDesc.hpp	Mon Sep 05 17:09:05 2011 -0700
@@ -39,15 +39,17 @@
   int _scope_decode_offset; // offset for scope in nmethod
   int _obj_decode_offset;
 
-  union PcDescFlags {
-    int word;
-    struct {
-      unsigned int reexecute: 1;
-      unsigned int is_method_handle_invoke: 1;
-      unsigned int return_oop: 1;
-    } bits;
-    bool operator ==(const PcDescFlags& other) { return word == other.word; }
-  } _flags;
+  enum {
+    PCDESC_reexecute               = 1 << 0,
+    PCDESC_is_method_handle_invoke = 1 << 1,
+    PCDESC_return_oop              = 1 << 2
+  };
+
+  int _flags;
+
+  void set_flag(int mask, bool z) {
+    _flags = z ? (_flags | mask) : (_flags & ~mask);
+  }
 
  public:
   int pc_offset() const           { return _pc_offset;   }
@@ -69,8 +71,8 @@
   };
 
   // Flags
-  bool     should_reexecute()              const { return _flags.bits.reexecute; }
-  void set_should_reexecute(bool z)              { _flags.bits.reexecute = z;    }
+  bool     should_reexecute()              const { return (_flags & PCDESC_reexecute) != 0; }
+  void set_should_reexecute(bool z)              { set_flag(PCDESC_reexecute, z); }
 
   // Does pd refer to the same information as pd?
   bool is_same_info(const PcDesc* pd) {
@@ -79,11 +81,11 @@
       _flags == pd->_flags;
   }
 
-  bool     is_method_handle_invoke()       const { return _flags.bits.is_method_handle_invoke;     }
-  void set_is_method_handle_invoke(bool z)       {        _flags.bits.is_method_handle_invoke = z; }
+  bool     is_method_handle_invoke()       const { return (_flags & PCDESC_is_method_handle_invoke) != 0;     }
+  void set_is_method_handle_invoke(bool z)       { set_flag(PCDESC_is_method_handle_invoke, z); }
 
-  bool     return_oop()                    const { return _flags.bits.return_oop;     }
-  void set_return_oop(bool z)                    {        _flags.bits.return_oop = z; }
+  bool     return_oop()                    const { return (_flags & PCDESC_return_oop) != 0;     }
+  void set_return_oop(bool z)                    { set_flag(PCDESC_return_oop, z); }
 
   // Returns the real pc
   address real_pc(const nmethod* code) const;
--- a/src/share/vm/runtime/sharedRuntime.hpp	Sat Sep 03 14:03:54 2011 -0700
+++ b/src/share/vm/runtime/sharedRuntime.hpp	Mon Sep 05 17:09:05 2011 -0700
@@ -45,6 +45,8 @@
 // information, etc.
 
 class SharedRuntime: AllStatic {
+  friend class VMStructs;
+
  private:
   static methodHandle resolve_sub_helper(JavaThread *thread,
                                      bool is_virtual,
--- a/src/share/vm/runtime/thread.cpp	Sat Sep 03 14:03:54 2011 -0700
+++ b/src/share/vm/runtime/thread.cpp	Mon Sep 05 17:09:05 2011 -0700
@@ -2859,6 +2859,44 @@
   }
 }
 
+class PrintAndVerifyOopClosure: public OopClosure {
+ protected:
+  template <class T> inline void do_oop_work(T* p) {
+    oop obj = oopDesc::load_decode_heap_oop(p);
+    if (obj == NULL) return;
+    tty->print(INTPTR_FORMAT ": ", p);
+    if (obj->is_oop_or_null()) {
+      if (obj->is_objArray()) {
+        tty->print_cr("valid objArray: " INTPTR_FORMAT, (oopDesc*) obj);
+      } else {
+        obj->print();
+      }
+    } else {
+      tty->print_cr("invalid oop: " INTPTR_FORMAT, (oopDesc*) obj);
+    }
+    tty->cr();
+  }
+ public:
+  virtual void do_oop(oop* p) { do_oop_work(p); }
+  virtual void do_oop(narrowOop* p)  { do_oop_work(p); }
+};
+
+
+static void oops_print(frame* f, const RegisterMap *map) {
+  PrintAndVerifyOopClosure print;
+  f->print_value();
+  f->oops_do(&print, NULL, (RegisterMap*)map);
+}
+
+// Print our all the locations that contain oops and whether they are
+// valid or not.  This useful when trying to find the oldest frame
+// where an oop has gone bad since the frame walk is from youngest to
+// oldest.
+void JavaThread::trace_oops() {
+  tty->print_cr("[Trace oops]");
+  frames_do(oops_print);
+}
+
 
 #ifdef ASSERT
 // Print or validate the layout of stack frames
--- a/src/share/vm/runtime/thread.hpp	Sat Sep 03 14:03:54 2011 -0700
+++ b/src/share/vm/runtime/thread.hpp	Mon Sep 05 17:09:05 2011 -0700
@@ -1375,6 +1375,7 @@
   void trace_stack()                             PRODUCT_RETURN;
   void trace_stack_from(vframe* start_vf)        PRODUCT_RETURN;
   void trace_frames()                            PRODUCT_RETURN;
+  void trace_oops()                              PRODUCT_RETURN;
 
   // Print an annotated view of the stack frames
   void print_frame_layout(int depth = 0, bool validate_only = false) NOT_DEBUG_RETURN;
--- a/src/share/vm/runtime/vmStructs.cpp	Sat Sep 03 14:03:54 2011 -0700
+++ b/src/share/vm/runtime/vmStructs.cpp	Mon Sep 05 17:09:05 2011 -0700
@@ -652,6 +652,7 @@
       static_field(SystemDictionary,            WK_KLASS(ThreadGroup_klass),                   klassOop)                             \
       static_field(SystemDictionary,            WK_KLASS(Properties_klass),                    klassOop)                             \
       static_field(SystemDictionary,            WK_KLASS(StringBuffer_klass),                  klassOop)                             \
+      static_field(SystemDictionary,            WK_KLASS(MethodHandle_klass),                  klassOop)                             \
       static_field(SystemDictionary,            _box_klasses[0],                               klassOop)                             \
       static_field(SystemDictionary,            _java_system_loader,                           oop)                                  \
                                                                                                                                      \
@@ -757,12 +758,19 @@
   nonstatic_field(PcDesc,                      _pc_offset,                                    int)                                   \
   nonstatic_field(PcDesc,                      _scope_decode_offset,                          int)                                   \
   nonstatic_field(PcDesc,                      _obj_decode_offset,                            int)                                   \
-  nonstatic_field(PcDesc,                      _flags,                        PcDesc::PcDescFlags)                                   \
+  nonstatic_field(PcDesc,                      _flags,                                        int)                                   \
                                                                                                                                      \
   /***************************************************/                                                                              \
   /* CodeBlobs (NOTE: incomplete, but only a little) */                                                                              \
   /***************************************************/                                                                              \
                                                                                                                                      \
+  X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _sender_pc,                                     address))                   \
+  X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _exact_sender_sp,                              intptr_t*))                  \
+  X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _sender_link,                                  intptr_t*))                  \
+  X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _saved_args_base,                              intptr_t*))                  \
+                                                                                                                                     \
+     static_field(SharedRuntime,               _ricochet_blob,                                RicochetBlob*)                         \
+                                                                                                                                     \
   nonstatic_field(CodeBlob,                    _name,                                         const char*)                           \
   nonstatic_field(CodeBlob,                    _size,                                         int)                                   \
   nonstatic_field(CodeBlob,                    _header_size,                                  int)                                   \
@@ -774,6 +782,8 @@
   nonstatic_field(CodeBlob,                    _frame_size,                                   int)                                   \
   nonstatic_field(CodeBlob,                    _oop_maps,                                     OopMapSet*)                            \
                                                                                                                                      \
+  nonstatic_field(RuntimeStub,                 _caller_must_gc_arguments,                     bool)                                  \
+                                                                                                                                     \
   /**************************************************/                                                                               \
   /* NMethods (NOTE: incomplete, but only a little) */                                                                               \
   /**************************************************/                                                                               \
@@ -786,6 +796,7 @@
   nonstatic_field(nmethod,             _state,                                        unsigned char)                         \
   nonstatic_field(nmethod,             _exception_offset,                             int)                                   \
   nonstatic_field(nmethod,             _deoptimize_offset,                            int)                                   \
+  nonstatic_field(nmethod,             _deoptimize_mh_offset,                         int)                                   \
   nonstatic_field(nmethod,             _orig_pc_offset,                               int)                                   \
   nonstatic_field(nmethod,             _stub_offset,                                  int)                                   \
   nonstatic_field(nmethod,             _consts_offset,                                int)                                   \
@@ -804,6 +815,9 @@
   nonstatic_field(nmethod,             _compile_id,                                   int)                                   \
   nonstatic_field(nmethod,             _marked_for_deoptimization,                    bool)                                  \
                                                                                                                                      \
+  nonstatic_field(RicochetBlob,        _bounce_offset,                                int)                                           \
+  nonstatic_field(RicochetBlob,        _exception_offset,                             int)                                           \
+                                                                                                                                     \
   /********************************/                                                                                                 \
   /* JavaCalls (NOTE: incomplete) */                                                                                                 \
   /********************************/                                                                                                 \
@@ -1310,24 +1324,27 @@
   /* CodeBlob hierarchy (needed for run-time type information) */         \
   /*************************************************************/         \
                                                                           \
+  declare_toplevel_type(SharedRuntime)                                    \
+  X86_ONLY(declare_toplevel_type(MethodHandles::RicochetFrame))           \
+                                                                          \
   declare_toplevel_type(CodeBlob)                                         \
-  declare_type(BufferBlob,            CodeBlob)                           \
-  declare_type(AdapterBlob,           BufferBlob)                         \
-  declare_type(nmethod,               CodeBlob)                           \
-  declare_type(RuntimeStub,           CodeBlob)                           \
-  declare_type(SingletonBlob,         CodeBlob)                           \
-  declare_type(SafepointBlob,         SingletonBlob)                      \
-  declare_type(DeoptimizationBlob,    SingletonBlob)                      \
-  declare_type(RicochetBlob,          SingletonBlob)                      \
-  declare_c2_type(ExceptionBlob,      SingletonBlob)                      \
-  declare_c2_type(UncommonTrapBlob,   CodeBlob)                           \
+  declare_type(BufferBlob,               CodeBlob)                        \
+  declare_type(AdapterBlob,              BufferBlob)                      \
+  declare_type(MethodHandlesAdapterBlob, BufferBlob)                      \
+  declare_type(nmethod,                  CodeBlob)                        \
+  declare_type(RuntimeStub,              CodeBlob)                        \
+  declare_type(SingletonBlob,            CodeBlob)                        \
+  declare_type(SafepointBlob,            SingletonBlob)                   \
+  declare_type(DeoptimizationBlob,       SingletonBlob)                   \
+  declare_type(RicochetBlob,             SingletonBlob)                   \
+  declare_c2_type(ExceptionBlob,         SingletonBlob)                   \
+  declare_c2_type(UncommonTrapBlob,      CodeBlob)                        \
                                                                           \
   /***************************************/                               \
   /* PcDesc and other compiled code info */                               \
   /***************************************/                               \
                                                                           \
   declare_toplevel_type(PcDesc)                                           \
-  declare_integer_type(PcDesc::PcDescFlags)                               \
                                                                           \
   /************************/                                              \
   /* OopMap and OopMapSet */                                              \
@@ -1796,6 +1813,21 @@
                                                                           \
   declare_constant(ObjectSynchronizer::_BLOCKSIZE)                        \
                                                                           \
+  /**********************/                                                \
+  /* PcDesc             */                                                \
+  /**********************/                                                \
+                                                                          \
+  declare_constant(PcDesc::PCDESC_reexecute)                              \
+  declare_constant(PcDesc::PCDESC_is_method_handle_invoke)                \
+  declare_constant(PcDesc::PCDESC_return_oop)                             \
+                                                                          \
+  /**********************/                                                \
+  /* frame              */                                                \
+  /**********************/                                                \
+                                                                          \
+  X86_ONLY(declare_constant(frame::entry_frame_call_wrapper_offset))      \
+  declare_constant(frame::pc_return_offset)                               \
+                                                                          \
   /********************************/                                      \
   /* Calling convention constants */                                      \
   /********************************/                                      \