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