blob: fdedc4a8aa07025b06ece816acaa3bbdd378e5ab [file] [log] [blame]
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package vm.runtime.defmeth.shared.data.method.body;
import vm.runtime.defmeth.shared.data.method.param.Param;
import jdk.internal.org.objectweb.asm.Opcodes;
import vm.runtime.defmeth.shared.data.Visitor;
import vm.runtime.defmeth.shared.data.Clazz;
import vm.runtime.defmeth.shared.data.Interface;
/**
* Represents arbitrary method call (invoke*).
*/
public class CallMethod implements MethodBody {
/** Invocation byte code instruction */
public static enum Invoke {
VIRTUAL( Opcodes.INVOKEVIRTUAL, "INVOKEVIRTUAL", 5),
INTERFACE( Opcodes.INVOKEINTERFACE, "INVOKEINTERFACE", 9),
SPECIAL( Opcodes.INVOKESPECIAL, "INVOKESPECIAL", 7),
STATIC( Opcodes.INVOKESTATIC, "INVOKESTATIC", 6);
private final int opcode;
private final String name;
// Kind Description Interpretation
// 1 REF_getField, getfield C.f:T
// 2 REF_getStatic getstatic C.f:T
// 3 REF_putField putfield C.f:T
// 4 REF_putStatic putstatic C.f:T
// 5 REF_invokeVirtual invokevirtual C.m:(A*)T
// 6 REF_invokeStatic invokestatic C.m:(A*)T
// 7 REF_invokeSpecial invokespecial C.m:(A*)T
// 8 REF_newInvokeSpecial new C; dup; invokespecial C.<init>:(A*)void
// 9 REF_invokeInterface invokeinterface C.m:(A*)T
private final int tag;
Invoke(int opcode, String name, int tag) {
this.opcode = opcode;
this.name = name;
this.tag = tag;
}
public int opcode() {
return opcode;
}
@Override
public String toString() {
return name;
}
public int tag() {
return tag;
}
}
/** At callsite direct visitMethodInsn() to issue a CONSTANT_Methodref,
a CONSTANT_InterfaceMethodref or let it be determined at the
callsite if the callee is an instance of an Interface */
public static enum IndexbyteOp {
METHODREF,
INTERFACEMETHODREF,
CALLSITE
}
/** Invoke instruction which should be used for the call */
final Invoke invokeInsn;
/** Static receiver class */
final Clazz staticClass;
/** Dynamic receiver class */
final Clazz receiverClass;
/** Name of the method to be invoked*/
final String methodName;
/** Descriptor of the method to be invoked */
final String methodDesc;
/** Parameter values */
final Param[] params;
/** Name of method's return type */
final String returnType;
/** Should return value be popped off the stack after the call */
final boolean popReturnValue;
/** Indexbyte operand to generate at call site */
final IndexbyteOp generateIndexbyteOp;
public CallMethod(Invoke invokeInsn, Clazz staticClass, Clazz receiverClass,
String methodName, String methodDesc, Param[] params,
String returnType, boolean popReturnValue,
IndexbyteOp generateIndexbyteOp) {
this.invokeInsn = invokeInsn;
this.staticClass = staticClass;
this.receiverClass = receiverClass;
this.methodName = methodName;
this.methodDesc = methodDesc;
this.params = params;
this.returnType = returnType;
this.popReturnValue = popReturnValue;
this.generateIndexbyteOp = generateIndexbyteOp;
}
public boolean popReturnValue() {
return popReturnValue;
}
public IndexbyteOp generateIndexbyteOp() {
return generateIndexbyteOp;
}
public Invoke invokeInsn() {
return invokeInsn;
}
public Clazz staticClass() {
return staticClass;
}
public Clazz receiverClass() {
return receiverClass;
}
public String methodName() {
return methodName;
}
public String methodDesc() {
return methodDesc;
}
public Param[] params() {
return params;
}
public String returnType() {
return returnType;
}
public boolean isInterface() {
return generateIndexbyteOp() == IndexbyteOp.METHODREF ?
false :
(generateIndexbyteOp() == IndexbyteOp.INTERFACEMETHODREF ?
true :
staticClass() instanceof Interface);
}
@Override
public void visit(Visitor v) {
v.visitCallMethod(this);
}
}