Mercurial > hg > truffle
diff agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java @ 3908:7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
Reviewed-by: kvn
author | never |
---|---|
date | Mon, 05 Sep 2011 17:09:05 -0700 |
parents | c18cbe5936b8 |
children | 1d7922586cf6 |
line wrap: on
line diff
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java Sat Sep 03 14:03:54 2011 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java Mon Sep 05 17:09:05 2011 -0700 @@ -25,7 +25,6 @@ package sun.jvm.hotspot.runtime.x86; import java.util.*; -import sun.jvm.hotspot.asm.x86.*; import sun.jvm.hotspot.code.*; import sun.jvm.hotspot.compiler.*; import sun.jvm.hotspot.debugger.*; @@ -62,11 +61,13 @@ private static int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET; // Entry frames - private static final int ENTRY_FRAME_CALL_WRAPPER_OFFSET = 2; + private static int ENTRY_FRAME_CALL_WRAPPER_OFFSET; // Native frames private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET = 2; + private static VMReg rbp; + static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -76,19 +77,23 @@ } private static synchronized void initialize(TypeDataBase db) { - if (VM.getVM().isCore()) { - INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; - } else { - INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; - INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1; - } + INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; + INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1; INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1; INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1; INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1; INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; + + ENTRY_FRAME_CALL_WRAPPER_OFFSET = db.lookupIntConstant("frame::entry_frame_call_wrapper_offset"); + if (VM.getVM().getAddressSize() == 4) { + rbp = new VMReg(5); + } else { + rbp = new VMReg(5 << 1); + } } + // an additional field beyond sp and pc: Address raw_fp; // frame pointer private Address raw_unextendedSP; @@ -102,7 +107,7 @@ CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); if (cb != null && cb.isJavaMethod()) { NMethod nm = (NMethod) cb; - if (pc.equals(nm.deoptBegin())) { + if (pc.equals(nm.deoptHandlerBegin())) { if (Assert.ASSERTS_ENABLED) { Assert.that(this.getUnextendedSP() != null, "null SP in Java frame"); } @@ -119,6 +124,7 @@ this.raw_unextendedSP = raw_sp; this.raw_fp = raw_fp; this.pc = pc; + adjustUnextendedSP(); // Frame must be fully constructed before this call adjustForDeopt(); @@ -134,6 +140,7 @@ this.raw_unextendedSP = raw_sp; this.raw_fp = raw_fp; this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); + adjustUnextendedSP(); // Frame must be fully constructed before this call adjustForDeopt(); @@ -144,24 +151,18 @@ } } - // This constructor should really take the unextended SP as an arg - // but then the constructor is ambiguous with constructor that takes - // a PC so take an int and convert it. - public X86Frame(Address raw_sp, Address raw_fp, long extension) { + public X86Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) { this.raw_sp = raw_sp; - if (raw_sp == null) { - this.raw_unextendedSP = null; - } else { - this.raw_unextendedSP = raw_sp.addOffsetTo(extension); - } + this.raw_unextendedSP = raw_unextendedSp; this.raw_fp = raw_fp; - this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); + this.pc = pc; + adjustUnextendedSP(); // Frame must be fully constructed before this call adjustForDeopt(); if (DEBUG) { - System.out.println("X86Frame(sp, fp): " + this); + System.out.println("X86Frame(sp, unextendedSP, fp, pc): " + this); dumpStack(); } @@ -172,7 +173,6 @@ frame.raw_sp = raw_sp; frame.raw_unextendedSP = raw_unextendedSP; frame.raw_fp = raw_fp; - frame.raw_fp = raw_fp; frame.pc = pc; frame.deoptimized = deoptimized; return frame; @@ -269,19 +269,18 @@ if (isEntryFrame()) return senderForEntryFrame(map); if (isInterpretedFrame()) return senderForInterpreterFrame(map); + if (isRicochetFrame()) return senderForRicochetFrame(map); - if (!VM.getVM().isCore()) { - if(cb == null) { - cb = VM.getVM().getCodeCache().findBlob(getPC()); - } else { - if (Assert.ASSERTS_ENABLED) { - Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same"); - } + if(cb == null) { + cb = VM.getVM().getCodeCache().findBlob(getPC()); + } else { + if (Assert.ASSERTS_ENABLED) { + Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same"); } + } - if (cb != null) { - return senderForCompiledFrame(map, cb); - } + if (cb != null) { + return senderForCompiledFrame(map, cb); } // Must be native-compiled frame, i.e. the marshaling code for native @@ -289,7 +288,20 @@ return new X86Frame(getSenderSP(), getLink(), getSenderPC()); } + private Frame senderForRicochetFrame(X86RegisterMap map) { + if (DEBUG) { + System.out.println("senderForRicochetFrame"); + } + X86RicochetFrame f = X86RicochetFrame.fromFrame(this); + if (map.getUpdateMap()) + updateMapWithSavedLink(map, f.senderLinkAddress()); + return new X86Frame(f.extendedSenderSP(), f.exactSenderSP(), f.senderLink(), f.senderPC()); + } + private Frame senderForEntryFrame(X86RegisterMap map) { + if (DEBUG) { + System.out.println("senderForEntryFrame"); + } if (Assert.ASSERTS_ENABLED) { Assert.that(map != null, "map must be set"); } @@ -313,7 +325,37 @@ return fr; } + //------------------------------------------------------------------------------ + // frame::adjust_unextended_sp + private void adjustUnextendedSP() { + // If we are returning to a compiled MethodHandle call site, the + // saved_fp will in fact be a saved value of the unextended SP. The + // simplest way to tell whether we are returning to such a call site + // is as follows: + + CodeBlob cb = cb(); + NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull(); + if (senderNm != null) { + // If the sender PC is a deoptimization point, get the original + // PC. For MethodHandle call site the unextended_sp is stored in + // saved_fp. + if (senderNm.isDeoptMhEntry(getPC())) { + // DEBUG_ONLY(verifyDeoptMhOriginalPc(senderNm, getFP())); + raw_unextendedSP = getFP(); + } + else if (senderNm.isDeoptEntry(getPC())) { + // DEBUG_ONLY(verifyDeoptOriginalPc(senderNm, raw_unextendedSp)); + } + else if (senderNm.isMethodHandleReturn(getPC())) { + raw_unextendedSP = getFP(); + } + } + } + private Frame senderForInterpreterFrame(X86RegisterMap map) { + if (DEBUG) { + System.out.println("senderForInterpreterFrame"); + } Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); Address sp = addressOfStackSlot(SENDER_SP_OFFSET); // We do not need to update the callee-save register mapping because above @@ -323,10 +365,21 @@ // However c2 no longer uses callee save register for java calls so there // are no callee register to find. - return new X86Frame(sp, getLink(), unextendedSP.minus(sp)); + if (map.getUpdateMap()) + updateMapWithSavedLink(map, addressOfStackSlot(LINK_OFFSET)); + + return new X86Frame(sp, unextendedSP, getLink(), getSenderPC()); + } + + private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) { + map.setLocation(rbp, savedFPAddr); } private Frame senderForCompiledFrame(X86RegisterMap map, CodeBlob cb) { + if (DEBUG) { + System.out.println("senderForCompiledFrame"); + } + // // NOTE: some of this code is (unfortunately) duplicated in X86CurrentFrameGuess // @@ -336,41 +389,35 @@ } // frame owned by optimizing compiler - Address sender_sp = null; - - if (VM.getVM().isClientCompiler()) { - sender_sp = addressOfStackSlot(SENDER_SP_OFFSET); - } else { - if (Assert.ASSERTS_ENABLED) { - Assert.that(cb.getFrameSize() >= 0, "Compiled by Compiler1: do not use"); - } - sender_sp = getUnextendedSP().addOffsetTo(cb.getFrameSize()); + if (Assert.ASSERTS_ENABLED) { + Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size"); } + Address senderSP = getUnextendedSP().addOffsetTo(cb.getFrameSize()); // On Intel the return_address is always the word on the stack - Address sender_pc = sender_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); + Address senderPC = senderSP.getAddressAt(-1 * VM.getVM().getAddressSize()); + + // This is the saved value of EBP which may or may not really be an FP. + // It is only an FP if the sender is an interpreter frame (or C1?). + Address savedFPAddr = senderSP.addOffsetTo(- SENDER_SP_OFFSET * VM.getVM().getAddressSize()); - if (map.getUpdateMap() && cb.getOopMaps() != null) { - OopMapSet.updateRegisterMap(this, cb, map, true); + if (map.getUpdateMap()) { + // Tell GC to use argument oopmaps for some runtime stubs that need it. + // For C1, the runtime stub might not have oop maps, so set this flag + // outside of update_register_map. + map.setIncludeArgumentOops(cb.callerMustGCArguments()); + + if (cb.getOopMaps() != null) { + OopMapSet.updateRegisterMap(this, cb, map, true); + } + + // Since the prolog does the save and restore of EBP there is no oopmap + // for it so we must fill in its location as if there was an oopmap entry + // since if our caller was compiled code there could be live jvm state in it. + updateMapWithSavedLink(map, savedFPAddr); } - if (VM.getVM().isClientCompiler()) { - // Move this here for C1 and collecting oops in arguments (According to Rene) - map.setIncludeArgumentOops(cb.callerMustGCArguments(map.getThread())); - } - - Address saved_fp = null; - if (VM.getVM().isClientCompiler()) { - saved_fp = getFP().getAddressAt(0); - } else if (VM.getVM().isServerCompiler() && - (VM.getVM().getInterpreter().contains(sender_pc) || - VM.getVM().getStubRoutines().returnsToCallStub(sender_pc))) { - // C2 prologue saves EBP in the usual place. - // however only use it if the sender had link infomration in it. - saved_fp = sender_sp.getAddressAt(-2 * VM.getVM().getAddressSize()); - } - - return new X86Frame(sender_sp, saved_fp, sender_pc); + return new X86Frame(senderSP, savedFPAddr.getAddressAt(0), senderPC); } protected boolean hasSenderPD() { @@ -403,14 +450,6 @@ public Address getSenderSP() { return addressOfStackSlot(SENDER_SP_OFFSET); } - public Address compiledArgumentToLocationPD(VMReg reg, RegisterMap regMap, int argSize) { - if (VM.getVM().isCore() || VM.getVM().isClientCompiler()) { - throw new RuntimeException("Should not reach here"); - } - - return oopMapRegToLocation(reg, regMap); - } - public Address addressOfInterpreterFrameLocals() { return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET); }