view src/main/gov/nasa/jpf/vm/Fields.java @ 0:61d41facf527

initial v8 import (history reset)
author Peter Mehlitz <Peter.C.Mehlitz@nasa.gov>
date Fri, 23 Jan 2015 10:14:01 -0800
parents
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.util.HashData;
import gov.nasa.jpf.util.IntVector;
import gov.nasa.jpf.util.Misc;
import gov.nasa.jpf.util.ObjectList;


/**
 * Represents the variable, hash-collapsed pooled data associated with an object
 * that is related to the object values (as opposed to synchronization ->Monitor).
 * Contains the values of the fields, not their descriptors.  Descriptors are represented
 * by gov.nasa.jpf.vm.FieldInfo objects, which are stored in the ClassInfo structure.
 *
 * @see gov.nasa.jpf.vm.FieldInfo
 * @see gov.nasa.jpf.vm.Monitor
 */
public abstract class Fields implements Cloneable {

  /**
   * we use this to store arbitrary field attributes (like symbolic values),
   * but only create this on demand
   */
  protected Object[] fieldAttrs;

  /**
   * attribute attached to the object as a whole
   */
  protected Object objectAttr;


  protected Fields() {}

  public boolean hasFieldAttr() {
    return fieldAttrs != null;
  }

  public boolean hasFieldAttr (Class<?> attrType){    
    Object[] fa = fieldAttrs;
    if (fa != null){
      for (int i=0; i<fa.length; i++){
        Object a = fa[i];
        if (a != null && ObjectList.containsType(a, attrType)){
          return true;
        }
      }
    }
    return false;
  }


  /**
   * this returns all of them - use either if you know there will be only
   * one attribute at a time, or check/process result with ObjectList
   */
  public Object getFieldAttr(int fieldOrElementIndex){
    if (fieldAttrs != null){
      return fieldAttrs[fieldOrElementIndex];
    }
    return null;
  }

  /**
   * this replaces all of them - use only if you know 
   *  - there will be only one attribute at a time
   *  - you obtained the value you set by a previous getXAttr()
   *  - you constructed a multi value list with ObjectList.createList()
   */
  public void setFieldAttr (int nFieldsOrElements, int fieldOrElementIndex, Object attr){
    if (fieldAttrs == null){
      if (attr == null){
        return; // no need to waste an array object for storing null
      }
      fieldAttrs = new Object[nFieldsOrElements];
    }
    fieldAttrs[fieldOrElementIndex] = attr;
  }
  
  public void addFieldAttr (int nFieldsOrElements, int fieldOrElementIndex, Object attr){
    if (attr != null){
      if (fieldAttrs == null) {
        fieldAttrs = new Object[nFieldsOrElements];
      }
      fieldAttrs[fieldOrElementIndex] = ObjectList.add(fieldAttrs[fieldOrElementIndex], attr);
    }
  }
  
  public void removeFieldAttr (int fieldOrElementIndex, Object attr){
    if (fieldAttrs != null){
     fieldAttrs[fieldOrElementIndex] = ObjectList.remove(fieldAttrs[fieldOrElementIndex], attr);
    }
  }
  
  public void replaceFieldAttr (int fieldOrElementIndex, Object oldAttr, Object newAttr){
    if (fieldAttrs != null){
     fieldAttrs[fieldOrElementIndex] = ObjectList.replace(fieldAttrs[fieldOrElementIndex], oldAttr, newAttr);
    }
  }
  
  public boolean hasFieldAttr (int fieldOrElementIndex, Class<?> type){
    if (fieldAttrs != null){
     return ObjectList.containsType(fieldAttrs[fieldOrElementIndex], type);
    }
    return false;
  }

  /**
   * this only returns the first attr of this type, there can be more
   * if you don't use client private types or the provided type is too general
   */
  public <T> T getFieldAttr (int fieldOrElementIndex, Class<T> type){
    if (fieldAttrs != null){
     return ObjectList.getFirst(fieldAttrs[fieldOrElementIndex], type);
    }
    return null;    
  }
  
  public <T> T getNextFieldAttr (int fieldOrElementIndex, Class<T> type, Object prev){
    if (fieldAttrs != null){
     return ObjectList.getNext(fieldAttrs[fieldOrElementIndex], type, prev);
    }
    return null;    
  }
  
  public ObjectList.Iterator fieldAttrIterator(int fieldOrElementIndex){
    Object a = (fieldAttrs != null) ? fieldAttrs[fieldOrElementIndex] : null;
    return ObjectList.iterator(a);
  }
  
  public <T> ObjectList.TypedIterator<T> fieldAttrIterator(int fieldOrElementIndex, Class<T> type){
    Object a = (fieldAttrs != null) ? fieldAttrs[fieldOrElementIndex] : null;
    return ObjectList.typedIterator(a, type);
  }
  

  //--- object attributes
  public boolean hasObjectAttr () {
    return (objectAttr != null);
  }

  public boolean hasObjectAttr (Class<?> attrType){
    return ObjectList.containsType(objectAttr, attrType);
  }

