Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java
41161 views
/*1* Copyright (c) 2002, 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.interpreter;2526import sun.jvm.hotspot.oops.*;27import sun.jvm.hotspot.runtime.*;28import sun.jvm.hotspot.utilities.*;2930public class BytecodeLoadConstant extends Bytecode {31BytecodeLoadConstant(Method method, int bci) {32super(method, bci);33}3435public boolean hasCacheIndex() {36// normal ldc uses CP index, but fast_aldc uses swapped CP cache index37return code() >= Bytecodes.number_of_java_codes;38}3940int rawIndex() {41if (javaCode() == Bytecodes._ldc)42return getIndexU1();43else44return getIndexU2(code(), false);45}4647public int poolIndex() {48int index = rawIndex();49if (hasCacheIndex()) {50return method().getConstants().objectToCPIndex(index);51} else {52return index;53}54}5556public int cacheIndex() {57if (hasCacheIndex()) {58return rawIndex();59} else {60return -1; // no cache index61}62}6364public BasicType resultType() {65int index = poolIndex();66ConstantTag tag = method().getConstants().getTagAt(index);67return tag.basicType();68}6970private Oop getCachedConstant() {71int i = cacheIndex();72if (i >= 0) {73throw new InternalError("invokedynamic not implemented yet");74}75return null;76}7778public void verify() {79if (Assert.ASSERTS_ENABLED) {80Assert.that(isValid(), "check load constant");81}82}8384public boolean isValid() {85int jcode = javaCode();86boolean codeOk = jcode == Bytecodes._ldc || jcode == Bytecodes._ldc_w ||87jcode == Bytecodes._ldc2_w;88if (! codeOk) return false;8990ConstantTag ctag = method().getConstants().getTagAt(poolIndex());91if (jcode == Bytecodes._ldc2_w) {92// has to be double or long93return (ctag.isDouble() || ctag.isLong()) ? true: false;94} else {95// has to be int or float or String or Klass96return (ctag.isString()97|| ctag.isUnresolvedKlass() || ctag.isKlass()98|| ctag.isMethodHandle() || ctag.isMethodType()99|| ctag.isInt() || ctag.isFloat())? true: false;100}101}102103public boolean isKlassConstant() {104int jcode = javaCode();105if (jcode == Bytecodes._ldc2_w) {106return false;107}108109ConstantTag ctag = method().getConstants().getTagAt(poolIndex());110return ctag.isKlass() || ctag.isUnresolvedKlass();111}112113// return Symbol (if unresolved) or Klass (if resolved)114public Object getKlass() {115if (Assert.ASSERTS_ENABLED) {116Assert.that(isKlassConstant(), "not a klass literal");117}118// tag change from 'unresolved' to 'klass' does not happen atomically.119// We just look at the object at the corresponding index and120// decide based on the oop type.121ConstantPool cpool = method().getConstants();122int cpIndex = poolIndex();123return cpool.getKlassNameAt(cpIndex);124}125126public static BytecodeLoadConstant at(Method method, int bci) {127BytecodeLoadConstant b = new BytecodeLoadConstant(method, bci);128if (Assert.ASSERTS_ENABLED) {129b.verify();130}131return b;132}133134/** Like at, but returns null if the BCI is not at ldc or ldc_w or ldc2_w */135public static BytecodeLoadConstant atCheck(Method method, int bci) {136BytecodeLoadConstant b = new BytecodeLoadConstant(method, bci);137return (b.isValid() ? b : null);138}139140public static BytecodeLoadConstant at(BytecodeStream bcs) {141return new BytecodeLoadConstant(bcs.method(), bcs.bci());142}143144public String getConstantValue() {145ConstantPool cpool = method().getConstants();146int cpIndex = poolIndex();147ConstantTag ctag = cpool.getTagAt(cpIndex);148if (ctag.isInt()) {149return "<int " + Integer.toString(cpool.getIntAt(cpIndex)) +">";150} else if (ctag.isLong()) {151return "<long " + Long.toString(cpool.getLongAt(cpIndex)) + "L>";152} else if (ctag.isFloat()) {153return "<float " + Float.toString(cpool.getFloatAt(cpIndex)) + "F>";154} else if (ctag.isDouble()) {155return "<double " + Double.toString(cpool.getDoubleAt(cpIndex)) + "D>";156} else if (ctag.isString()) {157// tag change from 'unresolved' to 'string' does not happen atomically.158// We just look at the object at the corresponding index and159// decide based on the oop type.160Symbol sym = cpool.getUnresolvedStringAt(cpIndex);161return "<String \"" + sym.asString() + "\">";162} else if (ctag.isKlass() || ctag.isUnresolvedKlass()) {163// tag change from 'unresolved' to 'klass' does not happen atomically.164// We just look at the object at the corresponding index and165// decide based on the oop type.166ConstantTag tag = cpool.getTagAt(cpIndex);167if (tag.isKlass()) {168Klass k = cpool.getKlassAt(cpIndex);169return "<Class " + k.getName().asString() + "@" + k.getAddress() + ">";170} else if (tag.isUnresolvedKlass()) {171Symbol sym = cpool.getKlassNameAt(cpIndex);172return "<Class " + sym.asString() + ">";173} else {174throw new RuntimeException("should not reach here");175}176} else if (ctag.isMethodHandle()) {177Oop x = getCachedConstant();178int refidx = cpool.getMethodHandleIndexAt(cpIndex);179int refkind = cpool.getMethodHandleRefKindAt(cpIndex);180return "<MethodHandle kind=" + Integer.toString(refkind) +181" ref=" + Integer.toString(refidx)182+ (x == null ? "" : " @" + x.getHandle()) + ">";183} else if (ctag.isMethodType()) {184Oop x = getCachedConstant();185int refidx = cpool.getMethodTypeIndexAt(cpIndex);186return "<MethodType " + cpool.getSymbolAt(refidx).asString()187+ (x == null ? "" : " @" + x.getHandle()) + ">";188} else {189if (Assert.ASSERTS_ENABLED) {190Assert.that(false, "invalid load constant type");191}192return null;193}194}195196public String toString() {197StringBuilder buf = new StringBuilder();198buf.append(getJavaBytecodeName());199buf.append(spaces);200buf.append('#');201buf.append(poolIndex());202if (hasCacheIndex()) {203buf.append('(');204buf.append(cacheIndex());205buf.append(')');206}207buf.append(spaces);208buf.append(getConstantValue());209if (code() != javaCode()) {210buf.append(spaces);211buf.append('[');212buf.append(getBytecodeName());213buf.append(']');214}215return buf.toString();216}217}218219220