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.io.DataOutputStream;
25import java.io.IOException;
26
27import com.sun.org.apache.bcel.internal.Const;
28import com.sun.org.apache.bcel.internal.ExceptionConst;
29import com.sun.org.apache.bcel.internal.classfile.ConstantPool;
30import com.sun.org.apache.bcel.internal.util.ByteSequence;
31
32/**
33 * INVOKEINTERFACE - Invoke interface method
34 * <PRE>Stack: ..., objectref, [arg1, [arg2 ...]] -&gt; ...</PRE>
35 *
36 * @version $Id: INVOKEINTERFACE.java 1747278 2016-06-07 17:28:43Z britter $
37 * @see
38 * <a href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.invokeinterface">
39 * The invokeinterface instruction in The Java Virtual Machine Specification</a>
40 */
41public final class INVOKEINTERFACE extends InvokeInstruction {
42
43    private int nargs; // Number of arguments on stack (number of stack slots), called "count" in vmspec2
44
45
46    /**
47     * Empty constructor needed for the Class.newInstance() statement in
48     * Instruction.readInstruction(). Not to be used otherwise.
49     */
50    INVOKEINTERFACE() {
51    }
52
53
54    public INVOKEINTERFACE(final int index, final int nargs) {
55        super(Const.INVOKEINTERFACE, index);
56        super.setLength(5);
57        if (nargs < 1) {
58            throw new ClassGenException("Number of arguments must be > 0 " + nargs);
59        }
60        this.nargs = nargs;
61    }
62
63
64    /**
65     * Dump instruction as byte code to stream out.
66     * @param out Output stream
67     */
68    @Override
69    public void dump( final DataOutputStream out ) throws IOException {
70        out.writeByte(super.getOpcode());
71        out.writeShort(super.getIndex());
72        out.writeByte(nargs);
73        out.writeByte(0);
74    }
75
76
77    /**
78     * The <B>count</B> argument according to the Java Language Specification,
79     * Second Edition.
80     */
81    public int getCount() {
82        return nargs;
83    }
84
85
86    /**
87     * Read needed data (i.e., index) from file.
88     */
89    @Override
90    protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException {
91        super.initFromFile(bytes, wide);
92        super.setLength(5);
93        nargs = bytes.readUnsignedByte();
94        bytes.readByte(); // Skip 0 byte
95    }
96
97
98    /**
99     * @return mnemonic for instruction with symbolic references resolved
100     */
101    @Override
102    public String toString( final ConstantPool cp ) {
103        return super.toString(cp) + " " + nargs;
104    }
105
106
107    @Override
108    public int consumeStack( final ConstantPoolGen cpg ) { // nargs is given in byte-code
109        return nargs; // nargs includes this reference
110    }
111
112
113    @Override
114    public Class<?>[] getExceptions() {
115        return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_INTERFACE_METHOD_RESOLUTION,
116            ExceptionConst.UNSATISFIED_LINK_ERROR,
117            ExceptionConst.ABSTRACT_METHOD_ERROR,
118            ExceptionConst.ILLEGAL_ACCESS_ERROR,
119            ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR);
120    }
121
122
123    /**
124     * Call corresponding visitor method(s). The order is:
125     * Call visitor methods of implemented interfaces first, then
126     * call methods according to the class hierarchy in descending order,
127     * i.e., the most specific visitXXX() call comes last.
128     *
129     * @param v Visitor object
130     */
131    @Override
132    public void accept( final Visitor v ) {
133        v.visitExceptionThrower(this);
134        v.visitTypedInstruction(this);
135        v.visitStackConsumer(this);
136        v.visitStackProducer(this);
137        v.visitLoadClass(this);
138        v.visitCPInstruction(this);
139        v.visitFieldOrMethod(this);
140        v.visitInvokeInstruction(this);
141        v.visitINVOKEINTERFACE(this);
142    }
143}
144