@@ -159,6 +159,33 @@ private val AbstractInsnNode.isBranchingInst
159159private val AbstractInsnNode .isTerminateInst
160160 get() = this is InsnNode && (this .opcode == Opcodes .ATHROW || this .opcode in Opcodes .IRETURN .. Opcodes .RETURN )
161161
162+ private fun LabelNode.isBetween (labelStart : LabelNode , labelEnd : LabelNode ): Boolean {
163+ var curNode: AbstractInsnNode ? = this
164+ var left = false
165+ var right = false
166+ while (curNode != null ) {
167+ if (curNode == labelStart) {
168+ left = true
169+ break
170+ }
171+ if (curNode == labelEnd && curNode != this ) {
172+ return false
173+ }
174+ curNode = curNode.previous
175+
176+ }
177+ if (! left) return false
178+ curNode = this
179+ while (curNode != null ) {
180+ if (curNode == labelEnd) {
181+ right = true
182+ break
183+ }
184+ curNode = curNode.next
185+ }
186+ return right
187+ }
188+
162189private val TryCatchBlockNode .typeOrDefault get() = this .type ? : THROWABLE_CLASS
163190
164191private val Collection <TryCatchBlockNode >.commonTypeOrDefault
@@ -381,30 +408,6 @@ class RawInstListBuilder(
381408 return currentFrame.locals.getValue(variable)
382409 }
383410
384- // fun LabelNode.isBetween(labelStart: LabelNode, labelEnd: LabelNode): Boolean {
385- // var curNode: AbstractInsnNode = labelStart
386- // while (curNode != labelEnd && curNode != null) {
387- // if (this == curNode) {
388- // return true
389- // }
390- // curNode = curNode.next
391- // }
392- // return this == curNode
393- // }
394- //
395- // val instrLabel = methodNode.instructions.takeWhile { it != insn }.last { it is LabelNode } as LabelNode
396- // val locals = methodNode.localVariables.filter { it.index == variable }
397- // locals.map { instrLabel.isBetween(it.start, it.end) }
398- // locals
399-
400-
401- // val oldVar = currentFrame.locals[variable]?.let {
402- // if (expr.typeName.isPrimitive.xor(it.typeName.isPrimitive)) {
403- // null
404- // } else {
405- // it
406- // }
407- // }
408411 private fun local (
409412 variable : Int ,
410413 expr : JcRawValue ,
@@ -919,6 +922,8 @@ class RawInstListBuilder(
919922 else -> {
920923 val assignment = nextRegister(type)
921924 for ((node, frame) in predFrames) {
925+ // TODO! Make anything with that (we should take into account subtyping)
926+ // assigment.isSubtypeOf(frame[variable]!!.typeName)
922927 if (frame != null ) {
923928 if (node.isBranchingInst) {
924929 addInstruction(node, JcRawAssignInst (method, assignment, frame[variable]!! ), 0 )
@@ -1191,17 +1196,26 @@ class RawInstListBuilder(
11911196 }
11921197 }
11931198
1194- private fun mergeFrames (frames : Map <AbstractInsnNode , Frame >): Frame {
1199+ private fun mergeFrames (frames : Map <AbstractInsnNode , Frame >, curLabel : LabelNode ): Frame {
11951200 val frameSet = frames.values
11961201 if (frames.isEmpty()) return currentFrame
11971202 if (frames.size == 1 ) return frameSet.first()
11981203
11991204 val allLocals = frameSet.flatMap { it.locals.keys }
12001205 val localTypes = allLocals
12011206 .filter { local -> frameSet.all { local in it.locals } }
1202- .associateWith {
1203- val types = frameSet.map { frame -> frame[it]!! .typeName }
1204- types.firstOrNull { it != NULL } ? : NULL
1207+ .associateWith { ind ->
1208+ val types = frameSet.map { frame -> frame[ind]!! .typeName }
1209+ // If we have several variables types for one register we have to search right type in debug info otherwise we cannot guarantee anything
1210+ if (types.toSet().size != 1 ) {
1211+ methodNode.localVariables
1212+ .firstOrNull { curLabel.isBetween(it.start, it.end) && it.index == ind }
1213+ ?.desc
1214+ ?.let { TypeNameImpl (it) }
1215+ ? : types.firstOrNull { it != NULL } ? : NULL
1216+ } else {
1217+ types.firstOrNull { it != NULL } ? : NULL
1218+ }
12051219 }
12061220 .toSortedMap()
12071221 val newLocals = localTypes.copyLocals(frames).toPersistentMap()
@@ -1227,7 +1241,7 @@ class RawInstListBuilder(
12271241 if (predecessorFrames.size == 1 ) {
12281242 currentFrame = predecessorFrames.first()
12291243 } else if (predecessors.size == predecessorFrames.size) {
1230- currentFrame = mergeFrames(predecessors.zip(predecessorFrames).toMap())
1244+ currentFrame = mergeFrames(predecessors.zip(predecessorFrames).toMap(), insnNode )
12311245 }
12321246 val catchEntries = methodNode.tryCatchBlocks.filter { it.handler == insnNode }
12331247
0 commit comments