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

Approaches for avoiding fragmentation in code memory allocation #14626

Closed
Keno opened this issue Jan 10, 2016 · 2 comments · Fixed by #16777
Closed

Approaches for avoiding fragmentation in code memory allocation #14626

Keno opened this issue Jan 10, 2016 · 2 comments · Fixed by #16777
Labels
compiler:codegen Generation of LLVM IR and native code

Comments

@Keno
Copy link
Member

Keno commented Jan 10, 2016

This is moved over from #14623. Currently LLVM's memory allocator will not write to memory that has been protected already, causing some amount of memory fragmentation. It would be good to figure out how to avoid this, while maintaining W^X memory protection guarantees.

@JeffBezanson JeffBezanson added the compiler:codegen Generation of LLVM IR and native code label Jan 10, 2016
This was referenced Jan 19, 2016
@Keno
Copy link
Member Author

Keno commented Jun 3, 2016

Ok, after a lengthy conversation between @yuyichao and myself we've come up with the following plan to address this:

As a generic fallback for Unix, use a MAP_SHARED mmap region to create two mappings to the memory region, the first of which has the appropriate permissions, the second is mapped either PROT_NONE or PROT_WRITE depending on whether we currently need to access it or not. Once we no longer need a page in the second mapping, we can also unmap it.

There are also several operating-system specific parts to take into account:

  • On Linux we can be more efficient and avoid the use of MAP_SHARED. The scheme is to map pages as MAP_PRIVATE as usual, but to either use /proc/self/mem or the appropriate userfaultfd ioctls to bypass the memory protection checks and write data to the protected page. Which to use needs to be benchmarked (and sincer the latter is only available in kernels >= 4.2, the former needs to exist as a fallback anyway). This will potentially require an additional copy, but that cost can be mitigated in LLVM (but doesn't need to be in the initial version).
  • On OS X we can use the mach_make_memory_entry_64 system call to obtain a reference to the local process's address space and establish a temporary dual mapping that way. It's worth noting that OS X allocated memory in 128MB chunks and you only ever get a reference to one chunk. Also shm_open regions can apparently not be mapped as PROT_EXEC (cf https://bugs.chromium.org/p/nativeclient/issues/detail?id=1872). It's not entirely clear that this code path is worth implementing, but avoiding MAP_SHARED may be desirable.
  • For any MAP_SHARED implementation, there need to be special considerations around fork, @yuyichao suggested the following:
if you fork,
on the child, you can just stop allocating in the shared region and create a new shm when you need to jit again
on the parent, you don't need to do anything
I guess rwdata can be a concern?
but rwdata can just use plain mmap
I wasn't planing to use dual map for rwdata anyway....
since they are, well, rw.....
and if you are paranoid about jitting on parent can be seen on the child, we can stop allocating on the parent in the shared page too
  • On Windows, one would use the regular CreateFileMapping/MapViewOfFileEx to create the requisite dual mappings.

@yuyichao Please add anything I may have forgotten.

@yuyichao
Copy link
Contributor

yuyichao commented Jun 3, 2016

For fork support, I guess throwing away the pages in the parent is potentially bad since it can happen fairly often. The fork concern also applies to many other implementations as well (/proc/self/mem and userfaultfd for example, due to shared handles, those handles needs to be reopen'd on fork too.)

yuyichao added a commit that referenced this issue Jun 6, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626
yuyichao added a commit that referenced this issue Jun 6, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626

[av skip]
yuyichao added a commit that referenced this issue Jun 6, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626

[av skip]
yuyichao added a commit that referenced this issue Jun 6, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626

[av skip]
yuyichao added a commit that referenced this issue Jun 6, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626

[av skip]
yuyichao added a commit that referenced this issue Jun 6, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626

[av skip]
yuyichao added a commit that referenced this issue Jun 7, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626
yuyichao added a commit that referenced this issue Jun 7, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626
yuyichao added a commit that referenced this issue Jun 7, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626
yuyichao added a commit that referenced this issue Jun 7, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626
yuyichao added a commit that referenced this issue Jun 7, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626
yuyichao added a commit that referenced this issue Jun 8, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626
yuyichao added a commit that referenced this issue Jun 9, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626
yuyichao added a commit that referenced this issue Jun 9, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626
yuyichao added a commit that referenced this issue Jun 9, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626
yuyichao added a commit that referenced this issue Jun 10, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626
yuyichao added a commit that referenced this issue Jun 10, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626
yuyichao added a commit that referenced this issue Jun 10, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626
yuyichao added a commit that referenced this issue Jun 11, 2016
Use various ways to reuse the page that has the page protection set in order
to avoid wasting a page of memory for each JIT event.

Fixes #14626
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler:codegen Generation of LLVM IR and native code
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants