Initial import
[jpf-core.git] / src / main / gov / nasa / jpf / vm / bytecode / StaticFieldInstruction.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
19 package gov.nasa.jpf.vm.bytecode;
20
21 import gov.nasa.jpf.vm.ClassInfo;
22 import gov.nasa.jpf.vm.ElementInfo;
23 import gov.nasa.jpf.vm.FieldInfo;
24 import gov.nasa.jpf.vm.StaticElementInfo;
25 import gov.nasa.jpf.vm.ThreadInfo;
26
27 /**
28  * common machine independent type for static field accessors
29  */
30 public abstract class StaticFieldInstruction extends FieldInstruction {
31
32   protected StaticFieldInstruction(String fieldName, String clsDescriptor, String fieldDescriptor){
33     super(fieldName, clsDescriptor, fieldDescriptor);
34   }
35
36   /**
37    * on-demand initialize the ClassInfo and FieldInfo fields. Note that
38    * classinfo might not correspond with the static className, but can be one of
39    * the super classes. Rather than checking for this on each subsequent access,
40    * we get the right one that declares the field here
41    */
42   protected void initialize() {
43     ClassInfo ciRef = mi.getClassInfo().resolveReferencedClass(className);
44     
45     FieldInfo f = ciRef.getStaticField(fname);
46     if (f != null){
47       ClassInfo ciField = f.getClassInfo();
48       if (!ciField.isRegistered()){
49         // classLoaded listeners might change/remove this field
50         ciField.registerClass(ThreadInfo.getCurrentThread());
51         f = ciField.getStaticField(fname);
52       }
53
54       fi = f;
55     }
56     // otherwise the referenced class has changed since compilation, which
57     // should throw a NoSuchFieldError in the caller
58   }
59
60   /**
61    * who owns the field?
62    * NOTE: this should only be used from a executeInstruction()/instructionExecuted() context
63    */
64   @Override
65   public ElementInfo getElementInfo(ThreadInfo ti){
66     return getFieldInfo().getClassInfo().getStaticElementInfo();
67   }
68   
69   @Override
70   public String toPostExecString(){
71     StringBuilder sb = new StringBuilder();
72     sb.append(getMnemonic());
73     sb.append(' ');
74     sb.append( fi.getFullName());
75     
76     return sb.toString();
77   }
78
79   public ClassInfo getClassInfo() {
80     if (fi == null) {
81       initialize();
82     }
83     return fi.getClassInfo();
84   }
85
86   @Override
87   public FieldInfo getFieldInfo() {
88     if (fi == null) {
89       initialize();
90     }
91     return fi;
92   }
93
94   /**
95    *  that's invariant, as opposed to InstanceFieldInstruction, so it's
96    *  not really a peek
97    */
98   @Override
99   public ElementInfo peekElementInfo (ThreadInfo ti) {
100     return getLastElementInfo();
101   }
102
103   @Override
104   public StaticElementInfo getLastElementInfo() {
105     return getFieldInfo().getClassInfo().getStaticElementInfo();
106   }
107
108   // this can be different than ciField - the field might be in one of its
109   // superclasses
110   public ClassInfo getLastClassInfo(){
111     return getFieldInfo().getClassInfo();
112   }
113
114   public String getLastClassName() {
115     return getLastClassInfo().getName();
116   }
117
118 }