001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.bcel.generic; 020 021import java.util.StringTokenizer; 022 023import org.apache.bcel.Const; 024import org.apache.bcel.classfile.Constant; 025import org.apache.bcel.classfile.ConstantCP; 026import org.apache.bcel.classfile.ConstantPool; 027import org.apache.bcel.classfile.Utility; 028 029/** 030 * Superclass for the INVOKExxx family of instructions. 031 */ 032public abstract class InvokeInstruction extends FieldOrMethod implements ExceptionThrower, StackConsumer, StackProducer { 033 034 /** 035 * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. 036 */ 037 InvokeInstruction() { 038 } 039 040 /** 041 * Constructs an InvokeInstruction. 042 * 043 * @param opcode The opcode. 044 * @param index to constant pool. 045 */ 046 protected InvokeInstruction(final short opcode, final int index) { 047 super(opcode, index); 048 } 049 050 /** 051 * Also works for instructions whose stack effect depends on the constant pool entry they reference. 052 * 053 * @return Number of words consumed from stack by this instruction. 054 */ 055 @Override 056 public int consumeStack(final ConstantPoolGen cpg) { 057 int sum; 058 if (super.getOpcode() == Const.INVOKESTATIC || super.getOpcode() == Const.INVOKEDYNAMIC) { 059 sum = 0; 060 } else { 061 sum = 1; // this reference 062 } 063 064 final String signature = getSignature(cpg); 065 sum += Type.getArgumentTypesSize(signature); 066 return sum; 067 } 068 069 /** 070 * Gets the argument types of referenced method. 071 * 072 * @param cpg The constant pool generator. 073 * @return argument types of referenced method. 074 */ 075 public Type[] getArgumentTypes(final ConstantPoolGen cpg) { 076 return Type.getArgumentTypes(getSignature(cpg)); 077 } 078 079 /** 080 * Gets the name of the referenced class or interface. 081 * <p> 082 * This overrides the deprecated version as we know here that the referenced class may legally be an array. 083 * </p> 084 * 085 * @return name of the referenced class/interface. 086 * @throws IllegalArgumentException Thrown if the referenced class is an array (this should not happen) 087 */ 088 @Override 089 public String getClassName(final ConstantPoolGen cpg) { 090 final ConstantPool cp = cpg.getConstantPool(); 091 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 092 final String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class); 093 return Utility.pathToPackage(className); 094 } 095 096 /** 097 * Gets the name of referenced method. 098 * 099 * @param cpg The constant pool generator. 100 * @return name of referenced method. 101 */ 102 public String getMethodName(final ConstantPoolGen cpg) { 103 return getName(cpg); 104 } 105 106 /** 107 * Gets the return type of referenced method. 108 * 109 * @param cpg The constant pool generator. 110 * @return return type of referenced method. 111 */ 112 public Type getReturnType(final ConstantPoolGen cpg) { 113 return Type.getReturnType(getSignature(cpg)); 114 } 115 116 /** 117 * Gets the return type of referenced method. 118 * 119 * @param cpg The constant pool generator. 120 * @return return type of referenced method. 121 */ 122 @Override 123 public Type getType(final ConstantPoolGen cpg) { 124 return getReturnType(cpg); 125 } 126 127 /** 128 * Also works for instructions whose stack effect depends on the constant pool entry they reference. 129 * 130 * @return Number of words produced onto stack by this instruction. 131 */ 132 @Override 133 public int produceStack(final ConstantPoolGen cpg) { 134 final String signature = getSignature(cpg); 135 return Type.getReturnTypeSize(signature); 136 } 137 138 /** 139 * @return mnemonic for instruction with symbolic references resolved. 140 */ 141 @Override 142 public String toString(final ConstantPool cp) { 143 final Constant c = cp.getConstant(super.getIndex()); 144 final StringTokenizer tok = new StringTokenizer(cp.constantToString(c)); 145 146 final String opcodeName = Const.getOpcodeName(super.getOpcode()); 147 148 final StringBuilder sb = new StringBuilder(opcodeName); 149 if (tok.hasMoreTokens()) { 150 sb.append(" "); 151 sb.append(Utility.packageToPath(tok.nextToken())); 152 if (tok.hasMoreTokens()) { 153 sb.append(tok.nextToken()); 154 } 155 } 156 157 return sb.toString(); 158 } 159 160} 161