Package com.artemis.weaver.packed

Source Code of com.artemis.weaver.packed.FieldToStructMethodTransformer

package com.artemis.weaver.packed;

import static com.artemis.weaver.packed.InstructionMutator.on;

import java.util.List;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.IntInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;

import com.artemis.meta.ClassMetadata;
import com.artemis.meta.ClassMetadataUtil;
import com.artemis.meta.FieldDescriptor;
import com.artemis.transformer.MethodTransformer;

public class FieldToStructMethodTransformer extends MethodTransformer implements Opcodes {

  private final ClassMetadata meta;
  private final String fieldDesc;
 
  private static final String BYTEBUFFER_DESC = "Ljava/nio/ByteBuffer;";
 
  private static final boolean LOG = false;

  public FieldToStructMethodTransformer(MethodTransformer mt, ClassMetadata meta, FieldDescriptor f) {
    super(mt);
    this.meta = meta;
   
    fieldDesc = f.desc;
  }
 
  @Override
  public boolean transform(MethodNode mn) {
    InsnList instructions = mn.instructions;
    String owner = meta.type.getInternalName();
   
    if (LOG) System.out.println("OWNER: " + owner + " " + mn.name);
   
    ByteBufferHelper bufferHelper = new ByteBufferHelper(meta);
   
    boolean shouldDoSetter = true;
    for (int i = 0; instructions.size() > i; i++) {
      AbstractInsnNode node = instructions.get(i);
      switch(node.getType()) {
        case AbstractInsnNode.FIELD_INSN:
          FieldInsnNode f = (FieldInsnNode)node;
          if (shouldDoSetter && isSettingFieldWithPrimitive(f)) {
            if (LOG) System.out.println(">> SETTING FIELD index=" + i);
            i = on(instructions, f)
              .insertAtOffset(2,
                new VarInsnNode(ALOAD, 0),
                new FieldInsnNode(GETFIELD, owner, "$data", BYTEBUFFER_DESC))
              .insertAtOffset(1,
                new FieldInsnNode(GETFIELD, owner, "$stride", "I"),
                fieldOffsetInstruction(f.name),
                new InsnNode(IADD))
              .insertAtOffset(0,
                bufferHelper.invokePutter(f.name),
                new InsnNode(POP))
              .delete(0)
              .transform();
          } else if (!shouldDoSetter && isSettingFieldWithPrimitive(f)) {
            if (LOG) System.out.println(">> SETTING FIELD index=" + i);
            i = on(instructions, f)
              .insertAtOffset(0,
                bufferHelper.invokePutter(f.name),
                new InsnNode(POP))
              .delete(0)
              .transform();
          } else if (isSettingFieldWithObject(f)) {
            if (LOG) System.out.println(">> SETTING FIELD FROM OBJECT index=" + i);
            i = on(instructions, f)
              .insertAtOffset(3,
                new VarInsnNode(ALOAD, 0),
                new FieldInsnNode(GETFIELD, owner, "$data", BYTEBUFFER_DESC))
              .insertAtOffset(2,
                new FieldInsnNode(GETFIELD, owner, "$stride", "I"),
                fieldOffsetInstruction(f.name),
                new InsnNode(IADD))
              .insertAtOffset(0,
                bufferHelper.invokePutter(f.name),
                new InsnNode(POP))
              .delete(0)
              .transform();
          } else if (isModifyingFieldWithObject(f)) {
            if (LOG) System.out.println(">> SETTING-MODIFYING FIELD FROM OBJECT index=" + i);
            i = on(instructions, f)
              .insertAtOffset(6,
                new VarInsnNode(ALOAD, 0),
                new FieldInsnNode(GETFIELD, owner, "$data", BYTEBUFFER_DESC))
              .insertAtOffset(5,
                new FieldInsnNode(GETFIELD, owner, "$stride", "I"),
                fieldOffsetInstruction(f.name),
                new InsnNode(IADD),
                new InsnNode(DUP2),
                bufferHelper.invokeGetter(f.name))
              .insertAtOffset(0,
                bufferHelper.invokePutter(f.name),
                new InsnNode(POP))
              .delete(5)
              .delete(4)
              .delete(0)
              .transform();
          } else if (isLoadingFromField(f)) {
            if (LOG) System.out.println("<< LOAD FIELD index=" + i);
            i = on(instructions, f)
              .insertAtOffset(2,
                new VarInsnNode(ALOAD, 0),
                new FieldInsnNode(GETFIELD, owner, "$data", BYTEBUFFER_DESC))
              .insertAtOffset(0,
                new FieldInsnNode(GETFIELD, owner, "$stride", "I"),
                fieldOffsetInstruction(f.name),
                new InsnNode(IADD),
                new InsnNode(DUP2),
                bufferHelper.invokeGetter(f.name))
              .delete(1)
              .delete(0)
              .transform();
            shouldDoSetter = false;
          } else if (isGettingField(f)) {
            if (LOG) System.out.println("<< GETTING FIELD index=" + i);
            i = on(instructions, f)
              .insertAtOffset(1,
                new VarInsnNode(ALOAD, 0),
                new FieldInsnNode(GETFIELD, owner, "$data", BYTEBUFFER_DESC))
              .insertAtOffset(0,
                new FieldInsnNode(GETFIELD, owner, "$stride", "I"),
                fieldOffsetInstruction(f.name),
                new InsnNode(IADD),
                bufferHelper.invokeGetter(f.name))
              .delete(0)
              .transform();
          }
          if (LOG) System.out.println("\tindex=" + i);
          break;
        default:
          break;
      }
    }
   
    return super.transform(mn);
  }

