diff --git a/agent/src/share/classes/sun/jvm/hotspot/HSDB.java b/agent/src/share/classes/sun/jvm/hotspot/HSDB.java index 5e7e4fb1cd5e2c2b09569eb5127f632b3331f0cc..d48c1600723af48caa25049c53271e80030f3571 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/HSDB.java +++ b/agent/src/share/classes/sun/jvm/hotspot/HSDB.java @@ -1740,7 +1740,7 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener { 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 --git a/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java b/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java index 7ed801eb5b825f1481bd4596cb1033c29dfa9888..a9bc5983bdac6ae23de8f00b79f5e4e7f173f004 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java +++ b/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java @@ -102,6 +102,11 @@ public class CodeBlob extends VMObject { /** 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 @@ public class CodeBlob extends VMObject { } // 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 --git a/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java b/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java index bf7a12f5bb00c1fbc6c447347d2630872ce3b21c..6d0dd0fb6d07e9815dfc4b9be765c1300e7ae3a8 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java +++ b/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java @@ -59,6 +59,7 @@ public class CodeCache { 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 @@ public class CodeCache { 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 --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64RegisterMap.java b/agent/src/share/classes/sun/jvm/hotspot/code/MethodHandlesAdapterBlob.java similarity index 57% rename from agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64RegisterMap.java rename to agent/src/share/classes/sun/jvm/hotspot/code/MethodHandlesAdapterBlob.java index d5b9956181069cd89f74f88736880c1995132f1c..3b265e1b72ea455b7cde08d5bedaaea0ba323b6c 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64RegisterMap.java +++ b/agent/src/share/classes/sun/jvm/hotspot/code/MethodHandlesAdapterBlob.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,31 +22,37 @@ * */ -package sun.jvm.hotspot.runtime.amd64; +package sun.jvm.hotspot.code; -import sun.jvm.hotspot.asm.amd64.*; +import java.util.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; -public class AMD64RegisterMap extends RegisterMap { +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"); - /** This is the only public constructor */ - public AMD64RegisterMap(JavaThread thread, boolean updateMap) { - super(thread, updateMap); + // FIXME: add any needed fields } - protected AMD64RegisterMap(RegisterMap map) { - super(map); + public MethodHandlesAdapterBlob(Address addr) { + super(addr); } - public Object clone() { - AMD64RegisterMap retval = new AMD64RegisterMap(this); - return retval; + public boolean isMethodHandlesAdapterBlob() { + return true; } - // 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; } + public String getName() { + return "MethodHandlesAdapterBlob: " + super.getName(); + } } diff --git a/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java b/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java index 80da843d3ab9f2845766609d5f7f06cc33c8720b..d33aaecebee523d5fd6cbd4979345942572c8be4 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java +++ b/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java @@ -46,6 +46,7 @@ public class NMethod extends CodeBlob { /** 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 @@ public class NMethod extends CodeBlob { 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 @@ public class NMethod extends CodeBlob { /** 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 @@ public class NMethod extends CodeBlob { 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 @@ public class NMethod extends CodeBlob { 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 --git a/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java b/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java index c6bf5d78b5ea829c605e19eaf793df2d13b148ea..15846108911a6ea5267cfb4eedb59d4b2ff516f3 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java +++ b/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java @@ -38,6 +38,9 @@ public class PCDesc extends VMObject { 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 @@ public class PCDesc extends VMObject { 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 class PCDesc extends VMObject { 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 --git a/agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java b/agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java index 3f7dd76545110f89a009aa8002f96f154512f934..0fa8518c8301fa2e11742f48d991b44e6908447f 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java +++ b/agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java @@ -41,11 +41,15 @@ public class RicochetBlob extends SingletonBlob { } 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 class RicochetBlob extends SingletonBlob { 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 --git a/agent/src/share/classes/sun/jvm/hotspot/code/RuntimeStub.java b/agent/src/share/classes/sun/jvm/hotspot/code/RuntimeStub.java index 86f471be7e30728e718904c0b29ecf9d2a2756b0..fd0d72aaaceee327b45aa1b45b2c21dff46e47ae 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/code/RuntimeStub.java +++ b/agent/src/share/classes/sun/jvm/hotspot/code/RuntimeStub.java @@ -30,6 +30,8 @@ import sun.jvm.hotspot.runtime.*; 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 @@ public class RuntimeStub extends CodeBlob { 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 @@ public class RuntimeStub extends CodeBlob { return true; } + public boolean callerMustGCArguments() { + return callerMustGCArgumentsField.getValue(addr) != 0; + } + + public String getName() { return "RuntimeStub: " + super.getName(); } diff --git a/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java b/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java index 3e8857893e1532006480c593f2e4d60465056624..9433cf6864d6bf19214a7a397b16f5467f070a6f 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java +++ b/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java @@ -246,7 +246,7 @@ public class OopMapSet extends VMObject { } // 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 --git a/agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java b/agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java index 811075dc635a146cb1be0d63df5e3c3442687be1..d28bca18d2e5d9ceb37b4f5feba97253747ffcf4 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java +++ b/agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java @@ -28,11 +28,13 @@ import java.io.*; 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 @@ implements ReferenceType { 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 @@ implements ReferenceType { 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 --git a/agent/src/share/classes/sun/jvm/hotspot/jdi/StackFrameImpl.java b/agent/src/share/classes/sun/jvm/hotspot/jdi/StackFrameImpl.java index 8ef0aa1eebe1b812f44d2249eaf5375db7cc71eb..69461d3712a8e1f50647262c5a6dce9f3f1d7567 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/jdi/StackFrameImpl.java +++ b/agent/src/share/classes/sun/jvm/hotspot/jdi/StackFrameImpl.java @@ -123,6 +123,9 @@ public class StackFrameImpl extends MirrorImpl 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 @@ public class StackFrameImpl extends MirrorImpl 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 @@ public class StackFrameImpl extends MirrorImpl 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 --git a/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java b/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java index f8bb01adb960fcffb39e7ecd195ea1c27e618964..c999ff1a80ddad6f1b8c6c9015d76eb85c4f0a8e 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java +++ b/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java @@ -44,6 +44,7 @@ public class SystemDictionary { 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 @@ public class SystemDictionary { 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 @@ public class SystemDictionary { 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 --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java index d0d96740080fac43a97944caafac99b8d679e937..ba42e8da19ffddbad700d7cf5d99f23ac2f7ab45 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java @@ -93,6 +93,8 @@ public class CompiledVFrame extends JavaVFrame { } public StackValueCollection getLocals() { + if (getScope() == null) + return new StackValueCollection(); List scvList = getScope().getLocals(); if (scvList == null) return new StackValueCollection(); @@ -108,6 +110,8 @@ public class CompiledVFrame extends JavaVFrame { } public StackValueCollection getExpressions() { + if (getScope() == null) + return new StackValueCollection(); List scvList = getScope().getExpressions(); if (scvList == null) return new StackValueCollection(); diff --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java index 3b99ec291682221a875d26e209e5a97aa343a818..70eace55f33f5897de97bc80318f394c38adb31d 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java @@ -33,6 +33,7 @@ import sun.jvm.hotspot.c1.*; 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 @@ public abstract class Frame implements Cloneable { /** 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 abstract class Frame implements Cloneable { 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 abstract class Frame implements Cloneable { } } + 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 @@ public abstract class Frame implements Cloneable { 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 abstract class Frame implements Cloneable { 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 @@ public abstract class Frame implements Cloneable { 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 @@ public abstract class Frame implements Cloneable { // } } + 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 --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java index 63108f78dd44820ae239fdd9524e0c1311e4873d..a45cbc3640c450a0d215189e8d6a518d250788aa 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java @@ -128,14 +128,14 @@ public abstract class JavaVFrame extends VFrame { } // 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 --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java index 78ba7384cf26b5c22223c824db9e263d90a16e89..5cc5f94ec8d5c3c7802a35bcf208de90bf4c676a 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java @@ -100,7 +100,7 @@ public class StackValue { 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 --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/VFrame.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/VFrame.java index 98591fda6afecb8481d09dce4373b6ea0827bd06..ea1ec197c6e64ffe2c080f4277eb8d93a292e99e 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/VFrame.java +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/VFrame.java @@ -77,7 +77,7 @@ public class VFrame { 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 --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java index 4d333baa9a6f128a9c3ec9a96df29495d4d0b877..b1c52a353191ddb97b9b591a7e472ae5046f9d44 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -30,6 +30,7 @@ import java.util.*; 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 @@ public class VM { 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 @@ public class VM { 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 --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java index c5e4e6312379ae31336af3a8a0201430997c83c1..6acf0d9605c824e9e44d6bc3d7f9d56f19994bc7 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java @@ -29,6 +29,7 @@ import sun.jvm.hotspot.debugger.amd64.*; 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 @@ public class AMD64CurrentFrameGuess {
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 --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64Frame.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64Frame.java
deleted file mode 100644
index 6a5d02c36438675b561d91f253a979cfde0c4aca..0000000000000000000000000000000000000000
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64Frame.java
+++ /dev/null
@@ -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 --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/linux_amd64/LinuxAMD64JavaThreadPDAccess.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/linux_amd64/LinuxAMD64JavaThreadPDAccess.java
index ea025da0bfc555000c032ce3ca64685ca6bfe176..89fcb12b1a6a6ca614b3e507a7ae5f81744600d0 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/linux_amd64/LinuxAMD64JavaThreadPDAccess.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/linux_amd64/LinuxAMD64JavaThreadPDAccess.java
@@ -30,6 +30,7 @@ import sun.jvm.hotspot.debugger.*;
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 @@ public class LinuxAMD64JavaThreadPDAccess implements JavaThreadPDAccess {
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 @@ public class LinuxAMD64JavaThreadPDAccess implements JavaThreadPDAccess {
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 --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java
index d3c307c5535ecc5063cfe23c860cf3d613249b82..6891040c253a63d93a3403ff25e1b95b86f1102a 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java
@@ -30,6 +30,7 @@ import sun.jvm.hotspot.debugger.*;
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 @@ public class SolarisAMD64JavaThreadPDAccess implements JavaThreadPDAccess {
}
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 @@ public class SolarisAMD64JavaThreadPDAccess implements JavaThreadPDAccess {
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 --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java
index 5523f35005fef22cf715b517fe2691cfb6364ba1..3d55dabd85cd8b443b8e1d986a507eeeefbbd835 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java
@@ -236,7 +236,7 @@ public class SPARCFrame extends Frame {
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 @@ public class SPARCFrame extends Frame {
}
}
- 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.
-
-
- // 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();
+ // 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();
+ 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 @@ public class SPARCFrame extends Frame {
}
+ 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 @@ public class SPARCFrame extends Frame {
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 --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCRicochetFrame.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCRicochetFrame.java
new file mode 100644
index 0000000000000000000000000000000000000000..57fa927fc0745070f8ff5ddc492bac8352504a44
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCRicochetFrame.java
@@ -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 --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java
index 76a686fae1e8e1e97da089fcd85bb62c67befa4d..64785ee8c1ff4304882392f48c026fc535eb3450 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java
@@ -31,6 +31,7 @@ import sun.jvm.hotspot.debugger.win32.*;
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 @@ public class Win32AMD64JavaThreadPDAccess implements JavaThreadPDAccess {
}
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 @@ public class Win32AMD64JavaThreadPDAccess implements JavaThreadPDAccess {
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 --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java
index f824218c7800f0641c48d959c805e66ea1f4ba0e..41ef83276c455c97425bdec4c68d1feeaeb4d134 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java
@@ -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 @@ public class X86Frame extends Frame {
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 @@ public class X86Frame extends Frame {
}
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 @@ public class X86Frame extends Frame {
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 @@ public class X86Frame extends Frame {
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 @@ public class X86Frame extends Frame {
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 @@ public class X86Frame extends Frame {
}
}
- // 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 @@ public class X86Frame extends Frame {
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 @@ public class X86Frame extends Frame {
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 @@ public class X86Frame extends Frame {
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 @@ public class X86Frame extends Frame {
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 @@ public class X86Frame extends Frame {
// 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 @@ public class X86Frame extends Frame {
}
// 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());
- if (map.getUpdateMap() && cb.getOopMaps() != null) {
- OopMapSet.updateRegisterMap(this, cb, map, true);
- }
+ // 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 (VM.getVM().isClientCompiler()) {
- // Move this here for C1 and collecting oops in arguments (According to Rene)
- map.setIncludeArgumentOops(cb.callerMustGCArguments(map.getThread()));
- }
+ 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());
- 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());
+ 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);
}
- 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 class X86Frame extends Frame {
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 --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86RicochetFrame.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86RicochetFrame.java
new file mode 100644
index 0000000000000000000000000000000000000000..5d73ac96a7b76488595186184ea7a589a43cb48f
--- /dev/null
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86RicochetFrame.java
@@ -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 --git a/src/cpu/x86/vm/methodHandles_x86.hpp b/src/cpu/x86/vm/methodHandles_x86.hpp
index c4ed0b706c0115a05c36b3d0e650c3e30f960946..bf85c33c731165a752e966e07acbea76f553b5ee 100644
--- a/src/cpu/x86/vm/methodHandles_x86.hpp
+++ b/src/cpu/x86/vm/methodHandles_x86.hpp
@@ -110,6 +110,7 @@ public:
class RicochetFrame {
friend class MethodHandles;
+ friend class VMStructs;
private:
intptr_t* _continuation; // what to do when control gets back here
diff --git a/src/share/vm/c1/c1_LinearScan.cpp b/src/share/vm/c1/c1_LinearScan.cpp
index ef41cfd322436902fe2029a88947814a20d44c1a..38ee82acdd9499ba9b4426151ec317ae28167c42 100644
--- a/src/share/vm/c1/c1_LinearScan.cpp
+++ b/src/share/vm/c1/c1_LinearScan.cpp
@@ -2404,7 +2404,7 @@ OopMap* LinearScan::compute_oop_map(IntervalWalker* iw, LIR_Op* op, CodeEmitInfo
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 @@ OopMap* LinearScan::compute_oop_map(IntervalWalker* iw, LIR_Op* op, CodeEmitInfo
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 @@ OopMap* LinearScan::compute_oop_map(IntervalWalker* iw, LIR_Op* op, CodeEmitInfo
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 --git a/src/share/vm/c1/c1_LinearScan.hpp b/src/share/vm/c1/c1_LinearScan.hpp
index 51789ebd85d240fe1f06a3b957c9597070821650..133cc85014c0b3ad0f7b13b58091838642d92366 100644
--- a/src/share/vm/c1/c1_LinearScan.hpp
+++ b/src/share/vm/c1/c1_LinearScan.hpp
@@ -352,6 +352,13 @@ class LinearScan : public CompilationResourceObj {
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