in openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCDataGenerator.java [365:558]
private void addFieldImplDataMethods(ClassNodeTracker cnt, ClassMetaData meta) {
ClassNode classNode = cnt.getClassNode();
int count = countImplDataFields(meta);
FieldNode impl = null;
// public void loadImplData(OpenJPAStateManager sm, int i)
{
MethodNode meth = new MethodNode(Opcodes.ACC_PRIVATE,
"loadImplData",
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(OpenJPAStateManager.class), Type.INT_TYPE),
null, null);
classNode.methods.add(meth);
InsnList instructions = meth.instructions;
if (count == 0) {
instructions.add(new InsnNode(Opcodes.RETURN));
}
else {
// Object[] fieldImpl
impl = new FieldNode(Opcodes.ACC_PRIVATE, "fieldImpl", Type.getDescriptor(Object[].class), null, null);
classNode.fields.add(impl);
// if (fieldImpl != null)
instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
instructions.add(new FieldInsnNode(Opcodes.GETFIELD, classNode.name, impl.name, impl.desc));
LabelNode lblEndIf = new LabelNode();
instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, lblEndIf));
instructions.add(new InsnNode(Opcodes.RETURN));
instructions.add(lblEndIf);
// Object obj = null;
int objVarPos = AsmHelper.getLocalVarPos(meth);
instructions.add(new InsnNode(Opcodes.ACONST_NULL));
instructions.add(new VarInsnNode(Opcodes.ASTORE, objVarPos));
LabelNode lblEnd = new LabelNode();
instructions.add(new VarInsnNode(Opcodes.ILOAD, 2));
// switch(i)
LookupSwitchInsnNode lSwitch = new LookupSwitchInsnNode(lblEnd, null, null);
FieldMetaData[] fields = meta.getFields();
int cacheable = 0;
for (int i = 0; i < fields.length; i++) {
if (!usesImplData(fields[i])) {
continue;
}
// case x: obj = fieldImpl[y]; break;
LabelNode lblCase = new LabelNode();
instructions.add(lblCase);
lSwitch.keys.add(i);
lSwitch.labels.add(lblCase);
instructions.add(new FieldInsnNode(Opcodes.GETFIELD, classNode.name, impl.name, impl.desc));
instructions.add(AsmHelper.getLoadConstantInsn(cacheable++));
instructions.add(new InsnNode(Opcodes.AALOAD));
instructions.add(new VarInsnNode(Opcodes.ASTORE, objVarPos));
instructions.add(new JumpInsnNode(Opcodes.GOTO, lblEnd));
}
// 'default:' is empty
instructions.add(lblEnd);
instructions.add(new VarInsnNode(Opcodes.ALOAD, objVarPos));
// if (obj != null) return;
lblEndIf = new LabelNode();
instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, lblEndIf));
instructions.add(new InsnNode(Opcodes.RETURN));
// end if
instructions.add(lblEndIf);
// sm.setImplData(index, impl);
instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 1st parameter OpenJPAStateManager
instructions.add(new VarInsnNode(Opcodes.ILOAD, 2)); // 2nd parameter int
instructions.add(new VarInsnNode(Opcodes.ALOAD, objVarPos)); // the previously stored fieldImpl
instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
Type.getInternalName(OpenJPAStateManager.class),
"setImplData",
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE, AsmHelper.TYPE_OBJECT)));
instructions.add(new InsnNode(Opcodes.RETURN));
}
}
// void storeImplData(OpenJPAStateManager sm, int index, boolean loaded)
{
MethodNode meth = new MethodNode(Opcodes.ACC_PRIVATE,
"storeImplData",
Type.getMethodDescriptor(Type.VOID_TYPE,
Type.getType(OpenJPAStateManager.class), Type.INT_TYPE, Type.BOOLEAN_TYPE),
null, null);
classNode.methods.add(meth);
InsnList instructions = meth.instructions;
if (count == 0) {
instructions.add(new InsnNode(Opcodes.RETURN));
}
else {
// int arrIdx = -1;
// switch(index)
int arrIdxVarPos = AsmHelper.getLocalVarPos(meth);
instructions.add(AsmHelper.getLoadConstantInsn(-1));
instructions.add(new VarInsnNode(Opcodes.ISTORE, arrIdxVarPos));
instructions.add(new VarInsnNode(Opcodes.ILOAD, 2)); // 2nd param int
LabelNode lblEnd = new LabelNode();
// switch(i)
LookupSwitchInsnNode lSwitch = new LookupSwitchInsnNode(lblEnd, null, null);
FieldMetaData[] fields = meta.getFields();
int cacheable = 0;
for (int i = 0; i < fields.length; i++) {
if (!usesImplData(fields[i])) {
continue;
}
// case x: arrIdx = y; break;
LabelNode lblCase = new LabelNode();
instructions.add(lblCase);
lSwitch.keys.add(i);
lSwitch.labels.add(lblCase);
instructions.add(AsmHelper.getLoadConstantInsn(cacheable++));
instructions.add(new VarInsnNode(Opcodes.ISTORE, arrIdxVarPos));
instructions.add(new JumpInsnNode(Opcodes.GOTO, lblEnd));
}
// 'default:' is empty
instructions.add(lblEnd);
// if (arrIdx != -1)
instructions.add(AsmHelper.getLoadConstantInsn(-1));
LabelNode lblEndIf = new LabelNode();
instructions.add(new JumpInsnNode(Opcodes.IF_ICMPNE, lblEndIf));
instructions.add(new InsnNode(Opcodes.RETURN));
// end if
instructions.add(lblEndIf);
// if (loaded)
instructions.add(new VarInsnNode(Opcodes.ILOAD, 3)); // 3rd param, boolean
lblEndIf = new LabelNode();
instructions.add(new JumpInsnNode(Opcodes.IFEQ, lblEndIf));
// Object obj = sm.getImplData(index)
int objVarPos = arrIdxVarPos+1;
instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 1st param, OpenJPAStateManager
instructions.add(new VarInsnNode(Opcodes.ILOAD, 2)); // 2st param, int
instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
Type.getInternalName(OpenJPAStateManager.class),
"getImplData",
Type.getMethodDescriptor(AsmHelper.TYPE_OBJECT, Type.INT_TYPE)));
instructions.add(new VarInsnNode(Opcodes.ASTORE, objVarPos));
// if (fieldImpl == null)
// fieldImpl = new Object[fields];
instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
instructions.add(new FieldInsnNode(Opcodes.GETFIELD, classNode.name, impl.name, impl.desc));
LabelNode lblEndIfNN = new LabelNode();
instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, lblEndIfNN));
instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
instructions.add(AsmHelper.getLoadConstantInsn(count));
instructions.add(new TypeInsnNode(Opcodes.ANEWARRAY, Type.getInternalName(Object.class)));
instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, classNode.name, impl.name, impl.desc));
instructions.add(lblEndIfNN);
// fieldImpl[arrIdx] = obj;
// return;
instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
instructions.add(new FieldInsnNode(Opcodes.GETFIELD, classNode.name, impl.name, impl.desc));
instructions.add(new VarInsnNode(Opcodes.ILOAD, arrIdxVarPos));
instructions.add(new VarInsnNode(Opcodes.ALOAD, objVarPos));
instructions.add(new InsnNode(Opcodes.AASTORE));
instructions.add(new InsnNode(Opcodes.RETURN));
instructions.add(lblEndIf);
// if (fieldImpl != null)
// fieldImpl[index] = null;
instructions.add(new FieldInsnNode(Opcodes.GETFIELD, classNode.name, impl.name, impl.desc));
lblEndIfNN = new LabelNode();
instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, lblEndIfNN));
instructions.add(new InsnNode(Opcodes.RETURN));
instructions.add(lblEndIfNN);
instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
instructions.add(new FieldInsnNode(Opcodes.GETFIELD, classNode.name, impl.name, impl.desc));
instructions.add(new VarInsnNode(Opcodes.ILOAD, arrIdxVarPos));
instructions.add(new InsnNode(Opcodes.ACONST_NULL));
instructions.add(new InsnNode(Opcodes.AASTORE));
instructions.add(new InsnNode(Opcodes.RETURN));
}
}
}