docs: private static void convertVals(final Object[] convertedVals,
              final Set<ReferenceEqualityKey<Object>> visitedOnPath,
              final Set<ReferenceEqualityKey<Object>> standardObjectVisited, final ClassFieldCache classFieldCache,
              final Map<ReferenceEqualityKey<Object>, JSONObject> objToJSONVal,
              final boolean onlySerializePublicFields) {
          // Pass 1: find standard objects (objects that are not of basic value type or collections/arrays/maps)
          // that have not yet been visited, and mark them as visited. Place a JSONReference placeholder in
          // convertedVals[i] to signify this. This first pass is non-recursive, so that objects are visited
          // as high up the tree as possible, since it is only the first visit of an object that shows in the
          // final JSON doc, and the rest are turned into references.
          final ReferenceEqualityKey<?>[] valKeys = new ReferenceEqualityKey<?>[convertedVals.length];
          final boolean[] needToConvert = new boolean[convertedVals.length];
          for (int i = 0; i < convertedVals.length; i++) {
              final Object val = convertedVals[i];
              // By default (for basic value types), don't convert vals
              needToConvert[i] = !JSONUtils.isBasicValueType(val);
              if (needToConvert[i] && !JSONUtils.isCollectionOrArray(val)) {
                  // If this object is a standard object or a map, check if it has already been visited
                  // elsewhere in the tree. If so, use a JSONReference instead, and mark the object
                  // as visited.
                  final ReferenceEqualityKey<Object> valKey = new ReferenceEqualityKey<>(val);
                  valKeys[i] = valKey;
                  final boolean alreadyVisited = !standardObjectVisited.add(valKey);
                  if (alreadyVisited) {
                      convertedVals[i] = new JSONReference(val);
                      needToConvert[i] = false;
                  }
              }
          }
          // Pass 2: Recursively convert items in standard objects, maps, collections and arrays to JSON objects.
          for (int i = 0; i < convertedVals.length; i++) {
              if (needToConvert[i]) {
                  // Recursively convert standard objects (if it is the first time they have been visited)
                  // and maps to JSON objects, and convert collections and arrays to JSON arrays.
                  final Object val = convertedVals[i];
                  convertedVals[i] = toJSONGraph(val, visitedOnPath, standardObjectVisited, classFieldCache,
                          objToJSONVal, onlySerializePublicFields);
                  if (!JSONUtils.isCollectionOrArray(val)) {
                      // If this object is a standard object or map, then it has not been visited before, 
                      // so save the mapping between original object and converted object
                      @SuppressWarnings("unchecked")
                      final ReferenceEqualityKey<Object> valKey = (ReferenceEqualityKey<Object>) valKeys[i];
                      objToJSONVal.put(valKey, (JSONObject) convertedVals[i]);
                  }
              }
          }
      }