Initial import
[jpf-core.git] / src / main / gov / nasa / jpf / jvm / bytecode / PUTFIELD.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.util.InstructionState;
21 import gov.nasa.jpf.vm.ElementInfo;
22 import gov.nasa.jpf.vm.FieldInfo;
23 import gov.nasa.jpf.vm.Instruction;
24 import gov.nasa.jpf.vm.MJIEnv;
25 import gov.nasa.jpf.vm.Scheduler;
26 import gov.nasa.jpf.vm.StackFrame;
27 import gov.nasa.jpf.vm.ThreadInfo;
28 import gov.nasa.jpf.vm.bytecode.WriteInstruction;
29
30 /**
31  * Set field in object
32  * ..., objectref, value => ...
33  */
34 public class PUTFIELD extends JVMInstanceFieldInstruction implements WriteInstruction {
35
36   public PUTFIELD(String fieldName, String clsDescriptor, String fieldDescriptor){
37     super(fieldName, clsDescriptor, fieldDescriptor);
38   }  
39
40   @Override
41   public int getObjectSlot (StackFrame frame){
42     return frame.getTopPos() - size;
43   }
44
45   /**
46    * where do we get the value from?
47    * NOTE: only makes sense in a executeInstruction() context 
48    */
49   @Override
50   public int getValueSlot (StackFrame frame){
51     return frame.getTopPos();
52   }
53
54   
55   /**
56    * where do we write to?
57    * NOTE: this should only be used from a executeInstruction()/instructionExecuted() context
58    */
59   @Override
60   public ElementInfo getElementInfo(ThreadInfo ti){
61     if (isCompleted(ti)){
62       return ti.getElementInfo(lastThis);
63     } else {
64       return peekElementInfo(ti); // get it from the stack
65     }
66   }
67
68   @Override
69   public Instruction execute (ThreadInfo ti) {
70     StackFrame frame = ti.getModifiableTopFrame();
71     int objRef = frame.peek( size);
72     lastThis = objRef;
73     
74     if (objRef == MJIEnv.NULL) {
75       return ti.createAndThrowException("java.lang.NullPointerException", "referencing field '" + fname + "' on null object");
76     }
77
78     ElementInfo eiFieldOwner = ti.getModifiableElementInfo(objRef);
79     FieldInfo fieldInfo = getFieldInfo();
80     if (fieldInfo == null) {
81       return ti.createAndThrowException("java.lang.NoSuchFieldError", "no field " + fname + " in " + eiFieldOwner);
82     }
83     
84     //--- check scheduling point due to shared object access
85     Scheduler scheduler = ti.getScheduler();
86     if (scheduler.canHaveSharedObjectCG(ti,this,eiFieldOwner,fieldInfo)){
87       eiFieldOwner = scheduler.updateObjectSharedness( ti, eiFieldOwner, fi);
88       if (scheduler.setsSharedObjectCG( ti, this, eiFieldOwner, fieldInfo)){
89         return this; // re-execute
90       }
91     }
92     
93     // this might be re-executed
94     if (frame.getAndResetFrameAttr(InstructionState.class) == null){
95       lastValue = PutHelper.setField(ti, frame, eiFieldOwner, fieldInfo);
96     }
97     
98     //--- check scheduling point due to exposure through shared object
99     if (isReferenceField()){
100       int refValue = frame.peek();
101       if (refValue != MJIEnv.NULL){
102         ElementInfo eiExposed = ti.getElementInfo(refValue);
103         if (scheduler.setsSharedObjectExposureCG(ti, this, eiFieldOwner, fi, eiExposed)){
104           frame.addFrameAttr( InstructionState.processed);
105           return this; // re-execute AFTER assignment
106         }
107       }
108     }
109     
110     popOperands(frame);      
111     return getNext();
112   }
113
114   protected void popOperands (StackFrame frame){
115     if (size == 1){
116       frame.pop(2); // .. objref, val => ..
117     } else {
118       frame.pop(3); // .. objref, highVal,lowVal => ..    
119     }
120   }
121     
122   @Override
123   public ElementInfo peekElementInfo (ThreadInfo ti) {
124     FieldInfo fi = getFieldInfo();
125     int storageSize = fi.getStorageSize();
126     int objRef = ti.getTopFrame().peek( (storageSize == 1) ? 1 : 2);
127     ElementInfo ei = ti.getElementInfo( objRef);
128
129     return ei;
130   }
131
132
133   @Override
134   public int getLength() {
135     return 3; // opcode, index1, index2
136   }
137
138   @Override
139   public int getByteCode () {
140     return 0xB5;
141   }
142
143   @Override
144   public boolean isRead() {
145     return false;
146   }
147
148   @Override
149   public void accept(JVMInstructionVisitor insVisitor) {
150           insVisitor.visit(this);
151   }
152 }
153
154
155