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 7700fdfd4 OPENJPA-2911 DetachedState as ASM 7700fdfd4 is described below commit 7700fdfd45d0f1995d7e4592d5a8c6c713c05faa Author: Mark Struberg <strub...@apache.org> AuthorDate: Wed Jul 12 11:05:04 2023 +0200 OPENJPA-2911 DetachedState as ASM --- .../org/apache/openjpa/enhance/PCEnhancer.java | 85 +++++++++++----------- 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java index 483f05aa3..2ff67b469 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java @@ -1687,7 +1687,7 @@ public class PCEnhancer { // pcVersionInit = true; instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this instructions.add(new InsnNode(Opcodes.ICONST_1)); - putfield(instructions, getType(_meta), VERSION_INIT_STR, boolean.class); + putfield(classNode, instructions, getType(_meta), VERSION_INIT_STR, boolean.class); } instructions.add(new InsnNode(Opcodes.RETURN)); @@ -4633,13 +4633,10 @@ public class PCEnhancer { // accessor methods if (_meta.getPCSuperclass() == null || getCreateSubclass() || parentDetachable != _meta.isDetachable()) { addIsDetachedMethod(classNode); - AsmHelper.readIntoBCClass(pc, _pc); - addDetachedStateMethods(_meta.usesDetachedState() != Boolean.FALSE); } - else { - AsmHelper.readIntoBCClass(pc, _pc); - } + + AsmHelper.readIntoBCClass(pc, _pc); // if we detach on serialize, we also need to implement the // externalizable interface to write just the state for the fields @@ -4662,54 +4659,55 @@ public class PCEnhancer { private void addDetachedStateMethods(boolean impl) { Field detachField = _meta.getDetachedStateField(); String name = null; - String declarer = null; + Class<?> declarer = null; + final ClassNode classNode = pc.getClassNode(); + + if (impl && detachField == null) { name = PRE + "DetachedState"; - declarer = _pc.getName(); - BCField field = _pc.declareField(name, Object.class); - field.makePrivate(); - field.setTransient(true); + FieldNode field = new FieldNode(Opcodes.ACC_PRIVATE | Opcodes.ACC_TRANSIENT, + name, + TYPE_OBJECT.getDescriptor(), + null, null); + classNode.fields.add(field); } else if (impl) { name = detachField.getName(); - declarer = detachField.getDeclaringClass().getName(); + declarer = detachField.getDeclaringClass(); } // public Object pcGetDetachedState () - BCMethod method = _pc.declareMethod(PRE + "GetDetachedState", - Object.class, null); - method.setStatic(false); - method.makePublic(); - int access = method.getAccessFlags(); + MethodNode getDetachedStateMeth = new MethodNode(Opcodes.ACC_PUBLIC, + PRE + "GetDetachedState", + Type.getMethodDescriptor(TYPE_OBJECT), + null, null); + classNode.methods.add(getDetachedStateMeth); - Code code = method.getCode(true); if (impl) { // return pcDetachedState; - loadManagedInstance(code, false); - getfield(code, _managedType.getProject().loadClass(declarer), - name); + getDetachedStateMeth.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this + getfield(classNode, getDetachedStateMeth.instructions, declarer, name, Object.class); } - else - code.constant().setNull(); - code.areturn(); - code.calculateMaxLocals(); - code.calculateMaxStack(); + else { + getDetachedStateMeth.instructions.add(new InsnNode(Opcodes.ACONST_NULL)); + } + getDetachedStateMeth.instructions.add(new InsnNode(Opcodes.ARETURN)); + // public void pcSetDetachedState (Object state) - method = _pc.declareMethod(PRE + "SetDetachedState", - void.class, new Class[]{Object.class}); - method.setAccessFlags(access); - code = method.getCode(true); + MethodNode setDetachedStateMeth = new MethodNode(Opcodes.ACC_PUBLIC, + PRE + "SetDetachedState", + Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_OBJECT), + null, null); + classNode.methods.add(setDetachedStateMeth); + if (impl) { // pcDetachedState = state; - loadManagedInstance(code, false); - code.aload().setParam(0); - putfield(code, _managedType.getProject().loadClass(declarer), - name, Object.class); + setDetachedStateMeth.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this + setDetachedStateMeth.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 1st parameter + putfield(classNode, setDetachedStateMeth.instructions, declarer, name, Object.class); } - code.vreturn(); - code.calculateMaxStack(); - code.calculateMaxLocals(); + setDetachedStateMeth.instructions.add(new InsnNode(Opcodes.RETURN)); } /** @@ -4859,9 +4857,11 @@ public class PCEnhancer { * When this method is invoked, the value to load must * already be on the top of the stack, * and the instance to load into must be second. - * @param declarer internal class name (org/bla/..) which contains the field + * + * @param classNode + * @param declarer internal class name (org/bla/..) which contains the field */ - private void putfield(InsnList instructions, Class declarer, String attrName, Class fieldType) { + private void putfield(ClassNode classNode, InsnList instructions, Class declarer, String attrName, Class fieldType) { String fieldName = toBackingFieldName(attrName); if (getRedefine() || getCreateSubclass()) { @@ -4889,7 +4889,8 @@ public class PCEnhancer { } else { - instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, Type.getInternalName(declarer), fieldName, Type.getDescriptor(fieldType))); + String owner = declarer != null ? Type.getInternalName(declarer) : classNode.name; + instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, owner, fieldName, Type.getDescriptor(fieldType))); } } @@ -5486,7 +5487,7 @@ public class PCEnhancer { // just do a subclass approach instead. But this is not a good option, // since it would sacrifice lazy loading and efficient dirty tracking. if (getRedefine() || isFieldAccess(fmd)) { - putfield(instructions, fmd.getDeclaringType(), fmd.getName(), fmd.getDeclaredType()); + putfield(classNode, instructions, fmd.getDeclaringType(), fmd.getName(), fmd.getDeclaredType()); } else if (getCreateSubclass()) { // property access, and we're not redefining. invoke the @@ -5520,7 +5521,7 @@ public class PCEnhancer { // just do a subclass approach instead. But this is not a good option, // since it would sacrifice lazy loading and efficient dirty tracking. if (getRedefine() || isFieldAccess(fmd)) { - putfield(instructions, getType(_meta), fmd.getName(), fmd.getDeclaredType()); + putfield(classNode, instructions, getType(_meta), fmd.getName(), fmd.getDeclaredType()); } else if (getCreateSubclass()) { // property access, and we're not redefining. invoke the