Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/compiler/ImmutableOopMapSet.java
41171 views
/*1* Copyright (c) 2000, 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.compiler;2526import java.util.*;2728import sun.jvm.hotspot.code.*;29import sun.jvm.hotspot.debugger.*;30import sun.jvm.hotspot.runtime.*;31import sun.jvm.hotspot.types.*;32import sun.jvm.hotspot.utilities.*;33import sun.jvm.hotspot.utilities.Observable;34import sun.jvm.hotspot.utilities.Observer;3536public class ImmutableOopMapSet extends VMObject {37private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.compiler.ImmutableOopMapSet.DEBUG") != null;3839private static CIntegerField countField;40private static CIntegerField sizeField;41private static AddressField omDataField;42private static int REG_COUNT;43private static int SAVED_ON_ENTRY_REG_COUNT;44private static int C_SAVED_ON_ENTRY_REG_COUNT;45private static long classSize;4647private static class MyVisitor implements OopMapVisitor {48private AddressVisitor addressVisitor;4950public MyVisitor(AddressVisitor oopVisitor) {51setAddressVisitor(oopVisitor);52}5354public void setAddressVisitor(AddressVisitor addressVisitor) {55this.addressVisitor = addressVisitor;56}5758public void visitOopLocation(Address oopAddr) {59addressVisitor.visitAddress(oopAddr);60}6162public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr) {63if (VM.getVM().isClientCompiler()) {64Assert.that(false, "should not reach here");65} else if (VM.getVM().isServerCompiler() &&66VM.getVM().useDerivedPointerTable()) {67Assert.that(false, "FIXME: add derived pointer table");68}69}7071public void visitNarrowOopLocation(Address narrowOopAddr) {72addressVisitor.visitCompOopAddress(narrowOopAddr);73}74}7576static {77VM.registerVMInitializedObserver(new Observer() {78public void update(Observable o, Object data) {79initialize(VM.getVM().getTypeDataBase());80}81});82}8384private static void initialize(TypeDataBase db) {85Type type = db.lookupType("ImmutableOopMapSet");8687countField = type.getCIntegerField("_count");88sizeField = type.getCIntegerField("_size");89classSize = type.getSize();9091if (!VM.getVM().isCore()) {92REG_COUNT = db.lookupIntConstant("REG_COUNT").intValue();93if (VM.getVM().isServerCompiler()) {94SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("SAVED_ON_ENTRY_REG_COUNT").intValue();95C_SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("C_SAVED_ON_ENTRY_REG_COUNT").intValue();96}97}98}99100public ImmutableOopMapSet(Address addr) {101super(addr);102}103104/**105* Returns the number of OopMaps in this ImmutableOopMapSet106*/107public int getCount() { return (int) countField.getValue(addr); }108109private Address dataStart() {110return (pairStart().addOffsetTo(ImmutableOopMapPair.classSize() * getCount()));111}112113private Address pairStart() {114return addr.addOffsetTo(ImmutableOopMapSet.classSize);115}116117public ImmutableOopMapPair pairAt(int index) {118Assert.that((index >= 0) && (index < getCount()), "bad index");119return new ImmutableOopMapPair(pairStart().addOffsetTo(index * ImmutableOopMapPair.classSize()));120}121122/**123* returns the OopMap at a given index124*/125public ImmutableOopMap getMapAt(int index) {126if (Assert.ASSERTS_ENABLED) {127Assert.that((index >= 0) && (index <= getCount()), "bad index");128}129130ImmutableOopMapPair immutableOopMapPair = pairAt(index);131return getMap(immutableOopMapPair);132}133134public ImmutableOopMap findMapAtOffset(long pcOffset, boolean debugging) {135int i;136int len = getCount();137if (Assert.ASSERTS_ENABLED) {138Assert.that(len > 0, "must have pointer maps");139}140141// Scan through oopmaps. Stop when current offset is either equal or greater142// than the one we are looking for.143for (i = 0; i < len; i++) {144if (pairAt(i).getPC() >= pcOffset) {145break;146}147}148149if (!debugging) {150if (Assert.ASSERTS_ENABLED) {151Assert.that(i < len, "oopmap not found for pcOffset = " + pcOffset + "; len = " + len);152Assert.that(pairAt(i).getPC() == pcOffset, "oopmap not found");153}154} else {155if (i == len) {156if (DEBUG) {157System.out.println("can't find oopmap at " + pcOffset);158System.out.print("Oopmap offsets are [ ");159for (i = 0; i < len; i++) {160System.out.print(pairAt(i).getPC());161}162System.out.println("]");163}164i = len - 1;165return getMapAt(i);166}167}168169ImmutableOopMap m = getMapAt(i);170return m;171}172173/**174* Visitation -- iterates through the frame for a compiled method.175* This is a very generic mechanism that requires the Address to be176* dereferenced by the callee. Other, more specialized, visitation177* mechanisms are given below.178*/179public static void oopsDo(Frame fr, CodeBlob cb, RegisterMap regMap, AddressVisitor oopVisitor, boolean debugging) {180allDo(fr, cb, regMap, new MyVisitor(oopVisitor), debugging);181}182183/**184* Note that there are 4 required AddressVisitors: one for oops,185* one for derived oops, one for values, and one for dead values186*/187public static void allDo(Frame fr, CodeBlob cb, RegisterMap regMap, OopMapVisitor visitor, boolean debugging) {188if (Assert.ASSERTS_ENABLED) {189CodeBlob tmpCB = VM.getVM().getCodeCache().findBlob(fr.getPC());190Assert.that(tmpCB != null && cb.equals(tmpCB), "wrong codeblob passed in");191}192193ImmutableOopMapSet maps = cb.getOopMaps();194ImmutableOopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging);195if (Assert.ASSERTS_ENABLED) {196Assert.that(map != null, "no ptr map found");197}198199// handle derived pointers first (otherwise base pointer may be200// changed before derived pointer offset has been collected)201OopMapValue omv;202{203for (OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.DERIVED_OOP_VALUE); !oms.isDone(); oms.next()) {204if (VM.getVM().isClientCompiler()) {205Assert.that(false, "should not reach here");206}207omv = oms.getCurrent();208Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap);209if (loc != null) {210Address baseLoc = fr.oopMapRegToLocation(omv.getContentReg(), regMap);211Address derivedLoc = loc;212visitor.visitDerivedOopLocation(baseLoc, derivedLoc);213}214}215}216217// We want narow oop and oop oop_types218OopMapValue.OopTypes[] values = new OopMapValue.OopTypes[] {219OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.NARROWOOP_VALUE220};221222{223for (OopMapStream oms = new OopMapStream(map, values); !oms.isDone(); oms.next()) {224omv = oms.getCurrent();225Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap);226if (loc != null) {227if (omv.getType() == OopMapValue.OopTypes.OOP_VALUE) {228// This assert commented out because this will be useful229// to detect in the debugging system230// assert(Universe::is_heap_or_null(*loc), "found non oop pointer");231visitor.visitOopLocation(loc);232} else if (omv.getType() == OopMapValue.OopTypes.NARROWOOP_VALUE) {233visitor.visitNarrowOopLocation(loc);234}235}236}237}238}239240/**241* Update callee-saved register info for the following frame.242* Should only be called in non-core builds.243*/244public static void updateRegisterMap(Frame fr, CodeBlob cb, RegisterMap regMap, boolean debugging) {245if (Assert.ASSERTS_ENABLED) {246Assert.that(!VM.getVM().isCore(), "non-core builds only");247}248249if (!VM.getVM().isDebugging()) {250if (Assert.ASSERTS_ENABLED) {251ImmutableOopMapSet maps = cb.getOopMaps();252Assert.that((maps != null) && (maps.getCount() > 0), "found null or empty ImmutableOopMapSet for CodeBlob");253}254} else {255// Hack for some topmost frames that have been found with empty256// OopMapSets. (Actually have not seen the null case, but don't257// want to take any chances.) See HSDB.showThreadStackMemory().258ImmutableOopMapSet maps = cb.getOopMaps();259if ((maps == null) || (maps.getCount() == 0)) {260return;261}262}263264// Check if caller must update oop argument265regMap.setIncludeArgumentOops(cb.callerMustGCArguments());266267int nofCallee = 0;268Address[] locs = new Address[2 * REG_COUNT + 1];269VMReg[] regs = new VMReg[2 * REG_COUNT + 1];270// ("+1" because REG_COUNT might be zero)271272// Scan through oopmap and find location of all callee-saved registers273// (we do not do update in place, since info could be overwritten)274ImmutableOopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging);275if (Assert.ASSERTS_ENABLED) {276Assert.that(map != null, "no ptr map found");277}278279OopMapValue omv = null;280for (OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE); !oms.isDone(); oms.next()) {281omv = oms.getCurrent();282if (Assert.ASSERTS_ENABLED) {283Assert.that(nofCallee < 2 * REG_COUNT, "overflow");284}285regs[nofCallee] = omv.getContentReg();286locs[nofCallee] = fr.oopMapRegToLocation(omv.getReg(), regMap);287nofCallee++;288}289290// Check that runtime stubs save all callee-saved registers291// After adapter frames were deleted C2 doesn't use callee save registers at present292if (Assert.ASSERTS_ENABLED) {293if (VM.getVM().isServerCompiler()) {294Assert.that(!cb.isRuntimeStub() ||295(nofCallee >= SAVED_ON_ENTRY_REG_COUNT || nofCallee >= C_SAVED_ON_ENTRY_REG_COUNT),296"must save all");297}298}299300// Copy found callee-saved register to reg_map301for (int i = 0; i < nofCallee; i++) {302regMap.setLocation(regs[i], locs[i]);303}304}305306public ImmutableOopMapPair getPairAt(int index) {307return pairAt(index);308}309310private int getSize() {311return (int) sizeField.getValue(addr);312}313314public ImmutableOopMap getMap(ImmutableOopMapPair pair) {315Assert.that(pair.getOffset() < getSize(), "boundary check: this: " + this + " offset: " + pair);316return new ImmutableOopMap(dataStart().addOffsetTo(pair.getOffset()));317}318319public String toString() {320StringBuilder builder = new StringBuilder();321builder.append("Set{ ")322.append("addr = ").append(addr)323.append(", count = ").append(getCount())324.append(", size = ").append(getSize())325.append(", pairs = [");326327for (int i = 0; i < getCount(); ++i) {328builder.append(getPairAt(i));329}330331builder.append("]");332return builder.toString();333}334}335336337