package gov.nasa.jpf.jvm; import java.util.HashMap; import java.util.Map; import java.util.Set; import cmu.conditional.ChoiceFactory; import cmu.conditional.Conditional; import cmu.conditional.One; import cmu.utils.RuntimeConstants; import de.fosd.typechef.featureexpr.FeatureExpr; /** * A heap to store values of the JVM created by nhandler. * * @author Jens Meinicke * */ public class JVMHeap { private static Map<Integer, Conditional<Object>> HEAP = new HashMap<>(); public static void put(int id, Object JVMObj, FeatureExpr ctx) { Conditional<Object> currentObject = HEAP.get(id); Conditional<Object> value; if (Conditional.isTautology(ctx)) { value = new One<>(JVMObj); } else { if (currentObject == null) { currentObject = new One<>(null); } value = ChoiceFactory.create(ctx, new One<>(JVMObj), currentObject).simplify(); } HEAP.put(id, value); } public static Object get(int id, FeatureExpr ctx) { Conditional<Object> conditional = HEAP.get(id); if (conditional != null) { Conditional<Object> simplify = conditional.simplify(ctx); if (simplify.isOne()) { return simplify.getValue(); } return simplify; } return null; } public static void remove(int id) { Object object = HEAP.remove(id); if (RuntimeConstants.debugGC) { if (object != null) { System.out.println("GC JVM Heap(" + HEAP.size() + ") " + printSize(object) + object.getClass().getName() + " @ " + id); } } } public static void clear() { HEAP.clear(); updatedJPFObj.clear(); } private static String printSize(final Object object) { int size = 0; if (object.getClass().isArray()) { final String componentType = object.getClass().getComponentType().getSimpleName(); switch (componentType) { case "char": size = Character.SIZE * ((char[]) object).length; break; case "byte": size = Byte.SIZE * ((byte[]) object).length; break; default: System.out.println("to string for " + componentType + " not supported"); break; } } else if (object instanceof String) { size = (Character.SIZE * ((String) object).toCharArray().length) >> 3; } if (size == 0) { return ""; } size = (size >> 3); if (size >= 1024) { size = size >> 10; if (size >= 1024) { size = size >> 10; return size + " MB "; } return size + " KB "; } return size + " Byte "; } public static boolean containsValue(Object jVMObj, FeatureExpr ctx) { for (Conditional<Object> v : HEAP.values()) { for (Object o : v.simplify(ctx).toList()) { if (jVMObj == o) { return true; } } } return false; }; public static Set<Integer> keySet() { return HEAP.keySet(); } public static boolean containsKey(int id, FeatureExpr ctx) { if (!HEAP.containsKey(id)) { return false; } Conditional<Object> value = HEAP.get(id).simplify(ctx); if (value.getValue() == null) { return false; } return true; } private static JVMHeap jvmheap = new JVMHeap(); public static JVMHeap instance() { return jvmheap; } /* * updated objects */ public static HashMap<Integer, Conditional<Object>> updatedJPFObj = new HashMap<>(); public static boolean isValueUpaded(Object jvmObj, FeatureExpr ctx) { for (Conditional<Object> v : updatedJPFObj.values()) { for (Object o : v.simplify(ctx).toList()) { if (jvmObj == o) { return false; } } } return false; } public static boolean isKeyUpdated(int id, FeatureExpr ctx) { if (!updatedJPFObj.containsKey(id)) { return false; } Conditional<Object> value = updatedJPFObj.get(id).simplify(ctx); if (value.getValue() == null) { return false; } return true; } public static Set<Integer> getUpdatesKeySet() { return updatedJPFObj.keySet(); } public static Conditional<Object> getUpdatesValue(int id, FeatureExpr ctx) { return updatedJPFObj.get(id).simplify(ctx); } public static void update(int id, Object JVMObj, FeatureExpr ctx) { Conditional<Object> currentObject = updatedJPFObj.get(id); Conditional<Object> value; if (Conditional.isTautology(ctx)) { value = new One<>(JVMObj); } else { if (currentObject == null) { currentObject = new One<>(null); } value = ChoiceFactory.create(ctx, new One<>(JVMObj), currentObject).simplify(); } updatedJPFObj.put(id, value); } }