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