Mercurial > hg > graal-compiler
diff agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | cecd8eb4e0ca |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,300 @@ +/* + * Copyright 2000-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.runtime; + +import java.util.*; +import sun.jvm.hotspot.code.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.utilities.*; + +/** FIXME: missing many accessors; all we have right now is the method + and BCI. NOTE that this has been modified from the VM's version to + handle NULL ScopeDescs for the debugging case. This simplifies + using code a great deal. */ + +public class CompiledVFrame extends JavaVFrame { + private ScopeDesc scope; + private boolean mayBeImprecise; + + public CompiledVFrame(Frame fr, RegisterMap regMap, JavaThread thread, ScopeDesc scope, boolean mayBeImprecise) { + super(fr, regMap, thread); + this.scope = scope; + this.mayBeImprecise = mayBeImprecise; + if (!VM.getVM().isDebugging()) { + Assert.that(scope != null, "scope must be present"); + } + } + + public boolean isTop() { + if (VM.getVM().isDebugging()) { + return (getScope() == null || getScope().isTop()); + } else { + return getScope().isTop(); + } + } + + public boolean isCompiledFrame() { + return true; + } + + public boolean isDeoptimized() { + return fr.isDeoptimized(); + } + + public boolean mayBeImpreciseDbg() { + return mayBeImprecise; + } + + /** Returns the active method */ + public NMethod getCode() { + return VM.getVM().getCodeCache().findNMethod(fr.getPC()); + } + + /** Returns the active method. Does not perform a guarantee + regarding unloaded methods -- more suitable for debugging + system. */ + public NMethod getCodeUnsafe() { + return VM.getVM().getCodeCache().findNMethodUnsafe(fr.getPC()); + } + + /** Returns the ScopeDesc */ + public ScopeDesc getScope() { + return scope; + } + + public Method getMethod() { + if (VM.getVM().isDebugging() && getScope() == null) { + return getCodeUnsafe().getMethod(); + } + return getScope().getMethod(); + } + + public StackValueCollection getLocals() { + List scvList = getScope().getLocals(); + if (scvList == null) + return new StackValueCollection(); + + // scvList is the list of ScopeValues describing the JVM stack state. + // There is one scv_list entry for every JVM stack state in use. + int length = scvList.size(); + StackValueCollection result = new StackValueCollection(length); + for( int i = 0; i < length; i++ ) + result.add( createStackValue((ScopeValue) scvList.get(i)) ); + + return result; + } + + public StackValueCollection getExpressions() { + List scvList = getScope().getExpressions(); + if (scvList == null) + return new StackValueCollection(); + + // scvList is the list of ScopeValues describing the JVM stack state. + // There is one scv_list entry for every JVM stack state in use. + int length = scvList.size(); + StackValueCollection result = new StackValueCollection(length); + for( int i = 0; i < length; i++ ) + result.add( createStackValue((ScopeValue) scvList.get(i)) ); + + return result; + } + + /** Returns List<MonitorInfo> */ + public List getMonitors() { + List monitors = getScope().getMonitors(); + if (monitors == null) { + return new ArrayList(); + } + List result = new ArrayList(monitors.size()); + for (int i = 0; i < monitors.size(); i++) { + MonitorValue mv = (MonitorValue) monitors.get(i); + StackValue ownerSV = createStackValue(mv.owner()); // it is an oop + result.add(new MonitorInfo(ownerSV.getObject(), resolveMonitorLock(mv.basicLock()))); + } + return result; + } + + public int getBCI() { + int raw = getRawBCI(); + return ((raw == DebugInformationRecorder.SYNCHRONIZATION_ENTRY_BCI) ? 0 : raw); + } + + /** Returns SynchronizationEntryBCI or bci() (used for synchronization) */ + public int getRawBCI() { + if (VM.getVM().isDebugging() && getScope() == null) { + return 0; // No debugging information! + } + return getScope().getBCI(); + } + + /** Returns the sender vframe */ + public VFrame sender() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(isTop(), "just checking"); + } + return sender(false); + } + + public VFrame sender(boolean mayBeImprecise) { + if (!VM.getVM().isDebugging()) { + if (Assert.ASSERTS_ENABLED) { + Assert.that(scope != null, "When new stub generator is in place, then scope can never be NULL"); + } + } + Frame f = (Frame) getFrame().clone(); + return (isTop() + ? super.sender(false) + : new CompiledVFrame(f, getRegisterMap(), getThread(), getScope().sender(), mayBeImprecise)); + } + + private StackValue createStackValue(ScopeValue sv) { + // FIXME: this code appears to be out-of-date with respect to the VM especially in 64-bit mode + if (sv.isLocation()) { + // Stack or register value + Location loc = ((LocationValue) sv).getLocation(); + + if (loc.isIllegal()) return new StackValue(); + + // First find address of value + Address valueAddr = loc.isRegister() + // Value was in a callee-save register + ? getRegisterMap().getLocation(new VMReg(loc.getRegisterNumber())) + // Else value was directly saved on the stack. The frame's original stack pointer, + // before any extension by its callee (due to Compiler1 linkage on SPARC), must be used. + : ((Address)fr.getUnextendedSP()).addOffsetTo(loc.getStackOffset()); + + // Then package it right depending on type + if (loc.holdsFloat()) { // Holds a float in a double register? + // The callee has no clue whether the register holds a float, + // double or is unused. He always saves a double. Here we know + // a double was saved, but we only want a float back. Narrow the + // saved double to the float that the JVM wants. + if (Assert.ASSERTS_ENABLED) { + Assert.that( loc.isRegister(), "floats always saved to stack in 1 word" ); + } + float value = (float) valueAddr.getJDoubleAt(0); + return new StackValue(Float.floatToIntBits(value) & 0xFFFFFFFF); // 64-bit high half is stack junk + } else if (loc.holdsInt()) { // Holds an int in a long register? + // The callee has no clue whether the register holds an int, + // long or is unused. He always saves a long. Here we know + // a long was saved, but we only want an int back. Narrow the + // saved long to the int that the JVM wants. + if (Assert.ASSERTS_ENABLED) { + Assert.that( loc.isRegister(), "ints always saved to stack in 1 word" ); + } + return new StackValue(valueAddr.getJLongAt(0) & 0xFFFFFFFF); + } else if( loc.holdsOop() ) { // Holds an oop? + return new StackValue(valueAddr.getOopHandleAt(0)); + } else if( loc.holdsDouble() ) { + // Double value in a single stack slot + return new StackValue(valueAddr.getJIntAt(0) & 0xFFFFFFFF); + } else if(loc.holdsAddr()) { + if (Assert.ASSERTS_ENABLED) { + Assert.that(!VM.getVM().isServerCompiler(), "No address type for locations with C2 (jsr-s are inlined)"); + } + // FIXME: not yet implemented (no access to safepoint state yet) + return new StackValue(0); + // intptr_t return_addr_tmp = *(intptr_t *)value_addr; + // int bci = -1; + // // Get the bci of the jsr that generated this returnAddress value. + // // If the destination of a jsr is a block that ends with a return or throw, then + // // the GraphBuilder converts the jsr into a direct goto. This has the side effect that + // // the return address for the jsr gets emitted as a bci instead of as a real pc + // if (code()->contains((address)return_addr_tmp)) { + // ScopeDesc* scope = code()->scope_desc_at((address)(return_addr_tmp - jsr_call_offset), false); + // bci = scope->bci(); + // } else { + // bci = (int)return_addr_tmp; + // } + // // no need to lock method as this happens at Safepoint + // assert (SafepointSynchronize::is_at_safepoint(), "must be at safepoint, otherwise lock method()"); + // // make sure bci points to jsr + // Bytecode* bytecode = Bytecode_at(method()->bcp_from(bci)); + // Bytecodes::Code bc = bytecode->code(); + // assert (bc == Bytecodes::_jsr || bc == Bytecodes::_jsr_w, "must be jsr"); + // + // // the real returnAddress is the bytecode following the jsr + // return new StackValue((intptr_t)(bci + Bytecodes::length_for(bc))); + } else if (VM.getVM().isLP64() && loc.holdsLong()) { + if ( loc.isRegister() ) { + // Long value in two registers, high half in the first, low in the second + return new StackValue(((valueAddr.getJLongAt(0) & 0xFFFFFFFF) << 32) | + ((valueAddr.getJLongAt(8) & 0xFFFFFFFF))); + } else { + // Long value in a single stack slot + return new StackValue(valueAddr.getJLongAt(0)); + } + } else if( loc.isRegister() ) { + // At the moment, all non-oop values in registers are 4 bytes, + // including double and long halves (see Compile::FillLocArray() in + // opto/output.cpp). Haul them out as such and return a StackValue + // containing an image of the value as it appears in a stack slot. + // If this is a double or long half, the interpreter _must_ deal + // with doubles and longs as entities split across two stack slots. + // To change this so doubles and/or longs can live in one stack slot, + // a StackValue will have to understand that it can contain an + // undivided double or long, implying that a Location (and the debug + // info mechanism) and FillLocArray() will also have to understand it. + return new StackValue(valueAddr.getJIntAt(0) & 0xFFFFFFFF); + } else { + return new StackValue(valueAddr.getJIntAt(0) & 0xFFFFFFFF); + } + } else if (sv.isConstantInt()) { + // Constant int: treat same as register int. + return new StackValue(((ConstantIntValue) sv).getValue() & 0xFFFFFFFF); + } else if (sv.isConstantOop()) { + // constant oop + return new StackValue(((ConstantOopReadValue) sv).getValue()); + } else if (sv.isConstantDouble()) { + // Constant double in a single stack slot + double d = ((ConstantDoubleValue) sv).getValue(); + return new StackValue(Double.doubleToLongBits(d) & 0xFFFFFFFF); + } else if (VM.getVM().isLP64() && sv.isConstantLong()) { + // Constant long in a single stack slot + return new StackValue(((ConstantLongValue) sv).getValue() & 0xFFFFFFFF); + } + + // Unknown ScopeValue type + Assert.that(false, "Should not reach here"); + return new StackValue(0); // dummy + } + + private BasicLock resolveMonitorLock(Location location) { + if (Assert.ASSERTS_ENABLED) { + Assert.that(location.isStack(), "for now we only look at the stack"); + } + int byteOffset = location.getStackOffset(); + // (stack picture) + // high: [ ] byte_offset + wordSize + // low [ ] byte_offset + // + // sp-> [ ] 0 + // the byte_offset is the distance from the stack pointer to the lowest address + // The frame's original stack pointer, before any extension by its callee + // (due to Compiler1 linkage on SPARC), must be used. + return new BasicLock(getFrame().getUnextendedSP().addOffsetTo(byteOffset)); + } +}