view src/main/gov/nasa/jpf/vm/StaticElementInfo.java @ 17:e15b03204dc7

added a @NoJPFExecution annotation, which sets a NoJPFExec system attr on marked methods during class load time, which gets checked by ThreadInfo.enter(). Useful to flag methods which have to be intercepted/cut off when executing classes under JPF that can also be used outside. Especially useful to avoid the recursive JPF problem that can be caused by tests (which mix classpath and native_classpath). This currently throws a JPFException, but we could also turn this into a AssertionError in the SUT so that we get the SUT stack trace
author Peter Mehlitz <pcmehlitz@gmail.com>
date Mon, 23 Mar 2015 12:54:20 -0700
parents 61d41facf527
children
line wrap: on
line source

/*
 * Copyright (C) 2014, United States Government, as represented by the
 * Administrator of the National Aeronautics and Space Administration.
 * All rights reserved.
 *
 * The Java Pathfinder core (jpf-core) platform is licensed under the
 * Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 * 
 *        http://www.apache.org/licenses/LICENSE-2.0. 
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */
package gov.nasa.jpf.vm;

import gov.nasa.jpf.JPFException;
import gov.nasa.jpf.util.HashData;

/**
 * A specialized version of ElementInfo that is used for static fields. Each
 * registered ClassInfo instance has its own StaticElementInfo instance
 */
public final class StaticElementInfo extends ElementInfo {

  // this is kind of dangerous - make sure these flags are still unused in ElementInfo
  static final int ATTR_COR_CHANGED    = 0x100000;
  static final int ATTR_STATUS_CHANGED = 0x200000;

  static final int ATTR_ANY_CHANGED = ElementInfo.ATTR_ANY_CHANGED | ATTR_COR_CHANGED | ATTR_STATUS_CHANGED;
  
  protected int classObjectRef = MJIEnv.NULL;
  protected int status = ClassInfo.UNINITIALIZED;

  
  public StaticElementInfo () {
  }

  public StaticElementInfo (int id, ClassInfo ci, Fields f, Monitor m, ThreadInfo ti, ElementInfo eiClsObj) {
    super(id, ci, f, m, ti);

    // startup classes don't have a class object yet
    if (eiClsObj != null) {
      classObjectRef = eiClsObj.getObjectRef();
    }

    ti.getScheduler().initializeClassSharedness(ti, this);
  }
  
  @Override
  public ElementInfo getModifiableInstance() {
    if (!isFrozen()) {
      return this;
    } else {
      Statics statics = ci.getStatics();
      return statics.getModifiable( objRef);
    }
  }
  
  @Override
  public boolean isObject(){
    return false;
  }

  @Override
  public boolean isArray(){
    return false;
  }
  
  @Override
  public boolean hasFinalizer() {
    return false;
  }
  
  @Override
  protected int getNumberOfFieldsOrElements(){
    // static fields can't be arrays, those are always heap objects
    return ci.getNumberOfStaticFields();
  }

  @Override
  public boolean hasChanged() {
    return (attributes & ATTR_ANY_CHANGED) != 0;
  }

  @Override
  public void markUnchanged() {
    attributes &= ~ATTR_ANY_CHANGED;
  }
  
  @Override
  public void hash(HashData hd) {
    super.hash(hd);
    hd.add(classObjectRef);
    hd.add(status);
  }

  @Override
  public boolean equals(Object o) {
    if (super.equals(o) && o instanceof StaticElementInfo) {
      StaticElementInfo other = (StaticElementInfo) o;

      if (classObjectRef != other.classObjectRef) {
        return false;
      }
      if (status != other.status) {
        return false;
      }

      return true;

    } else {
      return false;
    }
  }


  /**
  public boolean isShared() {
    // static fields are always thread global
    return true;
  }
  **/

  public int getStatus() {
    return status;
  }
  
  void setStatus (int newStatus) {
    checkIsModifiable();
    
    if (status != newStatus) {
      status = newStatus;
      attributes |= ATTR_STATUS_CHANGED;
    }
  }

  
  @Override
  protected FieldInfo getDeclaredFieldInfo (String clsBase, String fname) {
    ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsBase); // <2do> should use CL argument
    FieldInfo fi = ci.getDeclaredStaticField(fname);
    
    if (fi == null) {
      throw new JPFException("class " + ci.getName() +
                                         " has no static field " + fname);
    }
    return fi;
  }

  @Override
  public FieldInfo getFieldInfo (String fname) {
    ClassInfo ci = getClassInfo();
    return ci.getStaticField(fname);
  }
  
  protected void checkFieldInfo (FieldInfo fi) {
    if (getClassInfo() != fi.getClassInfo()) {
      throw new JPFException("wrong static FieldInfo : " + fi.getName()
          + " , no such field in class " + getClassInfo().getName());
    }
  }

  @Override
  public int getNumberOfFields () {
    return getClassInfo().getNumberOfStaticFields();
  }
  
  @Override
  public FieldInfo getFieldInfo (int fieldIndex) {
    return getClassInfo().getStaticField(fieldIndex);
  }
    
  /**
   * gc mark all objects stored in static reference fields
   */
  void markStaticRoot (Heap heap) {
    ClassInfo ci = getClassInfo();
    int n = ci.getNumberOfStaticFields();
    
    for (int i=0; i<n; i++) {
      FieldInfo fi = ci.getStaticField(i);
      if (fi.isReference()) {
        int objref = fields.getIntValue(fi.getStorageOffset());
        heap.markStaticRoot(objref);
      }
    }
    
    // don't forget the class object itself (which is not a field)
    heap.markStaticRoot(classObjectRef);
  }
      
  public int getClassObjectRef () {
    return classObjectRef;
  }
  
  public void setClassObjectRef(int r) {
    checkIsModifiable();
    
    classObjectRef = r;
    attributes |= ATTR_COR_CHANGED;
  }

  @Override
  public String toString() {
    return getClassInfo().getName(); // don't append objRef (useless and misleading for statics)
  }

  protected ElementInfo getReferencedElementInfo (FieldInfo fi){
    assert fi.isReference();
    Heap heap = VM.getVM().getHeap();
    return heap.get(getIntField(fi));
  }

}