diff --git a/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java b/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java index d3d3921946..9f148c0173 100644 --- a/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java +++ b/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java @@ -225,6 +225,12 @@ public interface IFernflowerPreferences { @Type(DecompilerOption.Type.BOOLEAN) String VERIFY_VARIABLE_MERGES = "verify-merges"; + @Name("[Experimental] Verify Pre Post Variable Merges") + @Description("Will try to validate that code before and after variable merges is equivalent") + @ShortName("pvm") + @Type(DecompilerOption.Type.BOOLEAN) + String VERIFY_PRE_POST_VARIABLE_MERGES = "verify-pre-post-merges"; + @Name("[Experimental] Use old try deduplication") @Description("Use the old try deduplication algorithm for methods with obfuscated exceptions, which inserts dummy exception handlers instead of duplicating blocks") @Type(DecompilerOption.Type.BOOLEAN) @@ -437,6 +443,7 @@ static Map getDefaults() { defaults.put(SHOW_HIDDEN_STATEMENTS, "0"); // Extra debugging that isn't useful in most cases defaults.put(SIMPLIFY_STACK_SECOND_PASS, "1"); // Generally produces better bytecode, useful to debug if it does something strange defaults.put(VERIFY_VARIABLE_MERGES, "0"); // Produces more correct code in rare cases, but hurts code cleanliness in the majority of cases. Default off until a better fix is created. + defaults.put(VERIFY_PRE_POST_VARIABLE_MERGES, "0"); defaults.put(OLD_TRY_DEDUP, "0"); defaults.put(DECOMPILE_PREVIEW, "1"); // Preview features are useful to decompile in almost all cases diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java index 49450d54ca..5ac6827ee0 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java @@ -9,10 +9,12 @@ import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.jetbrains.java.decompiler.main.rels.MethodWrapper; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; +import org.jetbrains.java.decompiler.modules.decompiler.StackVarsProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ValidationHelper; import org.jetbrains.java.decompiler.modules.decompiler.exps.*; import org.jetbrains.java.decompiler.modules.decompiler.flow.DirectGraph; import org.jetbrains.java.decompiler.modules.decompiler.flow.FlattenStatementsHelper; +import org.jetbrains.java.decompiler.modules.decompiler.sforms.SSAUConstructorSparseEx; import org.jetbrains.java.decompiler.modules.decompiler.stats.*; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarTypeProcessor.FinalType; import org.jetbrains.java.decompiler.struct.StructClass; @@ -44,7 +46,7 @@ public class VarDefinitionHelper { private final VarProcessor varproc; - private final Statement root; + private final RootStatement root; private final StructMethod mt; private final Map clashingNames = new HashMap<>(); @@ -519,7 +521,118 @@ private void populateTypeBounds(VarProcessor proc, Statement stat) { } } - private VPPEntry mergeVars(Statement stat) { + static class VarID { + final VarExprent var; + + VarID(VarExprent var) { + this.var = var; + } + + @Override + public int hashCode() { + return System.identityHashCode(var); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof VarID varID && var == varID.var; + } + } + + private Map> getVarExprentSources() { + // Do an ssau analysis to find the sources of variables + SSAUConstructorSparseEx ssau = new SSAUConstructorSparseEx(); + try { + ssau.splitVariables(root, mt); + } catch (NullPointerException t) { + // Can happen when something is wrong with variables ... + + StackVarsProcessor.setVersionsToNull(root); + return null; + } + + Map lookup = new HashMap<>(); + findAllVarExprents(root, lookup); + + Map> sources = new HashMap<>(); + for (VarVersionNode node : ssau.getSsuVersions().nodes) { + VarID target = lookup.get(node.asPair()); + if (target == null) { + continue; + } + + Set sourceVars = new HashSet<>(); + + for (VarVersionNode predecessor : node.getPredecessors()) { + VarID source = lookup.get(predecessor.asPair()); + if (source != null) { + sourceVars.add(source); + } + } + + if (node.phantomNode != null) { + VarID source = lookup.get(node.phantomNode.asPair()); + if (source != null) { + sourceVars.add(source); + } + } + + if (!sourceVars.isEmpty()) { + sources.put(target, sourceVars); + } + } + + StackVarsProcessor.setVersionsToNull(root); + + return sources; + } + + private static void findAllVarExprents(Statement stat, Map lookup) { + for (Exprent exprent : stat.getVarDefinitions()) { + if (exprent instanceof VarExprent varExprent) { + lookup.put(new VarVersionPair(varExprent), new VarID(varExprent)); + } + } + List lst = stat.getExprents(); + if (lst != null) { + for (Exprent exprent : lst) { + for (Exprent exp : exprent.getAllExprents(true, true)) { + if (exp instanceof VarExprent varExprent) { + lookup.put(new VarVersionPair(varExprent), new VarID(varExprent)); + } + } + } + } + + for (Statement subStat : stat.getStats()) { + findAllVarExprents(subStat, lookup); + } + } + + private void compareVarExprentSources( + Map> oldSources, + Map> newSources + ) { + if (newSources == null) return; + + for (var oldEntry : oldSources.entrySet()) { + Set oldSet = oldEntry.getValue(); + Set newSet = newSources.get(oldEntry.getKey()); + + // Check if sets match + if (!Objects.equals(oldSet, newSet)) { + root.addComment("$VF: Variable merging failed for merge " + oldEntry.getKey().var + ". Code has semantic differences!"); + } + } + + for (var newVar : newSources.keySet()) { + if (!oldSources.containsKey(newVar)) { + root.addComment("$VF: Variable merging added a var? " + newVar.var); + } + } + } + + private VPPEntry mergeVars(RootStatement stat) { Map parent = new HashMap<>(); // Always empty dua! MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); @@ -536,6 +649,12 @@ private VPPEntry mergeVars(Statement stat) { populateTypeBounds(varproc, stat); + + Map> sources = null; + if (DecompilerContext.getOption(IFernflowerPreferences.VERIFY_PRE_POST_VARIABLE_MERGES)) { + sources = getVarExprentSources(); + } + Map denylist = new HashMap<>(); VPPEntry remap = mergeVars(stat, parent, new HashMap<>(), denylist); while (remap != null) { @@ -546,6 +665,11 @@ private VPPEntry mergeVars(Statement stat) { remap = mergeVars(stat, parent, new HashMap<>(), denylist); } + + if (sources != null) { + Map> newSources = getVarExprentSources(); + compareVarExprentSources(sources, newSources); + } return null; } diff --git a/test/org/jetbrains/java/decompiler/SingleClassesTest.java b/test/org/jetbrains/java/decompiler/SingleClassesTest.java index 5ce78eca6f..e08c0fc374 100644 --- a/test/org/jetbrains/java/decompiler/SingleClassesTest.java +++ b/test/org/jetbrains/java/decompiler/SingleClassesTest.java @@ -20,7 +20,8 @@ protected void registerAll() { IFernflowerPreferences.VERIFY_ANONYMOUS_CLASSES, "1", IFernflowerPreferences.INCLUDE_ENTIRE_CLASSPATH, "0", IFernflowerPreferences.TERNARY_CONDITIONS, "1", - IFernflowerPreferences.FORCE_JSR_INLINE, "1" + IFernflowerPreferences.FORCE_JSR_INLINE, "1", + IFernflowerPreferences.VERIFY_PRE_POST_VARIABLE_MERGES, "1" ); registerSet("Entire Classpath", this::registerEntireClassPath, IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1", @@ -28,7 +29,8 @@ protected void registerAll() { IFernflowerPreferences.DUMP_EXCEPTION_ON_ERROR, "0", IFernflowerPreferences.IGNORE_INVALID_BYTECODE, "1", IFernflowerPreferences.VERIFY_ANONYMOUS_CLASSES, "1", - IFernflowerPreferences.INCLUDE_ENTIRE_CLASSPATH, "1" + IFernflowerPreferences.INCLUDE_ENTIRE_CLASSPATH, "1", + IFernflowerPreferences.VERIFY_PRE_POST_VARIABLE_MERGES, "1" ); registerSet("Java Runtime", this::registerJavaRuntime, IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1", @@ -36,7 +38,8 @@ protected void registerAll() { IFernflowerPreferences.DUMP_EXCEPTION_ON_ERROR, "0", IFernflowerPreferences.IGNORE_INVALID_BYTECODE, "1", IFernflowerPreferences.VERIFY_ANONYMOUS_CLASSES, "1", - IFernflowerPreferences.INCLUDE_JAVA_RUNTIME, "1" + IFernflowerPreferences.INCLUDE_JAVA_RUNTIME, "1", + IFernflowerPreferences.VERIFY_PRE_POST_VARIABLE_MERGES, "1" ); registerSet("Literals", this::registerLiterals, IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1", @@ -44,7 +47,8 @@ protected void registerAll() { IFernflowerPreferences.DUMP_EXCEPTION_ON_ERROR, "0", IFernflowerPreferences.IGNORE_INVALID_BYTECODE, "1", IFernflowerPreferences.VERIFY_ANONYMOUS_CLASSES, "1", - IFernflowerPreferences.LITERALS_AS_IS, "0" + IFernflowerPreferences.LITERALS_AS_IS, "0", + IFernflowerPreferences.VERIFY_PRE_POST_VARIABLE_MERGES, "1" ); registerSet("Pattern Matching", this::registerPatternMatching, IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1", @@ -53,7 +57,8 @@ protected void registerAll() { IFernflowerPreferences.IGNORE_INVALID_BYTECODE, "1", IFernflowerPreferences.VERIFY_ANONYMOUS_CLASSES, "1", IFernflowerPreferences.INCLUDE_ENTIRE_CLASSPATH, "0", - IFernflowerPreferences.PATTERN_MATCHING, "1" + IFernflowerPreferences.PATTERN_MATCHING, "1", + IFernflowerPreferences.VERIFY_PRE_POST_VARIABLE_MERGES, "1" ); registerSet("Ternary Constant Simplification", this::registerTernaryConstantSimplification, IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1", @@ -62,7 +67,8 @@ protected void registerAll() { IFernflowerPreferences.IGNORE_INVALID_BYTECODE, "1", IFernflowerPreferences.VERIFY_ANONYMOUS_CLASSES, "1", IFernflowerPreferences.LITERALS_AS_IS, "0", - IFernflowerPreferences.TERNARY_CONSTANT_SIMPLIFICATION, "1" + IFernflowerPreferences.TERNARY_CONSTANT_SIMPLIFICATION, "1", + IFernflowerPreferences.VERIFY_PRE_POST_VARIABLE_MERGES, "1" ); registerSet("LVT", this::registerLVT, IFernflowerPreferences.DECOMPILE_INNER, "1", @@ -71,7 +77,8 @@ protected void registerAll() { IFernflowerPreferences.ASCII_STRING_CHARACTERS, "1", IFernflowerPreferences.REMOVE_SYNTHETIC, "1", IFernflowerPreferences.REMOVE_BRIDGE, "1", - IFernflowerPreferences.USE_DEBUG_VAR_NAMES, "1" + IFernflowerPreferences.USE_DEBUG_VAR_NAMES, "1", + IFernflowerPreferences.VERIFY_PRE_POST_VARIABLE_MERGES, "1" ); registerSet("Try Loop", this::registerTryLoop, IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1", @@ -80,7 +87,8 @@ protected void registerAll() { IFernflowerPreferences.IGNORE_INVALID_BYTECODE, "1", IFernflowerPreferences.VERIFY_ANONYMOUS_CLASSES, "1", IFernflowerPreferences.INCLUDE_ENTIRE_CLASSPATH, "0", - IFernflowerPreferences.TRY_LOOP_FIX, "1" + IFernflowerPreferences.TRY_LOOP_FIX, "1", + IFernflowerPreferences.VERIFY_PRE_POST_VARIABLE_MERGES, "1" ); registerSet("Javadoc", () -> { register(JAVA_8, "TestJavadoc"); @@ -108,7 +116,8 @@ public String getMethodDoc(StructClass structClass, StructMethod structMethod) { IFernflowerPreferences.IGNORE_INVALID_BYTECODE, "1", IFernflowerPreferences.VERIFY_ANONYMOUS_CLASSES, "1", IFernflowerPreferences.INCLUDE_ENTIRE_CLASSPATH, "0", - IFernflowerPreferences.RENAME_ENTITIES, "1" + IFernflowerPreferences.RENAME_ENTITIES, "1", + IFernflowerPreferences.VERIFY_PRE_POST_VARIABLE_MERGES, "1" ); registerSet("Complex Condys", () -> register(JASM, "TestComplexCondy"), IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1", @@ -118,7 +127,8 @@ public String getMethodDoc(StructClass structClass, StructMethod structMethod) { IFernflowerPreferences.VERIFY_ANONYMOUS_CLASSES, "1", IFernflowerPreferences.INCLUDE_ENTIRE_CLASSPATH, "0", IFernflowerPreferences.DECOMPILE_COMPLEX_CONDYS, "1", - IFernflowerPreferences.PREFERRED_LINE_LENGTH, "250" + IFernflowerPreferences.PREFERRED_LINE_LENGTH, "250", + IFernflowerPreferences.VERIFY_PRE_POST_VARIABLE_MERGES, "1" ); registerSet("Text Tokens", this::registerTextTokens, IFernflowerPreferences.DUMP_TEXT_TOKENS, "1", @@ -130,7 +140,8 @@ public String getMethodDoc(StructClass structClass, StructMethod structMethod) { IFernflowerPreferences.INCLUDE_ENTIRE_CLASSPATH, "0", IFernflowerPreferences.TERNARY_CONDITIONS, "1", IFernflowerPreferences.FORCE_JSR_INLINE, "1", - IFernflowerPreferences.PREFERRED_LINE_LENGTH, "120" + IFernflowerPreferences.PREFERRED_LINE_LENGTH, "120", + IFernflowerPreferences.VERIFY_PRE_POST_VARIABLE_MERGES, "1" ); registerSet("Synthetics Marking", this::registerSyntheticsMarking, IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1", @@ -138,7 +149,8 @@ public String getMethodDoc(StructClass structClass, StructMethod structMethod) { IFernflowerPreferences.DUMP_EXCEPTION_ON_ERROR, "0", IFernflowerPreferences.IGNORE_INVALID_BYTECODE, "1", IFernflowerPreferences.VERIFY_ANONYMOUS_CLASSES, "1", - IFernflowerPreferences.MARK_CORRESPONDING_SYNTHETICS, "1" + IFernflowerPreferences.MARK_CORRESPONDING_SYNTHETICS, "1", + IFernflowerPreferences.VERIFY_PRE_POST_VARIABLE_MERGES, "1" ); registerSet("Lambda to Anonymous Class", this::registerLambdaToAnonymousClass, IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1", @@ -149,7 +161,8 @@ public String getMethodDoc(StructClass structClass, StructMethod structMethod) { IFernflowerPreferences.INCLUDE_ENTIRE_CLASSPATH, "0", IFernflowerPreferences.TERNARY_CONDITIONS, "1", IFernflowerPreferences.FORCE_JSR_INLINE, "1", - IFernflowerPreferences.LAMBDA_TO_ANONYMOUS_CLASS, "1" + IFernflowerPreferences.LAMBDA_TO_ANONYMOUS_CLASS, "1", + IFernflowerPreferences.VERIFY_PRE_POST_VARIABLE_MERGES, "1" ); // TODO: user renamer class test } diff --git a/testData/results/pkg/TestCompoundAssignmentReplace.dec b/testData/results/pkg/TestCompoundAssignmentReplace.dec index 17e2d6d1ba..c089a1e1a9 100644 --- a/testData/results/pkg/TestCompoundAssignmentReplace.dec +++ b/testData/results/pkg/TestCompoundAssignmentReplace.dec @@ -7,6 +7,7 @@ public class TestCompoundAssignmentReplace { private int i_4; private int i_5; + // $VF: Variable merging failed for merge VarExprent[1,0]: {var1}. Code has semantic differences! public void test(int var1, int var2) { var1 += var2; var1 += var2; @@ -24,44 +25,44 @@ public class TestCompoundAssignmentReplace { class 'pkg/TestCompoundAssignmentReplace' { method 'test (II)V' { - 0 18 - 3 10 - 5 10 - 6 19 - a 11 - c 11 - d 12 - e 12 - f 12 - 10 13 - 11 13 - 12 13 - 13 13 - 15 14 - 17 14 - 18 17 - 19 17 - 1a 17 - 1b 17 - 1c 17 - 1d 18 - 1e 18 - 1f 18 - 20 18 - 21 18 - 22 19 - 23 19 - 24 19 - 25 19 - 26 19 - 27 19 - 28 20 - 29 20 - 2a 20 - 2b 20 - 2c 20 - 2d 20 - 2e 21 + 0 19 + 3 11 + 5 11 + 6 20 + a 12 + c 12 + d 13 + e 13 + f 13 + 10 14 + 11 14 + 12 14 + 13 14 + 15 15 + 17 15 + 18 18 + 19 18 + 1a 18 + 1b 18 + 1c 18 + 1d 19 + 1e 19 + 1f 19 + 20 19 + 21 19 + 22 20 + 23 20 + 24 20 + 25 20 + 26 20 + 27 20 + 28 21 + 29 21 + 2a 21 + 2b 21 + 2c 21 + 2d 21 + 2e 22 } } diff --git a/testData/results/pkg/TestGroovyClass.dec b/testData/results/pkg/TestGroovyClass.dec index d6a62f29e6..eaab965f17 100644 --- a/testData/results/pkg/TestGroovyClass.dec +++ b/testData/results/pkg/TestGroovyClass.dec @@ -10,6 +10,7 @@ import java.util.concurrent.Callable; import org.codehaus.groovy.runtime.GeneratedClosure; import org.codehaus.groovy.runtime.ScriptBytecodeAdapter; import org.codehaus.groovy.runtime.callsite.CallSite; +import org.codehaus.groovy.runtime.callsite.CallSiteArray; public class TestGroovyClass implements GroovyObject { private final TestGroovyClass.Nested n; @@ -166,364 +167,364 @@ public class TestGroovyClass implements GroovyObject { class 'pkg/TestGroovyClass' { method ' ()V' { - 1 21 - 2 21 - 3 21 - 4 21 - 6 22 - 7 22 - 8 22 - 9 23 - a 23 - b 23 - c 23 - d 23 - e 23 - f 23 - 10 23 - 11 23 - 12 23 - 13 23 - 14 23 - 15 24 - 16 24 - 17 24 - 18 24 - 19 24 - 1a 24 - 1b 24 - 1c 24 - 1d 24 - 1e 24 - 20 24 - 21 24 - 22 24 - 25 25 - 26 25 - 27 25 - 28 25 - 29 25 - 2a 25 - 2b 25 - 2c 25 - 2d 25 - 2e 25 - 2f 25 - 30 25 - 31 25 - 32 26 - 33 26 - 34 26 - 35 26 - 36 26 - 37 26 - 38 26 - 39 26 - 3a 26 - 3b 26 - 3d 26 - 3e 26 - 3f 26 - 46 27 - 47 27 - 4b 27 - 4c 27 - 4d 28 - 4e 28 - 4f 28 - 51 28 - 52 28 - 53 28 - 5b 29 - 5c 29 - 60 29 - 61 29 - 62 30 - 63 30 - 64 30 - 66 30 - 67 30 - 68 30 - 6c 31 - 6d 31 - 6e 31 - 6f 31 - 70 31 - 71 31 - 72 32 - 73 32 - 74 32 - 76 32 - 77 32 - 78 32 - 7c 33 + 1 22 + 2 22 + 3 22 + 4 22 + 6 23 + 7 23 + 8 23 + 9 24 + a 24 + b 24 + c 24 + d 24 + e 24 + f 24 + 10 24 + 11 24 + 12 24 + 13 24 + 14 24 + 15 25 + 16 25 + 17 25 + 18 25 + 19 25 + 1a 25 + 1b 25 + 1c 25 + 1d 25 + 1e 25 + 20 25 + 21 25 + 22 25 + 25 26 + 26 26 + 27 26 + 28 26 + 29 26 + 2a 26 + 2b 26 + 2c 26 + 2d 26 + 2e 26 + 2f 26 + 30 26 + 31 26 + 32 27 + 33 27 + 34 27 + 35 27 + 36 27 + 37 27 + 38 27 + 39 27 + 3a 27 + 3b 27 + 3d 27 + 3e 27 + 3f 27 + 46 28 + 47 28 + 4b 28 + 4c 28 + 4d 29 + 4e 29 + 4f 29 + 51 29 + 52 29 + 53 29 + 5b 30 + 5c 30 + 60 30 + 61 30 + 62 31 + 63 31 + 64 31 + 66 31 + 67 31 + 68 31 + 6c 32 + 6d 32 + 6e 32 + 6f 32 + 70 32 + 71 32 + 72 33 + 73 33 + 74 33 + 76 33 + 77 33 + 78 33 + 7c 34 } method 'getMetaClass ()Lgroovy/lang/MetaClass;' { - 0 39 - 1 39 - 2 39 - 3 39 - 5 39 - 6 39 - 7 39 - 8 40 - a 42 - c 42 - d 42 - e 42 - f 42 - 10 42 - 11 42 - 12 43 - 13 43 - 14 43 - 15 43 - 16 43 + 0 40 + 1 40 + 2 40 + 3 40 + 5 40 + 6 40 + 7 40 + 8 41 + a 43 + c 43 + d 43 + e 43 + f 43 + 10 43 + 11 43 + 12 44 + 13 44 + 14 44 + 15 44 + 16 44 } method 'setMetaClass (Lgroovy/lang/MetaClass;)V' { - 0 50 - 1 50 - 2 50 - 3 50 - 4 50 - 5 51 + 0 51 + 1 51 + 2 51 + 3 51 + 4 51 + 5 52 } method 'getN ()Lpkg/TestGroovyClass$Nested;' { - 0 55 - 1 55 - 2 55 - 3 55 - 4 55 + 0 56 + 1 56 + 2 56 + 3 56 + 4 56 } method 'getI ()Lpkg/TestGroovyClass$Inner;' { - 0 60 - 1 60 - 2 60 - 3 60 - 4 60 + 0 61 + 1 61 + 2 61 + 3 61 + 4 61 } method 'getR ()Ljava/lang/Runnable;' { - 0 65 - 1 65 - 2 65 - 3 65 - 4 65 + 0 66 + 1 66 + 2 66 + 3 66 + 4 66 } method 'getC ()Ljava/util/concurrent/Callable;' { - 0 70 - 1 70 - 2 70 - 3 70 - 4 70 + 0 71 + 1 71 + 2 71 + 3 71 + 4 71 } } class 'pkg/TestGroovyClass$Inner' { method ' (Lpkg/TestGroovyClass;)V' { - 1 76 - 2 76 - 3 76 - 4 76 - 10 77 - 11 77 - 12 77 - 13 78 - 14 78 - 15 78 - 16 78 - 17 78 - 18 78 - 19 79 - 1a 79 - 1b 79 - 1d 79 - 1e 79 - 1f 79 - 23 80 + 1 77 + 2 77 + 3 77 + 4 77 + 10 78 + 11 78 + 12 78 + 13 79 + 14 79 + 15 79 + 16 79 + 17 79 + 18 79 + 19 80 + 1a 80 + 1b 80 + 1d 80 + 1e 80 + 1f 80 + 23 81 } method 'getMetaClass ()Lgroovy/lang/MetaClass;' { - 0 86 - 1 86 - 2 86 - 3 86 - 5 86 - 6 86 - 7 86 - 8 87 - a 89 - c 89 - d 89 - e 89 - f 89 - 10 89 - 11 89 - 12 90 - 13 90 - 14 90 - 15 90 - 16 90 + 0 87 + 1 87 + 2 87 + 3 87 + 5 87 + 6 87 + 7 87 + 8 88 + a 90 + c 90 + d 90 + e 90 + f 90 + 10 90 + 11 90 + 12 91 + 13 91 + 14 91 + 15 91 + 16 91 } method 'setMetaClass (Lgroovy/lang/MetaClass;)V' { - 0 97 - 1 97 - 2 97 - 3 97 - 4 97 - 5 98 + 0 98 + 1 98 + 2 98 + 3 98 + 4 98 + 5 99 } } class 'pkg/TestGroovyClass$Nested' { method ' ()V' { - 1 104 - 2 104 - 3 104 - 4 104 - 6 105 - 7 105 - 8 105 - 9 106 - a 106 - b 106 - c 106 - d 106 - e 107 - f 107 - 11 107 - 12 107 - 13 107 - 16 108 + 1 105 + 2 105 + 3 105 + 4 105 + 6 106 + 7 106 + 8 106 + 9 107 + a 107 + b 107 + c 107 + d 107 + e 108 + f 108 + 11 108 + 12 108 + 13 108 + 16 109 } method 'getMetaClass ()Lgroovy/lang/MetaClass;' { - 0 114 - 1 114 - 2 114 - 3 114 - 5 114 - 6 114 - 7 114 - 8 115 - a 117 - c 117 - d 117 - e 117 - f 117 - 10 117 - 11 117 - 12 118 - 13 118 - 14 118 - 15 118 - 16 118 + 0 115 + 1 115 + 2 115 + 3 115 + 5 115 + 6 115 + 7 115 + 8 116 + a 118 + c 118 + d 118 + e 118 + f 118 + 10 118 + 11 118 + 12 119 + 13 119 + 14 119 + 15 119 + 16 119 } method 'setMetaClass (Lgroovy/lang/MetaClass;)V' { - 0 125 - 1 125 - 2 125 - 3 125 - 4 125 - 5 126 + 0 126 + 1 126 + 2 126 + 3 126 + 4 126 + 5 127 } } class 'pkg/TestGroovyClass$_closure1' { method ' (Ljava/lang/Object;Ljava/lang/Object;)V' { - 1 131 - 2 131 - 3 131 - 4 131 - 6 132 - 7 132 - 8 132 - 9 132 - a 132 - b 133 + 1 132 + 2 132 + 3 132 + 4 132 + 6 133 + 7 133 + 8 133 + 9 133 + a 133 + b 134 } method 'doCall (Ljava/lang/Object;)Ljava/lang/Object;' { - 1 136 - 2 136 - 3 136 - 4 136 - 5 137 - 6 137 - 7 137 - 8 137 - 9 137 - a 137 - b 137 - c 137 - d 137 - e 137 - f 137 - 10 137 - 11 137 + 1 137 + 2 137 + 3 137 + 4 137 + 5 138 + 6 138 + 7 138 + 8 138 + 9 138 + a 138 + b 138 + c 138 + d 138 + e 138 + f 138 + 10 138 + 11 138 } method 'doCall ()Ljava/lang/Object;' { - 1 142 - 2 142 - 3 142 - 4 142 - 5 143 - 6 143 - 7 143 - 8 143 - 9 143 - a 143 + 1 143 + 2 143 + 3 143 + 4 143 + 5 144 + 6 144 + 7 144 + 8 144 + 9 144 + a 144 } } class 'pkg/TestGroovyClass$_closure2' { method ' (Ljava/lang/Object;Ljava/lang/Object;)V' { - 1 149 - 2 149 - 3 149 - 4 149 - 6 150 - 7 150 - 8 150 - 9 150 - a 150 - b 151 + 1 150 + 2 150 + 3 150 + 4 150 + 6 151 + 7 151 + 8 151 + 9 151 + a 151 + b 152 } method 'doCall (Ljava/lang/Object;)Ljava/lang/Object;' { - 1 154 - 2 154 - 3 154 - 4 154 - 5 155 - 6 155 - 7 155 + 1 155 + 2 155 + 3 155 + 4 155 + 5 156 + 6 156 + 7 156 } method 'doCall ()Ljava/lang/Object;' { - 1 160 - 2 160 - 3 160 - 4 160 - 5 161 - 6 161 - 7 161 - 8 161 - 9 161 - a 161 + 1 161 + 2 161 + 3 161 + 4 161 + 5 162 + 6 162 + 7 162 + 8 162 + 9 162 + a 162 } } Lines mapping: -9 <-> 24 -10 <-> 26 -11 <-> 138 -12 <-> 156 +9 <-> 25 +10 <-> 27 +11 <-> 139 +12 <-> 157 diff --git a/testData/results/pkg/TestGroovyTryCatch.dec b/testData/results/pkg/TestGroovyTryCatch.dec index 92f263e3db..20f7adfb4c 100644 --- a/testData/results/pkg/TestGroovyTryCatch.dec +++ b/testData/results/pkg/TestGroovyTryCatch.dec @@ -6,6 +6,7 @@ import groovy.transform.Generated; import groovy.transform.Internal; import java.beans.Transient; import org.codehaus.groovy.runtime.callsite.CallSite; +import org.codehaus.groovy.runtime.callsite.CallSiteArray; public class TestGroovyTryCatch implements GroovyObject { @Generated @@ -67,198 +68,198 @@ public class TestGroovyTryCatch implements GroovyObject { class 'pkg/TestGroovyTryCatch' { method ' ()V' { - 1 12 - 2 12 - 3 12 - 4 12 - 6 13 - 7 13 - 8 13 - 9 14 - a 14 - b 14 - c 14 - d 14 - e 15 - f 15 - 11 15 - 12 15 - 13 15 - 16 16 + 1 13 + 2 13 + 3 13 + 4 13 + 6 14 + 7 14 + 8 14 + 9 15 + a 15 + b 15 + c 15 + d 15 + e 16 + f 16 + 11 16 + 12 16 + 13 16 + 16 17 } method 'test ()V' { - 1 19 - 2 19 - 3 19 - 4 19 - 5 23 - 6 23 - 7 23 - 8 23 - 9 23 - a 23 - b 23 - c 23 - d 23 - e 23 - f 23 - 10 23 - 11 23 - 12 23 - 13 23 - 14 23 - 15 23 - 16 23 - 17 23 - 18 23 - 19 23 - 1a 23 - 1f 24 - 20 25 - 21 25 - 22 25 - 23 25 - 24 25 - 25 25 - 26 25 - 27 25 - 28 25 - 29 25 - 2a 25 - 2b 25 - 2c 25 - 2d 25 - 2e 25 - 2f 25 - 30 25 - 31 25 - 32 25 - 33 25 - 34 25 - 35 25 - 41 30 + 1 20 + 2 20 + 3 20 + 4 20 + 5 24 + 6 24 + 7 24 + 8 24 + 9 24 + a 24 + b 24 + c 24 + d 24 + e 24 + f 24 + 10 24 + 11 24 + 12 24 + 13 24 + 14 24 + 15 24 + 16 24 + 17 24 + 18 24 + 19 24 + 1a 24 + 1f 25 + 20 26 + 21 26 + 22 26 + 23 26 + 24 26 + 25 26 + 26 26 + 27 26 + 28 26 + 29 26 + 2a 26 + 2b 26 + 2c 26 + 2d 26 + 2e 26 + 2f 26 + 30 26 + 31 26 + 32 26 + 33 26 + 34 26 + 35 26 + 41 31 } method 'test1 ()V' { - 1 33 - 2 33 - 3 33 - 4 33 - 5 37 - 6 37 - 7 37 - 8 37 - 9 37 - a 37 - b 37 - c 37 - d 37 - e 37 - f 37 - 10 37 - 11 37 - 12 37 - 13 37 - 14 37 - 15 37 - 16 37 - 17 37 - 18 37 - 19 37 - 1a 37 - 1f 38 - 20 39 - 21 39 - 22 39 - 23 39 - 24 39 - 25 39 - 26 39 - 27 39 - 28 39 - 29 39 - 2a 39 - 2b 39 - 2c 39 - 2d 39 - 2e 39 - 2f 39 - 30 39 - 31 39 - 32 39 - 33 39 - 34 39 - 35 39 - 3b 40 - 3c 41 - 3d 41 - 3e 41 - 3f 41 - 40 41 - 41 41 - 42 41 - 43 41 - 44 41 - 45 41 - 46 41 - 47 41 - 48 41 - 49 41 - 4a 41 - 4b 41 - 4c 41 - 4d 41 - 4e 41 - 4f 41 - 50 41 - 51 41 - 5f 46 + 1 34 + 2 34 + 3 34 + 4 34 + 5 38 + 6 38 + 7 38 + 8 38 + 9 38 + a 38 + b 38 + c 38 + d 38 + e 38 + f 38 + 10 38 + 11 38 + 12 38 + 13 38 + 14 38 + 15 38 + 16 38 + 17 38 + 18 38 + 19 38 + 1a 38 + 1f 39 + 20 40 + 21 40 + 22 40 + 23 40 + 24 40 + 25 40 + 26 40 + 27 40 + 28 40 + 29 40 + 2a 40 + 2b 40 + 2c 40 + 2d 40 + 2e 40 + 2f 40 + 30 40 + 31 40 + 32 40 + 33 40 + 34 40 + 35 40 + 3b 41 + 3c 42 + 3d 42 + 3e 42 + 3f 42 + 40 42 + 41 42 + 42 42 + 43 42 + 44 42 + 45 42 + 46 42 + 47 42 + 48 42 + 49 42 + 4a 42 + 4b 42 + 4c 42 + 4d 42 + 4e 42 + 4f 42 + 50 42 + 51 42 + 5f 47 } method 'getMetaClass ()Lgroovy/lang/MetaClass;' { - 0 52 - 1 52 - 2 52 - 3 52 - 5 52 - 6 52 - 7 52 - 8 53 - a 55 - c 55 - d 55 - e 55 - f 55 - 10 55 - 11 55 - 12 56 - 13 56 - 14 56 - 15 56 - 16 56 + 0 53 + 1 53 + 2 53 + 3 53 + 5 53 + 6 53 + 7 53 + 8 54 + a 56 + c 56 + d 56 + e 56 + f 56 + 10 56 + 11 56 + 12 57 + 13 57 + 14 57 + 15 57 + 16 57 } method 'setMetaClass (Lgroovy/lang/MetaClass;)V' { - 0 63 - 1 63 - 2 63 - 3 63 - 4 63 - 5 64 + 0 64 + 1 64 + 2 64 + 3 64 + 4 64 + 5 65 } } Lines mapping: -5 <-> 24 -6 <-> 24 -7 <-> 25 -8 <-> 26 -9 <-> 31 -13 <-> 38 -14 <-> 38 -15 <-> 39 -16 <-> 40 -17 <-> 41 -18 <-> 42 -19 <-> 47 +5 <-> 25 +6 <-> 25 +7 <-> 26 +8 <-> 27 +9 <-> 32 +13 <-> 39 +14 <-> 39 +15 <-> 40 +16 <-> 41 +17 <-> 42 +18 <-> 43 +19 <-> 48 diff --git a/testData/results/pkg/TestJava11StringConcat.dec b/testData/results/pkg/TestJava11StringConcat.dec index 70f4848b9f..47f7725614 100644 --- a/testData/results/pkg/TestJava11StringConcat.dec +++ b/testData/results/pkg/TestJava11StringConcat.dec @@ -34,12 +34,12 @@ class 'pkg/TestJava11StringConcat' { 0 8 1 8 2 8 - 3 8 - 4 8 - 5 8 6 8 7 8 8 8 + 9 8 + a 8 + b 8 } method 'testEmptyPrefix (I)Ljava/lang/String;' { diff --git a/testData/results/pkg/TestLVTReassignment.dec b/testData/results/pkg/TestLVTReassignment.dec index 5682c66426..573913dc0f 100644 --- a/testData/results/pkg/TestLVTReassignment.dec +++ b/testData/results/pkg/TestLVTReassignment.dec @@ -1,6 +1,7 @@ package pkg; public class TestLVTReassignment { + // $VF: Variable merging failed for merge VarExprent[1,0]: {var1}. Code has semantic differences! public void test() { double one = 1.0;// 5 one = 0.0;// 7 @@ -16,35 +17,35 @@ public class TestLVTReassignment { class 'pkg/TestLVTReassignment' { method 'test ()V' { - 0 4 - 1 4 - 2 9 - 4 5 - 5 5 - 6 6 - 7 6 - 8 6 - 9 6 - a 6 - b 6 - c 9 - d 9 - e 9 - f 9 - 10 9 - 11 10 + 0 5 + 1 5 + 2 10 + 4 6 + 5 6 + 6 7 + 7 7 + 8 7 + 9 7 + a 7 + b 7 + c 10 + d 10 + e 10 + f 10 + 10 10 + 11 11 } method 'blackhole (D)V' { - 0 13 + 0 14 } } Lines mapping: -5 <-> 5 -6 <-> 10 -7 <-> 6 -8 <-> 7 -11 <-> 10 -12 <-> 11 -16 <-> 14 +5 <-> 6 +6 <-> 11 +7 <-> 7 +8 <-> 8 +11 <-> 11 +12 <-> 12 +16 <-> 15 diff --git a/testData/results/pkg/TestLoopFinally.dec b/testData/results/pkg/TestLoopFinally.dec index 716ce5f13f..b176568606 100644 --- a/testData/results/pkg/TestLoopFinally.dec +++ b/testData/results/pkg/TestLoopFinally.dec @@ -152,7 +152,7 @@ public class TestLoopFinally { return;// 171 } else { var3; - throw var3_1;// 164 + throw var3;// 164 } } } diff --git a/testData/results/pkg/TestPatternMatchingLoops.dec b/testData/results/pkg/TestPatternMatchingLoops.dec index 8897dd8ee4..f77ef36d3d 100644 --- a/testData/results/pkg/TestPatternMatchingLoops.dec +++ b/testData/results/pkg/TestPatternMatchingLoops.dec @@ -9,7 +9,7 @@ public class TestPatternMatchingLoops { System.out.println(i);// 20 if (i != null) {// 22 var10000; - for (TestPatternMatchingLoops l : var10000_1) {// 28 + for (TestPatternMatchingLoops l : var10000) {// 28 if (l != null) {// 29 System.out.println(l);// 33 }