Initial import
[jpf-core.git] / src / main / gov / nasa / jpf / jvm / bytecode / MONITORENTER.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.JPFException;
21 import gov.nasa.jpf.vm.ElementInfo;
22 import gov.nasa.jpf.vm.Instruction;
23 import gov.nasa.jpf.vm.MJIEnv;
24 import gov.nasa.jpf.vm.Scheduler;
25 import gov.nasa.jpf.vm.StackFrame;
26 import gov.nasa.jpf.vm.ThreadInfo;
27
28
29 /**
30  * Enter monitor for object
31  * ..., objectref => ...
32  */
33 public class MONITORENTER extends LockInstruction {
34
35   @Override
36   public Instruction execute (ThreadInfo ti) {
37     Scheduler scheduler = ti.getScheduler();
38     StackFrame frame = ti.getTopFrame();
39
40     int objref = frame.peek();      // Don't pop yet before we know we really enter
41     if (objref == MJIEnv.NULL){
42       return ti.createAndThrowException("java.lang.NullPointerException", "Attempt to acquire lock for null object");
43     }
44
45     lastLockRef = objref;
46     ElementInfo ei = ti.getModifiableElementInfo(objref);    
47     ei = scheduler.updateObjectSharedness(ti, ei, null); // locks most likely belong to shared objects
48     
49     if (!ti.isLockOwner(ei)){ // we only need to register, block and/or reschedule if this is not a recursive lock
50       if (ei.canLock(ti)) {
51         // record that this thread would lock the object upon next execution if we break the transition
52         // (note this doesn't re-add if already registered)
53         ei.registerLockContender(ti);
54         if (scheduler.setsLockAcquisitionCG(ti, ei)) { // optional scheduling point
55           return this;
56         }
57         
58       } else { // we need to block
59         ei.block(ti); // this means we only re-execute once we can acquire the lock
60         if (scheduler.setsBlockedThreadCG(ti, ei)){ // mandatory scheduling point
61           return this;
62         }
63         throw new JPFException("blocking MONITORENTER without transition break");            
64       }
65     }
66     
67     //--- bottom half or lock acquisition succeeded without transition break
68     frame = ti.getModifiableTopFrame(); // now we need to modify it
69     frame.pop();
70     
71     ei.lock(ti);  // mark object as locked, increment the lockCount, and set the thread as owner
72     return getNext(ti);
73   }  
74
75   @Override
76   public int getByteCode () {
77     return 0xC2;
78   }
79   
80   @Override
81   public void accept(JVMInstructionVisitor insVisitor) {
82           insVisitor.visit(this);
83   }
84 }