// // 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.vm; import cmu.conditional.Conditional; import java.util.function.Function; import cmu.conditional.One; import gov.nasa.jpf.JPFException; /** * A specialized version of ElementInfo that represents heap objects */ public class DynamicElementInfo extends ElementInfo { public DynamicElementInfo () { // for restoration } public DynamicElementInfo (int objref, ClassInfo ci, Fields f, Monitor m, ThreadInfo ti) { super(objref, ci, f, m, ti); attributes = ci.getElementInfoAttrs(); // <2do> not ideal, should be in superclass (but doesn't work for SEIs) referencingThreads = createThreadInfoSet(ti); // initialization depends on subclass and policy setSharednessFromReferencingThreads(); } @Override public ElementInfo getModifiableInstance() { if (!isFrozen()) { return this; } else { return VM.getVM().getHeap().getModifiable( objRef); } } // called during ElementInfo construction @Override protected ThreadInfoSet createThreadInfoSet(ThreadInfo ti){ return SharedObjectPolicy.getPolicy().getThreadInfoSet(ti, this); } @Override public boolean isObject(){ return true; } @Override public boolean hasFinalizer() { return (ci.getFinalizer()!=null); } @Override protected int getNumberOfFieldsOrElements(){ if (fields instanceof ArrayFields){ return ((ArrayFields)fields).arrayLength().getValue(); } else { return ci.getNumberOfInstanceFields(); } } public int getNumberOfFields () { return getClassInfo().getNumberOfInstanceFields(); } public FieldInfo getFieldInfo (int fieldIndex) { return getClassInfo().getInstanceField(fieldIndex); } public FieldInfo getFieldInfo (String fname) { return getClassInfo().getInstanceField(fname); } protected FieldInfo getDeclaredFieldInfo (String clsBase, String fname) { return getClassInfo().getClassLoaderInfo().getResolvedClassInfo(null, clsBase).getDeclaredInstanceField(fname); } public ElementInfo getEnclosingElementInfo(){ for (FieldInfo fi : getClassInfo().getDeclaredInstanceFields()){ if (fi.getName().startsWith("this$")){ int objref = getReferenceField(fi).getValue(); return VM.getVM().getElementInfo(objref); } } return null; } public Conditional<String> asString() { Conditional<char[]> data = getStringChars(); return data.map(new Function<char[], String>() { @Override public String apply(char[] data) { if (data != null) { return new String(data); } else { return ""; } } }); } public Conditional<char[]> getStringChars(){ if (!ClassInfo.isStringClassInfo(ci)) { throw new JPFException("object is not of type java.lang.String"); } Conditional<Integer> vref = getDeclaredReferenceField("value", "java.lang.String"); return vref.mapr(new Function<Integer, Conditional<char[]>>() { @SuppressWarnings("unchecked") @Override public Conditional<char[]> apply(Integer vref) { if (vref != MJIEnv.NULL){ ElementInfo eVal = VM.getVM().getHeap().get(vref); return eVal.asCharArray(); } else { return (Conditional<char[]>) One.NULL; } } }); } /** * just a helper to avoid creating objects just for the sake of comparing */ public boolean equalsString (String s) { if (!ClassInfo.isStringClassInfo(ci)) { return false; } int vref = getDeclaredReferenceField("value", "java.lang.String").getValue(); ElementInfo e = VM.getVM().getHeap().get(vref); CharArrayFields cf = (CharArrayFields)e.getFields(); char[] v = cf.asCharArray().getValue(); return new String(v).equals(s); } public boolean isBoxObject(){ String cname = ci.getName(); if (cname.startsWith("java.lang.")){ cname = cname.substring(10); return ("Boolean".equals(cname) || "Character".equals(cname) || "Byte".equals(cname) || "Short".equals(cname) || "Integer".equals(cname) || "Float".equals(cname) || "Long".equals(cname) || "Double".equals(cname) ); } else { return false; } } public Object asBoxObject(){ String cname = ci.getName(); if (cname.startsWith("java.lang.")){ cname = cname.substring(10); if ("Boolean".equals(cname)){ return getBooleanField("value").getValue(); } else if ("Character".equals(cname)){ return getCharField("value").getValue(); } else if ("Byte".equals(cname)){ return getByteField("value").getValue(); } else if ("Short".equals(cname)){ return getShortField("value").getValue(); } else if ("Integer".equals(cname)){ return getIntField("value").getValue(); } else if ("Float".equals(cname)){ return getFloatField("value").getValue(); } else if ("Long".equals(cname)){ return getLongField("value").getValue(); } else if ("Double".equals(cname)){ return getDoubleField("value").getValue(); } } throw new JPFException("object is not a box object: " + this); } }