aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornever <none@none>2011-09-05 17:09:05 -0700
committernever <none@none>2011-09-05 17:09:05 -0700
commit07785d075ede6e3ac1c3a0605fe1a02428aa1323 (patch)
tree78caeff9520b0e924b49412b530129665e374095
parent7d8079e852bda4486b0e1df934d602b729c2d0ab (diff)
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
Reviewed-by: kvn
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/HSDB.java2
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java7
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java5
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/code/MethodHandlesAdapterBlob.java (renamed from agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64RegisterMap.java)40
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java24
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java14
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java18
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/code/RuntimeStub.java8
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java2
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java24
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/jdi/StackFrameImpl.java62
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java6
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java4
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java31
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java4
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java2
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/VFrame.java2
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java16
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java3
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64Frame.java528
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/linux_amd64/LinuxAMD64JavaThreadPDAccess.java9
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java11
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java93
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCRicochetFrame.java77
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java11
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java173
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86RicochetFrame.java81
-rw-r--r--src/cpu/x86/vm/methodHandles_x86.hpp1
-rw-r--r--src/share/vm/c1/c1_LinearScan.cpp6
-rw-r--r--src/share/vm/c1/c1_LinearScan.hpp7
-rw-r--r--src/share/vm/code/pcDesc.cpp5
-rw-r--r--src/share/vm/code/pcDesc.hpp32
-rw-r--r--src/share/vm/runtime/sharedRuntime.hpp2
-rw-r--r--src/share/vm/runtime/thread.cpp38
-rw-r--r--src/share/vm/runtime/thread.hpp1
-rw-r--r--src/share/vm/runtime/vmStructs.cpp56
36 files changed, 677 insertions, 728 deletions
diff --git a/agent/src/share/classes/sun/jvm/hotspot/HSDB.java b/agent/src/share/classes/sun/jvm/hotspot/HSDB.java
index 5e7e4fb1c..d48c16007 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 7ed801eb5..a9bc5983b 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 bf7a12f5b..6d0dd0fb6 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
index d5b995618..3b265e1b7 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 80da843d3..d33aaeceb 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 c6bf5d78b..158461089 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 3f7dd7654..0fa8518c8 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 86f471be7..fd0d72aaa 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 3e8857893..9433cf686 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 811075dc6..d28bca18d 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 8ef0aa1ee..69461d371 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 f8bb01adb..c999ff1a8 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 d0d967400..ba42e8da1 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 3b99ec291..70eace55f 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 63108f78d..a45cbc364 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 78ba7384c..5cc5f94ec 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 98591fda6..ea1ec197c 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 4d333baa9..b1c52a353 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 c5e4e6312..6acf0d960 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.*;
/** <P> 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 6a5d02c36..000000000
--- 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 ea025da0b..89fcb12b1 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 d3c307c55..6891040c2 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 5523f3500..3d55dabd8 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 000000000..57fa927fc
--- /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 76a686fae..64785ee8c 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 f824218c7..41ef83276 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 000000000..5d73ac96a
--- /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 c4ed0b706..bf85c33c7 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 ef41cfd32..38ee82acd 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 51789ebd8..133cc8501 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<ScopeValue*>* scope_values);
int append_scope_value_for_operand(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values);
diff --git a/src/share/vm/code/pcDesc.cpp b/src/share/vm/code/pcDesc.cpp
index d6c375163..7ba25464f 100644
--- a/src/share/vm/code/pcDesc.cpp
+++ b/src/share/vm/code/pcDesc.cpp
@@ -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 @@ address PcDesc::real_pc(const nmethod* code) const {
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 --git a/src/share/vm/code/pcDesc.hpp b/src/share/vm/code/pcDesc.hpp
index 99a6e4c8e..83ec92149 100644
--- a/src/share/vm/code/pcDesc.hpp
+++ b/src/share/vm/code/pcDesc.hpp
@@ -39,15 +39,17 @@ class PcDesc VALUE_OBJ_CLASS_SPEC {
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 @@ class PcDesc VALUE_OBJ_CLASS_SPEC {
};
// 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 @@ class PcDesc VALUE_OBJ_CLASS_SPEC {
_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 --git a/src/share/vm/runtime/sharedRuntime.hpp b/src/share/vm/runtime/sharedRuntime.hpp
index d42ade40a..145dacd4b 100644
--- a/src/share/vm/runtime/sharedRuntime.hpp
+++ b/src/share/vm/runtime/sharedRuntime.hpp
@@ -45,6 +45,8 @@ class vframeStream;
// information, etc.
class SharedRuntime: AllStatic {
+ friend class VMStructs;
+
private:
static methodHandle resolve_sub_helper(JavaThread *thread,
bool is_virtual,
diff --git a/src/share/vm/runtime/thread.cpp b/src/share/vm/runtime/thread.cpp
index 18465a307..4553ea62f 100644
--- a/src/share/vm/runtime/thread.cpp
+++ b/src/share/vm/runtime/thread.cpp
@@ -2859,6 +2859,44 @@ void JavaThread::trace_frames() {
}
}
+class PrintAndVerifyOopClosure: public OopClosure {
+ protected:
+ template <class T> inline void do_oop_work(T* p) {
+ oop obj = oopDesc::load_decode_heap_oop(p);
+ if (obj == NULL) return;
+ tty->print(INTPTR_FORMAT ": ", p);
+ if (obj->is_oop_or_null()) {
+ if (obj->is_objArray()) {
+ tty->print_cr("valid objArray: " INTPTR_FORMAT, (oopDesc*) obj);
+ } else {
+ obj->print();
+ }
+ } else {
+ tty->print_cr("invalid oop: " INTPTR_FORMAT, (oopDesc*) obj);
+ }
+ tty->cr();
+ }
+ public:
+ virtual void do_oop(oop* p) { do_oop_work(p); }
+ virtual void do_oop(narrowOop* p) { do_oop_work(p); }
+};
+
+
+static void oops_print(frame* f, const RegisterMap *map) {
+ PrintAndVerifyOopClosure print;
+ f->print_value();
+ f->oops_do(&print, NULL, (RegisterMap*)map);
+}
+
+// Print our all the locations that contain oops and whether they are
+// valid or not. This useful when trying to find the oldest frame
+// where an oop has gone bad since the frame walk is from youngest to
+// oldest.
+void JavaThread::trace_oops() {
+ tty->print_cr("[Trace oops]");
+ frames_do(oops_print);
+}
+
#ifdef ASSERT
// Print or validate the layout of stack frames
diff --git a/src/share/vm/runtime/thread.hpp b/src/share/vm/runtime/thread.hpp
index 532ca1a55..4d5478bdc 100644
--- a/src/share/vm/runtime/thread.hpp
+++ b/src/share/vm/runtime/thread.hpp
@@ -1375,6 +1375,7 @@ public:
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 --git a/src/share/vm/runtime/vmStructs.cpp b/src/share/vm/runtime/vmStructs.cpp
index d1cb2cc7d..540649784 100644
--- a/src/share/vm/runtime/vmStructs.cpp
+++ b/src/share/vm/runtime/vmStructs.cpp
@@ -652,6 +652,7 @@ static inline uint64_t cast_uint64_t(size_t x)
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 @@ static inline uint64_t cast_uint64_t(size_t x)
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 @@ static inline uint64_t cast_uint64_t(size_t x)
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 @@ static inline uint64_t cast_uint64_t(size_t x)
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 @@ static inline uint64_t cast_uint64_t(size_t x)
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 @@ static inline uint64_t cast_uint64_t(size_t x)
/* 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 @@ static inline uint64_t cast_uint64_t(size_t x)
\
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 */ \
/********************************/ \