Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ArrayTypeCache recursion exception (fix) #2119

Open
eortega-pjr opened this issue Nov 1, 2024 · 0 comments
Open

ArrayTypeCache recursion exception (fix) #2119

eortega-pjr opened this issue Nov 1, 2024 · 0 comments

Comments

@eortega-pjr
Copy link

20baf2f introduced an ArrayTypeCache which evidences the following issue when processing certain inputs:

DEBUG: Caused by: java.lang.IllegalStateException: Recursive update
DEBUG:     at java.base/java.util.concurrent.ConcurrentHashMap.transfer(ConcurrentHashMap.java:2552)
DEBUG:     at java.base/java.util.concurrent.ConcurrentHashMap.addCount(ConcurrentHashMap.java:2354)
DEBUG:     at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1776)
DEBUG:     at soot.ArrayTypeCache$1.apply(ArrayTypeCache.java:54)
DEBUG:     at soot.ArrayTypeCache$1.apply(ArrayTypeCache.java:41)
DEBUG:     at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708)
DEBUG:     at soot.ArrayTypeCache.getArrayType(ArrayTypeCache.java:82)
DEBUG:     at soot.ArrayType.v(ArrayType.java:73)
DEBUG:     at soot.asm.AsmUtil.toJimpleType(AsmUtil.java:208)
DEBUG:     at soot.asm.SootClassBuilder.visitField(SootClassBuilder.java:166)
DEBUG:     at org.objectweb.asm.ClassReader.readField(ClassReader.java:1138)
DEBUG:     at org.objectweb.asm.ClassReader.accept(ClassReader.java:740)
DEBUG:     at org.objectweb.asm.ClassReader.accept(ClassReader.java:425)
DEBUG:     at soot.asm.AsmClassSource.resolve(AsmClassSource.java:67)
DEBUG:     at soot.SootResolver.bringToHierarchyUnchecked(SootResolver.java:258)
DEBUG:     at soot.SootResolver.bringToHierarchy(SootResolver.java:225)
DEBUG:     at soot.SootResolver.bringToSignatures(SootResolver.java:298)
DEBUG:     at soot.SootResolver.bringToBodies(SootResolver.java:342)
DEBUG:     at soot.SootResolver.processResolveWorklist(SootResolver.java:171)
DEBUG:     at soot.SootResolver.resolveClass(SootResolver.java:135)
DEBUG:     at soot.Scene.loadClass(Scene.java:492)
DEBUG:     at soot.Scene.loadClassAndSupport(Scene.java:479)
DEBUG:     at soot.Scene.loadNecessaryClasses(Scene.java:1331)

This is due to computeIfAbsent being called recursively, triggering a reentrant guard in ConcurrentHashMap.

I've rewritten the ArrayTypeCache as such and found it works nicely, speeding up some of our processing by 25%:

public class ArrayTypeCache {
  private final Map<Pair<Type, Integer>, ArrayType> cache = new ConcurrentHashMap<>();
  
  public ArrayTypeCache(final Global g) {
  }

  /**
   * Returns a potentially cached array type of the given dimensions
   * @param baseType the base type (array element type)
   * @param dimensionsCurrent the number of dimensions
   * @return the array type
   */
  public ArrayType getArrayType(final Type baseType, final int dimensionsCurrent) {
    final Pair<Type, Integer> pairSearch = new Pair<>(baseType, dimensionsCurrent);
    final ArrayType result = cache.get(pairSearch);
    if (result != null) {
      return result;
    }

    Type elementType = baseType;
    for (int i = 1; i <= dimensionsCurrent; i++) {
      final ArrayType ret =
        cache.computeIfAbsent( new Pair<>(baseType, i),
                               k -> { return new ArrayType(k.getO1(), k.getO2()); });
      elementType.setArrayType(ret);
      elementType = ret;
    }

    return cache.get(pairSearch);
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant