private void addFieldImplDataMethods(BCClass bc, ClassMetaData meta) {
// public void loadImplData(OpenJPAStateManager sm, int i)
BCMethod meth = bc.declareMethod("loadImplData", void.class,
new Class[]{ OpenJPAStateManager.class, int.class });
meth.makePrivate();
Code code = meth.getCode(true);
int count = countImplDataFields(meta);
BCField impl = null;
if (count == 0)
code.vreturn();
else {
// Object[] fieldImpl
impl = bc.declareField("fieldImpl", Object[].class);
impl.makePrivate();
// if (fieldImpl != null)
code.aload().setThis();
code.getfield().setField(impl);
JumpInstruction ifins = code.ifnonnull();
code.vreturn();
// Object obj = null;
int obj = code.getNextLocalsIndex();
ifins.setTarget(code.constant().setNull());
code.astore().setLocal(obj);
// establish switch target, then move before it
Instruction target = code.aload().setLocal(obj);
code.previous();
// switch(i)
code.iload().setParam(1);
LookupSwitchInstruction lswitch = code.lookupswitch();
FieldMetaData[] fields = meta.getFields();
int cacheable = 0;
for (int i = 0; i < fields.length; i++) {
if (!usesImplData(fields[i]))
continue;
// case x: obj = fieldImpl[y]; break;
lswitch.addCase(i, code.aload().setThis());
code.getfield().setField(impl);
code.constant().setValue(cacheable++);
code.aaload();
code.astore().setLocal(obj);
code.go2().setTarget(target);
}
lswitch.setDefaultTarget(target);
// if (obj != null)
code.next(); // jump back over target
ifins = code.ifnonnull();
code.vreturn();
// sm.setImplData(index, impl);
ifins.setTarget(code.aload().setParam(0));
code.iload().setParam(1);
code.aload().setLocal(obj);
code.invokeinterface().setMethod(OpenJPAStateManager.class,
"setImplData", void.class,
new Class[]{ int.class, Object.class });
code.vreturn();
}
code.calculateMaxLocals();
code.calculateMaxStack();
// void storeImplData(OpenJPAStateManager sm, int index, boolean loaded)
meth = bc.declareMethod("storeImplData", void.class,
new Class[]{ OpenJPAStateManager.class, int.class, boolean.class });
code = meth.getCode(true);
if (count == 0)
code.vreturn();
else {
// int arrIdx = -1;
// switch(index)
int arrIdx = code.getNextLocalsIndex();
code.constant().setValue(-1);
code.istore().setLocal(arrIdx);
code.iload().setParam(1);
LookupSwitchInstruction lswitch = code.lookupswitch();
// establish switch target, then move before it
Instruction switchTarget = code.iload().setLocal(arrIdx);
code.previous();
FieldMetaData[] fields = meta.getFields();
int cacheable = 0;
for (int i = 0; i < fields.length; i++) {
if (!usesImplData(fields[i]))
continue;
// case x: arrIdx = y; break;
lswitch.addCase(i, code.constant().setValue(cacheable++));
code.istore().setLocal(arrIdx);
code.go2().setTarget(switchTarget);
}
lswitch.setDefaultTarget(switchTarget);
code.next(); // step over switch target
// if (arrIdx != -1)
code.constant().setValue(-1);
JumpInstruction ifins = code.ificmpne();
code.vreturn();
// create null target, then move before it
Instruction nullTarget = code.aload().setThis();
code.previous();
// if (loaded)
ifins.setTarget(code.iload().setParam(2));
code.ifeq().setTarget(nullTarget);
// Object obj = sm.getImplData(index)
int obj = code.getNextLocalsIndex();
code.aload().setParam(0);
code.iload().setParam(1);
code.invokeinterface().setMethod(OpenJPAStateManager.class,
"getImplData", Object.class, new Class[]{ int.class });
code.astore().setLocal(obj);
// if (obj != null)
code.aload().setLocal(obj);
code.ifnull().setTarget(nullTarget);
// if (fieldImpl == null)
// fieldImpl = new Object[fields];
code.aload().setThis();
code.getfield().setField(impl);
ifins = code.ifnonnull();
code.aload().setThis();
code.constant().setValue(count);
code.anewarray().setType(Object.class);
code.putfield().setField(impl);
// fieldImpl[arrIdx] = obj;
// return;
ifins.setTarget(code.aload().setThis());
code.getfield().setField(impl);
code.iload().setLocal(arrIdx);
code.aload().setLocal(obj);
code.aastore();
code.vreturn();
// if (fieldImpl != null)
// fieldImpl[index] = null;
code.next(); // step over nullTarget
code.getfield().setField(impl);
ifins = code.ifnonnull();
code.vreturn();
ifins.setTarget(code.aload().setThis());
code.getfield().setField(impl);
code.iload().setLocal(arrIdx);
code.constant().setNull();
code.aastore();
code.vreturn();
}
code.calculateMaxStack();
code.calculateMaxLocals();
}