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