1 /*
2  * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 package vm.runtime.defmeth.shared.data.method.body;
25 
26 import vm.runtime.defmeth.shared.data.method.param.Param;
27 import jdk.internal.org.objectweb.asm.Opcodes;
28 import vm.runtime.defmeth.shared.data.Visitor;
29 import vm.runtime.defmeth.shared.data.Clazz;
30 import vm.runtime.defmeth.shared.data.Interface;
31 
32 /**
33  * Represents arbitrary method call (invoke*).
34  */
35 public class CallMethod implements MethodBody {
36 
37     /** Invocation byte code instruction */
38     public static enum Invoke {
39         VIRTUAL(   Opcodes.INVOKEVIRTUAL,   "INVOKEVIRTUAL",   5),
40         INTERFACE( Opcodes.INVOKEINTERFACE, "INVOKEINTERFACE", 9),
41         SPECIAL(   Opcodes.INVOKESPECIAL,   "INVOKESPECIAL",   7),
42         STATIC(    Opcodes.INVOKESTATIC,    "INVOKESTATIC",    6);
43 
44         private final int opcode;
45         private final String name;
46 
47         // Kind  Description           Interpretation
48         //    1   REF_getField,         getfield C.f:T
49         //    2   REF_getStatic         getstatic C.f:T
50         //    3   REF_putField          putfield C.f:T
51         //    4   REF_putStatic         putstatic C.f:T
52         //    5   REF_invokeVirtual     invokevirtual C.m:(A*)T
53         //    6   REF_invokeStatic      invokestatic C.m:(A*)T
54         //    7   REF_invokeSpecial     invokespecial C.m:(A*)T
55         //    8   REF_newInvokeSpecial  new C; dup; invokespecial C.<init>:(A*)void
56         //    9   REF_invokeInterface   invokeinterface C.m:(A*)T
57         private final int tag;
58 
Invoke(int opcode, String name, int tag)59         Invoke(int opcode, String name, int tag) {
60             this.opcode = opcode;
61             this.name = name;
62             this.tag = tag;
63         }
64 
opcode()65         public int opcode() {
66             return opcode;
67         }
68 
69         @Override
toString()70         public String toString() {
71             return name;
72         }
73 
tag()74         public int tag() {
75             return tag;
76         }
77     }
78 
79     /** At callsite direct visitMethodInsn() to issue a CONSTANT_Methodref,
80         a CONSTANT_InterfaceMethodref or let it be determined at the
81         callsite if the callee is an instance of an Interface */
82     public static enum IndexbyteOp {
83         METHODREF,
84         INTERFACEMETHODREF,
85         CALLSITE
86     }
87 
88     /** Invoke instruction which should be used for the call */
89     final Invoke invokeInsn;
90 
91     /** Static receiver class */
92     final Clazz staticClass;
93 
94     /** Dynamic receiver class */
95     final Clazz receiverClass;
96 
97     /** Name of the method to be invoked*/
98     final String methodName;
99 
100     /** Descriptor of the method to be invoked */
101     final String methodDesc;
102 
103     /** Parameter values */
104     final Param[] params;
105 
106     /** Name of method's return type */
107     final String returnType;
108 
109     /** Should return value be popped off the stack after the call */
110     final boolean popReturnValue;
111 
112     /** Indexbyte operand to generate at call site */
113     final IndexbyteOp generateIndexbyteOp;
114 
CallMethod(Invoke invokeInsn, Clazz staticClass, Clazz receiverClass, String methodName, String methodDesc, Param[] params, String returnType, boolean popReturnValue, IndexbyteOp generateIndexbyteOp)115     public CallMethod(Invoke invokeInsn, Clazz staticClass, Clazz receiverClass,
116                       String methodName, String methodDesc, Param[] params,
117                       String returnType, boolean popReturnValue,
118                       IndexbyteOp generateIndexbyteOp) {
119         this.invokeInsn = invokeInsn;
120         this.staticClass = staticClass;
121         this.receiverClass = receiverClass;
122         this.methodName = methodName;
123         this.methodDesc = methodDesc;
124         this.params = params;
125         this.returnType = returnType;
126         this.popReturnValue = popReturnValue;
127         this.generateIndexbyteOp = generateIndexbyteOp;
128     }
129 
popReturnValue()130     public boolean popReturnValue() {
131         return popReturnValue;
132     }
133 
generateIndexbyteOp()134     public IndexbyteOp generateIndexbyteOp() {
135         return generateIndexbyteOp;
136     }
137 
invokeInsn()138     public Invoke invokeInsn() {
139         return invokeInsn;
140     }
141 
staticClass()142     public Clazz staticClass() {
143         return staticClass;
144     }
145 
receiverClass()146     public Clazz receiverClass() {
147         return receiverClass;
148     }
149 
methodName()150     public String methodName() {
151         return methodName;
152     }
153 
methodDesc()154     public String methodDesc() {
155         return methodDesc;
156     }
157 
params()158     public Param[] params() {
159         return params;
160     }
161 
returnType()162     public String returnType() {
163         return returnType;
164     }
165 
isInterface()166     public boolean isInterface() {
167         return generateIndexbyteOp() == IndexbyteOp.METHODREF ?
168                      false :
169                      (generateIndexbyteOp() == IndexbyteOp.INTERFACEMETHODREF ?
170                          true :
171                          staticClass() instanceof Interface);
172     }
173 
174     @Override
visit(Visitor v)175     public void visit(Visitor v) {
176         v.visitCallMethod(this);
177     }
178 }
179