/* * 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.HashSet; import java.util.List; import java.util.Set; import org.trifort.rootbeer.generate.bytecode.permissiongraph.PermissionGraph; import org.trifort.rootbeer.generate.bytecode.permissiongraph.PermissionGraphNode; import org.trifort.rootbeer.generate.opencl.ClassConstantNumbers; import org.trifort.rootbeer.generate.opencl.OpenCLScene; import org.trifort.rootbeer.generate.opencl.fields.OpenCLField; import soot.*; import soot.jimple.ClassConstant; import soot.jimple.IntConstant; import soot.jimple.LongConstant; import soot.jimple.StringConstant; import soot.rbclassload.RootbeerClassLoader; public class VisitorWriteGenStatic extends AbstractVisitorGen { private Local m_Mem; private StaticOffsets m_StaticOffsets; private Set<String> m_AttachedWriters; public VisitorWriteGenStatic(BytecodeLanguage bcl){ m_bcl.push(bcl); m_StaticOffsets = new StaticOffsets(); m_AttachedWriters = new HashSet<String>(); } public void makeMethod(){ BytecodeLanguage bcl = m_bcl.top(); bcl.startMethod("doWriteStaticsToHeap", VoidType.v()); m_thisRef = bcl.refThis(); m_currThisRef.push(m_thisRef); m_gcObjVisitor.push(m_thisRef); m_Mem = bcl.refInstanceField(m_thisRef, "mMem"); m_currMem.push(m_Mem); BclMemory bcl_mem = new BclMemory(bcl, m_Mem); bcl_mem.useInstancePointer(); bcl_mem.mallocWithSize(IntConstant.v(m_StaticOffsets.getEndIndex())); PermissionGraph graph = new PermissionGraph(); List<PermissionGraphNode> roots = graph.getRoots(); for(PermissionGraphNode node : roots){ SootClass soot_class = node.getSootClass(); if(soot_class.isApplicationClass()){ attachAndCallWriter(soot_class, node.getChildren()); } else { //doWriter(soot_class, node.getChildren()); doWriter(soot_class, new ArrayList<SootClass>()); } } //write .class's for array types Set<ArrayType> array_types = RootbeerClassLoader.v().getDfsInfo().getArrayTypes(); for(ArrayType type : array_types){ writeType(type); } bcl_mem.useStaticPointer(); bcl_mem.setAddress(LongConstant.v(m_StaticOffsets.getLockStart())); //write the lock objects for all the classes int count = m_StaticOffsets.getClassSize(); for(int i = 0; i < count; ++i){ bcl_mem.writeInt(-1); } int zeros = m_StaticOffsets.getZerosSize(); for(int i = 0; i < zeros; ++i){ bcl_mem.writeByte((byte) 0); } bcl_mem.useInstancePointer(); bcl.returnVoid(); bcl.endMethod(); m_gcObjVisitor.pop(); } private void attachAndCallWriter(SootClass soot_class, List<SootClass> children){ String class_name = soot_class.getName(); if(m_classesToIgnore.contains(class_name)) return; attachWriter(soot_class, children); callWriter(soot_class); } private void callWriter(SootClass soot_class){ BytecodeLanguage bcl = m_bcl.top(); String method_name = getWriterName(soot_class); SootClass mem = Scene.v().getSootClass("org.trifort.rootbeer.runtime.Memory"); bcl.pushMethod(soot_class, method_name, VoidType.v(), mem.getType(), m_gcObjVisitor.top().getType()); bcl.invokeStaticMethodNoRet(m_currMem.top(), m_gcObjVisitor.top()); } private String getWriterName(SootClass soot_class){ return "org_trifort_writeStaticsToHeap"+JavaNameToOpenCL.convert(soot_class.getName())+OpenCLScene.v().getIdent(); } private void attachWriter(SootClass soot_class, List<SootClass> children){ String method_name = getWriterName(soot_class); if(m_AttachedWriters.contains(method_name)) return; m_AttachedWriters.add(method_name); BytecodeLanguage bcl = new BytecodeLanguage(); m_bcl.push(bcl); bcl.openClass(soot_class); SootClass mem = Scene.v().getSootClass("org.trifort.rootbeer.runtime.Memory"); bcl.startStaticMethod(method_name, VoidType.v(), mem.getType(), m_gcObjVisitor.top().getType()); Local memory = bcl.refParameter(0); Local gc_visit = bcl.refParameter(1); m_currMem.push(memory); m_gcObjVisitor.push(gc_visit); doWriter(soot_class, children); bcl.returnVoid(); bcl.endMethod(); m_gcObjVisitor.pop(); m_currMem.pop(); m_bcl.pop(); } private void doWriter(SootClass soot_class, List<SootClass> children){ BytecodeLanguage bcl = m_bcl.top(); Local memory = m_currMem.top(); Local gc_visit = m_gcObjVisitor.top(); writeType(soot_class.getType()); List<OpenCLField> static_fields = m_StaticOffsets.getStaticFields(soot_class); BclMemory bcl_mem = new BclMemory(bcl, memory); SootClass obj = Scene.v().getSootClass("java.lang.Object"); for(OpenCLField field : static_fields){ Local field_value; if(soot_class.isApplicationClass()){ field_value = bcl.refStaticField(soot_class.getType(), field.getName()); } else { SootClass string = Scene.v().getSootClass("java.lang.String"); SootClass cls = Scene.v().getSootClass("java.lang.Class"); bcl.pushMethod(gc_visit, "readStaticField", obj.getType(), cls.getType(), string.getType()); Local obj_field_value = bcl.invokeMethodRet(gc_visit, ClassConstant.v(toConstant(soot_class.getName())), StringConstant.v(field.getName())); if(field.getType().isRefType()){ field_value = obj_field_value; } else { Local capital_value = bcl.cast(field.getType().getCapitalType(), obj_field_value); bcl.pushMethod(capital_value, field.getType().getName()+"Value", field.getType().getSootType()); field_value = bcl.invokeMethodRet(capital_value); } } if(field.getType().isRefType()){ bcl.pushMethod(gc_visit, "writeToHeap", LongType.v(), obj.getType(), BooleanType.v()); Local ref = bcl.invokeMethodRet(gc_visit, field_value, IntConstant.v(1)); bcl_mem.useStaticPointer(); bcl_mem.setAddress(LongConstant.v(m_StaticOffsets.getIndex(field))); bcl_mem.writeRef(ref); bcl_mem.useInstancePointer(); } else { bcl_mem.useStaticPointer(); bcl_mem.setAddress(LongConstant.v(m_StaticOffsets.getIndex(field))); bcl_mem.writeVar(field_value); bcl_mem.useInstancePointer(); } } for(SootClass child : children){ if(soot_class.isApplicationClass()){ attachAndCallWriter(child, new ArrayList<SootClass>()); } else { doWriter(child, new ArrayList<SootClass>()); } } } private boolean reachesJavaLangClass(){ List<RefType> ref_types = RootbeerClassLoader.v().getDfsInfo().getOrderedRefTypes(); RefType java_lang_class = RefType.v("java.lang.Class"); return ref_types.contains(java_lang_class); } private void writeType(Type type) { if(reachesJavaLangClass() == false){ return; } int number = OpenCLScene.v().getClassConstantNumbers().get(type); Local gc_visit = m_gcObjVisitor.top(); Local class_obj = null; if(type instanceof ArrayType){ ArrayType array_type = (ArrayType) type; class_obj = m_bcl.top().classConstant(type); } else { RefType ref_type = (RefType) type; class_obj = m_bcl.top().classConstant(type); } //getName has to be called to load the name variable SootClass str_cls = Scene.v().getSootClass("java.lang.String"); m_bcl.top().pushMethod(class_obj, "getName", str_cls.getType()); m_bcl.top().invokeMethodRet(class_obj); SootClass obj_cls = Scene.v().getSootClass("java.lang.Object"); m_bcl.top().pushMethod(gc_visit, "writeToHeap", LongType.v(), obj_cls.getType(), BooleanType.v()); Local ref = m_bcl.top().invokeMethodRet(gc_visit, class_obj, IntConstant.v(1)); m_bcl.top().pushMethod(gc_visit, "addClassRef", VoidType.v(), LongType.v(), IntType.v()); m_bcl.top().invokeMethodNoRet(gc_visit, ref, IntConstant.v(number)); } }