/**
* 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.Type;
import org.objectweb.perseus.cache.api.CacheEntry;
import org.objectweb.perseus.cache.api.FixableCacheEntry;
import org.objectweb.perseus.cache.replacement.api.ReplaceableCacheEntry;
import org.objectweb.speedo.generation.enhancer.common.LoggedClassAdapter;
import org.objectweb.speedo.lib.Personality;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
/**
* Is an ASM visitor adding the implementation of the ReplaceableCacheEntry
* interface.
*
* @author S.Chassande-Barrioz
*/
public class CacheEntryAdder extends LoggedClassAdapter {
public final static String FIX_FIELD_NAME = "speedoFixCount";
public final static String AGE_FIELD_NAME = "speedoAge";
private String classToWrite;
public CacheEntryAdder(ClassVisitor classVisitor, Logger logger,
String className, Personality p) {
super(classVisitor, p, logger);
this.classToWrite = getJVMClassName(className);
}
public void visit(final int version, final int access, final String name,
final String superName, final String[] interfaces,
final String sourceFile) {
String[] itfs;
if (interfaces != null && interfaces.length > 0) {
itfs = new String[interfaces.length + 3];
System.arraycopy(interfaces, 0, itfs, 3, interfaces.length);
} else {
itfs = new String[3];
}
itfs[0] = Type.getInternalName(ReplaceableCacheEntry.class);
itfs[1] = Type.getInternalName(FixableCacheEntry.class);
itfs[2] = Type.getInternalName(CacheEntry.class);
cv.visit(version, access, name, superName, itfs, sourceFile);
generateField();
generateGetCeObjectMethod();
generateGetCeIdentifierMethod();
generateFixCeMethod();
generateUnfixCeMethod();
generateGetCeFixCountMethod();
generateGetCeAgeMethod();
generateSetCeAgeMethod();
}
/**
* Generates the field #FIX_FIELD_NAME and #AGE_FIELD_NAME
*/
private void generateField() {
if (debug) {
logger.log(BasicLevel.DEBUG, "Generate the field: int "
+ FIX_FIELD_NAME);
}
cv.visitField(ACC_TRANSIENT + ACC_PROTECTED, FIX_FIELD_NAME,
Type.INT_TYPE.getDescriptor(), null, null);
if (debug) {
logger.log(BasicLevel.DEBUG, "Generate the field: long "
+ AGE_FIELD_NAME);
}
cv.visitField(ACC_TRANSIENT + ACC_PROTECTED, AGE_FIELD_NAME,
Type.LONG_TYPE.getDescriptor(), null, null);
}
/**
* Generates the method getCeObject():Object
*
* @param classToWrite
* is the class name
*/
private void generateGetCeObjectMethod() {
if (debug) {
logger.log(BasicLevel.DEBUG, "Generate the method: getCeObject");
}
CodeVisitor mv = cv.visitMethod(ACC_PUBLIC, "getCeObject",
"()Ljava/lang/Object;", null, null);
// return this;
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
}
/**
* Generates the method getCeIdentifier():Object
*
* @param classToWrite
* is the class name
*/
private void generateGetCeIdentifierMethod() {
if (debug) {
logger
.log(BasicLevel.DEBUG,
"Generate the method: getCeIdentifier");
}
CodeVisitor mv = cv.visitMethod(ACC_PUBLIC, "getCeIdentifier",
"()Ljava/lang/Object;", null, null);
// return getPName();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, "getPName",
"()Lorg/objectweb/jorm/naming/api/PName;");
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
}
/**
* Generates the method fixCe():void
*
* @param classToWrite
* is the class name
*/
private void generateFixCeMethod() {
if (debug) {
logger.log(BasicLevel.DEBUG, "Generate the method: fixCe");
}
CodeVisitor mv = cv.visitMethod(ACC_PUBLIC, "fixCe", "()V", null, null);
// speedoFixCount++;
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(DUP);
mv.visitFieldInsn(GETFIELD, classToWrite, FIX_FIELD_NAME, "I");
mv.visitInsn(ICONST_1);
mv.visitInsn(IADD);
mv.visitFieldInsn(PUTFIELD, classToWrite, FIX_FIELD_NAME, "I");
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
}
/**
* Generates the method unfixCe():void
*
* @param classToWrite
* is the class name
*/
private void generateUnfixCeMethod() {
if (debug) {
logger.log(BasicLevel.DEBUG, "Generate the method: unfixCe");
}
CodeVisitor mv = cv.visitMethod(ACC_PUBLIC, "unfixCe", "()V", null,
null);
// speedoFixCount--;
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(DUP);
mv.visitFieldInsn(GETFIELD, classToWrite, FIX_FIELD_NAME, "I");
mv.visitInsn(ICONST_1);
mv.visitInsn(ISUB);
mv.visitFieldInsn(PUTFIELD, classToWrite, FIX_FIELD_NAME, "I");
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
}
/**
* Generates the method getCeFixCount():int
*
* @param classToWrite
* is the class name
*/
private void generateGetCeFixCountMethod() {
if (debug) {
logger.log(BasicLevel.DEBUG, "Generate the method: getCeFixCount");
}
CodeVisitor mv = cv.visitMethod(ACC_PUBLIC, "getCeFixCount", "()I",
null, null);
// return speedoFixCount;
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classToWrite, FIX_FIELD_NAME, "I");
mv.visitInsn(IRETURN);
mv.visitMaxs(0, 0);
}
/**
* Generates the method getCeAge():long
*
* @param classToWrite
* is the class name
*/
private void generateGetCeAgeMethod() {
if (debug) {
logger.log(BasicLevel.DEBUG, "Generate the method: getCeAge");
}
CodeVisitor mv = cv.visitMethod(ACC_PUBLIC, "getCeAge", "()J", null,
null);
// return speedoAge;
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classToWrite, AGE_FIELD_NAME, "J");
mv.visitInsn(LRETURN);
mv.visitMaxs(0, 0);
}
/**
* Generates the method setCeAge(long):void
*
* @param classToWrite
* is the class name
*/
private void generateSetCeAgeMethod() {
if (debug) {
logger.log(BasicLevel.DEBUG, "Generate the method: setCeAge");
}
CodeVisitor mv = cv.visitMethod(ACC_PUBLIC, "setCeAge", "(J)V", null,
null);
// this.speedoAge = a;
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(LLOAD, 1);
mv.visitFieldInsn(PUTFIELD, classToWrite, AGE_FIELD_NAME, "J");
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
}
}