Start working on a JavaTX signature attribute

This commit is contained in:
Victorious3 2023-02-21 14:05:21 +01:00
parent 24bbce8265
commit a92172c9da
3 changed files with 83 additions and 42 deletions

View File

@ -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;
}
} }

View File

@ -36,10 +36,12 @@ public class ASTToTargetAST {
return all.stream().map(GenericsResult::new).toList(); return all.stream().map(GenericsResult::new).toList();
} }
record Generics(Set<ResultPair<?, ?>> javaGenerics, Set<ResultPair<?, ?>> txGenerics) {}
class Sigma { class Sigma {
Map<Method, Set<ResultPair<?, ?>>> computedGenericsOfMethods = new HashMap<>(); Map<Method, Generics> computedGenericsOfMethods = new HashMap<>();
Map<ClassOrInterface, Generics> computedGenericsOfClasses = new HashMap<>();
Map<Method, Set<TypePlaceholder>> usedTPHsOfMethods = new HashMap<>(); Map<Method, Set<TypePlaceholder>> usedTPHsOfMethods = new HashMap<>();
Map<ClassOrInterface, Set<ResultPair<?, ?>>> computedGenericsOfClasses = new HashMap<>();
Set<PairTPHsmallerTPH> simplifiedConstraints = new HashSet<>(); Set<PairTPHsmallerTPH> simplifiedConstraints = new HashSet<>();
Map<TypePlaceholder, RefTypeOrTPHOrWildcardOrGeneric> concreteTypes = new HashMap<>(); Map<TypePlaceholder, RefTypeOrTPHOrWildcardOrGeneric> concreteTypes = new HashMap<>();
@ -134,14 +136,16 @@ public class ASTToTargetAST {
} }
// Family of generated Generics // Family of generated Generics
Set<ResultPair<?, ?>> generics(ClassOrInterface owner, Method method) { Generics generics(ClassOrInterface owner, Method method) {
if (computedGenericsOfMethods.containsKey(method)) if (computedGenericsOfMethods.containsKey(method))
return computedGenericsOfMethods.get(method); return computedGenericsOfMethods.get(method);
Set<ResultPair<?, ?>> result = new HashSet<>(); Set<ResultPair<?, ?>> txResult = new HashSet<>();
computedGenericsOfMethods.put(method, result); Set<ResultPair<?, ?>> 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); var simplifiedConstraints = new HashSet<>(this.simplifiedConstraints);
HashSet<TypePlaceholder> typeVariables = new HashSet<>(); HashSet<TypePlaceholder> typeVariables = new HashSet<>();
@ -178,7 +182,7 @@ public class ASTToTargetAST {
if (typeVariablesOfClass.contains(typeVariable)) continue; if (typeVariablesOfClass.contains(typeVariable)) continue;
for (var pair : simplifiedConstraints) { for (var pair : simplifiedConstraints) {
if (pair.left.equals(typeVariable) && typeVariables.contains(pair.right)) { 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); typeVariables.add(pair.right);
} }
} }
@ -197,7 +201,7 @@ public class ASTToTargetAST {
methodCall.getArgumentList() methodCall.getArgumentList()
.getArguments() .getArguments()
.stream() .stream()
.map(x -> x.getType()) .map(TypableStatement::getType)
.collect(Collectors.toCollection(HashSet::new)) .collect(Collectors.toCollection(HashSet::new))
.stream().filter(x -> x instanceof TypePlaceholder) .stream().filter(x -> x instanceof TypePlaceholder)
.map(tph -> equality.getOrDefault(tph, (TypePlaceholder) tph)) .map(tph -> equality.getOrDefault(tph, (TypePlaceholder) tph))
@ -221,7 +225,7 @@ public class ASTToTargetAST {
if (optMethod.isEmpty()) return; if (optMethod.isEmpty()) return;
var method = optMethod.get(); var method = optMethod.get();
var generics = generics(owner, method); var generics = generics(owner, method).txGenerics();
// transitive and // transitive and
var all = transitiveClosure(generics); var all = transitiveClosure(generics);
@ -256,8 +260,8 @@ public class ASTToTargetAST {
var newPair = new PairTPHsmallerTPH(tph, tph2); var newPair = new PairTPHsmallerTPH(tph, tph2);
newPairs.add(newPair); newPairs.add(newPair);
if (!containsRelation(result, newPair)) if (!containsRelation(txResult, newPair))
addToPairs(result, newPair); addToPairs(txResult, newPair);
continue outer; continue outer;
} }
} }
@ -470,18 +474,18 @@ public class ASTToTargetAST {
} }
if (minimalPair != null) if (minimalPair != null)
addToPairs(result, minimalPair); addToPairs(txResult, minimalPair);
} }
// All unbounded type variables (bounds not in method) // All unbounded type variables (bounds not in method)
outer: outer:
for (var typeVariable : typeVariables) { for (var typeVariable : typeVariables) {
if (typeVariablesOfClass.contains(typeVariable)) continue; if (typeVariablesOfClass.contains(typeVariable)) continue;
for (var pair : result) { for (var pair : txResult) {
if (pair.getLeft().equals(typeVariable)) if (pair.getLeft().equals(typeVariable))
continue outer; continue outer;
} }
addToPairs(result, new PairTPHequalRefTypeOrWildcardType(typeVariable, OBJECT)); addToPairs(txResult, new PairTPHequalRefTypeOrWildcardType(typeVariable, OBJECT));
} }
// All unbounded bounds // All unbounded bounds
@ -492,10 +496,14 @@ public class ASTToTargetAST {
continue outer; continue outer;
} }
if (!typeVariablesOfClass.contains(pair.right) && typeVariables.contains(pair.right)) { 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 // For eliminating inner type variables we need to figure out which ones are actually used
// TODO Maybe don't do this twice? // TODO Maybe don't do this twice?
@ -507,13 +515,16 @@ public class ASTToTargetAST {
var referenced = new HashSet<>(usedTphs); var referenced = new HashSet<>(usedTphs);
referenced.addAll(typeVariablesOfClass); referenced.addAll(typeVariablesOfClass);
eliminateInnerTypeVariables(referenced, result); eliminateInnerTypeVariables(referenced, javaResult);
eliminateInnerTypeVariables(referenced, txResult);
usedTPHsOfMethods.put(method, usedTphs); 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<ResultPair<?, ?>> generics) { void findAllBounds(RefTypeOrTPHOrWildcardOrGeneric type, Set<ResultPair<?, ?>> generics) {
@ -546,21 +557,29 @@ public class ASTToTargetAST {
} }
} }
Set<ResultPair<?, ?>> generics(ClassOrInterface classOrInterface) { Generics generics(ClassOrInterface classOrInterface) {
if (computedGenericsOfClasses.containsKey(classOrInterface)) if (computedGenericsOfClasses.containsKey(classOrInterface))
return computedGenericsOfClasses.get(classOrInterface); return computedGenericsOfClasses.get(classOrInterface);
Set<ResultPair<?, ?>> result = new HashSet<>(); Set<ResultPair<?, ?>> txResult = new HashSet<>();
for (var field : classOrInterface.getFieldDecl()) { Set<ResultPair<?, ?>> javaResult = new HashSet<>();
findAllBounds(field.getType(), result); var generics = new Generics(javaResult, txResult);
}
computedGenericsOfClasses.put(classOrInterface, result);
eliminateCyclesAndInfima(result);
eliminateInnerTypeVariablesOfClass(classOrInterface, result);
equalizeTypeVariables(result);
System.out.println("Class " + classOrInterface.getClassName().getClassName() + ": " + result); for (var field : classOrInterface.getFieldDecl()) {
return result; 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<ResultPair<?, ?>> input) { void equalizeTypeVariables(Set<ResultPair<?, ?>> input) {
@ -707,11 +726,6 @@ public class ASTToTargetAST {
} while (foundInfima); } while (foundInfima);
} }
void eliminateCyclesAndInfima(Set<ResultPair<?, ?>> input) {
eliminateCycles(input);
eliminateInfima(input);
}
RefTypeOrTPHOrWildcardOrGeneric getType(RefTypeOrTPHOrWildcardOrGeneric type) { RefTypeOrTPHOrWildcardOrGeneric getType(RefTypeOrTPHOrWildcardOrGeneric type) {
if (type instanceof TypePlaceholder tph) { if (type instanceof TypePlaceholder tph) {
if (equality.containsKey(tph)) { if (equality.containsKey(tph)) {
@ -888,14 +902,14 @@ public class ASTToTargetAST {
var genericsIter = input.getGenerics().iterator(); var genericsIter = input.getGenerics().iterator();
if (genericsIter.hasNext()) { if (genericsIter.hasNext()) {
// Add empty set of generics to cache so that it doesn't try to calculate it later // 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()) { while (genericsIter.hasNext()) {
var next = genericsIter.next(); var next = genericsIter.next();
generics.addAll(convert(next)); generics.addAll(convert(next));
} }
} else { } else {
// Generate generics only if there are no user defined ones // Generate generics only if there are no user defined ones
generics = convert(sigma.generics(input)); generics = convert(sigma.generics(input).javaGenerics());
} }
TargetBlock fieldInitializer = null; TargetBlock fieldInitializer = null;
@ -956,7 +970,7 @@ public class ASTToTargetAST {
var generics = sigma.generics(currentClass, input); var generics = sigma.generics(currentClass, input);
List<MethodParameter> params = convert(input.getParameterList()); List<MethodParameter> params = convert(input.getParameterList());
if (parameterSet.stream().noneMatch(p -> p.equals(params))) { 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)); result.add(new TargetConstructor(input.modifier, convertedGenerics, params, convert(input.block), fieldInitializer));
parameterSet.add(params); parameterSet.add(params);
} }
@ -975,7 +989,7 @@ public class ASTToTargetAST {
var generics = sigma.generics(currentClass, input); var generics = sigma.generics(currentClass, input);
List<MethodParameter> params = convert(input.getParameterList()); List<MethodParameter> params = convert(input.getParameterList());
if (parameterSet.stream().noneMatch(p -> p.equals(params))) { if (parameterSet.stream().noneMatch(p -> p.equals(params))) {
var convertedGenerics = collectMethodGenerics(generics, input); var convertedGenerics = collectMethodGenerics(generics.javaGenerics(), input);
result.add(new TargetMethod( result.add(new TargetMethod(
input.modifier, input.modifier,
input.name, convertedGenerics, params, input.name, convertedGenerics, params,

View File

@ -16,11 +16,16 @@ public class GenericsResult {
} }
public Set<ResultPair<?, ?>> get(ClassOrInterface clazz) { public Set<ResultPair<?, ?>> 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<ResultPair<?, ?>> get(Method method) { public Set<ResultPair<?, ?>> 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) { public BoundsList getBounds(RefTypeOrTPHOrWildcardOrGeneric type, ClassOrInterface clazz) {