/* * Copyright 2012 Phil Pratt-Szeliga and other contributors * http://chirrup.org/ * * See the file LICENSE for copying permission. */ package org.trifort.rootbeer.generate.bytecode; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.trifort.rootbeer.generate.opencl.OpenCLClass; import org.trifort.rootbeer.generate.opencl.OpenCLScene; import org.trifort.rootbeer.generate.opencl.fields.CompositeField; import org.trifort.rootbeer.generate.opencl.fields.OpenCLField; import soot.RefType; import soot.Scene; import soot.SootClass; import soot.Type; import soot.rbclassload.RootbeerClassLoader; public class StaticOffsets { private Map<Integer, SortableField> m_offsetToFieldMap; private Map<OpenCLField, Integer> m_fieldToOffsetMap; private Map<SootClass, Integer> m_classToOffsetMap; private Map<SootClass, List<OpenCLField>> m_staticFields; private int m_endIndex; private int m_lockStart; private int m_zerosSize; public StaticOffsets(){ m_offsetToFieldMap = new HashMap<Integer, SortableField>(); m_fieldToOffsetMap = new HashMap<OpenCLField, Integer>(); m_classToOffsetMap = new HashMap<SootClass, Integer>(); m_staticFields = new HashMap<SootClass, List<OpenCLField>>(); buildMaps(); } public OpenCLField getField(int index){ return m_offsetToFieldMap.get(index).m_field; } public int getIndex(OpenCLField field){ return m_fieldToOffsetMap.get(field); } public int getIndex(SootClass soot_class){ return m_classToOffsetMap.get(soot_class); } public int getEndIndex(){ return m_endIndex; } public List<OpenCLField> getStaticFields(SootClass soot_class){ List<OpenCLField> ret = m_staticFields.get(soot_class); if(ret == null){ ret = new ArrayList<OpenCLField>(); } return ret; } private void buildMaps() { List<CompositeField> composites = OpenCLScene.v().getCompositeFields(); Set<SortableField> sortable_fields = new HashSet<SortableField>(); for(CompositeField composite : composites){ List<SootClass> classes = composite.getClasses(); for(SootClass soot_class : classes){ sortable_fields.addAll(convert(composite.getRefFieldsByClass(soot_class), soot_class)); sortable_fields.addAll(convert(composite.getNonRefFieldsByClass(soot_class), soot_class)); List<OpenCLField> static_fields = new ArrayList<OpenCLField>(); static_fields.addAll(staticFilter(composite.getRefFieldsByClass(soot_class))); static_fields.addAll(staticFilter(composite.getNonRefFieldsByClass(soot_class))); m_staticFields.put(soot_class, static_fields); } } SortableField[] array = new SortableField[sortable_fields.size()]; array = sortable_fields.toArray(array); Arrays.sort(array); int index = 0; for(SortableField field : array){ m_offsetToFieldMap.put(index, field); m_fieldToOffsetMap.put(field.m_field, index); int size = field.m_field.getSize(); index += size; } int leftover = index % 4; if(leftover != 0){ index += leftover; } m_lockStart = index; Set<Type> types = RootbeerClassLoader.v().getDfsInfo().getDfsTypes(); for(Type type : types){ if(type instanceof RefType == false){ continue; } RefType ref_type = (RefType) type; String curr = ref_type.getClassName(); SootClass soot_class = Scene.v().getSootClass(curr); m_classToOffsetMap.put(soot_class, index); index += 4; } m_endIndex = index; int mod = m_endIndex % 16; m_zerosSize = 0; if(mod != 0){ m_endIndex += (16 - mod); m_zerosSize += (16 - mod); } //give room for junk space. some reason 32 bytes of space are needed for //the synchronized tests to pass. m_endIndex += 32; m_zerosSize += 32; } public int getZerosSize(){ return m_zerosSize; } private List<SortableField> convert(List<OpenCLField> fields, SootClass soot_class) { fields = staticFilter(fields); List<SortableField> ret = new ArrayList<SortableField>(); for(OpenCLField field : fields){ ret.add(new SortableField(field, soot_class)); } return ret; } private List<OpenCLField> staticFilter(List<OpenCLField> fields){ List<OpenCLField> ret = new ArrayList<OpenCLField>(); for(OpenCLField field : fields){ if(field.isInstance() == false){ ret.add(field); } } return ret; } public int getClassSize() { return m_classToOffsetMap.size(); } public int getLockStart() { return m_lockStart; } private class SortableField implements Comparable<SortableField> { public OpenCLField m_field; public SootClass m_sootClass; public SortableField(OpenCLField field, SootClass soot_class){ m_field = field; m_sootClass = soot_class; } public int compareTo(SortableField o) { int this_size = m_field.getSize(); int o_size = o.m_field.getSize(); return Integer.valueOf(o_size).compareTo(Integer.valueOf(this_size)); } @Override public boolean equals(Object other){ if(other instanceof SortableField == false){ return false; } SortableField rhs = (SortableField) other; if(m_field.getName().equals(rhs.m_field.getName()) == false){ return false; } if(m_field.getSootField().getDeclaringClass().getName().equals(rhs.m_field.getSootField().getDeclaringClass().getName()) == false){ return false; } return true; } @Override public int hashCode() { int hash = 3; hash = 23 * hash + (this.m_field.toString() != null ? this.m_field.toString().hashCode() : 0); return hash; } } }