Package org.trifort.rootbeer.generate.bytecode

Source Code of org.trifort.rootbeer.generate.bytecode.VisitorReadGen

/*
* 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.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.trifort.rootbeer.generate.opencl.OpenCLScene;
import org.trifort.rootbeer.generate.opencl.OpenCLType;
import org.trifort.rootbeer.generate.opencl.fields.OpenCLField;
import org.trifort.rootbeer.util.Stack;

import soot.*;
import soot.jimple.IntConstant;
import soot.jimple.LongConstant;
import soot.jimple.NullConstant;
import soot.rbclassload.ClassHierarchy;
import soot.rbclassload.RootbeerClassLoader;

public class VisitorReadGen extends AbstractVisitorGen {

  private Stack<Local> m_currObj;
 
  private Local m_param0;
  private Local m_param1;
  private Local m_refParam;
  private Local m_mem;
  private Local m_textureMem;
 
  private Map<Type, Local> m_readFromHeapMethodsMade;
  private Map<Type, Local> m_ctorReadFromHeapMethodsMade;
  private List<Type> m_orderedHistory;
  private Set<String> m_visitedReader;
 
  public VisitorReadGen(List<Type> ordered_history, String class_name,
    BytecodeLanguage bcl){
   
    m_readFromHeapMethodsMade = new HashMap<Type, Local>();
    m_ctorReadFromHeapMethodsMade = new HashMap<Type, Local>();
    m_orderedHistory = ordered_history;
    m_visitedReader = new HashSet<String>();
    m_bcl = new Stack<BytecodeLanguage>();
    m_bcl.push(bcl);
    m_gcObjVisitor = new Stack<Local>();
    m_objSerializing = new Stack<Local>();
    m_currMem = new Stack<Local>();
    m_currObj = new Stack<Local>();
  }
 
  public void makeReadFromHeapMethod() {
    BytecodeLanguage bcl = m_bcl.top();
    SootClass obj_cls = Scene.v().getSootClass("java.lang.Object");
    bcl.startMethod("doReadFromHeap", obj_cls.getType(), obj_cls.getType(), BooleanType.v(), LongType.v());
    m_thisRef = bcl.refThis();
    m_gcObjVisitor.push(m_thisRef);
    m_param0 = bcl.refParameter(0);
    m_objSerializing.push(m_param0);
    m_param1 = bcl.refParameter(1);
    m_refParam = bcl.refParameter(2);
    m_mem = bcl.refInstanceField(m_thisRef, "mMem");
    m_textureMem = bcl.refInstanceField(m_thisRef, "mTextureMem");

    String dont_return_null_label = getNextLabel();
    bcl.ifStmt(m_refParam, "!=", LongConstant.v(-1), dont_return_null_label);
    bcl.println("returning null");
    bcl.returnValue(NullConstant.v());
    bcl.label(dont_return_null_label);   
       
    Local mem = bcl.local(m_mem.getType());
   
    bcl.assign(mem, m_mem);     
    m_currMem.push(mem);
   
    BclMemory bcl_mem = new BclMemory(m_bcl.top(), mem);
    bcl_mem.setAddress(m_refParam);

    bcl_mem.incrementAddress(3);
    Local ctor_used = bcl_mem.readByte();
    Local class_number = bcl_mem.readInt();
   
    ClassHierarchy class_hierarchy = RootbeerClassLoader.v().getClassHierarchy();
    long string_number = class_hierarchy.getNumberForType("java.lang.String");
   
    //create readers for String and char[]
    Local ret;

    String after_ctors_label = getNextLabel();
    String ctors_label = getNextLabel();
    String string_label = getNextLabel();
    String increment_addr_label = getNextLabel();
    bcl.ifStmt(class_number, "==", IntConstant.v((int) string_number), string_label);
    bcl.ifStmt(ctor_used, "==", IntConstant.v(1), ctors_label);
    bcl.ifStmt(m_param0, "==", NullConstant.v(), ctors_label);
   
    bcl.gotoLabel(increment_addr_label);
   
    bcl.label(string_label);
   
    RefType string_type = RefType.v("java.lang.String");
    ret = makeReadFromHeapBodyForString(string_type);
    m_readFromHeapMethodsMade.put(string_type, ret);
    bcl.returnValue(ret);
   
    bcl.label(ctors_label);
   
    for(Type type : m_orderedHistory){
      makeCtorReadFromHeapMethodForType(type, false, class_number, ctor_used, after_ctors_label);
    }

    RefType obj = RefType.v("java.lang.Object");
    makeCtorReadFromHeapMethodForType(obj, true, class_number, ctor_used, after_ctors_label);

    bcl.label(increment_addr_label);
    bcl_mem.incrementAddress(8);
   
    bcl.label(after_ctors_label);
    bcl_mem.incrementAddress(16);

    for(Type type : m_orderedHistory){
      makeReadFromHeapMethodForType(type, false, ctor_used);
    }
   
    makeReadFromHeapMethodForType(obj, true, ctor_used);   
   
    bcl.returnValue(NullConstant.v());
    bcl.endMethod();
  }
  
  private void makeReadFromHeapMethodForType(Type type, boolean doing_object,
      Local ctor_used)
  {
    if(type instanceof ArrayType == false &&
       type instanceof RefType == false){
      return;
    }
   
    if(m_readFromHeapMethodsMade.containsKey(type))
      return;
   
    if(type instanceof RefType){
      RefType ref_type = (RefType) type;
      if(ref_type.getClassName().equals("java.lang.Object")){
        if(!doing_object){
          return;
        }
      }
      SootClass soot_class = ref_type.getSootClass();
      if(soot_class.isInterface()){
        return;
      }
      if(differentPackageAndPrivate(ref_type)){
        return
      }
    }
   
    String label = getNextLabel();
    BytecodeLanguage bcl = m_bcl.top();
       
    bcl.ifInstanceOfStmt(m_param0, type, label);
   
    //bcl.println("reading: "+type.toString());
    //BclMemory bcl_mem = new BclMemory(bcl, m_mem);
    //Local ptr = bcl_mem.getPointer();
    //bcl.println(ptr);
   
    Local ret;
    if(type instanceof ArrayType){
      ret = makeReadFromHeapBodyForArrayType((ArrayType) type);
    }
    else {
      ret = makeReadFromHeapBodyForSootClass((RefType) type);
    }
    m_readFromHeapMethodsMade.put(type, ret);
    bcl.returnValue(ret);
    bcl.label(label);
  }

  private void makeCtorReadFromHeapMethodForType(Type type, boolean doing_object,
      Local class_number, Local ctor_used, String after_ctors_label)
  {
    if(type instanceof ArrayType == false &&
       type instanceof RefType == false){
      return;
    }
   
    if(m_ctorReadFromHeapMethodsMade.containsKey(type))
      return;
   
    if(type instanceof RefType){
      RefType ref_type = (RefType) type;
      if(ref_type.getClassName().equals("java.lang.Object")){
        if(!doing_object){
          return;
        }
      }
      SootClass soot_class = ref_type.getSootClass();
      if(soot_class.isInterface()){
        return;
      }
      if(differentPackageAndPrivate(ref_type)){
        return
      }
    }
   
    String label = getNextLabel();
    BytecodeLanguage bcl = m_bcl.top();
       
    ClassHierarchy class_hierarchy = RootbeerClassLoader.v().getClassHierarchy();
    long number = class_hierarchy.getNumberForType(type.toString());
   
    bcl.ifStmt(class_number, "!=", IntConstant.v((int) number), label);
   
    Local ret;
    if(type instanceof ArrayType){
      ret = makeCtorReadFromHeapBodyForArrayType((ArrayType) type, ctor_used);
      m_ctorReadFromHeapMethodsMade.put(type, ret);
      bcl.assign(m_param0, ret);
      bcl.gotoLabel(after_ctors_label);
    }
    else {
      ret = makeCtorReadFromHeapBodyForSootClass((RefType) type, ctor_used, class_number);
      m_ctorReadFromHeapMethodsMade.put(type, ret);
      bcl.assign(m_param0, ret);
      bcl.gotoLabel(after_ctors_label);
    }
    bcl.label(label);
  }

  private Local makeCtorReadFromHeapBodyForArrayType(ArrayType type,
      Local ctor_used) {

    BytecodeLanguage bcl = m_bcl.top();
    BclMemory bcl_mem = new BclMemory(bcl, m_currMem.top());  
    bcl_mem.incrementAddress(4);
   
    Local array_length = bcl_mem.readInt();
    //bcl.println("reading size: ");
    //bcl.println(size);
    Local ret = bcl.local(type);
   
    bcl.assign(ret, bcl.newArray(type, array_length));

    return ret;
  }

  private Local makeReadFromHeapBodyForArrayType(ArrayType type) {
    BytecodeLanguage bcl = m_bcl.top();

    BclMemory bcl_mem = new BclMemory(bcl, m_currMem.top());  
   
    Local ret = bcl.local(type);
    ret = bcl.cast(type, m_param0);
    Local size = bcl.lengthof(ret);
       
    //optimization for single-dimensional arrays of primitive types.
    //doesn't work for chars yet because they are still stored as ints on the gpu
    if(type.baseType instanceof PrimType && type.numDimensions == 1 &&
       type.baseType.equals(CharType.v()) == false){
     
      bcl.pushMethod(m_currMem.top(), "readArray", VoidType.v(), type);
      bcl.invokeMethodNoRet(m_currMem.top(), ret);
      OpenCLType ocl_type = new OpenCLType(type.baseType);
      Local element_size = bcl.local(IntType.v());
      bcl.assign(element_size, IntConstant.v(ocl_type.getSize()));
      bcl.mult(element_size, size);
      bcl_mem.incrementAddress(element_size);
     
      return ret;
    }

    Local i = bcl.local(IntType.v());
    bcl.assign(i, IntConstant.v(0));

    String end_for_label = getNextLabel();
    String before_if_label = getNextLabel();
    bcl.label(before_if_label);
    bcl.ifStmt(i, "==", size, end_for_label);

    Local new_curr;

    if(type.numDimensions != 1){
      new_curr = readFromHeapArray(ret, i, size);
    } else if(type.baseType instanceof RefType){
      Local temp = readFromHeapArray(ret, i, size);
      new_curr = bcl.cast(type.baseType, temp);
    } else {
      new_curr = bcl_mem.readVar(type.baseType);
    }
   
    bcl.assignElementToArray(ret, new_curr, i);

    bcl.plus(i, 1);
    bcl.gotoLabel(before_if_label);
    bcl.label(end_for_label);
   
    bcl_mem.finishReading();

    return ret;
  }

  private Local makeReadFromHeapBodyForString(RefType type){
    BytecodeLanguage bcl = m_bcl.top();
    BclMemory bcl_mem = new BclMemory(bcl, m_currMem.top());
 
    bcl_mem.incrementAddress(4+4+16);
    Local ref = bcl_mem.readRef();
   
    bcl_mem.setAddress(ref);
    bcl_mem.incrementAddress(12);
   
    Local array_length = bcl_mem.readInt();
   
    bcl_mem.incrementAddress(16);
   
    ArrayType array_type = ArrayType.v(CharType.v(), 1);
   
    Local ret = bcl.local(array_type);
    bcl.assign(ret, bcl.newArray(array_type, array_length));
   
    Local i = bcl.local(IntType.v());
    bcl.assign(i, IntConstant.v(0));

    String end_for_label = getNextLabel();
    String before_if_label = getNextLabel();
    bcl.label(before_if_label);
    bcl.ifStmt(i, "==", array_length, end_for_label);

    Local new_curr = bcl_mem.readChar();
    bcl.assignElementToArray(ret, new_curr, i);

    bcl.plus(i, 1);
    bcl.gotoLabel(before_if_label);
    bcl.label(end_for_label);

    SootClass string_class = Scene.v().getSootClass("java.lang.String");
    Local new_string = bcl.newInstance(string_class.getName(), ret);
    bcl_mem.finishReading();
   
    m_ctorReadFromHeapMethodsMade.put(type, new_string);
    m_readFromHeapMethodsMade.put(type, new_string);
   
    return new_string;
  }

  private Local makeCtorReadFromHeapBodyForSootClass(RefType type,
      Local ctor_used, Local class_number) {

    BytecodeLanguage bcl = m_bcl.top();
    BclMemory bcl_mem = new BclMemory(bcl, m_currMem.top());  
    bcl_mem.incrementAddress(8);
   
    SootClass soot_class = type.getSootClass();
   
    String name = soot_class.getName();
    if(soot_class.isApplicationClass() == false){   
      if(soot_class.declaresMethod("void <init>()")){
        Local object_to_write_to = bcl.local(type);
        Local new_object = bcl.newInstance(name);
        bcl.assign(object_to_write_to, new_object);
        return object_to_write_to;
      } else {
        JavaNumberTypes number_types = new JavaNumberTypes();
        String type_string = type.toString();
        if(number_types.get().contains(type_string)){

          bcl_mem.incrementAddress(Constants.MallocAlignBytes)
         
          Local value;
         
          if(type_string.equals("java.lang.Byte")){
            value = bcl_mem.readByte();
          } else if(type_string.equals("java.lang.Boolean")){
            value = bcl_mem.readBoolean();
          } else if(type_string.equals("java.lang.Character")){
            value = bcl_mem.readChar();
          } else if(type_string.equals("java.lang.Short")){
            value = bcl_mem.readShort();
          } else if(type_string.equals("java.lang.Integer")){
            value = bcl_mem.readInt();
          } else if(type_string.equals("java.lang.Long")){
            value = bcl_mem.readLong();
          } else if(type_string.equals("java.lang.Float")){
            value = bcl_mem.readFloat();
          } else if(type_string.equals("java.lang.Double")){
            value = bcl_mem.readDouble();
          } else {
            throw new UnsupportedOperationException("cannot create type: "+type_string);
          }

          Local object_to_write_to = bcl.local(type);
          Local new_object = bcl.newInstance(name, value);
          bcl.assign(object_to_write_to, new_object);

          bcl_mem.finishReading();
         
          bcl.returnValue(object_to_write_to);
          return object_to_write_to;
        } else {
          Local object_to_write_to = bcl.local(type);
          bcl.assign(object_to_write_to, NullConstant.v());
          return object_to_write_to;
        }
      }
    } else {
      Local object_to_write_to = bcl.local(type);
      Local sentinal = bcl.newInstance("org.trifort.rootbeer.runtime.Sentinal");
      Local new_object = bcl.newInstance(name, sentinal);
      bcl.assign(object_to_write_to, new_object);
      return object_to_write_to;
    }
  }
 
  private Local makeReadFromHeapBodyForSootClass(RefType type){
   
    BytecodeLanguage bcl = m_bcl.top();
    SootClass soot_class = type.getSootClass();
   
    Local object_to_write_to = bcl.cast(type, m_param0);
    BclMemory bcl_mem = new BclMemory(bcl, m_currMem.top());
   
    SootClass obj_class = Scene.v().getSootClass("java.lang.Object");
    bcl.pushMethod(m_thisRef, "checkCache",obj_class.getType(), LongType.v(), obj_class.getType());
    object_to_write_to = bcl.invokeMethodRet(m_thisRef, m_refParam, object_to_write_to);
    object_to_write_to = bcl.cast(type, object_to_write_to);
   
    m_currObj.push(object_to_write_to);
    m_objSerializing.push(object_to_write_to);
    readFields(soot_class, true);
    readFields(soot_class, false);
    m_currObj.pop();
    m_objSerializing.pop();
  
    bcl_mem.finishReading();

    return object_to_write_to;
  }
 
  private void readFields(SootClass curr_class, boolean ref_types){
    if(curr_class.isApplicationClass()){
      attachReader(curr_class.getName(), ref_types);
      callBaseClassReader(curr_class.getName(), ref_types);
    } else {
      insertReader(curr_class.getName(), ref_types);
    }   
  }
   
  private Local readFromHeapArray(Local object_to_read_from, Local i, Local size) {
    BytecodeLanguage bcl = m_bcl.top();
    BclMemory bcl_mem = new BclMemory(bcl, m_currMem.top());  
   
    Local curr;
   
    String after_read = getNextLabel();
    String before_read_int = getNextLabel();
   
    bcl.ifStmt(i, ">=", size, after_read);
    curr = bcl.indexArray(object_to_read_from, i);
    bcl.gotoLabel(before_read_int);
    bcl.label(after_read);
    if(object_to_read_from.getType() instanceof RefLikeType){
      bcl.assign(curr, NullConstant.v());
    } else {
      bcl.assign(curr, IntConstant.v(0));
    }
    bcl.label(before_read_int);
    Local curr_phi = bcl.local(object_to_read_from.getType());
    bcl.assign(curr_phi, curr);
    Local object_addr = bcl_mem.readRef();
    bcl_mem.pushAddress();
    SootClass obj_cls = Scene.v().getSootClass("java.lang.Object");
    bcl.pushMethod(m_thisRef, "readFromHeap", obj_cls.getType(), obj_cls.getType(), BooleanType.v(), LongType.v());
    Local ret = bcl.invokeMethodRet(m_thisRef, curr_phi, m_param1, object_addr);
    bcl_mem.popAddress();

    return ret;
  }
 
  public void attachReader(String class_name, boolean ref_fields){
    String specialization;
   
    if(ref_fields){
      specialization = "RefFields";
    } else {
      specialization = "NonRefFields";
    }
    specialization += JavaNameToOpenCL.convert(class_name);
    specialization += OpenCLScene.v().getIdent();
    String visited_name = class_name + specialization;
   
    if(m_visitedReader.contains(visited_name))
      return;
    m_visitedReader.add(visited_name)
       
    SootClass curr_class = Scene.v().getSootClass(class_name);
    SootClass parent = curr_class.getSuperclass();
    parent = Scene.v().getSootClass(parent.getName());
    if(parent.isApplicationClass()){
      attachReader(parent.getName(), ref_fields);
    }
   
    BytecodeLanguage bcl = new BytecodeLanguage();
    Local gc_obj_visit = m_gcObjVisitor.top();
    m_bcl.push(bcl);
    bcl.openClass(class_name);
    SootClass mem = Scene.v().getSootClass("org.trifort.rootbeer.runtime.Memory");
    bcl.startMethod("org_trifort_readFromHeap"+specialization, VoidType.v(), mem.getType(), gc_obj_visit.getType());
    m_objSerializing.push(bcl.refThis());
    m_currMem.push(bcl.refParameter(0));
    m_gcObjVisitor.push(bcl.refParameter(1));
   
    doReader(class_name, ref_fields);
   
    if(parent.getName().equals("java.lang.Object") == false){
      if(parent.isApplicationClass()){
        callBaseClassReader(parent.getName(), ref_fields);
      } else {
        insertReader(parent.getName(), ref_fields);
      }
    }
   
    bcl.returnVoid();
    bcl.endMethod();
   
    m_objSerializing.pop();
    m_currMem.pop();
    m_gcObjVisitor.pop();
    m_bcl.pop();
  }
 
  public void insertReader(String class_name, boolean ref_fields){
    doReader(class_name, ref_fields);
   
    SootClass curr_class = Scene.v().getSootClass(class_name);
    if(curr_class.hasSuperclass() == false)
      return;
   
    SootClass parent = curr_class.getSuperclass();
    parent = Scene.v().getSootClass(parent.getName());
    if(parent.getName().equals("java.lang.Object") == false){
      if(parent.isApplicationClass()){
        attachReader(parent.getName(), ref_fields);
        callBaseClassReader(parent.getName(), ref_fields);
      } else {
        insertReader(parent.getName(), ref_fields);
      }
    }
  }
     
  public void doReader(String class_name, boolean do_ref_fields){
    BytecodeLanguage bcl = m_bcl.top();
    BclMemory bcl_mem = new BclMemory(bcl, m_currMem.top());
    SootClass soot_class = Scene.v().getSootClass(class_name);
   
    //read all the ref fields
    int inc_size = 0;
    if(do_ref_fields){
      List<OpenCLField> ref_fields = getRefFields(soot_class);
      for(OpenCLField ref_field : ref_fields){
        //increment the address to get to this location
        bcl_mem.incrementAddress(inc_size);
        inc_size = 0;

        //read the field
        readRefField(ref_field);
      }

      if(inc_size > 0){
        bcl_mem.incrementAddress(inc_size);
      }
    } else {
      List<OpenCLField> non_ref_fields = getNonRefFields(soot_class);
      for(OpenCLField non_ref_field : non_ref_fields){
        //increment the address to get to this location
        if(inc_size > 0){
          bcl_mem.incrementAddress(inc_size);
          inc_size = 0;
        }
        //read the field
        readNonRefField(non_ref_field)
      }
      if(inc_size > 0){
        bcl_mem.incrementAddress(inc_size);
      }
    }
    bcl_mem.align();
 
 
  public void callBaseClassReader(String class_name, boolean ref_types) {
    String specialization;
    if(ref_types){
      specialization = "RefFields";
    } else {
      specialization = "NonRefFields";
    }
    specialization += JavaNameToOpenCL.convert(class_name);
    specialization += OpenCLScene.v().getIdent();
    SootClass mem = Scene.v().getSootClass("org.trifort.rootbeer.runtime.Memory");
    BytecodeLanguage bcl = m_bcl.top();
    Local gc_obj_visit = m_gcObjVisitor.top();
    bcl.pushMethod(class_name, "org_trifort_readFromHeap"+specialization, VoidType.v(), mem.getType(), gc_obj_visit.getType());
    bcl.invokeMethodNoRet(m_objSerializing.top(), m_currMem.top(), gc_obj_visit);
  }

}
TOP

Related Classes of org.trifort.rootbeer.generate.bytecode.VisitorReadGen

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.