Rewrite alloc-release-alloc sequences on Windows using VirtualAlloc2

XMLWordPrintable

    • Type: Enhancement
    • Resolution: Unresolved
    • Priority: P4
    • None
    • Affects Version/s: 27
    • Component/s: hotspot

      Historically, we only had VirtualAlloc. A reservation returned with VirtualAlloc cannot be split, and we cannot release parts of the mapping.

      For cases where we need to allocate a larger contiguous space that should then be managed and released as two or more mappings independently from each other (e.g. CDS+classspace), we needed to VirtualAlloc a large area, free it, then quickly allocate within that area the separate areas that should replace it. Obviously, this is racy, since concurrent allocations could place their areas within the just-vacated original contiguous area before we can place the replacement areas. The larger the area, the more likely this is to happen. And obviously, this is subject to OS internal ASLR rules.

      Note that this is safe as in Windows will not just replace existing areas, unlike mmap - but what would happen is that the allocation fails and the JVM does not come up.

      Similar logic we use to implement reserve_memory_aligned on Windows, where we allocate with over-alignment, then try to replace the area with the properly aligned replacement. Same problem.

      Windows now seems to have a way to split an area: Using VirtualAlloc2 with MEM_RESERVE | MEM_RESERVE_PLACEHOLDER.

      So these code sections should be rewritten.

      VirtualAlloc2 is only available since Windows 10. I don't know if we support older Windows versions; if so, we need to dynamically resolve those functions.
       
      ----

      Some more details:

      Today, we do this:
      A os::reserve_memory - VirtualAlloc(MEM_RESERVE)
      B os::commit_memory - VirtualAlloc(MEM_COMMIT)
      C os::uncommit_memory - VirtualFree(MEM_DECOMMIT)
      D os::release_memory - VirtualFree(MEM_RELEASE)

      D can only release A in its whole, not parts of it. So to get two reservations inside A, or to get a smaller one, one has to do the release-and-re-reserve game.

      If I understand the MSDN correctly, VirtualAlloc2 can be used like this:

      - Reserve: VirtualAlloc2 with MEM_RESERVE | MEM_RESERVE_PLACEHOLDER
      - Split the reservation with VirtualFree and MEM_PRESERVE_PLACEHOLDER. Now we have two mappings
      - Use VirtualAlloc2 with MEM_REPLACE_PLACEHOLDER to commit the memory or
      - Use MapViewOfFile3 to map a file in there (this would be the technique for the CDS archive in metaspaceShared.cpp)



            Assignee:
            Robert Toyonaga
            Reporter:
            Thomas Stuefe
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: