code: void free(long handle, ByteBuffer nioBuffer) {
          int memoryMapIdx = memoryMapIdx(handle);
          int bitmapIdx = bitmapIdx(handle);
  
          if (bitmapIdx != 0) { // free a subpage
              PoolSubpage<T> subpage = subpages[subpageIdx(memoryMapIdx)];
              assert subpage != null && subpage.doNotDestroy;
  
              // Obtain the head of the PoolSubPage pool that is owned by the PoolArena and synchronize on it.
              // This is need as we may add it back and so alter the linked-list structure.
              PoolSubpage<T> head = arena.findSubpagePoolHead(subpage.elemSize);
              synchronized (head) {
                  if (subpage.free(head, bitmapIdx & 0x3FFFFFFF)) {
                      return;
                  }
              }
          }
          freeBytes += runLength(memoryMapIdx);
          setValue(memoryMapIdx, depth(memoryMapIdx));
          updateParentsFree(memoryMapIdx);
  
          if (nioBuffer != null && cachedNioBuffers != null &&
                  cachedNioBuffers.size() < PooledByteBufAllocator.DEFAULT_MAX_CACHED_BYTEBUFFERS_PER_CHUNK) {
              cachedNioBuffers.offer(nioBuffer);
          }
      }
docs: Free a subpage or a run of pages
  When a subpage is freed from PoolSubpage, it might be added back to subpage pool of the owning PoolArena
  If the subpage pool in PoolArena has at least one other PoolSubpage of given elemSize, we can
  completely free the owning Page so it is available for subsequent allocations
  
  @param handle handle to free