• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 1998, 2016, 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package com.sun.tools.jdi;
27 
28 import com.sun.jdi.*;
29 
30 import java.util.List;
31 import java.util.Iterator;
32 import java.util.ArrayList;
33 import java.util.Comparator;
34 
35 public abstract class MethodImpl extends TypeComponentImpl
36     implements Method {
37     private JNITypeParser signatureParser;
argSlotCount()38     abstract int argSlotCount() throws AbsentInformationException;
39 
allLineLocations(SDE.Stratum stratum, String sourceName)40     abstract List<Location> allLineLocations(SDE.Stratum stratum,
41                                    String sourceName)
42                            throws AbsentInformationException;
43 
locationsOfLine(SDE.Stratum stratum, String sourceName, int lineNumber)44     abstract List<Location> locationsOfLine(SDE.Stratum stratum,
45                                   String sourceName,
46                                   int lineNumber)
47                            throws AbsentInformationException;
48 
MethodImpl(VirtualMachine vm, ReferenceTypeImpl declaringType, long ref, String name, String signature, String genericSignature, int modifiers)49     MethodImpl(VirtualMachine vm, ReferenceTypeImpl declaringType,
50                long ref,
51                String name, String signature,
52                String genericSignature, int modifiers) {
53         super(vm, declaringType, ref, name, signature,
54               genericSignature, modifiers);
55         signatureParser = new JNITypeParser(signature);
56     }
57 
createMethodImpl(VirtualMachine vm, ReferenceTypeImpl declaringType, long ref, String name, String signature, String genericSignature, int modifiers)58     static MethodImpl createMethodImpl(VirtualMachine vm,
59                                        ReferenceTypeImpl declaringType,
60                                        long ref,
61                                        String name,
62                                        String signature,
63                                        String genericSignature,
64                                        int modifiers) {
65         if ((modifiers &
66              (VMModifiers.NATIVE | VMModifiers.ABSTRACT)) != 0) {
67             return new NonConcreteMethodImpl(vm, declaringType, ref,
68                                              name, signature,
69                                              genericSignature,
70                                              modifiers);
71         } else {
72             return new ConcreteMethodImpl(vm, declaringType, ref,
73                                           name, signature,
74                                           genericSignature,
75                                           modifiers);
76         }
77     }
78 
equals(Object obj)79     public boolean equals(Object obj) {
80         if ((obj != null) && (obj instanceof MethodImpl)) {
81             MethodImpl other = (MethodImpl)obj;
82             return (declaringType().equals(other.declaringType())) &&
83                    (ref() == other.ref()) &&
84                    super.equals(obj);
85         } else {
86             return false;
87         }
88     }
89 
hashCode()90     public int hashCode() {
91         return (int)ref();
92     }
93 
allLineLocations()94     public final List<Location> allLineLocations()
95                            throws AbsentInformationException {
96         return allLineLocations(vm.getDefaultStratum(), null);
97     }
98 
allLineLocations(String stratumID, String sourceName)99     public List<Location> allLineLocations(String stratumID,
100                                  String sourceName)
101                            throws AbsentInformationException {
102         return allLineLocations(declaringType.stratum(stratumID),
103                                 sourceName);
104     }
105 
locationsOfLine(int lineNumber)106     public final List<Location> locationsOfLine(int lineNumber)
107                            throws AbsentInformationException {
108         return locationsOfLine(vm.getDefaultStratum(),
109                                null, lineNumber);
110     }
111 
locationsOfLine(String stratumID, String sourceName, int lineNumber)112     public List<Location> locationsOfLine(String stratumID,
113                                 String sourceName,
114                                 int lineNumber)
115                            throws AbsentInformationException {
116         return locationsOfLine(declaringType.stratum(stratumID),
117                                sourceName, lineNumber);
118     }
119 
codeIndexToLineInfo(SDE.Stratum stratum, long codeIndex)120     LineInfo codeIndexToLineInfo(SDE.Stratum stratum,
121                                  long codeIndex) {
122         if (stratum.isJava()) {
123             return new BaseLineInfo(-1, declaringType);
124         } else {
125             return new StratumLineInfo(stratum.id(), -1,
126                                        null, null);
127         }
128     }
129 
130     /**
131      * @return a text representation of the declared return type
132      * of this method.
133      */
returnTypeName()134     public String returnTypeName() {
135         return signatureParser.typeName();
136     }
137 
returnSignature()138     private String returnSignature() {
139         return signatureParser.signature();
140     }
141 
returnType()142     public Type returnType() throws ClassNotLoadedException {
143         return findType(returnSignature());
144     }
145 
findType(String signature)146     public Type findType(String signature) throws ClassNotLoadedException {
147         ReferenceTypeImpl enclosing = (ReferenceTypeImpl)declaringType();
148         return enclosing.findType(signature);
149     }
150 
argumentTypeNames()151     public List<String> argumentTypeNames() {
152         return signatureParser.argumentTypeNames();
153     }
154 
argumentSignatures()155     public List<String> argumentSignatures() {
156         return signatureParser.argumentSignatures();
157     }
158 
argumentType(int index)159     Type argumentType(int index) throws ClassNotLoadedException {
160         ReferenceTypeImpl enclosing = (ReferenceTypeImpl)declaringType();
161         String signature = argumentSignatures().get(index);
162         return enclosing.findType(signature);
163     }
164 
argumentTypes()165     public List<Type> argumentTypes() throws ClassNotLoadedException {
166         int size = argumentSignatures().size();
167         ArrayList<Type> types = new ArrayList<Type>(size);
168         for (int i = 0; i < size; i++) {
169             Type type = argumentType(i);
170             types.add(type);
171         }
172 
173         return types;
174     }
175 
compareTo(Method method)176     public int compareTo(Method method) {
177         ReferenceTypeImpl declaringType = (ReferenceTypeImpl)declaringType();
178         int rc = declaringType.compareTo(method.declaringType());
179         if (rc == 0) {
180             rc = declaringType.indexOf(this) -
181                     declaringType.indexOf(method);
182         }
183         return rc;
184     }
185 
isAbstract()186     public boolean isAbstract() {
187         return isModifierSet(VMModifiers.ABSTRACT);
188     }
189 
isDefault()190     public boolean isDefault() {
191         return !isModifierSet(VMModifiers.ABSTRACT) &&
192                !isModifierSet(VMModifiers.STATIC) &&
193                !isModifierSet(VMModifiers.PRIVATE) &&
194                declaringType() instanceof InterfaceType;
195     }
196 
isSynchronized()197     public boolean isSynchronized() {
198         return isModifierSet(VMModifiers.SYNCHRONIZED);
199     }
200 
isNative()201     public boolean isNative() {
202         return isModifierSet(VMModifiers.NATIVE);
203     }
204 
isVarArgs()205     public boolean isVarArgs() {
206         return isModifierSet(VMModifiers.VARARGS);
207     }
208 
isBridge()209     public boolean isBridge() {
210         return isModifierSet(VMModifiers.BRIDGE);
211     }
212 
isConstructor()213     public boolean isConstructor() {
214         return name().equals("<init>");
215     }
216 
isStaticInitializer()217     public boolean isStaticInitializer() {
218         return name().equals("<clinit>");
219     }
220 
isObsolete()221     public boolean isObsolete() {
222         try {
223             return JDWP.Method.IsObsolete.process(vm,
224                                     declaringType, ref).isObsolete;
225         } catch (JDWPException exc) {
226             throw exc.toJDIException();
227         }
228     }
229 
230 
231     /*
232      * A container class for the return value to allow
233      * proper type-checking.
234      */
235     class ReturnContainer implements ValueContainer {
ReturnContainer()236         ReturnContainer() {
237         }
type()238         public Type type() throws ClassNotLoadedException {
239             return returnType();
240         }
typeName()241         public String typeName(){
242             return returnTypeName();
243         }
signature()244         public String signature() {
245             return returnSignature(); //type().signature();
246         }
findType(String signature)247         public Type findType(String signature) throws ClassNotLoadedException {
248             return MethodImpl.this.findType(signature);
249         }
250     }
251     ReturnContainer retValContainer = null;
getReturnValueContainer()252     ReturnContainer getReturnValueContainer() {
253         if (retValContainer == null) {
254             retValContainer = new ReturnContainer();
255         }
256         return retValContainer;
257     }
258 
259     /*
260      * A container class for the argument to allow
261      * proper type-checking.
262      */
263     class ArgumentContainer implements ValueContainer {
264         int index;
265 
ArgumentContainer(int index)266         ArgumentContainer(int index) {
267             this.index = index;
268         }
type()269         public Type type() throws ClassNotLoadedException {
270             return argumentType(index);
271         }
typeName()272         public String typeName(){
273             return argumentTypeNames().get(index);
274         }
signature()275         public String signature() {
276             return argumentSignatures().get(index);
277         }
findType(String signature)278         public Type findType(String signature) throws ClassNotLoadedException {
279             return MethodImpl.this.findType(signature);
280         }
281     }
282 
283     /*
284      * This is a var args method.  Thus, its last param is an
285      * array. If the method has n params, then:
286      * 1.  If there are n args and the last is the same type as the type of
287      *     the last param, do nothing.  IE, a String[]
288      *     can be passed to a String...
289      * 2.  If there are >= n arguments and for each arg whose number is >= n,
290      *     the arg type is 'compatible' with the component type of
291      *     the last param, then do
292      *     - create an array of the type of the last param
293      *     - put the n, ... args into this array.
294      *       We might have to do conversions here.
295      *     - put this array into arguments(n)
296      *     - delete arguments(n+1), ...
297      * NOTE that this might modify the input list.
298      */
handleVarArgs(List<Value> arguments)299     void handleVarArgs(List<Value> arguments)
300         throws ClassNotLoadedException, InvalidTypeException {
301         List<Type> paramTypes = this.argumentTypes();
302         ArrayType lastParamType = (ArrayType)paramTypes.get(paramTypes.size() - 1);
303         Type componentType = lastParamType.componentType();
304         int argCount = arguments.size();
305         int paramCount = paramTypes.size();
306         if (argCount < paramCount - 1) {
307             // Error; will be caught later.
308             return;
309         }
310         if (argCount == paramCount - 1) {
311             // It is ok to pass 0 args to the var arg.
312             // We have to gen a 0 length array.
313             ArrayReference argArray = lastParamType.newInstance(0);
314             arguments.add(argArray);
315             return;
316         }
317         Value nthArgValue = arguments.get(paramCount - 1);
318         if (nthArgValue == null && argCount == paramCount) {
319             // We have one varargs parameter and it is null
320             // so we don't have to do anything.
321             return;
322         }
323         // If the first varargs parameter is null, then don't
324         // access its type since it can't be an array.
325         Type nthArgType = (nthArgValue == null) ? null : nthArgValue.type();
326         if (nthArgType instanceof ArrayTypeImpl) {
327             if (argCount == paramCount &&
328                 ((ArrayTypeImpl)nthArgType).isAssignableTo(lastParamType)) {
329                 /*
330                  * This is case 1.  A compatible array is being passed to the
331                  * var args array param.  We don't have to do anything.
332                  */
333                 return;
334             }
335         }
336 
337         /*
338          * Case 2.  We have to verify that the n, n+1, ... args are compatible
339          * with componentType, and do conversions if necessary and create
340          * an array of componentType to hold these possibly converted values.
341          */
342         int count = argCount - paramCount + 1;
343         ArrayReference argArray = lastParamType.newInstance(count);
344 
345         /*
346          * This will copy arguments(paramCount - 1) ... to argArray(0) ...
347          * doing whatever conversions are needed!  It will throw an
348          * exception if an incompatible arg is encountered
349          */
350         argArray.setValues(0, arguments, paramCount - 1, count);
351         arguments.set(paramCount - 1, argArray);
352 
353         /*
354          * Remove the excess args
355          */
356         for (int ii = paramCount; ii < argCount; ii++) {
357             arguments.remove(paramCount);
358         }
359         return;
360     }
361 
362     /*
363      * The output list will be different than the input list.
364      */
validateAndPrepareArgumentsForInvoke(List<? extends Value> origArguments)365     List<Value> validateAndPrepareArgumentsForInvoke(List<? extends Value> origArguments)
366                          throws ClassNotLoadedException, InvalidTypeException {
367 
368         List<Value> arguments = new ArrayList<Value>(origArguments);
369         if (isVarArgs()) {
370             handleVarArgs(arguments);
371         }
372 
373         int argSize = arguments.size();
374 
375         JNITypeParser parser = new JNITypeParser(signature());
376         List<String> signatures = parser.argumentSignatures();
377 
378         if (signatures.size() != argSize) {
379             throw new IllegalArgumentException("Invalid argument count: expected " +
380                                                signatures.size() + ", received " +
381                                                arguments.size());
382         }
383 
384         for (int i = 0; i < argSize; i++) {
385             Value value = arguments.get(i);
386             value = ValueImpl.prepareForAssignment(value,
387                                                    new ArgumentContainer(i));
388             arguments.set(i, value);
389         }
390         return arguments;
391     }
392 
toString()393     public String toString() {
394         StringBuffer sb = new StringBuffer();
395         sb.append(declaringType().name());
396         sb.append(".");
397         sb.append(name());
398         sb.append("(");
399         boolean first = true;
400         for (String name : argumentTypeNames()) {
401             if (!first) {
402                 sb.append(", ");
403             }
404             sb.append(name);
405             first = false;
406         }
407         sb.append(")");
408         return sb.toString();
409     }
410 }
411