mirror of https://github.com/apache/openjpa.git
OPENJPA-2911 migrate addNewInstance to ASM
This commit is contained in:
parent
4c7c81d249
commit
972b5d0e62
|
@ -107,9 +107,12 @@ import org.apache.xbean.asm9.tree.FieldInsnNode;
|
||||||
import org.apache.xbean.asm9.tree.FieldNode;
|
import org.apache.xbean.asm9.tree.FieldNode;
|
||||||
import org.apache.xbean.asm9.tree.InsnList;
|
import org.apache.xbean.asm9.tree.InsnList;
|
||||||
import org.apache.xbean.asm9.tree.InsnNode;
|
import org.apache.xbean.asm9.tree.InsnNode;
|
||||||
|
import org.apache.xbean.asm9.tree.JumpInsnNode;
|
||||||
|
import org.apache.xbean.asm9.tree.LabelNode;
|
||||||
import org.apache.xbean.asm9.tree.LdcInsnNode;
|
import org.apache.xbean.asm9.tree.LdcInsnNode;
|
||||||
import org.apache.xbean.asm9.tree.MethodInsnNode;
|
import org.apache.xbean.asm9.tree.MethodInsnNode;
|
||||||
import org.apache.xbean.asm9.tree.MethodNode;
|
import org.apache.xbean.asm9.tree.MethodNode;
|
||||||
|
import org.apache.xbean.asm9.tree.TypeInsnNode;
|
||||||
import org.apache.xbean.asm9.tree.VarInsnNode;
|
import org.apache.xbean.asm9.tree.VarInsnNode;
|
||||||
|
|
||||||
import serp.bytecode.BCClass;
|
import serp.bytecode.BCClass;
|
||||||
|
@ -1337,12 +1340,12 @@ public class PCEnhancer {
|
||||||
* least-derived PersistenceCapable type.
|
* least-derived PersistenceCapable type.
|
||||||
*/
|
*/
|
||||||
private void addPCMethods(ClassNodeTracker classNodeTracker) throws NoSuchMethodException {
|
private void addPCMethods(ClassNodeTracker classNodeTracker) throws NoSuchMethodException {
|
||||||
//X addClearFieldsMethod();
|
|
||||||
addClearFieldsMethod(classNodeTracker.getClassNode());
|
addClearFieldsMethod(classNodeTracker.getClassNode());
|
||||||
|
addNewInstanceMethod(classNodeTracker.getClassNode(), true);
|
||||||
|
addNewInstanceMethod(classNodeTracker.getClassNode(), false);
|
||||||
|
|
||||||
AsmHelper.readIntoBCClass(classNodeTracker, _pc);
|
AsmHelper.readIntoBCClass(classNodeTracker, _pc);
|
||||||
|
|
||||||
addNewInstanceMethod(true);
|
|
||||||
addNewInstanceMethod(false);
|
|
||||||
addManagedFieldCountMethod();
|
addManagedFieldCountMethod();
|
||||||
addReplaceFieldsMethods();
|
addReplaceFieldsMethods();
|
||||||
addProvideFieldsMethods();
|
addProvideFieldsMethods();
|
||||||
|
@ -1384,7 +1387,7 @@ public class PCEnhancer {
|
||||||
addGetIDOwningClass();
|
addGetIDOwningClass();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a method to clear all persistent fields; we'll call this from
|
* Add a method to clear all persistent fields; we'll call this from
|
||||||
* the new instance method to ensure that unloaded fields have
|
* the new instance method to ensure that unloaded fields have
|
||||||
|
@ -1448,58 +1451,68 @@ public class PCEnhancer {
|
||||||
* @param oid set to true to mimic the method version that takes
|
* @param oid set to true to mimic the method version that takes
|
||||||
* an oid value as well as a state manager
|
* an oid value as well as a state manager
|
||||||
*/
|
*/
|
||||||
private void addNewInstanceMethod(boolean oid) {
|
private void addNewInstanceMethod(ClassNode classNode, boolean oid) {
|
||||||
// public PersistenceCapable pcNewInstance (...)
|
// public PersistenceCapable pcNewInstance (...)
|
||||||
Class[] args =
|
String desc = oid
|
||||||
(oid) ? new Class[]{ SMTYPE, Object.class, boolean.class }
|
? Type.getMethodDescriptor(Type.getType(PCTYPE), Type.getType(SMTYPE), Type.getType(Object.class), Type.BOOLEAN_TYPE)
|
||||||
: new Class[]{ SMTYPE, boolean.class };
|
: Type.getMethodDescriptor(Type.getType(PCTYPE), Type.getType(SMTYPE), Type.BOOLEAN_TYPE);
|
||||||
BCMethod method = _pc.declareMethod(PRE + "NewInstance", PCTYPE, args);
|
MethodNode newInstance = new MethodNode(Opcodes.ACC_PUBLIC,
|
||||||
Code code = method.getCode(true);
|
PRE + "NewInstance",
|
||||||
|
desc,
|
||||||
|
null, null);
|
||||||
|
classNode.methods.add(newInstance);
|
||||||
|
final InsnList instructions = newInstance.instructions;
|
||||||
|
|
||||||
// if the type is abstract, throw a UserException
|
|
||||||
if (_pc.isAbstract()) {
|
if (_pc.isAbstract()) {
|
||||||
throwException(code, USEREXCEP);
|
instructions.add(throwException(USEREXCEP));
|
||||||
|
|
||||||
code.calculateMaxStack();
|
|
||||||
code.calculateMaxLocals();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX pc = new XXX ();
|
// XXX pc = new XXX ();
|
||||||
code.anew().setType(_pc);
|
instructions.add(new TypeInsnNode(Opcodes.NEW, classNode.name));
|
||||||
code.dup();
|
instructions.add(new InsnNode(Opcodes.DUP));
|
||||||
code.invokespecial().setMethod("<init>", void.class, null);
|
instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
|
||||||
int inst = code.getNextLocalsIndex();
|
classNode.name,
|
||||||
code.astore().setLocal(inst);
|
"<init>",
|
||||||
|
Type.getMethodDescriptor(Type.VOID_TYPE)));
|
||||||
|
|
||||||
|
int newPcVarPos = (oid) ? 4 : 3; // number of params +1
|
||||||
|
instructions.add(new VarInsnNode(Opcodes.ASTORE, newPcVarPos));
|
||||||
|
|
||||||
// if (clear)
|
// if (clear)
|
||||||
// pc.pcClearFields ();
|
// pc.pcClearFields ();
|
||||||
code.iload().setParam((oid) ? 2 : 1);
|
instructions.add(new VarInsnNode(Opcodes.ILOAD, (oid) ? 3 : 2));
|
||||||
JumpInstruction noclear = code.ifeq();
|
LabelNode labelAfterClearFields = new LabelNode();
|
||||||
code.aload().setLocal(inst);
|
instructions.add(new JumpInsnNode(Opcodes.IFEQ, labelAfterClearFields));
|
||||||
code.invokevirtual().setMethod(PRE + "ClearFields", void.class, null);
|
|
||||||
|
// inside the if
|
||||||
|
instructions.add(new VarInsnNode(Opcodes.ALOAD, newPcVarPos));
|
||||||
|
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
|
||||||
|
classNode.name,
|
||||||
|
PRE + "ClearFields",
|
||||||
|
Type.getMethodDescriptor(Type.VOID_TYPE)));
|
||||||
|
|
||||||
|
instructions.add(labelAfterClearFields);
|
||||||
|
|
||||||
// pc.pcStateManager = sm;
|
// pc.pcStateManager = sm;
|
||||||
noclear.setTarget(code.aload().setLocal(inst));
|
instructions.add(new VarInsnNode(Opcodes.ALOAD, newPcVarPos));
|
||||||
code.aload().setParam(0);
|
instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // the 1st method param
|
||||||
code.putfield().setField(SM, SMTYPE);
|
instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, classNode.name, SM, Type.getDescriptor(SMTYPE)));
|
||||||
|
|
||||||
// copy key fields from oid
|
// copy key fields from oid
|
||||||
if (oid) {
|
if (oid) {
|
||||||
code.aload().setLocal(inst);
|
instructions.add(new VarInsnNode(Opcodes.ALOAD, newPcVarPos));
|
||||||
code.aload().setParam(1);
|
instructions.add(new VarInsnNode(Opcodes.ALOAD, 2)); // the 2nd method param, Object
|
||||||
code.invokevirtual().setMethod(PRE + "CopyKeyFieldsFromObjectId",
|
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
|
||||||
void.class, new Class[]{ Object.class });
|
classNode.name,
|
||||||
|
PRE + "CopyKeyFieldsFromObjectId",
|
||||||
|
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Object.class))));
|
||||||
}
|
}
|
||||||
|
|
||||||
// return pc;
|
instructions.add(new VarInsnNode(Opcodes.ALOAD, newPcVarPos));
|
||||||
code.aload().setLocal(inst);
|
instructions.add(new InsnNode(Opcodes.ARETURN));
|
||||||
code.areturn();
|
|
||||||
|
|
||||||
code.calculateMaxStack();
|
|
||||||
code.calculateMaxLocals();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the <code>protected static int pcGetManagedFieldCount ()</code>
|
* Adds the <code>protected static int pcGetManagedFieldCount ()</code>
|
||||||
* method to the bytecode, returning the inherited field count added
|
* method to the bytecode, returning the inherited field count added
|
||||||
|
@ -3061,6 +3074,24 @@ public class PCEnhancer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to add the code necessary to throw the given
|
||||||
|
* exception type, sans message.
|
||||||
|
*/
|
||||||
|
private InsnList throwException(Class type) {
|
||||||
|
InsnList instructions = new InsnList();
|
||||||
|
instructions.add(new TypeInsnNode(Opcodes.NEW, Type.getInternalName(type)));
|
||||||
|
instructions.add(new InsnNode(Opcodes.DUP));
|
||||||
|
instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
|
||||||
|
Type.getInternalName(type),
|
||||||
|
"<init>",
|
||||||
|
Type.getMethodDescriptor(Type.VOID_TYPE)));
|
||||||
|
instructions.add(new InsnNode(Opcodes.ATHROW));
|
||||||
|
|
||||||
|
return instructions;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to add the code necessary to throw the given
|
* Helper method to add the code necessary to throw the given
|
||||||
* exception type, sans message.
|
* exception type, sans message.
|
||||||
|
|
Loading…
Reference in New Issue