Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/compiler/ImmutableOopMapSet.java
68559 views
/*1* Copyright (c) 2000, 2021, 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); !oms.isDone(); oms.next()) {204omv = oms.getCurrent();205if (omv.getType() != OopMapValue.OopTypes.DERIVED_OOP_VALUE) {206continue;207}208if (VM.getVM().isClientCompiler()) {209Assert.that(false, "should not reach here");210}211Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap);212if (loc != null) {213Address baseLoc = fr.oopMapRegToLocation(omv.getContentReg(), regMap);214Address derivedLoc = loc;215visitor.visitDerivedOopLocation(baseLoc, derivedLoc);216}217}218}219220// We want narow oop and oop oop_types221{222for (OopMapStream oms = new OopMapStream(map); !oms.isDone(); oms.next()) {223omv = oms.getCurrent();224Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap);225if (loc != null) {226if (omv.getType() == OopMapValue.OopTypes.OOP_VALUE) {227// This assert commented out because this will be useful228// to detect in the debugging system229// assert(Universe::is_heap_or_null(*loc), "found non oop pointer");230visitor.visitOopLocation(loc);231} else if (omv.getType() == OopMapValue.OopTypes.NARROWOOP_VALUE) {232visitor.visitNarrowOopLocation(loc);233}234}235}236}237}238239/**240* Update callee-saved register info for the following frame.241* Should only be called in non-core builds.242*/243public static void updateRegisterMap(Frame fr, CodeBlob cb, RegisterMap regMap, boolean debugging) {244if (Assert.ASSERTS_ENABLED) {245Assert.that(!VM.getVM().isCore(), "non-core builds only");246}247248if (!VM.getVM().isDebugging()) {249if (Assert.ASSERTS_ENABLED) {250ImmutableOopMapSet maps = cb.getOopMaps();251Assert.that((maps != null) && (maps.getCount() > 0), "found null or empty ImmutableOopMapSet for CodeBlob");252}253} else {254// Hack for some topmost frames that have been found with empty255// OopMapSets. (Actually have not seen the null case, but don't256// want to take any chances.) See HSDB.showThreadStackMemory().257ImmutableOopMapSet maps = cb.getOopMaps();258if ((maps == null) || (maps.getCount() == 0)) {259return;260}261}262263// Check if caller must update oop argument264regMap.setIncludeArgumentOops(cb.callerMustGCArguments());265266int nofCallee = 0;267Address[] locs = new Address[2 * REG_COUNT + 1];268VMReg[] regs = new VMReg[2 * REG_COUNT + 1];269// ("+1" because REG_COUNT might be zero)270271// Scan through oopmap and find location of all callee-saved registers272// (we do not do update in place, since info could be overwritten)273ImmutableOopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging);274if (Assert.ASSERTS_ENABLED) {275Assert.that(map != null, "no ptr map found");276}277278OopMapValue omv = null;279for (OopMapStream oms = new OopMapStream(map); !oms.isDone(); oms.next()) {280omv = oms.getCurrent();281if (omv.getType() != OopMapValue.OopTypes.CALLEE_SAVED_VALUE) {282continue;283}284if (Assert.ASSERTS_ENABLED) {285Assert.that(nofCallee < 2 * REG_COUNT, "overflow");286}287regs[nofCallee] = omv.getContentReg();288locs[nofCallee] = fr.oopMapRegToLocation(omv.getReg(), regMap);289nofCallee++;290}291292// Check that runtime stubs save all callee-saved registers293// After adapter frames were deleted C2 doesn't use callee save registers at present294if (Assert.ASSERTS_ENABLED) {295if (VM.getVM().isServerCompiler()) {296Assert.that(!cb.isRuntimeStub() ||297(nofCallee >= SAVED_ON_ENTRY_REG_COUNT || nofCallee >= C_SAVED_ON_ENTRY_REG_COUNT),298"must save all");299}300}301302// Copy found callee-saved register to reg_map303for (int i = 0; i < nofCallee; i++) {304regMap.setLocation(regs[i], locs[i]);305}306}307308public ImmutableOopMapPair getPairAt(int index) {309return pairAt(index);310}311312private int getSize() {313return (int) sizeField.getValue(addr);314}315316public ImmutableOopMap getMap(ImmutableOopMapPair pair) {317Assert.that(pair.getOffset() < getSize(), "boundary check: this: " + this + " offset: " + pair);318return new ImmutableOopMap(dataStart().addOffsetTo(pair.getOffset()));319}320321public String toString() {322StringBuilder builder = new StringBuilder();323builder.append("Set{ ")324.append("addr = ").append(addr)325.append(", count = ").append(getCount())326.append(", size = ").append(getSize())327.append(", pairs = [");328329for (int i = 0; i < getCount(); ++i) {330builder.append(getPairAt(i));331}332333builder.append("]");334return builder.toString();335}336}337338339