Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstMethod.java
41161 views
/*1* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324package sun.jvm.hotspot.oops;2526import java.io.*;27import java.util.*;28import sun.jvm.hotspot.code.*;29import sun.jvm.hotspot.debugger.*;30import sun.jvm.hotspot.interpreter.*;31import sun.jvm.hotspot.memory.*;32import sun.jvm.hotspot.runtime.*;33import sun.jvm.hotspot.types.*;34import sun.jvm.hotspot.utilities.*;35import sun.jvm.hotspot.utilities.Observable;36import sun.jvm.hotspot.utilities.Observer;3738public class ConstMethod extends Metadata {39static {40VM.registerVMInitializedObserver(new Observer() {41public void update(Observable o, Object data) {42initialize(VM.getVM().getTypeDataBase());43}44});45}4647// anon-enum constants for _flags.48private static int HAS_LINENUMBER_TABLE;49private static int HAS_CHECKED_EXCEPTIONS;50private static int HAS_LOCALVARIABLE_TABLE;51private static int HAS_EXCEPTION_TABLE;52private static int HAS_GENERIC_SIGNATURE;53private static int HAS_METHOD_ANNOTATIONS;54private static int HAS_PARAMETER_ANNOTATIONS;55private static int HAS_METHOD_PARAMETERS;56private static int HAS_DEFAULT_ANNOTATIONS;57private static int HAS_TYPE_ANNOTATIONS;5859private static final int sizeofShort = 2;6061private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {62Type type = db.lookupType("ConstMethod");63constants = new MetadataField(type.getAddressField("_constants"), 0);64constMethodSize = new CIntField(type.getCIntegerField("_constMethod_size"), 0);65flags = new CIntField(type.getCIntegerField("_flags"), 0);6667// enum constants for flags68HAS_LINENUMBER_TABLE = db.lookupIntConstant("ConstMethod::_has_linenumber_table").intValue();69HAS_CHECKED_EXCEPTIONS = db.lookupIntConstant("ConstMethod::_has_checked_exceptions").intValue();70HAS_LOCALVARIABLE_TABLE = db.lookupIntConstant("ConstMethod::_has_localvariable_table").intValue();71HAS_EXCEPTION_TABLE = db.lookupIntConstant("ConstMethod::_has_exception_table").intValue();72HAS_GENERIC_SIGNATURE = db.lookupIntConstant("ConstMethod::_has_generic_signature").intValue();73HAS_METHOD_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_method_annotations").intValue();74HAS_PARAMETER_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_parameter_annotations").intValue();75HAS_METHOD_PARAMETERS = db.lookupIntConstant("ConstMethod::_has_method_parameters").intValue();76HAS_DEFAULT_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_default_annotations").intValue();77HAS_TYPE_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_type_annotations").intValue();7879// Size of Java bytecodes allocated immediately after ConstMethod*.80codeSize = new CIntField(type.getCIntegerField("_code_size"), 0);81nameIndex = new CIntField(type.getCIntegerField("_name_index"), 0);82signatureIndex = new CIntField(type.getCIntegerField("_signature_index"), 0);83idnum = new CIntField(type.getCIntegerField("_method_idnum"), 0);84maxStack = new CIntField(type.getCIntegerField("_max_stack"), 0);85maxLocals = new CIntField(type.getCIntegerField("_max_locals"), 0);86sizeOfParameters = new CIntField(type.getCIntegerField("_size_of_parameters"), 0);8788// start of byte code89bytecodeOffset = type.getSize();9091type = db.lookupType("MethodParametersElement");92methodParametersElementSize = type.getSize();9394type = db.lookupType("CheckedExceptionElement");95checkedExceptionElementSize = type.getSize();9697type = db.lookupType("LocalVariableTableElement");98localVariableTableElementSize = type.getSize();99100type = db.lookupType("ExceptionTableElement");101exceptionTableElementSize = type.getSize();102}103104public ConstMethod(Address addr) {105super(addr);106}107108// Fields109private static MetadataField constants;110private static CIntField constMethodSize;111private static CIntField flags;112private static CIntField codeSize;113private static CIntField nameIndex;114private static CIntField signatureIndex;115private static CIntField idnum;116private static CIntField maxStack;117private static CIntField maxLocals;118private static CIntField sizeOfParameters;119120// start of bytecode121private static long bytecodeOffset;122private static long methodParametersElementSize;123private static long checkedExceptionElementSize;124private static long localVariableTableElementSize;125private static long exceptionTableElementSize;126127public Method getMethod() {128InstanceKlass ik = (InstanceKlass)getConstants().getPoolHolder();129MethodArray methods = ik.getMethods();130return methods.at((int)getIdNum());131}132133// Accessors for declared fields134public ConstantPool getConstants() {135return (ConstantPool) constants.getValue(this);136}137138public long getConstMethodSize() {139return constMethodSize.getValue(this);140}141142public long getFlags() {143return flags.getValue(this);144}145146public long getCodeSize() {147return codeSize.getValue(this);148}149150public long getNameIndex() {151return nameIndex.getValue(this);152}153154public long getSignatureIndex() {155return signatureIndex.getValue(this);156}157158public long getGenericSignatureIndex() {159if (hasGenericSignature()) {160return getAddress().getCIntegerAt(offsetOfGenericSignatureIndex(), 2, true);161} else {162return 0;163}164}165166public long getIdNum() {167return idnum.getValue(this);168}169170public long getMaxStack() {171return maxStack.getValue(this);172}173174public long getMaxLocals() {175return maxLocals.getValue(this);176}177178public long getSizeOfParameters() {179return sizeOfParameters.getValue(this);180}181182public Symbol getName() {183return getMethod().getName();184}185186public Symbol getSignature() {187return getMethod().getSignature();188}189190public Symbol getGenericSignature() {191return getMethod().getGenericSignature();192}193194// bytecode accessors195196/** See if address is in the Method's bytecodes */197public boolean isAddressInMethod(Address bcp) {198Address bytecodeStart = getAddress().addOffsetTo(bytecodeOffset);199Address bytecodeEnd = bytecodeStart.addOffsetTo(getCodeSize() - 1);200if (bcp.greaterThanOrEqual(bytecodeStart) && bcp.lessThanOrEqual(bytecodeEnd)) {201return true;202} else {203return false;204}205}206207/** Get a bytecode or breakpoint at the given bci */208public int getBytecodeOrBPAt(int bci) {209return getAddress().getJByteAt(bytecodeOffset + bci) & 0xFF;210}211212public byte getBytecodeByteArg(int bci) {213return (byte) getBytecodeOrBPAt(bci);214}215216/** Fetches a 16-bit big-endian ("Java ordered") value from the217bytecode stream */218public short getBytecodeShortArg(int bci) {219int hi = getBytecodeOrBPAt(bci);220int lo = getBytecodeOrBPAt(bci + 1);221return (short) ((hi << 8) | lo);222}223224/** Fetches a 16-bit native ordered value from the225bytecode stream */226public short getNativeShortArg(int bci) {227int hi = getBytecodeOrBPAt(bci);228int lo = getBytecodeOrBPAt(bci + 1);229if (VM.getVM().isBigEndian()) {230return (short) ((hi << 8) | lo);231} else {232return (short) ((lo << 8) | hi);233}234}235236/** Fetches a 32-bit big-endian ("Java ordered") value from the237bytecode stream */238public int getBytecodeIntArg(int bci) {239int b4 = getBytecodeOrBPAt(bci);240int b3 = getBytecodeOrBPAt(bci + 1);241int b2 = getBytecodeOrBPAt(bci + 2);242int b1 = getBytecodeOrBPAt(bci + 3);243244return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;245}246247/** Fetches a 32-bit native ordered value from the248bytecode stream */249public int getNativeIntArg(int bci) {250int b4 = getBytecodeOrBPAt(bci);251int b3 = getBytecodeOrBPAt(bci + 1);252int b2 = getBytecodeOrBPAt(bci + 2);253int b1 = getBytecodeOrBPAt(bci + 3);254255if (VM.getVM().isBigEndian()) {256return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;257} else {258return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;259}260}261262public byte[] getByteCode() {263byte[] bc = new byte[ (int) getCodeSize() ];264for( int i=0; i < bc.length; i++ )265{266long offs = bytecodeOffset + i;267bc[i] = getAddress().getJByteAt( offs );268}269return bc;270}271272public long getSize() {273return getConstMethodSize();274}275276public void printValueOn(PrintStream tty) {277tty.print("ConstMethod " + getName().asString() + getSignature().asString() + "@" + getAddress());278}279280public void iterateFields(MetadataVisitor visitor) {281visitor.doMetadata(constants, true);282visitor.doCInt(constMethodSize, true);283visitor.doCInt(flags, true);284visitor.doCInt(codeSize, true);285visitor.doCInt(nameIndex, true);286visitor.doCInt(signatureIndex, true);287visitor.doCInt(codeSize, true);288visitor.doCInt(maxStack, true);289visitor.doCInt(maxLocals, true);290visitor.doCInt(sizeOfParameters, true);291}292293// Accessors294295public boolean hasLineNumberTable() {296return (getFlags() & HAS_LINENUMBER_TABLE) != 0;297}298299public int getLineNumberFromBCI(int bci) {300if (!VM.getVM().isCore()) {301if (bci == DebugInformationRecorder.SYNCHRONIZATION_ENTRY_BCI) bci = 0;302}303304if (isNative()) {305return -1;306}307308if (Assert.ASSERTS_ENABLED) {309Assert.that(0 <= bci && bci < getCodeSize(),310"illegal bci(" + bci + ") codeSize(" + getCodeSize() + ")");311}312int bestBCI = 0;313int bestLine = -1;314if (hasLineNumberTable()) {315// The line numbers are a short array of 2-tuples [start_pc, line_number].316// Not necessarily sorted and not necessarily one-to-one.317CompressedLineNumberReadStream stream =318new CompressedLineNumberReadStream(getAddress(), (int) offsetOfCompressedLineNumberTable());319while (stream.readPair()) {320if (stream.bci() == bci) {321// perfect match322return stream.line();323} else {324// update best_bci/line325if (stream.bci() < bci && stream.bci() >= bestBCI) {326bestBCI = stream.bci();327bestLine = stream.line();328}329}330}331}332return bestLine;333}334335public LineNumberTableElement[] getLineNumberTable() {336if (Assert.ASSERTS_ENABLED) {337Assert.that(hasLineNumberTable(),338"should only be called if table is present");339}340int len = getLineNumberTableLength();341CompressedLineNumberReadStream stream =342new CompressedLineNumberReadStream(getAddress(), (int) offsetOfCompressedLineNumberTable());343LineNumberTableElement[] ret = new LineNumberTableElement[len];344345for (int idx = 0; idx < len; idx++) {346stream.readPair();347ret[idx] = new LineNumberTableElement(stream.bci(), stream.line());348}349return ret;350}351352public boolean hasLocalVariableTable() {353return (getFlags() & HAS_LOCALVARIABLE_TABLE) != 0;354}355356public Symbol getLocalVariableName(int bci, int slot) {357return getMethod().getLocalVariableName(bci, slot);358}359360/** Should only be called if table is present */361public LocalVariableTableElement[] getLocalVariableTable() {362if (Assert.ASSERTS_ENABLED) {363Assert.that(hasLocalVariableTable(), "should only be called if table is present");364}365LocalVariableTableElement[] ret = new LocalVariableTableElement[getLocalVariableTableLength()];366long offset = offsetOfLocalVariableTable();367for (int i = 0; i < ret.length; i++) {368ret[i] = new LocalVariableTableElement(getAddress(), offset);369offset += localVariableTableElementSize;370}371return ret;372}373374public boolean hasExceptionTable() {375return (getFlags() & HAS_EXCEPTION_TABLE) != 0;376}377378public ExceptionTableElement[] getExceptionTable() {379if (Assert.ASSERTS_ENABLED) {380Assert.that(hasExceptionTable(), "should only be called if table is present");381}382ExceptionTableElement[] ret = new ExceptionTableElement[getExceptionTableLength()];383long offset = offsetOfExceptionTable();384for (int i = 0; i < ret.length; i++) {385ret[i] = new ExceptionTableElement(getAddress(), offset);386offset += exceptionTableElementSize;387}388return ret;389}390391public boolean hasCheckedExceptions() {392return (getFlags() & HAS_CHECKED_EXCEPTIONS) != 0;393}394395public CheckedExceptionElement[] getCheckedExceptions() {396if (Assert.ASSERTS_ENABLED) {397Assert.that(hasCheckedExceptions(), "should only be called if table is present");398}399CheckedExceptionElement[] ret = new CheckedExceptionElement[getCheckedExceptionsLength()];400long offset = offsetOfCheckedExceptions();401for (int i = 0; i < ret.length; i++) {402ret[i] = new CheckedExceptionElement(getAddress(), offset);403offset += checkedExceptionElementSize;404}405return ret;406}407408private boolean hasMethodParameters() {409return (getFlags() & HAS_METHOD_PARAMETERS) != 0;410}411412private boolean hasGenericSignature() {413return (getFlags() & HAS_GENERIC_SIGNATURE) != 0;414}415416private boolean hasMethodAnnotations() {417return (getFlags() & HAS_METHOD_ANNOTATIONS) != 0;418}419420private boolean hasParameterAnnotations() {421return (getFlags() & HAS_PARAMETER_ANNOTATIONS) != 0;422}423424private boolean hasDefaultAnnotations() {425return (getFlags() & HAS_DEFAULT_ANNOTATIONS) != 0;426}427428private boolean hasTypeAnnotations() {429return (getFlags() & HAS_TYPE_ANNOTATIONS) != 0;430}431432433//---------------------------------------------------------------------------434// Internals only below this point435//436437private boolean isNative() {438return getMethod().isNative();439}440441// Offset of end of code442private long offsetOfCodeEnd() {443return bytecodeOffset + getCodeSize();444}445446// Offset of start of compressed line number table (see method.hpp)447private long offsetOfCompressedLineNumberTable() {448return offsetOfCodeEnd() + (isNative() ? 2 * VM.getVM().getAddressSize() : 0);449}450451// Offset of last short in Method* before annotations, if present452private long offsetOfLastU2Element() {453int offset = 0;454if (hasMethodAnnotations()) offset++;455if (hasParameterAnnotations()) offset++;456if (hasTypeAnnotations()) offset++;457if (hasDefaultAnnotations()) offset++;458long wordSize = VM.getVM().getObjectHeap().getOopSize();459return (getSize() * wordSize) - (offset * wordSize) - sizeofShort;460}461462// Offset of the generic signature index463private long offsetOfGenericSignatureIndex() {464return offsetOfLastU2Element();465}466467private long offsetOfMethodParametersLength() {468if (Assert.ASSERTS_ENABLED) {469Assert.that(hasMethodParameters(), "should only be called if table is present");470}471return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :472offsetOfLastU2Element();473}474475private int getMethodParametersLength() {476if (hasMethodParameters())477return (int) getAddress().getCIntegerAt(offsetOfMethodParametersLength(), 2, true);478else479return 0;480}481482// Offset of start of checked exceptions483private long offsetOfMethodParameters() {484long offset = offsetOfMethodParametersLength();485long length = getMethodParametersLength();486if (Assert.ASSERTS_ENABLED) {487Assert.that(length > 0, "should only be called if method parameter information is present");488}489offset -= length * methodParametersElementSize;490return offset;491}492493private long offsetOfCheckedExceptionsLength() {494if (hasMethodParameters())495return offsetOfMethodParameters() - sizeofShort;496else {497return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :498offsetOfLastU2Element();499}500}501502private int getCheckedExceptionsLength() {503if (hasCheckedExceptions()) {504return (int) getAddress().getCIntegerAt(offsetOfCheckedExceptionsLength(), 2, true);505} else {506return 0;507}508}509510// Offset of start of checked exceptions511private long offsetOfCheckedExceptions() {512long offset = offsetOfCheckedExceptionsLength();513long length = getCheckedExceptionsLength();514if (Assert.ASSERTS_ENABLED) {515Assert.that(length > 0, "should only be called if table is present");516}517offset -= length * checkedExceptionElementSize;518return offset;519}520521private int getLineNumberTableLength() {522int len = 0;523if (hasLineNumberTable()) {524CompressedLineNumberReadStream stream =525new CompressedLineNumberReadStream(getAddress(), (int) offsetOfCompressedLineNumberTable());526while (stream.readPair()) {527len += 1;528}529}530return len;531}532533private int getLocalVariableTableLength() {534if (hasLocalVariableTable()) {535return (int) getAddress().getCIntegerAt(offsetOfLocalVariableTableLength(), 2, true);536} else {537return 0;538}539}540541// Offset of local variable table length542private long offsetOfLocalVariableTableLength() {543if (Assert.ASSERTS_ENABLED) {544Assert.that(hasLocalVariableTable(), "should only be called if table is present");545}546547if (hasExceptionTable()) {548return offsetOfExceptionTable() - sizeofShort;549} else if (hasCheckedExceptions()) {550return offsetOfCheckedExceptions() - sizeofShort;551} else if (hasMethodParameters()) {552return offsetOfMethodParameters() - sizeofShort;553} else {554return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :555offsetOfLastU2Element();556}557}558559private long offsetOfLocalVariableTable() {560long offset = offsetOfLocalVariableTableLength();561long length = getLocalVariableTableLength();562if (Assert.ASSERTS_ENABLED) {563Assert.that(length > 0, "should only be called if table is present");564}565offset -= length * localVariableTableElementSize;566return offset;567}568569private int getExceptionTableLength() {570if (hasExceptionTable()) {571return (int) getAddress().getCIntegerAt(offsetOfExceptionTableLength(), 2, true);572} else {573return 0;574}575}576577private long offsetOfExceptionTableLength() {578if (Assert.ASSERTS_ENABLED) {579Assert.that(hasExceptionTable(), "should only be called if table is present");580}581if (hasCheckedExceptions()) {582return offsetOfCheckedExceptions() - sizeofShort;583} else if (hasMethodParameters()) {584return offsetOfMethodParameters() - sizeofShort;585} else {586return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :587offsetOfLastU2Element();588}589}590591private long offsetOfExceptionTable() {592long offset = offsetOfExceptionTableLength();593long length = getExceptionTableLength();594if (Assert.ASSERTS_ENABLED) {595Assert.that(length > 0, "should only be called if table is present");596}597offset -= length * exceptionTableElementSize;598return offset;599}600601}602603604