001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 *  Unless required by applicable law or agreed to in writing, software
012 *  distributed under the License is distributed on an "AS IS" BASIS,
013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 *  See the License for the specific language governing permissions and
015 *  limitations under the License.
016 *
017 */
018package org.apache.bcel.generic;
019
020import java.io.DataOutputStream;
021import java.io.IOException;
022
023import org.apache.bcel.Const;
024import org.apache.bcel.ExceptionConst;
025import org.apache.bcel.classfile.ConstantPool;
026import org.apache.bcel.util.ByteSequence;
027
028/**
029 * INVOKEINTERFACE - Invoke interface method
030 * <PRE>Stack: ..., objectref, [arg1, [arg2 ...]] -&gt; ...</PRE>
031 *
032 * @version $Id: INVOKEINTERFACE.java 1812166 2017-10-13 23:48:11Z ggregory $
033 * @see
034 * <a href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.invokeinterface">
035 * The invokeinterface instruction in The Java Virtual Machine Specification</a>
036 */
037public final class INVOKEINTERFACE extends InvokeInstruction {
038
039    private int nargs; // Number of arguments on stack (number of stack slots), called "count" in vmspec2
040
041
042    /**
043     * Empty constructor needed for Instruction.readInstruction.
044     * Not to be used otherwise.
045     */
046    INVOKEINTERFACE() {
047    }
048
049
050    public INVOKEINTERFACE(final int index, final int nargs) {
051        super(Const.INVOKEINTERFACE, index);
052        super.setLength(5);
053        if (nargs < 1) {
054            throw new ClassGenException("Number of arguments must be > 0 " + nargs);
055        }
056        this.nargs = nargs;
057    }
058
059
060    /**
061     * Dump instruction as byte code to stream out.
062     * @param out Output stream
063     */
064    @Override
065    public void dump( final DataOutputStream out ) throws IOException {
066        out.writeByte(super.getOpcode());
067        out.writeShort(super.getIndex());
068        out.writeByte(nargs);
069        out.writeByte(0);
070    }
071
072
073    /**
074     * The <B>count</B> argument according to the Java Language Specification,
075     * Second Edition.
076     */
077    public int getCount() {
078        return nargs;
079    }
080
081
082    /**
083     * Read needed data (i.e., index) from file.
084     */
085    @Override
086    protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException {
087        super.initFromFile(bytes, wide);
088        super.setLength(5);
089        nargs = bytes.readUnsignedByte();
090        bytes.readByte(); // Skip 0 byte
091    }
092
093
094    /**
095     * @return mnemonic for instruction with symbolic references resolved
096     */
097    @Override
098    public String toString( final ConstantPool cp ) {
099        return super.toString(cp) + " " + nargs;
100    }
101
102
103    @Override
104    public int consumeStack( final ConstantPoolGen cpg ) { // nargs is given in byte-code
105        return nargs; // nargs includes this reference
106    }
107
108
109    @Override
110    public Class<?>[] getExceptions() {
111        return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_INTERFACE_METHOD_RESOLUTION,
112            ExceptionConst.UNSATISFIED_LINK_ERROR,
113            ExceptionConst.ABSTRACT_METHOD_ERROR,
114            ExceptionConst.ILLEGAL_ACCESS_ERROR,
115            ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR);
116    }
117
118
119    /**
120     * Call corresponding visitor method(s). The order is:
121     * Call visitor methods of implemented interfaces first, then
122     * call methods according to the class hierarchy in descending order,
123     * i.e., the most specific visitXXX() call comes last.
124     *
125     * @param v Visitor object
126     */
127    @Override
128    public void accept( final Visitor v ) {
129        v.visitExceptionThrower(this);
130        v.visitTypedInstruction(this);
131        v.visitStackConsumer(this);
132        v.visitStackProducer(this);
133        v.visitLoadClass(this);
134        v.visitCPInstruction(this);
135        v.visitFieldOrMethod(this);
136        v.visitInvokeInstruction(this);
137        v.visitINVOKEINTERFACE(this);
138    }
139}