![JAR search and dependency download from the Maven repository](/logo.png)
org.sfm.reflect.asm.CsvMapperCellHandlerBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of simpleFlatMapper Show documentation
Show all versions of simpleFlatMapper Show documentation
Java library to map flat record - ResultSet, csv - to java object with minimum configuration and low footprint.
package org.sfm.reflect.asm;
import org.objectweb.asm.*;
import org.sfm.csv.CsvColumnKey;
import org.sfm.csv.impl.*;
import org.sfm.map.FieldMapperErrorHandler;
import org.sfm.reflect.Instantiator;
import java.lang.reflect.Type;
import static org.objectweb.asm.Opcodes.*;
public class CsvMapperCellHandlerBuilder {
public static final String DELAYED_CELL_SETTER_TYPE = AsmUtils.toType(DelayedCellSetter.class);
public static final String CELL_SETTER_TYPE = AsmUtils.toType(CellSetter.class);
public static final String CSV_CELL_MAPPER_TYPE = AsmUtils.toType(CsvMapperCellHandler.class);
public static final String CELL_HANDLER_FACTORY_TYPE = AsmUtils.toType(CsvMapperCellHandlerFactory.class);
public static byte[] createTargetSetterClass(String className,
DelayedCellSetterFactory[] delayedCellSetters,
CellSetter[] setters, Type type, boolean ignoreException, int maxMethodSize) throws Exception {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
FieldVisitor fv;
MethodVisitor mv;
final String targetType = AsmUtils.toType(type);
final String classType = AsmUtils.toType(className);
cw.visit(V1_6, ACC_FINAL +ACC_PUBLIC + ACC_SUPER, classType,
"L" + CSV_CELL_MAPPER_TYPE + ";", CSV_CELL_MAPPER_TYPE, null);
// declare fields
for(int i = 0; i < delayedCellSetters.length; i++) {
if (delayedCellSetters[i] != null) {
fv = cw.visitField(ACC_PROTECTED + ACC_FINAL, "delayedCellSetter" + i,
AsmUtils.toDeclaredLType(DELAYED_CELL_SETTER_TYPE),
"L" + DELAYED_CELL_SETTER_TYPE + ";", null);
fv.visitEnd();
}
}
for(int i = 0; i < setters.length; i++) {
if (setters[i] != null) {
fv = cw.visitField(ACC_PROTECTED + ACC_FINAL, "setter" + i,
AsmUtils.toDeclaredLType(CELL_SETTER_TYPE),
"L" + CELL_SETTER_TYPE + ";", null);
fv.visitEnd();
}
}
appendInit(delayedCellSetters, setters, cw, targetType, classType, maxMethodSize);
appendDelayedCellValue(delayedCellSetters, ignoreException, cw, classType);
append_delayedCellValue(delayedCellSetters, cw, classType, maxMethodSize);
appendCellValue(setters, ignoreException, cw, classType);
append_cellValue(delayedCellSetters, setters, cw, classType, maxMethodSize);
appendApplyDelayedSetter(delayedCellSetters, ignoreException, cw, classType, maxMethodSize);
appendApplyDelayedCellSetterN(delayedCellSetters, cw, classType);
appendGetDelayedCellSetter(delayedCellSetters, cw, targetType, classType, maxMethodSize);
appendPeekDelayedCellSetterValue(delayedCellSetters, cw, classType, maxMethodSize);
cw.visitEnd();
return AsmUtils.writeClassToFile(className, cw.toByteArray());
}
private static void append_cellValue(final DelayedCellSetterFactory[] delayedCellSetters, final CellSetter[] setters, ClassWriter cw, final String classType, final int maxMethodSize) {
ShardingHelper.shard(setters.length, maxMethodSize, new AbstractMethodDispatchShardCallBack(cw, classType, maxMethodSize ) {
@Override
protected void appendLeafSwitch(MethodVisitor mv, int start, int end) {
Label defaultLabel = new Label();
Label[] labels = newLabels(end - start);
mv.visitTableSwitchInsn(delayedCellSetters.length + start, delayedCellSetters.length + end - 1, defaultLabel, labels);
for (int i = start; i < end; i++) {
mv.visitLabel(labels[i - start]);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
if (setters[i] != null) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classType, "setter" + i, "L" + CELL_SETTER_TYPE + ";");
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classType, "currentInstance", "Ljava/lang/Object;");
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ILOAD, 2);
mv.visitVarInsn(ILOAD, 3);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classType, "parsingContext", AsmUtils.toDeclaredLType(ParsingContext.class));
mv.visitMethodInsn(INVOKEINTERFACE, CELL_SETTER_TYPE, "set", "(Ljava/lang/Object;[CIIL" + AsmUtils.toType(ParsingContext.class) + ";)V", true);
}
if (i < (end - 1)) {
mv.visitJumpInsn(GOTO, defaultLabel);
}
}
mv.visitLabel(defaultLabel);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
}
@Override
protected int maxArgIndex() {
return 4;
}
@Override
protected void loadArguments(MethodVisitor mv) {
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ILOAD, 2);
mv.visitVarInsn(ILOAD, 3);
mv.visitVarInsn(ILOAD, 4);
}
@Override
protected int argIndex() {
return 4;
}
@Override
protected String name() {
return "_cellValue";
}
@Override
protected String signature() {
return "([CIII)V";
}
@Override
protected int leafStart() {
return delayedCellSetters.length;
}
@Override
protected void appendDebugInfo(MethodVisitor mv, Label startLabel, Label endLabel) {
mv.visitLocalVariable("this", "Lorg/sfm/reflect/asm/sample/AsmCsvMapperCellHandler;", null, startLabel, endLabel, 0);
mv.visitLocalVariable("chars", "[C", null, startLabel, endLabel, 1);
mv.visitLocalVariable("offset", "I", null, startLabel, endLabel, 2);
mv.visitLocalVariable("length", "I", null, startLabel, endLabel, 3);
mv.visitLocalVariable("cellIndex", "I", null, startLabel, endLabel, 4);
}
});
}
private static void appendPeekDelayedCellSetterValue(final DelayedCellSetterFactory[] delayedCellSetters, final ClassWriter cw, final String classType, final int maxMethodSize) {
ShardingHelper.shard(delayedCellSetters.length, maxMethodSize, new AbstractMethodDispatchShardCallBack(cw, classType, maxMethodSize ) {
@Override
protected void appendLeafSwitch(MethodVisitor mv, int start, int end) {
Label defaultLabel = new Label();
Label[] labels = newLabels(end - start);
mv.visitTableSwitchInsn(start, end - 1, defaultLabel, labels);
for (int i = start; i < end; i++) {
mv.visitLabel(labels[i -start]);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
if (delayedCellSetters[i] != null) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classType, "delayedCellSetter" + i, "L" + DELAYED_CELL_SETTER_TYPE + ";");
mv.visitMethodInsn(INVOKEINTERFACE, DELAYED_CELL_SETTER_TYPE, "peekValue", "()Ljava/lang/Object;", true);
mv.visitInsn(ARETURN);
} else if (i < (delayedCellSetters.length - 1)) {
mv.visitInsn(ACONST_NULL);
mv.visitInsn(ARETURN);
}
}
mv.visitLabel(defaultLabel);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
}
@Override
protected int maxArgIndex() {
return 1;
}
@Override
protected void loadArguments(MethodVisitor mv) {
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ILOAD, 1);
}
@Override
protected int argIndex() {
return 1;
}
@Override
protected String name() {
return "_peekDelayedCellSetterValue";
}
@Override
protected String signature() {
return "(I)Ljava/lang/Object;";
}
});
MethodVisitor mv;
mv = cw.visitMethod(ACC_PUBLIC, "peekDelayedCellSetterValue" , "(L" + AsmUtils.toType(CsvColumnKey.class) + ";)Ljava/lang/Object;", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, AsmUtils.toType(CsvColumnKey.class), "getIndex", "()I", false);
mv.visitVarInsn(ISTORE, 2);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ILOAD, 2);
mv.visitMethodInsn(INVOKESPECIAL, classType, "_peekDelayedCellSetterValue", "(I)Ljava/lang/Object;", false);
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 2);
mv.visitEnd();
}
private static void append_delayedCellValue(final DelayedCellSetterFactory[] delayedCellSetters, final ClassWriter cw, final String classType, final int maxMethodSize) {
ShardingHelper.shard(delayedCellSetters.length, maxMethodSize, new AbstractMethodDispatchShardCallBack(cw, classType, maxMethodSize ) {
@Override
protected void appendLeafSwitch(MethodVisitor mv, int start, int end) {
Label defaultLabel = new Label();
Label[] labels = newLabels(end - start);
mv.visitTableSwitchInsn(start, end - 1, defaultLabel, labels);
for (int i = start; i < end; i++) {
mv.visitLabel(labels[i - start]);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
if (delayedCellSetters[i] != null) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classType, "delayedCellSetter" + i, "L" + DELAYED_CELL_SETTER_TYPE + ";");
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ILOAD, 2);
mv.visitVarInsn(ILOAD, 3);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classType, "parsingContext", AsmUtils.toDeclaredLType(ParsingContext.class));
mv.visitMethodInsn(INVOKEINTERFACE, DELAYED_CELL_SETTER_TYPE, "set", "([CIIL" + AsmUtils.toType(ParsingContext.class) + ";)V", true);
}
if (i < (end - 1)) {
mv.visitJumpInsn(GOTO, defaultLabel);
}
}
mv.visitLabel(defaultLabel);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); }
@Override
protected void loadArguments(MethodVisitor mv) {
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ILOAD, 2);
mv.visitVarInsn(ILOAD, 3);
mv.visitVarInsn(ILOAD, 4);
}
@Override
protected int maxArgIndex() {
return 4;
}
@Override
protected int argIndex() {
return 4;
}
@Override
protected String name() {
return "_delayedCellValue";
}
@Override
protected String signature() {
return "([CIII)V";
}
});
}
private static void appendApplyDelayedSetter(final DelayedCellSetterFactory[] delayedCellSetters, final boolean ignoreException, final ClassWriter cw, final String classType, final int maxMethodSize) {
ShardingHelper.shard(delayedCellSetters.length, maxMethodSize, new ShardingHelper.ShardCallBack() {
@Override
public void leafDispatch(String suffix, int start, int end) {
MethodVisitor mv;
mv = cw.visitMethod(ACC_PUBLIC, "applyDelayedSetters" + suffix, "()V", null, null);
mv.visitCode();
if (end - start > 0) {
if (!ignoreException) {
Label[] labels = newLabels((3 * getNbNonNullSettersWithSetters(delayedCellSetters, start, end)) + 1);
for (int i = start, j = 0; i < end; i++) {
if (delayedCellSetters[i] != null && delayedCellSetters[i].hasSetter()) {
mv.visitTryCatchBlock(labels[j], labels[j + 1], labels[j + 2], "java/lang/Exception");
j += 3;
}
}
for (int i = start, j = 0; i < end; i++) {
if (delayedCellSetters[i] != null && delayedCellSetters[i].hasSetter()) {
mv.visitLabel(labels[j]);
if (j > 0) {
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
}
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, classType, "applyDelayedCellSetter" + i, "()V", false);
mv.visitLabel(labels[j + 1]);
mv.visitJumpInsn(GOTO, labels[j + 3]);
mv.visitLabel(labels[j + 2]);
mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[]{"java/lang/Exception"});
mv.visitVarInsn(ASTORE, 1);
mv.visitVarInsn(ALOAD, 0);
AsmUtils.addIndex(mv, i);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, classType, "fieldError", "(ILjava/lang/Exception;)V", false);
j += 3;
}
}
mv.visitLabel(labels[labels.length - 1]);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
} else {
for (int i = start; i < end; i++) {
if (delayedCellSetters[i] != null && delayedCellSetters[i].hasSetter()) {
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, classType, "applyDelayedCellSetter" + i, "()V", false);
}
}
}
}
mv.visitInsn(RETURN);
mv.visitMaxs(3, 2);
mv.visitEnd();
}
@Override
public void nodeDispatch(String suffix, int divide, int start, int end) {
MethodVisitor mv;
mv = cw.visitMethod(ACC_PUBLIC, "applyDelayedSetters" + suffix, "()V", null, new String[]{"java/lang/Exception"});
mv.visitCode();
final int powerOfTwo = Integer.numberOfTrailingZeros(divide);
int sStart = start >> powerOfTwo;
int sEnd = end >> powerOfTwo;
int left = end - (sEnd << powerOfTwo);
if (left > 0) {
sEnd ++;
}
for (int i = sStart; i < sEnd; i++) {
int estart = i * divide;
int eend = Math.min(end, (i+1) * divide);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, classType, "applyDelayedSetters"+ (divide/maxMethodSize) + "n" + estart + "t" + eend, "()V" , false);
}
mv.visitInsn(RETURN);
mv.visitMaxs(6, 5);
mv.visitEnd();
}
});
}
private static Label[] newLabels(int ll) {
Label[] labels = new Label[ll];
for (int i = 0; i < labels.length; i++) {
labels[i] = new Label();
}
return labels;
}
private static void appendApplyDelayedCellSetterN(DelayedCellSetterFactory[] delayedCellSetters, ClassWriter cw, String classType) {
MethodVisitor mv;
for(int i = 0; i < delayedCellSetters.length; i++) {
if (delayedCellSetters[i] != null) {
mv = cw.visitMethod(ACC_PRIVATE, "applyDelayedCellSetter" + i, "()V", null, new String[]{"java/lang/Exception"});
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classType, "delayedCellSetter" + i, "L" + DELAYED_CELL_SETTER_TYPE + ";");
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classType, "currentInstance", "Ljava/lang/Object;");
mv.visitMethodInsn(INVOKEINTERFACE, DELAYED_CELL_SETTER_TYPE, "set", "(Ljava/lang/Object;)V", true);
mv.visitInsn(RETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
}
}
}
private static void appendCellValue(CellSetter[] setters, boolean ignoreException, ClassWriter cw, String classType) {
MethodVisitor mv;
mv = cw.visitMethod(ACC_PUBLIC, "cellValue", "([CIII)V", null, null);
mv.visitCode();
if (setters.length != 0) {
if (ignoreException) {
callCellValue(mv, classType);
} else {
Label l0 = new Label();
Label l1 = new Label();
Label l2 = new Label();
mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Exception");
mv.visitLabel(l0);
callCellValue(mv, classType);
mv.visitLabel(l1);
Label l3 = new Label();
mv.visitJumpInsn(GOTO, l3);
mv.visitLabel(l2);
mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[]{"java/lang/Exception"});
mv.visitVarInsn(ASTORE, 5);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ILOAD, 4);
mv.visitVarInsn(ALOAD, 5);
mv.visitMethodInsn(INVOKEVIRTUAL, classType, "fieldError", "(ILjava/lang/Exception;)V", false);
mv.visitLabel(l3);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
}
}
mv.visitInsn(RETURN);
mv.visitMaxs(5, 6);
mv.visitEnd();
}
private static void appendDelayedCellValue(DelayedCellSetterFactory[] delayedCellSetters, boolean ignoreException, ClassWriter cw, String classType) {
MethodVisitor mv;
mv = cw.visitMethod(ACC_PUBLIC, "delayedCellValue", "([CIII)V", null, null);
mv.visitCode();
if (delayedCellSetters.length != 0) {
if (ignoreException) {
callDelayedCellValue(mv, classType);
} else {
Label l0 = new Label();
Label l1 = new Label();
Label l2 = new Label();
mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Exception");
mv.visitLabel(l0);
callDelayedCellValue(mv, classType);
mv.visitLabel(l1);
Label l3 = new Label();
mv.visitJumpInsn(GOTO, l3);
mv.visitLabel(l2);
mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[]{"java/lang/Exception"});
mv.visitVarInsn(ASTORE, 5);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ILOAD, 4);
mv.visitVarInsn(ALOAD, 5);
mv.visitMethodInsn(INVOKEVIRTUAL, classType, "fieldError", "(ILjava/lang/Exception;)V", false);
mv.visitLabel(l3);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
}
}
mv.visitInsn(RETURN);
mv.visitMaxs(5, 6);
mv.visitEnd();
}
private static void appendInit(DelayedCellSetterFactory[] delayedCellSetters, CellSetter[] setters, ClassWriter cw, String targetType, String classType, int maxSize) {
MethodVisitor mv;// constructor
{
mv = cw.visitMethod(ACC_PUBLIC, "", "(" +
AsmUtils.toDeclaredLType(Instantiator.class) +
AsmUtils.toDeclaredLType(DelayedCellSetter[].class) +
AsmUtils.toDeclaredLType(CellSetter[].class) +
AsmUtils.toDeclaredLType(CsvColumnKey[].class) +
AsmUtils.toDeclaredLType(ParsingContext.class) +
AsmUtils.toDeclaredLType(FieldMapperErrorHandler.class) +
")V",
"(" +
"L" + AsmUtils.toType(Instantiator.class) +";L"+ targetType + ";>;" +
"[L" + DELAYED_CELL_SETTER_TYPE + ";" +
"[L" + CELL_SETTER_TYPE + ";" +
AsmUtils.toDeclaredLType(CsvColumnKey[].class) +
AsmUtils.toDeclaredLType(ParsingContext.class) +
"L" + AsmUtils.toType(FieldMapperErrorHandler.class) + ";" +
")V", null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 4);
mv.visitVarInsn(ALOAD, 2);
mv.visitInsn(ARRAYLENGTH);
mv.visitVarInsn(ALOAD, 3);
mv.visitInsn(ARRAYLENGTH);
mv.visitVarInsn(ALOAD, 5);
mv.visitVarInsn(ALOAD, 6);
mv.visitMethodInsn(INVOKESPECIAL, CSV_CELL_MAPPER_TYPE, "",
"(" +
AsmUtils.toDeclaredLType(Instantiator.class) +
AsmUtils.toDeclaredLType(CsvColumnKey[].class) +
"I" +
"I" +
AsmUtils.toDeclaredLType(ParsingContext.class) +
AsmUtils.toDeclaredLType(FieldMapperErrorHandler.class) +
")V", false);
ShardingHelper.shard(delayedCellSetters.length, maxSize, new ShardingHelper.ShardCallBack() {
@Override
public void leafDispatch(String suffix, int start, int end) {
}
@Override
public void nodeDispatch(String suffix, int divide, int start, int end) {
}
});
for(int i = 0; i < delayedCellSetters.length; i++) {
if (delayedCellSetters[i] != null) {
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 2);
AsmUtils.addIndex(mv, i);
mv.visitInsn(AALOAD);
mv.visitFieldInsn(PUTFIELD,
classType,
"delayedCellSetter" + i,
AsmUtils.toDeclaredLType(DELAYED_CELL_SETTER_TYPE));
}
}
for(int i = 0; i < setters.length; i++) {
if (setters[i] != null) {
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 3);
AsmUtils.addIndex(mv, i);
mv.visitInsn(AALOAD);
mv.visitFieldInsn(PUTFIELD,
classType,
"setter" + i ,
AsmUtils.toDeclaredLType(CELL_SETTER_TYPE));
}
}
mv.visitInsn(RETURN);
mv.visitMaxs(7, 7);
mv.visitEnd();
}
}
private static void appendGetDelayedCellSetter(DelayedCellSetterFactory[] delayedCellSetters, ClassWriter cw, String targetType, String classType, int maxMethodSize) {
MethodVisitor mv;
mv = cw.visitMethod(ACC_PUBLIC, "getDelayedCellSetter", "(I)L" + DELAYED_CELL_SETTER_TYPE + ";",
"(I)L" + DELAYED_CELL_SETTER_TYPE + ";", null);
mv.visitCode();
if (delayedCellSetters.length != 0) {
final int switchStart = 0;
final int switchEnd = delayedCellSetters.length;
appendGetDelayedCellSetterSwitch(delayedCellSetters, classType, mv, switchStart, switchEnd);
}
mv.visitInsn(ACONST_NULL);
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 2);
mv.visitEnd();
}
private static void appendGetDelayedCellSetterSwitch(DelayedCellSetterFactory[] delayedCellSetters, String classType, MethodVisitor mv, int switchStart, int switchEnd) {
mv.visitVarInsn(ILOAD, 1);
Label defaultLabel = new Label();
Label[] labels = newLabels(switchEnd - switchStart);
mv.visitTableSwitchInsn(switchStart, switchEnd - 1, defaultLabel, labels);
for (int i = switchStart; i < switchEnd; i++) {
mv.visitLabel(labels[i - switchStart]);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
if (delayedCellSetters != null) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classType, "delayedCellSetter" + i, "L" + DELAYED_CELL_SETTER_TYPE + ";");
} else {
mv.visitInsn(ACONST_NULL);
}
mv.visitInsn(ARETURN);
}
mv.visitLabel(defaultLabel);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
}
private static void callCellValue(MethodVisitor mv, String classType) {
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ILOAD, 2);
mv.visitVarInsn(ILOAD, 3);
mv.visitVarInsn(ILOAD, 4);
mv.visitMethodInsn(INVOKESPECIAL, classType, "_cellValue", "([CIII)V", false);
}
private static void callDelayedCellValue(MethodVisitor mv, String classType) {
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ILOAD, 2);
mv.visitVarInsn(ILOAD, 3);
mv.visitVarInsn(ILOAD, 4);
mv.visitMethodInsn(INVOKESPECIAL, classType, "_delayedCellValue", "([CIII)V", false);
}
private static int getNbNonNullSettersWithSetters(DelayedCellSetterFactory[] delayedCellSetters, int start, int end) {
int n = 0;
for(int i = start; i < end; i++) {
if (delayedCellSetters[i] != null && delayedCellSetters[i].hasSetter()) n++;
}
return n;
}
public static byte[] createTargetSetterFactory(String factoryName, String className, Type target) throws Exception {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
MethodVisitor mv;
String factoryType = AsmUtils.toType(factoryName);
String classType = AsmUtils.toType(className);
String targetType = AsmUtils.toType(target);
cw.visit(V1_6, ACC_FINAL + ACC_PUBLIC + ACC_SUPER,
factoryType,
"L" + CELL_HANDLER_FACTORY_TYPE + ";",
CELL_HANDLER_FACTORY_TYPE, null);
{
mv = cw.visitMethod(ACC_PUBLIC, "", "(" +
AsmUtils.toDeclaredLType(Instantiator.class) +
AsmUtils.toDeclaredLType(CsvColumnKey[].class) +
AsmUtils.toDeclaredLType(ParsingContextFactory.class) +
AsmUtils.toDeclaredLType(FieldMapperErrorHandler.class) +
")V",
"(" +
"L"+ AsmUtils.toType(Instantiator.class) +
";L" + targetType + ";>;" +
AsmUtils.toDeclaredLType(CsvColumnKey[].class) +
AsmUtils.toDeclaredLType(ParsingContextFactory.class) +
"L" + AsmUtils.toType(FieldMapperErrorHandler.class) + ";" +
")V", null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ALOAD, 3);
mv.visitVarInsn(ALOAD, 4);
mv.visitMethodInsn(INVOKESPECIAL, CELL_HANDLER_FACTORY_TYPE, "",
"(" +
AsmUtils.toDeclaredLType(Instantiator.class) +
AsmUtils.toDeclaredLType(CsvColumnKey[].class) +
AsmUtils.toDeclaredLType(ParsingContextFactory.class) +
AsmUtils.toDeclaredLType(FieldMapperErrorHandler.class) +
")V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(5, 5);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC, "newInstance", "(" +
AsmUtils.toDeclaredLType(DelayedCellSetter[].class) +
AsmUtils.toDeclaredLType(CellSetter[].class) +
")" + AsmUtils.toDeclaredLType(CsvMapperCellHandler.class),
"(" +
"[L" + DELAYED_CELL_SETTER_TYPE + ";" +
"[L" + CELL_SETTER_TYPE + ";" +
")" +
"L" + AsmUtils.toType(CsvMapperCellHandler.class) + ";", null);
mv.visitCode();
mv.visitTypeInsn(NEW, classType);
mv.visitInsn(DUP);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, factoryType, "instantiator", AsmUtils.toDeclaredLType(Instantiator.class));
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, factoryType, "keys", AsmUtils.toDeclaredLType(CsvColumnKey[].class));
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, factoryType, "parsingContextFactory", AsmUtils.toDeclaredLType(ParsingContextFactory.class));
mv.visitMethodInsn(INVOKEVIRTUAL, AsmUtils.toType(ParsingContextFactory.class), "newContext", "()" + AsmUtils.toDeclaredLType(ParsingContext.class), false);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, factoryType, "fieldErrorHandler", AsmUtils.toDeclaredLType(FieldMapperErrorHandler.class));
mv.visitMethodInsn(INVOKESPECIAL, classType, "",
"(" +
AsmUtils.toDeclaredLType(Instantiator.class) +
AsmUtils.toDeclaredLType(DelayedCellSetter[].class) +
AsmUtils.toDeclaredLType(CellSetter[].class) +
AsmUtils.toDeclaredLType(CsvColumnKey[].class) +
AsmUtils.toDeclaredLType(ParsingContext.class) +
AsmUtils.toDeclaredLType(FieldMapperErrorHandler.class) +
")V", false);
mv.visitInsn(ARETURN);
mv.visitMaxs(8, 3);
mv.visitEnd();
}
cw.visitEnd();
return cw.toByteArray();
}
private static abstract class AbstractMethodDispatchShardCallBack implements ShardingHelper.ShardCallBack {
private final ClassWriter cw;
private final String classType;
private final int maxMethodSize;
public AbstractMethodDispatchShardCallBack(ClassWriter cw, String classType, int maxMethodSize) {
this.cw = cw;
this.classType = classType;
this.maxMethodSize = maxMethodSize;
}
@Override
public void leafDispatch(String suffix, int start, int end) {
MethodVisitor mv;
mv = cw.visitMethod(ACC_PUBLIC, name() + suffix, signature(), null, null);
mv.visitCode();
if (end - start > 0) {
mv.visitVarInsn(ILOAD, argIndex());
appendLeafSwitch(mv, start, end);
}
if (isVoid()) {
mv.visitInsn(RETURN);
} else {
mv.visitInsn(ACONST_NULL);
mv.visitInsn(ARETURN);
}
mv.visitMaxs(1, 2);
mv.visitEnd();
}
protected abstract void appendLeafSwitch(MethodVisitor mv, int start, int end);
@Override
public void nodeDispatch(String suffix, int divide, int start, int end) {
MethodVisitor mv;
mv = cw.visitMethod(ACC_PRIVATE, name() + suffix, signature(), null, null);
mv.visitCode();
Label startLabel = new Label();
mv.visitLabel(startLabel);
final int powerOfTwo = Integer.numberOfTrailingZeros(divide);
int sStart = start >> powerOfTwo;
int sEnd = end >> powerOfTwo;
int left = end - (sEnd << powerOfTwo);
if (left > 0) {
sEnd ++;
}
Label[] labels = newLabels(sEnd - sStart);
Label defaultLabel = new Label();
mv.visitVarInsn(ILOAD, argIndex());
int sub = leafStart();
if (sub != 0) {
AsmUtils.addIndex(mv, sub);
mv.visitInsn(ISUB);
}
AsmUtils.addIndex(mv, powerOfTwo);
mv.visitInsn(ISHR);
mv.visitVarInsn(ISTORE, maxArgIndex() + 1);
mv.visitVarInsn(ILOAD, maxArgIndex() + 1);
mv.visitTableSwitchInsn(sStart, sEnd - 1, defaultLabel, labels);
for (int i = sStart; i < sEnd; i++) {
int estart = i << powerOfTwo;
int eend = Math.min(end, (i+1) << powerOfTwo);
mv.visitLabel(labels[i - sStart]);
if ( i == start) {
mv.visitFrame(Opcodes.F_APPEND, 1, new Object[]{Opcodes.INTEGER}, 0, null);
} else {
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
}
loadArguments(mv);
mv.visitMethodInsn(INVOKESPECIAL, classType, name() + (divide / maxMethodSize) + "n" + estart + "t" + eend, signature(), false);
if (isVoid()) {
if (i < (sEnd - 1)) {
mv.visitJumpInsn(GOTO, defaultLabel);
}
} else {
mv.visitInsn(ARETURN);
}
}
mv.visitLabel(defaultLabel);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
if (isVoid()) {
mv.visitInsn(RETURN);
} else {
mv.visitInsn(ACONST_NULL);
mv.visitInsn(ARETURN);
}
Label endLabel = new Label();
mv.visitLabel(endLabel);
appendDebugInfo(mv, startLabel, endLabel);
mv.visitMaxs(6, 5);
mv.visitEnd();
}
protected int leafStart() {
return 0;
}
protected abstract int maxArgIndex();
protected void appendDebugInfo(MethodVisitor mv, Label startLabel, Label endLabel) {
}
protected abstract void loadArguments(MethodVisitor mv);
protected abstract int argIndex();
private boolean isVoid() {
return signature().endsWith("V");
}
protected abstract String name();
protected abstract String signature();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy