use of javassist.bytecode.StackMapTable in project hibernate-orm by hibernate.
the class BulkAccessorFactory method addSetter.
private void addSetter(ClassFile classfile, final Method[] setters) throws CannotCompileException {
final ConstPool constPool = classfile.getConstPool();
final int targetTypeConstPoolIndex = constPool.addClassInfo(this.targetBean.getName());
final String desc = GET_SETTER_DESC;
final MethodInfo setterMethodInfo = new MethodInfo(constPool, GENERATED_SETTER_NAME, desc);
final Bytecode code = new Bytecode(constPool, 4, 6);
StackMapTable stackmap = null;
/* | this | bean | args | i | raw bean | exception | */
if (setters.length > 0) {
// required to exception table
int start;
int end;
// iconst_0 // i
code.addIconst(0);
// istore_3 // store i
code.addIstore(3);
// aload_1 // load the bean
code.addAload(1);
// checkcast // cast the bean into a raw bean
code.addCheckcast(this.targetBean.getName());
// astore 4 // store the raw bean
code.addAstore(4);
/* current stack len = 0 */
// start region to handling exception (BulkAccessorException)
start = code.currentPc();
int lastIndex = 0;
for (int i = 0; i < setters.length; ++i) {
if (setters[i] != null) {
final int diff = i - lastIndex;
if (diff > 0) {
// iinc 3, 1
code.addOpcode(Opcode.IINC);
code.add(3);
code.add(diff);
lastIndex = i;
}
}
/* current stack len = 0 */
// aload 4 // load the raw bean
code.addAload(4);
// aload_2 // load the args
code.addAload(2);
// iconst_i
code.addIconst(i);
// aaload
code.addOpcode(Opcode.AALOAD);
// checkcast
final Class[] setterParamTypes = setters[i].getParameterTypes();
final Class setterParamType = setterParamTypes[0];
if (setterParamType.isPrimitive()) {
// checkcast (case of primitive type)
// invokevirtual (case of primitive type)
this.addUnwrapper(code, setterParamType);
} else {
// checkcast (case of reference type)
code.addCheckcast(setterParamType.getName());
}
/* current stack len = 2 */
final String rawSetterMethodDesc = RuntimeSupport.makeDescriptor(setters[i]);
if (!this.targetBean.isInterface()) {
// invokevirtual
code.addInvokevirtual(targetTypeConstPoolIndex, setters[i].getName(), rawSetterMethodDesc);
} else {
// invokeinterface
final Class[] params = setters[i].getParameterTypes();
int size;
if (params[0].equals(Double.TYPE) || params[0].equals(Long.TYPE)) {
size = 3;
} else {
size = 2;
}
code.addInvokeinterface(targetTypeConstPoolIndex, setters[i].getName(), rawSetterMethodDesc, size);
}
}
// end region to handling exception (BulkAccessorException)
end = code.currentPc();
// return
code.addOpcode(Opcode.RETURN);
/* current stack len = 0 */
// register in exception table
final int throwableTypeIndex = constPool.addClassInfo(THROWABLE_CLASS_NAME);
final int handlerPc = code.currentPc();
code.addExceptionHandler(start, end, handlerPc, throwableTypeIndex);
// astore 5 // store exception
code.addAstore(5);
// new // BulkAccessorException
code.addNew(BULKEXCEPTION_CLASS_NAME);
// dup
code.addOpcode(Opcode.DUP);
// aload 5 // load exception
code.addAload(5);
// iload_3 // i
code.addIload(3);
// invokespecial // BulkAccessorException.<init>
final String consDesc = "(Ljava/lang/Throwable;I)V";
code.addInvokespecial(BULKEXCEPTION_CLASS_NAME, MethodInfo.nameInit, consDesc);
// athrow
code.addOpcode(Opcode.ATHROW);
final StackMapTable.Writer writer = new StackMapTable.Writer(32);
final int[] localTags = { StackMapTable.OBJECT, StackMapTable.OBJECT, StackMapTable.OBJECT, StackMapTable.INTEGER };
final int[] localData = { constPool.getThisClassInfo(), constPool.addClassInfo("java/lang/Object"), constPool.addClassInfo("[Ljava/lang/Object;"), 0 };
final int[] stackTags = { StackMapTable.OBJECT };
final int[] stackData = { throwableTypeIndex };
writer.fullFrame(handlerPc, localTags, localData, stackTags, stackData);
stackmap = writer.toStackMapTable(constPool);
} else {
// return
code.addOpcode(Opcode.RETURN);
}
final CodeAttribute ca = code.toCodeAttribute();
if (stackmap != null) {
ca.setAttribute(stackmap);
}
setterMethodInfo.setCodeAttribute(ca);
setterMethodInfo.setAccessFlags(AccessFlag.PUBLIC);
classfile.addMethod(setterMethodInfo);
}
Aggregations