Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeCache.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.code;2526import java.util.*;27import sun.jvm.hotspot.debugger.*;28import sun.jvm.hotspot.memory.*;29import sun.jvm.hotspot.runtime.*;30import sun.jvm.hotspot.types.*;31import sun.jvm.hotspot.utilities.*;32import sun.jvm.hotspot.utilities.Observable;33import sun.jvm.hotspot.utilities.Observer;3435public class CodeCache {36private static GrowableArray<CodeHeap> heapArray;37private static VirtualConstructor virtualConstructor;3839static {40VM.registerVMInitializedObserver(new Observer() {41public void update(Observable o, Object data) {42initialize(VM.getVM().getTypeDataBase());43}44});45}4647private static synchronized void initialize(TypeDataBase db) {48Type type = db.lookupType("CodeCache");4950// Get array of CodeHeaps51// Note: CodeHeap may be subclassed with optional private heap mechanisms.52Type codeHeapType = db.lookupType("CodeHeap");53VirtualBaseConstructor<CodeHeap> heapConstructor =54new VirtualBaseConstructor<>(db, codeHeapType, "sun.jvm.hotspot.memory", CodeHeap.class);5556AddressField heapsField = type.getAddressField("_heaps");57heapArray = GrowableArray.create(heapsField.getValue(), heapConstructor);5859virtualConstructor = new VirtualConstructor(db);60// Add mappings for all possible CodeBlob subclasses61virtualConstructor.addMapping("BufferBlob", BufferBlob.class);62virtualConstructor.addMapping("nmethod", NMethod.class);63virtualConstructor.addMapping("RuntimeStub", RuntimeStub.class);64virtualConstructor.addMapping("AdapterBlob", AdapterBlob.class);65virtualConstructor.addMapping("MethodHandlesAdapterBlob", MethodHandlesAdapterBlob.class);66virtualConstructor.addMapping("VtableBlob", VtableBlob.class);67virtualConstructor.addMapping("SafepointBlob", SafepointBlob.class);68virtualConstructor.addMapping("DeoptimizationBlob", DeoptimizationBlob.class);69if (VM.getVM().isServerCompiler()) {70virtualConstructor.addMapping("ExceptionBlob", ExceptionBlob.class);71virtualConstructor.addMapping("UncommonTrapBlob", UncommonTrapBlob.class);72}73}7475public boolean contains(Address p) {76for (int i = 0; i < heapArray.length(); ++i) {77if (heapArray.at(i).contains(p)) {78return true;79}80}81return false;82}8384/** When VM.getVM().isDebugging() returns true, this behaves like85findBlobUnsafe */86public CodeBlob findBlob(Address start) {87CodeBlob result = findBlobUnsafe(start);88if (result == null) return null;89if (VM.getVM().isDebugging()) {90return result;91}92// We could potientially look up non_entrant methods93// NOTE: this is effectively a "guarantee", and is slightly different from the one in the VM94if (Assert.ASSERTS_ENABLED) {95Assert.that(!(result.isZombie() || result.isLockedByVM()), "unsafe access to zombie method");96}97return result;98}99100public CodeBlob findBlobUnsafe(Address start) {101CodeBlob result = null;102CodeHeap containing_heap = null;103for (int i = 0; i < heapArray.length(); ++i) {104if (heapArray.at(i).contains(start)) {105containing_heap = heapArray.at(i);106break;107}108}109if (containing_heap == null) {110return null;111}112113try {114result = (CodeBlob) virtualConstructor.instantiateWrapperFor(containing_heap.findStart(start));115}116catch (WrongTypeException wte) {117Address cbAddr = null;118try {119cbAddr = containing_heap.findStart(start);120}121catch (Exception findEx) {122findEx.printStackTrace();123}124125String message = "Couldn't deduce type of CodeBlob ";126if (cbAddr != null) {127message = message + "@" + cbAddr + " ";128}129message = message + "for PC=" + start;130131throw new RuntimeException(message, wte);132}133if (result == null) return null;134if (Assert.ASSERTS_ENABLED) {135// The pointer to the HeapBlock that contains this blob is outside of the blob,136// but it shouldn't be an error to find a blob based on the pointer to the HeapBlock.137// The heap block header is padded out to an 8-byte boundary. See heap.hpp. The138// simplest way to compute the header size is just 2 * addressSize.139Assert.that(result.blobContains(start) ||140result.blobContains(start.addOffsetTo(2 * VM.getVM().getAddressSize())),141"found wrong CodeBlob");142}143return result;144}145146public NMethod findNMethod(Address start) {147CodeBlob cb = findBlob(start);148if (Assert.ASSERTS_ENABLED) {149Assert.that(cb == null || cb.isNMethod(), "did not find an nmethod");150}151return (NMethod) cb;152}153154public NMethod findNMethodUnsafe(Address start) {155CodeBlob cb = findBlobUnsafe(start);156if (Assert.ASSERTS_ENABLED) {157Assert.that(cb == null || cb.isNMethod(), "did not find an nmethod");158}159return (NMethod) cb;160}161162/** Routine for instantiating appropriately-typed wrapper for a163CodeBlob. Used by CodeCache, Runtime1, etc. */164public CodeBlob createCodeBlobWrapper(Address codeBlobAddr) {165try {166return (CodeBlob) virtualConstructor.instantiateWrapperFor(codeBlobAddr);167}168catch (Exception e) {169String message = "Unable to deduce type of CodeBlob from address " + codeBlobAddr +170" (expected type nmethod, RuntimeStub, VtableBlob, ";171if (VM.getVM().isClientCompiler()) {172message = message + " or ";173}174message = message + "SafepointBlob";175if (VM.getVM().isServerCompiler()) {176message = message + ", DeoptimizationBlob, or ExceptionBlob";177}178message = message + ")";179throw new RuntimeException(message);180}181}182183public void iterate(CodeCacheVisitor visitor) {184visitor.prologue(lowBound(), highBound());185for (int i = 0; i < heapArray.length(); ++i) {186CodeHeap current_heap = heapArray.at(i);187current_heap.iterate(visitor, this);188}189visitor.epilogue();190}191192//--------------------------------------------------------------------------------193// Internals only below this point194//195196private Address lowBound() {197Address low = heapArray.at(0).begin();198for (int i = 1; i < heapArray.length(); ++i) {199if (heapArray.at(i).begin().lessThan(low)) {200low = heapArray.at(i).begin();201}202}203return low;204}205206private Address highBound() {207Address high = heapArray.at(0).end();208for (int i = 1; i < heapArray.length(); ++i) {209if (heapArray.at(i).end().greaterThan(high)) {210high = heapArray.at(i).end();211}212}213return high;214}215}216217218