@@ -188,7 +188,6 @@ class RawInstListBuilder(
188
188
private val laterAssignments = identityMap<AbstractInsnNode , MutableMap <Int , JcRawValue >>()
189
189
private val laterStackAssignments = identityMap<AbstractInsnNode , MutableMap <Int , JcRawValue >>()
190
190
private val localTypeRefinement = identityMap<JcRawLocalVar , JcRawLocalVar >()
191
- private val postfixInstructions = hashMapOf<Int , JcRawInst >()
192
191
193
192
private var labelCounter = 0
194
193
private var localCounter = 0
@@ -213,12 +212,13 @@ class RawInstListBuilder(
213
212
private fun buildInstructions () {
214
213
currentFrame = createInitialFrame()
215
214
frames[ENTRY ] = currentFrame
216
- methodNode.instructions.forEachIndexed { index, insn ->
215
+ val nodes = methodNode.instructions.toList()
216
+ nodes.forEachIndexed { index, insn ->
217
217
when (insn) {
218
218
is InsnNode -> buildInsnNode(insn)
219
219
is FieldInsnNode -> buildFieldInsnNode(insn)
220
220
is FrameNode -> buildFrameNode(insn)
221
- is IincInsnNode -> buildIincInsnNode(insn)
221
+ is IincInsnNode -> buildIincInsnNode(insn, nodes.getOrNull(index + 1 ) )
222
222
is IntInsnNode -> buildIntInsnNode(insn)
223
223
is InvokeDynamicInsnNode -> buildInvokeDynamicInsn(insn)
224
224
is JumpInsnNode -> buildJumpInsnNode(insn)
@@ -250,11 +250,14 @@ class RawInstListBuilder(
250
250
val insnList = instructionList(insn)
251
251
val frame = frames[insn]!!
252
252
for ((variable, value) in assignments) {
253
- if (value != frame[variable]) {
254
- if (insn.isBranchingInst || insn.isTerminateInst) {
255
- insnList.addInst(insn, JcRawAssignInst (method, value, frame[variable]!! ), insnList.lastIndex)
253
+ val frameVariable = frame[variable]
254
+ if (frameVariable != null && value != frameVariable) {
255
+ if (insn.isBranchingInst) {
256
+ insnList.addInst(insn, JcRawAssignInst (method, value, frameVariable), 0 )
257
+ }else if (insn.isTerminateInst) {
258
+ insnList.addInst(insn, JcRawAssignInst (method, value, frameVariable), insnList.lastIndex)
256
259
} else {
257
- insnList.addInst(insn, JcRawAssignInst (method, value, frame[variable] !! ))
260
+ insnList.addInst(insn, JcRawAssignInst (method, value, frameVariable ))
258
261
}
259
262
}
260
263
}
@@ -375,11 +378,16 @@ class RawInstListBuilder(
375
378
return currentFrame.locals.getValue(variable)
376
379
}
377
380
378
- private fun local (variable : Int , expr : JcRawValue , insn : AbstractInsnNode ): JcRawAssignInst ? {
381
+ private fun local (variable : Int , expr : JcRawValue , insn : AbstractInsnNode , override : Boolean = false ): JcRawAssignInst ? {
379
382
val oldVar = currentFrame.locals[variable]
380
383
return if (oldVar != null ) {
381
384
if (oldVar.typeName == expr.typeName || (expr is JcRawNullConstant && ! oldVar.typeName.isPrimitive)) {
382
- JcRawAssignInst (method, oldVar, expr)
385
+ if (override ) {
386
+ currentFrame = currentFrame.put(variable, expr)
387
+ JcRawAssignInst (method, expr, expr)
388
+ } else {
389
+ JcRawAssignInst (method, oldVar, expr)
390
+ }
383
391
} else if (expr is JcRawSimpleValue ) {
384
392
currentFrame = currentFrame.put(variable, expr)
385
393
null
@@ -403,7 +411,7 @@ class RawInstListBuilder(
403
411
private fun instructionList (insn : AbstractInsnNode ) = instructions.getOrPut(insn, ::mutableListOf)
404
412
405
413
private fun addInstruction (insn : AbstractInsnNode , inst : JcRawInst , index : Int? = null) {
406
- instructionList(insn).addInst(insn, inst, index)
414
+ instructionList(insn).addInst(insn, inst, index)
407
415
}
408
416
409
417
private fun MutableList<JcRawInst>.addInst (node : AbstractInsnNode , inst : JcRawInst , index : Int? = null) {
@@ -412,18 +420,6 @@ class RawInstListBuilder(
412
420
} else {
413
421
add(inst)
414
422
}
415
- if (postfixInstructions.isNotEmpty()) {
416
- when {
417
- node.isBranchingInst -> postfixInstructions.forEach {
418
- instructionList(node).add(0 , it.value)
419
- }
420
-
421
- inst !is JcRawReturnInst -> postfixInstructions.forEach {
422
- instructionList(node).add(it.value)
423
- }
424
- }
425
- postfixInstructions.clear()
426
- }
427
423
}
428
424
429
425
private fun nextRegister (typeName : TypeName ): JcRawValue {
@@ -825,7 +821,7 @@ class RawInstListBuilder(
825
821
* a helper function that helps to merge local variables from several predecessor frames into one map
826
822
* if all the predecessor frames are known (meaning we already visited all the corresponding instructions
827
823
* in the bytecode) --- merge process is trivial
828
- * if some predecessor frames are unknown, we remebmer them and add requried assignment instructions after
824
+ * if some predecessor frames are unknown, we remember them and add required assignment instructions after
829
825
* the full construction process is complete, see #buildRequiredAssignments function
830
826
*/
831
827
private fun SortedMap <Int , TypeName >.copyLocals (predFrames : Map <AbstractInsnNode , Frame ?>): Map <Int , JcRawValue > =
@@ -1017,13 +1013,18 @@ class RawInstListBuilder(
1017
1013
}
1018
1014
}
1019
1015
1020
- private fun buildIincInsnNode (insnNode : IincInsnNode ) {
1016
+ private fun buildIincInsnNode (insnNode : IincInsnNode , nextInst : AbstractInsnNode ? ) {
1021
1017
val variable = insnNode.`var `
1022
1018
val local = local(variable)
1023
- postfixInstructions[variable] = JcRawAssignInst (method, local,
1024
- JcRawAddExpr (local.typeName, local, JcRawInt (insnNode.incr))
1025
- )
1026
- local(variable, local, insnNode)
1019
+ val incrementedVariable = when {
1020
+ nextInst != null && nextInst.isBranchingInst -> local
1021
+ nextInst != null && (
1022
+ (nextInst is VarInsnNode && nextInst.`var ` == variable) || nextInst is LabelNode ) -> local
1023
+ else -> nextRegister(local.typeName)
1024
+ }
1025
+ val add = JcRawAddExpr (local.typeName, local, JcRawInt (insnNode.incr))
1026
+ instructionList(insnNode) + = JcRawAssignInst (method, incrementedVariable, add)
1027
+ local(variable, incrementedVariable, insnNode, override = incrementedVariable != local)
1027
1028
}
1028
1029
1029
1030
private fun buildIntInsnNode (insnNode : IntInsnNode ) {
@@ -1428,10 +1429,6 @@ class RawInstListBuilder(
1428
1429
1429
1430
in Opcodes .ILOAD .. Opcodes .ALOAD -> {
1430
1431
push(local(variable))
1431
- postfixInstructions[variable]?.let {
1432
- postfixInstructions.remove(variable)
1433
- instructionList(insnNode).add(it) // do not reuse `addInstruction` function here
1434
- }
1435
1432
}
1436
1433
else -> error(" Unknown opcode ${insnNode.opcode} in VarInsnNode" )
1437
1434
}
0 commit comments