View Javadoc
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  package org.apache.bcel.generic;
18  
19  import java.util.StringTokenizer;
20  
21  import org.apache.bcel.Const;
22  import org.apache.bcel.classfile.Constant;
23  import org.apache.bcel.classfile.ConstantCP;
24  import org.apache.bcel.classfile.ConstantPool;
25  import org.apache.bcel.classfile.Utility;
26  
27  /**
28   * Super class for the INVOKExxx family of instructions.
29   */
30  public abstract class InvokeInstruction extends FieldOrMethod implements ExceptionThrower, StackConsumer, StackProducer {
31  
32      /**
33       * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise.
34       */
35      InvokeInstruction() {
36      }
37  
38      /**
39       * @param index to constant pool
40       */
41      protected InvokeInstruction(final short opcode, final int index) {
42          super(opcode, index);
43      }
44  
45      /**
46       * Also works for instructions whose stack effect depends on the constant pool entry they reference.
47       *
48       * @return Number of words consumed from stack by this instruction
49       */
50      @Override
51      public int consumeStack(final ConstantPoolGen cpg) {
52          int sum;
53          if (super.getOpcode() == Const.INVOKESTATIC || super.getOpcode() == Const.INVOKEDYNAMIC) {
54              sum = 0;
55          } else {
56              sum = 1; // this reference
57          }
58  
59          final String signature = getSignature(cpg);
60          sum += Type.getArgumentTypesSize(signature);
61          return sum;
62      }
63  
64      /**
65       * @return argument types of referenced method.
66       */
67      public Type[] getArgumentTypes(final ConstantPoolGen cpg) {
68          return Type.getArgumentTypes(getSignature(cpg));
69      }
70  
71      /**
72       * This overrides the deprecated version as we know here that the referenced class may legally be an array.
73       *
74       * @return name of the referenced class/interface
75       * @throws IllegalArgumentException if the referenced class is an array (this should not happen)
76       */
77      @Override
78      public String getClassName(final ConstantPoolGen cpg) {
79          final ConstantPool cp = cpg.getConstantPool();
80          final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex());
81          final String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class);
82          return Utility.pathToPackage(className);
83      }
84  
85      /**
86       * @return name of referenced method.
87       */
88      public String getMethodName(final ConstantPoolGen cpg) {
89          return getName(cpg);
90      }
91  
92      /**
93       * @return return type of referenced method.
94       */
95      public Type getReturnType(final ConstantPoolGen cpg) {
96          return Type.getReturnType(getSignature(cpg));
97      }
98  
99      /**
100      * @return return type of referenced method.
101      */
102     @Override
103     public Type getType(final ConstantPoolGen cpg) {
104         return getReturnType(cpg);
105     }
106 
107     /**
108      * Also works for instructions whose stack effect depends on the constant pool entry they reference.
109      *
110      * @return Number of words produced onto stack by this instruction
111      */
112     @Override
113     public int produceStack(final ConstantPoolGen cpg) {
114         final String signature = getSignature(cpg);
115         return Type.getReturnTypeSize(signature);
116     }
117 
118     /**
119      * @return mnemonic for instruction with symbolic references resolved
120      */
121     @Override
122     public String toString(final ConstantPool cp) {
123         final Constant c = cp.getConstant(super.getIndex());
124         final StringTokenizer tok = new StringTokenizer(cp.constantToString(c));
125 
126         final String opcodeName = Const.getOpcodeName(super.getOpcode());
127 
128         final StringBuilder sb = new StringBuilder(opcodeName);
129         if (tok.hasMoreTokens()) {
130             sb.append(" ");
131             sb.append(Utility.packageToPath(tok.nextToken()));
132             if (tok.hasMoreTokens()) {
133                 sb.append(tok.nextToken());
134             }
135         }
136 
137         return sb.toString();
138     }
139 
140 }