// // Copyright (C) 2006 United States Government as represented by the // Administrator of the National Aeronautics and Space Administration // (NASA). All Rights Reserved. // // This software is distributed under the NASA Open Source Agreement // (NOSA), version 1.3. The NOSA has been approved by the Open Source // Initiative. See the file NOSA-1.3-JPF at the top of the distribution // directory tree for the complete NOSA document. // // THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY // KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT // LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO // SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR // A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT // THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT // DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. // package gov.nasa.jpf.jvm.bytecode; import de.fosd.typechef.featureexpr.FeatureExpr; import de.fosd.typechef.featureexpr.FeatureExprFactory; import gov.nasa.jpf.vm.ClassInfo; import gov.nasa.jpf.vm.ElementInfo; import gov.nasa.jpf.vm.FieldInfo; import gov.nasa.jpf.vm.Instruction; import gov.nasa.jpf.vm.MethodInfo; import gov.nasa.jpf.vm.StaticElementInfo; import gov.nasa.jpf.vm.ThreadInfo; /** * class to abstract instructions accessing static fields */ public abstract class StaticFieldInstruction extends FieldInstruction { protected StaticFieldInstruction(){} protected StaticFieldInstruction(String fieldName, String clsDescriptor, String fieldDescriptor){ super(fieldName, clsDescriptor, fieldDescriptor); } /** * on-demand initialize the ClassInfo and FieldInfo fields. Note that * classinfo might not correspond with the static className, but can be one of * the super classes. Rather than checking for this on each subsequent access, * we get the right one that declares the field here */ protected void initialize(FeatureExpr ctx) { ClassInfo ciRef = mi.getClassInfo().resolveReferencedClass(ctx, className); FieldInfo f = ciRef.getStaticField(fname); ClassInfo ciField = f.getClassInfo(); if (!ciField.isRegistered()){ // classLoaded listeners might change/remove this field ciField.registerClass(FeatureExprFactory.True(), ThreadInfo.getCurrentThread()); f = ciField.getStaticField(fname); } fi = f; } public ClassInfo getClassInfo() { if (fi == null) { initialize(null); } return fi.getClassInfo(); } public FieldInfo getFieldInfo(FeatureExpr ctx) { if (fi == null) { initialize(ctx); } return fi; } /** * that's invariant, as opposed to InstanceFieldInstruction, so it's * not really a peek */ public ElementInfo peekElementInfo (ThreadInfo ti) { return getLastElementInfo(); } public StaticElementInfo getLastElementInfo() { return getFieldInfo(FeatureExprFactory.True()).getClassInfo().getStaticElementInfo(); } // this can be different than ciField - the field might be in one of its // superclasses public ClassInfo getLastClassInfo(){ return getFieldInfo(FeatureExprFactory.True()).getClassInfo(); } public String getLastClassName() { return getLastClassInfo().getName(); } protected boolean isNewPorFieldBoundary (ThreadInfo ti) { return !ti.isFirstStepInsn() && ti.usePorFieldBoundaries() && isSchedulingRelevant(ti); } @Override protected boolean isSkippedFinalField (ElementInfo ei) { if (fi.isFinal()){ // NOTE - we only encounter this for references, other static finals // will be inlined by the compiler if (skipFinals || skipStaticFinals) { return true; } } return false; } protected boolean isSchedulingRelevant (ThreadInfo ti) { //--- configured override FieldInfo fi = getFieldInfo(null); if (fi.neverBreak()) { // this should filter out the bulk in most real apps (library code) return false; } else if (fi.breakShared()){ return true; } //--- field owner properties ElementInfo ei = fi.getClassInfo().getStaticElementInfo(); if (ei.isImmutable() || isSkippedFinalField(ei)) { return false; } if (!ei.isShared()) { return false; } if (!ti.hasOtherRunnables()) { // single threaded return false; } //--- special code patterns if (isMonitorEnterPrologue()) { // if this is a GET followed by a MONITOR_ENTER then we just break on the monitor return false; } if (mi.isClinit() && (fi.getClassInfo() == mi.getClassInfo())) { // clinits are all synchronized, so they don't count return false; } if (ti.usePorSyncDetection()) { if (isLockProtected(ti, ei)) { return false; } } return true; } public void accept(InstructionVisitor insVisitor) { insVisitor.visit(this); } @Override public Instruction typeSafeClone(MethodInfo mi) { StaticFieldInstruction clone = null; try { clone = (StaticFieldInstruction) super.clone(); // reset the method that this insn belongs to clone.mi = mi; clone.fi = null; // ClassInfo is going to be different } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clone; } }