// of the outlined method, create a field in the
// CopyLocals class, and generate the necessary code for
// copying the value.
if (copyInLocalValue || copyOutLocalValue) {
String varName = oldLVG.getName();
Type varType = oldLVG.getType();
newLVG = outlinedMethodGen.addLocalVariable(varName,
varType,
null,
null);
int newLocalVarIndex = newLVG.getIndex();
String varSignature = varType.getSignature();
// Record the mapping from the old local to the new
localVarMap.put(oldLVG, newLVG);
copyAreaFieldCount++;
String copyAreaFieldName =
"field" + copyAreaFieldCount;
copyAreaCG.addField(
new Field(ACC_PUBLIC,
copyAreaCPG.addUtf8(copyAreaFieldName),
copyAreaCPG.addUtf8(varSignature),
null, copyAreaCPG.getConstantPool()));
int fieldRef = cpg.addFieldref(argTypeName,
copyAreaFieldName,
varSignature);
if (copyInLocalValue) {
// Generate code for the old method to store the
// value of the local into the correct field in
// CopyLocals prior to invocation of the
// outlined method.
oldMethCopyInIL.append(
InstructionConstants.DUP);
InstructionHandle copyInLoad =
oldMethCopyInIL.append(
loadLocal(oldLocalVarIndex, varType));
oldMethCopyInIL.append(new PUTFIELD(fieldRef));
// If the end of the live range of the old
// variable was in the middle of the outlined
// chunk. Make the load of its value the new
// end of its range.
if (!copyOutLocalValue) {
revisedLocalVarEnd.put(oldLVG, copyInLoad);
}
// Generate code for start of the outlined
// method to copy the value from a field in
// CopyLocals to the new local in the outlined
// method
newMethCopyInIL.append(
InstructionConstants.ALOAD_1);
newMethCopyInIL.append(new GETFIELD(fieldRef));
newMethCopyInIL.append(
storeLocal(newLocalVarIndex, varType));
}
if (copyOutLocalValue) {
// Generate code for the end of the outlined
// method to copy the value from the new local
// variable into a field in CopyLocals
// method
newMethCopyOutIL.append(
InstructionConstants.ALOAD_1);
newMethCopyOutIL.append(
loadLocal(newLocalVarIndex, varType));
newMethCopyOutIL.append(new PUTFIELD(fieldRef));
// Generate code to copy the value from a field
// in CopyLocals into a local in the original
// method following invocation of the outlined
// method.
oldMethCopyOutIL.append(
InstructionConstants.DUP);
oldMethCopyOutIL.append(new GETFIELD(fieldRef));
InstructionHandle copyOutStore =
oldMethCopyOutIL.append(
storeLocal(oldLocalVarIndex, varType));
// If the start of the live range of the old
// variable was in the middle of the outlined
// chunk. Make this store into it the new start
// of its range.
if (!copyInLocalValue) {
revisedLocalVarStart.put(oldLVG,
copyOutStore);
}
}
}
}
}
if (ih.hasTargeters()) {
targetMap.put(ih, lastCopyHandle);
}
// If this is the first instruction copied following a sequence
// of OutlineableChunkStart instructions, indicate that the
// sequence of old instruction all map to this newly created
// instruction
if (chunkStartTargetMappingsPending) {
do {
targetMap.put(pendingTargetMappingHandle,
lastCopyHandle);
pendingTargetMappingHandle =
pendingTargetMappingHandle.getNext();
} while(pendingTargetMappingHandle != ih);
chunkStartTargetMappingsPending = false;
}
}
}
// Pass 2: Walk old and new instruction lists, updating branch targets
// and local variable references in the new list
InstructionHandle ih = first;
InstructionHandle ch = newIL.getStart();
while (ch != null) {
// i == old instruction; c == copied instruction
Instruction i = ih.getInstruction();
Instruction c = ch.getInstruction();
if (i instanceof BranchInstruction) {
BranchInstruction bc = (BranchInstruction)c;
BranchInstruction bi = (BranchInstruction)i;
InstructionHandle itarget = bi.getTarget(); // old target
// New target must be in targetMap
InstructionHandle newTarget =
(InstructionHandle)targetMap.get(itarget);
bc.setTarget(newTarget);
// Handle LOOKUPSWITCH or TABLESWITCH which may have many
// target instructions
if (bi instanceof Select) {
InstructionHandle[] itargets = ((Select)bi).getTargets();
InstructionHandle[] ctargets = ((Select)bc).getTargets();
// Update all targets
for (int j=0; j < itargets.length; j++) {
ctargets[j] =
(InstructionHandle)targetMap.get(itargets[j]);
}
}
} else if (i instanceof LocalVariableInstruction
|| i instanceof RET) {
// For any instruction that touches a local variable,
// map the location of the variable in the original
// method to its location in the new method.
IndexedInstruction lvi = (IndexedInstruction)c;
int oldLocalVarIndex = lvi.getIndex();
LocalVariableGen oldLVG =
getLocalVariableRegistry()
.lookupRegisteredLocalVariable(oldLocalVarIndex,
ih.getPosition());
LocalVariableGen newLVG =
(LocalVariableGen)localVarMap.get(oldLVG);
int newLocalVarIndex;
if (newLVG == null) {
// Create new variable based on old variable - use same
// name and type, but we will let the variable be active
// for the entire outlined method.
// LocalVariableGen oldLocal = oldLocals[oldLocalVarIndex];
String varName = oldLVG.getName();
Type varType = oldLVG.getType();
newLVG = outlinedMethodGen.addLocalVariable(varName,
varType,
null,
null);
newLocalVarIndex = newLVG.getIndex();