Initial import
[jpf-core.git] / src / main / gov / nasa / jpf / jvm / bytecode / INVOKESPECIAL.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The Java Pathfinder core (jpf-core) platform is licensed under the
7  * Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  * 
10  *        http://www.apache.org/licenses/LICENSE-2.0. 
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and 
16  * limitations under the License.
17  */
18 package gov.nasa.jpf.jvm.bytecode;
19
20 import gov.nasa.jpf.vm.ClassInfo;
21 import gov.nasa.jpf.vm.ClassLoaderInfo;
22 import gov.nasa.jpf.vm.ElementInfo;
23 import gov.nasa.jpf.vm.Instruction;
24 import gov.nasa.jpf.vm.LoadOnJPFRequired;
25 import gov.nasa.jpf.vm.MethodInfo;
26 import gov.nasa.jpf.vm.ThreadInfo;
27
28
29 /**
30  * Invoke instance method; special handling for superclass, private,
31  * and instance initialization method invocations
32  * ..., objectref, [arg1, [arg2 ...]] => ...
33  *
34  * invokedMethod is supposed to be constant (ClassInfo can't change)
35  */
36 public class INVOKESPECIAL extends InstanceInvocation {
37
38   public INVOKESPECIAL (String clsDescriptor, String methodName, String signature){
39     super(clsDescriptor, methodName, signature);
40   }
41
42
43   @Override
44   public int getByteCode () {
45     return 0xB7;
46   }
47
48   @Override
49   public Instruction execute (ThreadInfo ti) {
50     int argSize = getArgSize();
51     int objRef = ti.getCalleeThis( argSize);
52     lastObj = objRef;
53
54     // we don't have to check for NULL objects since this is either a ctor, a 
55     // private method, or a super method
56
57     MethodInfo callee;  
58     try {
59       callee = getInvokedMethod(ti);
60     } catch(LoadOnJPFRequired rre) {
61       return ti.getPC();
62     }      
63
64     if (callee == null){
65       return ti.createAndThrowException("java.lang.NoSuchMethodException", "Calling " + cname + '.' + mname);
66     }
67
68     ElementInfo ei = ti.getElementInfo(objRef);
69     if (callee.isSynchronized()){
70       ei = ti.getScheduler().updateObjectSharedness(ti, ei, null); // locks most likely belong to shared objects
71       if (reschedulesLockAcquisition(ti, ei)){
72         return this;
73       }
74     }
75
76     setupCallee( ti, callee); // this creates, initializes and pushes the callee StackFrame
77
78     return ti.getPC(); // we can't just return the first callee insn if a listener throws an exception
79   }
80
81   /**
82    * If the current thread already owns the lock, then the current thread can go on.
83    * For example, this is a recursive acquisition.
84    */
85   protected boolean isLockOwner(ThreadInfo ti, ElementInfo ei) {
86     return ei.getLockingThread() == ti;
87   }
88
89   /**
90    * If the object will still be owned, then the current thread can go on.
91    * For example, all but the last monitorexit for the object.
92    */
93   protected boolean isLastUnlock(ElementInfo ei) {
94     return ei.getLockCount() == 1;
95   }
96
97   /**
98     * we can do some more caching here - the MethodInfo should be const
99     */
100   @Override
101   public MethodInfo getInvokedMethod (ThreadInfo th) {
102
103     // since INVOKESPECIAL is only used for private methods and ctors,
104     // we don't have to deal with null object calls
105
106     if (invokedMethod == null) {
107       ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(cname);
108       boolean recursiveLookup = (mname.charAt(0) != '<'); // no hierarchy lookup for <init>
109       invokedMethod = ci.getMethod(mname, recursiveLookup);
110     }
111
112     return invokedMethod; // we can store internally
113   }
114
115   @Override
116   public String toString() {
117     return ("invokespecial " + cname + '.' + mname);
118   }
119
120   @Override
121   public Object getFieldValue (String id, ThreadInfo ti) {
122     int objRef = getCalleeThis(ti);
123     ElementInfo ei = ti.getElementInfo(objRef);
124
125     Object v = ei.getFieldValueObject(id);
126
127     if (v == null){ // try a static field
128       v = ei.getClassInfo().getStaticFieldValueObject(id);
129     }
130
131     return v;
132   }
133
134   @Override
135   public void accept(JVMInstructionVisitor insVisitor) {
136           insVisitor.visit(this);
137   }
138 }