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 <strub...@apache.org>
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

Reply via email to