Package org.objectweb.speedo.generation.enhancer.pc

Source Code of org.objectweb.speedo.generation.enhancer.pc.POAdder

/**
* Copyright (C) 2001-2005 France Telecom R&D
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
package org.objectweb.speedo.generation.enhancer.pc;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.CodeVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.Type;
import org.objectweb.jorm.type.api.PType;
import org.objectweb.speedo.api.SpeedoException;
import org.objectweb.speedo.generation.api.SpeedoCompilerParameter;
import org.objectweb.speedo.generation.generator.lib.AbstractSpeedoGenerator;
import org.objectweb.speedo.lib.Personality;
import org.objectweb.speedo.metadata.SpeedoClass;
import org.objectweb.speedo.mim.api.PersistentObjectItf;
import org.objectweb.speedo.mim.lib.SpeedoPOSerializer;
import org.objectweb.speedo.naming.api.NamingManager;
import org.objectweb.util.monolog.api.Logger;

/**
* Is an ASM visitor adding the implementation of the PersistenceCapable
* interface.
*
* @author S.Chassande-Barrioz
*/
public class POAdder    
    extends AbstractPCModifier
    implements POVariableNames {

    public POAdder(ClassVisitor classVisitor,
            Logger logger,
            SpeedoClass sc,
            SpeedoCompilerParameter cp,
            Personality p) {
        super(classVisitor, logger, sc, cp, p);
    }
   
    public void visit(final int version,
            final int access,
              final String name,
              final String superName,
              final String[] interfaces,
              final String sourceFile) {
        //indicate the number of new interface to add
        String[] itfs;
        if (interfaces != null && interfaces.length > 0) {
            itfs = new String[interfaces.length + 1];
            System.arraycopy(interfaces, 0, itfs, 1, interfaces.length);
        } else {
            itfs = new String[1];
        }
        itfs[0] =  Type.getInternalName(PersistentObjectItf.class);
        cv.visit(version, access, name, superName, itfs, sourceFile);
    }
    public void visitEnd() {
        if (speedoClass.getSuper() == null) {
            generateFields();
            generateSpeedoIsActiveMethod();
            generateSpeedoIsActiveZMethod();
            generateSpeedoGetHomeMethod();
            generateSpeedoGetReferenceStateMethod();
            generateSpeedoSetReferenceStateMethod();
            generateSpeedoGetStateMethod();
            generateSpeedoCopyStateMethod();
            generateSpeedoReadIntentionMethod();
            generateSpeedoWriteIntentionMethod();
            generateSpeedoGetEncodedPNameMethod();
            generateSpeedoSetEncodedPNameMethod();
            generateSpeedoGetPNameHintsMethod();
            generateSpeedoGetPOManagerMethod();
            generateSpeedoIsPersistentMethod();
        }
        generateSpeedoCreateStateMethod();
        final int nbfields = speedoClass.computeFieldNumbers();
        if (speedoClass.isSerializable) {
            generateReadObjectMethod(nbfields);
            generateWriteObjectMethod(nbfields);
        }
        super.visitEnd();
    }

    private void generateFields() {
        //transient protected boolean speedoIsActive = false;
        cv.visitField(ACC_TRANSIENT + ACC_PROTECTED, ISACTIVE_FIELD_NAME,
                Type.BOOLEAN_TYPE.getDescriptor(), null, null);
        //transient protected $classNameFields speedoReferenceState = null;
        cv.visitField(ACC_TRANSIENT + ACC_PROTECTED, REFSTATE_FIELD_NAME,
                xfieldsJT, null, null);
        //protected Object encodedPName = null;
        cv.visitField(ACC_PROTECTED, ENCODEDPNAME_FIELD_NAME,
                "Ljava/lang/Object;", null, null);
    }
   
    private void generateSpeedoIsActiveMethod() {
        CodeVisitor mv;
        mv = cv.visitMethod(ACC_PUBLIC, ISACTIVE_FIELD_NAME, "()Z", null, null);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, classToWrite, ISACTIVE_FIELD_NAME, "Z");
        mv.visitInsn(IRETURN);
        mv.visitMaxs(0, 0);
    }
    private void generateSpeedoIsActiveZMethod() {
        CodeVisitor mv;
        mv = cv.visitMethod(ACC_PUBLIC, ISACTIVE_FIELD_NAME, "(Z)V", null, null);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ILOAD, 1);
        mv.visitFieldInsn(PUTFIELD, classToWrite, ISACTIVE_FIELD_NAME, "Z");
        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 0);
    }
    private void generateSpeedoGetHomeMethod() {
        CodeVisitor mv;
        mv = cv.visitMethod(ACC_PUBLIC, M_SPEEDO_GET_HOME, "()" + JT_HOME, null, null);
        mv.visitVarInsn(ALOAD, 0);
        //return (HomeItf) getPClassMapping();
        mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, "getPClassMapping",
                "()Lorg/objectweb/jorm/api/PClassMapping;");
        mv.visitTypeInsn(CHECKCAST, JCN_HOME);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0);
    }
    private void generateSpeedoGetReferenceStateMethod() {
        CodeVisitor mv;
        mv = cv.visitMethod(ACC_PUBLIC, M_SPEEDO_GET_REF_STATE, "()" + JT_STATE, null, null);
        //return speedoReferenceState
        generateGetRefState(mv, false);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0);
    }
    private void generateSpeedoGetStateMethod() {
        CodeVisitor mv;
        mv = cv.visitMethod(ACC_PUBLIC, M_SPEEDO_GET_STATE, "()" + JT_STATE, null, null);
        //if (!speedoIsActive) {
        //    return speedoReferenceState;
        //}
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, classToWrite, ISACTIVE_FIELD_NAME, "Z");
        Label l1 = new Label();
        mv.visitJumpInsn(IFNE, l1);
        generateGetRefState(mv, false);
        mv.visitInsn(ARETURN);
        mv.visitLabel(l1);

        //return speedoGetHome().getSpeedoAccessor(this);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, M_SPEEDO_GET_HOME, "()" + JT_HOME);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKEINTERFACE, JCN_HOME, "getState",
                "(" + JT_PO + ")" + JT_STATE);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0);
    }
    private void generateSpeedoReadIntentionMethod() {
        CodeVisitor mv;
        mv = cv.visitMethod(ACC_PUBLIC, "speedoReadIntention",
                "([J)" + JT_STATE, null, null);
        //if (!speedoIsActive) {
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, classToWrite, ISACTIVE_FIELD_NAME, "Z");
        Label l1 = new Label();
        mv.visitJumpInsn(IFNE, l1);
        {
            //if (speedoReferenceState == null) {
            generateGetRefState(mv, false);
            Label l3 = new Label();
            mv.visitJumpInsn(IFNONNULL, l3);
            {
                //speedoSetReferenceState(speedoCreateState());
                mv.visitVarInsn(ALOAD, 0);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
                        M_SPEEDO_CREATE_STATE, "()" + JT_STATE);
                mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
                        M_SPEEDO_SET_REF_STATE, "(" + JT_STATE + ")V");
            }
            //return speedoReferenceState;
            mv.visitLabel(l3);
            generateGetRefState(mv, false);
            mv.visitInsn(ARETURN);
        }
       
        //return speedoGetHome().readIntention(this, fields);
        mv.visitLabel(l1);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, M_SPEEDO_GET_HOME, "()" + JT_HOME);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(INVOKEINTERFACE, JCN_HOME, "readIntention",
                "(" + JT_PO + "[J)" + JT_STATE);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0);
    }
    private void generateSpeedoWriteIntentionMethod() {
        CodeVisitor mv;
        mv = cv.visitMethod(ACC_PUBLIC, "speedoWriteIntention",
                "([J)" + JT_STATE, null, null);
        //if (!speedoIsActive) {
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, classToWrite, ISACTIVE_FIELD_NAME, "Z");
        Label l1 = new Label();
        mv.visitJumpInsn(IFNE, l1);
        {
            //if (speedoReferenceState == null) {
            generateGetRefState(mv, false);
            Label l3 = new Label();
            mv.visitJumpInsn(IFNONNULL, l3);
            {
                //speedoSetReferenceState(speedoCreateState());
                mv.visitVarInsn(ALOAD, 0);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
                        M_SPEEDO_CREATE_STATE, "()" + JT_STATE);
                mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
                        M_SPEEDO_SET_REF_STATE, "(" + JT_STATE + ")V");
            }
            //if(speedoReferenceState.getDetachedStatus() == DetachedLifeCycle.DETACHED_CLEAN){  
            mv.visitLabel(l3);
            generateGetRefState(mv, false);
            mv.visitMethodInsn(INVOKEVIRTUAL, xfieldsAncestorJCN, "getDetachedStatus", "()B");
            mv.visitInsn(ICONST_1);
            Label l5 = new Label();
            mv.visitJumpInsn(IF_ICMPNE, l5);
            {
                //speedoReferenceState.setDetachedStatus(DetachedLifeCycle.DETACHED_DIRTY);
                generateGetRefState(mv, false);
                mv.visitInsn(ICONST_2);
                mv.visitMethodInsn(INVOKEVIRTUAL, xfieldsAncestorJCN, "setDetachedStatus", "(B)V");
            }
            //return speedoReferenceState;
            mv.visitLabel(l5);
            generateGetRefState(mv, false);
            mv.visitInsn(ARETURN);
        }
        //return speedoGetHome().writeIntention(this, fields);
        mv.visitLabel(l1);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, M_SPEEDO_GET_HOME, "()" + JT_HOME);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(INVOKEINTERFACE, JCN_HOME, "writeIntention",
                "(" + JT_PO + "[J)" + JT_STATE);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0);
    }
    private void generateSpeedoGetEncodedPNameMethod() {
        CodeVisitor mv;
        mv = cv.visitMethod(ACC_PUBLIC, "speedoGetEncodedPName", "()Ljava/lang/Object;", null, null);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, classToWrite, ENCODEDPNAME_FIELD_NAME, "Ljava/lang/Object;");
        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0);
    }
    private void generateSpeedoSetEncodedPNameMethod() {
        CodeVisitor mv;
        mv = cv.visitMethod(ACC_PUBLIC, "speedoSetEncodedPName", "(Ljava/lang/Object;)V", null, null);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitFieldInsn(PUTFIELD, classToWrite, ENCODEDPNAME_FIELD_NAME, "Ljava/lang/Object;");
        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 0);
    }

    private void generateSpeedoGetPNameHintsMethod() {
        CodeVisitor mv;
        mv = cv.visitMethod(ACC_PUBLIC, "speedoGetPNameHints", "()Ljava/lang/Object;", null, null);
        final Object[] actions;
        try {
            actions = scp.nmf.getNamingManager(speedoClass).getPNameHints2(
                    speedoClass,
                    AbstractSpeedoGenerator.getClassNameDef(speedoClass.jormclass, scp));
        } catch (SpeedoException e) {
            throw personality.newRuntimeException(e.getMessage(), e);
        }
        if (actions == null || actions.length == 0) {
            mv.visitInsn(ACONST_NULL);
        } else if (actions[0].equals(NamingManager.PNH_NULL_VALUE)) {
            mv.visitInsn(ACONST_NULL);

        } else if (actions[0].equals(NamingManager.PNH_REF_STATE)) {
            generateGetRefState(mv, false);
       
        } else if (actions[0].equals(NamingManager.PNH_PFIELD)) {
            final PType pt = (PType) actions[2];
            final String fieldName = (String) actions[1];
            final String jvmFieldType = getJVMType(pt);
            final String wrapper = getJavaWrapper(pt);
            if (wrapper != null) {
                mv.visitTypeInsn(NEW, wrapper);
                mv.visitInsn(DUP);
            }
            generateGetRefState(mv, true);
            mv.visitFieldInsn(GETFIELD, xfieldsJCN, fieldName, jvmFieldType);
            if (wrapper != null) {
                mv.visitMethodInsn(INVOKESPECIAL, wrapper, "<init>",
                        "(" + jvmFieldType + ")V");
            }
        }

        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0);
    }
    private void generateSpeedoGetPOManagerMethod() {
        CodeVisitor mv = cv.visitMethod(ACC_PUBLIC, "speedoGetPOManager",
                "()Lorg/objectweb/speedo/pm/api/POManagerItf;", null, null);
        //return (speedoIsActive
                //? speedoGetHome().getPOManagerFactory().lookup()
                //: null);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, classToWrite, ISACTIVE_FIELD_NAME, "Z");
        Label l1 = new Label();
        mv.visitJumpInsn(IFEQ, l1);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, "speedoGetHome",
                "()" + JT_HOME);
        mv.visitMethodInsn(INVOKEINTERFACE, JCN_HOME, "getPOManagerFactory",
                "()" + JT_POMF);
        mv.visitMethodInsn(INVOKEINTERFACE, JCN_POMF, "lookup", "()" + JT_POM);
        Label l2 = new Label();
        mv.visitJumpInsn(GOTO, l2);
        mv.visitLabel(l1);
        mv.visitInsn(ACONST_NULL);
        mv.visitLabel(l2);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0);
    }
    private String getJavaWrapper(PType pt) {
        switch (pt.getTypeCode()) {
        case PType.TYPECODE_BOOLEAN:
            return getJVMClassName(Boolean.class);
        case PType.TYPECODE_CHAR:
            return getJVMClassName(Character.class);
        case PType.TYPECODE_BYTE:
            return getJVMClassName(Byte.class);
        case PType.TYPECODE_SHORT:
            return getJVMClassName(Short.class);
        case PType.TYPECODE_INT:
            return getJVMClassName(Integer.class);
        case PType.TYPECODE_LONG:
            return getJVMClassName(Long.class);
        case PType.TYPECODE_FLOAT:
            return getJVMClassName(Float.class);
        case PType.TYPECODE_DOUBLE:
            return getJVMClassName(Double.class);
        default:
            return null;
        }
    }
   
    private void generateSpeedoCreateStateMethod() {
        CodeVisitor mv;
        mv = cv.visitMethod(ACC_PUBLIC, M_SPEEDO_CREATE_STATE, "()" + JT_STATE, null, null);
        //return new $classNameFields(this);
        mv.visitTypeInsn(NEW, xfieldsJCN);
        mv.visitInsn(DUP);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, xfieldsJCN, "<init>", "(" + JT_PO + ")V");
        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0);
    }

    private void generateSpeedoSetReferenceStateMethod() {
        CodeVisitor mv;
        mv = cv.visitMethod(ACC_PUBLIC, M_SPEEDO_SET_REF_STATE, "("+ JT_STATE + ")V", null, null);
        //speedoReferenceState = ($classNameFields) refAcc;
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(CHECKCAST, xfieldsAncestorJCN);
        mv.visitFieldInsn(PUTFIELD, ancestorJCN, REFSTATE_FIELD_NAME, xfieldsAncestorJT);
        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 0);
    }
    private void generateSpeedoCopyStateMethod() {
        CodeVisitor mv;
        mv = cv.visitMethod(ACC_PUBLIC, M_SPEEDO_COPY_STATE,
                "(" + JT_STATE + JT_STATE + ")V", null, null);
        //(($classNameFields) src).speedoCopyState(src, dest);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(CHECKCAST, xfieldsJCN);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitMethodInsn(INVOKEVIRTUAL, xfieldsJCN, M_SPEEDO_COPY_STATE,
                "(" + JT_STATE + JT_STATE + ")V");
        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 0);
    }
    private void generateReadObjectMethod(int nbField) {
        CodeVisitor mv;
        mv = cv.visitMethod(ACC_PRIVATE, "readObject",
                "(Ljava/io/ObjectInputStream;)V",
                new String[] { "java/io/IOException", "java/lang/ClassNotFoundException" }, null);
        mv.visitVarInsn(ALOAD, 1); //param
        mv.visitVarInsn(ALOAD, 0); //this
        mv.visitMethodInsn(INVOKESTATIC, getJVMClassName(SpeedoPOSerializer.class),
                "readObject",
                "(Ljava/io/ObjectInputStream;" + JT_PO + ")V");
        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 0);
    }
    private void generateWriteObjectMethod(int nbField) {
        CodeVisitor mv;
        mv = cv.visitMethod(ACC_PRIVATE, "writeObject",
                "(Ljava/io/ObjectOutputStream;)V",
                new String[] { "java/io/IOException" }, null);
        mv.visitVarInsn(ALOAD, 1); //param
        mv.visitVarInsn(ALOAD, 0); //this
        // new long[]{0xffffffffffffffffL, ..., 0xffffffffffffffffL}
        generateFieldIdAsLongArray(null, nbField, mv);
        mv.visitMethodInsn(INVOKESTATIC, getJVMClassName(SpeedoPOSerializer.class),
                "writeObject",
                "(Ljava/io/ObjectOutputStream;" + JT_PO + "[J)V");
        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 0);
    }
    private void generateSpeedoIsPersistentMethod() {
        CodeVisitor mv;
        mv = cv.visitMethod(ACC_PUBLIC, "speedoIsPersistent", "()Z", null, null);

        //if (!speedoIsActive) {
        //    return false;
        //}
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, classToWrite, ISACTIVE_FIELD_NAME, "Z");
        Label l1 = new Label();
        mv.visitJumpInsn(IFNE, l1);
        mv.visitInsn(ICONST_0);
        mv.visitInsn(IRETURN);
        mv.visitLabel(l1);

        //StateItf sa = speedoGetState();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, M_SPEEDO_GET_STATE, "()" + JT_STATE);
        mv.visitVarInsn(ASTORE, 1);

        //return sa == null || LifeCycle.isPersistent(sa.speedoGetStatus());
        mv.visitVarInsn(ALOAD, 1);
        Label l4 = new Label();
        mv.visitJumpInsn(IFNULL, l4);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(INVOKEINTERFACE, JCN_STATE, M_SPEEDO_GET_STATUS, "()B");
        mv.visitMethodInsn(INVOKESTATIC, JCN_LIFE_CYCLE, "isPersistent", "(B)Z");
        Label l5 = new Label();
        mv.visitJumpInsn(IFEQ, l5);
        mv.visitLabel(l4);
        mv.visitInsn(ICONST_1);
        Label l6 = new Label();
        mv.visitJumpInsn(GOTO, l6);
       
        mv.visitLabel(l5);
        mv.visitInsn(ICONST_0);

        mv.visitLabel(l6);
        mv.visitInsn(IRETURN);
        mv.visitMaxs(0, 0);
    }
   
}
TOP

Related Classes of org.objectweb.speedo.generation.enhancer.pc.POAdder

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.