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