  /**
   * this returns all of them - use either if you know there will be only
   * one attribute at a time, or check/process result with ObjectList
   */
  public Object getObjectAttr(){
    return objectAttr;
  }

  /**
   * this replaces all of them - use only if you know 
   *  - there will be only one attribute at a time
   *  - you obtained the value you set by a previous getXAttr()
   *  - you constructed a multi value list with ObjectList.createList()
   */
  public void setObjectAttr (Object attr){
    objectAttr = attr;    
  }

  public void addObjectAttr (Object attr){
    objectAttr = ObjectList.add(objectAttr, attr);
  }

  public void removeObjectAttr (Object attr){
    objectAttr = ObjectList.remove(objectAttr, attr);
  }

  public void replaceObjectAttr (Object oldAttr, Object newAttr){
    objectAttr = ObjectList.replace(objectAttr, oldAttr, newAttr);
  }

  /**
   * this only returns the first attr of this type, there can be more
   * if you don't use client private types or the provided type is too general
   */
  public <T> T getObjectAttr (Class<T> attrType) {
    return ObjectList.getFirst(objectAttr, attrType);
  }

  public <T> T getNextObjectAttr (Class<T> attrType, Object prev) {
    return ObjectList.getNext(objectAttr, attrType, prev);
  }

  public ObjectList.Iterator objectAttrIterator(){
    return ObjectList.iterator(objectAttr);
  }
  
  public <T> ObjectList.TypedIterator<T> objectAttrIterator(Class<T> attrType){
    return ObjectList.typedIterator(objectAttr, attrType);
  }


  public abstract int[] asFieldSlots();

  /**
   * give an approximation of the heap size in bytes - we assume fields are word
   * aligned, hence the number of values*4 should be good. Note that this is
   * overridden by ArrayFields (arrays would be packed)
   */
  public abstract int getHeapSize ();


  public boolean isReferenceArray () {
    return false;
  }

  // our low level getters and setters
  public abstract int getIntValue (int index);

  // same as getIntValue(), just here to make intentions clear
  public abstract int getReferenceValue (int index);

  public abstract long getLongValue (int index);

  public abstract boolean getBooleanValue (int index);

  public abstract byte getByteValue (int index);

  public abstract char getCharValue (int index);

  public abstract short getShortValue (int index);

  public abstract float getFloatValue (int index);

  public abstract double getDoubleValue (int index);

  //--- the field modifier methods (both instance and static)

  public abstract void setReferenceValue (int index, int newValue);

  public abstract void setBooleanValue (int index, boolean newValue);

  public abstract void setByteValue (int index, byte newValue);

  public abstract void setCharValue (int index, char newValue);

  public abstract void setShortValue (int index, short newValue);

  public abstract void setFloatValue (int index, float newValue);

  public abstract void setIntValue (int index, int newValue);

  public abstract void setLongValue (int index, long newValue);

  public abstract void setDoubleValue (int index, double newValue);

  @Override
  public abstract Fields clone ();

  protected Fields cloneFields() {
    try {
      Fields f = (Fields)super.clone();

      if (fieldAttrs != null) {
        f.fieldAttrs = fieldAttrs.clone();
      }

      if (objectAttr != null) {
        f.objectAttr = objectAttr; //
      }

      return f;
    } catch (CloneNotSupportedException cnsx){
      return null;
    }
  }

  @Override
  public abstract boolean equals(Object o);

  // <2do> not multi-attr aware yet
  protected boolean compareAttrs(Fields f) {
    if (fieldAttrs != null || f.fieldAttrs != null) {
      if (!Misc.equals(fieldAttrs, f.fieldAttrs)) {
        return false;
      }
    }

    if (!ObjectList.equals(objectAttr, f.objectAttr)){
      return false;
    }

    return true;
  }

  // serialization interface
  public abstract void appendTo(IntVector v);


  @Override
  public int hashCode () {
    HashData hd = new HashData();
    hash(hd);
    hashAttrs(hd);
    return hd.getValue();
  }

  public abstract void hash(HashData hd);

  /**
   * Adds some data to the computation of an hashcode.
   */
  public void hashAttrs (HashData hd) {

    // it's debatable if we add the attributes to the state, but whatever it
    // is, it should be kept consistent with the StackFrame.hash()
    Object[] a = fieldAttrs;
    if (a != null) {
      for (int i=0, l=a.length; i < l; i++) {
        ObjectList.hash(a[i], hd);
      }
    }

    if (objectAttr != null){
      ObjectList.hash(objectAttr, hd);
    }
  }


  // <2do> not multi-attr aware yet
  public void copyAttrs(Fields other) {
    if (other.fieldAttrs != null){
      if (fieldAttrs == null){
        fieldAttrs = other.fieldAttrs.clone();
      } else {
        System.arraycopy(other.fieldAttrs, 0, fieldAttrs, 0, fieldAttrs.length);
      }
    }

    objectAttr = other.objectAttr;
  }
}