下面列出了org.objectweb.asm.Opcodes# DUP_X1 ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void invokeRecordAllocation(String typeName) {
Matcher matcher = namePattern.matcher(typeName);
if (matcher.find()) {
typeName = matcher.group(1);
}
// stack: ... count newobj
super.visitInsn(Opcodes.DUP_X1);
// -> stack: ... newobj count newobj
super.visitLdcInsn(typeName);
// -> stack: ... newobj count newobj typename
super.visitInsn(Opcodes.SWAP);
// -> stack: ... newobj count typename newobj
super.visitMethodInsn(
Opcodes.INVOKESTATIC, recorderClass, recorderMethod, RECORDER_SIGNATURE, false);
// -> stack: ... newobj
}
public static int getDupXOpcode(Type dType, Type bType) {
if (dType.getSize() == 1 && bType.getSize() == 1) {
return Opcodes.DUP_X1;
} else if (dType.getSize() == 1 && bType.getSize() == 2) {
return Opcodes.DUP_X2;
} else if (dType.getSize() == 2 && bType.getSize() == 1) {
return Opcodes.DUP2_X1;
} else if (dType.getSize() == 2 && bType.getSize() == 2) {
return Opcodes.DUP2_X2;
} else {
throw new IllegalArgumentException(dType.toString() + " " + bType.toString());
}
}
void calculateArrayLengthAndDispatch(String typeName, int dimCount) {
// Since the dimensions of the array are not known at instrumentation
// time, we take the created multi-dimensional array and peel off nesting
// levels from the left. For each nesting layer we probe the array length
// and accumulate a partial product which we can then feed the recording
// function.
// below we note the partial product of dimensions 1 to X-1 as productToX
// (so productTo1 == 1 == no dimensions yet). We denote by aref0 the
// array reference at the current nesting level (the containing aref's [0]
// element). If we hit a level whose arraylength is 0 or whose
// reference is null, there's no point continuing, so we shortcut
// out.
// This approach works pretty well when you create a new array with the
// newarray bytecodes. You can also create a new array by cloning an
// existing array; an existing multidimensional array might have had some
// of its [0] elements nulled out. We currently deal with this by bailing
// out, but arguably we should do something more principled (like calculate
// the size of the multidimensional array from scratch if you are using
// clone()).
// TODO(java-platform-team): Do something about modified multidimensional
// arrays and clone().
Label zeroDimension = new Label();
super.visitInsn(Opcodes.DUP); // -> stack: ... origaref aref0
super.visitLdcInsn(1); // -> stack: ... origaref aref0 productTo1
for (int i = 0; i < dimCount; ++i) {
// pre: stack: ... origaref aref0 productToI
super.visitInsn(Opcodes.SWAP); // -> stack: ... origaref productToI aref
super.visitInsn(Opcodes.DUP);
Label nonNullDimension = new Label();
// -> stack: ... origaref productToI aref aref
super.visitJumpInsn(Opcodes.IFNONNULL, nonNullDimension);
// -> stack: ... origaref productToI aref
super.visitInsn(Opcodes.SWAP);
// -> stack: ... origaref aref productToI
super.visitJumpInsn(Opcodes.GOTO, zeroDimension);
super.visitLabel(nonNullDimension);
// -> stack: ... origaref productToI aref
super.visitInsn(Opcodes.DUP_X1);
// -> stack: ... origaref aref0 productToI aref
super.visitInsn(Opcodes.ARRAYLENGTH);
// -> stack: ... origaref aref0 productToI dimI
Label nonZeroDimension = new Label();
super.visitInsn(Opcodes.DUP);
// -> stack: ... origaref aref0 productToI dimI dimI
super.visitJumpInsn(Opcodes.IFNE, nonZeroDimension);
// -> stack: ... origaref aref0 productToI dimI
super.visitInsn(Opcodes.POP);
// -> stack: ... origaref aref0 productToI
super.visitJumpInsn(Opcodes.GOTO, zeroDimension);
super.visitLabel(nonZeroDimension);
// -> stack: ... origaref aref0 productToI max(dimI,1)
super.visitInsn(Opcodes.IMUL);
// -> stack: ... origaref aref0 productTo{I+1}
if (i < dimCount - 1) {
super.visitInsn(Opcodes.SWAP);
// -> stack: ... origaref productTo{I+1} aref0
super.visitInsn(Opcodes.ICONST_0);
// -> stack: ... origaref productTo{I+1} aref0 0
super.visitInsn(Opcodes.AALOAD);
// -> stack: ... origaref productTo{I+1} aref0'
super.visitInsn(Opcodes.SWAP);
}
// post: stack: ... origaref aref0 productTo{I+1}
}
super.visitLabel(zeroDimension);
super.visitInsn(Opcodes.SWAP); // -> stack: ... origaref product aref0
super.visitInsn(Opcodes.POP); // -> stack: ... origaref product
super.visitInsn(Opcodes.SWAP); // -> stack: ... product origaref
invokeRecordAllocation(typeName);
}