态的,如果是静态的,将 堆栈帧槽初始化为零(不是静态正好相反)。这种方式与 Java 如何处理方法调用有关。对 于非静态的方法,每次调用的第一个(隐藏的)参数是目标对象的 this 引用,在计算堆栈 帧中完整参数集大小时我要考虑到这点。
清单 4. 设置包装的调用
// compute the size of the calling parameters
Type[] types = methgen.getArgumentTypes();
int slot = methgen.isStatic() ? 0 : 1;
for (int i = 0; i < types.length; i++) {
slot += types[i].getSize();
}
// save time prior to invocation
ilist.append(ifact.createInvoke("java.lang.System",
"currentTimeMillis", Type.LONG, Type.NO_ARGS,
Constants.INVOKESTATIC));
ilist.append(InstructionFactory.createStore(Type.LONG, slot));
清单 5 显示了生成对包装方法的调用并保存结果(如果有的话)的代码。这段代码的第 一部分再次检查方法是否是静态的。如果方法不是静态的,那么就生成将 this 对象引用装 载到堆栈中的代码,同时设置方法调用类型为 virtual (而不是 static )。然后 for 循 环生成将所有调用参数值拷贝到堆栈中的代码, createInvoke() 方法生成对包装的方法的 实际调用,最后 if 语句将结果值保存到位于堆栈帧中的另一个局部变量中(如果结果类型 不是 void )。
清单 5. 调用包装的方法
// call the wrapped method
int offset = 0;
short invoke = Constants.INVOKESTATIC;
if (!methgen.isStatic()) {
ilist.append(InstructionFactory.createLoad(Type.OBJECT, 0));
offset = 1;
invoke = Constants.INVOKEVIRTUAL;
}
for (int i = 0; i < types.length; i++) {
Type type = types[i];
ilist.append(InstructionFactory.createLoad(type, offset));
offset += type.getSize();
}
Type result = methgen.getReturnType();
ilist.append(ifact.createInvoke(cname,
iname, result, types, invoke));
// store result for return later
if (result != Type.VOID) {
ilist.append(InstructionFactory.createStore(result, slot+2));
}
Java園殻議強蓑來?及7何蛍: 喘BCEL譜柴忖准鷹(4)
扮寂:2011-04-09 IBM Dennis M. Sosnoski
?壓蝕兵淫廾。賠汽 6 伏撹糞縞柴麻蝕兵扮寂朔将狛議坐昼方?旺恬葎園電挫鯉塀議? 連嬉咫竃栖議旗鷹。宸匯何蛍心貧肇載鹸墫?徽頁寄謹方荷恬糞縞貧峪頁亟竃補竃?連議光 倖何蛍。万鳩糞婢幣阻叱嶽厘壓念中議旗鷹嶄短嗤聞喘議荷恬窃侏?淫凄忖粁恵諒?欺 java.lang.System.out ?才叱嶽音揖議峺綜窃侏。泌惚繍 JVM ??葎児噐均媚議侃尖匂? 夸凪嶄寄謹方頁否叟尖盾議?咀緩厘壓宸戦祥音壅?聾傍苧阻。
賠汽 6. 柴麻旺嬉咫侭聞喘議扮寂
// print time required for method call
ilist.append(ifact.createFieldAccess("java.lang.System", "out",
new ObjectType("java.io.PrintStream"), Constants.GETSTATIC));
ilist.append(InstructionConstants.DUP);
ilist.append(InstructionConstants.DUP);
String text = "Call to method " + methgen.getName() + " took ";
ilist.append(new PUSH(pgen, text));
ilist.append(ifact.createInvoke("java.io.PrintStream", "print",
Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL));
ilist.append(ifact.createInvoke("java.lang.
|