  private boolean isSettingFieldWithPrimitive(FieldInsnNode f) {
    return PUTFIELD == f.getOpcode() &&
      f.owner.equals(meta.type.getInternalName()) &&
      f.desc.equals(fieldDesc) &&
      hasInstanceField(meta, f.name) &&
      !isObjectAccess(f.getPrevious()) &&
      !isObjectAccess(f.getPrevious().getPrevious());
  }
 
  private boolean isSettingFieldWithObject(FieldInsnNode f) {
    return PUTFIELD == f.getOpcode() &&
      isObjectAccess(f.getPrevious()) &&
      f.owner.equals(meta.type.getInternalName()) &&
      f.desc.equals(fieldDesc) &&
      hasInstanceField(meta, f.name);
  }
 
  private boolean isModifyingFieldWithObject(FieldInsnNode f) {
    return PUTFIELD == f.getOpcode() &&
      isObjectAccess(f.getPrevious().getPrevious()) &&
      f.owner.equals(meta.type.getInternalName()) &&
      f.desc.equals(fieldDesc) &&
      hasInstanceField(meta, f.name);
  }


  private boolean isLoadingFromField(FieldInsnNode f) {
    return GETFIELD == f.getOpcode() &&
      DUP == f.getPrevious().getOpcode() &&
      !isObjectAccess(f.getNext().getNext()) &&
      f.owner.equals(meta.type.getInternalName()) &&
      f.desc.equals(fieldDesc) &&
      hasInstanceField(meta, f.name);
  }
 
  private boolean isGettingField(FieldInsnNode f) {
    return GETFIELD == f.getOpcode() &&
      DUP != f.getPrevious().getOpcode() &&
      f.owner.equals(meta.type.getInternalName()) &&
      f.desc.equals(fieldDesc) &&
      hasInstanceField(meta, f.name);
  }
 
 
  private static boolean hasInstanceField(ClassMetadata meta, String fieldName) {
    for (FieldDescriptor f : ClassMetadataUtil.instanceFields(meta)) {
      if (f.name.equals(fieldName))
        return true;
    }
   
    return false;
  }
 
  private boolean isObjectAccess(AbstractInsnNode n) {
    if (n == null) return false;
   
    int opcode = n.getOpcode();
    return
      opcode == INVOKESPECIAL ||
      opcode == INVOKEVIRTUAL ||
      opcode == INVOKEINTERFACE ||
      (opcode == GETFIELD && !((FieldInsnNode)n).owner.equals(meta.type.getInternalName()));
  }
 
  private AbstractInsnNode fieldOffsetInstruction(String name) {
    int offset = offset(name);
   
    if (offset <= 5)
      return new InsnNode(ICONST_0 + offset);
    else if (offset <= 0xff)
      return new IntInsnNode(BIPUSH, offset);
    else
      return new IntInsnNode(SIPUSH, offset);
  }
 
  private int offset(String name) {
    List<FieldDescriptor> fields = meta.fields;
   
    int offset = 0;
    for (int i = 0; fields.size() > i; i++) {
      FieldDescriptor fd = fields.get(i);
      if (fd.name.equals(name))
        break;
     
      offset += ClassMetadataUtil.sizeOf(fd);
    }
    return offset;
  }
}
TOP

Related Classes of com.artemis.weaver.packed.FieldToStructMethodTransformer

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.