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