Fixing a few bugs in the statistics printout.
[jpf-core.git] / src / peers / gov / nasa / jpf / vm / JPF_java_lang_Object.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.vm;
19
20 import gov.nasa.jpf.JPFException;
21 import gov.nasa.jpf.annotation.MJI;
22 import gov.nasa.jpf.vm.ClassInfo;
23 import gov.nasa.jpf.vm.ElementInfo;
24 import gov.nasa.jpf.vm.Heap;
25 import gov.nasa.jpf.vm.MJIEnv;
26 import gov.nasa.jpf.vm.NativePeer;
27 import gov.nasa.jpf.vm.ThreadInfo;
28 import gov.nasa.jpf.vm.Types;
29
30
31 /**
32  * MJI NativePeer class for java.lang.Object library abstraction
33  */
34 public class JPF_java_lang_Object extends NativePeer {
35   
36   @MJI
37   public int getClass____Ljava_lang_Class_2 (MJIEnv env, int objref) {
38     ClassInfo oci = env.getClassInfo(objref);
39
40     return oci.getClassObjectRef();
41   }
42
43   @MJI
44   public int clone____Ljava_lang_Object_2 (MJIEnv env, int objref) {
45     Heap heap = env.getHeap();
46     ElementInfo ei = heap.get(objref);
47     ClassInfo ci = ei.getClassInfo();
48     ElementInfo eiClone = null;
49     
50     if (!ci.isInstanceOf("java.lang.Cloneable")) {
51       env.throwException("java.lang.CloneNotSupportedException",
52           ci.getName() + " does not implement java.lang.Cloneable.");
53       return MJIEnv.NULL;  // meaningless
54       
55     } else {
56       int newref;
57       if (ci.isArray()) {
58         ClassInfo cci = ci.getComponentClassInfo();
59         
60         String componentType;
61         if (cci.isPrimitive()){
62           componentType = Types.getTypeSignature(cci.getName(),false);
63         } else {
64           componentType = cci.getType();
65         }
66
67         eiClone = heap.newArray(componentType, ei.arrayLength(), env.getThreadInfo());
68         
69       } else {
70         eiClone = heap.newObject(ci, env.getThreadInfo());
71       }
72       
73       // Ok, this is nasty but efficient
74       eiClone.fields = ei.getFields().clone();
75
76       return eiClone.getObjectRef();
77     }
78   }
79
80   @MJI
81   public int hashCode____I (MJIEnv env, int objref) {
82     return (objref ^ 0xABCD);
83   }
84
85   protected void wait0 (MJIEnv env, int objref, long timeout) {
86     ThreadInfo ti = env.getThreadInfo();
87     ElementInfo ei = env.getModifiableElementInfo(objref);
88     
89     if (!ti.isFirstStepInsn()) {
90       if (!ei.isLockedBy(ti)) {
91         env.throwException("java.lang.IllegalMonitorStateException", "wait() without holding lock");
92         return;
93       }
94
95       if (ti.isInterrupted(true)) {
96         env.throwException("java.lang.InterruptedException");
97       } else {
98         ei.wait(ti, timeout); // block
99       }
100     }
101     
102     // scheduling point
103     if (ti.getScheduler().setsWaitCG(ti, timeout)) {
104       env.repeatInvocation();
105       return;
106     }
107     
108     // bottom half, unblock
109     switch (ti.getState()) {
110       case WAITING:
111       case TIMEOUT_WAITING:
112         throw new JPFException("blocking wait() without transition break");      
113       
114       // we can get here by direct call from ...Unsafe.park__ZJ__V()
115       // which aquires the park lock and waits natively
116       case RUNNING:
117
118       // note that we can't get here if we are in NOTIFIED or INTERRUPTED state,
119       // since we still have to reacquire the lock
120       case UNBLOCKED:
121       case TIMEDOUT: // nobody else acquired the lock
122         // thread status set by explicit notify() call
123         env.lockNotified(objref);
124
125         if (ti.isInterrupted(true)) {
126           env.throwException("java.lang.InterruptedException");
127         }
128         break;
129
130       default:
131         throw new JPFException("invalid thread state of: " + ti.getName() + " is " + ti.getStateName()
132                 + " while waiting on " + ei);
133     }
134   }
135   
136   // we intercept them both so that we don't get the java.lang.Object.wait() location
137   // as the blocking insn
138   @MJI
139   public void wait____V (MJIEnv env, int objref){
140     wait0(env,objref,0);
141   }
142   
143   @MJI
144   public void wait__J__V (MJIEnv env, int objref, long timeout) {
145     wait0(env,objref,timeout);
146   }
147
148   @MJI
149   public void wait__JI__V (MJIEnv env, int objref, long timeout, int nanos) {
150     wait0(env,objref,timeout);
151   }
152
153   
154   @MJI
155   public void notify____V (MJIEnv env, int objref) {
156     boolean didNotify = false;
157     ThreadInfo ti = env.getThreadInfo();
158     
159     if (!ti.isFirstStepInsn()) {
160       ElementInfo ei = env.getModifiableElementInfo(objref);
161       if (!ei.isLockedBy(ti)) {
162         env.throwException("java.lang.IllegalMonitorStateException", "notify() without holding lock");
163         return;
164       }
165       
166       didNotify = env.notify(ei);
167     }
168     
169     if (ti.getScheduler().setsNotifyCG(ti, didNotify)){
170       env.repeatInvocation();
171       return;
172     }
173   }
174
175   @MJI
176   public void notifyAll____V (MJIEnv env, int objref) {
177     boolean didNotify = false;
178     ThreadInfo ti = env.getThreadInfo();
179     
180     if (!ti.isFirstStepInsn()) {
181       ElementInfo ei = env.getModifiableElementInfo(objref);
182       if (!ei.isLockedBy(ti)) {
183         env.throwException("java.lang.IllegalMonitorStateException", "notifyAll() without holding lock");
184         return;
185       }
186       
187       didNotify = env.notifyAll(ei);
188     }
189     
190     if (ti.getScheduler().setsNotifyCG(ti, didNotify)){
191       env.repeatInvocation();
192       return;
193     }
194   }
195
196   @MJI
197   public int toString____Ljava_lang_String_2 (MJIEnv env, int objref) {
198     ClassInfo ci = env.getClassInfo(objref);
199     int hc = hashCode____I(env,objref);
200     
201     String s = ci.getName() + '@' + hc;
202     int sref = env.newString(s);
203     return sref;
204   }
205 }