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