提交 779f33aa 编写于 作者: N never

7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)

Reviewed-by: kvn
上级 078b0f05
......@@ -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()) {
......
......@@ -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));
......
......@@ -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;
}
......
/*
* 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();
}
}
......@@ -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); }
......
......@@ -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) {
......
......@@ -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));
}
}
......@@ -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();
}
......
......@@ -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];
......
......@@ -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);
}
......
......@@ -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;
......
......@@ -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);
......
......@@ -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();
......
......@@ -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
}
......
......@@ -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 */
......
......@@ -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;
......
......@@ -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);
......
......@@ -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();
......
......@@ -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()) {
......
/*
* 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));
}
}
}
}
......@@ -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());
}
}
......
......@@ -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());
}
}
......
......@@ -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");
......
/*
* 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();
}
}
......@@ -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());
}
}
......
......@@ -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);
}
......
/*
* 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);
}
}
......@@ -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
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
......@@ -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;
......
......@@ -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,
......
......@@ -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
......
......@@ -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;
......
......@@ -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 */ \
/********************************/ \
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册