protected void readNonRefField(OpenCLField field) {
    SootField soot_field = field.getSootField();
    String function_name = "read" + getTypeString(soot_field);

    BytecodeLanguage bcl = m_bcl.top();
    bcl.pushMethod(m_currMem.top(), function_name, soot_field.getType());
    Local data = bcl.invokeMethodRet(m_currMem.top());

    SootClass soot_class = Scene.v().getSootClass(soot_field.getDeclaringClass().getName());
    if (soot_class.isApplicationClass()) {
      if (field.isInstance()) {
        bcl.setInstanceField(soot_field, m_objSerializing.top(), data);
      } else {
        bcl.setStaticField(soot_field, data);
      }
    } else {
      SootClass obj = Scene.v().getSootClass("java.lang.Object");
      SootClass string = Scene.v().getSootClass("java.lang.String");
      String static_str;
      SootClass first_param_type;
      Value first_param;
      if (field.isInstance()) {
        static_str = "";
        first_param_type = obj;
        first_param = m_objSerializing.top();
      } else {
        static_str = "Static";
        first_param_type = Scene.v().getSootClass("java.lang.Class");
        first_param = ClassConstant.v(soot_class.getName());
      }
      String private_field_fun_name = "write" + static_str + getTypeString(soot_field);
      Local private_fields = bcl.newInstance("org.trifort.rootbeer.runtime.PrivateFields");
      bcl.pushMethod(
          private_fields,
          private_field_fun_name,
          VoidType.v(),
          first_param_type.getType(),
          string.getType(),
          string.getType(),
          soot_field.getType());
      bcl.invokeMethodNoRet(
          private_fields,
          first_param,
          StringConstant.v(soot_field.getName()),
          StringConstant.v(soot_field.getDeclaringClass().getName()),
          data);
    }
  }
  protected void readRefField(OpenCLField ref_field) {
    SootField soot_field = ref_field.getSootField();
    SootClass soot_class = Scene.v().getSootClass(soot_field.getDeclaringClass().getName());

    BytecodeLanguage bcl = m_bcl.top();
    Local gc_obj_visit = m_gcObjVisitor.top();
    BclMemory bcl_mem = new BclMemory(bcl, m_currMem.top());

    Local ref = bcl_mem.readRef();
    bcl_mem.useInstancePointer();
    bcl_mem.pushAddress();
    bcl_mem.setAddress(ref);

    // bcl.println("reading field: "+ref_field.getName());

    SootClass obj_class = Scene.v().getSootClass("java.lang.Object");
    SootClass string = Scene.v().getSootClass("java.lang.String");
    SootClass class_class = Scene.v().getSootClass("java.lang.Class");
    Local original_field_value;
    if (soot_class.isApplicationClass() == false) {
      if (ref_field.isInstance()) {
        bcl.pushMethod(
            gc_obj_visit, "readField", obj_class.getType(), obj_class.getType(), string.getType());
        original_field_value =
            bcl.invokeMethodRet(
                gc_obj_visit, m_objSerializing.top(), StringConstant.v(soot_field.getName()));
      } else {
        bcl.pushMethod(
            gc_obj_visit,
            "readStaticField",
            obj_class.getType(),
            class_class.getType(),
            string.getType());
        Local cls = bcl.classConstant(soot_field.getDeclaringClass().getType());
        original_field_value =
            bcl.invokeMethodRet(gc_obj_visit, cls, StringConstant.v(soot_field.getName()));
      }
    } else {
      if (ref_field.isInstance()) {
        original_field_value = bcl.refInstanceField(m_objSerializing.top(), ref_field.getName());
      } else {
        original_field_value = bcl.refStaticField(soot_class.getType(), ref_field.getName());
      }
    }
    bcl.pushMethod(
        gc_obj_visit,
        "readFromHeap",
        obj_class.getType(),
        obj_class.getType(),
        BooleanType.v(),
        LongType.v());
    int should_read = 1;
    Local ret_obj =
        bcl.invokeMethodRet(gc_obj_visit, original_field_value, IntConstant.v(should_read), ref);

    Type type = soot_field.getType();
    Local ret = bcl.cast(type, ret_obj);

    if (soot_class.isApplicationClass() == false) {
      if (ref_field.isInstance()) {
        bcl.pushMethod(
            gc_obj_visit,
            "writeField",
            VoidType.v(),
            obj_class.getType(),
            string.getType(),
            obj_class.getType());
        bcl.invokeMethodNoRet(
            gc_obj_visit, m_objSerializing.top(), StringConstant.v(soot_field.getName()), ret);
      } else {
        bcl.pushMethod(
            gc_obj_visit,
            "writeStaticField",
            VoidType.v(),
            class_class.getType(),
            string.getType(),
            obj_class.getType());
        Local cls = bcl.classConstant(soot_field.getDeclaringClass().getType());
        bcl.invokeMethodNoRet(gc_obj_visit, cls, StringConstant.v(soot_field.getName()), ret);
      }
    } else {
      if (ref_field.isInstance()) {
        bcl.setInstanceField(soot_field, m_objSerializing.top(), ret);
      } else {
        bcl.setStaticField(soot_field, ret);
      }
    }

    bcl_mem.popAddress();
  }