private static <T> void append_cellValue( final DelayedCellSetterFactory<T, ?>[] delayedCellSetters, final CellSetter<T>[] setters, ClassWriter cw, final String classType, final int maxMethodSize) { ShardingHelper.shard( setters.length, maxMethodSize, new AbstractMethodDispatchShardCallBack<T>(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 <T> void appendInit( DelayedCellSetterFactory<T, ?>[] delayedCellSetters, CellSetter<T>[] setters, ClassWriter cw, String targetType, String classType, int maxSize) { MethodVisitor mv; // constructor { mv = cw.visitMethod( ACC_PUBLIC, "<init>", "(" + 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" + AsmUtils.toType(CsvMapperCellHandler.class) + "<L" + targetType + ";>;L" + targetType + ";>;" + "[L" + DELAYED_CELL_SETTER_TYPE + "<L" + targetType + ";*>;" + "[L" + CELL_SETTER_TYPE + "<L" + targetType + ";>;" + AsmUtils.toDeclaredLType(CsvColumnKey[].class) + AsmUtils.toDeclaredLType(ParsingContext.class) + "L" + AsmUtils.toType(FieldMapperErrorHandler.class) + "<L" + AsmUtils.toType(CsvColumnKey.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, "<init>", "(" + 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 <T> void append_delayedCellValue( final DelayedCellSetterFactory<T, ?>[] delayedCellSetters, final ClassWriter cw, final String classType, final int maxMethodSize) { ShardingHelper.shard( delayedCellSetters.length, maxMethodSize, new AbstractMethodDispatchShardCallBack<T>(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 <T> void appendApplyDelayedSetter( final DelayedCellSetterFactory<T, ?>[] 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 <T> void appendPeekDelayedCellSetterValue( final DelayedCellSetterFactory<T, ?>[] delayedCellSetters, final ClassWriter cw, final String classType, final int maxMethodSize) { ShardingHelper.shard( delayedCellSetters.length, maxMethodSize, new AbstractMethodDispatchShardCallBack<T>(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(); }