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 * Super class 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 * This overrides the deprecated version as we know here that the referenced class may legally be an array. 081 * 082 * @return name of the referenced class/interface. 083 * @throws IllegalArgumentException if the referenced class is an array (this should not happen) 084 */ 085 @Override 086 public String getClassName(final ConstantPoolGen cpg) { 087 final ConstantPool cp = cpg.getConstantPool(); 088 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 089 final String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class); 090 return Utility.pathToPackage(className); 091 } 092 093 /** 094 * Gets the name of referenced method. 095 * 096 * @param cpg the constant pool generator. 097 * @return name of referenced method. 098 */ 099 public String getMethodName(final ConstantPoolGen cpg) { 100 return getName(cpg); 101 } 102 103 /** 104 * Gets the return type of referenced method. 105 * 106 * @param cpg the constant pool generator. 107 * @return return type of referenced method. 108 */ 109 public Type getReturnType(final ConstantPoolGen cpg) { 110 return Type.getReturnType(getSignature(cpg)); 111 } 112 113 /** 114 * Gets the return type of referenced method. 115 * 116 * @param cpg the constant pool generator. 117 * @return return type of referenced method. 118 */ 119 @Override 120 public Type getType(final ConstantPoolGen cpg) { 121 return getReturnType(cpg); 122 } 123 124 /** 125 * Also works for instructions whose stack effect depends on the constant pool entry they reference. 126 * 127 * @return Number of words produced onto stack by this instruction. 128 */ 129 @Override 130 public int produceStack(final ConstantPoolGen cpg) { 131 final String signature = getSignature(cpg); 132 return Type.getReturnTypeSize(signature); 133 } 134 135 /** 136 * @return mnemonic for instruction with symbolic references resolved. 137 */ 138 @Override 139 public String toString(final ConstantPool cp) { 140 final Constant c = cp.getConstant(super.getIndex()); 141 final StringTokenizer tok = new StringTokenizer(cp.constantToString(c)); 142 143 final String opcodeName = Const.getOpcodeName(super.getOpcode()); 144 145 final StringBuilder sb = new StringBuilder(opcodeName); 146 if (tok.hasMoreTokens()) { 147 sb.append(" "); 148 sb.append(Utility.packageToPath(tok.nextToken())); 149 if (tok.hasMoreTokens()) { 150 sb.append(tok.nextToken()); 151 } 152 } 153 154 return sb.toString(); 155 } 156 157} 158