From b1aca7ece482e0070c32382a17c9ff492a0b382b Mon Sep 17 00:00:00 2001 From: nbauma109 Date: Sun, 19 Jun 2022 20:24:08 +0200 Subject: [PATCH] fine tune foreach loop reconstruction and line number realignment --- .../instruction/fast/instruction/FastTry.java | 7 +-- .../fast/FastInstructionListBuilder.java | 37 +++++++++++----- .../visitor/MinMaxLineNumberVisitor.java | 44 +++++++++++++++++++ 3 files changed, 72 insertions(+), 16 deletions(-) create mode 100644 src/main/java/jd/core/process/layouter/visitor/MinMaxLineNumberVisitor.java diff --git a/src/main/java/jd/core/model/instruction/fast/instruction/FastTry.java b/src/main/java/jd/core/model/instruction/fast/instruction/FastTry.java index 5c50b779..f736c1a0 100644 --- a/src/main/java/jd/core/model/instruction/fast/instruction/FastTry.java +++ b/src/main/java/jd/core/model/instruction/fast/instruction/FastTry.java @@ -21,10 +21,8 @@ import org.jd.core.v1.model.classfile.constant.ConstantMethodref; import java.util.ArrayList; -import java.util.Comparator; import java.util.Iterator; import java.util.List; -import java.util.Optional; import jd.core.model.classfile.ConstantPool; import jd.core.model.classfile.LocalVariable; @@ -38,7 +36,7 @@ import jd.core.model.instruction.bytecode.instruction.Invokevirtual; import jd.core.model.instruction.bytecode.instruction.StoreInstruction; import jd.core.model.instruction.fast.FastConstants; -import jd.core.process.layouter.visitor.MinLineNumberVisitor; +import jd.core.process.layouter.visitor.MinMaxLineNumberVisitor; /** * try-catch-finally @@ -69,8 +67,7 @@ public boolean removeOutOfBounds(int firstLineNumber) { } public int minLineNumber() { - Optional minLineNoInstr = instructions.stream().min(Comparator.comparing(MinLineNumberVisitor::visit)); - return minLineNoInstr.isPresent() ? minLineNoInstr.get().getLineNumber() : Integer.MAX_VALUE; + return MinMaxLineNumberVisitor.visit(instructions).minLineNumber(); } } diff --git a/src/main/java/jd/core/process/analyzer/instruction/fast/FastInstructionListBuilder.java b/src/main/java/jd/core/process/analyzer/instruction/fast/FastInstructionListBuilder.java index 96ab40a4..fa52d32f 100644 --- a/src/main/java/jd/core/process/analyzer/instruction/fast/FastInstructionListBuilder.java +++ b/src/main/java/jd/core/process/analyzer/instruction/fast/FastInstructionListBuilder.java @@ -25,13 +25,11 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -111,8 +109,8 @@ import jd.core.process.analyzer.instruction.fast.reconstructor.TernaryOpInReturnReconstructor; import jd.core.process.analyzer.instruction.fast.reconstructor.TernaryOpReconstructor; import jd.core.process.analyzer.util.InstructionUtil; -import jd.core.process.layouter.visitor.MaxLineNumberVisitor; -import jd.core.process.layouter.visitor.MinLineNumberVisitor; +import jd.core.process.layouter.visitor.MinMaxLineNumberVisitor; +import jd.core.process.layouter.visitor.MinMaxLineNumberVisitor.MinMaxLineNumber; import jd.core.util.IntSet; import jd.core.util.SignatureUtil; @@ -1059,15 +1057,14 @@ private static void createFastTry(ReferenceMap referenceMap, ClassFile classFile List instructionsToMove = new ArrayList<>(); if (fastTry.hasFinally()) { - Optional finallyMinLineNoInstr = finallyInstructions.stream().min(Comparator.comparing(MinLineNumberVisitor::visit)); - Optional finallyMaxLineNoInstr = finallyInstructions.stream().max(Comparator.comparing(MaxLineNumberVisitor::visit)); - if (finallyMinLineNoInstr.isPresent() && finallyMaxLineNoInstr.isPresent()) { + MinMaxLineNumber minMaxLineNumber = MinMaxLineNumberVisitor.visit(finallyInstructions); + if (minMaxLineNumber.isValid()) { for (Instruction tryInstruction : fastTry.getInstructions()) { - if (tryInstruction.getLineNumber() > finallyMaxLineNoInstr.get().getLineNumber()) { + if (tryInstruction.getLineNumber() > minMaxLineNumber.maxLineNumber()) { instructionsToMove.add(tryInstruction); } } - fastTry.removeOutOfBoundsInstructions(finallyMinLineNoInstr.get().getLineNumber()); + fastTry.removeOutOfBoundsInstructions(minMaxLineNumber.minLineNumber()); } } @@ -2862,8 +2859,26 @@ private static int createForLoopCase3(ClassFile classFile, Method method, List minMaxLineNumber.maxLineNumber()) { + if (lastBodyWhileLoop.getOpcode() != Const.GOTO) { + subList.add(lastBodyWhileLoop); + } + Instruction variable = createForEachVariableInstruction(subList.remove(0)); + InvokeNoStaticInstruction insi = (InvokeNoStaticInstruction) ((AStore) beforeWhileLoop).getValueref(); + Instruction values = insi.getObjectref(); + + // Remove iterator local variable + removeLocalVariable(method, (StoreInstruction) beforeWhileLoop); + + variable.setLineNumber(values.getLineNumber()); + + list.set(beforeWhileLoopIndex, new FastForEach(FastConstants.FOREACH, forLoopOffset, + values.getLineNumber(), branch, variable, values, subList)); + } else { + list.set(beforeWhileLoopIndex, new FastFor(FastConstants.FOR, forLoopOffset, beforeWhileLoop.getLineNumber(), + branch, beforeWhileLoop, test, lastBodyWhileLoop, subList)); + } } } diff --git a/src/main/java/jd/core/process/layouter/visitor/MinMaxLineNumberVisitor.java b/src/main/java/jd/core/process/layouter/visitor/MinMaxLineNumberVisitor.java new file mode 100644 index 00000000..e4ab9d9f --- /dev/null +++ b/src/main/java/jd/core/process/layouter/visitor/MinMaxLineNumberVisitor.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (C) 2022 GPLv3 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package jd.core.process.layouter.visitor; + +import java.util.List; + +import jd.core.model.instruction.bytecode.instruction.Instruction; + +public final class MinMaxLineNumberVisitor { + + private MinMaxLineNumberVisitor() { + } + + public static MinMaxLineNumber visit(List instructions) { + int minLineNumber = Integer.MAX_VALUE; + int maxLineNumber = Integer.MIN_VALUE; + for (Instruction instruction : instructions) { + minLineNumber = Math.min(minLineNumber, MinLineNumberVisitor.visit(instruction)); + maxLineNumber = Math.max(maxLineNumber, MaxLineNumberVisitor.visit(instruction)); + } + return new MinMaxLineNumber(minLineNumber, maxLineNumber); + } + + public record MinMaxLineNumber(int minLineNumber, int maxLineNumber) { + + public boolean isValid() { + return minLineNumber != Integer.MAX_VALUE && maxLineNumber != Integer.MIN_VALUE; + } + } +}