/* * 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.OpenCLScene; import org.trifort.rootbeer.generate.opencl.fields.OpenCLField; import org.trifort.rootbeer.util.Stack; import soot.*; import soot.jimple.ClassConstant; import soot.jimple.IntConstant; import soot.jimple.LongConstant; import soot.jimple.StringConstant; import soot.rbclassload.RootbeerClassLoader; public class VisitorReadGenStatic extends AbstractVisitorGen { private Local m_mem; private Set<String> m_attachedReaders; private StaticOffsets m_staticOffsets; public VisitorReadGenStatic(BytecodeLanguage bcl){ m_bcl.push(bcl); m_attachedReaders = new HashSet<String>(); m_objSerializing = new Stack<Local>(); m_staticOffsets = new StaticOffsets(); m_currMem = new Stack<Local>(); } public void makeMethod(){ BytecodeLanguage bcl = m_bcl.top(); bcl.startMethod("doReadStaticsFromHeap", VoidType.v()); m_thisRef = bcl.refThis(); m_mem = bcl.refInstanceField(m_thisRef, "mMem"); m_currMem.push(m_mem); m_gcObjVisitor.push(m_thisRef); PermissionGraph graph = new PermissionGraph(); List<PermissionGraphNode> roots = graph.getRoots(); for(PermissionGraphNode node : roots){ SootClass soot_class = node.getSootClass(); if(soot_class.isApplicationClass()){ attachAndCallReader(soot_class, node.getChildren()); } else { doReader(soot_class); } } bcl.returnVoid(); bcl.endMethod(); m_currMem.pop(); m_gcObjVisitor.pop(); } private String getReaderName(SootClass soot_class){ return "org_trifort_readStaticsFromHeap"+JavaNameToOpenCL.convert(soot_class.getName())+OpenCLScene.v().getIdent(); } private void attachReader(SootClass soot_class, List<SootClass> children){ String method_name = getReaderName(soot_class); if(m_attachedReaders.contains(method_name)) return; m_attachedReaders.add(method_name); List<OpenCLField> static_fields = m_staticOffsets.getStaticFields(soot_class); 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_thisRef.getType()); Local memory = bcl.refParameter(0); Local gc_visit = bcl.refParameter(1); m_gcObjVisitor.push(gc_visit); m_currMem.push(memory); BclMemory bcl_mem = new BclMemory(bcl, memory); for(OpenCLField field : static_fields){ int index = m_staticOffsets.getIndex(field); bcl_mem.setAddress(LongConstant.v(index)); if(field.getType().isRefType()){ readRefField(field); } else { readNonRefField(field); } } for(SootClass child : children){ attachAndCallReader(child, new ArrayList<SootClass>()); } bcl.returnVoid(); bcl.endMethod(); m_gcObjVisitor.pop(); m_currMem.pop(); m_bcl.pop(); } private void attachAndCallReader(SootClass soot_class, List<SootClass> children) { String class_name = soot_class.getName(); if(m_classesToIgnore.contains(class_name)) return; attachReader(soot_class, children); callReader(soot_class); } private void callReader(SootClass soot_class) { BytecodeLanguage bcl = m_bcl.top(); String method_name = getReaderName(soot_class); SootClass mem = Scene.v().getSootClass("org.trifort.rootbeer.runtime.Memory"); bcl.pushMethod(soot_class, method_name, VoidType.v(), mem.getType(), m_thisRef.getType()); bcl.invokeStaticMethodNoRet(m_currMem.top(), m_gcObjVisitor.top()); } private void doReader(SootClass soot_class) { BytecodeLanguage bcl = m_bcl.top(); Local memory = m_currMem.top(); Local gc_visit = m_gcObjVisitor.top(); 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(field.getType().isRefType()){ bcl_mem.useStaticPointer(); bcl_mem.setAddress(LongConstant.v(m_staticOffsets.getIndex(field))); Local ref = bcl_mem.readRef(); bcl_mem.useInstancePointer(); if(soot_class.isApplicationClass()){ bcl_mem.useStaticPointer(); bcl_mem.setAddress(LongConstant.v(m_staticOffsets.getIndex(field))); field_value = bcl_mem.readVar(field.getType().getSootType()); bcl_mem.useInstancePointer(); } 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); } } bcl.pushMethod(m_thisRef, "readFromHeap", obj.getType(), obj.getType(), BooleanType.v(), LongType.v()); field_value = bcl.invokeMethodRet(m_thisRef, field_value, IntConstant.v(0), ref); } else { bcl_mem.useStaticPointer(); bcl_mem.setAddress(LongConstant.v(m_staticOffsets.getIndex(field))); field_value = bcl_mem.readVar(field.getType().getSootType()); bcl_mem.useInstancePointer(); } if(field.isFinal()){ continue; } if(soot_class.isApplicationClass()){ bcl.setStaticField(field.getSootField(), field_value); } else { SootClass string = Scene.v().getSootClass("java.lang.String"); SootClass cls = Scene.v().getSootClass("java.lang.Class"); if(field.getType().isRefType()){ bcl.pushMethod(gc_visit, "writeStaticField", VoidType.v(), cls.getType(), string.getType(), obj.getType()); bcl.invokeMethodNoRet(gc_visit, ClassConstant.v(toConstant(soot_class.getName())), StringConstant.v(field.getName()), field_value); } else { bcl.pushMethod(gc_visit, "writeStatic"+field.getType().getCapitalName()+"Field", VoidType.v(), cls.getType(), string.getType(), field.getType().getSootType()); bcl.invokeMethodNoRet(gc_visit, ClassConstant.v(toConstant(soot_class.getName())), StringConstant.v(field.getName()), field_value); } } } } }