[GHC] #8199: Get rid of HEAP_ALLOCED
GHC
ghc-devs at haskell.org
Thu Nov 27 23:34:09 UTC 2014
#8199: Get rid of HEAP_ALLOCED
-------------------------------------+-------------------------------------
Reporter: ezyang | Owner: ezyang
Type: feature | Status: new
request | Milestone: 7.10.1
Priority: normal | Version: 7.7
Component: Compiler | Keywords:
Resolution: | Architecture: Unknown/Multiple
Operating System: | Difficulty: Project (more
Unknown/Multiple | than a week)
Type of failure: | Blocked By: 5435
None/Unknown | Related Tickets:
Test Case: |
Blocking: |
Differential Revisions: D207 |
-------------------------------------+-------------------------------------
Comment (by ajp):
Method 1 from the attached task may actually be made to work (at least on
Linux). The key point is that we don't have to use the memory address that
we happened to be given at startup. We can shift it to an aligned location
using MREMAP, and simply include a mb of padding at the end to avoid
trashing anything. Here's a modification of the code in the attached task
that demostrates shifting the memory address with zero copies.
{{{
┌─[anders gurney] [~/devel/alignment]
└─[139] cat test.S
.section foo,"aw"
.p2align 20
.global foo_start
.global foo_end
foo_start:
.ascii "A"
.fill 1048576
foo_end:
.ascii "B"
┌─[anders gurney] [~/devel/alignment]
└─[0] cat main.c
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/mman.h>
extern char foo_start;
extern char foo_end;
size_t mb = 1024 * 1024;
size_t round_to_mb(size_t x) {
return (x + mb - 1) & ~(mb - 1);
}
size_t main(void) {
printf("%c %c\n", foo_start, foo_end); // force libtest.so to be
loaded
printf("%p foo_start\n", &foo_start);
printf("%p foo_end\n", &foo_end);
printf("%d delta\n", &foo_end - &foo_start);
void *next_mb_aligned_address = (void *)
round_to_mb((size_t)&foo_start);
printf("%p next mb aligned address\n", next_mb_aligned_address);
void* new_address = mremap(&foo_start, 4096, 4096, MREMAP_MAYMOVE |
MREMAP_FIXED, next_mb_aligned_address);
printf("%p %p // should be the same\n", new_address,
next_mb_aligned_address);
printf("%c // should be A\n", * (char *) new_address);
printf("%c // should be B\n", foo_end);
printf("and this should segfault\n");
printf("%c\n", foo_start);
}
┌─[anders gurney] [~/devel/alignment]
└─[0] gcc test.S -shared -o libtest.so -fPIC
┌─[anders gurney] [~/devel/alignment]
└─[0] gcc -Wl,-R`pwd` -L. main.c -ltest -g -O0 -fPIC && ./a.out
/nix/store/ycmsiznf2484vbjwmj57jdy2ncyrj7fj-binutils-2.23.1/bin/ld:
warning: type and size of dynamic symbol `foo_start' are not defined
/nix/store/ycmsiznf2484vbjwmj57jdy2ncyrj7fj-binutils-2.23.1/bin/ld:
warning: type and size of dynamic symbol `foo_end' are not defined
A B
0x7f8318c95000 foo_start
0x7f8318d95001 foo_end
1048577 delta
0x7f8318d00000 next mb aligned address
0x7f8318d00000 0x7f8318d00000 // should be the same
A // should be A
B // should be B
and this should segfault
zsh: segmentation fault ./a.out
}}}
Is there sonething fundamental that would prohibit this technique from
working? It seems neater than the idea in #9706, as it
- doesn't rely on overcommit
- doesn't screw up accounting of VMA size
- doesn't "use up" the trick of putting objects in arbitrary memory
locations with MAP_FIXED. This could for example be used by an optimized
application at the app level to use 48 bit pointers for a large skiplist.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8199#comment:45>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list