View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.bcel.generic;
20  
21  import java.util.StringTokenizer;
22  
23  import org.apache.bcel.Const;
24  import org.apache.bcel.classfile.Constant;
25  import org.apache.bcel.classfile.ConstantCP;
26  import org.apache.bcel.classfile.ConstantPool;
27  import org.apache.bcel.classfile.Utility;
28  
29  /**
30   * Super class for the INVOKExxx family of instructions.
31   */
32  public abstract class InvokeInstruction extends FieldOrMethod implements ExceptionThrower, StackConsumer, StackProducer {
33  
34      /**
35       * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise.
36       */
37      InvokeInstruction() {
38      }
39  
40      /**
41       * Constructs an InvokeInstruction.
42       *
43       * @param opcode the opcode.
44       * @param index to constant pool.
45       */
46      protected InvokeInstruction(final short opcode, final int index) {
47          super(opcode, index);
48      }
49  
50      /**
51       * Also works for instructions whose stack effect depends on the constant pool entry they reference.
52       *
53       * @return Number of words consumed from stack by this instruction.
54       */
55      @Override
56      public int consumeStack(final ConstantPoolGen cpg) {
57          int sum;
58          if (super.getOpcode() == Const.INVOKESTATIC || super.getOpcode() == Const.INVOKEDYNAMIC) {
59              sum = 0;
60          } else {
61              sum = 1; // this reference
62          }
63  
64          final String signature = getSignature(cpg);
65          sum += Type.getArgumentTypesSize(signature);
66          return sum;
67      }
68  
69      /**
70       * Gets the argument types of referenced method.
71       *
72       * @param cpg the constant pool generator.
73       * @return argument types of referenced method.
74       */
75      public Type[] getArgumentTypes(final ConstantPoolGen cpg) {
76          return Type.getArgumentTypes(getSignature(cpg));
77      }
78  
79      /**
80       * This overrides the deprecated version as we know here that the referenced class may legally be an array.
81       *
82       * @return name of the referenced class/interface.
83       * @throws IllegalArgumentException if the referenced class is an array (this should not happen)
84       */
85      @Override
86      public String getClassName(final ConstantPoolGen cpg) {
87          final ConstantPool cp = cpg.getConstantPool();
88          final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex());
89          final String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class);
90          return Utility.pathToPackage(className);
91      }
92  
93      /**
94       * Gets the name of referenced method.
95       *
96       * @param cpg the constant pool generator.
97       * @return name of referenced method.
98       */
99      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