# HG changeset patch # User never # Date 1315267745 25200 # Node ID f92c9ff3a15f1ef566c4600cc18737665b193bbb # Parent 2797e487c09f5c5c1d49fda43cfb973006e61c78 7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244) Reviewed-by: kvn diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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()) { diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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)); diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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; } diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/code/MethodHandlesAdapterBlob.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/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(); + } +} diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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); } diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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) { diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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)); + } + } diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/code/RuntimeStub.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/RuntimeStub.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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(); } diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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]; diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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); } diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/StackFrameImpl.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/StackFrameImpl.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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; diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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); diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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(); diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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 } diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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 */ diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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; diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VFrame.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VFrame.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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); diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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(); diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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.*; /**

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()) { diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64Frame.java --- a/hotspot/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)); - } - } - } -} diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64RegisterMap.java --- a/hotspot/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; } -} diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/linux_amd64/LinuxAMD64JavaThreadPDAccess.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/linux_amd64/LinuxAMD64JavaThreadPDAccess.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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()); } } diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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()); } } diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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"); diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCRicochetFrame.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/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(); + } +} diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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()); } } diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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 (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()); + if (Assert.ASSERTS_ENABLED) { + Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size"); } + Address senderSP = 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()); + 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() && cb.getOopMaps() != null) { - OopMapSet.updateRegisterMap(this, cb, map, true); + 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); + } + + // 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); } - 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); } diff -r 2797e487c09f -r f92c9ff3a15f hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86RicochetFrame.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/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); + } +} diff -r 2797e487c09f -r f92c9ff3a15f hotspot/src/cpu/x86/vm/methodHandles_x86.hpp --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.hpp Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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 diff -r 2797e487c09f -r f92c9ff3a15f hotspot/src/share/vm/c1/c1_LinearScan.cpp --- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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; diff -r 2797e487c09f -r f92c9ff3a15f hotspot/src/share/vm/c1/c1_LinearScan.hpp --- a/hotspot/src/share/vm/c1/c1_LinearScan.hpp Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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* scope_values); int append_scope_value_for_operand(LIR_Opr opr, GrowableArray* scope_values); diff -r 2797e487c09f -r f92c9ff3a15f hotspot/src/share/vm/code/pcDesc.cpp --- a/hotspot/src/share/vm/code/pcDesc.cpp Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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; diff -r 2797e487c09f -r f92c9ff3a15f hotspot/src/share/vm/code/pcDesc.hpp --- a/hotspot/src/share/vm/code/pcDesc.hpp Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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; diff -r 2797e487c09f -r f92c9ff3a15f hotspot/src/share/vm/runtime/sharedRuntime.hpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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, diff -r 2797e487c09f -r f92c9ff3a15f hotspot/src/share/vm/runtime/thread.cpp --- a/hotspot/src/share/vm/runtime/thread.cpp Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/src/share/vm/runtime/thread.cpp Mon Sep 05 17:09:05 2011 -0700 @@ -2859,6 +2859,44 @@ } } +class PrintAndVerifyOopClosure: public OopClosure { + protected: + template 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 diff -r 2797e487c09f -r f92c9ff3a15f hotspot/src/share/vm/runtime/thread.hpp --- a/hotspot/src/share/vm/runtime/thread.hpp Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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; diff -r 2797e487c09f -r f92c9ff3a15f hotspot/src/share/vm/runtime/vmStructs.cpp --- a/hotspot/src/share/vm/runtime/vmStructs.cpp Sat Sep 03 14:03:54 2011 -0700 +++ b/hotspot/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 */ \ /********************************/ \