Моя цель — вставить немного инструментального кода в начало каждого базового блока кода. Это кажется довольно простой задачей с помощью ControlFlow.Block и CtMethod.insertAt() Javaassist. Вот соответствующий фрагмент кода (он находится в функции преобразования):
ControlFlow flow=new ControlFlow(m); //m is the CtMethod currently being instrumented
Block[] blockArray=flow.basicBlocks();
for(Block thisbb : blockArray){
//Dynamically Update Method Statistics
String blockUpdate=new String();
String thisbbIndex=Integer.toString(thisbb.index());
blockUpdate+=mse+".setBlockIndex("+thisbbIndex+"); ";
blockUpdate="{ " + blockUpdate + "} ";
//Insert
int pos=m.getMethodInfo().getLineNumber(thisbb.position()); //Source code line position from binary line position
System.out.print("At "+pos+": "+blockUpdate);
int n=m.insertAt(pos, blockUpdate);
System.out.println(" -> "+n);
}
Обратите внимание, что параметр "line" в CtMethod.insertAt(line,srcCode)
является позицией строки исходного кода, а не позицией строки bytecode. В исходном коде некоторые базовые блоки сообщают об одном и том же номере строки! Вот результат:
At 6: { _JDA_mse.setBlockIndex(0); } -> 6
At 8: { _JDA_mse.setBlockIndex(1); } -> 8
At 8: { _JDA_mse.setBlockIndex(2); } -> 8
At 8: { _JDA_mse.setBlockIndex(3); } -> 8
At 8: { _JDA_mse.setBlockIndex(4); } -> 8
At 8: { _JDA_mse.setBlockIndex(5); } -> 8
At 8: { _JDA_mse.setBlockIndex(6); } -> 8
At #
представляет собой место, куда я запросил разместить код, а -> #
представляет место в исходном коде, куда он был фактически вставлен (если все работает, они должны быть одинаковыми). Все, что находится внутри { ... }
, — это код, который я хочу разместить (_JDA_mse
— это локальная переменная, которую я добавил в функцию с помощью методов Javassist, так что с ее использованием проблем не возникает).
Проблема в том, что for(int i=0; i<size; ++i)
содержит несколько базовых блоков, неразделимых в исходном коде, но четко различающихся в байт-коде. Вот почему несколько базовых блоков сопоставляются с одной и той же исходной строкой, и это просто показывает, что строки исходного кода не обеспечивают достаточную инструментальную точность для регистрации базовых блоков. Есть ли способ эмулировать CtMethod.insertAt(bytecodePosition,srcString) вместо использования предоставленного CtMethod.insertAt(sourceLine,srcString)?