From a92172c9dacf8e80889180320591b2d630e93851 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Tue, 21 Feb 2023 14:05:21 +0100 Subject: [PATCH] Start working on a JavaTX signature attribute --- .../bytecode/JavaTXSignatureAttribute.java | 24 ++++- .../target/generate/ASTToTargetAST.java | 92 +++++++++++-------- .../target/generate/GenericsResult.java | 9 +- 3 files changed, 83 insertions(+), 42 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/JavaTXSignatureAttribute.java b/src/main/java/de/dhbwstuttgart/bytecode/JavaTXSignatureAttribute.java index 30f08a8a..f185494c 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/JavaTXSignatureAttribute.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/JavaTXSignatureAttribute.java @@ -1,2 +1,24 @@ -package de.dhbwstuttgart.bytecode;public class JavaTXSignatureAttribute { +package de.dhbwstuttgart.bytecode; + +import org.objectweb.asm.*; + +public class JavaTXSignatureAttribute extends Attribute { + final String signature; + + protected JavaTXSignatureAttribute(String signature) { + super("JavaTXSignature"); + this.signature = signature; + } + + @Override + protected Attribute read(ClassReader classReader, int offset, int length, char[] charBuffer, int codeAttributeOffset, Label[] labels) { + return super.read(classReader, offset, length, charBuffer, codeAttributeOffset, labels); + } + + @Override + protected ByteVector write(ClassWriter classWriter, byte[] code, int codeLength, int maxStack, int maxLocals) { + var data = new ByteVector(); + data.putUTF8(this.signature); + return data; + } } diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 541eb761..95395f71 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -36,10 +36,12 @@ public class ASTToTargetAST { return all.stream().map(GenericsResult::new).toList(); } + record Generics(Set> javaGenerics, Set> txGenerics) {} + class Sigma { - Map>> computedGenericsOfMethods = new HashMap<>(); + Map computedGenericsOfMethods = new HashMap<>(); + Map computedGenericsOfClasses = new HashMap<>(); Map> usedTPHsOfMethods = new HashMap<>(); - Map>> computedGenericsOfClasses = new HashMap<>(); Set simplifiedConstraints = new HashSet<>(); Map concreteTypes = new HashMap<>(); @@ -134,14 +136,16 @@ public class ASTToTargetAST { } // Family of generated Generics - Set> generics(ClassOrInterface owner, Method method) { + Generics generics(ClassOrInterface owner, Method method) { if (computedGenericsOfMethods.containsKey(method)) return computedGenericsOfMethods.get(method); - Set> result = new HashSet<>(); - computedGenericsOfMethods.put(method, result); + Set> txResult = new HashSet<>(); + Set> javaResult = new HashSet<>(); + var generics = new Generics(javaResult, txResult); + computedGenericsOfMethods.put(method, generics); - var genericsOfClass = generics(owner); + var genericsOfClass = generics(owner).txGenerics(); var simplifiedConstraints = new HashSet<>(this.simplifiedConstraints); HashSet typeVariables = new HashSet<>(); @@ -178,7 +182,7 @@ public class ASTToTargetAST { if (typeVariablesOfClass.contains(typeVariable)) continue; for (var pair : simplifiedConstraints) { if (pair.left.equals(typeVariable) && typeVariables.contains(pair.right)) { - addToPairs(result, new PairTPHsmallerTPH(pair.left, equality.getOrDefault(pair.right, pair.right))); + addToPairs(txResult, new PairTPHsmallerTPH(pair.left, equality.getOrDefault(pair.right, pair.right))); typeVariables.add(pair.right); } } @@ -197,7 +201,7 @@ public class ASTToTargetAST { methodCall.getArgumentList() .getArguments() .stream() - .map(x -> x.getType()) + .map(TypableStatement::getType) .collect(Collectors.toCollection(HashSet::new)) .stream().filter(x -> x instanceof TypePlaceholder) .map(tph -> equality.getOrDefault(tph, (TypePlaceholder) tph)) @@ -221,7 +225,7 @@ public class ASTToTargetAST { if (optMethod.isEmpty()) return; var method = optMethod.get(); - var generics = generics(owner, method); + var generics = generics(owner, method).txGenerics(); // transitive and var all = transitiveClosure(generics); @@ -256,8 +260,8 @@ public class ASTToTargetAST { var newPair = new PairTPHsmallerTPH(tph, tph2); newPairs.add(newPair); - if (!containsRelation(result, newPair)) - addToPairs(result, newPair); + if (!containsRelation(txResult, newPair)) + addToPairs(txResult, newPair); continue outer; } } @@ -470,18 +474,18 @@ public class ASTToTargetAST { } if (minimalPair != null) - addToPairs(result, minimalPair); + addToPairs(txResult, minimalPair); } // All unbounded type variables (bounds not in method) outer: for (var typeVariable : typeVariables) { if (typeVariablesOfClass.contains(typeVariable)) continue; - for (var pair : result) { + for (var pair : txResult) { if (pair.getLeft().equals(typeVariable)) continue outer; } - addToPairs(result, new PairTPHequalRefTypeOrWildcardType(typeVariable, OBJECT)); + addToPairs(txResult, new PairTPHequalRefTypeOrWildcardType(typeVariable, OBJECT)); } // All unbounded bounds @@ -492,10 +496,14 @@ public class ASTToTargetAST { continue outer; } if (!typeVariablesOfClass.contains(pair.right) && typeVariables.contains(pair.right)) { - addToPairs(result, new PairTPHequalRefTypeOrWildcardType(pair.right, OBJECT)); + addToPairs(txResult, new PairTPHequalRefTypeOrWildcardType(pair.right, OBJECT)); } } - eliminateCyclesAndInfima(result); + + javaResult.addAll(txResult); // Same result until here + eliminateCycles(javaResult); + eliminateInfima(javaResult); + eliminateInfima(txResult); // For eliminating inner type variables we need to figure out which ones are actually used // TODO Maybe don't do this twice? @@ -507,13 +515,16 @@ public class ASTToTargetAST { var referenced = new HashSet<>(usedTphs); referenced.addAll(typeVariablesOfClass); - eliminateInnerTypeVariables(referenced, result); + eliminateInnerTypeVariables(referenced, javaResult); + eliminateInnerTypeVariables(referenced, txResult); usedTPHsOfMethods.put(method, usedTphs); - System.out.println(method.name + ": " + result); + equalizeTypeVariables(javaResult); - return result; + System.out.println(method.name + ": " + txResult + " & " + javaResult); + + return generics; } void findAllBounds(RefTypeOrTPHOrWildcardOrGeneric type, Set> generics) { @@ -546,21 +557,29 @@ public class ASTToTargetAST { } } - Set> generics(ClassOrInterface classOrInterface) { + Generics generics(ClassOrInterface classOrInterface) { if (computedGenericsOfClasses.containsKey(classOrInterface)) return computedGenericsOfClasses.get(classOrInterface); - Set> result = new HashSet<>(); - for (var field : classOrInterface.getFieldDecl()) { - findAllBounds(field.getType(), result); - } - computedGenericsOfClasses.put(classOrInterface, result); - eliminateCyclesAndInfima(result); - eliminateInnerTypeVariablesOfClass(classOrInterface, result); - equalizeTypeVariables(result); + Set> txResult = new HashSet<>(); + Set> javaResult = new HashSet<>(); + var generics = new Generics(javaResult, txResult); - System.out.println("Class " + classOrInterface.getClassName().getClassName() + ": " + result); - return result; + for (var field : classOrInterface.getFieldDecl()) { + findAllBounds(field.getType(), txResult); + } + computedGenericsOfClasses.put(classOrInterface, generics); + + javaResult.addAll(txResult); + eliminateCycles(javaResult); + eliminateInfima(txResult); + eliminateInfima(javaResult); + eliminateInnerTypeVariablesOfClass(classOrInterface, txResult); + eliminateInnerTypeVariablesOfClass(classOrInterface, javaResult); + equalizeTypeVariables(javaResult); + + System.out.println("Class " + classOrInterface.getClassName().getClassName() + ": " + txResult); + return generics; } void equalizeTypeVariables(Set> input) { @@ -707,11 +726,6 @@ public class ASTToTargetAST { } while (foundInfima); } - void eliminateCyclesAndInfima(Set> input) { - eliminateCycles(input); - eliminateInfima(input); - } - RefTypeOrTPHOrWildcardOrGeneric getType(RefTypeOrTPHOrWildcardOrGeneric type) { if (type instanceof TypePlaceholder tph) { if (equality.containsKey(tph)) { @@ -888,14 +902,14 @@ public class ASTToTargetAST { var genericsIter = input.getGenerics().iterator(); if (genericsIter.hasNext()) { // Add empty set of generics to cache so that it doesn't try to calculate it later - sigma.computedGenericsOfClasses.put(input, new HashSet<>()); + sigma.computedGenericsOfClasses.put(input, new Generics(new HashSet<>(), new HashSet<>())); while (genericsIter.hasNext()) { var next = genericsIter.next(); generics.addAll(convert(next)); } } else { // Generate generics only if there are no user defined ones - generics = convert(sigma.generics(input)); + generics = convert(sigma.generics(input).javaGenerics()); } TargetBlock fieldInitializer = null; @@ -956,7 +970,7 @@ public class ASTToTargetAST { var generics = sigma.generics(currentClass, input); List params = convert(input.getParameterList()); if (parameterSet.stream().noneMatch(p -> p.equals(params))) { - var convertedGenerics = collectMethodGenerics(generics, input); + var convertedGenerics = collectMethodGenerics(generics.javaGenerics(), input); result.add(new TargetConstructor(input.modifier, convertedGenerics, params, convert(input.block), fieldInitializer)); parameterSet.add(params); } @@ -975,7 +989,7 @@ public class ASTToTargetAST { var generics = sigma.generics(currentClass, input); List params = convert(input.getParameterList()); if (parameterSet.stream().noneMatch(p -> p.equals(params))) { - var convertedGenerics = collectMethodGenerics(generics, input); + var convertedGenerics = collectMethodGenerics(generics.javaGenerics(), input); result.add(new TargetMethod( input.modifier, input.name, convertedGenerics, params, diff --git a/src/main/java/de/dhbwstuttgart/target/generate/GenericsResult.java b/src/main/java/de/dhbwstuttgart/target/generate/GenericsResult.java index df7a555f..e0b736c9 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/GenericsResult.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/GenericsResult.java @@ -16,11 +16,16 @@ public class GenericsResult { } public Set> get(ClassOrInterface clazz) { - return this.sigma.computedGenericsOfClasses.getOrDefault(clazz, Set.of()); + var generics = this.sigma.computedGenericsOfClasses.get(clazz); + if (generics == null) return Set.of(); + return generics.txGenerics(); } + // TODO Compute generics if not present? public Set> get(Method method) { - return this.sigma.computedGenericsOfMethods.getOrDefault(method, Set.of()); + var generics = this.sigma.computedGenericsOfMethods.get(method); + if (generics == null) return Set.of(); + return generics.txGenerics(); } public BoundsList getBounds(RefTypeOrTPHOrWildcardOrGeneric type, ClassOrInterface clazz) {