In service of #1859, I've been investigating building JitBuilder on Windows.
While longer term I want to use CMake to do these builds, I wanted to build on the already working JIT Compilation story for OpenJ9, so I have borrowed the Makefile fragments from OpenJ9 that drive windows compilation for the J9 JIT.
There's a couple of issues that I've found. Some easier to tackle than others: I want to use this issue to gather notes on the status of this, and how to proceed.
[ ] Some minor type errors, where container allocator types don't quite match what's expected. The one places that has caught this, using auto is a simple correction.
[ ] Deleted copy constructors aren't supported, so type dictionary needs to have its copy constructor made private instead.
[ ] The compiler technology uses <unistd.h> for getpid() in compiler/control/CompileMethod.cpp as part of writePerfToolEntry. I've partially dealt with this issue by wrapping the body the function in #ifndef WINDOWS, but it seems that this should be at least wrapped in #ifdef LINUX.
[ ] The build version of windows we have doesn't _seem_ to have a definition of snprintf, so I ended up temporarily working around this with
+#ifdef WINDOWS
+#define snprintf _snprintf
+#endif
but that doesn't feel like the right answer.
[ ] What to do about mmap? The JitBuilder CodeCache uses mmap directly, and as well as using mmap in
The platform issues seem like an argument in favour of reprioritizing https://github.com/eclipse/omr/issues/1642
Current sticking point is code cache @dsouzai: Could I safely just use Malloc in there? (I don't know enough about Windows NX support) to say Yay or Nay.
The mmap equivalent on Windows is VirtualAlloc
Re: NX:
To execute dynamically generated code, use VirtualAlloc to allocate memory and the VirtualProtect function to grant PAGE_EXECUTE access.
As Luc mentioned you can use VirtualAlloc on Windows as is done in DebugSegmentProvider:
That said, the question worth asking is, why was it using mmap to allocate that memory in the first place? Nothing about Relocation Data (at least from the name) implies it requires setting any sort of execute access on that memory, or that the memory needs to be page aligned. So if we only need read/write access, maybe it should be changed to use TR::RawAllocator.
I believe this goes back to the historic roots of JitBuilder. From what remember, only the PPC TOC stuff actually uses this (please verify rather than taking my word for it), so this may be a non-issue on Windows. I'm just guessing, but the TOC stuff may be sensitive to being page aligned, thus necessitating mmap.
For the mmap issue I think this would be a great opportunity for the compiler technology to start using the PortLibrary.
The compiler will very soon be linking against the port library with #2393 and #2385, which makes now a good time to revisit this issue.
For memory mapping, there is omrvmem_reserve_memory_ex, here is an example.
There is also a call for obtaining the PID:
uintptr_t
omrsysinfo_get_pid()
For snprintf, there is:
uintptr_t
omrstr_printf(char *buf, uintptr_t bufLen, const char *format, ...)
To make these calls, there is some macro-magic involved. Add this incantation to the beginning of any function making port calls:
OMRPORT_ACCESS_FROM_OMRPORT( /* port library pointer */ );
What about time API? I see sme compiler header files include
There is a time API.
About mmap: I've found this library on GitHub: mman-win32. Also, there is a replacement for dlfcn.h: dlfcn-win32. If using third party libraries is not a problem, these projects could help us to adapt the code of JitBuilder for Windows.
@samolisov thanks for looking into it! OMR can use third party libraries (though we have to follow an Eclipse process to validate the license/IP before we can incorporate their use into the project), but I think the OMR port library should provide all the underlying platform code needed to get JitBuilder up and going on Windows.
I thought about it, in my opinion as much as possible platform specific code (memory management, timer api, file api, load shared libraries, etc.) should be put in the port library. One thing I can't understand it is why the interface to the portlibrary is so difficult: we must get a VMThread, then use a macro to get the set of a function pointers and call a funtion using the chosen pointer. Is the design driven by some historic reasons or there is a way tomuse polimorphism in C code, so some OMR clients can implement their own portlibrary (OpenJ9 maybe)?
I agree with you, the port library interface is not exactly amazing. You don't need a vm thread though, you can use:
OMRPORT_ACCESS_FROM_OMRPORT(AnyPortLibraryPointer);
and hang the port library ptr from some compiler global.
I think the purpose of the table is to change function implementations at runtime, although I don't know where we actually do it. We might also use the table to obtain function pointers when calling from jitted code or the interpreter. Someone else will know more.
AFAIK, openJ9 _does_ implement a custom port library, but only to extend the table with additional entries.
Unfortunately, to get omrport library via OMRPORT_ACCESS_FROM_XXX within the compiler requires a difficult (at least for me) change in the compile controlflow: OMR_VM, OMR_VMThread or PortLibrary must be available inside the FEBase_t/allocateRelocationData, TestCompiler::CodeCacheManager::allocateCodeCacheSegment and JitBuilder::CodeCacheManager::allocateCodeCacheSegment methods. The OMR_VMThread is available via TR::Compilation, the first parameter of the FEBase<Derived>::allocateRelocationData(TR::Compilation* comp, uint32_t size) method (but as I see, the parameter is set to NULL within the codebase). No OMR_xxx is available in the **::CodeCacheManager::allocateCodeCacheSegment one. So, I think the injection of the port library pointer should be designed and the design must be accepted by committers before the changes is implemented in the code.
I've opened three pull requests to solve the compiler compilation errors on Windows (Windows API, as well as mmap, are still used there):
This is done!
Most helpful comment
For the mmap issue I think this would be a great opportunity for the compiler technology to start using the PortLibrary.