This is an automated email from the ASF dual-hosted git repository.
struberg pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openjpa.git
The following commit(s) were added to refs/heads/master by this push:
new 07edae25b OPENJPA-2911 addLoadWithFieldsMethod via ASM
07edae25b is described below
commit 07edae25bf11bd496fcc94bebbc57cd5f6e27f75
Author: Mark Struberg <[email protected]>
AuthorDate: Mon Jul 24 22:55:59 2023 +0200
OPENJPA-2911 addLoadWithFieldsMethod via ASM
---
.../apache/openjpa/enhance/PCDataGenerator.java | 244 +++++++--------------
1 file changed, 79 insertions(+), 165 deletions(-)
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCDataGenerator.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCDataGenerator.java
index e9f4e2acd..a2cbe55fc 100644
---
a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCDataGenerator.java
+++
b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCDataGenerator.java
@@ -174,11 +174,11 @@ public class PCDataGenerator extends
DynamicStorageGenerator {
addVersionMethods(bc);
addFieldImplDataMethods(bc, meta);
addLoadMethod(bc, meta);
+ addLoadWithFieldsMethod(bc, meta);
BCClass _bc = new
Project().loadClass(bc.getClassNode().name.replace("/", "."));
AsmHelper.readIntoBCClass(bc, _bc);
- addLoadWithFieldsMethod(_bc, meta);
addStoreMethods(_bc, meta);
addNewEmbedded(_bc);
addGetData(_bc);
@@ -648,7 +648,6 @@ public class PCDataGenerator extends
DynamicStorageGenerator {
boolean intermediate;
LabelNode lblEndIf = null;
for (int i = 0; i < fmds.length; i++) {
-
if (lblEndIf != null) {
instructions.add(lblEndIf);
}
@@ -710,72 +709,103 @@ public class PCDataGenerator extends
DynamicStorageGenerator {
instructions.add(new InsnNode(Opcodes.RETURN));
}
- private void addLoadWithFieldsMethod(BCClass bc, ClassMetaData meta) {
- Code code = addLoadMethod(bc, true);
- // public void load(OpenJPAStateManager sm, BitSet fields,
- // FetchConfiguration fetch, Object conn)
+ private void addLoadWithFieldsMethod(ClassNodeTracker cnt, ClassMetaData
meta) {
+ final ClassNode classNode = cnt.getClassNode();
+
+ // public void load(OpenJPAStateManager sm, BitSet fields,
FetchConfiguration fetch, Object conn)
+ MethodNode meth = addLoadMethod(cnt, true);
+ InsnList instructions = meth.instructions;
+
FieldMetaData[] fmds = meta.getFields();
- Collection<Instruction> jumps = new LinkedList<>();
- Collection<Instruction> jumps2;
+
+ int localVarPos = AsmHelper.getLocalVarPos(meth);
+ instructions.add(new InsnNode(Opcodes.ACONST_NULL));
+ instructions.add(new VarInsnNode(Opcodes.ASTORE, localVarPos));
+ int interVarPos = localVarPos + 1;
+ instructions.add(new InsnNode(Opcodes.ACONST_NULL));
+ instructions.add(new VarInsnNode(Opcodes.ASTORE, interVarPos));
+
int objectCount = 0;
boolean intermediate;
- int local = code.getNextLocalsIndex();
- code.constant().setNull();
- code.astore().setLocal(local);
- int inter = code.getNextLocalsIndex();
- code.constant().setNull();
- code.astore().setLocal(inter);
-
+ LabelNode lblEndIf = null;
for (int i = 0; i < fmds.length; i++) {
- jumps2 = new LinkedList<>();
+ if (lblEndIf != null) {
+ instructions.add(lblEndIf);
+ }
+ lblEndIf = new LabelNode();
+
intermediate = usesIntermediate(fmds[i]);
+
// if (fields.get(i))
// {
// if (loaded.get(i))
- setTarget(code.aload().setParam(1), jumps);
- code.constant().setValue(i);
- code.invokevirtual().setMethod(BitSet.class, "get",
- boolean.class, new Class[]{ int.class });
- jumps2.add(code.ifeq());
- code.aload().setThis();
- code.getfield().setField("loaded", BitSet.class);
- code.constant().setValue(i);
- code.invokevirtual().setMethod(BitSet.class, "get",
- boolean.class, new Class[]{ int.class });
- if (intermediate)
- jumps.add(code.ifeq());
- else
- jumps2.add(code.ifeq());
+ instructions.add(new VarInsnNode(Opcodes.ALOAD, 2)); // 2nd param,
BitSet
+ instructions.add(AsmHelper.getLoadConstantInsn(i));
+ instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+
Type.getInternalName(BitSet.class),
+ "get",
+
Type.getMethodDescriptor(Type.BOOLEAN_TYPE, Type.INT_TYPE)));
+
+ instructions.add(new JumpInsnNode(Opcodes.IFEQ, lblEndIf));
+ instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+ instructions.add(new FieldInsnNode(Opcodes.GETFIELD,
classNode.name, "loaded", Type.getDescriptor(BitSet.class)));
+ instructions.add(AsmHelper.getLoadConstantInsn(i));
+ instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+
Type.getInternalName(BitSet.class),
+ "get",
+
Type.getMethodDescriptor(Type.BOOLEAN_TYPE, Type.INT_TYPE)));
+
+ LabelNode lblEndIf2 = null;
+ if (intermediate) {
+ // nested if/else. Thus we need another jump target
+ lblEndIf2 = new LabelNode();
+ instructions.add(new JumpInsnNode(Opcodes.IFEQ, lblEndIf2));
+ }
+ else {
+ instructions.add(new JumpInsnNode(Opcodes.IFEQ, lblEndIf));
+ }
+
+ addLoad(classNode, instructions, fmds[i], objectCount,
localVarPos, true);
- addLoad(bc, code, fmds[i], objectCount, local, true);
if (usesImplData(fmds[i])) {
// loadImplData(sm, i);
- code.aload().setThis();
- code.aload().setParam(0);
- code.constant().setValue(i);
- code.invokevirtual().setMethod("loadImplData", void.class,
- new Class[]{ OpenJPAStateManager.class, int.class });
+ instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+ instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 1st
param, OpenJPAStateManager
+ instructions.add(AsmHelper.getLoadConstantInsn(i));
+ instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+ classNode.name,
+ "loadImplData",
+
Type.getMethodDescriptor(Type.VOID_TYPE,
+
Type.getType(OpenJPAStateManager.class), Type.INT_TYPE)));
}
// fields.clear(i);
- code.aload().setParam(1);
- code.constant().setValue(i);
- code.invokevirtual().setMethod(BitSet.class, "clear", void.class,
- new Class[] { int.class });
+ instructions.add(new VarInsnNode(Opcodes.ALOAD, 2)); // 2nd param,
BitSet
+ instructions.add(AsmHelper.getLoadConstantInsn(i));
+ instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+
Type.getInternalName(BitSet.class),
+ "clear",
+
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE)));
- jumps2.add(code.go2());
+ if (intermediate) {
+ instructions.add(new JumpInsnNode(Opcodes.GOTO, lblEndIf));
- if (intermediate)
- setTarget(addLoadIntermediate
- (code, i, objectCount, jumps2, inter), jumps);
+ // else part
+ instructions.add(lblEndIf2);
+ addLoadIntermediate(classNode, instructions, i, objectCount,
interVarPos);
+ }
- jumps = jumps2;
- if (replaceType(fmds[i]) >= JavaTypes.OBJECT)
+ if (replaceType(fmds[i]) >= JavaTypes.OBJECT) {
objectCount++;
+ }
}
- setTarget(code.vreturn(), jumps);
- code.calculateMaxStack();
- code.calculateMaxLocals();
+
+ if (lblEndIf != null) {
+ instructions.add(lblEndIf);
+ }
+
+ instructions.add(new InsnNode(Opcodes.RETURN));
+
}
/**
@@ -1210,122 +1240,6 @@ public class PCDataGenerator extends
DynamicStorageGenerator {
return strings;
}
- /**
- * Declare and start the base load method.
- */
- @Deprecated
- private Code addLoadMethod(BCClass bc, boolean fields) {
- Class<?>[] args = null;
- if (fields)
- args = new Class[]{ OpenJPAStateManager.class, BitSet.class,
- FetchConfiguration.class, Object.class };
- else
- args = new Class[]{ OpenJPAStateManager.class,
- FetchConfiguration.class, Object.class };
- BCMethod load = bc.declareMethod("load", void.class, args);
- Code code = load.getCode(true);
-
- //loadVersion(sm);
- code.aload().setThis();
- code.aload().setParam(0);
- code.invokevirtual().setMethod("loadVersion", void.class,
- new Class[]{ OpenJPAStateManager.class
});
-
- //loadImplData(sm);
- code.aload().setThis();
- code.aload().setParam(0);
- code.invokevirtual().setMethod("loadImplData", void.class,
- new Class[]{ OpenJPAStateManager.class
});
- return code;
- }
-
-
- /**
- * Add the field load.
- */
- private Instruction addLoad(BCClass bc, Code code, FieldMetaData fmd,
- int objectCount, int local, boolean fields) {
- int index = fmd.getIndex();
- int typeCode = replaceType(fmd);
- Instruction first;
- if (typeCode < JavaTypes.OBJECT) {
- // sm.store<type>(i, field<i>)
- Class<?> type = forType(fmd.getTypeCode());
- first = code.aload().setParam(0);
- code.constant().setValue(index);
- code.aload().setThis();
- code.getfield().setField(getFieldName(index), type);
- code.invokeinterface().setMethod(OpenJPAStateManager.class,
- "store" +
StringUtil.capitalize(type.getName()),
- void.class, new Class[]{
int.class, type });
- } else {
- // fmd = sm.getMetaData().getField(i);
- int offset = fields ? 1 : 0;
- first = code.aload().setParam(0);
- code.invokeinterface().setMethod(OpenJPAStateManager.class,
- "getMetaData",
ClassMetaData.class, null);
- code.constant().setValue(fmd.getIndex());
- code.invokevirtual().setMethod(ClassMetaData.class, "getField",
- FieldMetaData.class, new Class[]{
int.class });
- code.astore().setLocal(local);
- // sm.storeField(i, toField(sm, fmd, objects[objectCount],
- // fetch, context);
- code.aload().setParam(0);
- code.constant().setValue(index);
- code.aload().setThis();
- code.aload().setParam(0);
- code.aload().setLocal(local);
- code.aload().setThis();
- code.getfield().setField("objects", Object[].class);
- code.constant().setValue(objectCount);
- code.aaload();
- code.aload().setParam(1 + offset);
- code.aload().setParam(2 + offset);
- code.invokevirtual().setMethod(bc.getName(), "toField",
- Object.class.getName(),
toStrings(new Class[]{
- OpenJPAStateManager.class, FieldMetaData.class,
- Object.class, FetchConfiguration.class,
Object.class }));
- code.invokeinterface().setMethod(OpenJPAStateManager.class,
- "storeField", void.class,
- new Class[]{ int.class,
Object.class });
- }
- return first;
- }
-
- /**
- * Load intermediate data if possible.
- */
- @Deprecated
- private Instruction addLoadIntermediate(Code code, int index,
- int objectCount,
Collection<Instruction> jumps2, int inter) {
- // {
- // Object inter = objects[objectCount];
- Instruction first = code.aload().setThis();
- code.getfield().setField("objects", Object[].class);
- code.constant().setValue(objectCount);
- code.aaload();
- code.astore().setLocal(inter);
- // if (inter != null && !sm.getLoaded().get(index))
- code.aload().setLocal(inter);
- jumps2.add(code.ifnull());
- code.aload().setParam(0);
- code.invokeinterface().setMethod(OpenJPAStateManager.class,
- "getLoaded", BitSet.class, null);
- code.constant().setValue(index);
- code.invokevirtual().setMethod(BitSet.class, "get",
- boolean.class, new Class[]{ int.class
});
- jumps2.add(code.ifne());
- // sm.setIntermediate(index, inter);
- // } // end else
- code.aload().setParam(0);
- code.constant().setValue(index);
- code.aload().setLocal(inter);
- code.invokeinterface().setMethod(OpenJPAStateManager.class,
- "setIntermediate", void.class,
- new Class[]{ int.class, Object.class
});
- return first;
- }
-
/**
* Dynamic {@link PCData}s generated will implement this interface