[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