1 /* 2 * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package com.sun.org.apache.bcel.internal.generic; 22 23 import java.util.StringTokenizer; 24 25 import com.sun.org.apache.bcel.internal.Const; 26 import com.sun.org.apache.bcel.internal.classfile.Constant; 27 import com.sun.org.apache.bcel.internal.classfile.ConstantCP; 28 import com.sun.org.apache.bcel.internal.classfile.ConstantPool; 29 30 /** 31 * Super class for the INVOKExxx family of instructions. 32 * 33 * @LastModified: Jan 2020 34 */ 35 public abstract class InvokeInstruction extends FieldOrMethod implements ExceptionThrower, 36 StackConsumer, StackProducer { 37 38 /** 39 * Empty constructor needed for Instruction.readInstruction. 40 * Not to be used otherwise. 41 */ InvokeInstruction()42 InvokeInstruction() { 43 } 44 45 46 /** 47 * @param index to constant pool 48 */ InvokeInstruction(final short opcode, final int index)49 protected InvokeInstruction(final short opcode, final int index) { 50 super(opcode, index); 51 } 52 53 54 /** 55 * @return mnemonic for instruction with symbolic references resolved 56 */ 57 @Override toString( final ConstantPool cp )58 public String toString( final ConstantPool cp ) { 59 final Constant c = cp.getConstant(super.getIndex()); 60 final StringTokenizer tok = new StringTokenizer(cp.constantToString(c)); 61 62 final String opcodeName = Const.getOpcodeName(super.getOpcode()); 63 64 final StringBuilder sb = new StringBuilder(opcodeName); 65 if (tok.hasMoreTokens()) { 66 sb.append(" "); 67 sb.append(tok.nextToken().replace('.', '/')); 68 if (tok.hasMoreTokens()) { 69 sb.append(tok.nextToken()); 70 } 71 } 72 73 return sb.toString(); 74 } 75 76 77 /** 78 * Also works for instructions whose stack effect depends on the 79 * constant pool entry they reference. 80 * @return Number of words consumed from stack by this instruction 81 */ 82 @Override consumeStack( final ConstantPoolGen cpg )83 public int consumeStack( final ConstantPoolGen cpg ) { 84 int sum; 85 if ((super.getOpcode() == Const.INVOKESTATIC) || (super.getOpcode() == Const.INVOKEDYNAMIC)) { 86 sum = 0; 87 } else { 88 sum = 1; // this reference 89 } 90 91 final String signature = getSignature(cpg); 92 sum += Type.getArgumentTypesSize(signature); 93 return sum; 94 } 95 96 97 /** 98 * Also works for instructions whose stack effect depends on the 99 * constant pool entry they reference. 100 * @return Number of words produced onto stack by this instruction 101 */ 102 @Override produceStack( final ConstantPoolGen cpg )103 public int produceStack( final ConstantPoolGen cpg ) { 104 final String signature = getSignature(cpg); 105 return Type.getReturnTypeSize(signature); 106 } 107 108 /** 109 * This overrides the deprecated version as we know here that the referenced class 110 * may legally be an array. 111 * 112 * @deprecated in FieldOrMethod 113 * 114 * @return name of the referenced class/interface 115 * @throws IllegalArgumentException if the referenced class is an array (this should not happen) 116 */ 117 @Override 118 @Deprecated getClassName( final ConstantPoolGen cpg )119 public String getClassName( final ConstantPoolGen cpg ) { 120 final ConstantPool cp = cpg.getConstantPool(); 121 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 122 final String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class); 123 return className.replace('/', '.'); 124 } 125 126 /** @return return type of referenced method. 127 */ 128 @Override getType( final ConstantPoolGen cpg )129 public Type getType( final ConstantPoolGen cpg ) { 130 return getReturnType(cpg); 131 } 132 133 134 /** @return name of referenced method. 135 */ getMethodName( final ConstantPoolGen cpg )136 public String getMethodName( final ConstantPoolGen cpg ) { 137 return getName(cpg); 138 } 139 140 141 /** @return return type of referenced method. 142 */ getReturnType( final ConstantPoolGen cpg )143 public Type getReturnType( final ConstantPoolGen cpg ) { 144 return Type.getReturnType(getSignature(cpg)); 145 } 146 147 148 /** @return argument types of referenced method. 149 */ getArgumentTypes( final ConstantPoolGen cpg )150 public Type[] getArgumentTypes( final ConstantPoolGen cpg ) { 151 return Type.getArgumentTypes(getSignature(cpg)); 152 } 153 154 } 155