Kaynağa Gözat

Updated to bdwgc 8.2.0.ea9845c

Brucey 3 yıl önce
ebeveyn
işleme
667cbef062
100 değiştirilmiş dosya ile 28772 ekleme ve 2316 silme
  1. 453 0
      blitz.mod/bdwgc/AUTHORS
  2. 754 0
      blitz.mod/bdwgc/CMakeLists.txt
  3. 10334 0
      blitz.mod/bdwgc/ChangeLog
  4. 5 0
      blitz.mod/bdwgc/Config.cmake.in
  5. 33 0
      blitz.mod/bdwgc/LICENSE
  6. 256 0
      blitz.mod/bdwgc/Makefile.am
  7. 436 0
      blitz.mod/bdwgc/Makefile.direct
  8. 191 0
      blitz.mod/bdwgc/NT_MAKEFILE
  9. 64 0
      blitz.mod/bdwgc/OS2_MAKEFILE
  10. 47 0
      blitz.mod/bdwgc/PCR-Makefile
  11. 586 0
      blitz.mod/bdwgc/README.md
  12. 174 0
      blitz.mod/bdwgc/SMakefile.amiga
  13. 291 0
      blitz.mod/bdwgc/WCC_MAKEFILE
  14. 100 9
      blitz.mod/bdwgc/allchblk.c
  15. 170 46
      blitz.mod/bdwgc/alloc.c
  16. 18 0
      blitz.mod/bdwgc/autogen.sh
  17. 8 6
      blitz.mod/bdwgc/backgraph.c
  18. 10 0
      blitz.mod/bdwgc/bdw-gc.pc.in
  19. 11 0
      blitz.mod/bdwgc/blacklst.c
  20. 78 0
      blitz.mod/bdwgc/build/s60v3/libgc.mmp
  21. 2 2
      blitz.mod/bdwgc/checksums.c
  22. 1191 0
      blitz.mod/bdwgc/configure.ac
  23. 40 0
      blitz.mod/bdwgc/cord/cord.am
  24. 943 0
      blitz.mod/bdwgc/cord/cordbscs.c
  25. 446 0
      blitz.mod/bdwgc/cord/cordprnt.c
  26. 639 0
      blitz.mod/bdwgc/cord/cordxtra.c
  27. 325 0
      blitz.mod/bdwgc/cord/tests/cordtest.c
  28. 641 0
      blitz.mod/bdwgc/cord/tests/de.c
  29. 31 0
      blitz.mod/bdwgc/cord/tests/de_cmds.h
  30. 387 0
      blitz.mod/bdwgc/cord/tests/de_win.c
  31. 97 0
      blitz.mod/bdwgc/cord/tests/de_win.h
  32. 70 0
      blitz.mod/bdwgc/cord/tests/de_win.rc
  33. 12 9
      blitz.mod/bdwgc/darwin_stop_world.c
  34. 6 6
      blitz.mod/bdwgc/dbg_mlc.c
  35. 102 0
      blitz.mod/bdwgc/digimars.mak
  36. 39 0
      blitz.mod/bdwgc/doc/README.DGUX386
  37. 332 0
      blitz.mod/bdwgc/doc/README.Mac
  38. 6 0
      blitz.mod/bdwgc/doc/README.OS2
  39. 9 0
      blitz.mod/bdwgc/doc/README.aix
  40. 284 0
      blitz.mod/bdwgc/doc/README.amiga
  41. 62 0
      blitz.mod/bdwgc/doc/README.arm.cross
  42. 59 0
      blitz.mod/bdwgc/doc/README.autoconf
  43. 62 0
      blitz.mod/bdwgc/doc/README.cmake
  44. 40 0
      blitz.mod/bdwgc/doc/README.cords
  45. 81 0
      blitz.mod/bdwgc/doc/README.darwin
  46. 15 0
      blitz.mod/bdwgc/doc/README.emscripten
  47. 185 0
      blitz.mod/bdwgc/doc/README.environment
  48. 81 0
      blitz.mod/bdwgc/doc/README.ews4800
  49. 18 0
      blitz.mod/bdwgc/doc/README.hp
  50. 127 0
      blitz.mod/bdwgc/doc/README.linux
  51. 605 0
      blitz.mod/bdwgc/doc/README.macros
  52. 39 0
      blitz.mod/bdwgc/doc/README.sgi
  53. 68 0
      blitz.mod/bdwgc/doc/README.solaris2
  54. 11 0
      blitz.mod/bdwgc/doc/README.symbian
  55. 2 0
      blitz.mod/bdwgc/doc/README.uts
  56. 215 0
      blitz.mod/bdwgc/doc/README.win32
  57. 27 0
      blitz.mod/bdwgc/doc/README.win64
  58. 273 0
      blitz.mod/bdwgc/doc/debugging.md
  59. 158 0
      blitz.mod/bdwgc/doc/finalization.md
  60. 546 0
      blitz.mod/bdwgc/doc/gcdescr.md
  61. 216 0
      blitz.mod/bdwgc/doc/gcinterface.md
  62. 160 0
      blitz.mod/bdwgc/doc/leak.md
  63. 310 0
      blitz.mod/bdwgc/doc/overview.md
  64. 263 0
      blitz.mod/bdwgc/doc/porting.md
  65. 172 0
      blitz.mod/bdwgc/doc/scale.md
  66. 182 0
      blitz.mod/bdwgc/doc/simple_example.md
  67. 175 0
      blitz.mod/bdwgc/doc/tree.md
  68. 45 44
      blitz.mod/bdwgc/dyn_load.c
  69. 544 0
      blitz.mod/bdwgc/extra/AmigaOS.c
  70. 169 0
      blitz.mod/bdwgc/extra/MacOS.c
  71. 27 0
      blitz.mod/bdwgc/extra/Mac_files/MacOS_config.h
  72. 9 0
      blitz.mod/bdwgc/extra/Mac_files/dataend.c
  73. 9 0
      blitz.mod/bdwgc/extra/Mac_files/datastart.c
  74. 93 0
      blitz.mod/bdwgc/extra/gc.c
  75. 392 0
      blitz.mod/bdwgc/extra/msvc_dbg.c
  76. 181 0
      blitz.mod/bdwgc/extra/pcr_interface.c
  77. 39 0
      blitz.mod/bdwgc/extra/real_malloc.c
  78. 52 0
      blitz.mod/bdwgc/extra/symbian.cpp
  79. 10 0
      blitz.mod/bdwgc/extra/symbian/global_end.cpp
  80. 10 0
      blitz.mod/bdwgc/extra/symbian/global_start.cpp
  81. 28 0
      blitz.mod/bdwgc/extra/symbian/init_global_static_roots.cpp
  82. 6 21
      blitz.mod/bdwgc/finalize.c
  83. 2 2
      blitz.mod/bdwgc/fnlz_mlc.c
  84. 155 0
      blitz.mod/bdwgc/gc.man
  85. 1 1
      blitz.mod/bdwgc/gc_dlopen.c
  86. 27 19
      blitz.mod/bdwgc/headers.c
  87. 2 2151
      blitz.mod/bdwgc/include/gc.h
  88. 0 0
      blitz.mod/bdwgc/include/gc/cord.h
  89. 0 0
      blitz.mod/bdwgc/include/gc/cord_pos.h
  90. 0 0
      blitz.mod/bdwgc/include/gc/ec.h
  91. 2172 0
      blitz.mod/bdwgc/include/gc/gc.h
  92. 0 0
      blitz.mod/bdwgc/include/gc/gc_allocator.h
  93. 0 0
      blitz.mod/bdwgc/include/gc/gc_backptr.h
  94. 458 0
      blitz.mod/bdwgc/include/gc/gc_config_macros.h
  95. 568 0
      blitz.mod/bdwgc/include/gc/gc_cpp.h
  96. 0 0
      blitz.mod/bdwgc/include/gc/gc_disclaim.h
  97. 0 0
      blitz.mod/bdwgc/include/gc/gc_gcj.h
  98. 0 0
      blitz.mod/bdwgc/include/gc/gc_inline.h
  99. 0 0
      blitz.mod/bdwgc/include/gc/gc_mark.h
  100. 0 0
      blitz.mod/bdwgc/include/gc/gc_pthread_redirects.h

+ 453 - 0
blitz.mod/bdwgc/AUTHORS

@@ -0,0 +1,453 @@
+This is an attempt to acknowledge contributions to the garbage collector.
+Early contributions also mentioned (duplicated) in ChangeLog file; details of
+later ones should be in "git log".
+
+Currently maintained by Ivan Maidanski.
+
+HISTORY -
+
+  Early versions of this collector were developed as a part of research
+projects supported in part by the National Science Foundation
+and the Defense Advance Research Projects Agency.
+
+The garbage collector originated as part of the run-time system for
+the Russell programming language implementation. The first version of the
+garbage collector was written primarily by Alan Demers.  It was then refined
+and mostly rewritten, primarily by Hans-J. Boehm, at Cornell U.,
+the University of Washington, Rice University (where it was first used for
+C and assembly code), Xerox PARC, SGI, and HP Labs.  However, significant
+contributions have also been made by many others.
+
+Other contributors (my apologies for any omissions):
+
+Adam Megacz <[email protected]>
+Adnan Ali
+Adrian Bunk <[email protected]>
+Adrian Pop <[email protected]>
+Akira Tagoh <[email protected]>
+Alain Novak <[email protected]>
+Alan Dosser <[email protected]>
+Alan J. Demers <[email protected]>
+Alaskan Emily <[email protected]>
+Aleksey Demakov <[email protected]>
+Alessandro Bruni <[email protected]>
+Alex Ronne Petersen <[email protected]>
+Alexander Belchenko <[email protected]>
+Alexander Gavrilov <[email protected]>
+Alexander Herz <[email protected]>
+Alexandr Petrosian <[email protected]>
+Alexandr Shadchin <[email protected]>
+Alexandre Oliva <[email protected]>
+Alexis Laferriere <[email protected]>
+Alistair G. Crooks <[email protected]>
+Allan Hsu <[email protected]>
+Andre Leiradella <[email protected]>
+Andreas Jaeger <[email protected]>
+Andreas Tobler <[email protected]>
+Andrei Polushin <[email protected]>
+Andrej Cedilnik <[email protected]>
+Andrew Begel <[email protected]>
+Andrew Buss <[email protected]>
+Andrew Gray <[email protected]>
+Andrew Haley <[email protected]>
+Andrew Horton <[email protected]>
+Andrew McKinlay <[email protected]>
+Andrew Pinski <[email protected]>
+Andrew Stitcher <[email protected]>
+Andrew Stone <[email protected]>
+Andrew Whatson <[email protected]>
+Andy Li <[email protected]>
+Andy Wingo <[email protected]>
+Anselm Baird-Smith <[email protected]>
+Anthony Green <[email protected]>
+Antoine de Maricourt
+Ari Huttunen <[email protected]>
+Arrigo Triulzi <[email protected]>
+Ashley Bone <[email protected]>
+Assar Westerlund <[email protected]>
+Aurelien Larcher <[email protected]>
+Barry DeFreese <[email protected]>
+Baruch Siach <[email protected]>
+Ben A. Mesander <[email protected]>
+Ben Cottrell <[email protected]>
+Ben Hutchings <[email protected]>
+Ben Maurer <[email protected]>
+Benjamin Lerman <[email protected]>
+Bernd Edlinger <[email protected]>
+Bernd Kuhls <[email protected]>
+Bernie Solomon <[email protected]>
+Bill Janssen <[email protected]>
+Bo Thorsen <[email protected]>
+Bradley D. LaRonde <[email protected]>
+Bradley Smith <[email protected]>
+Brent Benson <[email protected]>
+Brian Alliet <[email protected]>
+Brian Beuning <[email protected]>
+Brian Burton <[email protected]>
+Brian D. Carlstrom <[email protected]>
+Brian F. Dennis <[email protected]>
+Brian J. Cardiff <[email protected]>
+Brian Lewis <[email protected]>
+Bruce A Henderson <[email protected]>
+Bruce Hoult <[email protected]>
+Bruce Mitchener <[email protected]>
+Bruno Haible <[email protected]>
+Bryce McKinlay <[email protected]>
+Burkhard Linke <[email protected]>
+Calvin Buckley <[email protected]>
+Carlos J. Puga Medina <[email protected]>
+Cesar Eduardo Barros <[email protected]>
+Charles Fiterman <[email protected]>
+Charles Mills <[email protected]>
+Chris Dodd <[email protected]>
+Chris Lingard <[email protected]>
+Chris Metcalf <[email protected]>
+Christian Joensson <[email protected]>
+Christian Limpach <[email protected]>
+Christian Thalinger <[email protected]>
+Christian Weisgerber <[email protected]>
+Christoffe Raffali <[email protected]>
+Clay Spence <[email protected]>
+Clement Chigot <[email protected]>
+Colin LeMahieu <[email protected]>
+Craig McDaniel <[email protected]>
+Dai Sato <[email protected]>
+Dan Bonachea <[email protected]>
+Dan Fandrich <[email protected]>
+Dan Sullivan <[email protected]>
+Daniel R. Grayson <[email protected]>
+Danny Smith <[email protected]>
+Darrell Schiebel <[email protected]>
+Dave Barrett <[email protected]>
+Dave Detlefs <[email protected]>
+Dave Korn <[email protected]>
+Dave Love <[email protected]>
+David Ayers <[email protected]>
+David Brownlee <[email protected]>
+David Butenhof <[email protected]>
+David Chase <[email protected]>
+David Daney <[email protected]>
+David Grove <[email protected]>
+David Leonard <[email protected]>
+David Miller <[email protected]>
+David Mosberger <[email protected]>
+David Peroutka <[email protected]>
+David Pickens <[email protected]>
+David Stes <[email protected]>
+David Terei <[email protected]>
+David Van Horn <[email protected]>
+Davide Angelocola <[email protected]>
+Demyan Kimitsa <[email protected]>
+Dick Porter <[email protected]>
+Dietmar Planitzer <[email protected]>
+Dima Pasechnik <[email protected]>
+Dimitris Vyzovitis <[email protected]>
+Dimitry Andric <[email protected]>
+Djamel Magri <[email protected]>
+Doug Kaufman <[email protected]>
+Doug Moen <[email protected]>
+Douglas Steel <[email protected]>
+Eli Barzilay <[email protected]>
+Elijah Taylor <[email protected]>
+Elvenlord Elrond <[email protected]>
+Emmanual Stumpf
+Eric Benson <[email protected]>
+Eric Holk <[email protected]>
+Erik M. Bray <[email protected]>
+Fabian Thylman
+Fabrice Fontaine <[email protected]>
+Fergus Henderson <[email protected]>
+Franklin Chen <[email protected]>
+Fred Gilham <[email protected]>
+Fred Stearns
+Friedrich Dominicus <[email protected]>
+Gabor Drescher <[email protected]>
+Gary Leavens <[email protected]>
+Geoff Norton <[email protected]>
+George Koehler <[email protected]>
+George Talbot <[email protected]>
+Gerard A Allan
+Glauco Masotti <[email protected]>
+Grzegorz Jakacki <[email protected]>
+Gustavo Giraldez <[email protected]>
+Gustavo Rodriguez-Rivera <[email protected]>
+H.J. Lu <[email protected]>
+Hamayama <[email protected]>
+Hannes Mehnert <[email protected]>
+Hanno Boeck <[email protected]>
+Hans Boehm <[email protected]>
+Hans-Peter Nilsson <[email protected]>
+Henning Makholm <[email protected]>
+Henrik Theiling <[email protected]>
+Hironori Sakamoto <[email protected]>
+Hiroshi Kawashima <[email protected]>
+Hiroshi Yokota <[email protected]>
+Hubert Garavel <[email protected]>
+Iain Sandoe <[email protected]>
+Ian Piumarta <[email protected]>
+Ian Searle <[email protected]>
+Igor Khavkine <[email protected]>
+Ivan Demakov <[email protected]>
+Ivan Maidanski <[email protected]>
+Ivan R <[email protected]>
+Jaap Boender <[email protected]>
+Jack Andrews <[email protected]>
+Jacob Navia <[email protected]>
+Jakub Jelinek <[email protected]>
+Jakub Wojciech <[email protected]>
+James Clark <[email protected]>
+James Dominy
+James Moran <[email protected]>
+Jan Alexander Steffens <[email protected]>
+Jan Wielemaker <[email protected]>
+Jani Kajala <[email protected]>
+Jared McNeill <[email protected]>
+Jasper Lievisse Adriaanse <[email protected]>
+Jay Krell <[email protected]>
+Jean-Baptiste Nivois
+Jean-Claude Beaudoin <[email protected]>
+Jean-Daniel Fekete <[email protected]>
+Jeff Sturm <[email protected]>
+Jeffrey Hsu <[email protected]>
+Jeffrey Mark Siskind
+Jeremy Fitzhardinge <[email protected]>
+Jesper Peterson <[email protected]>
+Jesse Hull <[email protected]>
+Jesse Jones <[email protected]>
+Jesse Rosenstock <[email protected]>
+Ji-Yong Chung
+Jie Liu <[email protected]>
+Jim Marshall <[email protected]>
+Jim Meyering <[email protected]>
+Joao Abecasis <[email protected]>
+Joerg Sonnenberger <[email protected]>
+Johannes Schmidt <[email protected]>
+Johannes Totz <[email protected]>
+John Bowman <[email protected]>
+John Clements <[email protected]>
+John David Anglin <[email protected]>
+John Ellis <[email protected]>
+John Ericson <[email protected]>
+John Merryweather Cooper <[email protected]>
+Jon Moore <[email protected]>
+Jonas Echterhoff <[email protected]>
+Jonas Hahnfeld <[email protected]>
+Jonathan Bachrach <[email protected]>
+Jonathan Chambers <[email protected]>
+Jonathan Clark
+Jonathan Pryor <[email protected]>
+Josh Peterson <[email protected]>
+Joshua Richardson <[email protected]>
+Juan Jose Garcia-Ripoll <[email protected]>
+Jukka Jylanki <[email protected]>
+Kai Tietz <[email protected]>
+Kaz Kojima <[email protected]>
+Kazu Hirata <[email protected]>
+Kazuhiro Inaoka <[email protected]>
+Keith Seitz <[email protected]>
+Kenjiro Taura <[email protected]>
+Kenneth Schalk <[email protected]>
+Kevin Kenny <[email protected]>
+Kevin Tew <[email protected]>
+Kevin Warne <[email protected]>
+Kimura Wataru <[email protected]>
+Kjetil Matheussen <[email protected]>
+Klaus Treichel <[email protected]>
+Klemens Zwischenbrugger <[email protected]>
+Knut Tvedten <[email protected]>
+Krister Walfridsson <[email protected]>
+Kristian Kristensen <[email protected]>
+Kumar Srikantan
+Kurt Miller <[email protected]>
+Lars Farm <[email protected]>
+Laurent Morichetti <[email protected]>
+Leonardo Taccari <[email protected]>
+Linas Vepstas <[email protected]>
+Loren J. Rittle <[email protected]>
+Louis Zhuang <[email protected]>
+Lucas Meijer <[email protected]>
+Ludovic Courtes <[email protected]>
+Maarten Thibaut <[email protected]>
+Mahder Gebremedhin <[email protected]>
+Manuel A. Fernandez Montecelo <[email protected]>
+Manuel Serrano <[email protected]>
+Marc Recht <[email protected]>
+Marco Maggi <[email protected]>
+Marcos Dione <[email protected]>
+Marcus Herbert
+Marek Vasut <[email protected]>
+Margaret Fleck <[email protected]>
+Mark Boulter <[email protected]>
+Mark Mitchell <[email protected]>
+Mark Reichert <[email protected]>
+Mark Sibly
+Mark Weiser <[email protected]>
+Martin Hirzel <[email protected]>
+Martin Koeppe <[email protected]>
+Martin Tauchmann <[email protected]>
+Massimiliano Gubinelli <[email protected]>
+Matheus Rambo <[email protected]>
+Matt Austern <[email protected]>
+Matthew Flatt <[email protected]>
+Matthias Andree <[email protected]>
+Matthias Drochner <[email protected]>
+Matthieu Herrb <[email protected]>
+Maurizio Vairani <[email protected]>
+Max Mouratov <[email protected]>
+Maya Rashish <[email protected]>
+Melissa O'Neill <[email protected]>
+Michael Arnoldus <[email protected]>
+Michael DeRoy <[email protected]>
+Michael Fox <[email protected]>
+Michael Herring <[email protected]>
+Michael Smith <[email protected]>
+Michael Spertus <[email protected]>
+Michel Schinz <[email protected]>
+Miguel de Icaza <[email protected]>
+Mikael Djurfeldt <[email protected]>
+Mike Frysinger <[email protected]>
+Mike Gran <[email protected]>
+Mike McGaughey <[email protected]>
+Mike Stump <[email protected]>
+Mitch Harris <[email protected]>
+Mohan Embar <[email protected]>
+Naoyuki Sawa <[email protected]>
+Nathanael Nerode <[email protected]>
+Neale Ferguson <[email protected]>
+Neil Sharman <[email protected]>
+Nguyen Thai Ngoc Duy <[email protected]>
+Nicolas Cannasse <[email protected]>
+Niibe Yutaka <[email protected]>
+Nikita Ermakov <[email protected]>
+Niklas Therning <[email protected]>
+Noah Lavine <[email protected]>
+Nobuyuki Hikichi <[email protected]>
+Oliver Kurth <[email protected]>
+Ondrej Bilka <[email protected]>
+Paolo Molaro <[email protected]>
+Parag Patel <[email protected]>
+Patrick Bridges <[email protected]>
+Patrick C. Beard <[email protected]>
+Patrick Doyle <[email protected]>
+Paul Bone <[email protected]>
+Paul Brook <[email protected]>
+Paul Graham
+Paul Nash <[email protected]>
+Per Bothner <[email protected]>
+Peter Bigot <[email protected]>
+Peter Budai <[email protected]>
+Peter Chubb <[email protected]>
+Peter Colson <[email protected]>
+Peter Housel <[email protected]>
+Peter Monks <[email protected]>
+Peter Ross <[email protected]>
+Peter Seebach <[email protected]>
+Peter Wang <[email protected]>
+Petr Krajca <[email protected]>
+Petr Salinger <[email protected]>
+Petter Urkedal <[email protected]>
+Philip Brown <[email protected]>
+Philipp Tomsich <[email protected]>
+Philippe Queinnec <[email protected]>
+Phillip Musumeci <[email protected]>
+Phong Vo <[email protected]>
+Pierre de Rop
+Pontus Rydin <[email protected]>
+Radek Polak <[email protected]>
+Rainer Orth <[email protected]>
+Ranjit Mathew <[email protected]>
+Rauli Ruohonen <[email protected]>
+Regis Cridlig <[email protected]>
+Reimer Behrends <[email protected]>
+Renaud Blanch <[email protected]>
+Rene Girard
+Rex Dieter <[email protected]>
+Reza Shahidi
+Richard Earnshaw <[email protected]>
+Richard Henderson <[email protected]>
+Richard Sandiford <[email protected]>
+Richard Zidlicky <[email protected]>
+Rob Haack <[email protected]>
+Robert Brazile <[email protected]>
+Rodrigo Kumpera <[email protected]>
+Roger Sayle <[email protected]>
+Roland McGrath <[email protected]>
+Roman Hodek <[email protected]>
+Romain Naour <[email protected]>
+Romano Paolo Tenca <[email protected]>
+Rutger Ovidius <[email protected]>
+Ryan Gonzalez <[email protected]>
+Ryan Murray <[email protected]>
+Salvador Eduardo Tropea <[email protected]>
+Samuel Martin <[email protected]>
+Samuel Thibault <[email protected]>
+Scott Ananian <[email protected]>
+Scott Ferguson <[email protected]>
+Scott Schwartz <[email protected]>
+Shawn Wagner <[email protected]>
+Shea Levy <[email protected]>
+Shiro Kawai <[email protected]>
+Simon Gornall <[email protected]>
+Simon Posnjak <[email protected]>
+Slava Sysoltsev <[email protected]>
+Sorawee Porncharoenwase <[email protected]>
+ssrlive <[email protected]>
+Stefan Ring <[email protected]>
+Stefano Rivera <[email protected]>
+Steve Youngs <[email protected]>
+Sugioka Toshinobu <[email protected]>
+Suzuki Toshiya <[email protected]>
+Sven Hartrumpf <[email protected]>
+Sven Verdoolaege <[email protected]>
+Takis Psarogiannakopoulos <[email protected]>
+Tatsuya Bizenn <[email protected]>
+Tautvydas Zilys <[email protected]>
+Terrell Russell <[email protected]>
+Thiemo Seufer <[email protected]>
+Thomas Funke <[email protected]>
+Thomas Klausner <[email protected]>
+Thomas Linder Puls <[email protected]>
+Thomas Maier <[email protected]>
+Thomas Schwinge <[email protected]>
+Thomas Thiriez <[email protected]>
+Thorsten Glaser <[email protected]>
+Tilman Vogel <[email protected]>
+Tim Bingham <[email protected]>
+Tim Cannell <[email protected]>
+Tim Gates <[email protected]>
+Timothy N. Newsham <[email protected]>
+Tom Tromey <[email protected]>
+Tommaso Tagliapietra <[email protected]>
+Toralf Foerster <[email protected]>
+Toshio Endo <[email protected]>
+Tsugutomo Enami <[email protected]>
+Tum Nguyen <[email protected]>
+Tyson Dowd <[email protected]>
+Uchiyama Yasushi <[email protected]>
+Ulrich Drepper <[email protected]>
+Ulrich Weigand <[email protected]>
+Uros Bizjak <[email protected]>
+Vernon Lee <[email protected]>
+Victor Ivrii <[email protected]>
+Victor Romero <[email protected]>
+Vineet Gupta <[email protected]>
+Vitaly Magerya <[email protected]>
+Vladimir Tsichevski <[email protected]>
+Walter Bright <[email protected]>
+Walter Underwood <[email protected]>
+Wilson Ho <[email protected]>
+Wink Saville <[email protected]>
+Wookey <[email protected]>
+Xi Wang <[email protected]>
+Xiaokun Zhu <[email protected]>
+Yann Dirson <[email protected]>
+Yannis Bres <[email protected]>
+Yasuhiro Kimura <[email protected]>
+Yuki Okumura <[email protected]>
+Yusuke Suzuki <[email protected]>
+Yvan Roux <[email protected]>
+Zach Saw <[email protected]>
+Zhang Na <[email protected]>
+Zhiying Chen
+Zhong Shao <[email protected]>
+Zoltan Varga <[email protected]>

+ 754 - 0
blitz.mod/bdwgc/CMakeLists.txt

@@ -0,0 +1,754 @@
+#
+# Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
+# Copyright (c) 1996 by Silicon Graphics.  All rights reserved.
+# Copyright (c) 1998 by Fergus Henderson.  All rights reserved.
+# Copyright (c) 2000-2010 by Hewlett-Packard Company.  All rights reserved.
+# Copyright (c) 2010-2021 Ivan Maidanski
+##
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+##
+# Permission is hereby granted to use or copy this program
+# for any purpose,  provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is granted,
+# provided the above notices are retained, and a notice that the code was
+# modified is included with the above copyright notice.
+##
+
+#
+#  get cmake and run:
+#    cmake -G "Visual Studio 8 2005"
+#  in the same dir as this file
+#  this will generate gc.sln
+#
+
+cmake_minimum_required(VERSION 3.1)
+
+set(PACKAGE_VERSION 8.3.0)
+# Version must match that in AC_INIT of configure.ac and that in README.
+# Version must conform to: [0-9]+[.][0-9]+[.][0-9]+
+
+# Info (current:revision:age) for the Libtool versioning system.
+# These values should match those in cord/cord.am and Makefile.am.
+set(LIBCORD_VER_INFO    5:0:4)
+set(LIBGC_VER_INFO      6:0:5)
+set(LIBGCCPP_VER_INFO   6:0:5)
+
+option(enable_cplusplus "C++ support" OFF)
+if (enable_cplusplus)
+  project(gc)
+else()
+  project(gc C)
+endif()
+
+include(CheckCCompilerFlag)
+include(CheckCSourceCompiles)
+include(CheckFunctionExists)
+include(CheckIncludeFile)
+include(CheckSymbolExists)
+include(CMakePackageConfigHelpers)
+include(CTest)
+include(GNUInstallDirs)
+
+# Customize the build by passing "-D<option_name>=ON|OFF" in the command line.
+option(BUILD_SHARED_LIBS "Build shared libraries" ON)
+option(build_cord "Build cord library" ON)
+option(build_tests "Build tests" OFF)
+option(enable_docs "Build and install documentation" ON)
+option(enable_threads "Support threads" ON)
+option(enable_parallel_mark "Parallelize marking and free list construction" ON)
+option(enable_thread_local_alloc "Turn on thread-local allocation optimization" ON)
+option(enable_threads_discovery "Enable threads discovery in GC" ON)
+option(enable_throw_bad_alloc_library "Turn on C++ gctba library build" ON)
+option(enable_gcj_support "Support for gcj" ON)
+option(enable_sigrt_signals "Use SIGRTMIN-based signals for thread suspend/resume" OFF)
+option(enable_gc_debug "Support for pointer back-tracing" OFF)
+option(disable_gc_debug "Disable debugging like GC_dump and its callees" OFF)
+option(enable_java_finalization "Support for java finalization" ON)
+option(enable_atomic_uncollectable "Support for atomic uncollectible allocation" ON)
+option(enable_redirect_malloc "Redirect malloc and friends to GC routines" OFF)
+option(enable_disclaim "Support alternative finalization interface" ON)
+option(enable_large_config "Optimize for large heap or root set" OFF)
+option(enable_gc_assertions "Enable collector-internal assertion checking" OFF)
+option(enable_mmap "Use mmap instead of sbrk to expand the heap" OFF)
+option(enable_munmap "Return page to the OS if empty for N collections" ON)
+option(enable_dynamic_loading "Enable tracing of dynamic library data roots" ON)
+option(enable_register_main_static_data "Perform the initial guess of data root sets" ON)
+option(enable_checksums "Report erroneously cleared dirty bits" OFF)
+option(enable_werror "Pass -Werror to the C compiler (treat warnings as errors)" OFF)
+option(enable_single_obj_compilation "Compile all libgc source files into single .o" OFF)
+option(enable_handle_fork "Attempt to ensure a usable collector after fork()" ON)
+option(disable_handle_fork "Prohibit installation of pthread_atfork() handlers" OFF)
+option(install_headers "Install header and pkg-config metadata files" ON)
+
+# Convert VER_INFO values to [SO]VERSION ones.
+if (BUILD_SHARED_LIBS)
+  # cord:
+  string(REGEX REPLACE "(.+):.+:.+"  "\\1" cord_cur ${LIBCORD_VER_INFO})
+  string(REGEX REPLACE ".+:(.+):.+"  "\\1" cord_rev ${LIBCORD_VER_INFO})
+  string(REGEX REPLACE ".+:.+:(.+)$" "\\1" cord_age ${LIBCORD_VER_INFO})
+  math(EXPR CORD_SOVERSION "${cord_cur} - ${cord_age}")
+  set(CORD_VERSION "${CORD_SOVERSION}.${cord_age}.${cord_rev}")
+  message(STATUS "CORD_VERSION = ${CORD_VERSION}")
+  # gc:
+  string(REGEX REPLACE "(.+):.+:.+"  "\\1" gc_cur ${LIBGC_VER_INFO})
+  string(REGEX REPLACE ".+:(.+):.+"  "\\1" gc_rev ${LIBGC_VER_INFO})
+  string(REGEX REPLACE ".+:.+:(.+)$" "\\1" gc_age ${LIBGC_VER_INFO})
+  math(EXPR GC_SOVERSION "${gc_cur} - ${gc_age}")
+  set(GC_VERSION "${GC_SOVERSION}.${gc_age}.${gc_rev}")
+  message(STATUS "GC_VERSION = ${GC_VERSION}")
+  # gccpp and gctba:
+  string(REGEX REPLACE "(.+):.+:.+"  "\\1" gccpp_cur ${LIBGCCPP_VER_INFO})
+  string(REGEX REPLACE ".+:(.+):.+"  "\\1" gccpp_rev ${LIBGCCPP_VER_INFO})
+  string(REGEX REPLACE ".+:.+:(.+)$" "\\1" gccpp_age ${LIBGCCPP_VER_INFO})
+  math(EXPR GCCPP_SOVERSION "${gccpp_cur} - ${gccpp_age}")
+  set(GCCPP_VERSION "${GCCPP_SOVERSION}.${gccpp_age}.${gccpp_rev}")
+  message(STATUS "GCCPP_VERSION = ${GCCPP_VERSION}")
+endif(BUILD_SHARED_LIBS)
+
+add_definitions("-DALL_INTERIOR_POINTERS -DNO_EXECUTE_PERMISSION")
+
+# Set struct packing alignment to word (instead of 1-byte).
+if (BORLAND)
+  add_compile_options(/a4)
+elseif (WATCOM)
+  add_compile_options(/zp4)
+endif()
+
+# Output all warnings.
+if (BORLAND)
+  # All warnings except for particular ones.
+  add_compile_options(/w /w-pro /w-aus /w-par /w-ccc /w-inl /w-rch)
+elseif (MSVC)
+  # All warnings but ignoring "unreferenced formal parameter" and
+  # "conditional expression is constant" ones.
+  add_compile_options(/W4 /wd4100 /wd4127)
+  # Disable crt security warnings, since unfortunately they warn about all
+  # sorts of safe uses of strncpy.
+  add_definitions("-D_CRT_SECURE_NO_DEPRECATE")
+elseif (WATCOM)
+  add_compile_options(/wx)
+else()
+  # TODO add -[W]pedantic -Wno-long-long
+  add_compile_options(-Wall -Wextra)
+endif()
+
+include_directories(include)
+
+set(SRC alloc.c reclaim.c allchblk.c misc.c mach_dep.c os_dep.c
+        mark_rts.c headers.c mark.c obj_map.c blacklst.c finalize.c
+        new_hblk.c dbg_mlc.c malloc.c dyn_load.c typd_mlc.c ptr_chck.c
+        mallocx.c)
+set(THREADDLLIBS_LIST)
+
+set(_HOST ${CMAKE_SYSTEM_PROCESSOR}-unknown-${CMAKE_SYSTEM})
+string(TOLOWER ${_HOST} HOST)
+message(STATUS "TARGET = ${HOST}")
+
+if (enable_threads)
+  find_package(Threads REQUIRED)
+  message(STATUS "Thread library: ${CMAKE_THREAD_LIBS_INIT}")
+  include_directories(libatomic_ops/src)
+  include_directories(${Threads_INCLUDE_DIR})
+  set(THREADDLLIBS_LIST ${CMAKE_THREAD_LIBS_INIT})
+  if (${CMAKE_DL_LIBS} MATCHES ^[^-].*)
+    # Some cmake versions have a broken non-empty CMAKE_DL_LIBS omitting "-l".
+    # Assume CMAKE_DL_LIBS contains just one library.
+    set(THREADDLLIBS_LIST ${THREADDLLIBS_LIST} -l${CMAKE_DL_LIBS})
+  else()
+    set(THREADDLLIBS_LIST ${THREADDLLIBS_LIST} ${CMAKE_DL_LIBS})
+  endif()
+endif(enable_threads)
+
+set(ATOMIC_OPS_LIBS "") # TODO: Assume libatomic_ops library is not needed.
+
+# Thread support detection.
+if (CMAKE_USE_PTHREADS_INIT)
+  set(SRC ${SRC} gc_dlopen.c)
+  if (CYGWIN OR MSYS)
+    set(SRC ${SRC} win32_threads.c)
+  else()
+    set(SRC ${SRC} pthread_start.c pthread_stop_world.c pthread_support.c)
+  endif()
+  if (HOST MATCHES .*-.*-hpux10.*)
+    message(FATAL_ERROR "HP/UX 10 POSIX threads are not supported.")
+  endif()
+  # Assume the compiler supports GCC atomic intrinsics.
+  add_definitions("-DGC_BUILTIN_ATOMIC")
+  # Common defines for POSIX platforms.
+  add_definitions("-DGC_THREADS -D_REENTRANT")
+  if (enable_parallel_mark)
+    add_definitions("-DPARALLEL_MARK")
+  endif()
+  if (enable_thread_local_alloc)
+    add_definitions("-DTHREAD_LOCAL_ALLOC")
+    set(SRC ${SRC} specific.c thread_local_alloc.c)
+  endif()
+  message("Explicit GC_INIT() calls may be required.")
+  if (HOST MATCHES .*-.*-hpux11.*)
+    message("Only HP/UX 11 POSIX threads are supported.")
+    add_definitions("-D_POSIX_C_SOURCE=199506L")
+  elseif (HOST MATCHES .*-.*-netbsd.*)
+    message("Only on NetBSD 2.0 or later.")
+    add_definitions("-D_PTHREADS")
+  endif()
+  if (MSYS)
+    # Does not provide process fork functionality.
+  elseif (APPLE)
+    # The incremental mode conflicts with fork handling (for now).
+    # Thus, HANDLE_FORK is not defined.
+    set(SRC ${SRC} darwin_stop_world.c)
+  elseif (enable_handle_fork AND NOT disable_handle_fork)
+    add_definitions("-DHANDLE_FORK")
+  endif()
+  if (enable_sigrt_signals)
+    add_definitions("-DGC_USESIGRT_SIGNALS")
+  endif()
+elseif (CMAKE_USE_WIN32_THREADS_INIT)
+  add_definitions("-DGC_THREADS")
+  if (enable_parallel_mark)
+    add_definitions("-DPARALLEL_MARK")
+  endif()
+  if (enable_thread_local_alloc AND (enable_parallel_mark OR NOT BUILD_SHARED_LIBS))
+    # Imply THREAD_LOCAL_ALLOC unless GC_DLL.
+    add_definitions("-DTHREAD_LOCAL_ALLOC")
+    set(SRC ${SRC} thread_local_alloc.c)
+  endif()
+  add_definitions("-DEMPTY_GETENV_RESULTS")
+  set(SRC ${SRC} win32_threads.c)
+elseif (CMAKE_HP_PTHREADS_INIT OR CMAKE_USE_SPROC_INIT)
+  message(FATAL_ERROR "Unsupported thread package")
+endif()
+
+if (disable_handle_fork)
+  add_definitions("-DNO_HANDLE_FORK")
+endif()
+
+if (enable_gcj_support)
+  add_definitions("-DGC_GCJ_SUPPORT")
+  if (enable_threads AND NOT (enable_thread_local_alloc AND HOST MATCHES .*-.*-kfreebsd.*-gnu))
+    # FIXME: For a reason, gctest hangs up on kFreeBSD if both of
+    # THREAD_LOCAL_ALLOC and GC_ENABLE_SUSPEND_THREAD are defined.
+    add_definitions("-DGC_ENABLE_SUSPEND_THREAD")
+  endif()
+  set(SRC ${SRC} gcj_mlc.c)
+endif(enable_gcj_support)
+
+if (enable_disclaim)
+  add_definitions("-DENABLE_DISCLAIM")
+  set(SRC ${SRC} fnlz_mlc.c)
+endif()
+
+if (enable_java_finalization)
+  add_definitions("-DJAVA_FINALIZATION")
+endif()
+
+if (enable_atomic_uncollectable)
+  add_definitions("-DGC_ATOMIC_UNCOLLECTABLE")
+endif()
+
+if (enable_gc_debug)
+  add_definitions("-DDBG_HDRS_ALL -DKEEP_BACK_PTRS")
+  if (HOST MATCHES i.86-.*-dgux.*|ia64-.*-linux.*|i586-.*-linux.*|i686-.*-linux.*|x86-.*-linux.*|x86_64-.*-linux.*)
+    add_definitions("-DMAKE_BACK_GRAPH")
+    if (HOST MATCHES .*-.*-.*linux.*)
+      add_definitions("-DSAVE_CALL_COUNT=8")
+    endif()
+    set(SRC ${SRC} backgraph.c)
+  endif()
+endif(enable_gc_debug)
+
+if (disable_gc_debug)
+  add_definitions("-DNO_DEBUGGING")
+elseif (WINCE)
+  # Read environment variables from "<program>.gc.env" file.
+  add_definitions("-DGC_READ_ENV_FILE")
+endif()
+
+if (enable_redirect_malloc)
+  if (enable_gc_debug)
+    add_definitions("-DREDIRECT_MALLOC=GC_debug_malloc_replacement")
+    add_definitions("-DREDIRECT_REALLOC=GC_debug_realloc_replacement")
+    add_definitions("-DREDIRECT_FREE=GC_debug_free")
+  else()
+    add_definitions("-DREDIRECT_MALLOC=GC_malloc")
+  endif()
+  add_definitions("-DGC_USE_DLOPEN_WRAP")
+endif(enable_redirect_malloc)
+
+if (enable_munmap)
+  add_definitions("-DUSE_MMAP -DUSE_MUNMAP")
+elseif (enable_mmap)
+  add_definitions("-DUSE_MMAP")
+endif()
+
+if (NOT enable_dynamic_loading)
+  add_definitions("-DIGNORE_DYNAMIC_LOADING")
+endif()
+
+if (NOT enable_register_main_static_data)
+  add_definitions("-DGC_DONT_REGISTER_MAIN_STATIC_DATA")
+endif()
+
+if (enable_large_config)
+  add_definitions("-DLARGE_CONFIG")
+endif()
+
+if (enable_gc_assertions)
+  add_definitions("-DGC_ASSERTIONS")
+endif()
+
+if (NOT enable_threads_discovery)
+  add_definitions("-DGC_NO_THREADS_DISCOVERY")
+endif()
+
+if (enable_checksums)
+  if (enable_munmap OR enable_threads)
+    message(FATAL_ERROR "CHECKSUMS not compatible with USE_MUNMAP or threads")
+  endif()
+  add_definitions("-DCHECKSUMS")
+  set(SRC ${SRC} checksums.c)
+endif(enable_checksums)
+
+if (enable_werror)
+  if (BORLAND)
+    add_compile_options(/w!)
+  elseif (MSVC)
+    add_compile_options(/WX)
+    # Workaround "typedef ignored on left of ..." warning reported in
+    # imagehlp.h of e.g. Windows Kit 8.1.
+    add_compile_options(/wd4091)
+  elseif (WATCOM)
+    add_compile_options(/we)
+  else()
+    add_compile_options(-Werror)
+    if (APPLE)
+      # _dyld_bind_fully_image_containing_address is deprecated in OS X 10.5+
+      add_compile_options(-Wno-deprecated-declarations)
+    endif()
+  endif()
+endif(enable_werror)
+
+if (enable_single_obj_compilation OR BUILD_SHARED_LIBS)
+  set(SRC extra/gc.c) # override SRC
+  if (CMAKE_USE_PTHREADS_INIT)
+    add_definitions("-DGC_PTHREAD_START_STANDALONE")
+    set(SRC ${SRC} pthread_start.c)
+  endif(CMAKE_USE_PTHREADS_INIT)
+elseif (BORLAND)
+  # Suppress "GC_push_contents_hdr() is declared but never used" warning.
+  add_compile_options(/w-use)
+endif()
+
+# Add implementation of backtrace() and backtrace_symbols().
+if (MSVC)
+  set(SRC ${SRC} extra/msvc_dbg.c)
+endif()
+
+# Instruct check_c_source_compiles and similar CMake checks not to ignore
+# compiler warnings (like "implicit declaration of function").
+if (NOT BORLAND AND NOT MSVC AND NOT WATCOM)
+  check_c_compiler_flag(-Werror HAVE_FLAG_WERROR)
+  if (HAVE_FLAG_WERROR)
+    SET(CMAKE_REQUIRED_FLAGS "-Werror")
+  endif(HAVE_FLAG_WERROR)
+endif()
+
+if (BUILD_SHARED_LIBS)
+  add_definitions("-DGC_DLL")
+  # Pass -fvisibility=hidden option if supported.
+  check_c_compiler_flag(-fvisibility=hidden HAVE_FLAG_F_VISIBILITY_HIDDEN)
+  if (HAVE_FLAG_F_VISIBILITY_HIDDEN)
+    add_definitions("-DGC_VISIBILITY_HIDDEN_SET")
+    add_compile_options(-fvisibility=hidden)
+  else()
+    add_definitions("-DGC_NO_VISIBILITY")
+  endif()
+  check_c_compiler_flag(-Wl,--no-undefined HAVE_FLAG_WL_NO_UNDEFINED)
+else()
+  add_definitions("-DGC_NOT_DLL")
+  if (WIN32)
+    # Do not require the clients to link with "user32" system library.
+    add_definitions("-DDONT_USE_USER32_DLL")
+  endif(WIN32)
+endif()
+
+# Disable strict aliasing optimizations.
+# It could re-enabled back by a flag passed in CFLAGS_EXTRA.
+check_c_compiler_flag(-fno-strict-aliasing HAVE_FLAG_F_NO_STRICT_ALIASING)
+if (HAVE_FLAG_F_NO_STRICT_ALIASING)
+  add_compile_options(-fno-strict-aliasing)
+endif()
+
+# Extra user-defined flags to pass both to C and C++ compilers.
+if (DEFINED CFLAGS_EXTRA)
+  add_compile_options(${CFLAGS_EXTRA})
+endif()
+
+# Check whether execinfo.h header file is present.
+check_include_file(execinfo.h HAVE_EXECINFO_H)
+if (NOT HAVE_EXECINFO_H)
+  add_definitions("-DGC_MISSING_EXECINFO_H")
+endif()
+
+# Check for getcontext (uClibc can be configured without it, for example).
+check_function_exists(getcontext HAVE_GETCONTEXT)
+if (NOT HAVE_GETCONTEXT)
+  add_definitions("-DNO_GETCONTEXT")
+endif()
+
+# Check whether dl_iterate_phdr exists (as a strong symbol).
+check_function_exists(dl_iterate_phdr HAVE_DL_ITERATE_PHDR)
+if (HAVE_DL_ITERATE_PHDR)
+  add_definitions("-DHAVE_DL_ITERATE_PHDR")
+endif()
+
+check_symbol_exists(sigsetjmp setjmp.h HAVE_SIGSETJMP)
+if (NOT HAVE_SIGSETJMP)
+  add_definitions("-DGC_NO_SIGSETJMP")
+endif()
+
+# pthread_setname_np, if available, may have 1, 2 or 3 arguments.
+if (CMAKE_USE_PTHREADS_INIT)
+  check_c_source_compiles("
+#include <pthread.h>\n
+int main(void) { (void)pthread_setname_np(\"thread-name\"); return 0; }"
+    HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID)
+  if (HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID)
+    # Define to use 'pthread_setname_np(const char*)' function.
+    add_definitions("-DHAVE_PTHREAD_SETNAME_NP_WITHOUT_TID")
+  else()
+    check_c_source_compiles("
+#include <pthread.h>\n
+int main(void) {\n
+  (void)pthread_setname_np(pthread_self(), \"thread-name-%u\", 0); return 0; }"
+      HAVE_PTHREAD_SETNAME_NP_WITH_TID_AND_ARG)
+    if (HAVE_PTHREAD_SETNAME_NP_WITH_TID_AND_ARG)
+      # Define to use 'pthread_setname_np(pthread_t, const char*, void *)'.
+      add_definitions("-DHAVE_PTHREAD_SETNAME_NP_WITH_TID_AND_ARG")
+    else()
+      check_c_source_compiles("
+#if defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) || defined(__CYGWIN__)\n
+#define _GNU_SOURCE 1\n
+#endif\n
+#include <pthread.h>\n
+int main(void) {\n
+  (void)pthread_setname_np(pthread_self(), \"thread-name\"); return 0; }"
+        HAVE_PTHREAD_SETNAME_NP_WITH_TID)
+      if (HAVE_PTHREAD_SETNAME_NP_WITH_TID)
+        # Define to use 'pthread_setname_np(pthread_t, const char*)' function.
+        add_definitions("-DHAVE_PTHREAD_SETNAME_NP_WITH_TID")
+      endif()
+    endif(HAVE_PTHREAD_SETNAME_NP_WITH_TID_AND_ARG)
+  endif (HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID)
+endif()
+
+# Check for dladdr (used for debugging).
+check_c_source_compiles("
+#define _GNU_SOURCE 1\n
+#include <dlfcn.h>\n
+int main(void) { Dl_info info; (void)dladdr(\"\", &info); return 0; }"
+  HAVE_DLADDR)
+if (HAVE_DLADDR)
+  # Define to use 'dladdr' function.
+  add_definitions("-DHAVE_DLADDR")
+endif()
+
+add_library(gc ${SRC})
+if (enable_threads)
+  target_link_libraries(gc PRIVATE ${THREADDLLIBS_LIST} ${ATOMIC_OPS_LIBS})
+endif()
+target_include_directories(gc INTERFACE
+        "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
+        "$<INSTALL_INTERFACE:include>")
+
+if (enable_cplusplus)
+  if (BORLAND OR MSVC OR WATCOM)
+    add_library(gccpp gc_badalc.cpp gc_cpp.cpp)
+  else()
+    add_library(gccpp gc_badalc.cc gc_cpp.cc)
+  endif()
+  target_link_libraries(gccpp PRIVATE gc)
+  target_include_directories(gccpp INTERFACE
+        "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
+        "$<INSTALL_INTERFACE:include>")
+  if (enable_throw_bad_alloc_library)
+    # The same as gccpp but contains only gc_badalc.
+    if (BORLAND OR MSVC OR WATCOM)
+      add_library(gctba gc_badalc.cpp)
+    else()
+      add_library(gctba gc_badalc.cc)
+    endif()
+    target_link_libraries(gctba PRIVATE gc)
+    target_include_directories(gctba INTERFACE
+        "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
+        "$<INSTALL_INTERFACE:include>")
+  endif(enable_throw_bad_alloc_library)
+endif()
+
+if (build_cord)
+  set(CORD_SRC cord/cordbscs.c cord/cordprnt.c cord/cordxtra.c)
+  add_library(cord ${CORD_SRC})
+  target_link_libraries(cord PRIVATE gc)
+  target_include_directories(cord INTERFACE
+        "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
+        "$<INSTALL_INTERFACE:include>")
+  if (BUILD_SHARED_LIBS)
+    set_property(TARGET cord PROPERTY VERSION ${CORD_VERSION})
+    set_property(TARGET cord PROPERTY SOVERSION ${CORD_SOVERSION})
+  endif()
+  install(TARGETS cord EXPORT BDWgcTargets
+          LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+          ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+          RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
+          INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
+endif(build_cord)
+
+if (BUILD_SHARED_LIBS AND HAVE_FLAG_WL_NO_UNDEFINED)
+  # Declare that the libraries do not refer to external symbols.
+  # TODO: use add_link_options() when cmake_minimum_required > 3.13
+  target_link_libraries(gc PRIVATE -Wl,--no-undefined)
+  if (enable_cplusplus)
+    target_link_libraries(gccpp PRIVATE -Wl,--no-undefined)
+    if (enable_throw_bad_alloc_library)
+      target_link_libraries(gctba PRIVATE -Wl,--no-undefined)
+    endif(enable_throw_bad_alloc_library)
+  endif(enable_cplusplus)
+  if (build_cord)
+    target_link_libraries(cord PRIVATE -Wl,--no-undefined)
+  endif(build_cord)
+endif()
+
+if (BUILD_SHARED_LIBS)
+  set_property(TARGET gc PROPERTY VERSION ${GC_VERSION})
+  set_property(TARGET gc PROPERTY SOVERSION ${GC_SOVERSION})
+endif()
+install(TARGETS gc EXPORT BDWgcTargets
+        LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+        ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+        RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
+        INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
+
+if (enable_cplusplus)
+  if (BUILD_SHARED_LIBS)
+    set_property(TARGET gccpp PROPERTY VERSION ${GCCPP_VERSION})
+    set_property(TARGET gccpp PROPERTY SOVERSION ${GCCPP_SOVERSION})
+  endif()
+  install(TARGETS gccpp EXPORT BDWgcTargets
+          LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+          ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+          RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
+          INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
+  if (enable_throw_bad_alloc_library)
+    if (BUILD_SHARED_LIBS)
+      set_property(TARGET gctba PROPERTY VERSION ${GCCPP_VERSION})
+      set_property(TARGET gctba PROPERTY SOVERSION ${GCCPP_SOVERSION})
+    endif()
+    install(TARGETS gctba EXPORT BDWgcTargets
+            LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+            ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+            RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
+            INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
+  endif(enable_throw_bad_alloc_library)
+endif(enable_cplusplus)
+
+if (install_headers)
+  install(FILES include/gc/gc.h
+                include/gc/gc_backptr.h
+                include/gc/gc_config_macros.h
+                include/gc/gc_inline.h
+                include/gc/gc_mark.h
+                include/gc/gc_tiny_fl.h
+                include/gc/gc_typed.h
+                include/gc/gc_version.h
+                include/gc/javaxfc.h
+                include/gc/leak_detector.h
+          DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/gc")
+  install(FILES include/gc.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
+  if (enable_cplusplus)
+    install(FILES include/gc_cpp.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
+    install(FILES include/gc/gc_allocator.h
+                  include/gc/gc_cpp.h
+            DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/gc")
+  endif()
+  if (enable_disclaim)
+    install(FILES include/gc/gc_disclaim.h
+            DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/gc")
+  endif()
+  if (enable_gcj_support)
+    install(FILES include/gc/gc_gcj.h
+            DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/gc")
+  endif()
+  if (enable_threads AND CMAKE_USE_PTHREADS_INIT)
+    install(FILES include/gc/gc_pthread_redirects.h
+            DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/gc")
+  endif()
+  if (build_cord)
+    install(FILES include/gc/cord.h
+                  include/gc/cord_pos.h
+                  include/gc/ec.h
+            DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/gc")
+  endif()
+
+  # Provide pkg-config metadata.
+  set(prefix "${CMAKE_INSTALL_PREFIX}")
+  set(exec_prefix \${prefix})
+  set(includedir "${CMAKE_INSTALL_FULL_INCLUDEDIR}")
+  set(libdir "${CMAKE_INSTALL_FULL_LIBDIR}")
+  string(REPLACE ";" " " THREADDLLIBS "${THREADDLLIBS_LIST}")
+  # ATOMIC_OPS_LIBS, PACKAGE_VERSION are defined above.
+  configure_file(bdw-gc.pc.in bdw-gc.pc @ONLY)
+  install(FILES "${CMAKE_CURRENT_BINARY_DIR}/bdw-gc.pc"
+          DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+endif(install_headers)
+
+if (build_tests)
+  if (build_cord)
+    add_executable(cordtest cord/tests/cordtest.c)
+    target_link_libraries(cordtest PRIVATE cord gc)
+    add_test(NAME cordtest COMMAND cordtest)
+
+    if (WIN32 AND NOT CYGWIN)
+      add_executable(de cord/tests/de.c cord/tests/de_win.c
+                     cord/tests/de_win.rc)
+      set_target_properties(de PROPERTIES WIN32_EXECUTABLE TRUE)
+      target_link_libraries(de PRIVATE cord gc gdi32)
+    endif()
+  endif(build_cord)
+
+  # Compile some tests as C++ to test extern "C" in header files.
+  if (enable_cplusplus)
+    set_source_files_properties(tests/leak_test.c tests/test.c
+                                PROPERTIES LANGUAGE CXX)
+    # To avoid "treating 'c' input as 'c++' when in C++ mode" Clang warning.
+    if (NOT (BORLAND OR MSVC OR WATCOM))
+      add_compile_options(-x c++)
+    endif()
+  endif(enable_cplusplus)
+
+  add_executable(gctest WIN32 tests/test.c)
+  target_link_libraries(gctest PRIVATE gc ${THREADDLLIBS_LIST})
+  add_test(NAME gctest COMMAND gctest)
+  if (WATCOM)
+    # Suppress "conditional expression in if statement is always true/false"
+    # and "unreachable code" warnings in GC_MALLOC_[ATOMIC_]WORDS.
+    target_compile_options(gctest PRIVATE
+                           /wcd=13 /wcd=201 /wcd=367 /wcd=368 /wcd=726)
+  endif()
+
+  add_executable(hugetest tests/huge_test.c)
+  target_link_libraries(hugetest PRIVATE gc)
+  add_test(NAME hugetest COMMAND hugetest)
+
+  add_executable(leaktest tests/leak_test.c)
+  target_link_libraries(leaktest PRIVATE gc)
+  add_test(NAME leaktest COMMAND leaktest)
+
+  add_executable(middletest tests/middle.c)
+  target_link_libraries(middletest PRIVATE gc)
+  add_test(NAME middletest COMMAND middletest)
+
+  add_executable(realloc_test tests/realloc_test.c)
+  target_link_libraries(realloc_test PRIVATE gc)
+  add_test(NAME realloc_test COMMAND realloc_test)
+
+  add_executable(smashtest tests/smash_test.c)
+  target_link_libraries(smashtest PRIVATE gc)
+  add_test(NAME smashtest COMMAND smashtest)
+
+  if (NOT (BUILD_SHARED_LIBS AND WIN32))
+    add_library(staticrootslib_test tests/staticrootslib.c)
+    target_link_libraries(staticrootslib_test PRIVATE gc)
+    add_library(staticrootslib2_test tests/staticrootslib.c)
+    target_compile_options(staticrootslib2_test PRIVATE "-DSTATICROOTSLIB2")
+    target_link_libraries(staticrootslib2_test PRIVATE gc)
+    add_executable(staticrootstest tests/staticrootstest.c)
+    target_compile_options(staticrootstest PRIVATE "-DSTATICROOTSLIB2")
+    target_link_libraries(staticrootstest PRIVATE
+                          gc staticrootslib_test staticrootslib2_test)
+    add_test(NAME staticrootstest COMMAND staticrootstest)
+  endif()
+
+  if (enable_gc_debug)
+    add_executable(tracetest tests/trace_test.c)
+    target_link_libraries(tracetest PRIVATE gc)
+    add_test(NAME tracetest COMMAND tracetest)
+  endif()
+
+  if (enable_threads)
+    add_executable(test_atomic_ops tests/test_atomic_ops.c)
+    target_link_libraries(test_atomic_ops PRIVATE ${THREADDLLIBS_LIST})
+    add_test(NAME test_atomic_ops COMMAND test_atomic_ops)
+
+    add_executable(threadleaktest tests/thread_leak_test.c)
+    target_link_libraries(threadleaktest PRIVATE gc ${THREADDLLIBS_LIST})
+    add_test(NAME threadleaktest COMMAND threadleaktest)
+
+    if (NOT WIN32)
+      add_executable(threadkey_test tests/threadkey_test.c)
+      target_link_libraries(threadkey_test PRIVATE gc ${THREADDLLIBS_LIST})
+      add_test(NAME threadkey_test COMMAND threadkey_test)
+    endif()
+
+    add_executable(subthreadcreate_test tests/subthread_create.c)
+    target_link_libraries(subthreadcreate_test PRIVATE gc ${THREADDLLIBS_LIST})
+    add_test(NAME subthreadcreate_test COMMAND subthreadcreate_test)
+
+    add_executable(initsecondarythread_test tests/initsecondarythread.c)
+    target_link_libraries(initsecondarythread_test
+                          PRIVATE gc ${THREADDLLIBS_LIST})
+    add_test(NAME initsecondarythread_test COMMAND initsecondarythread_test)
+  endif(enable_threads)
+
+  if (enable_cplusplus)
+    add_executable(test_cpp WIN32 tests/test_cpp.cc)
+    target_link_libraries(test_cpp PRIVATE gc gccpp)
+    add_test(NAME test_cpp COMMAND test_cpp)
+  endif()
+
+  if (enable_disclaim)
+    add_executable(disclaim_bench tests/disclaim_bench.c)
+    target_link_libraries(disclaim_bench PRIVATE gc)
+    add_test(NAME disclaim_bench COMMAND disclaim_bench)
+
+    add_executable(disclaim_test tests/disclaim_test.c)
+    target_link_libraries(disclaim_test PRIVATE gc ${THREADDLLIBS_LIST})
+    add_test(NAME disclaim_test COMMAND disclaim_test)
+
+    add_executable(disclaim_weakmap_test tests/disclaim_weakmap_test.c)
+    target_link_libraries(disclaim_weakmap_test
+                          PRIVATE gc ${THREADDLLIBS_LIST})
+    add_test(NAME disclaim_weakmap_test COMMAND disclaim_weakmap_test)
+  endif()
+endif(build_tests)
+
+if (enable_docs)
+  install(FILES AUTHORS LICENSE README.md
+          DESTINATION "${CMAKE_INSTALL_DOCDIR}")
+  install(DIRECTORY doc/ DESTINATION "${CMAKE_INSTALL_DOCDIR}"
+          FILES_MATCHING
+            PATTERN "README.*"
+            PATTERN "*.md")
+
+  install(FILES gc.man DESTINATION "${CMAKE_INSTALL_MANDIR}/man3" RENAME gc.3)
+endif(enable_docs)
+
+# CMake config/targets files.
+install(EXPORT BDWgcTargets FILE BDWgcTargets.cmake
+        NAMESPACE BDWgc:: DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/bdwgc")
+
+configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in"
+        "${CMAKE_CURRENT_BINARY_DIR}/BDWgcConfig.cmake"
+        INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/bdwgc"
+        NO_SET_AND_CHECK_MACRO)
+
+write_basic_package_version_file(
+        "${CMAKE_CURRENT_BINARY_DIR}/BDWgcConfigVersion.cmake"
+        VERSION "${PACKAGE_VERSION}" COMPATIBILITY AnyNewerVersion)
+
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/BDWgcConfig.cmake"
+              "${CMAKE_CURRENT_BINARY_DIR}/BDWgcConfigVersion.cmake"
+        DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/bdwgc")
+
+export(EXPORT BDWgcTargets
+       FILE "${CMAKE_CURRENT_BINARY_DIR}/BDWgcTargets.cmake")

+ 10334 - 0
blitz.mod/bdwgc/ChangeLog

@@ -0,0 +1,10334 @@
+
+== [8.2.0] 2021-09-29 ==
+
+* Add API for accessing incremental GC time limit with nanosecond precision
+* Add API function to force start of incremental collection
+* Add GC_ prefix to scan_ptr and some other static variables (refactoring)
+* Add GC_get/set_disable_automatic_collection API
+* Add I_HOLD_LOCK assertion to expand_hp_inner and related functions
+* Add assertion on free-list argument and result of GC_new_kind
+* Add assertion that GC is initialized to base incremental_protection_needs
+* Add assertions that GC_page_size is initialized
+* Add cordtest, staticrootstest, test_cpp, tracetest, disclaim tests (CMake)
+* Add debug messages on thread suspend/resume (Win32)
+* Add dummy testing of GC_incr_bytes_allocd/freed
+* Add table of contents in gcdescr.md
+* Add testing of GC_CALLOC/MALLOC_EXPLICITLY_TYPED (gctest)
+* Adjust formatting of numbered lists in README.md to match other .md files
+* Adjust highlighting of API prototypes in gcinterface.md
+* Adjust macro def/usage for AVR32, CRIS, NETBSD, OPENBSD, SH4 in gcconfig.h
+* Adjust printf calls in gctest check_heap_stats so that each has new-line
+* Allow incremental GC on Cygwin
+* Allow memory unmapping in case of MPROTECT_VDB
+* Allow to disable GWW or mprotect-based VDB at build
+* Allow to disable Glibc FPU exception mask and TSX workarounds (Linux)
+* Allow to disable __builtin_return_address(1) usage (x86 and x64)
+* Allow to specify custom value of LOG_PHT_ENTRIES
+* Always abort on failure to access /proc/self/maps (Linux)
+* Always define default_push_other_roots (code refactoring)
+* Avoid gcc stringop-overflow warning for intended overflow in smashtest
+* Avoid initial 3ms pause on world stop/start with GC_retry_signals (Linux)
+* Build cord.lib by Makefile.direct, NT_MAKEFILE, OS2_MAKEFILE, WCC_MAKEFILE
+* Build gc as a shared multi-threaded library by default (CMake)
+* Build gccpp library by Makefile.direct, NT_MAKEFILE and WCC_MAKEFILE
+* Build gctba library
+* Build shared libraries by default (WCC_MAKEFILE)
+* Change CLOCK_TYPE to timespec for Nintendo Switch (code refactoring)
+* Change EMSCRIPTEN macro for internal use to no-underscore format
+* Change log_size fields of finalizer to unsigned type (code refactoring)
+* Change type of toggleref_array_size/capacity to size_t (code refactoring)
+* Check leak of objects allocated by CRT malloc in gctest (MS VC)
+* Check real-symbols are already initialized in pthread_join/detach
+* Collapse multiple includes of windows.h (code refactoring)
+* Comments reformatting in mark.c to properly delimit sentences
+* Compile de test GUI app with resources (CMake)
+* Compile gc.c unless building static libraries (NT_MAKEFILE, WCC_MAKEFILE)
+* Compile msvc_dbg.c by CMake script (MS VC)
+* Declare API function and print amount of memory obtained from OS
+* Define GC_win32_free_heap API function for all Windows targets
+* Define STATIC macro to static by default
+* Depend number of fork_a_thread calls on NTHREADS (gctest)
+* Detect dladdr() presence in CMake script
+* Detect presence of execinfo.h system header in CMake script
+* Detect presence of getcontext and dl_iterate_phdr in CMake script
+* Detect sigsetjmp() availability in CMake script
+* Disable Clang/GCC aliasing optimization in CMake script by default
+* Do not build tests by default (Makefile.direct and other Makefiles)
+* Do not build the tests by default (CMake)
+* Do not call GC_push_conditional unless PROC_VDB
+* Do not call add_to_our_memory with null pointer (refactoring)
+* Do not compile pthread_*.c files in Cygwin or MSYS (CMake)
+* Do not define GC_write_cs for Xbox One target
+* Do not define HAVE_NO_FORK for all Unix-like systems
+* Do not hard-code CMAKE_DL_LIBS value and install paths (CMake)
+* Do not hard-code finalizable objects limit which triggers GC
+* Do not update scratch_last_end_ptr unless used by reg dynamic libraries
+* Document GC_incr_bytes_allocd/freed API function
+* Eliminate '(long)size<=0 is always false' cppcheck FP
+* Eliminate 'Consecutive return is unnecessary' cppcheck style warning
+* Eliminate 'accessing GC_dont_gc without lock' in GC_init code defect FP
+* Eliminate 'bytes_freed access w/o lock in incr_bytes_free' code defect FP
+* Eliminate 'checking if unsigned i < 0' cppcheck FP in is_heap_base
+* Eliminate 'hash_val value is never used' cppcheck false positive
+* Eliminate 'passing tainted var maps_buf to tainted sink' code defect FP
+* Eliminate 'retry_cnt is assigned value but never used' cppcheck FP
+* Eliminate 'stop variable is always 0' compiler warning in print_callers
+* Eliminate 'struct member os_callback is never used' cppcheck warning
+* Eliminate 't->flags not atomically updated' code defect FP
+* Eliminate 'tmpl might be accessed at non-zero index' cppcheck error
+* Eliminate GCC warning of unsafe __builtin_return_address(1)
+* Eliminate code duplication in reclaim_clear and disclaim_and_reclaim
+* Eliminate double lock code defect false positive in generic_lock
+* Eliminate memory leak reported in add_current_malloc_heap at exit (Win32)
+* Emscripten single-threaded support (detect stack base, push registers)
+* Enable CMake-based build for Borland and Watcom compilers
+* Enable compilation without C runtime (Win32)
+* Enable fork testing in single-thread builds (Unix-like)
+* Enable mprotect-based incremental GC for Linux/arm and Linux/aarch64
+* Enable true incremental collection even if parallel marker is on
+* Enable use of __builtin_unwind_init() if clang-8 or later
+* Ensure ELFSIZE is defined in dyn_load.c for OpenBSD (code refactoring)
+* Ensure add_to_heap_inner arguments are valid (refactoring)
+* Ensure all getters and setters are run at least once by gctest (pthreads)
+* Export CMake targets with namespace BDWgc
+* Fix 'const obj must be initialized if not extern' error in gc_alloc_ptrs.h
+* Fix ./libgc.la dependency on FreeBSD (Automake)
+* Fix HOST determination in CMake script
+* Fix copyright message in de_win.rc, gc_cpp.cc, ec.h and specific.h
+* Fix missing OS_TYPE definition for some targets
+* Fix mmap(PROT_NONE) failure if RLIMIT_AS value is low (Linux)
+* Generate cordtest and de executable files in GC base folder
+* Generate pkg-config metadata file (CMake)
+* Get rid of some non-ELF ifdefs (code refactoring)
+* Handle potential incomplete buffer read in GC_linux_main_stack_base
+* Implement GET_TIME for Nintendo Switch
+* Increase NTHREADS value in tests if code coverage analysis
+* Install docs and man page if enable_docs (CMake)
+* Install gc_gcj.h and gc_pthread_redirects.h only if appropriate
+* Log abort message details even if not print_stats (unless SMALL_CONFIG)
+* Mark buffer returned by get_maps as const (code refactoring)
+* Move C++ GC_ATTR_EXPLICIT and GC_NOEXCEPT definition to gc_config_macros.h
+* Move GC state non-pointer variables into GC_arrays (code refactoring)
+* Move GC state pointer variables into GC_arrays
+* Move GC_scratch_recycle_inner() to alloc.c (refactoring)
+* Move GC_throw_bad_alloc definition to new C++ file
+* Move QNX and Emscripten macro definitions to proper place in gcconfig.h
+* Move definition of GC_n_mark_procs and GC_n_kinds from mark.c to misc.c
+* New API (GC_set_markers_count) to control number of parallel markers
+* New API function to clear GC exclusion table
+* New API function to get size of object debug header
+* New API standalone functions to acquire and release the allocator lock
+* New CMake option (disable_gc_debug) to remove debugging code
+* New CMake option (disable_handle_fork) to disable fork handling completely
+* New macro (CONSOLE_LOG) to enable logging to console on Win32
+* New macro (GCTEST_PRINT_VERBOSE) to enable verbose logging in test.c only
+* New macro (NO_MSGBOX_ON_ERROR) to avoid message box on GC abort (Win32)
+* OpenBSD does not use ELF_CLASS (code refactoring)
+* Pass -D GC_DLL -fvisibility=hidden if default configure build is requested
+* Pass -no-undefined linker flag if building shared libraries (CMake)
+* Print pid of child processes if verbose logging (gctest)
+* Read environment variables from a file on WinCE (CMake script)
+* Reduce stack-allocated buffer in get_nprocs from 4KB to 1.7KB
+* Refine flags field comment in pthread_support.h
+* Reflect result of VDB selection at runtime in incremental_protection_needs
+* Reformat code of GC_push_roots
+* Reformat gc.man (wrap long lines)
+* Reformatting and code refactoring of CMake script
+* Remove 'current users' section from overview.md
+* Remove 'distributed ports', 'scalable versions' sections from overview.md
+* Remove AC_MSG_RESULT for THREADDLLIBS (dgux386)
+* Remove Borland-specific Makefile and gc.mak script
+* Remove GC_eobjfreelist variable in typd_mlc.c (code refactoring)
+* Remove GC_gcj_malloc_initialized variable (code refactoring)
+* Remove Linux-specific commands for building cord/de from Makefile.direct
+* Remove Win32 main_thread static variable if threads discovery is disabled
+* Remove code duplication between GC_unmap and GC_unmap_gap (refactoring)
+* Remove code duplication between PROTECT and UNPROTECT macros (refactoring)
+* Remove commented out assignment of gc_use_mmap in configure (refactoring)
+* Remove dash characters comprising prefix of some verbose logs (gctest)
+* Remove dependency on user32.dll import library from static libgc (Win32)
+* Remove documentation specific to particular old BDWGC releases
+* Remove duplicate Linux-related macro definitions in gcconfig.h
+* Remove duplicate macro definitions in gcconfig.h except for Linux
+* Remove gcmt-dll generation, rename libgc-lib.a to libgc.a (CMake)
+* Remove goto statement in print_callers (code refactoring)
+* Remove limit on number of heap sections
+* Remove new_gc_alloc.h file
+* Remove redundant GC_with_callee_saves_pushed call in multi-threaded builds
+* Remove redundant check of GC_free argument in register_finalizer
+* Remove redundant type casts in backgraph HEIGHT_UNKNOWN/IN_PROGRESS
+* Remove unused GC_prev_heap_addr (refactoring)
+* Remove unused STACK_GRAN macro definitions (code refactoring)
+* Remove unused sparc_sunos4_mach_dep.s file
+* Remove useless empty statements after block ones (refactoring)
+* Remove weakobj_free_list variable in disclaim_weakmap_test (refactoring)
+* Rename READ to PROC_READ in os_dep.c (code refactoring)
+* Rename cord/cord test executable to de (CMake)
+* Rename ext_descr to typed_ext_descr_t (code refactoring)
+* Rename gc64.dll to gc.dll and gc[64]_dll.lib to gc.lib in NT_MAKEFILE
+* Rename gc68060.lib to gc.lib, cord/cord68060.lib to cord.lib in SMakefile
+* Rename make_as_lib option to enable_static in NT_MAKEFILE and WCC_MAKEFILE
+* Rename nothreads option to disable_threads in NT_MAKEFILE
+* Repeat run_one_test NTHREADS times by gctest if single-threaded
+* Replace "msecs" with "ms" in all comments and messages
+* Replace 'stack base' with 'stack bottom' in the documentation
+* Replace SN_TARGET_ORBIS to PLATFORM_* and GC_NO_* macros
+* Replace _M_AMD64 macro with _M_X64 (code refactoring)
+* Replace find_limit_openbsd to find_limit_with_bound (OpenBSD 5.2+)
+* Replace obsolete AC_HELP_STRING with AS_HELP_STRING (refactoring)
+* Replace push_one calls with push_many_regs one for Win32 thread context
+* Report memory region bounds and errno on GC_unmap/remap failure
+* Report presence of process fork testing (gctest)
+* Report time with a nanosecond precision where available
+* Retry suspend/resume signals on all platforms by default
+* Run tree and typed tests in child process (gctest)
+* Set GC_collecting hint for GC_collect_a_little_inner calls (pthreads)
+* Set name of GC marker threads
+* Set so-version for installed shared libraries (CMake)
+* Simplify logged message in scratch_recycle
+* Simplify loops of collect_a_little/stopped_mark invoking mark_some
+* Support -fvisibility=hidden option in CMake script
+* Support CFLAGS_EXTRA to pass extra user-defined compiler flags (CMake)
+* Support FreeBSD/RISC-V, Linux/arc, LoongArch, OpenBSD/powerpc64
+* Support header files installation (CMake)
+* Support most configure options in CMake script
+* Suppress warnings in test_tinyfl() of gctest reported by Watcom C complier
+* Take nanoseconds into account when updating full_gc_total_time
+* Turn off C++ API by default, export it in gccpp library (CMake)
+* Turn on automatic fork() handling by default on Android
+* Update README.cmake regarding Unix, C++ and tests
+* Update libgc.so version info to differentiate against v8.0.x
+* Update the ASCII diagrams describing the tree structure for pointer lookups
+* Update the documentation to match the current GC implementation
+* Upgrade cmake_minimum_required(version) to 3.1
+* Use CreateThread without GC_ prefix in gctest (code refactoring)
+* Use KB/MB/GB abbreviations uniformly across entire documentation
+* Use USE_MMAP_ANON when USE_MMAP is configured on OpenBSD
+* Use a specific Emscripten allocator for Tiny
+* Use atomic primitives for Sony PlayStation Portable 2 and PS4
+* Use better precision Windows timers
+* Use clock_gettime() instead of clock() on Cygwin and Linux
+* Use compiler TLS on FreeBSD and NetBSD
+* Use mprotect-based VDB on PowerPC and S390 (Linux)
+* Use soft dirty bits on Linux (i386, powerpc, s390, x86_64)
+* Workaround 'condition result<=0 is always false' cppcheck FP in get_maps
+* Workaround 'push_regs configured incorrectly' error (GCC-11)
+* Workaround 'same value in both branches of ternary operator' cppcheck FP
+* Workaround various cppcheck false positives
+
+
+== [8.0.6] 2021-09-28 ==
+
+* Add loop to handle abort error like in suspend logic on Darwin
+* Add support of OpenBSD/aarch64
+* Add threading libraries to bdw-gc.pc
+* Allocate start_info struct on the stack in GC_pthread_create
+* Allow GC_PAUSE_TIME_TARGET environment variable values smaller than 5 ms
+* Avoid compiler warning about unused d in GC_CALLOC/MALLOC_EXPLICITLY_TYPED
+* Avoid gcc stringop-overflow warning for intended overflow in smashtest
+* Check _MSVC_LANG macro in addition to __cplusplus (MS VC)
+* Compile C++ code with exception handling enabled in NT_MAKEFILE
+* Define OS_TYPE and DATAEND for UWP targets
+* Disable mprotect-based incremental GC if /proc roots are used (Linux)
+* Do not report 'Incremental GC incompatible' warning more than once
+* Do not use Manual VDB mode if C malloc is redirected
+* Do not use iOS private symbols
+* Eliminate 'GC_non_gc_bytes is deprecated' warning in new_gc_alloc.h
+* Eliminate 'GC_old_bus_handler defined but not used' compiler warning
+* Eliminate 'cast between incompatible func types' warnings for FARPROC vars
+* Eliminate 'comparing signed and unsigned values' BCC warning in cordtest
+* Eliminate 'gc_pthread_redirects.h should contain header guard' code defect
+* Eliminate 'implicit declaration of sbrk' gcc warning if -std=c11 on Cygwin
+* Eliminate 'possible loss of data' BCC and MS VC warnings
+* Eliminate 'static GC_sysinfo definition has incomplete type' Clang warning
+* Eliminate 'unused function' compiler warnings (GC_add_map_entry, GC_lock)
+* Eliminate 'while clause does not guard' GCC warning in GC_parse_map_entry
+* Enable sbrk-to-mmap fallback on major supported Unix-like platforms
+* Ensure process is running on one CPU core if AO ops are emulated with locks
+* Explicitly zero-initialize trace_buf (fix trace_buf initialization)
+* Fix 'ACCESS_VIOLATION in marker' GC warning on Win32 async thread start
+* Fix 'GC_generic_malloc must be available' GCC error in new_gc_alloc.h
+* Fix 'ISO C++17 does not allow dynamic exception spec' clang-8 error
+* Fix 'Wrong __data_start/_end pair' if -Bsymbolic-functions used (Linux)
+* Fix 'condition pred!=NULL is always true' compiler warning
+* Fix 'external linkage required for var because of dllimport' error on MinGW
+* Fix 'ulong undefined' compilation error on AIX
+* Fix 'undefined reference to __data_start' linker error on RISC-V
+* Fix 'use of undeclared BUS_PAGE_FAULT' compilation error on FreeBSD 12
+* Fix 'write to GC log failed' error (Cygwin)
+* Fix 'wrong finalization data' gctest failure on Windows
+* Fix CMake build on macOS Catalina
+* Fix GC_OPENBSD_THREADS definition (OpenBSD/hppa)
+* Fix GC_proc_fd value in child process at fork (Solaris)
+* Fix GC_with_callee_saves_pushed for Android NDK r23 (clang-12)
+* Fix MPROTECT_VDB definition for single-threaded GC builds
+* Fix OS_TYPE and USE_MMAP_ANON definitions for Cygwin/x64
+* Fix STACKBOTTOM on 32-bit HP/UX 11.11
+* Fix abort in GC_printf when gctest is built as WinMain executable (Cygwin)
+* Fix assertion violation in register_dynlib_callback on Android
+* Fix build for OS X (CMake)
+* Fix building of shared library with C++ support on MinGW
+* Fix compiling by Makefile.direct on OpenBSD/UltraSparc
+* Fix configure message about 'AIX gcc optimization fix'
+* Fix cordtest build in SMakefile.amiga
+* Fix data race regarding *rlh value in generic_malloc_many
+* Fix first_thread stack_base initialization if custom GC_stackbottom (Win32)
+* Fix gc_allocator.h compilation by Clang
+* Fix gc_cflags variable name in configure (HP/UX)
+* Fix handling of areas smaller than page size in GC_scratch_recycle
+* Fix incorrect markup formatting in documentation
+* Fix misaligned tlfs passed to AO_load on m68k
+* Fix missing GC_quiet declaration in pcr_interface.c
+* Fix missing gc_dlopen.c and specific.c in CMake script
+* Fix missing scratch_last_end_ptr update (Irix)
+* Fix mmap() failures on AIX, HP/UX and Haiku
+* Fix overflow of scratch_free_ptr value
+* Fix page_was_[ever_]dirty() for static roots (Solaris)
+* Fix printf format specifier in simple_example.md
+* Fix save_callers for multi-threaded case if built-in backtrace unavailable
+* Fix subexpression widening in memhash() of disclaim_weakmap_test
+* Fix test_cpp failure caused by arbitrary link order (Win32)
+* Fix test_cpp failure when gc_cpp resides in a dll (Borland, Watcom)
+* Fix various typos mostly in documentation files
+* Fix word size, data start and alignment for OpenBSD/mips64(el)
+* Include <alloca.h> when using alloca on AIX
+* Limit number of unmapped regions (Linux and DragonFly)
+* New macro to avoid system-wide new/delete inlining in gc_cpp.h (Win32)
+* Prevent GetThreadContext failure (Windows)
+* Prevent WARN of incompatible incremental GC if default or manual VDB
+* Reduce a time period between GetExitCodeThread and SuspendThread (Win32)
+* Refactoring of WoW64 workaround (Win32)
+* Refine GC_INIT documentation about its multiple invocation
+* Refine GC_parallel documentation in gc.h
+* Refine do_blocking() documentation in gc.h
+* Remove a misleading comment about Solaris in gc.h
+* Remove cord .h files from list of non-installed headers (Automake)
+* Remove dead part of condition to define NEED_FIND_LIMIT in gc_priv.h
+* Remove gcmt-lib generation by CMake
+* Support MSYS builds by CMake and configure
+* Update documentation about the incremental collector support
+* Use HEURISTIC2 on OpenBSD when single-threaded
+* Use pstat_getprocvm to determine main stack bottom on HP-UX
+* Workaround 'expression is only useful for its side effects' WCC warning
+* Workaround clang-3.8/s390x bug when processing __builtin_frame_address
+* Workaround fread fail after enable_incremental if malloc redirected (Linux)
+
+
+== [8.0.4] 2019-03-02 ==
+
+* Avoid a full GC when growing finalizer tables if in incremental mode
+* Avoid potential race in hb_sz access between realloc and reclaim_block
+* Avoid test.o rebuild on tests folder timestamp change (Makefile.direct)
+* Avoid unexpected heap growth in gctest caused by GC_disable
+* Ensure result of every variant of MS_TIME_DIFF has unsigned long type
+* Fix 'duplicate symbol' error for tests using multiple static libs (OS X)
+* Fix 'undefined reference to __data_start' linker error (Android/aarch64)
+* Fix 'unexpected mark stack overflow' abort in push_all_stack
+* Fix 'wrong __data_start/_end pair' error on Android
+* Fix BSD_TIME variant of MS_TIME_DIFF for the case of a.tv_usec < b.tv_usec
+* Fix GetThreadContext stale register values use if WoW64 (Win32)
+* Fix invalid initializer of CLOCK_TYPE variables if BSD_TIME
+* Fix thread_info() count argument value (OS X)
+* Support de_win.c compilation by Makefile.direct (cord/de)
+
+
+== [8.0.2] 2018-12-23 ==
+
+* Abort with appropriate message if executable pages cannot be allocated
+* Add initial testing of GC_enable/disable, MALLOC[_ATOMIC]_IGNORE_OFF_PAGE
+* Add paths to filenames mentioned in the copyright section in README
+* Add test using disclaim notifiers to implement a weak map
+* Adjust #error messages format
+* Allow to force executable pages allocation in gctest
+* Avoid potential 'macro redefinition' errors for config.h macros
+* Call real pthread_sigmask instead of its wrapper in start_mark_threads
+* Check result of pthread_mutex_unlock in specific.c
+* Default to a single-threaded build for Nintendo, Orbis, Sony PSP targets
+* Default to non-executable memory allocation across all make scripts
+* Define GC_ATOMIC_UNCOLLECTABLE and JAVA_FINALIZATION in all make scripts
+* Do not prevent GC from looking at environment variables (BCC_MAKEFILE)
+* Do not use 'ifndef AO_CLEAR' in mark, pthread_support and gctest
+* Do not use spin locks if AO test-and-set is emulated (pthreads)
+* Document HANDLE_FORK macro optional usage in Makefile.direct
+* Document assertion in the setters that used to return old value
+* Eliminate 'assigned value never used' compiler warning in test_cpp WinMain
+* Eliminate 'casting signed to bigger unsigned int' CSA warning
+* Eliminate 'different const qualifiers' MS VC warnings in cordbscs
+* Eliminate 'function is never used' cppcheck warning for calloc/realloc
+* Eliminate 'non-virtual destructor for class with inheritors' CSA warning
+* Eliminate 'pointer targets differ in signedness' compiler warning (Win32)
+* Eliminate 'struct member is never used' cppcheck warnings in os_dep
+* Eliminate 'uninitialized var' cppcheck false positive in mach_dep, os_dep
+* Eliminate 'unreferenced formal parameter' compiler warning in msvc_dbg
+* Eliminate redundant check in backwards_height
+* Fix 'USE_MUNMAP macro redefinition' error for NaCl
+* Fix 'collecting from unknown thread' abort in leak-finding mode for Win32
+* Fix 'mprotect remapping failed' abort on NetBSD with PaX enabled
+* Fix 'too wide non-owner permissions are set for resource' code defect
+* Fix GC_VSNPRINTF in cordprnt for DJGPP and MS VC for WinCE
+* Fix GC_register_disclaim_proc for leak-finding mode
+* Fix a deadlock in write_fault_handler if AO_or is emulated
+* Fix comment typo in CMakeLists.txt
+* Fix concurrent bitmap update in GC_dirty
+* Fix deadlocks in write and suspend handlers if AO test-and-set is emulated
+* Fix executable memory allocation in GC_unix_get_mem
+* Fix hbp overflow in GC_install_counts
+* Fix linkage with a system libatomic_ops shared library
+* Fix lock assertion violation in get_index if GC_ALWAYS_MULTITHREADED
+* Fix marking of finalizer closure object
+* Fix marks and hb_n_marks consistency when disclaim returns true
+* Fix memory allocation on GCF (Linux/x64)
+* Fix missing curses.h in cord/de when compiling manually (MS VC, MinGW)
+* Fix test_cpp assertion violation in find-leak mode
+* Fix tests linkage with internal atomic_ops.o
+* Fix unneeded end_stubborn_change/ptr_store_and_dirty in disclaim_test
+* Guard against potential buffer overflow in CORD_next and CORD_pos_fetch
+* New macro to suppress printing of leaked objects
+* Pass -Wall -Wextra -Wpedantic to g++ if supported (configure)
+* Prefix internal durango_get_mem symbol with 'GC_'
+* Prevent double inclusion of javaxfc.h and private/specific.h
+* Print relevant message in tests not appropriate for leak detection mode
+* Reduce scope of local variables in GC_remove_all_threads_but_me
+* Refine HIDE_POINTER documentation for the case of the leak-finding mode
+* Refine documentation in gc_disclaim.h
+* Remove extra USE_MMAP definition for Interix
+* Remove redundant header double-inclusion checks in the private headers
+* Remove strlen calls with a constant string argument in msvc_dbg
+* Specify register_disclaim_proc and finalized_malloc argument as non-null
+* Support UWP/arm64 target
+* Test marking of finalizer closure object in disclaim_test
+* Turn off leak detection mode explicitly in cord/de
+* Turn off parallel marker, thread-local allocation if used AO ops emulated
+* Turn on gcj functionality in BCC, DMC, NT, OS/2, WCC makefiles
+* Turn on memory unmapping in BCC/DMC/NT/WCC makefiles and Makefile.direct
+* Update NO_EXECUTE_PERMISSION documentation
+* Update documentation about arm64 ABI in gcconfig.h
+* Use AO_or in async_set_pht_entry_from_index if available
+* Use GC_WORD_MAX macro across all C source files
+* Use macro to operate on a flag residing in GC_stop_count
+* Use standalone private macro to guard against ptr_t redefinition
+* Workaround '#error' cppcheck messages in backgraph and private headers
+* Workaround 'AST broken' syntax error reported by cppcheck in GC_mark_some
+* Workaround 'GC_dump function is never used' cppcheck warning
+* Workaround 'local address assignment to a global variable' CSA warning
+* Workaround 'local variable end shadows outer symbol' cppcheck warnings
+* Workaround 'local variable obj_displ shadows outer symbol' cppcheck warning
+* Workaround 'nonlocal var will use ptr to local var' cppcheck false positive
+* Workaround 'pointer addition with NULL pointer' cppcheck error in msvc_dbg
+* Workaround 'potential non-terminated string' false positive in cordbscs
+* Workaround 'value of _MAX_PATH is unknown' cppcheck warning
+* Workaround cppcheck warnings regarding CLOCKS_PER_SEC, REDIRECT_REALLOC
+
+
+== [8.0.0] 2018-09-05 ==
+
+* Accept Android platform by both CMake and configure
+* Access finalize_now atomically to avoid TSan warning without no-sanitize
+* Acknowledge thread restart from suspend_handler (NetBSD)
+* Add a sanity check that load_acquire and store_release are available
+* Add AO primitives implementation to GC based on GCC atomic intrinsic
+* Add assertion for suspend_ack_sem in start_world
+* Add assertion to allocobj that live unmarked object cannot be reclaimed
+* Add assertions about held lock when accessing all_bottom_indices
+* Add assertions to ensure ADD_CALL_CHAIN is called holding the lock
+* Add assertions to finalize and threads support for MANUAL_VDB needs
+* Add basic calculation of the total full-collection time
+* Add check that gc_cpp operator delete is called (test_cpp)
+* Add debug logging to new_thread about GC_threads hash table collisions
+* Add GC prefix to _MSVC_DBG_H macro
+* Add initial RISC-V support
+* Add Makefile target to run all tests without test-driver
+* Add test_atomic_ops to perform minimal testing of used atomic primitives
+* Add two-argument alloc_size attribute to calloc_explicitly_typed (GCC)
+* Align IRIX/OSF1_THREADS definition in gc_config_macros.h with gcconfig.h
+* Allocate non-executable memory by default (CMake)
+* Allow compilation of PROC_VDB code on Linux host (GC_NO_SYS_FAULT_H)
+* Allow configure --with-libatomic-ops=none to use GCC atomic intrinsics
+* Allow custom N_LOCAL_ITERS and ENTRIES_TO_GET values
+* Allow disabling of dynamic loading in CMake script and configure
+* Allow disabling of main static data registration in CMake and configure
+* Allow disabling of threads discovery in CMake script and configure
+* Allow gc_assertions enabling in CMake script
+* Allow gc_debug, redirect_malloc, large_config options in CMake script
+* Allow GC_NETBSD_THREADS_WORKAROUND macro manual definition
+* Allow mmap enabling in CMake script and configure
+* Allow passing -D DEFAULT_VDB to CFLAGS
+* Allow subthreadcreate_test to be compiled with zero NTHREADS
+* Allow to turn on spin locking even if thread-local allocations are used
+* Always include gc_atomic_ops.h unless threads are disabled
+* Avoid 'Unexpected heap growth' in 64-bit multi-threaded gctest if n_tests=1
+* Avoid duplication of code handling pthreads case in configure
+* Avoid potential data race during apply_to_each_object(reset_back_edge)
+* Avoid potential data race during GC_dump execution
+* Avoid potential race between malloc_kind and mark_thread_local_fls_for
+* Avoid potential race between realloc and clear_hdr_marks/reclaim_generic
+* Avoid potential race in print_static_roots called by dyld_image_add/remove
+* Avoid potential race in SET_MARK_BIT_EXIT_IF_SET if parallel marking
+* Avoid potential race when accessing size_map table
+* Avoid potential race when storing oh_back_ptr during parallel marking
+* Avoid SIGSEGV during GC_INIT on some Android devices
+* Build only shared libraries by default (configure)
+* Change pointer arguments of push_all[_eager]/conditional API to void* type
+* Change type of hb_sz field (of hblkhdr) from size_t to word
+* Check consistency of descr, adjust, clear arguments of GC_new_kind
+* Check that GC_WIN32_PTHREADS is not specified for Cygwin
+* Check thread_local is initialized before accessing thread_key
+* Collapse multiple BCOPY_EXISTS macro definitions
+* Collapse multiple NT_*_MAKEFILE scripts into a single NT_MAKEFILE
+* Collapse multiple page_was_dirty, remove_protection, read_dirty definitions
+* Compile checksums.c only if --enable-checksums is given (configure)
+* Consistently define WIN32_LEAN_AND_MEAN/NOSERVICE before include windows.h
+* Convert .html files to Markdown format
+* Convert code of .c files to valid C++ code
+* Decide between memory unmapping and mprotect-based dirty bits at runtime
+* Declare t local variable in the block where the variable is used
+* Define ABORT() using _CrtDbgBreak (if available) on Windows host
+* Define CLANG/GNUC_PREREQ macros to check gcc/clang minimum version
+* Define DYNAMIC_LOADING for Darwin unless IGNORE_DYNAMIC_LOADING
+* Define GC_ASSERT(x) as C assert(x) for external clients of gc_inline.h
+* Define GC_PREFETCH_FOR_WRITE to __builtin_prefetch in gc_inline.h (GCC)
+* Define GC_THREADS instead of GC_x_THREADS in Makefiles
+* Define macro to specify the environment file name extension (Win32/WinCE)
+* Define static resend_lost_signals(), restart_all() in pthread_stop_world
+* Detect sigsetjmp() availability by configure
+* Determine whether to use compiler TLS for kFreeBSD at compile time
+* Do not call BCOPY and BZERO if size is zero
+* Do not call sem_getvalue in stop_world if one thread exists
+* Do not call set_handle_fork(1) in gctest if pthread_atfork not supported
+* Do not compile pcr_interface.c and real_malloc.c except by PCR-Makefile
+* Do not declare dl_iterate_phdr as weak for kFreeBSD
+* Do not include windows.h when compiling gc_cpp.cc
+* Do not install gc_allocator.h, gc_disclaim.h unless the features enabled
+* Do not merge dynamic root with the existing static one in add_roots_inner
+* Do not print n_rescuing_pages value if incremental collections disabled
+* Do not push cpsr and frame pointer on Darwin/arm and Darwin/arm64
+* Do not rebuild_root_index unless remove_root_at_pos is called
+* Do not specify version info for test libraries (Automake)
+* Do not use alternate thread library on Solaris
+* Do not use asm in GC_pause
+* Do not use PKG_CHECK_MODULES in configure
+* Do not use system clock consistently if NO_CLOCK
+* Do not use x86 asm in PUSH_CONTENTS_HDR for NaCl
+* Document GC_BUILTIN_ATOMIC macro (and gc_atomic_ops private header file)
+* Document STACK_NOT_SCANNED macro in gcconfig.h (Emscripten)
+* Eliminate 'comparison is always false' code defect in get_maps
+* Eliminate 'GC_DEBUG redefined' compiler warning in smashtest
+* Eliminate 'potential unsafe sign check of a bitwise operation' code defect
+* Enable alternative finalization interface (DISCLAIM) in all makefiles
+* Enable compilation for Cygwin with MPROTECT_VDB
+* Enable handle-fork and memory unmapping by default
+* Enable mprotect-based incremental GC for Win64 (GCC)
+* Expose API to control rate and max prior attempts of collect_a_little
+* Expose API to control the minimum bytes allocated before a GC occurs
+* Fix 'comparison of 255 with expr of type bool' error in gc_atomic_ops.h
+* Fix 'doc' files installation folder
+* Fix build of cord tests as C++ files (Makefile.direct)
+* Fix comment typos in backgraph.c, de.c, gcconfig.h
+* Fix delete operator redirection if gc_cpp is built as .dll (Cygwin, MinGW)
+* Fix start_world not resuming all threads on Darwin
+* Fix test_cpp failure in case GC_DEBUG is defined
+* Group common defines for POSIX platforms in configure and CMake scripts
+* Guard against USE_PTHREAD_LOCKS and USE_SPIN_LOCK are both defined
+* Handle pthread restart signals loss if retry_signals
+* Hide value stored to thread-specific entries for a test purpose
+* Implement FindTopOfStack(0) for ARM and AArch64 (Darwin)
+* Implement memory unmapping for Sony PS/3
+* Imply configure --single-obj-compilation if --disable-static
+* Include malloc.c in extra/gc.c after include gc_inline.h
+* Increase MAX_HEAP_SECTS (10 times) for large-config
+* Initial single-threaded support of Interix subsystem
+* Initial support of Nintendo, Orbis, Sony PSP2, WinRT, Xbox One
+* Initial support of TIZEN platform
+* Install gc.3 man page instead of copying gc.man to doc folder (configure)
+* Make extend_size_map() static (code refactoring)
+* Make subthreadcreate test compilable even without libatomic_ops
+* Match GC_FAST_MALLOC_GRANS formal and actual arguments where possible
+* Move de_win compiled resource files to cord/tests
+* Move pcr_interface.c, real_malloc.c to 'extra' folder
+* New API function (GC_dump_named) to produce named dumps
+* New API function (GC_is_incremental_mode)
+* New API function (get_expl_freed_bytes_since_gc)
+* New API function (get_size_map_at) to get content of size_map table
+* New API to stop and start the GC world externally
+* New API to turn on manual VDB at runtime
+* New field (expl_freed_bytes_since_gc) in public prof_stats_s
+* New macro ALWAYS_SMALL_CLEAR_STACK to avoid clearing large stack sections
+* New public API (PTR_STORE_AND_DIRTY) to simplify store-and-dirty operation
+* Pass CFLAGS_FOR_PIC value to CFLAGS in Makefile.direct
+* Print time passed since GC initialization in GC_dump
+* Public API (GC_deinit) to allow Win32 critical sections deletion
+* Reduce probability of collision in threads hashtable for 64-bit targets
+* Reduce the default MUNMAP_THRESHOLD value to 2 for Sony PS/3
+* Refactoring of USE_MMAP/USE_MMAP_ANON pairs definition in gcconfig.h
+* Reformat code and comments in gc_allocator.h
+* Remove 'dist' target from Makefile.direct
+* Remove a redundant check of __cplusplus in Symbian-specific .cpp files
+* Remove Android-specific code in gcconfig.h for M68K
+* Remove C++ WeakPointer and CleanUp API which lacks implementation
+* Remove DGUX_THREADS macro which duplicates GC_DGUX386_THREADS (configure)
+* Remove done_init static variable from fnlz_mlc.c
+* Remove duplicate definition of ALIGNMENT macro for OpenBSD/arm
+* Remove duplicated sample code in leak.md
+* Remove EMX_MAKEFILE (add EMX support to Makefile.direct)
+* Remove GC code fragment (which already merged) from README.Mac
+* Remove GC_GNU_THREADS macro (HURD)
+* Remove GENERAL_MALLOC internal macro
+* Remove HIGH_BIT macro duplicating SIGNB
+* Remove lint-specific code
+* Remove Makefile KandRtest target (that supported K&R C compiler)
+* Remove MIN_WORDS macro from gc_priv.h
+* Remove multi-line macros (FOR_EACH_PRED, ITERATE_DL_HASHTBL_*, PUSH_OBJ)
+* Remove name of optional arguments of operator new and new[] in gc_cpp.h
+* Remove notes that K&R C compiler is unsupported
+* Remove PUSH_CONTENTS_HDR multi-line macro
+* Remove redundant check that clear_fl_marks argument is non-null
+* Remove redundant THREADS macro checks in alloc.c and gc_priv.h
+* Remove stubborn objects allocation code completely, remove stubborn.c
+* Remove unnecessary argument casts in add_roots_inner calls
+* Remove unnecessary type casts in n_set_marks
+* Remove unused USE_GENERIC macro definition and description
+* Remove version info in 'de' cord test application
+* Replace GC_MALLOC(sizeof T) with GC_NEW(T) in tests
+* Replace GC_NO_RETRY_SIGNALS environment variable with GC_RETRY_SIGNALS=0
+* Replace some FIXME items with TODO ones
+* Run command passed to if_not_there directly from Makefile.direct
+* Same type casts for GC_PTR_STORE arguments regardless of GC_DEBUG
+* Skip grungy_pages update when mark state invalid to speedup read_dirty
+* Skip typed_test in gctest if NO_TYPED_TEST macro is defined
+* Support configure --disable-thread-local-alloc option (similar for CMake)
+* Support enable_checksums option in CMake script
+* Support Haiku multi-threaded build by CMake
+* Support threads for DragonFly in configure
+* Turn on 'atomic uncollectable' functionality by default (CMake)
+* Turn on GC assertions in NT_MAKEFILE for debug builds
+* Turn on gcj, disclaim and java finalization by default (CMake)
+* Turn on incremental collection in gctest also if DEFAULT_VDB or MANUAL_VDB
+* Turn on incremental mode in cordtest and cord/de
+* Turn on incremental mode in disclaim_test, test_cpp and staticroots test
+* Turn on parallel marker by default for all multi-threaded builds
+* Update GC compilation and usage notes for Win32
+* Update shared libraries version info to differentiate against v7.6
+* Update top_index entry pointer only when the entry is constructed fully
+* Use __builtin_expect in SIZET_SAT_ADD macro
+* Use __declspec(allocator) for malloc-like prototypes (MS VS 2015+)
+* Use __int64 instead of 'long long' in LONG_MULT if appropriate
+* Use __thread keyword for Android NDK r12b+ Clang (arm)
+* Use atomic allocation for leafs in reverse_test (gctest)
+* Use atomic load/store for the concurrently accessed variables in GC_lock
+* Use C11 static_assert if available
+* Use compiler atomic intrinsics by default if available (configure)
+* Use EXPECT FALSE for mark_from code documented as executed rarely
+* Use heap-allocated memory for local mark stack of non-marker thread
+* Use HOST_ANDROID define instead of PLATFORM_ANDROID
+* Use include gc.h with the angle brackets in the man page synopsis
+* Use longjmp in fault_handler_openbsd if siglongjmp unavailable (OpenBSD)
+* Use MARK_BIT_PER_GRANULE instead of MARK_BIT_PER_OBJ where appropriate
+* Use noexcept specifier in gc_allocator and gc_cpp if C++11
+* Use same macro (NTHREADS) across all tests to specify number of threads
+* Use sigsetjmp() in setjmp_t tool if available
+* Use thread-local allocations for all multi-threaded builds
+* Use THREAD_EQUAL consistently to compare pthread_t values
+* Workaround 'bad pointer arithmetic' false waring in check_annotated_obj
+* Workaround Clang optimizer bug crashing clear_stack_inner on OS X 10.8
+* Workaround Thread Sanitizer (TSan) false positive warnings
+
+
+== [7.6.14] 2021-09-28 ==
+
+* Add loop to handle abort error like in suspend logic on Darwin
+* Add support of OpenBSD/aarch64
+* Add threading libraries to bdw-gc.pc
+* Disable mprotect-based incremental GC if /proc roots are used (Linux)
+* Do not use iOS private symbols
+* Eliminate 'GC_old_bus_handler defined but not used' compiler warning
+* Eliminate 'comparing signed and unsigned values' BCC warning in cordtest
+* Eliminate 'possible loss of data' BCC and MS VC warnings
+* Eliminate 'static GC_sysinfo definition has incomplete type' Clang warning
+* Eliminate 'unused function GC_add_map_entry' compiler warning
+* Eliminate 'while clause does not guard' GCC warning in GC_parse_map_entry
+* Explicitly zero-initialize trace_buf (fix trace_buf initialization)
+* Fix 'ACCESS_VIOLATION in marker' GC warning on Win32 async thread start
+* Fix 'GC_generic_malloc must be available' GCC error in new_gc_alloc.h
+* Fix 'ulong undefined' compilation error on AIX
+* Fix 'undefined reference to __data_start' linker error on RISC-V
+* Fix 'write to GC log failed' error
+* Fix GC_proc_fd value in child process at fork (Solaris)
+* Fix MPROTECT_VDB definition for single-threaded GC builds
+* Fix OS_TYPE and USE_MMAP_ANON definitions for Cygwin/x64
+* Fix STACKBOTTOM on 32-bit HP/UX 11.11
+* Fix abort in GC_printf when gctest is built as WinMain executable (Cygwin)
+* Fix assertion violation in register_dynlib_callback on Android
+* Fix compiling by Makefile.direct on OpenBSD/UltraSparc
+* Fix configure message about 'AIX gcc optimization fix'
+* Fix cordtest build in SMakefile.amiga
+* Fix data race regarding *rlh value in generic_malloc_many
+* Fix first_thread stack_base initialization if custom GC_stackbottom (Win32)
+* Fix gc_allocator.h compilation by Clang
+* Fix gc_cflags variable name in configure (HP/UX)
+* Fix handling of areas smaller than page size in GC_scratch_recycle
+* Fix incorrect define GC_OPENBSD_THREADS on sparc64
+* Fix misaligned tlfs passed to AO_load on m68k
+* Fix missing GC_quiet declaration in pcr_interface.c
+* Fix missing gc_dlopen.c in CMake script
+* Fix missing scratch_last_end_ptr update (Irix)
+* Fix overflow of scratch_free_ptr value
+* Fix page_was_[ever_]dirty() for static roots (Solaris)
+* Fix printf format specifier in simple_example.html
+* Fix save_callers for multi-threaded case if built-in backtrace unavailable
+* Fix test_cpp failure caused by arbitrary link order (Win32)
+* Fix test_cpp failure when gc_cpp resides in a dll (Borland, Watcom)
+* Fix various typos mostly in documentation files
+* Fix word size, data start and alignment for OpenBSD/mips64(el)
+* Prevent GetThreadContext failure (Windows)
+* Prevent WARN of incompatible incremental GC if default or manual VDB
+* Reduce a time period between GetExitCodeThread and SuspendThread (Win32)
+* Refactoring of WoW64 workaround (Win32)
+* Remove a misleading comment about Solaris in gc.h
+* Workaround 'expression is only useful for its side effects' WCC warning
+* Workaround fread fail after enable_incremental if malloc redirected (Linux)
+
+
+== [7.6.12] 2019-03-01 ==
+
+* Eliminate 'assigned value never used' compiler warning in test_cpp WinMain
+* Fix 'mprotect remapping failed' abort on NetBSD with PaX enabled
+* Fix 'undefined reference to __data_start' linker error (Android/aarch64)
+* Fix 'unexpected mark stack overflow' abort in push_all_stack
+* Fix 'wrong __data_start/_end pair' error on Android
+* Fix BSD_TIME variant of MS_TIME_DIFF for the case of a.tv_usec < b.tv_usec
+* Fix GetThreadContext stale register values use if WoW64 (Win32)
+* Fix executable memory allocation in GC_unix_get_mem
+* Fix invalid initializer of CLOCK_TYPE variables if BSD_TIME
+* Fix thread_info() count argument value (OS X)
+* Update NO_EXECUTE_PERMISSION documentation
+
+
+== [7.6.10] 2018-12-13 ==
+
+* Add paths to filenames mentioned in the copyright section in README
+* Call real pthread_sigmask instead of its wrapper in start_mark_threads
+* Eliminate 'casting signed to bigger unsigned int' CSA warning
+* Eliminate 'non-virtual destructor for class with inheritors' CSA warning
+* Fix 'collecting from unknown thread' abort in leak-finding mode for Win32
+* Fix 'too wide non-owner permissions are set for resource' code defect
+* Fix 'undefined reference to GC_incremental' linker error in pthread_start
+* Fix GC_VSNPRINTF in cordprnt for DJGPP and MS VC for WinCE
+* Fix GC_register_disclaim_proc for leak-finding mode
+* Fix a deadlock in write_fault_handler if AO_or is emulated
+* Fix comment typos in CMakeLists.txt, backgraph.c, de.c, gcconfig.h
+* Fix concurrent bitmap update in GC_dirty
+* Fix delete operator redirection if gc_cpp is built as .dll (Cygwin, MinGW)
+* Fix hbp overflow in GC_install_counts
+* Fix linkage with a system libatomic_ops shared library
+* Fix lock assertion violation in get_index if GC_ALWAYS_MULTITHREADED
+* Fix marking of finalizer closure object
+* Fix marks and hb_n_marks consistency when disclaim returns true
+* Fix memory allocation on GCF (Linux/x64)
+* Fix missing curses.h in cord/de when compiling manually (MS VC, MinGW)
+* Fix start_world not resuming all threads on Darwin
+* Fix test_cpp assertion violation in find-leak mode
+* Fix tests linkage with internal atomic_ops.o
+* Fix unneeded end_stubborn_change in disclaim_test
+* Guard against potential buffer overflow in CORD_next and CORD_pos_fetch
+* New macro to suppress printing of leaked objects
+* Prevent double inclusion of javaxfc.h and private/specific.h
+* Reduce scope of local variables in GC_remove_all_threads_but_me
+* Refine HIDE_POINTER documentation for the case of the leak-finding mode
+* Refine documentation in gc_disclaim.h
+* Test marking of finalizer closure object in disclaim_test
+* Update documentation about arm64 ABI in gcconfig.h
+* Use AO_or in async_set_pht_entry_from_index if available
+* Use include gc.h with the angle brackets in the man page synopsis
+
+
+== [7.6.8] 2018-08-12 ==
+
+* Add cpu, make_as_lib, nothreads options to NT_MAKEFILE
+* Add NetBSD/aarch64 and initial RISC-V support
+* Adjust formatting of configure help messages and config.h comments
+* Avoid multiple 'getcontext failed' warnings if getcontext is broken
+* Cleanup BCC Makefile (remove absolute GC paths, fix del cmd, update clean)
+* Collapse multiple NT_*_MAKEFILE scripts into a single NT_MAKEFILE
+* Do not call GC_dirty_inner unless GC_incremental
+* Do not use NULL in gc_inline.h
+* Eliminate 'cast between incompatible function types' compiler warning
+* Eliminate 'comparing signed and unsigned values' compiler warnings (bcc)
+* Eliminate 'condition is always true' cppcheck warning in init_gcj_malloc
+* Eliminate 'declaration of var hides global declaration' compiler warning
+* Eliminate 'language extension used' Clang warning in gc.h
+* Eliminate 'possibly incorrect assignment in CORD_vsprintf' compiler warning
+* Eliminate 'ptr arithmetic with NULL' cppcheck warning in alloc_mark_stack
+* Eliminate 'scope of var can be reduced' cppcheck warning in pthread_join
+* Eliminate 'switch statement contains no case label' compiler warning
+* Eliminate 'variable might be uninitialized' warning in win32_start_inner
+* Eliminate duplicate clear_mark_bit call when removing disappearing link
+* Fast fail on invalid CPU parameter passed to NT_MAKEFILE
+* Fix 'collecting from unknown thread' abort in leak-finding mode
+* Fix 'pointer arithmetic with NULL' code defect in print_callers
+* Fix Borland version in documentation to match that in BCC_MAKEFILE
+* Fix comment about inv_sz computation in setup_header
+* Fix comments style in configure.ac and Makefile.am
+* Fix compilation by digimars.mak (DMC)
+* Fix compilation by WCC makefile
+* Fix compilation of darwin_stop_world for iOS 8+
+* Fix cords for MANUAL_VDB
+* Fix dependency on gc_cpp source in BCC_MAKEFILE and NT_MAKEFILE
+* Fix GC_is_valid_displacement and GC_is_visible for non-small objects
+* Fix gctest in leak-finding mode
+* Fix infinite restarting of mark_some when a static root disappeared (Linux)
+* Fix large object base computation in PUSH_CONTENTS() if MARK_BIT_PER_OBJ
+* Fix mark stack overflow checking in push_selected
+* Fix missing GC_dirty calls for GC-allocated objects used internally
+* Fix missing GC_dirty invocation from debug_end_stubborn_change
+* Fix MSWIN32 macro redefinition (WCC)
+* Fix multi-threaded gctest for the case of NTHREADS is set to zero
+* Fix new and delete operators definition for DigitalMars compiler
+* Fix NT_MAKEFILE for VS 2017
+* Fix potential null dereference in GC_CONS
+* Fix register_dynamic_libraries on Windows 10
+* Fix result computation in n_set_marks
+* Fix return type in GC_set_warn_proc API documentation
+* Fix tests for GC compiled with MANUAL_VDB
+* Fix the build for Emscripten
+* Fix typo in comment for CORD_ec_flush_buf prototype
+* Fix typos in ChangeLog and generic_malloc
+* Fix UNTESTED for multi-threaded API functions in gctest
+* Fix VirtualQuery call in case of malloc failure (Win32)
+* Install gc.3 man page instead of copying gc.man to doc folder (configure)
+* Keep pointer to the start of previous entry in remove_specific_after_fork
+* Move de_win compiled resource files to cord/tests
+* Never return null by C++ GC allocators and gc_cpp operator new
+* Perform thread_suspend in loop as it may be interrupted (Darwin)
+* Really abort if failed to read /proc for library registration (Linux)
+* Remove code duplication in gcj_malloc and malloc_explicitly_typed
+* Remove duplicate local variable in reclaim_block
+* Remove information how to send bugs from README.cords file
+* Remove libatomic_ops license information
+* Remove unused USE_GENERIC macro definition and description
+* Suppress 'functions containing switch are not expanded inline' bcc warning
+* Suppress 'non-member operator new/delete may not be inline' VC++ warning
+* Turn on incremental collection in gctest also if MANUAL_VDB
+* Update copyright information in alloc.c, gc.c/h and the documentation
+* Update EXTRA_DIST in Makefile, Win32/64 docs after NT_*_MAKEFILE removal
+* Update NT_MAKEFILE usage information in README files for Win32 and Win64
+* Workaround 'class C does not have a copy constructor' cppcheck warning
+* Workaround 'function nested_sp is never used' cppcheck style warning
+* Workaround 'opposite expression on both sides of &' cppcheck style warning
+* Workaround 'template-id not supported in this context' compiler error (WCC)
+
+
+== [7.6.6] 2018-04-20 ==
+
+* Define GC_FREEBSD_THREADS and GC_ADD_CALLER macros for kFreeBSD
+* Eliminate 'boolean result used in bitwise operation' cppcheck warning
+* Eliminate 'there is pointer arithmetic with NULL' cppcheck warning
+* Explicitly unblock GC signals on GC initialization
+* Fix 'scope of var can be reduced' cppcheck err in enqueue_all_finalizers
+* Fix 'undefined reference to __builtin_unwind_init' linker error (ArmCC)
+* Fix arguments delimiter in pcr_interface.c (PCR)
+* Fix assertion violation in DllMain of win32_threads
+* Fix comment for debug_generic_malloc_inner[_ignore_off_page]
+* Fix data race during apply_to_each_object(reset_back_edge)
+* Fix dbg_mlc.c/o file name in documentation
+* Fix gctest with musl libc on s390x
+* Fix include gc_gcj.h in thread_local_alloc.c
+* Fix man section number (3)
+* Fix missing GC_generic_malloc_words_small implementation in new_gc_alloc.h
+* Fix missing new-line in ABORT_ARG<n> definition
+* Fix missing SIGBUS handler setup for kFreeBSD
+* Fix null dereference in print_callers on backtrace_symbols failure
+* Fix null pointer dereference in get_private_path_and_zero_file (Symbian)
+* Fix the collector hang when it is configured with --enable-gc-debug
+* Fix thread_suspend fail for threads registered from key destructor (OS X)
+* Fix type of local variables receiving result of PHT_HASH
+* Fix typo in AIX macro name
+* Fix typo in comment in specific.h
+* Fix unbounded heap growth in case of intensive disappearing links usage
+* Remove API symbols renaming in WCC_MAKEFILE
+* Support Haiku/amd64 and Haiku/x86 hosts
+* Support threads for DragonFly in configure
+* Workaround 'address of auto-variable returned' cppcheck error
+* Workaround gctest hang on kFreeBSD (if thread-local allocations are on)
+
+
+== [7.6.4] 2018-01-26 ==
+
+* Add note of set_free_space_divisor, set_warn_proc ABI change after gc-7.1
+* Change compiler invocation example in gc.man to use dynamic libgc
+* Delete dont_ar_* build intermediate files on make clean (Makefile.direct)
+* Do not declare dl_iterate_phdr as weak for DragonFly
+* Fix 'cords' parallel build in Makefile.direct
+* Fix 'undeclared identifier USRSTACK' compiler error on OpenBSD-6.2
+* Fix error code in abort message if sem_wait failed in start_world (NetBSD)
+* Fix GC allocation mutex in child after a fork
+* Fix global operator delete definition for C++14 in gc_cpp
+* Fix last_reclaimed..gc_no interval comparison to threshold in unmap_old
+* Fix libgc version which was changed in linkage breaking way
+* Fix missing EOLn output in threadlibs tool
+* Fix threadlibs tool to output '-lpthread' for DragonFly
+* Prevent DATASTART redefinition for NaCl
+* Remove obsolete advice about linking with _DYNAMIC=0 (Linux)
+
+
+== [7.6.2] 2017-12-23 ==
+
+* Add assertion that no hb_n_marks underflow occurs
+* Add minimal testing of GC_MALLOC_[ATOMIC_]WORDS and GC_CONS (gctest)
+* Add minimal testing of GC_set_bit (gctest)
+* Add more cases to huge_test to cover sizes close to word-type maximum
+* Add testing of new[]/delete[] (test_cpp)
+* Adjust AO_HAVE_x check to match AO_fetch_and_add primitive variant used
+* Adjust code indentation of calloc_explicitly_typed
+* Align local_mark_stack in help_marker explicitly
+* Allow custom TRACE_ENTRIES value
+* Allow gctest and thread_leak_test with zero NTHREADS
+* Avoid data race in finalized_count (gctest)
+* Code refactoring of divide-by-HBLKSIZE occurrences
+* Code refactoring of huge_test
+* Code refactoring of tests/subthread_create regarding AO add primitive
+* Compile thread_local_alloc only if multi-threaded build (Makefile.am)
+* Delete preprocessor output on make clean (Makefile.direct)
+* Disable implicit multi-threaded mode for Win32 to avoid LOCK crash
+* Do not disable parallel mark for WRAP_MARK_SOME
+* Do not enable mprotect-based incremental mode if unmapping is on (gctest)
+* Do not install documentation if configure --disable-docs (new option)
+* Do not use tkill (Android)
+* Document base and size of objects allocated by finalized_malloc
+* Document configure 'syntax error' issue in README
+* Eliminate 'address of local variable returned' static analyzer warning
+* Eliminate 'array vs singleton' code defect in typed_test (gctest)
+* Eliminate 'assigned value never used' CSA warning in min_bytes_allocd
+* Eliminate 'boolean result used in bitwise op' cppcheck false warning
+* Eliminate 'C-style pointer casting' cppcheck style warnings in test
+* Eliminate 'checking if unsigned variable is <0' cppcheck style warning
+* Eliminate 'class member var with name also defined in parent' warning
+* Eliminate 'comparison is always false' static analyzer warning in finalize
+* Eliminate 'Condition 0==datastart always false' cppcheck warning (dyn_load)
+* Eliminate 'condition is always true' cppcheck style warning
+* Eliminate 'constructor with 1 argument is not explicit' cppcheck warning
+* Eliminate 'CORD_*printf is never used' cppcheck style warnings (cordtest)
+* Eliminate 'dereference of null' CSA false warning in array_mark_proc
+* Eliminate 'function result not used' code defect in GC_mark_local
+* Eliminate 'GC_collecting is set but never used' code defect (Win32)
+* Eliminate 'GC_record_fault is never used' cppcheck style warning
+* Eliminate 'integer shift by a negative amount' code defect in finalize
+* Eliminate 'label not used' cppcheck false warnings in GC_mark_X
+* Eliminate 'memory leak' code defect for scratch-allocated memory
+* Eliminate 'memory leak' code defect in remove_specific
+* Eliminate 'non-null arg compared to null' warning in toggleref_add (GCC)
+* Eliminate 'non-reentrant function strtok called' cppcheck warning (POSIX)
+* Eliminate 'possible integer underflow' code defect (cord-de)
+* Eliminate 'potential overflow' static analyzer warning in test
+* Eliminate 'printf format specifies type void*' GCC pedantic warnings
+* Eliminate 'scope of variable can be reduced' cppcheck warnings
+* Eliminate 'suspicious pointer subtraction' cppcheck warning (gc_cpp)
+* Eliminate 'this statement may fall through' GCC warnings
+* Eliminate 'unnecessary comparison of static strings' cppcheck warning
+* Eliminate 'unsafe vsprintf is deprecated' compiler warning
+* Eliminate 'unused formal parameter' compiler warnings in C++ code (MS VC)
+* Eliminate 'unused variable' compiler warning in remove_all_threads_but_me
+* Eliminate 'use of vulnerable sprintf' code defect in de_win test (cord)
+* Eliminate 'value exceeds maximum object size' GCC warning in huge_test
+* Eliminate 'value of CLOCK_TYPE unknown' cppcheck info message
+* Eliminate 'value of DATASTART2 unknown' cppcheck info messages
+* Eliminate 'value of GC_PTHREAD_EXIT_ATTRIBUTE unknown' cppcheck messages
+* Eliminate 'value of GC_RETURN_ADDR_PARENT unknown' cppcheck info messages
+* Eliminate 'value of NEED_FIXUP_POINTER unknown' cppcheck info messages
+* Eliminate 'write to memory that was const-qualified' code analyzer warning
+* Eliminate all 'scope of variable can be reduced' cppcheck style warnings
+* Eliminate CSA warning about incorrect cast applied to HBLK_OBJS
+* Eliminate CSA warning about narrowing cast in CleanUp of test_cpp
+* Eliminate CSA warning of non-virtual destructor in test_cpp base class
+* Eliminate CSA warning of staticroot that can be a local variable (tests)
+* Eliminate CSA warning of unmodified non-const static var (disclaim_test)
+* Eliminate redundant local variable in register_finalizer
+* Eliminate TSan (Thread Sanitizer) warnings in gctest
+* Eliminate UBSan warning of overflow during descr subtraction in mark_from
+* Eliminate unreachable PROC/DEFAULT_VDB GC_printf calls in gctest main()
+* Eliminate unsigned fl_builder_count underflow in mark_thread
+* Enable GC_is_tmp_root for all platforms
+* Execute more single-threaded GC tests by CMake
+* Expand tabs to spaces in de_win.rc (tests)
+* Export GC_dump_finalization/regions()
+* Export GC_is_tmp_root() and GC_print_trace[_inner]()
+* Export GC_print_free_list()
+* Fix '32-bit value shift followed by expansion to 64-bit' code defect
+* Fix 'GC_written_pages never read' code defect (GWW_VDB)
+* Fix 'label cannot be reached' static analyzer warning in disclaim_test
+* Fix 'size of tv is unknown' error in brief_async_signal_safe_sleep (musl)
+* Fix 'syntax error' reported by cppcheck for mach_dep
+* Fix 'unknown type name GC_INNER' compilation error (FreeBSD)
+* Fix 'variable assigned a value that is never used' cppcheck style warnings
+* Fix 'void pointers in calculations: behavior undefined' cppcheck warning
+* Fix assertion violation about disabled cancel in try_to_collect_inner
+* Fix atomic_ops build in Makefile.direct for Solaris
+* Fix Clang static analyzer warning about not found gc_priv.h in extra files
+* Fix compilation error in get_main_stack_base (Emscripten)
+* Fix compilation for winpthreads if HANDLE_FORK
+* Fix compilation if configured with --enable-werror on OS X
+* Fix cord/de build in Makefile.direct (Linux)
+* Fix data race in a list referenced by A.aa (gctest)
+* Fix data race in collectable_count (gctest)
+* Fix data race in do_local_mark when comparing active_count to helper_count
+* Fix data race in GC_suspend/resume_thread
+* Fix data race in last_stop_count access (suspend_handler_inner)
+* Fix data race in make_descriptor when setting explicit_typing_initialized
+* Fix data race in mark_thread when updating mark_no
+* Fix data race when getting object size in explicitly-typed allocators
+* Fix deadlock in GC_suspend_thread
+* Fix gctest failure for Darwin if CPPCHECK is defined
+* Fix lack of barriers to synchronize memory for suspend_handler
+* Fix marking of disclaim-reachable objects in the incremental mode
+* Fix message of VDB implementation used if MPROTECT_VDB+GWW_VDB (gctest)
+* Fix missing started_thread_while_stopped call from mark_some if GCC/Clang
+* Fix null dereference in GC_stack_range_for if not DARWIN_DONT_PARSE_STACK
+* Fix page calculation in checksums
+* Fix parallel build in Makefile.direct
+* Fix test_cpp and c++ parallel build in Makefile.direct
+* Fix typo in comment of GC_mark_some
+* Fix typos in cdescr.html and README.sgi
+* Make GC_INIT optional for clients even if thread-local allocations enabled
+* Match uclinux pattern in configure
+* Move conditional GC_need_to_lock setting to gc_locks.h (refactoring)
+* Move README.QUICK from DOC_FILES to OTHER_FILES in Makefile.direct
+* New API function (GC_is_init_called) to check if BDWGC is initialized
+* New target (check-cpp) in Makefile.direct
+* Prevent abort in register_data_segments for Symbian and Emscripten
+* Prevent multiple 'Caught ACCESS_VIOLATION in marker' per collection
+* Print realloc_count value in gctest
+* Put invariant name in quotes to make mark_state comments clearer
+* Refine configure messages when checking for compiler option support
+* Remove extraneous semicolons after AC_MSG_WARN (configure)
+* Remove page_was_dirty and remove_protection duplicate definitions
+* Remove unnecessary type casts of printf arguments to unsigned long
+* Remove unused ALIGN_DOUBLE, USE_GENERIC_PUSH_REGS macros (TILE-Gx/Pro)
+* Rename 'test' to 'check' target in Makefile.direct
+* Replace deprecated rewind to fseek in cordxtra
+* Report gcc/clang pedantic warnings (configure)
+* Skip thread suspend/resume API testing for Tru64 (OSF1)
+* Support AddressSanitizer (Clang/GCC) and MemorySanitizer (Clang)
+* Support GC_init (and get_stack_base) from non-main thread on FreeBSD/NetBSD
+* Suppress 'tainted string passed to vulnerable operation' false defects
+* Suppress 'taking address of label non-standard' GCC/Clang pedantic warning
+* Test GC initialization from non-main thread on FreeBSD and NetBSD
+* Test GCJ object creation with length-based descriptor (gctest)
+* Update comment in finalized_disclaim to match FINALIZER_CLOSURE_FLAG
+* Update README regarding make cords with Makefile.direct
+* Update README to use autogen.sh on build from the source repository
+* Update shared libraries version info to differentiate against v7.4
+* Use mprotect instead of mmap in GC_unmap() on Cygwin
+* Use same style of include gc.h in documentation
+* Workaround '!GC_page_size is always false' cppcheck style warning
+* Workaround '#error' cppcheck error messages
+* Workaround '32-bit value shift by >31 bits is undefined' cppcheck warnings
+* Workaround 'array compared to 0', 'untrusted loop bound' false defects
+* Workaround 'bad address arithmetic' static analysis tool false positive
+* Workaround 'checking if unsigned value is negative' cppcheck warning
+* Workaround 'checking unsigned value is negative' code defect in mark_from
+* Workaround 'comparison of identical expressions' false code defects
+* Workaround 'Condition 0!=GETENV() is always false' cppcheck style warnings
+* Workaround 'condition is always false' cppcheck warning in get_next_stack
+* Workaround 'condition is always true' cppcheck style warnings in GC_init
+* Workaround 'function is never used' cppcheck style warnings
+* Workaround 'insecure libc pseudo-random number generator used' code defect
+* Workaround 'int shift by negative amount' false code defect in finalize
+* Workaround 'local variable size too big' static analyzer warning
+* Workaround 'memory leak: result' cppcheck false error (POSIX)
+* Workaround 'null pointer dereference' false positive in push_next_marked
+* Workaround 'obsolescent bcopy, bzero called' cppcheck warnings (POSIX)
+* Workaround 'obsolescent usleep called' cppcheck warning (POSIX)
+* Workaround 'obsolete function alloca() called' cppcheck warnings
+* Workaround 'passing untyped NULL to variadic function' cppcheck warning
+* Workaround 'pointer used before comparison to null' code defect (pthread)
+* Workaround 'possible null pointer dereference' cppcheck warnings
+* Workaround 'potential multiplication overflow' code defect in de_win (cord)
+* Workaround 'redundant assignment of *result to itself' cppcheck warning
+* Workaround 'resource leak' false positives in alloc_MS, bl/envfile_init
+* Workaround 'same expression on both sides of ==' cppcheck style warning
+* Workaround 'same expression on both sides of OR' cppcheck style warning
+* Workaround 'struct member is never used' cppcheck style warnings
+* Workaround 'tainted int used as loop bound' static analysis tool warning
+* Workaround 'Uninitialized variable' cppcheck errors
+* Workaround 'unused variable' cppcheck style warnings
+* Workaround 'va_list used before va_start' cppcheck error in cord
+* Workaround 'value of macro unknown' cppcheck info messages
+* Workaround 'value of REDIRECT_MALLOC/FREE unknown' cppcheck info messages
+* Workaround 'value of SIGBUS unknown' cppcheck info messages
+* Workaround 'value of WINAPI unknown' cppcheck info messages
+* Workaround 'variable hides enumerator with same name' cppcheck warnings
+* Workaround 'variable reassigned before old value used' cppcheck warnings
+* Workaround 'waiting while holding lock' code defect in stop_world (Unix)
+* Workaround false 'uninitialized var use' code defect (initsecondarythread)
+
+Also, includes 7.4.6 changes
+
+
+== [7.6.0] 2016-08-02 ==
+
+* ABORT_ARGn log details at INFO level (Android)
+* Add 'pragma message' to gc.h to detect inconsistent WIN64/_WIN64 (MS VC)
+* Add API function to calculate total memory in use by all GC blocks
+* Add API function to set/modify GC log file descriptor (Unix)
+* Add alloc_size attribute to GC_generic_malloc
+* Add alt-stack registration support
+* Add assertion for GC_new_kind boolean arguments
+* Add assertion on lock status to GC_alloc_large and its callers
+* Add build scripts for VC 9 (Win32/64)
+* Add build system plumbing for building with -Werror
+* Add incremental GC support for Darwin/arm64
+* Add profiling callback events to indicate start/end of reclaim phase
+* Add support for enumerating the reachable objects in the heap
+* Add toggle-ref support (following Mono GC API)
+* Added instructions to README.md for building from git
+* Adjust code indentation of malloc/calloc/str[n]dup
+* Allow fork() automatic handling on Android with API level 21+
+* Allow specific TLS attributes for GC_thread_key
+* Allow thread local allocations from within pthread TLS destructors
+* Allow to force GC_dump_regularly set on at compilation
+* Altera NIOS2 support
+* Change 'cord' no-argument functions declaration style to ANSI C
+* Check DATASTART is less than DATAEND even assertions off
+* Check for execinfo.h by configure
+* Code refactoring of GC_push_finalizer/thread/typed_structures
+* Code refactoring regarding 'data start' definition for FreeBSD
+* Consistently set type of DATASTART/END to ptr_t (code refactoring)
+* Consistently use int[] type for '_end' symbol (code refactoring)
+* Consistently use outermost parentheses for DATASTART/END, STACKBOTTOM
+* Define GC_LINUX_THREADS, NO_EXECUTE_PERMISSION in configure for NaCl
+* Define ROUNDUP_PAGESIZE, ROUNDUP_GRANULE_SIZE macros (code refactoring)
+* Define public GC_GENERIC_OR_SPECIAL_MALLOC and GC_get_kind_and_size
+* Do no declare kernel_id field of GC_Thread_Rep for 64-bit Android
+* Do not allow SHORT_DBG_HDRS if KEEP_BACK_PTRS or MAKE_BACK_GRAPH
+* Do not warn of missing PT_GNU_RELRO segment when custom DSO filter used
+* Document GC_register_my_thread returned value
+* Dump the block information in CSV format
+* Eliminate redundant *flh check for null in GC_allocobj
+* Enable atomic-uncollectable in operator new in gc_cpp.h
+* Enable build with musl libc
+* Enable gc.h inclusion by client without implicit include windows.h (Win32)
+* Enable huge_test for Win64 (and LLP64 target)
+* Enable thread-local storage for Android Clang
+* Enable thread-local storage usage for GC_malloc/calloc_explicitly_typed
+* Export GC_push_all_eager, GC_push_finalizer_structures
+* Fix 'arg parameter might be clobbered by setjmp' compiler warning
+* Fix assertion in GC_mark_from for non-heap regions
+* Fix compilation for Android clang/arm with bfd linker
+* Fix integer shift undefined behavior in GC_init_explicit_typing
+* Fix missing new-line and redundant trailing dot in WARN messages
+* Fix STACKBOTTOM for Solaris 11/x86
+* Fix tag collision between ENABLE_DISCLAIM and KEEP_BACK_PTRS
+* Fix unchecked fork() result in gctest (Unix, Cygwin)
+* Fix user-defined signals drop by marker threads
+* Fix various typos in comments and documentation
+* FreeBSD/arm support improvement
+* GC_make_descriptor code refactoring (eliminate two local variables)
+* GC_malloc[_atomic] global and thread-local generalization with kind
+* GC_malloc_[atomic_]uncollectable generalization
+* GC_scratch_alloc code refactoring (and WARN message improvement)
+* Group all compact fields of GC_arrays to fit in single page
+* Handle load_segs overflow in register_dynlib_callback gracefully
+* Harmonize OSX/iOS configuration; enable compiling for iPhone simulator
+* Implement event callbacks for profiling (following Mono GC API)
+* Implement the finalization extension API
+* Implement thread suspend/resume API (Linux threads only)
+* Improve documentation for disappearing links in gc.h
+* Make heap growth more conservative after GC_gcollect_and_unmap call
+* Mark fo_head, finalize_now with a single GC_push_all call (refactoring)
+* Move MessageBox invocation code from GC_abort to a separate routine (Win32)
+* NaCl/arm initial support; NaCl runtime fixes for other CPUs
+* New macro (GC_ALWAYS_MULTITHREADED) to set multi-threaded mode implicitly
+* New macro (NO_WINMAIN_ENTRY) to prefer main() instead of WinMain in test
+* New macro (REDIRECT_MALLOC_IN_HEADER) to enable source-level redirection
+* Process all PT_LOAD segments before PT_GNU_RELRO segments (Glibc)
+* Re-implement GC_finalized_malloc using GC_malloc_kind
+* Refactoring of android_thread_kill/pthread_kill calls
+* Refactoring of GC_Xobjfreelist (use single array to keep free lists)
+* Refactoring of thread-local *_freelists (use single array of free lists)
+* Refine description in README how to build from source repository
+* Refine GC_free_space_divisor comment regarding its initial value
+* Reformat code of gc_cpp.cc/h
+* Remove 'opp' local variable in GC_malloc_X
+* Remove 'sig' argument of GC_suspend_handler_inner (code refactoring)
+* Remove code commented out by 'ifdef UNDEFINED'
+* Remove hb_large_block field (use 1 extra bit of hb_flags instead)
+* Remove obsolete BACKING_STORE_ALIGNMENT/DISPLACEMENT macros for Linux/IA64
+* Remove redundant casts in GC_generic_or_special_malloc and similar
+* Remove unsupported FreeBSD/ia64 case from gcconfig.h file
+* Remove unused GC_gcjdebugobjfreelist
+* Rename ATOMIC_UNCOLLECTABLE to GC_ATOMIC_UNCOLLECTABLE
+* Replace non-API occurrences of GC_word to word (code refactoring)
+* Return GC_UNIMPLEMENTED instead of abort in GC_get_stack_base (OS/2)
+* Show WoW64 warning message if running 32-bit on Win64 (enabled by macro)
+* Standalone profiling callback for threads suspend/resume
+* Support (add machine description for) TILE-Gx and TILEPro targets
+* Support build for Android 64-bit (arm64, mips64, x86_64)
+* Support FreeBSD/aarch64, FreeBSD/mips
+* Support iOS7 64-bit (AArch64) and iOS8+ 32/64-bit (Darwin)
+* Support MinGW build in scripts
+* Turn off sigsetjmp workaround for Android/x86 starting from NDK r8e
+* Use magic header on objects to improve disclaim_test
+* Workaround 'sa_sigaction member missing' compiler error (Android/x32)
+* Workaround 'unresolved __tls_get_addr' error for Android NDK Clang
+* Workaround a bug in winpthreads causing parallel marks deadlock (MinGW)
+
+Also, includes 7.4.4 changes
+
+
+== [7.4.20] 2021-09-28 ==
+
+* Do not hold GC_fault_handler_lock when in Sleep (Windows)
+* Eliminate 'static GC_sysinfo definition has incomplete type' Clang warning
+* Eliminate 'unused function GC_add_map_entry' compiler warning
+* Eliminate 'while clause does not guard' GCC warning in GC_parse_map_entry
+* Fix OS_TYPE and USE_MMAP_ANON definitions for Cygwin/x64
+* Fix abort in GC_printf when gctest is built as WinMain executable (Cygwin)
+* Fix configure message about 'AIX gcc optimization fix'
+* Fix cordtest build in SMakefile.amiga
+* Prevent GetThreadContext failure (Windows)
+* Refactoring of WoW64 workaround (Win32)
+
+Also, includes 7.2o changes
+
+
+== [7.4.18] 2019-03-01 ==
+
+* Fix 'wrong __data_start/_end pair' error on Android
+* Fix thread_info() count argument value (OS X)
+
+Also, includes 7.2n changes
+
+
+== [7.4.16] 2018-12-13 ==
+
+* Fix 'collecting from unknown thread' abort in leak-finding mode for Win32
+* Fix 'undefined reference to GC_incremental' linker error in pthread_start
+* Fix GC_register_disclaim_proc for leak-finding mode
+* Fix concurrent bitmap update in GC_dirty
+* Fix marking of finalizer closure object
+* Fix marks and hb_n_marks consistency when disclaim returns true
+* Fix missing curses.h in cord/de when compiling manually (MS VC, MinGW)
+* Refine documentation in gc_disclaim.h
+
+Also, includes 7.2m changes
+
+
+== [7.4.14] 2018-08-11 ==
+
+* Cleanup BCC Makefile (remove absolute GC paths, fix del cmd, update clean)
+* Do not call GC_dirty_inner unless GC_incremental
+* Eliminate 'cast between incompatible function types' compiler warning
+* Eliminate 'comparing signed and unsigned values' compiler warnings (bcc)
+* Eliminate 'language extension used' Clang warning in gc.h
+* Eliminate 'possibly incorrect assignment in CORD_vsprintf' compiler warning
+* Eliminate 'switch statement contains no case label' compiler warning
+* Eliminate 'variable might be uninitialized' warning in win32_start_inner
+* Eliminate duplicate clear_mark_bit call when removing disappearing link
+* Fix 'collecting from unknown thread' abort in leak-finding mode
+* Fix compilation by digimars.mak (DMC) and by WCC makefile
+* Fix cords for MANUAL_VDB
+* Fix dependency on gc_cpp source in BCC_MAKEFILE and NT_MAKEFILE
+* Fix gctest in leak-finding mode
+* Fix missing GC_dirty calls for GC-allocated objects used internally
+* Fix missing GC_dirty invocation from debug_end_stubborn_change
+* Fix multi-threaded gctest for the case of NTHREADS is set to zero
+* Fix typos in ChangeLog and generic_malloc
+* Keep pointer to the start of previous entry in remove_specific_after_fork
+* New API function (GC_is_init_called) to check if BDWGC is initialized
+* Remove code duplication in gcj_malloc and malloc_explicitly_typed
+* Remove duplicate local variable in reclaim_block
+* Remove libatomic_ops license information from README
+* Workaround 'dynamic exception specifications deprecated in C++11' warning
+
+Also, includes 7.2l changes
+
+
+== [7.4.12] 2018-04-19 ==
+
+* Define GC_FREEBSD_THREADS and GC_ADD_CALLER macros for kFreeBSD
+* Fix comment for debug_generic_malloc_inner[_ignore_off_page]
+* Fix gctest with musl libc on s390x
+* Fix missing new-line in ABORT_ARG<n> definition
+* Fix null pointer dereference in get_private_path_and_zero_file (Symbian)
+* Fix type of local variables receiving result of PHT_HASH
+* Remove API symbols renaming in WCC_MAKEFILE
+
+Also, includes 7.2k changes
+
+
+== [7.4.10] 2018-01-22 ==
+
+* Fix error code in abort message if sem_wait failed in start_world (NetBSD)
+Also, includes 7.2j changes
+
+
+== [7.4.8] 2017-12-22 ==
+
+* Eliminate 'this statement may fall through' GCC warnings
+* Eliminate 'value exceeds maximum object size' GCC warning in huge_test
+* Fix data race in make_descriptor when setting explicit_typing_initialized
+* Fix marking of disclaim-reachable objects in the incremental mode
+* Update comment in finalized_disclaim to match FINALIZER_CLOSURE_FLAG
+Also, includes 7.2i changes
+
+
+== [7.4.6] 2017-10-26 ==
+
+* Add configure --enable-gcov option (enable code coverage analysis)
+* Add configure check whether to define NO_GETCONTEXT
+* Adjust GC_memalign comment
+* Allow HAVE_DL_ITERATE_PHDR to be defined by client (musl)
+* Allow PKG_CHECK_MODULES in configure.ac to be commented out easily
+* Avoid busy waiting in mark_thread while GC_parallel is false
+* Better document minimum value of size argument for typed allocations
+* Change type of THREAD_TABLE_INDEX result to int in win32_threads.c
+* Consistently use 'msec' instead of 'ms' in comments in pthread_support
+* Do not define amiga_get_mem, MacTemporaryNewPtr unless really used (extra)
+* Do not produce .tar.bz2 distribution file (configure)
+* Do not require libatomic_ops for single-threaded builds (configure)
+* Do not warn of missing PT_GNU_RELRO segment when custom DSO filter used
+* Document GWW_VDB in gcdescr.html
+* Eliminate 'cast to void* from int' compiler warnings (Darwin/x64)
+* Eliminate 'conditional expression is always true' code defect in GC_init
+* Eliminate 'FP divide-by-zero' static analyzer warning
+* Eliminate 'incompatible function pointer' warning in mark_some (MinGW/x86)
+* Eliminate 'ISO C forbids an empty translation unit' GCC pedantic warning
+* Eliminate 'ISO C forbids object to function pointer conversion' warning
+* Eliminate 'locally defined symbol imported' MS linker warnings (cord)
+* Eliminate 'null dereference' code defect warning in register_finalizer
+* Eliminate 'possible loss of data' compiler warnings (MS VC)
+* Eliminate 'printf format specifier mismatch' compiler warning (tools)
+* Eliminate 'type defaults to int in declaration' warning (REDIRECT_MALLOC)
+* Eliminate 'value stored is never read' warning of Clang static analyzer
+* Eliminate duplicate log messages in GC_mark_from
+* Eliminate most of collisions in GC_threads on Linux/x64
+* Ensure GC initialized when atfork_prepare is called by client
+* Fix 'arg parameter might be clobbered by setjmp' compiler warning
+* Fix 'bogus LR' detection in FindTopOfStack (Darwin)
+* Fix 'execvp argument incompatible pointer type' compiler warning (tools)
+* Fix 'GetVersion deprecated' compiler warning in os_dep (MS VC)
+* Fix 'incompatible pointer' compiler warning in GC_init_dyld (OS X 64-bit)
+* Fix 'incompatible ptr-to-int conversion' compiler warning in push_all_stack
+* Fix 'ISO C90 does not support %lf, %lg gnu_printf formats' GCC warnings
+* Fix 'ISO C90 forbids mixed declarations and code' compiler warning
+* Fix 'missing libc-version.h' build error (uClibc/x86[_64])
+* Fix 'replacement operator delete cannot be inline' GCC warning (Cygwin)
+* Fix 'variable unused' compiler warning in FirstDLOpenedLinkMap
+* Fix 'zero-size array is extension' Clang warning in os_dep (Linux/x86)
+* Fix (adjust) GC_scratch_alloc actual argument type
+* Fix deadlock in GC_help_marker caused by use of mark_cv of parent process
+* Fix finalize.c compilation in 'strict ANSI' mode
+* Fix GC shared library tests failure related to dl_iterate_phdr (musl)
+* Fix gc.h compliance to strict ANSI (pthreads)
+* Fix GC_bytes_allocd incrementation in case of allocation failure
+* Fix GC_jmp_buf multiple definition
+* Fix GC_noop6 definition to avoid its calls to be optimized away
+* Fix gctest failure if PARALLEL_MARK (musl)
+* Fix gctest thread stack overflow (musl-gcc)
+* Fix initsecondarythread_test runtime failure if GC compiled w/o threads
+* Fix lack of 2 trailing zeros in _MSC_VER numbers
+* Fix local variable declarations in disclaim_bench
+* Fix missing #error pragma
+* Fix missing .exe for disclaim test filenames in Makefile (MinGW)
+* Fix missing atomic/[un]collectable/realloc_count increments in gctest
+* Fix missing new-line and redundant trailing dot in WARN messages
+* Fix missing new-line at format strings end in subthread_create test
+* Fix mixed include of GC public header and gc_priv.h in disclaim bench/test
+* Fix potential overflow in decrement when computing GC_markers_m1
+* Fix printf format specifiers in extra files (cppcheck warnings)
+* Fix pthread_start compilation if single-obj-compilation (Linux)
+* Fix register_finalizer call in disclaim_bench for GC_DEBUG
+* Fix static assertion violation in LONG_MULT for 64-bit targets
+* Fix tag collision between ENABLE_DISCLAIM and KEEP_BACK_PTRS
+* Fix thread id leaks in subthread_create and threadkey_test
+* Fix threaded tests runtime crash if GC_NO_THREAD_REDIRECTS supplied
+* Fix tools/setjmp_t to prevent nested_sp inlining
+* Fix typo in CHECK_GCLIB_VERSION name (test)
+* Fix typos in comments/documentation (ews4800, extend_size_map, push_roots)
+* Fix unchecked fork() result in gctest (Unix, Cygwin)
+* Improve detection of internal libatomic_ops (configure)
+* Move libraries version info to the beginning of Makefile.am
+* Prevent abort in register_data_segments for Symbian
+* Process all PT_LOAD segments before PT_GNU_RELRO segments (Glibc)
+* Refine Makefile.direct comment about multi-threaded GC build
+* Refine README about library source downloading
+* Refine should_invoke_finalizers documentation
+* Remove all generated files by NT_X64_THREADS_MAKEFILE 'clean' target
+* Remove non-existent configure option in simple_example.html
+* Replace C++ style comments to C ones, remove commented out code (extra)
+* Support CFLAGS_EXTRA to pass extra user-defined compiler flags (configure)
+* Support CFLAGS_EXTRA when checking for inline and dladdr (configure)
+* Suppress 'tainted string passed to vulnerable operation' false defects
+* Suppress MS VC warnings about unused param, const condition (NT_MAKEFILE)
+* Update bdwgc mailing list online archive link in documentation
+* Update shared libraries version info to differentiate against v7.2
+* Use AC_DEFINE for defining NO_GETCONTEXT in configure
+* Workaround 'index out of bounds' UBSan false warning in push_marked
+* Workaround 'mmap() resource handle leak' static analyzer warning
+* Workaround 'redundant assignment of *result to itself' cppcheck warning
+* Workaround 'resource leak' error reported by cppcheck (tools, test)
+Also, includes 7.2h changes
+
+
+== [7.4.4] 2016-05-25 ==
+
+* Allow GC_FAST_MALLOC_GRANS() multiple use in a function
+* Also enable the TSX workaround for i386 (Linux)
+* Avoid unstructured procfs on Solaris
+* Change cord/de main() declaration style from K-R to ANSI C
+* Change no-argument functions declaration style to ANSI C (cord)
+* Do not include sigcontext.h and asm/sigcontext.h
+* Eliminate 'divide by zero' compiler warning in cordtest
+* Eliminate warning about 64-bit pointer-to-int cast (Win64/pthreads-w32)
+* Eliminate warnings detected by Cppcheck in cord de[_win]
+* Fix 'comparison of non-null parameter is always false' warning (Clang)
+* Fix 'CORD_iter5 unused result' code defect in cordxtra
+* Fix 'GC_generic_malloc_inner_ignore_off_page not used' compiler warning
+* Fix 'implicit declaration of vsnprintf' GCC warning (if strict ANSI mode)
+* Fix 'signed-to-bigger-unsigned value assignment' in GC_init_size_map
+* Fix 'signed-to-bigger-unsigned value assignment' warning for hb_map
+* Fix 'signed-to-bigger-unsigned value assignment' warning in GC_setpagesize
+* Fix 'statement unreachable' compiler warning in GC_mark_from
+* Fix 'statement unreachable' compiler warning in memalign
+* Fix 'unused label' compiler warning in cord/de
+* Fix 'value truncated' compiler warning in CORD_cat (MS VC)
+* Fix 'variable unused' warning in GC_save_callers
+* Fix 'visibility attribute not supported' GCC warning (IBM AIX)
+* Fix CMake warning about CMP0054 by unquoting instances of HOST
+* Fix Cygwin64 build
+* Fix GC_REALLOC to call GC_FREE if new size is zero and pointer is non-NULL
+* Fix Makefile.direct for Cygwin
+* Fix __alloc_size__ availability detection (Clang)
+* Fix abort message in GC_move_long_link
+* Fix and code refactoring of lock elision workaround (Linux/x64)
+* Fix assertion on mark_lock_holder for non-unique NUMERIC_THREAD_ID
+* Fix data race in GC_init_explicit_typing
+* Fix gc.mak regarding msvc_dbg and test (MSVC)
+* Fix missing error handling of pthread_attr_init/getstacksize
+* Fix missing error handling of pthreads_mutex_init and cond_wait
+* Fix missing numeric casts in cord
+* Fix potential left shift overflows in finalize.c (64-bit targets)
+* Fix pthreads-win32 name in comments and documentation
+* Fix setup_mark_lock missing prototype
+* Fix unchecked fcntl() result
+* Fix unchecked pointer dereference in check_ints (gctest)
+* Fix unchecked pthread_join() result in threadkey_test
+* Fix unchecked sigdelset() result in pthread_support
+* Fix undefined PTRFREE/NORMAL in gc_inline.h
+* Prefix PREFETCH_FOR_WRITE with GC_ as used in gc_inline.h public header
+* Relax mark_mutex attribute needed to disable elision (Linux/x64)
+* Remove (deprecate) TODO file
+* Remove code duplication in GC_realloc
+* Remove duplicate new-line in OUT_OF_MEMORY message (cord)
+* Remove references to missing linux_threads.c from documentation
+* Revert "Move asm machine-dependent files to 'src' folder" (partly)
+* Support Android API level 21
+* Update compiler options in gc.mak (Win32)
+* Use mmap instead of sbrk (Hurd)
+* Workaround 'comparison is always false' GCC warning in GC_FAST_MALLOC_GRANS
+* Workaround 'identical expr on both sides of bitwise op' warning
+* Workaround Linux NTPL lock elision bug
+* Workaround false warning about unreachable code path
+* Workaround invalid '_end' symbol on Android clang 3.5+
+Also, includes 7.2g changes
+
+
+== [7.4.2] 2014-06-03 ==
+
+* Add config option to use STGRTMIN-based signals for thread suspend/resume
+* Allow parallel mark to be enabled on powerpc-linux systems
+* Check for Fujitsu compiler in builtin_unwind logic (enable FX10/K-Computer)
+* Fix 'Array subscript is above array bounds' GCC warning in GC_new_kind/proc
+* Fix 'attribute declaration must precede definition' warning (clang-3.1)
+* Fix (enable) Cygwin-64 build
+* Fix GC_finalized_malloc failure on disclaim_test
+* Fix GC_sig_suspend initialization when non-constant SIGRTMIN used
+* Fix MS VC redefinition warning for functions declared with GC_ATTR_MALLOC
+* Fix TEXT() usage for concatenated strings in GC_CreateLogFile (Win32)
+* Fix data roots registration for Android/x86 and NDK ARM 'gold' linker
+* Fix find stackbottom on BlueGene P/Q systems
+* Fix machdep .lo files path in configure (SPARC, IA-64)
+* Fix ok_init assignment (missing cast) in GC_new_kind_inner
+* Fix typos in names in AUTHORS and ChangeLog files
+* Remove barrett_diagram file duplicated by tree.html
+* Remove non-existing DISCARD_WORDS from GC data structure ASCII diagram
+* Restore contribution information for ancient releases in ChangeLog
+Also, includes 7.2f changes
+
+
+== [7.4.0] 2013-11-17 ==
+
+* Add 'bytes reclaimed' counters to public GC_prof_stats_s
+* Add AArch64 (64-bit ARM) target support
+* Add GC_LONG_REFS_NOT_NEEDED ifdefs to exclude long link functionality
+* Add GC_get_prof_stats[_unsafe]() to GC public API
+* Add GC_push_all/conditional() to GC public API
+* Add assertion on number_of_objs to GC_extend_size_map
+* Add assertion to GC_enable() ensuring no counter underflow
+* Add assertion to LOCK definition that lock is not already held
+* Add assertion to LONG_MULT and remove useless assert in PUSH_CONTENTS_HDR
+* Add double-lock assertion to GC_acquire_mark_lock
+* Add manual POSIX fork handling support (Android)
+* Add note about 'pkg-config' solving problem with autoconf 2.68 or older
+* Add public GC_set/get_abort_func to replace default GC_on_abort
+* Add public GC_start_mark_threads() to allow parallel marker in fork child
+* Add public setter and getter for GC_push_other_roots
+* Add support of Android logger
+* Add tests for GC_register/move/unregister_long_link
+* Add thread suspend/resume signals public setters (POSIX threads)
+* Added long weakref support
+* Adjust GC_dont_expand/gc/precollect and GC_print_stats type to match gc.h
+* Adjust README.md title and references to doc .html files in it
+* Adjust build scripts to enable additional test library in staticrootstest
+* Adjust logged messages in start_mark_threads and GC_thr_init
+* Adjust printf format specifiers in GC_print_trace
+* Allow not to rely on __data_start value (Linux)
+* Allow pthread_kill error code logging in GC_suspend/resume (debugging)
+* Allow to compile GC_inner_start_routine aside from extra/gc.c
+* Allow to omit libc atexit() call
+* Avoid LOCK/UNLOCK hard-coding in gc_locks.h for PS3 target
+* Better document GC_warn_proc in gc.h
+* Call GC_on_abort (with NULL argument) on exit(1)
+* Call GC_stats/verbose_log_printf instead of GC_log_printf if print_stats
+* Change policy regarding version numbers ("micro" part instead of "alpha")
+* Changed C99-style designated init of GC_dl_hashtbl struct to use C89-style
+* Check GC_base result in GC_print_all_smashed_proc
+* Check that SIG_SUSPEND and SIG_THR_RESTART are different (Pthreads)
+* Check traceable_allocator.allocate result before dereference in test_cpp
+* Code refactoring of GC_x_printf (move shared code to macro)
+* Convert readme to markdown
+* Default to use libc_stack_end in single-threaded GC on glibc targets
+* Define GC_VSNPRINTF internal macro in misc.c (code refactoring)
+* Define functions in darwin_semaphore.h as inline instead of static
+* Define old_bus_handler static variable only if used (Unix)
+* Detect dladdr() presence by configure
+* Disable find-leak GC_gcollect on GC abnormal EXIT
+* Do not define _setjmp/_longjmp macros in mach_dep.c
+* Do not duplicate android_log_write output to GC log file (Android)
+* Do not include sigcontext.h if NO_SIGCONTEXT_H (Linux)
+* Do not set GC_lock_holder by call_with_alloc_lock if assertions disabled
+* Do not use pthread_getattr_np if NO_PTHREAD_GETATTR_NP specified
+* Elaborate comment on dependencies in autogen.sh
+* Eliminate 'cast from int to pointer' warning in GC_exclude_static_roots
+* Eliminate 'missing exception specification' warning in gc_cpp.cc (Clang)
+* Eliminate 'uninitialized variable use' warning in test_printf (cord)
+* Eliminate 'unused result' compiler warning in main() of test_cpp
+* Eliminate 'unused value' compiler warning in GC_stop_world (Pthreads)
+* Eliminate 'unused variable' compiler warning in start_mark_threads (HP/UX)
+* Eliminate Clang warning for GC_pthread_exit attribute
+* Eliminate GCC warning about uninitialized 'hhdr' in GC_allochblk_nth
+* Eliminate GCC warning in GC_get_main_stack_base (OpenBSD)
+* Eliminate GCC warnings in setjmp_t.c, test_cpp and cord 'de' app
+* Eliminate GC_first_nonempty atomic value reload in GC_mark_local assertion
+* Eliminate SIGBUS-related dead code in GC_write_fault_handler (Linux)
+* Eliminate warning and simplify expression in GC_init_explicit_typing
+* Enable 'force GC at every GC_malloc' debug-related functionality
+* Enable on-demand debug logging in GC_FindTopOfStack (Darwin)
+* Enable prefetch operations by default (GCC 3.0+)
+* Enable staticrootstest for the case of GC shared library build
+* Enable thread-local allocation support for Clang on Cygwin
+* Explicitly specify that Darwin, Linux and Solaris platforms have dladdr
+* Fix ABORT definition for mingw32ce (WinCE)
+* Fix AM_CONFIG_HEADER in configure for autoconf-2.69-1
+* Fix GC_CreateThread and GC_beginthreadex definition for Cygwin
+* Fix GC_INIT_CONF_ROOTS in gc.h for Android
+* Fix GC_INLINE definition to comply with ISO C90 standard (GCC)
+* Fix GC_remove_all_threads_but_me for Android (fork support)
+* Fix debug_register_displacement calls from GC_debug_generic_malloc_inner
+* Fix dyn_load.c compilation for Android 4.3
+* Fix make disclaim_test to link with new GNU ld linking rules
+* Improve GC error printing atomicity in GC_debug_X and GC_print_obj
+* Improve GC output atomicity in GC_print_obj, GC_print_all_errors
+* Improve debug-only messages of add/remove_roots and init_linux_data_start
+* Improve fork test logging in gctest
+* Improve logged messages about heap size and usage
+* Improve logging for Android differentiating messages by log level
+* Improve staticrootstest (add global data to library, add lib w/o GC_INIT)
+* Improve staticrootstest checks (tests)
+* Include "config.h" instead of "private/config.h" on HAVE_CONFIG_H
+* Include proper header file in 'tools' for configuration macros
+* Include pthread_np.h from pthread_stop_world.c on OpenBSD
+* Log error messages to stderr instead of stdout in tests
+* Make GC_generic_malloc_ignore_off_page() public
+* Make GC_mark_lock_holder variable static
+* Make GC_print_trace always thread-safe and remove 'lock' argument
+* Mark GC_started_thread_while_stopped() as GC_INNER
+* Minimize code duplication in GC_mark_and_push
+* Move 'include setjmp.h' from mach_dep.c to gc_priv.h
+* Move GC_OPENBSD_UTHREADS definition to private/gcconfig.h (OpenBSD)
+* Move GC_get_suspend/thr_restart_signal to misc.c for NaCl and OpenBSD
+* Move LOCK/UNLOCK from GC_unregister_disappearing_link_inner outer
+* Port BDWGC to Android/x86
+* Postpone the suspend signal in GC_dirty_init only if used to stop world
+* Prepend '#' symbol to GC number in logged messages
+* Prevent POSIX fork if mprotect_thread is started (Darwin)
+* Prevent abort on GC_err/warn_printf write failure
+* Prevent misleading AC_MSG_ERROR/AS_IF errors reported in configure.ac
+* Put gc_cpp symbols into 'boehmgc' namespace if GC_NAMESPACE defined
+* Recognize GC_DONT_GC macro in gc.h (causes GC_INIT to turn off GC)
+* Recognize GC_SIG_SUSPEND and GC_SIG_THR_RESTART tuning macros in gc.h
+* Redirect WRITE to __android_log_write if GC_ANDROID_LOG (Android)
+* Refine comment of GC_is_heap_ptr and GC_thread_is_registered in gc.h
+* Register dynamic libraries via dl_iterate_phdr on Android and OpenBSD
+* Remove DebugBreak on WriteFile failure (Win32)
+* Remove GC_BUILD definition from build scripts
+* Remove abort on open log failure from GC_write (Win32)
+* Remove configure.ac outdated revision number
+* Remove nested EXPECT in GC_core_finalized_malloc
+* Remove nested always-false ifdef for HPUX and FREEBSD
+* Remove redundant GC_err_printf before abort
+* Remove unused UTHREAD_SP_OFFSET macro (OpenBSD)
+* Rename subthread_create to subthreadcreate_test (Makefile)
+* Replace GC_COND_LOG_PRINTF calls with WARN for allocation failure messages
+* Replace GC_log/err_printf() followed by ABORT with ABORT_ARGn()
+* Replace GC_stats_log_printf with GC_DBG/INFOLOG_PRINTF
+* Replace SIG_SUSPEND/THR_RESTART macros to variables in pthread_stop_world
+* Replace Win32 GC_delete_gc_thread with GC_delete_gc_thread_no_free
+* Replace conditional GC_log_printf calls with GC_COND/VERBOSE_LOG_PRINTF
+* Replace sprintf with defensive snprintf
+* Replace var-args GC_noop with GC_noop6 (to eliminate Clang warning)
+* Simplify LOCK/UNLOCK macro definition for static code analysis tools
+* Specify GC_malloc result is unused in some tests
+* Specify GC_pthread_join result is unused in threadkey_test
+* Specify LT_INIT in configure.ac
+* Start of port to QNX
+* Support rthreads introduced in OpenBSD 5.2+
+* Suppress 'GC_dont_gc deprecated' warning in gc.h if GC_DONT_GC
+* Tag GC malloc routines with alloc_size attribute for Clang 3.2+
+* Test NO_WRAP_MARK_SOME macro to suppress WRAP_MARK_SOME-specific code
+* Turn off GC_LOOP_ON_ABORT functionality if GC compiled with NO_DEBUGGING
+* Turn on world-stop delay logging at debug level by default for Android
+* Use EXPECT in GC_COND/VERBOSE_LOG_PRINTF
+* Use GC_log_printf for logging instead of GC_[err_]printf
+* Use compiler TLS for Android NDK gcc/arm
+* Use memcpy (BCOPY) instead of strcpy (to suppress GCC warning)
+* Use pthread API to operate thread-local data on Linux if no compiler TLS
+* Workaround 'ELF_DATA/EM_ALPHA redefined' warning in Android linker.h
+* Workaround 'unresolved __tls_get_addr' error for Android NDK Clang
+Also, includes 7.2e, 7.2d, 7.2c, 7.2b changes
+
+
+== [7.3alpha2] 2012-05-11 ==
+
+* Add 'const' qualifier to pointer argument of some API functions
+* Add GC_UNDERSCORE_STDCALL, UNICODE macro templates to configure (Win32)
+* Add GC_get_thr_restart_signal, GC_thread_is_registered to GC API
+* Add GC_is_heap_ptr, GC_move_disappearing_link to GC API
+* Add SHORT_DBG_HDRS macro template to configure
+* Add Symbian port to mainline (porting done by Djamel Magri)
+* Add TODO file
+* Add assertion ensuring proper alignment of 'pushed' GC symbols
+* Add assertion in GC_getspecific on qtid
+* Add assertion to GC_incremental_protection_needs, refine documentation
+* Add assertion to check GC_large_free_bytes by GC_finish_collection
+* Add configure option to compile all library .c files into single gc.o
+* Add cordtest to make check
+* Add disclaim callbacks for efficient finalization (ENABLE_DISCLAIM)
+* Add finalization.html to 'doc' folder
+* Add javaxfc.h to the installation set of GC header files (configure)
+* Add on-heap-resize event notification to API
+* Adjust GC_log_printf format specifiers (regarding signed/unsigned long)
+* Adjust GC_requested_heapsize on GC_init if GC_INITIAL_HEAP_SIZE given
+* Allow GC_exclude_static_roots() region start to be unaligned
+* Allow Win32 DllMain chaining on the client side
+* Allow to exclude finalization support by GC_NO_FINALIZATION macro
+* Allow to get memory via Win32 VirtualAlloc (USE_WINALLOC) on Cygwin
+* Avoid unnecessary GC_find_limit invocation if GC_no_dls
+* Avoid use of deprecated GC_dont_gc and GC_stackbottom in gctest
+* Cast pointers to word (instead of unsigned long) in specific.h
+* Changed the order in autogen.sh so ltmain exists in time for automake
+* Declare privately and use handy GC_base_C() for constant object pointers
+* Define GC_DLL if DLL_EXPORT at GC build (for Cygwin/MinGW)
+* Define GC_READ_ENV_FILE in configure for WinCE unless gc-debug is off
+* Do not compile backgraph.c unless configure '--enable-gc-debug'
+* Do not compile pthread_stop_world.c for Cygwin/Darwin (configure)
+* Do not install ancient new_gc_alloc.h broken for modern STL (configure)
+* Enable GC_MIN_MARKERS to set minimal number of pthread-based markers
+* Enable PARALLEL_MARK and THREAD_LOCAL_ALLOC for FreeBSD in configure
+* Enable parallel mark by default in configure (Darwin/Linux/Solaris/Win32)
+* Export GC_is_marked, GC_clear/set_mark_bit (for mark-bit manipulation)
+* Extend thread-related debug messages
+* Fix 'configure --enable-cplusplus' for Cygwin/MinGW
+* Fix DATASTART (and other minor improvements) for NaCl target
+* Fix GC_setspecific to prevent garbage collection inside
+* Fix compiler warning in cordtest
+* Fix minor warnings reported by GCC with '-pedantic' option
+* Fix static data roots registration on Android (if GC is shared)
+* Implement GC_get_stack_base for Darwin for single-threaded mode
+* Improve GC_allochblk algorithm of block splitting when unmapping enabled
+* Improve GC_collect_or_expand algorithm for many finalizers registered case
+* In tests, print a message in case a test is a no-op
+* Instruct configure to hide internal libgc.so symbols if supported by GCC
+* Log amount of unmapped memory (if enabled) on marking-for-collection
+* Make __data_start a weak symbol to allow loading modules on mips
+* Move "cord" library tests to "cord/tests" folder
+* Move asm machine-dependent files to "src" folder
+* Move build tools sources to "tools" folder
+* Move cord_pos.h to public headers folder
+* Open log file in APPEND mode on Win32 (similar that on Unix/Cygwin)
+* Optimize some functions by moving pthread_self calls out of LOCK section
+* Place only major per-release changes description to ChangeLog (this file)
+* Prevent compiler warnings in GC_FindTopOfStack and GC_ports (Darwin)
+* Recognize GC_LOG_TO_FILE_ALWAYS macro to log to 'gc.log' by default
+* Remove all auto-generated files from the repo
+* Remove binary icon file for de_win
+* Remove cordtest from "cord" library
+* Remove duplicate MacOS_Test_config.h file
+* Remove gc_amiga_redirects.h (included internally) from public headers
+* Remove obsolete Makefile.DLL (superseded by Cygwin/MinGW configure)
+* Remove obsolete unused asm files for ALPHA, HPUX, SGI, RS6000, ULTRIX
+* Remove unsupported MMAP_STACKS (specific to Solaris threads)
+* Remove unused ancient SILENT, __STDC__, NO_SIGNALS macros
+* Replace ARGSUSED comment-based annotation with GCC 'unused' attribute
+* Replace GC_ms_entry declaration with opaque definition for public API
+* Replace long GC_markers global variable with int GC_markers_m1
+* Replace pointer relational comparisons with non-pointer ones
+* Replace printf PRIxMAX specifier with '%p' for thread id debug output
+* Require autoconf 2.61 instead of v2.64
+* Simplify autogen.sh (use autoreconf)
+* Split GC_abort with GC_on_abort and abort() invoked from ABORT
+* Support GC_ATTR_MALLOC for MS VisualStudio
+* Tag auxiliary malloc-like API functions with 'malloc' attribute
+* Tag deprecated variables in GC API
+* Tag must-be-non-null arguments of GC API functions
+* Turn on "extra" GCC warnings
+* Turn on unused-parameter checking for GCC
+* Update AUTHORS file
+* Use EXPECT for checking various 'initialized' boolean variables
+* Use USE_COMPILER_TLS on Cygwin
+* Use pthread_key for thread-local storage on FreeBSD
+* Use union of AO_t and word to favor strict-aliasing compiler optimization
+Also, includes 7.2 changes
+
+
+== [7.2o] 2021-09-28 ==
+
+* Add loop to handle abort error like in suspend logic on Darwin
+* Disable mprotect-based incremental GC if /proc roots are used (Linux)
+* Explicitly zero-initialize trace_buf (fix trace_buf initialization)
+* Fix 'ACCESS_VIOLATION in marker' GC warning on Win32 async thread start
+* Fix 'GC_generic_malloc must be available' GCC error in new_gc_alloc.h
+* Fix 'expected function body after declarator' clang error in gc_cpp.cc
+* Fix 'write to GC log failed' error
+* Fix GC_proc_fd value in child process at fork (Solaris)
+* Fix assertion violation in register_dynlib_callback on Android
+* Fix configure message about 'AIX gcc optimization fix'
+* Fix data race regarding *rlh value in generic_malloc_many
+* Fix first_thread stack_base initialization if custom GC_stackbottom (Win32)
+* Fix fread failure after enable_incremental if malloc is redirected (Linux)
+* Fix gc_cflags variable name in configure (HP/UX)
+* Fix handling of areas smaller than page size on recycle scratch area
+* Fix incorrect define GC_OPENBSD_THREADS on sparc64
+* Fix misaligned tlfs passed to AO_load on m68k
+* Fix missing GC_quiet declaration in pcr_interface.c
+* Fix missing gc_dlopen.c in CMake script
+* Fix missing scratch_last_end_ptr update (Irix)
+* Fix overflow of scratch_free_ptr value
+* Fix page_was_[ever_]dirty() for static roots (Solaris)
+* Fix printf format specifier in simple_example.html
+* Fix save_callers for multi-threaded case if built-in backtrace unavailable
+* Fix various typos in comments and documentation files
+* Fix word size, data start and alignment for OpenBSD/mips64(el)
+* Prevent WARN of incompatible incremental GC if default or manual VDB
+* Reduce a time period between GetExitCodeThread and SuspendThread (Win32)
+* Remove a misleading comment about Solaris in gc.h
+
+
+== [7.2n] 2019-03-01 ==
+
+* Fix 'mprotect remapping failed' abort on NetBSD with PaX enabled
+* Fix 'unexpected mark stack overflow' abort in push_all_stack
+* Fix BSD_TIME variant of MS_TIME_DIFF for the case of a.tv_usec < b.tv_usec
+* Fix GetThreadContext stale register values use if WoW64 (Win32)
+* Fix executable memory allocation in GC_unix_get_mem
+* Fix invalid initializer of CLOCK_TYPE variables if BSD_TIME
+
+
+== [7.2m] 2018-12-11 ==
+
+* Fix comment typos in CMakeLists.txt, backgraph.c, de.c, gcconfig.h
+* Fix hbp overflow in GC_install_counts
+* Fix start_world not resuming all threads on Darwin
+* Guard against potential buffer overflow in CORD_next and CORD_pos_fetch
+
+
+== [7.2l] 2018-08-10 ==
+
+* Fix 'pointer arithmetic with NULL' code defect in print_callers
+* Fix Borland version in documentation to match that in BCC_MAKEFILE
+* Fix comment about inv_sz computation in setup_header
+* Fix comments style in configure.ac and Makefile.am
+* Fix GC_is_valid_displacement and GC_is_visible for non-small objects
+* Fix global operator delete definition for C++14 in gc_cpp
+* Fix infinite restarting of mark_some when a static root disappeared (Linux)
+* Fix large object base computation in PUSH_CONTENTS() if MARK_BIT_PER_OBJ
+* Fix mark stack overflow checking in push_selected
+* Fix MSWIN32 macro redefinition (WCC)
+* Fix potential null dereference in GC_CONS
+* Fix register_dynamic_libraries on Windows 10
+* Fix result computation in n_set_marks
+* Fix return type in GC_set_warn_proc API documentation
+* Fix typo in comment for CORD_ec_flush_buf prototype
+* Fix typos in ChangeLog
+* Fix VirtualQuery call in case of malloc failure (Win32)
+* Install gc.3 man page instead of copying gc.man to doc folder (configure)
+* Perform thread_suspend in loop as it may be interrupted (Darwin)
+* Workaround 'template-id not supported in this context' compiler error (WCC)
+
+
+== [7.2k] 2018-04-19 ==
+
+* Fix arguments delimiter in pcr_interface.c (PCR)
+* Fix assertion violation in DllMain of win32_threads
+* Fix data race during apply_to_each_object(reset_back_edge)
+* Fix dbg_mlc.c/o file name in documentation
+* Fix include gc_gcj.h in thread_local_alloc.c
+* Fix man section number (3)
+* Fix missing GC_generic_malloc_words_small implementation in new_gc_alloc.h
+* Fix missing SIGBUS handler setup for kFreeBSD
+* Fix null dereference in print_callers on backtrace_symbols failure
+* Fix the collector hang when it is configured with --enable-gc-debug
+* Fix thread_suspend fail for threads registered from key destructor (OS X)
+* Fix typo in AIX macro name
+* Fix typo in comment in specific.h
+
+
+== [7.2j] 2018-01-21 ==
+
+* Fix GC allocation mutex in child after a fork
+* Fix last_reclaimed..gc_no interval comparison to threshold in unmap_old
+* Fix libgc version which was changed in linkage breaking way
+* Fix missing EOLn output in threadlibs tool
+
+
+== [7.2i] 2017-12-21 ==
+
+* Avoid data race in finalized_count (gctest)
+* Fix assertion violation about disabled cancel in try_to_collect_inner
+* Fix data race in a list referenced by A.aa (gctest)
+* Fix data race in do_local_mark when comparing active_count to helper_count
+* Fix data race in GC_init_explicit_typing
+* Fix data race in last_stop_count access (suspend_handler_inner)
+* Fix data race in mark_thread when updating mark_no
+* Fix data race when getting object size in explicitly-typed allocators
+* Fix lack of barriers to synchronize memory for suspend_handler
+* Fix typos in cdescr.html, extend_size_map and ews4800 doc, README.sgi
+* Prevent 'Unexpected heap growth' in single-threaded gctest (Linux/x64)
+
+
+== [7.2h] 2017-10-12 ==
+
+* Add gctest as a test (CMake)
+* Change no-argument functions declaration style to ANSI C (extra files)
+* Do not allow SHORT_DBG_HDRS if KEEP_BACK_PTRS or MAKE_BACK_GRAPH
+* Ensure oom_fn callback executed on out-of-memory in calloc
+* Fix '~' operator application to unsigned values shorter than word
+* Fix 'context local variable might be clobbered by setjmp' compiler warning
+* Fix 'doc' files installation folder
+* Fix 'shift count >= width of type' compiler warning in GC_SQRT_SIZE_MAX
+* Fix ALL_INTERIOR_POINTERS name in comments and documentation
+* Fix AO_SRC_DIR target name in NT_*_MAKEFILE
+* Fix assertion in GC_mark_from for non-heap regions
+* Fix assertion in GC_steal_mark_stack for non-heap regions
+* Fix assertion violation in GC_repeat_read if --enable-redirect-malloc
+* Fix assertion violation in GC_wait_builder called from start_mark_threads
+* Fix assertion violation in mark_local checking GC_mark_stack_top
+* Fix assertion violation in return_single_freelist in child process
+* Fix bm_huge initialization for 64-bit targets (gctest)
+* Fix broken external links in documentation
+* Fix bytes count passed to add_to_our_memory in backgraph new_back_edges
+* Fix calloc_explicitly_typed in case of lb*n overflow
+* Fix CMake warning about CMP0054 by unquoting instances of HOST
+* Fix conditional expression in pos_fetch, next non-macro definitions (cord)
+* Fix configure --disable-munmap handling
+* Fix CORD_substr_closure for the case when CORD_from_fn returns C string
+* Fix crash in FirstDLOpenedLinkMap if app linked statically (Alpine Linux)
+* Fix double lock in pthread_detach (Cygwin, winpthreads)
+* Fix double multiplication of lb by n in calloc_explicitly_typed
+* Fix enable_parallel_mark condition in CMake script
+* Fix external libatomic_ops pkg-config-based detection
+* Fix gc_allocator.h file name in new_gc_alloc.h comment
+* Fix gc_backptr.h, gc_mark.h, GC_DS_TAGS names in documentation
+* Fix gc_cleanup destructor for non-heap objects (gc_cpp)
+* Fix GC_collect_or_expand to prevent allocation size value wrap-around
+* Fix GC_incremental declaration/definition type mismatch
+* Fix GC_mark_stack_top assertion violation properly in mark_local
+* Fix GC_remove_specific invocation from remove_all_threads_but_me
+* Fix GC_requested_heapsize increment in GC_init
+* Fix GC_setspecific to prevent garbage collection inside
+* Fix GC_SIZE_MAX definition (Linux/musl-gcc)
+* Fix GCJ support in CMake build script
+* Fix gctest crash if configure --enable-handle-fork on Darwin
+* Fix get_maps on proc maps file asynchronous growth
+* Fix hb_n_marks underflow in clear_fl_marks if MARK_BIT_PER_OBJ
+* Fix header filename in gcconfig.h comment
+* Fix infinite mark_some calls after memory mapping disappeared (Glibc)
+* Fix integer shift undefined behavior in GC_init_explicit_typing
+* Fix leak_test crash in print_callers if free() is redirected
+* Fix Makefile.direct recursive invocation
+* Fix malloc routines to prevent size value wrap-around (fix CVE-2016-9427)
+* Fix missing win32_threads.c compilation for Cygwin (CMake)
+* Fix MS VC warning about compiling unused checksums and thread_local_alloc
+* Fix name typos in GC_FAST_MALLOC_GRANS comment
+* Fix null dereference in reclaim_block if DONT_ADD_BYTE_AT_END
+* Fix OSF1 host pattern in CMakeLists.txt
+* Fix PCR-Makefile by removing compilation of a missing file
+* Fix potential data race in GC_SysVGetDataStart (SPARC)
+* Fix potential integer overflow in GC_find_limit_* functions
+* Fix printf arguments type in print_callers
+* Fix pthread_detach for threads not yet registered (Cygwin, winpthreads)
+* Fix pthread_join to avoid thread removal on failure (Cygwin, winpthreads)
+* Fix pthread_join when thread is registered in thread key destructor
+* Fix push_complex_descriptor to avoid unlimited global mark stack growth
+* Fix removal of dead threads in a child process
+* Fix SIGSEGV in GC_is_marked when gc_cleanup is used in leak-finding mode
+* Fix SIGSEGV in mark_from called from do_local_mark if WRAP_MARK_SOME
+* Fix Solaris/sparc detection in case of strict C compliance is enforced
+* Fix STACKBOTTOM for Solaris 11/x86
+* Fix storage class of local variable in register_dynamic_libraries (Irix)
+* Fix tools/setjmp_t hang (OS X)
+* Fix typed_test to prevent fails in malloc_explicitly_typed (64-bit)
+* Fix undefined HEAP_START in register_dynamic_libraries
+* Fix USE_CUSTOM_SPECIFIC mode (if manually enabled) for Win32
+* Fix USE_GET_STACKBASE_FOR_MAIN definition in gcconfig.h
+* Fix various typos in comments, documentation and printed messages
+* Handle load_segs overflow in register_dynlib_callback gracefully
+* Prevent misleading AC_MSG_ERROR/AS_IF errors reported in configure.ac
+* Replace (fix) 'objs' acronym in comments with 'objects' word
+* Revert "Skip GC_DS_PER_OBJECT objs with negative descriptor in GC_mark_from"
+* Update documentation about bugs reporting and new releases notification
+* Update Download information in GC overview document
+* Update shared libraries version info (v7.2)
+* Workaround a bug in winpthreads causing parallel marks deadlock (MinGW)
+* Workaround missing getcontext() in Docker osrf/ubuntu_32bit
+
+
+== [7.2g] 2016-05-23 ==
+
+* Fix 'illegal option -xassembler-with-cpp' error (Oracle SunCC)
+* Fix 'implicit declaration of function' compiler warnings in cord/de
+* Fix CFLAGS in configure regarding -O flag passing to SunCC compiler
+* Fix FirstDLOpenedLinkMap for case libgc not 1st dynamically linked (NetBSD)
+* Fix GC initialization in cord de_win for Cygwin
+* Fix GC_get_stack_base if called before GC_init (Win32)
+* Fix OSX issue with pthread_attr_setstacksize failure
+* Fix Unicode Win32 API calls in cord de_win
+* Fix USE_COMPILER_TLS macro duplicate description in README
+* Fix cord de_win WndProc prototype parameters for 64-bit (Win64)
+* Fix file descriptor resource leak in GC_register_data_segments (OS/2)
+* Fix filename printing in cordtest
+* Fix missing cord_pos.h, ec.h among installed headers (Automake)
+* Fix missing GC_get_stack_base for Amiga
+* Fix missing msvc_dbg.h in dist_noinst_HEADERS (Automake)
+* Fix mistyped ARM_THREAD_STATE macro (Darwin/arm)
+* Fix null-pointer dereferences on out-of-memory in cord and tests
+* Fix potential multiplication overflow in check_heap_stats (gctest)
+* Fix race (and potential deadlock) at marker threads initialization
+* Fix signedness of char values passed to isspace, iscntrl, isxdigit
+* Fix typo (items numbering) in GC_finalize_all documentation
+* Fix typos in ERROR_FL, GC_malloc_uncollectable comments
+* Fix typos in gc_priv.h, in README for ews4800
+* Fix unresolved vsnprintf in misc.c and snprintf in cordtest (DJGPP, VC)
+* Fix various spelling errors
+* Fix vsprintf_args initialization/cleanup in CORD_vsprintf for EMX
+* Regenerate configure files using official libtool release (v2.4.2)
+* Remove documentation about obsolete GC_REDIRECT_TO_LOCAL
+* Skip GC_DS_PER_OBJECT objects with negative descriptor in GC_mark_from
+* windows-untested: Fix paths to msvc_dbg.c/h
+
+
+== [7.2f] 2014-06-03 ==
+
+* Fix 'Bad signal in suspend_handler' abort on FreeBSD-9.2
+* Fix 'source file in a subdirectory' Automake warnings
+* Fix ABORT message in GC_restart_handler
+* Fix ADD_DEFINITION in CMakeLists.txt for kFreeBSD
+* Fix CMakeLists.txt: do not override CMAKE_OSX_ARCHITECTURES
+* Fix GC_alloc_large by bumping GC_collect_at_heapsize in GC_add_to_heap
+* Fix GC_scratch_last_end_ptr update on GC_scratch_alloc failure
+* Fix GET_MEM argument rounding in GC_scratch_alloc and similar
+* Fix PARALLEL_MARK for Windows 7+
+* Fix build (broken by fenv.h inclusion) on Linux/x86_64 under uClibc
+* Fix crash when using GC_malloc_many() as first allocation call
+* Fix mark stack excessive growth during parallel mark
+* Fix or remove broken URLs in documentation
+* Fix out-of-memory case in new_back_edges, push_in_progress (backgraph)
+* Fix typo in GC_collect_or_expand comment
+* Fix typos in GC overview file, gc_config_macros.h, gc_cpp.h, README.changes
+* Regenerate configure files by automake 1.14.1, libtool 2.4.2.418
+* Update emails/links due to project site and ML transition
+
+
+== [7.2e] 2013-11-10 ==
+
+* Add weak attribute to avoid __data_start undefined messages (s390x)
+* Add weak stubs for pthread_cancel API
+* Adjust 'pthread_[un]register_cancel undefined ref' workaround (Pthreads)
+* Append _test suffix to 'initsecondarythread' binary file names
+* Enable PARALLEL_MARK and THREAD_LOCAL_ALLOC for FreeBSD in configure
+* Fix 'stack section' pointer passed to push_all_stack_sections (Pthreads)
+* Fix GC_CreateThread 'dwStackSize' argument type for Win64
+* Fix GC_PTHREAD_PTRVAL definition for GC_PTHREADS_PARAMARK (Win32)
+* Fix GC_clear_stack by declaring 'dummy' local array as volatile
+* Fix GC_get_stack_base assembly code (Cygwin/Clang)
+* Fix GC_malloc_explicitly_typed_ignore_off_page for large allocations
+* Fix GC_marker_Id elements initialization (WinCE)
+* Fix GC_print_trace missing unlock
+* Fix GC_unix_mmap_get_mem for open of /dev/zero failure
+* Fix GC_win32_free_heap compilation error for Cygwin
+* Fix GC_win32_free_heap to prevent memory leak if USE_GLOBAL_ALLOC
+* Fix Win32 GC_write preventing potential infinite recursion at abort
+* Fix assertion violation in GC_mark_from prefetch loop
+* Fix collection of objects referenced only from GC_mark_stack_X variables
+* Fix dwSize argument of VirtualFree call in detect_GetWriteWatch (Win32)
+* Fix heap sections overflow for Win32/Cygwin with enabled parallel marker
+* Fix min_bytes_allocd preventing potential infinite loop in GC_allocobj
+* Fix missing tabs in SMakefile.amiga file
+* Fix null-pointer dereference in CORD_substr_closure
+* Fix old_segv/bus_act variables initialization for FreeBSD
+* Fix potential double fclose in test_extras (cordtest)
+* Fix pthread_attr_t resource leak in pthread_create
+* Fix race in GC_print_all_errors regarding GC_leaked
+* Fix sizeof in GC_push_thread_structures
+* Fix stackbottom/stack_end assignment in GC_call_with_gc_active
+* Fix tests makefile to link with new GNU ld linking rules
+* Fix typos in comments and documentation
+* Fix unportable '==' test operators in configure
+* Fix vsprintf_args cleanup in CORD_vsprintf
+* Merge FreeBSD New ports collection for boehm-gc v7.2d
+* Replace GC_DBG_RA with GC_DBG_EXTRAS macro
+* Replace deprecated [CXX]INCLUDES to AM_C[PP]FLAGS in configure.ac file
+* Use __builtin_extract_return_addr in GC_RETURN_ADDR_PARENT (gcc/x86)
+
+
+== [7.2d] 2012-08-09 ==
+
+* Fix GC_call_with_stack_base to prevent its tail-call optimization
+* Fix all address-of-dummy operations by using GC_approx_sp() instead
+* Fix stop_info.stack_ptr assignment in GC_suspend_all for OpenBSD
+* Fix test_cpp (ensure the collector recognizes pointers to interiors)
+* Fix thread-related tests for pthreads-w32
+* test_cpp: Fix WinMain to prevent SEGV if zero arguments passed (MinGW)
+
+
+== [7.2c] 2012-06-11 ==
+
+* Fix CORD_cat_char_star to prevent SEGV in case of out-of-memory
+* Fix GC_FirstDLOpenedLinkMap() for NetBSD 6 release
+* Fix GC_scratch_alloc and GC_get_maps invocations to prevent SEGV
+* Fix visibility of GC_clear/set_mark_bit (unhide symbols)
+* Fix visibility of GC_push_all/conditional, GC_push_other_roots symbols
+
+
+== [7.2b] 2012-05-23 ==
+
+* Fix assertion in GC_malloc_[atomic_]uncollectable (THREADS case only)
+
+
+== [7.2] 2012-05-11 ==
+
+* Abort in GC_thr_init on pthread_atfork failure (POSIX threads)
+* Add GC_WIN32_PTHREADS target in configure
+* Add GC_is_disabled new function to GC API
+* Add info that getcontext() resets FPE mask no longer on Linux/x86_64
+* Add public GC_set_handle_fork to control forked child handling support
+* Add realloc_test.c test
+* Add support for Hexagon target
+* Add thread-safe GC_get_heap_usage_safe to GC API
+* Change GC_check_fl_marks prototype and implementation
+* Check pthread_create/join result in test
+* Define GC_DLL (in configure) if building only dynamic libraries
+* Define NO_DEBUGGING (in configure) if "--disable-gc-debug" is set
+* Disable incremental mode on Darwin if fork handling requested
+* Enable parallel marker in configure for Solaris
+* Fix "comparison of signed and unsigned values" compiler warnings
+* Fix 'volatile' keyword placement in GC_SysVGetDataStart
+* Fix ALIGNMENT, CPP_WORDSZ, GC_GRANULE_BYTES/WORDS for x32 target
+* Fix GC_READ_ENV_FILE code for Cygwin
+* Fix GC_add_roots_inner for Mac OS X (align segment start)
+* Fix GC_check_fl_marks regarding concurrent access
+* Fix GC_finalizer_nested size to workaround alignment problem in Watcom
+* Fix GC_find_limit_with_bound to always reset fault handler on return
+* Fix GC_init static assertion for clang/x64 (Darwin)
+* Fix GC_init[_lib_bounds] and GC_get_main_stack_base for malloc redirection
+* Fix GC_push_all/selected boundaries check
+* Fix GC_register_my_thread marking thread as detached (Cygwin/pthreads-w32)
+* Fix GC_remove_all_threads_but_me to cleanup thread-specific data storage
+* Fix GC_restart_handler to preserve errno if needed
+* Fix GC_root_size update in GC_add_roots_inner (Win32)
+* Fix GC_unregister_my_thread to ensure no ongoing incremental GC (Win32)
+* Fix GC_with_callee_saves_pushed for clang (disable __builtin_unwind_init)
+* Fix calloc, GC_generic_malloc to check for allocation size overflows
+* Fix compiler warning in GC_dyld_image_add/remove (Darwin)
+* Fix configure --enable-cplusplus make install
+* Fix configure to disable GCC aliasing optimization unless forced to
+* Fix duplicate definitions in gcconfig.h for NetBSD
+* Fix fork() support on Cygwin and Darwin targets
+* Fix gc.h compatibility regression regarding GC_PTR, GC_I_HIDE_POINTERS
+* Fix gc_cpp.cc for Cygwin (remove duplicate function definition)
+* Fix gcconfig.h to define USE_GET_STACKBASE_FOR_MAIN for Android
+* Fix gcconfig.h to handle mips64-linux target
+* Fix gctest (for Win32) to avoid GC_print_stats internal variable usage
+* Fix mach_dep.c to include sys/ucontext.h on Mac OS X 10.6
+* Fix tests to check GC_malloc result for NULL (out-of-memory)
+* Fix thread model in configure for MinGW ("win32" instead of "posix")
+* Fix various warnings reported by LINT-like tools
+* Fix visibility of some GC internal symbols used by GNU GCJ currently
+* Port some thread tests to Win32
+* Refine API GC setters and getter comments regarding locking
+* Refine GC_stackbottom description in gc.h
+* Remove duplicate calls in GC_register_dynamic_libraries
+* Remove locking in API GC_get_bytes_since_gc and friends
+* Remove newly-added GC_get_heap_size/free_bytes_inner from API
+* Remove some local variables that are unused
+* Support multi-threading for RTEMS target
+* Use global GC_noop_sink variable in GC_noop1 to suppress compiler warning
+* Use pkg-config to pick up libatomic_ops, etc
+* Workaround some Linux/arm kernels bug to get correct GC_nprocs value
+
+
+== [7.2alpha6] 2011-06-14 ==
+
+* configure_atomic_ops.sh: Remove.
+* Makefile.direct (dist gc.tar): Remove configure_atomic_ops.sh.
+* Makefile.am (EXTRA_DIST): Add autogen.sh.
+
+* NT_STATIC_THREADS_MAKEFILE (.cpp.obj): Remove duplicate .cpp
+filename passed.
+* NT_X64_THREADS_MAKEFILE (.cpp.obj): Use lowercase file
+extension.
+* NT_X64_STATIC_THREADS_MAKEFILE (.cpp.obj): Likewise.
+* NT_MAKEFILE (.cpp.obj): Likewise.
+
+* alloc.c (GC_add_current_malloc_heap, GC_build_back_graph,
+GC_traverse_back_graph): Move prototype to gc_priv.h.
+* checksums.c (GC_page_was_ever_dirty): Likewise.
+* dbg_mlc.c (GC_default_print_heap_obj_proc): Likewise.
+* dyn_load.c (GC_parse_map_entry, GC_get_maps,
+GC_segment_is_thread_stack, GC_roots_present, GC_is_heap_base,
+GC_get_next_stack): Likewise.
+* finalize.c (GC_reset_finalizer_nested,
+GC_check_finalizer_nested): Likewise.
+* gcj_mlc.c (GC_start_debugging, GC_store_debug_info): Likewise.
+* malloc.c (GC_extend_size_map, GC_text_mapping): Likewise.
+* mark_rts.c (GC_mark_thread_local_free_lists): Likewise.
+* misc.c (GC_register_main_static_data, GC_init_win32,
+GC_setpagesize, GC_init_linux_data_start,
+GC_set_and_save_fault_handler, GC_init_dyld, GC_init_netbsd_elf,
+GC_initialize_offsets, GC_bl_init, GC_do_blocking_inner,
+GC_bl_init_no_interiors): Likewise.
+* os_dep.c (GC_greatest_stack_base_below, GC_push_all_stacks):
+Likewise.
+* reclaim.c (GC_check_leaked): Likewise.
+* win32_threads.c (GC_gww_dirty_init): Likewise.
+* darwin_stop_world.c (GC_is_mach_marker, GC_mprotect_stop,
+GC_mprotect_resume): Move prototype to darwin_stop_world.h.
+* pthread_support.c (GC_FindTopOfStack): Likewise.
+* dyn_load.c (GC_cond_add_roots): Merge adjacent definitions.
+* mark.c (GC_page_was_ever_dirty): Remove (as already declared).
+* mark_rts.c (GC_roots_present): Change return type to void
+pointer (to match the prototype); return NULL instead of FALSE.
+* mark_rts.c (GC_add_roots_inner): Cast GC_roots_present() result.
+* os_dep.c (NEED_PROC_MAPS): Move definition to gcconfig.h.
+* os_dep.c (GC_write_fault_handler): Make STATIC.
+* os_dep.c (GC_set_write_fault_handler): New function (only if
+GC_WIN32_THREADS).
+* pthread_start.c (GC_start_rtn_prepare_thread,
+GC_thread_exit_proc): Move prototype to pthread_support.h.
+* pthread_support.c (GC_nacl_initialize_gc_thread,
+GC_nacl_shutdown_gc_thread, GC_unblock_gc_signals):
+Likewise.
+* pthread_support.c (GC_stop_init): Move prototype to
+pthread_stop_world.h.
+* win32_threads.c (GC_write_fault_handler): Remove prototype.
+* win32_threads.c (GC_register_my_thread_inner): Call
+GC_set_write_fault_handler instead of SetUnhandledExceptionFilter
+(only if MPROTECT_VDB).
+* doc/README.win32: Add information about DMC.
+* include/private/gc_priv.h (GC_set_write_fault_handler): New
+prototype (only if GC_WIN32_THREADS and MPROTECT_VDB).
+
+* misc.c (vsnprintf): Redirect to vsprintf() if NO_VSNPRINTF.
+
+* win32_threads.c (GC_unregister_my_thread): Use KNOWN_FINISHED()
+instead of FINISHED macro.
+* tests/test.c (check_heap_stats): Round up max_heap_sz value for
+Win32 (same as for USE_MMAP).
+
+* tests/test.c (check_heap_stats): Adjust printf format specifier
+for max_heap_sz; cast max_heap_sz accordingly.
+
+* doc/README.solaris2: Add note.
+
+* configure.ac (SOLARIS25_PROC_VDB_BUG_FIXED): Don't define for
+Solaris/x86 2.10+.
+
+* tests/threadkey_test.c (SKIP_THREADKEY_TEST): Skip the test if
+defined; explicitly define for some targets.
+
+* mark.c (GC_dirty): Add prototype (only if MANUAL_VDB).
+* stubborn.c (GC_dirty): Likewise.
+* include/private/gcconfig.h (GWW_VDB, MPROTECT_VDB, PCR_VDB,
+PROC_VDB): Undefine if MANUAL_VDB.
+* include/private/gcconfig.h (DEFAULT_VDB): Don't define if
+MANUAL_VDB.
+* os_dep.c (async_set_pht_entry_from_index): Define for
+MANUAL_VDB.
+* os_dep.c (GC_read_dirty): Set GC_dirty_maintained only if
+success; if ioctl() failed then just print warning instead of
+aborting.
+
+* include/private/gc_priv.h (GC_ASSERT): Use "%d" (instead of %ld)
+for line number printing.
+
+* os_dep.c (GC_read_dirty): Add debug logging if DEBUG_DIRTY_BITS
+(for PROC_VDB only); print errors via GC_err_printf; rename "ps"
+and "np" local variables to npages and pagesize, respectively;
+remove "current_addr" local variable.
+
+* os_dep.c (GC_get_main_stack_base): Convert to GC_get_stack_base
+for BeOS and OS/2; define HAVE_GET_STACK_BASE.
+* os_dep.c (GET_MAIN_STACKBASE_SPECIAL): Define when a specific
+GC_get_main_stack_base implementation is defined.
+* os_dep.c (GC_get_main_stack_base): Define that based on
+GC_get_stack_base() in a single place (only if
+GET_MAIN_STACKBASE_SPECIAL is unset); check GC_get_stack_base()
+result.
+
+* mark.c (GC_push_selected): Remove "push_fn" argument (use
+GC_push_all directly); update the documentation.
+* mark.c (GC_push_conditional): Simplify the code (for better
+readability).
+
+* mark.c (alloc_mark_stack): Use FALSE/TRUE (instead of 0/1) for
+boolean local variables.
+* doc/README.macros (GC_PREFER_MPROTECT_VDB): Update.
+* os_dep.c (GC_page_was_dirty, GC_page_was_ever_dirty,
+GC_remove_protection): Define for GWW_VDB and PROC_VDB in a single
+place.
+* os_dep.c (GC_page_was_dirty, GC_page_was_ever_dirty): Compute
+PHT_HASH(h) only once (store result to a local variable).
+
+* doc/README.solaris2: Update.
+
+* include/private/gcconfig.h (end, InitStackBottom): Declare
+extern variable for RTEMS.
+* include/private/gcconfig.h (DATASTART, DATAEND, STACKBOTTOM):
+Update (for RTEMS).
+* include/private/gcconfig.h (DATAEND): Fix a typo in the macro
+name (for RTEMS).
+* tests/test.c (CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER):
+Replace with CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER (for RTEMS).
+
+* include/private/gcconfig.h (MPROTECT_VDB): Enable for Solaris in
+single-threaded environment.
+
+* include/private/gcconfig.h (MPROTECT_VDB): Undefine if PROC_VDB.
+* tests/test.c (NUMBER_ROUND_UP): New macro.
+* tests/test.c (check_heap_stats): Round up total expected heap
+size to the nearest 4 MiB bound.
+* tests/test.c (check_heap_stats): Print the current and expected
+heap sizes in case of failure.
+
+* checksums.c (GC_check_blocks, GC_check_dirty): Do log printing
+only if GC_print_stats; print errors using GC_err_printf.
+* checksums.c (GC_check_blocks): Join adjacent printf() calls into
+a single one.
+
+* pthread_support.c (pthread_join): Add assertion (check thread is
+finished).
+* pthread_support.c (GC_register_my_thread): Don't detach the
+thread if invoked from the thread destructor.
+* win32_threads.c (GC_register_my_thread): Likewise.
+* win32_threads.c (GC_unregister_my_thread): Don't delete the
+thread (just set FINISHED) if the thread is not detached (only if
+GC_PTHREADS); add assertion (check the thread is not finished).
+* tests/threadkey_test.c (main): Join some created threads.
+
+* pthread_support.c (GC_delete_gc_thread): Rename "gc_id" local
+variable to "t".
+* win32_threads.c (GC_delete_gc_thread): Likewise.
+* pthread_support.c (pthread_join, pthread_detach,
+pthread_cancel): Rename "thread_gc_id" local variable to "t".
+* win32_threads.c (GC_pthread_detach): Likewise.
+* win32_threads.c (GC_delete_gc_thread): Remove "gc_nvid" local
+variable.
+* win32_threads.c (GC_pthread_join): Rename "joinee" local
+variable to "t".
+
+* pthread_stop_world.c (pthread_sigmask): Undefine even if not
+DEBUG_THREADS.
+* pthread_stop_world.c (GC_unblock_gc_signals): New function (only
+if GC_EXPLICIT_SIGNALS_UNBLOCK).
+* pthread_support.c (GC_unblock_gc_signals): New prototype.
+* pthread_support.c (GC_register_my_thread_inner,
+GC_register_my_thread): Call GC_unblock_gc_signals (only if
+GC_EXPLICIT_SIGNALS_UNBLOCK); add comment.
+* include/private/gcconfig.h (GC_EXPLICIT_SIGNALS_UNBLOCK): New
+macro.
+
+* pthread_stop_world.c (GC_suspend_handler_inner): Remove "dummy",
+"sig" local variables; rename my_thread local variable to "self".
+
+* tests/threadkey_test.c (LIMIT): Use smaller value (don't create
+more than 30 in parallel by default).
+
+* tests/threadkey_test.c (key_once, main): Work around for Solaris
+PTHREAD_ONCE_INIT.
+* tests/threadkey_test.c (LIMIT): Use smaller value for Solaris.
+
+* dyn_load.c (GC_FirstDLOpenedLinkMap): Remove unused "r" local
+variable.
+* pthread_support.c (GC_unregister_my_thread_inner): Revert back
+GC_remove_specific invocation; add a comment.
+* include/private/thread_local_alloc.h (GC_remove_specific):
+Revert back.
+* specific.c (slow_getspecific): Cast qtid to AO_t.
+* include/private/specific.h (key_create, setspecific,
+remove_specific): Remove "extern" keyword.
+* include/private/specific.h (getspecific): Change type of "qtid"
+local variable to unsigned long.
+
+* pthread_support.c (GC_check_tls): Fix "#endif" comment.
+* include/gc.h (GC_REDIRECT_TO_LOCAL): Remove deprecated comment.
+* include/private/thread_local_alloc.h (THREAD_LOCAL_ALLOC):
+Remove redundant test of the macro.
+
+* backgraph.c (add_edge): Recognize DEBUG_PRINT_BIG_N_EDGES macro.
+* os_dep.c (GC_set_and_save_fault_handler): Recognize
+SIGACTION_FLAGS_NODEFER_HACK macro.
+* pthread_support.c (mark_mutex): Recognize GLIBC_2_1_MUTEX_HACK
+macro.
+* pthread_support.c (GC_acquire_mark_lock): Remove commented out
+code.
+* include/private/gc_priv.h (SUNOS5SIGS): Don't include
+sys/siginfo.h on Linux.
+* include/private/gcconfig.h (FORCE_WRITE_PREFETCH): New macro
+recognized, force PREFETCH_FOR_WRITE to be defined on x86.
+* include/private/gcconfig.h (USE_HPUX_FIXED_STACKBOTTOM): New
+macro recognized (for HP/UX).
+
+* os_dep.c (GC_gww_page_was_ever_dirty): Fix comment (for
+GWW_VDB).
+* os_dep.c (GC_dirty_init): Use memset() for GC_written_pages
+resetting (for PROC_VDB).
+
+* tests/threadkey_test.c: New file.
+* tests/tests.am (TESTS, check_PROGRAMS): Add 'threadkey_test'.
+* tests/tests.am (threadkey_test_SOURCES, threadkey_test_LDADD):
+New variable.
+
+* pthread_support.c (GC_unregister_my_thread_inner): Don't call
+GC_remove_specific.
+* include/private/thread_local_alloc.h (GC_remove_specific):
+Remove (since it is empty for all targets).
+* pthread_support.c (GC_record_stack_base): New inline function.
+* win32_threads.c (GC_record_stack_base): Likewise.
+* pthread_support.c (GC_register_my_thread_inner): Invoke
+GC_record_stack_base.
+* win32_threads.c (GC_register_my_thread_inner): Likewise.
+* pthread_support.c (GC_register_my_thread): If thread is FINISHED
+then call GC_record_stack_base, clear FINISHED, initialize
+thread-local list and return success.
+* win32_threads.c (GC_register_my_thread): Likewise.
+* include/gc.h (GC_register_my_thread): Update documentation.
+* include/private/thread_local_alloc.h (GC_thread_key): Likewise.
+
+* thread_local_alloc.c (GC_malloc, GC_malloc_atomic): Join
+adjacent "#ifdef".
+* thread_local_alloc.c (GC_malloc_atomic): Call
+GC_core_malloc_atomic (instead of GC_core_malloc).
+
+* pthread_start.c (GC_start_rtn_prepare_thread): Change return
+type to GC_thread.
+* pthread_start.c (GC_inner_start_routine): Pass the current
+thread descriptor to pthread_cleanup_push (same as in
+win32_threads.c).
+* pthread_stop_world.c (GC_push_all_stacks): Rename "me" local
+variable to "self".
+* win32_threads.c (GC_push_all_stacks): Likewise.
+* pthread_stop_world.c (GC_suspend_all, GC_start_world): Rename
+"my_thread" local variable to "self".
+* pthread_support.c (GC_unregister_my_thread_inner): New static
+function.
+* pthread_support.c (GC_unregister_my_thread,
+GC_thread_exit_proc): Use GC_unregister_my_thread_inner.
+* win32_threads.c (GC_register_my_thread, GC_unregister_my_thread,
+GC_do_blocking_inner): Rename "t" local variable to "thread_id".
+* win32_threads.c (GC_wait_marker, GC_notify_all_marker): Rename
+"id" local variable to "thread_id".
+
+* pthread_support.c (GC_unregister_my_thread): Call pthread_self
+only once.
+* win32_threads.c (GC_pthread_start_inner): Likewise.
+* pthread_support.c (GC_unregister_my_thread): Add debug output.
+* win32_threads.c (GC_unregister_my_thread): Likewise.
+* pthread_support.c (GC_register_my_thread,
+GC_start_rtn_prepare_thread): Rename "my_pthread" local variable
+to "self".
+
+* include/gc.h (GC_HIDE_POINTER, GC_REVEAL_POINTER): Define
+unconditionally (do not test GC_I_HIDE_POINTERS); update the
+comment.
+* include/gc.h (HIDE_POINTER, REVEAL_POINTER): Define as alias to
+GC_HIDE/REVEAL_POINTER, respectively.
+* include/private/gc_pmark.h (GC_I_HIDE_POINTERS): Do not define.
+* include/private/gc_priv.h (GC_I_HIDE_POINTERS): Likewise.
+
+* include/gc.h (GC_register_my_thread): Refine the comment.
+
+* include/gc_inline.h (GC_MALLOC_WORDS, GC_CONS): Add missing
+parentheses.
+* include/gc_typed.h (GC_get_bit, GC_set_bit,
+GC_CALLOC_EXPLICITLY_TYPED): Likewise.
+
+* include/private/gcconfig.h (NO_GETCONTEXT): Add missing ')'.
+
+* include/private/gcconfig.h (NO_GETCONTEXT): Do not use
+getcontext(2) on m68k because it is not implemented there.
+
+* alloc.c (GC_clear_a_few_frames): Use BZERO().
+* mark_rts.c (GC_clear_roots, GC_rebuild_root_index): Likewise.
+* reclaim.c (GC_start_reclaim): Likewise.
+* blacklst.c (total_stack_black_listed): Remove "len" local
+variable.
+* dbg_mlc.c (GC_generate_random_valid_address): Replace "for"
+statement with "do-while" one.
+* dyn_load.c (GC_register_dynamic_libraries,
+GC_register_dynlib_callback): Remove redundant parentheses.
+
+* cord/cordxtra.c (CORD_from_file_lazy_inner): Suppress
+"unused result" compiler warning for fread().
+
+* os_dep.c (GC_write_fault_handler): Break when in_allocd_block
+is set to true.
+
+* dbg_mlc.c (GC_has_other_debug_info): Change return type to int;
+return -1 if the object has (or had) debugging info but was
+marked deallocated.
+* include/private/dbg_mlc.h (GC_has_other_debug_info): Likewise.
+* dbg_mlc.c (GC_has_other_debug_info): Update documentation;
+remove "ohdr" local variable.
+* dbg_mlc.c (GC_debug_free): Don't call GC_free if the object has
+probably been deallocated.
+* dbg_mlc.c (GC_debug_free): Don't actually free the object even
+in the leak-finding mode if GC_findleak_delay_free.
+* dbg_mlc.c (GC_check_leaked): New function (only unless
+SHORT_DBG_HDRS).
+* doc/README.environment (GC_FINDLEAK_DELAY_FREE): Document.
+* doc/README.macros (GC_FINDLEAK_DELAY_FREE): Likewise.
+* include/private/dbg_mlc.h (START_FLAG, END_FLAG): Use GC_WORD_C
+on 64-bit architectures.
+* include/private/dbg_mlc.h (NOT_MARKED): Remove redundant
+parentheses.
+* include/private/dbg_mlc.h (GC_HAS_DEBUG_INFO): Update (due to
+GC_has_other_debug_info change).
+* include/private/gc_priv.h (GC_findleak_delay_free): New global
+variable declaration (unless SHORT_DBG_HDRS).
+* misc.c (GC_findleak_delay_free): New global variable; recognize
+GC_FINDLEAK_DELAY_FREE.
+* misc.c (GC_init): Recognize GC_FINDLEAK_DELAY_FREE environment
+variable (unless SHORT_DBG_HDRS).
+* reclaim.c (GC_check_leaked): Declare (unless SHORT_DBG_HDRS).
+* reclaim.c (GC_add_leaked): Don't add the object to leaked list
+if marked as deallocated.
+
+* dbg_mlc.c (GC_has_other_debug_info): Fix punctuation in the
+comment.
+* dbg_mlc.c (GC_FREED_MEM_MARKER): New macro.
+* dbg_mlc.c (GC_debug_free): Use GC_FREED_MEM_MARKER.
+* dbg_mlc.c (GC_smashed): Refine documentation.
+* mark.c (GC_push_selected): Change dirty_fn return type to
+GC_bool.
+* os_dep.c (GC_page_was_ever_dirty): Make GC_INNER.
+* reclaim.c (GC_reclaim_small_nonempty_block): Remove "kind"
+local  variable.
+* reclaim.c (GC_reclaim_block): Pass true constant to
+GC_reclaim_small_nonempty_block (instead of report_if_found).
+* doc/README.autoconf: Update; fix a typo.
+* include/private/gcconfig.h (GC_WORD_C): New macro.
+
+* dbg_mlc.c (GC_store_debug_info_inner): Cast "linenum".
+* dbg_mlc.c (GC_check_annotated_obj): Fix punctuation in the
+comment.
+* dbg_mlc.c (GC_print_smashed_obj): Add (and print) "msg"
+argument.
+* dbg_mlc.c (GC_debug_free, GC_print_all_smashed_proc): Pass
+message to GC_print_smashed_obj.
+* dbg_mlc.c (GC_debug_free): Call GC_size once.
+* dbg_mlc.c (GC_debug_realloc): Calculate old_sz only if
+allocation succeeded; remove unnecessary check for object is
+smashed (since this is done in GC_debug_free); remove "clobbered"
+local variable.
+
+* dbg_mlc.c (GC_store_debug_info_inner, GC_store_debug_info):
+Rename "integer" argument to "linenum"; change the type of the
+argument to int.
+* gcj_mlc.c (GC_store_debug_info): Likewise.
+* dbg_mlc.c (GET_OH_LINENUM): New macro.
+* dbg_mlc.c (GC_print_obj, GC_print_smashed_obj): Use
+GET_OH_LINENUM; adjust print format specifier.
+* dbg_mlc.c (GC_debug_malloc, GC_debug_malloc_ignore_off_page,
+GC_debug_malloc_atomic_ignore_off_page,
+GC_debug_generic_malloc_inner,
+GC_debug_generic_malloc_inner_ignore_off_page,
+GC_debug_malloc_stubborn, GC_debug_malloc_atomic,
+GC_debug_malloc_uncollectable,
+GC_debug_malloc_atomic_uncollectable): Remove unnecessary cast of
+"i".
+* gcj_mlc.c (GC_debug_gcj_malloc): Likewise.
+
+* os_dep.c (GC_linux_stack_base): Rename to
+GC_linux_main_stack_base.
+* os_dep.c (GC_freebsd_stack_base): Rename to
+GC_freebsd_main_stack_base; adjust error message.
+* pthread_stop_world.c (GC_stop_init): Use GC_SEM_INIT_PSHARED
+as an argument for sem_init().
+* pthread_support.c (pthread_create): Likewise.
+* pthread_support.c (pthread_create): Abort in case sem_init()
+fails.
+* include/private/gc_priv.h (GC_SEM_INIT_PSHARED): Define.
+* tests/initsecondarythread.c: Include gcconfig.h; call GC_INIT
+from main() if it should be done from the primordial thread only.
+
+* alloc.c: Don't include sys/types.h for ArmCC.
+* dyn_load.c: Likewise.
+* os_dep.c: Likewise.
+* mach_dep.c (_setjmp, _longjmp): Redirect to setjmp/longjmp for
+ArmCC.
+* mark.c (GC_noop): Define specially for ArmCC.
+* include/private/gc_priv.h (GC_noop): Likewise.
+* misc.c (GC_init): Don't test pointers comparison for ArmCC.
+* misc.c: Don't include unistd.h for ArmCC.
+* os_dep.c (pages_executable): Rename to GC_pages_executable;
+make STATIC.
+* os_dep.c (GC_unix_mmap_get_mem): Don't define for ArmCC.
+* ptr_chck.c (GC_is_visible): Explicitly cast
+(GC_DS_PER_OBJECT-GC_INDIR_PER_OBJ_BIAS) to word (to suppress
+a compiler warning).
+* include/private/gcconfig.h: Recognize __arm.
+* include/private/gcconfig.h (HBLKPTR): Define for ArmCC.
+* include/private/gcconfig.h (HBLKPTR): Add parentheses for
+"bytes" argument.
+
+* pthread_support.c (GC_get_nprocs): Don't define for Android.
+* pthread_support.c (GC_dummy_thread_local): Don't test
+GC_LINUX_THREADS.
+* include/gc_config_macros.h (GC_ADD_CALLER, GC_RETURN_ADDR):
+Define for Android.
+
+* mach_dep.c (NO_GETCONTEXT): Move to gcconfig.h.
+* os_dep.c (GC_write_fault_handler): Don't include ucontext.h if
+NO_GETCONTEXT.
+* include/private/gcconfig.h (GETPAGESIZE): Define as a sysconf
+call for Android.
+
+* include/private/gc_locks.h (WIN32_LEAN_AND_MEAN, NOSERVICE):
+Define before including windows.h.
+* include/private/gc_priv.h (WIN32_LEAN_AND_MEAN, NOSERVICE):
+Likewise.
+* include/private/thread_local_alloc.h (WIN32_LEAN_AND_MEAN,
+NOSERVICE): Likewise.
+* include/private/gc_priv.h (MS_TIME_DIFF): Avoid floating-point
+arithmetics; add a comment.
+
+* mark.c (GC_clear_hdr_marks): Don't test USE_MARK_BYTES.
+* extra/setjmp_t.c (main): Don't test USE_MARK_BITS.
+* include/private/gc_pmark.h (SET_MARK_BIT_EXIT_IF_SET): Likewise.
+* include/private/gc_pmark.h (SET_MARK_BIT_EXIT_IF_SET): Remove
+"mark_byte" local variable.
+* include/private/gc_pmark.h (OR_WORD_EXIT_IF_SET): Add a comment
+about that AO_or() is not used by GC unless USE_MARK_BITS
+explicitly set.
+* include/private/gc_priv.h (OR_WORD): Likewise.
+* include/private/gc_pmark.h (INCR_MARKS): Remove trailing ';',
+add parentheses.
+* include/private/gc_priv.h (ONES): Define before use by
+MAKE_COOLER.
+* include/private/gc_priv.h (MARK_BITS_SZ): Define where used.
+* include/private/gc_priv.h (OR_WORD): Don't define if
+USE_MARK_BYTES.
+* include/private/gcconfig.h (USE_MARK_BYTES); Remove duplicate
+definition; simplify expression.
+
+* os_dep.c (GC_get_maps): Always close the file.
+* pthread_support.c (GC_get_nprocs): Likewise.
+* os_dep.c (READ): Define similarly across the file (without
+parameters).
+* pthread_support.c (GC_get_nprocs): Use signed int type for "i"
+and "len" local variables (since read() may return -1).
+* include/private/gc_pmark.h (LONG_MULT): Add prefix/suffix
+double underscore; add "volatile" for asm.
+* include/private/gc_pmark.h (LONG_MULT): Add missing
+parentheses.
+* include/private/gc_priv.h (OR_WORD): Likewise.
+* include/private/gc_priv.h (OR_WORD): Remove unnecessary brackets
+and ';' symbol.
+
+* os_dep.c (GC_get_stack_base): Implement for Android (same as
+for Linux).
+* pthread_support.c (GC_get_nprocs): Return 1 (instead of -1) if
+failed to open "stat" file (not to issue a warning twice); update
+the comment.
+* pthread_support.c (GC_thr_init): Call sysconf() on Android to
+get the number of CPUs.
+
+* include/private/gc_priv.h (_GNU_SOURCE): Revert one of the
+recent patches regarding this macro as the macro should be set
+(to 1) before including any other system header.
+
+* doc/README.environment (GC_INITIAL_HEAP_SIZE,
+GC_MAXIMUM_HEAP_SIZE): Update.
+
+* misc.c (GC_parse_mem_size_arg): Allow 'k', 'M', 'G' suffixes in
+heap size specifier; return 0 if not a valid one.
+* include/gc_cpp.h: Explicitly define inline one-argument delete
+operator for Cygwin (as a workaround).
+* tests/test_cpp.cc (main): Suppress compiler warnings about
+"assigned value is unused".
+
+* misc.c (GC_parse_mem_size_arg): New function.
+* misc.c (GC_init): Use GC_parse_mem_size_arg().
+* pthread_stop_world.c (tkill): Declare for Android.
+
+* include/private/gc_priv.h (_GNU_SOURCE): Include features.h
+first (except for NaCl) and then define the macro to 1 if not yet.
+
+* tests/tests.am (TESTS, check_PROGRAMS): Add
+'initsecondarythread'.
+* tests/tests.am (initsecondarythread_SOURCES,
+initsecondarythread_LDADD): New variable.
+
+* dbg_mlc.c (GC_store_debug_info_inner): Always define; add
+"const" to its string argument.
+* dbg_mlc.c (GC_store_debug_info): Call GC_store_debug_info_inner.
+* dbg_mlc.c (GC_debug_free): Set GC_have_errors in case of
+smashed or previously deallocated found.
+* dbg_mlc.c (GC_check_heap_block): Replace while loop with a for
+one.
+* reclaim.c (GC_reclaim_check): Likewise.
+* dbg_mlc.c (GC_check_heap_proc): Remove redundant cast to word.
+* os_dep.c (GC_get_stack_base): Don't initialize
+stackbase_main_self/ss_sp on Solaris if thr_main() is zero (thus
+calling GC_INIT() from a non-primordial thread is possible now).
+* reclaim.c (GC_add_leaked): Turn into an inline one.
+* reclaim.c (GC_reclaim_small_nonempty_block):
+Change report_if_found type from int/word to boolean.
+* include/private/gc_priv.h (GC_start_reclaim): Likewise.
+* include/private/gc_priv.h (set_mark_bit_from_hdr,
+clear_mark_bit_from_hdr): Place closing parenthesis properly.
+
+* os_dep.c (GC_get_main_stack_base): Try to use
+pthread_attr_getstack first for Linux if THREADS.
+* doc/README.macros (USE_GET_STACKBASE_FOR_MAIN): Adjust text
+alignment.
+
+* dbg_mlc.c (GC_generate_random_backtrace_no_gc): Fix a message
+typo.
+* dbg_mlc.c (GC_debug_malloc): Add a comment (about zero size).
+* dbg_mlc.c (GC_strdup): Call GC_err_printf instead of WARN (in
+case of NULL argument).
+* dbg_mlc.c (GC_free): In case of NULL argument, just return
+(without any warning printed); eliminate "uncollectable" local
+variable.
+
+* configure.ac (THREADDLLIBS): Use alternate thread library on
+Solaris 8.
+* configure.ac (need_atomic_ops_asm): Set to true only for SPARC
+Solaris.
+* configure.ac: Don't use libdl on mips-sgi-irix6.
+
+* mach_dep.c (NO_GETCONTEXT); Define for RTEMS.
+* mach_dep.c (GC_with_callee_saves_pushed): Don't call
+__builtin_unwind_init() for RTEMS; use setjmp() without the
+leading underscore (for RTEMS).
+* tests/test.c (BIG): Use smaller value for RTEMS.
+* tests/test.c (main): Customize for RTEMS.
+
+* configure.host: Remove doubled words in comments.
+* os_dep.c: Likewise.
+* doc/README: Likewise.
+* extra/setjmp_t.c: Likewise.
+* tests/huge_test.c: Likewise.
+* extra/setjmp_t.c (getpagesize, nested_sp, main, g): Replace the
+K&R-style function definition with the ANSI C one.
+* extra/setjmp_t.c (nested_sp): Implement in the same way as
+GC_approx_sp.
+
+* dyn_load.c (GC_dyld_sections): Add more sections.
+* dyn_load.c (GC_dyld_add_sect_fmts): New static variable.
+* dyn_load.c (L2_MAX_OFILE_ALIGNMENT): New macro.
+* dyn_load.c (GC_dyld_image_add, GC_dyld_image_remove): Improve
+logging; add support for on-demand sections.
+
+* gcj_mlc.c (GC_gcj_malloc_initialized): Use STATIC unless
+GC_ASSERTIONS.
+* include/private/gc_priv.h (GC_gcj_malloc_initialized): Don't
+declare (as external) unless GC_ASSERTIONS.
+* os_dep.c (GC_win32_free_heap): Clear GC_heap_bases[] also for
+Cygwin; add FIXME.
+* include/private/gcconfig.h: Include <sys/unistd.h> for RTEMS.
+* include/private/gcconfig.h: Add "#error" for every "-->" mark.
+* include/private/gcconfig.h (CLEAR_DOUBLE): Turn the code into
+an expression.
+* include/private/pthread_support.h (SUSPENDED_EXT): Add new flag
+(which existed previously as SUSPENDED and still exists in GCJ).
+* include/private/pthread_support.h (DISABLED_GC): Change the
+value (as it is already used by SUSPENDED_EXT).
+
+* tests/test.c (reverse_test):  Modify count (BIG) for
+ppc64-darwin.
+
+* reclaim.c (GC_print_all_errors): Recognize new GC_ABORT_ON_LEAK
+macro and environment variable; abort if any error has been
+printed provided the environment variable (or macro) is set.
+* doc/README.environment (GC_ABORT_ON_LEAK): Document.
+* doc/README.macros (GC_ABORT_ON_LEAK): Likewise.
+
+* os_dep.c (GC_unix_sbrk_get_mem, GC_unix_get_mem): Don't define
+for RTEMS.
+* include/private/gcconfig.h (RTEMS): Add support for.
+* include/private/gcconfig.h (GET_MEM): Use calloc() for RTEMS.
+
+* mallocx.c (GC_malloc_uncollectable): Move to malloc.c (since
+it is used internally in some places).
+
+* dbg_mlc.c (GC_register_finalizer_no_order): Remove redundant
+declaration.
+* dbg_mlc.c (GC_debug_malloc_replacement,
+GC_debug_realloc_replacement): Rename RA to GC_DBG_RA.
+* malloc.c (GC_debug_malloc_replacement): Likewise.
+* mallocx.c (GC_debug_realloc_replacement): Likewise.
+* dbg_mlc.c (GC_store_debug_info): Move proto from dbg_mlc.h.
+* malloc.c (GC_strdup, GC_strndup, GC_wcsdup): Move to mallocx.c.
+* malloc.c: Include errno.h only REDIRECT_MALLOC; remove redundant
+includes of string.h.
+* mallocx.c: Include string.h (for GC_strdup).
+* include/private/dbg_mlc.h (GC_store_debug_info): Move declaration
+to dbg_mlc.c.
+* include/private/gc_locks.h (UNCOND_LOCK, UNCOND_UNLOCK): Remove
+redundant trailing ';'.
+* include/private/gc_priv.h (START_WORLD, COND_DUMP): Likewise.
+* include/private/gc_locks.h (LOCK, UNLOCK): Place opening '{'
+properly.
+* include/private/gc_priv.h (GC_DBG_RA): Move from dbg_mlc.c,
+malloc.c, mallocx.c.
+
+* alloc.c (GC_check_heap, GC_print_all_smashed): Move the
+definition from misc.c.
+* dbg_mlc.c (GC_debug_malloc_atomic_uncollectable): Define as
+public.
+* include/gc.h (GC_debug_malloc_atomic_uncollectable): Declare.
+* include/gc.h (GC_MALLOC_ATOMIC_UNCOLLECTABLE): Define new public
+macro.
+* dbg_mlc.c (MAX_SMASHED): Don't define if already set.
+* reclaim.c (MAX_LEAKED): Likewise.
+* dbg_mlc.c (GC_add_smashed): Add FIXME about the concurrent
+access to the global array.
+* reclaim.c (GC_add_leaked): Likewise.
+* misc.c (GC_print_back_height): Set on if GC_PRINT_BACK_HEIGHT
+(new macro) is defined.
+* doc/README.macros (GC_PRINT_BACK_HEIGHT): Document.
+* misc.c (GC_dump_regularly, GC_init): Replace 0/1 for
+GC_dump_regularly and GC_print_back_height variables with
+FALSE/TRUE.
+* reclaim.c (GC_print_all_errors): Refine the comment.
+
+* tests/test.c (reverse_test_inner): Undo one of the previous
+patches which shifts "c" and "d" pointers only if
+ALL_INTERIOR_POINTERS (since interior pointers are always
+recognized in stacks).
+
+* misc.c (GC_stdout, GC_stderr): Move the definition to the place
+where GC_log is defined (Unix only).
+* misc.c (GC_init): Recognize "GC_ONLY_LOG_TO_FILE" environment
+variable and the similar macro; redirect GC_stdout and GC_stderr
+to GC_log if "GC_LOG_FILE" environment variable is set unless
+prohibited by GC_ONLY_LOG_TO_FILE (Unix only).
+* doc/README.environment (GC_ONLY_LOG_TO_FILE): Document.
+* doc/README.macros (GC_ONLY_LOG_TO_FILE): Likewise.
+
+* misc.c (GC_stdout, GC_write): Rename GC_stdout to GC_log (Win32
+only).
+* misc.c (GC_write): Add for MacOS (and OS/2); change WRITE()
+accordingly.
+* misc.c (GC_printf): Check GC_quiet before va_start().
+
+* allchblk.c (GC_freehblk): Use GC_log_printf instead of GC_printf
+inside "if (GC_print_stats)" branch.
+* alloc.c (GC_collect_or_expand): Likewise.
+* dyn_load.c (GC_register_dynamic_libraries): Likewise.
+* headers.c (GC_scratch_alloc): Likewise.
+* os_dep.c (GC_get_maps, GC_remap, PROTECT,
+GC_write_fault_handler, GC_dirty_init, GC_mprotect_thread): Likewise.
+* alloc.c (min_bytes_allocd): Use GC_log_printf instead of
+GC_printf for DEBUG_THREADS output.
+* darwin_stop_world.c (GC_stack_range_for, GC_suspend_thread_list,
+GC_stop_world, GC_thread_resume, GC_start_world): Likewise.
+* pthread_start.c (GC_inner_start_routine): Likewise.
+* pthread_stop_world.c (GC_suspend_handler, GC_restart_handler,
+GC_push_all_stacks, GC_suspend_all, GC_stop_world,
+GC_start_world): Likewise.
+* pthread_support.c (GC_mark_thread, GC_get_nprocs,
+GC_start_rtn_prepare_thread, pthread_create): Likewise.
+* checksums.c (GC_update_check_page): Use GC_printf() instead of
+GC_err_printf() for error printing.
+* checksums.c (GC_check_blocks, GC_check_dirty): Use GC_log_printf
+instead of GC_printf for logging purposes.
+* dyn_load.c (sys_errlist, sys_nerr, errno): Move declaration of
+external variable outside from GC_register_dynamic_libraries.
+* dyn_load.c (GC_register_dynamic_libraries): Don't use
+sys_errlist value if errno equals to sys_nerr.
+* dyn_load.c (GC_register_dynamic_libraries): Use GC_log_printf
+instead of GC_printf for DL_VERBOSE output.
+* dyn_load.c (GC_dyld_image_add, GC_dyld_image_remove,
+GC_init_dyld): Use GC_log_printf instead of GC_printf for
+DARWIN_DEBUG output.
+* os_dep.c (catch_exception_raise): Use GC_log_printf
+instead of GC_printf for DEBUG_EXCEPTION_HANDLING output.
+* reclaim.c (GC_print_free_list): Move "n" increment out of
+GC_printf() call.
+
+* win32_threads.c (DEBUG_CYGWIN_THREADS, DEBUG_WIN32_PTHREADS,
+DEBUG_WIN32_THREADS): Remove.
+* win32_threads.c (GC_register_my_thread_inner,
+GC_win32_start_inner): Use GC_log_printf instead of GC_printf
+inside "if (GC_print_stats)" branch.
+* win32_threads.c (GC_PTHREAD_PTRVAL): New macro (defined only if
+GC_PTHREADS).
+* win32_threads.c (GC_delete_gc_thread, NUMERIC_THREAD_ID,
+GC_pthread_join, GC_pthread_create): Use GC_PTHREAD_PTRVAL
+macro.
+* win32_threads.c (GC_push_stack_for, GC_mark_thread,
+GC_CreateThread, GC_beginthreadex, GC_pthread_join,
+GC_pthread_create, GC_pthread_start_inner, GC_thread_exit_proc,
+GC_mark_thread_local_free_lists): Use GC_log_printf instead of
+GC_printf for DEBUG_THREADS output.
+* win32_threads.c (GC_win32_start_inner, GC_CreateThread,
+GC_beginthreadex, GC_pthread_join, GC_pthread_create,
+GC_pthread_start_inner, GC_thread_exit_proc): Cast
+GetCurrentThreadId result to long; don't cast value of pthread_t
+type to int; adjust printf format specifiers.
+* doc/README.win32 (DEBUG_WIN32_PTHREADS): Remove obsolete
+information.
+
+* tests/test.c (cons, small_cons, gcj_cons, check_ints,
+check_uncollectable_ints, print_int_list, check_marks_int_list,
+fork_a_thread, finalizer, mktree, chktree, alloc8bytes,
+alloc_small, tree_test, typed_test, check_heap_stats, WinMain,
+test, main): Remove unnecessary casts of GC_printf calls to void.
+
+* allchblk.c (GC_print_hblkfreelist): Adjust (make uniform across
+BDWGC) printed message (adjust letters case, terminating dot and
+new line symbols).
+* alloc.c (GC_check_fl_marks): Likewise.
+* backgraph.c (new_back_edges): Likewise.
+* checksums.c (GC_check_dirty): Likewise.
+* darwin_stop_world.c (GC_push_all_stacks,
+GC_suspend_thread_list): Likewise.
+* dbg_mlc.c (GC_print_type, GC_debug_free, GC_debug_realloc,
+store_old): Likewise.
+* dyn_load.c (GC_register_dynamic_libraries): Likewise.
+* mark.c (GC_initiate_gc, GC_mark_some, GC_mark_from, GC_push_all,
+GC_push_selected, GC_push_next_marked_dirty): Likewise.
+* mark_rts.c (GC_exclude_static_roots_inner): Likewise.
+* os_dep.c (GC_remap, GC_default_push_other_roots,
+GC_push_thread_structures, GC_dirty_init, GC_read_dirty,
+catch_exception_raise_state, catch_exception_raise_state_identity,
+GC_mprotect_thread_notify, GC_mprotect_thread,
+catch_exception_raise): Likewise.
+* pthread_stop_world.c (GC_print_sig_mask, GC_push_all_stacks,
+GC_stop_world, GC_stop_init): Likewise.
+* pthread_support.c (GC_thr_init, GC_register_my_thread_inner,
+GC_start_routine): Likewise.
+* win32_threads.c (GC_register_my_thread_inner,
+GC_push_all_stacks, GC_win32_start_inner, GC_pthread_join,
+GC_pthread_start_inner): Likewise.
+* alloc.c (GC_expand_hp_inner): Realign the code.
+* mark.c (GC_mark_from, GC_mark_local, GC_do_parallel_mark):
+Likewise.
+* misc.c (GC_init): Likewise.
+* os_dep.c (GC_dirty_init, GC_read_dirty): Likewise.
+* include/private/gc_pmark.h (PUSH_CONTENTS_HDR): Likewise.
+* tests/test.c (run_one_test): Likewise.
+* misc.c (GC_err_puts): Document.
+* misc.c (GC_err_write): Remove.
+* os_dep.c (dump_maps): Likewise.
+* include/private/gc_priv.h (GC_err_write): Likewise.
+* os_dep.c (GC_print_address_map): Call GC_err_puts() instead of
+dump_maps() and GC_err_write().
+* os_dep.c (GC_read_dirty): Remove redundant brackets.
+
+* tests/test.c (reverse_test_inner): Test interior pointer
+recognition only if ALL_INTERIOR_POINTERS.
+* tests/test.c (run_one_test): Replace GC_all_interior_pointers
+with GC_get_all_interior_pointers(); simplify the expression.
+* tests/test.c (check_heap_stats): Replace GC_bytes_allocd and
+GC_bytes_allocd_before_gc with GC_get_total_bytes().
+* tests/test.c (main): Replace GC_gc_no with GC_get_gc_no().
+
+* dbg_mlc.c (GC_debug_strdup, GC_debug_free): Output a portability
+warning if the argument is NULL and GC is in leaks detection mode.
+* dbg_mlc.c (GC_debug_strndup, GC_debug_wcsdup): New public
+function definition.
+* malloc.c (GC_strndup, GC_wcsdup, strndup): Likewise.
+* mallocx.c (GC_posix_memalign): Likewise.
+* malloc.c (strdup): Fix string size value; rename "len" to "lb".
+* mallocx.c: Include errno.h unless WinCE (otherwise include
+windows.h for Win32 error constants).
+* win32_threads.c: Define WIN32_LEAN_AND_MEAN and NOSERVICE before
+windows.h inclusion.
+* misc.c (GC_init): Register at-exit callback if GC_find_leak
+(even if GC_FIND_LEAK macro is unset).
+* pthread_stop_world.c (NACL_STORE_REGS,
+__nacl_suspend_thread_if_needed, GC_nacl_initialize_gc_thread):
+Use BCOPY() instead of memcpy().
+* pthread_support.c (GC_init_real_syms): Likewise.
+* doc/README.macros (GC_DEBUG_REPLACEMENT, GC_REQUIRE_WCSDUP):
+Document new macro.
+* doc/README.macros (REDIRECT_MALLOC): Update documentation.
+* include/gc.h (GC_strndup, GC_posix_memalign, GC_debug_strndup):
+New API function prototype.
+* include/gc.h (GC_MALLOC, GC_REALLOC): Redirect to
+GC_debug_malloc/realloc_replacement() if GC_DEBUG_REPLACEMENT.
+* include/gc.h (GC_STRDUP): Remove redundant parentheses.
+* include/leak_detector.h (realloc, strdup): Likewise.
+* include/gc.h (GC_STRNDUP): New API macro.
+* include/gc.h (GC_NEW, GC_NEW_ATOMIC, GC_NEW_STUBBORN,
+GC_NEW_UNCOLLECTABLE): Add missing parentheses.
+* include/gc.h (GC_wcsdup, GC_debug_wcsdup): New API function
+prototype (only if GC_REQUIRE_WCSDUP).
+* include/gc.h (GC_WCSDUP): New API macro (only if
+GC_REQUIRE_WCSDUP).
+* include/leak_detector.h: Include stdlib.h and string.h after gc.h (unless
+GC_DONT_INCLUDE_STDLIB).
+* include/leak_detector.h (malloc, calloc, free, realloc):
+Undefine symbol before its redefinition.
+* include/leak_detector.h (strndup, memalign, posix_memalign):
+Redefine to the corresponding GC function.
+* include/leak_detector.h (wcsdup): Redefine to GC_WCSDUP (only
+if GC_REQUIRE_WCSDUP).
+* include/leak_detector.h (CHECK_LEAKS): Add comment; don't define
+the macro if already defined.
+
+* misc.c (GC_abort): Use _exit() (instead of DebugBreak) on Win32
+when doing code static analysis (to inform the tool that the
+function is a no-return one).
+* os_dep.c (GC_linux_stack_base): Remove a duplicate validation
+of the length of "stat" file; use signed int type for "i",
+"buf_offset" and "len" local variables (since read() may
+return -1).
+
+* blacklst.c (GC_bl_init_no_interiors): New function (the code
+moved from GC_bl_init).
+* blacklst.c (GC_bl_init): Invoke GC_bl_init_no_interiors unless
+GC_all_interior_pointers mode; remove unnecessarily parameter cast
+for GC_scratch_alloc call.
+* include/private/gc_priv.h (GC_bl_init): Move the function
+declaration to misc.c file.
+* misc.c (GC_bl_init_no_interiors): Add a prototype.
+* misc.c (GC_set_all_interior_pointers): Allow values other than 0
+and 1; allow altering GC_set_all_interior_pointers value even
+after GC initialization.
+* obj_map.c (GC_initialize_offsets): Clear GC_valid_offsets and
+GC_modws_valid_offsets if GC_all_interior_pointers is off.
+* misc.c (GC_init): Don't call GC_initialize_offsets() unless
+GC_all_interior_pointers mode.
+
+* alloc.c (GC_finish_collection): Remove redundant brackets;
+adjust code indentation.
+* blacklst.c (GC_add_to_black_list_normal): Simplify expression
+(to improve code readability).
+* blacklst.c (GC_is_black_listed): Join nested "if" (into a single
+conditional expression); initialize "nblocks" just before the loop
+beginning.
+* misc.c (GC_init): Don't compute initial_heap_sz if GC is already
+initialized.
+* include/private/gc_priv.h (GC_initialize_offsets): Move the
+function declaration to misc.c file.
+* obj_map.c (GC_initialize_offsets): Remove offsets_initialized
+static variable since the function is called only once.
+* tests/middle.c (main): Use setter for GC_all_interior_pointers;
+adjust printf format specifier (and cast the value passed to).
+
+* doc/README.macros (SMALL_CONFIG, LARGE_CONFIG): Refine the
+documentation.
+* include/private/gc_hdrs.h (LOG_BOTTOM_SZ): Ignore SMALL_CONFIG
+if LARGE_CONFIG is defined.
+* include/private/gc_priv.h (CPP_LOG_HBLKSIZE): Likewise.
+
+* alloc.c (GC_finish_collection): Replace "#else #ifdef" with
+"#elif".
+* include/private/gc_priv.h (CPP_LOG_HBLKSIZE, LOG_PHT_ENTRIES,
+MAX_ROOT_SETS, MAX_HEAP_SECTS): Likewise.
+* alloc.c (GC_expand_hp_inner): Check for GC_collect_at_heapsize
+overflow even if not LARGE_CONFIG.
+* dbg_mlc.c (GC_check_heap_proc): Check "oh" size even if
+SMALL_CONFIG.
+* finalize.c (GC_print_finalization_stats): Fix "#endif" comment.
+* doc/README.environment (GC_LOG_FILE, GC_PRINT_VERBOSE_STATS,
+GC_FULL_FREQUENCY): Refine the documentation.
+
+* extra/msvc_dbg.c: Test _MSC_VER macro; include "gc.h" (for
+GC_word).
+* extra/msvc_dbg.c (ULONG_PTR): Replace with GC_ULONG_PTR; define
+as word.
+
+* dbg_mlc.c (GC_get_back_ptr_info, GC_print_obj,
+GC_print_smashed_obj, GC_debug_free_inner): Add a code for a
+LINT-like tool to instruct it that the function is invoked only
+with valid parameters (otherwise a SEGV is ok); recognize LINT2
+new macro.
+* misc.c (GC_abort): Instruct a LINT-like tool that the function
+never returns in fact.
+* os_dep.c (GC_linux_stack_base): Check for read buffer overflow;
+close the file immediately after read; use STRTOULL() instead of
+decoding the address number manually.
+* include/private/gc_priv.h (EXPECT): Don't specify outcome for a
+LINT-like tool.
+* include/private/gc_priv.h (GC_all_interior_pointers): Instruct a
+LINT-like tool that the value is restricted to zero and one only
+(required since the variable is global and its value is used as a
+part of array index expression is some places).
+
+* dbg_mlc.c (GC_make_closure): Fix SEGV in case GC_malloc returns
+NULL.
+* dbg_mlc.c (GC_debug_register_finalizer,
+GC_debug_register_finalizer_no_order,
+GC_debug_register_finalizer_unreachable,
+GC_debug_register_finalizer_ignore_self): Handle out of memory
+case properly (similar to GC_register_finalizer_inner).
+* headers.c (GC_install_header): Handle the case when alloc_hdr()
+returns NULL.
+* os_dep.c (GC_get_maps_len): Defend against missing "maps" file.
+* pthread_support.c (GC_mark_thread): Place a dummy return
+statement (which uses "id" argument) before the actual use of "id"
+as an array index (to suppress a warning produced by some static
+code analysis tools).
+* win32_threads.c (GC_mark_thread): Likewise.
+* pthread_support.c (GC_thr_init): Abort (with the appropriate
+message) if out of memory.
+
+* finalize.c (GC_register_finalizer_inner): Fix a typo in a
+comment.
+*include/private/gcconfig.h (STACKBOTTOM): Likewise.
+* gcj_mlc.c (GC_core_gcj_malloc): Replace 0/1 with TRUE/FALSE in
+EXPECT (the 2nd argument).
+* malloc.c (GC_core_malloc_atomic, GC_core_malloc, GC_free):
+Likewise.
+* mark.c (GC_mark_and_push, GC_mark_and_push_stack): Likewise.
+* thread_local_alloc.c (GC_malloc, GC_malloc_atomic): Likewise.
+* include/private/gc_hdrs.h (HC_GET_HDR): Likewise.
+* include/private/gc_priv.h (SMALL_OBJ): Likewise.
+* include/private/specific.h (getspecific): Likewise.
+* pthread_support.c (LOCK_STATS): Add a comment.
+
+* include/gc_pthread_redirects.h (GC_NO_DLOPEN,
+GC_NO_PTHREAD_SIGMASK, GC_PTHREAD_CREATE_CONST,
+GC_PTHREAD_EXIT_ATTRIBUTE, GC_NO_PTHREAD_CANCEL): Move the
+definition to gc_config_macros.
+
+* pthread_support.c (pthread_cancel, GC_pthread_cancel_t,
+GC_pthread_cancel): Test GC_NO_PTHREAD_CANCEL (instead of NACL and
+GC_PTHREAD_EXIT_ATTRIBUTE).
+* include/gc_pthread_redirects.h (GC_pthread_cancel,
+pthread_cancel): Likewise.
+* pthread_support.c (GC_pthread_create, GC_pthread_sigmask,
+GC_pthread_join, GC_pthread_detach, GC_pthread_cancel): Realign
+code.
+* include/gc_pthread_redirects.h (GC_PTHREAD_EXIT_ATTRIBUTE):
+Define as empty for NaCl.
+* include/gc_pthread_redirects.h (GC_NO_PTHREAD_CANCEL): New macro
+defined.
+
+* dyn_load.c (GC_init_dyld): Do not invoke
+_dyld_bind_fully_image_containing_address() if GC_no_dls (as it is
+not required to register the main data segment in that case).
+* include/gc.h (GC_no_dls): Adjust the comment.
+
+* dyn_load.c (GC_MUST_RESTORE_REDEFINED_DLOPEN): Test
+GC_NO_DLOPEN.
+* gc_dlopen.c: Likewise.
+* include/gc_pthread_redirects.h (GC_dlopen, dlopen): Likewise.
+* gc_dlopen.c: Don't include dlfcn.h (as it is included in
+gc_pthread_redirects.h).
+* pthread_support.c (pthread_sigmask, GC_pthread_sigmask_t,
+GC_pthread_sigmask): Test GC_NO_PTHREAD_SIGMASK (instead of
+GC_DARWIN_THREADS, GC_OPENBSD_THREADS and NACL).
+* include/gc_pthread_redirects.h (GC_pthread_sigmask,
+pthread_sigmask): Likewise.
+* win32_threads.c (pthread_sigmask, GC_pthread_sigmask): Test
+GC_NO_PTHREAD_SIGMASK (instead of GC_WIN32_PTHREADS).
+* pthread_support.c (pthread_create, GC_pthread_create_t,
+GC_pthread_create): Rename GC_PTHREAD_CONST to
+GC_PTHREAD_CREATE_CONST.
+* win32_threads.c (GC_pthread_create): Likewise.
+* include/gc_pthread_redirects.h: Likewise.
+* include/gc_pthread_redirects.h (GC_NO_DLOPEN,
+GC_NO_PTHREAD_SIGMASK): New macro defined.
+* include/gc_pthread_redirects.h (GC_PTHREAD_CREATE_CONST): Set to
+empty for NaCl.
+* include/gc_pthread_redirects.h (GC_PTHREAD_EXIT_ATTRIBUTE): Do
+not define for Android (as CANCEL_SAFE is not defined).
+
+* include/gc.h (GC_ADD_CALLER, GC_RETURN_ADDR,
+GC_HAVE_BUILTIN_BACKTRACE, GC_CAN_SAVE_CALL_STACKS): Move
+definition to gc_config_macros.h file.
+* include/gc_config_macros.h: Check the file is included from gc.h
+file.
+* include/gc_version.h: Likewise.
+
+* gc_dlopen.c: Empty unit for NaCl.
+* os_dep.c: Include fcntl.h for NaCl.
+* os_dep.c (GC_get_main_stack_base): Ignore
+USE_GET_STACKBASE_FOR_MAIN macro for NaCl.
+* os_dep.c (GC_get_stack_base): Return GC_UNIMPLEMENTED for NaCl.
+* os_dep.c (GC_remap): Use mmap (instead of mprotect) for NaCl.
+* pthread_start.c (GC_inner_start_routine): Don't invoke
+pthread_cleanup_push/pop for NaCl.
+* pthread_stop_world.c (GC_nacl_num_gc_threads,
+GC_nacl_thread_idx, GC_nacl_park_threads_now,
+GC_nacl_thread_parker, GC_nacl_gc_thread_self,
+GC_nacl_thread_parked, GC_nacl_thread_used,
+GC_nacl_thread_parking_inited, GC_nacl_thread_alloc_lock): New
+variable (fo NaCl only).
+* pthread_stop_world.c (GC_remove_allowed_signals,
+suspend_handler_mask, GC_stop_count, GC_world_is_stopped,
+GC_retry_signals, SIG_THR_RESTART, GC_suspend_ack_sem,
+GC_restart_ack_sem, GC_suspend_handler_inner, GC_suspend_handler,
+GC_restart_handler): Don't define for NaCl.
+* pthread_support.c (GC_get_nprocs): Likewise.
+* include/private/gc_priv.h (SIG_SUSPEND): Likewise.
+* include/private/gcconfig.h (LINUX): Likewise.
+* pthread_stop_world.c (GC_push_all_stacks): Push register storage
+for NaCl.
+* pthread_stop_world.c (GC_suspend_all, GC_stop_world,
+GC_start_world): Implement for NaCl.
+* pthread_stop_world.c (GC_stop_world): Don't define unused "i"
+local variable for OpenBSD (and NaCl).
+* pthread_stop_world.c (NACL_STORE_REGS): New macro definition for
+NaCl.
+* pthread_stop_world.c (nacl_pre_syscall_hook,
+__nacl_suspend_thread_if_needed, nacl_post_syscall_hook,
+GC_nacl_initialize_gc_thread, GC_nacl_shutdown_gc_thread): New
+function (for NaCl only).
+* pthread_stop_world.c (GC_stop_init): Empty for NaCl.
+* pthread_support.c (pthread_cancel, pthread_sigmask): Don't
+redirect for NaCl.
+* include/gc_pthread_redirects.h (pthread_cancel,
+pthread_sigmask): Likewise.
+* pthread_support.c (GC_nacl_initialize_gc_thread,
+GC_nacl_shutdown_gc_thread): New internal prototype (NaCl only).
+* pthread_support.c (GC_new_thread, GC_delete_thread): Initialize
+and shutdown thread for NaCl.
+* pthread_support.c (GC_thr_init): Call sysconf for NaCl.
+* pthread_support.c (GC_pthread_exit): Call GC_thread_exit_proc
+for NaCl.
+* include/gc.h: Don't include features.h for NaCl.
+* include/gc_pthread_redirects.h (GC_PTHREAD_CONST): New macro.
+* include/gc_pthread_redirects.h (GC_pthread_create): Use
+GC_PTHREAD_CONST instead of const.
+* win32_threads.c (GC_pthread_create): Likewise.
+* pthread_support.c (GC_pthread_create_t, GC_pthread_create,
+pthread_create): Likewise.
+* include/private/gcconfig.h (NACL): Recognize NaCl.
+* include/private/gcconfig.h (GC_LINUX_THREADS): Valid for NaCl.
+* include/private/pthread_stop_world.h (thread_stop_info): Add
+reg_storage member; define NACL_GC_REG_STORAGE_SIZE macro (for
+NaCl only).
+* include/private/pthread_support.h (GC_nacl_gc_thread_self):
+Declare internal variable (for NaCl only).
+
+* mach_dep.c (GC_with_callee_saves_pushed): Fix FE_ALL_EXCEPT
+macro.
+
+* mark.c (GC_mark_some): Prefix and suffix "asm" and "volatile"
+keywords with double underscore.
+* os_dep.c (catch_exception_raise, catch_exception_raise_state,
+catch_exception_raise_state_identity): Add GC_API_OSCALL to
+function definition.
+* os_dep.c (catch_exception_raise_state,
+catch_exception_raise_state_identity): Move definition to be
+before GC_ports.
+* os_dep.c (catch_exception_raise): Declare to have the symbol
+defined before GC_ports.
+* os_dep.c (GC_ports): Store references to catch_exception_raise,
+catch_exception_raise_state, catch_exception_raise_state_identity
+(to prevent stripping these symbols as dead).
+* os_dep.c (catch_exception_raise, catch_exception_raise_state,
+catch_exception_raise_state_identity): Mark these symbols as
+"referenced dynamically" via an assembler directive (unless
+NO_DESC_CATCH_EXCEPTION_RAISE).
+* include/private/gc_priv.h (GC_API_OSCALL): New macro (defined
+similar to GC_API but as if GC_DLL is always defined).
+
+* os_dep.c: Don't include signal.h for GC_write_fault_handler on
+Win32.
+* os_dep.c (SIG_OK): Don't return true unless SIGSEGV or SIGBUS on
+FreeBSD.
+* os_dep.c (CODE_OK): Use SEGV_ACCERR on FreeBSD (define
+SEGV_ACCERR for older FreeBSD releases).
+
+* dyn_load.c (GC_register_map_entries,
+GC_register_dynamic_libraries_dl_iterate_phdr): Calculate
+DATASTART only once if DATASTART_IS_FUNC.
+* dyn_load.c (GC_register_dynamic_libraries_dl_iterate_phdr):
+Calculate DATAEND only once if DATAEND_IS_FUNC.
+* dyn_load.c: Add comment to some endif; realign some code.
+* dyn_load.c (GC_init_dyld): Don't use
+_dyld_bind_fully_image_containing_address if
+NO_DYLD_BIND_FULLY_IMAGE defined; add FIXME.
+* include/private/gcconfig.h (GC_data_start, GC_find_limit):
+Declare if used by DATASTART/DATAEND, respectively.
+* include/private/gcconfig.h (DATASTART_IS_FUNC, DATAEND_IS_FUNC):
+Define if DATASTART/DATAEND is a function, respectively.
+* include/private/gcconfig.h (GETPAGESIZE, NO_PTHREAD_TRYLOCK,
+NO_DYLD_BIND_FULLY_IMAGE): Define for Darwin/arm as well; include
+unistd.h.
+
+* os_dep.c (GC_setpagesize, GC_task_self, PROTECT, UNPROTECT):
+Reorder to remove redundant ifdef for Win32.
+* os_dep.c: Add comment to some endif.
+* os_dep.c: Include pthread.h (for Linux even if single-threaded)
+if USE_GET_STACKBASE_FOR_MAIN; also include it for Darwin.
+* os_dep.c (STACKBOTTOM): Redefine for Darwin (unless prohibited
+for some reason).
+* os_dep.c (GC_get_main_stack_base): Allow
+USE_GET_STACKBASE_FOR_MAIN for Linux even if single-threaded; add
+assertion for the returned result.
+* os_dep.c (GC_get_stack_base): Define for Darwin if
+multi-threaded.
+* os_dep.c (SIG_OK, CODE_OK): Add comment (for FreeBSD).
+* os_dep.c (ID_STOP, ID_RESUME): Define only if threads.
+* os_dep.c (catch_exception_raise): Remove redundant parentheses;
+refine the documentation.
+
+* NT_MAKEFILE: Define _CRT_SECURE_NO_DEPRECATE for C++ files as
+well.
+* NT_STATIC_THREADS_MAKEFILE: Likewise.
+* doc/README.macros (USE_GET_STACKBASE_FOR_MAIN): Refine.
+* include/gc.h (GC_INIT): Document.
+* include/private/gc_priv.h (GC_MACH_HEADER, GC_MACH_SECTION,
+GC_GETSECTBYNAME): Define depending only on the word size (i.e.,
+define these macros also for ARM).
+* tests/test.c (check_heap_stats): Print main thread stack bottom
+as well (only if verbose mode is on).
+
+* mach_dep.c (GC_with_callee_saves_pushed): Fix and improve code
+introduced by the previous patch (if GETCONTEXT_FPU_EXCMASK_BUG
+and X86_64).
+
+* darwin_stop_world.c (GC_FindTopOfStack): Prefix and suffix
+"volatile" keyword with double underscore.
+* mach_dep.c (GETCONTEXT_FPU_EXCMASK_BUG): Recognize new macro and
+include fenv.h if defined (unless NO_GETCONTEXT or HAVE_PUSH_REGS).
+* mach_dep.c (GC_with_callee_saves_pushed): Restore FPU exception
+mask corrupted by getcontext if GETCONTEXT_FPU_EXCMASK_BUG.
+* include/private/gcconfig.h (GETCONTEXT_FPU_EXCMASK_BUG): Define
+for Linux/amd64 (since its GLibc getcontext currently has the bug).
+
+* allchblk.c (GC_use_entire_heap): Change type to int (as declared
+in gc.h); set the default value depending on new GC_USE_ENTIRE_HEAP
+macro.
+* misc.c (GC_init): Test GC_USE_ENTIRE_HEAP environment variable to
+alter the default value of GC_use_entire_heap.
+* doc/README.environment (GC_USE_ENTIRE_HEAP): Document.
+* doc/README.macros (GC_USE_ENTIRE_HEAP): Likewise.
+
+* include/private/gcconfig.h (PARALLEL_MARK): Do not make it cause
+MPROTECT_VDB undefining.
+
+* include/private/gcconfig.h (DYNAMIC_LOADING): Fix filename in
+the comment.
+
+* include/private/gc_priv.h (_GC_arrays): Move the conditional
+macro definitions (shortcuts for GC_arrays members) into the
+structure body.
+
+* darwin_stop_world.c (GC_mach_handler_thread,
+GC_use_mach_handler_thread,
+GC_darwin_register_mach_handler_thread): Define only if
+MPROTECT_VDB.
+* darwin_stop_world.c (GC_suspend_thread_list): Use
+GC_mach_handler_thread and GC_use_mach_handler_thread only if
+MPROTECT_VDB.
+* darwin_stop_world.c (GC_stop_world): Reset GC_mach_threads_count
+only if defined (i.e. unless GC_NO_THREADS_DISCOVERY).
+* misc.c (GC_init): Fix comment for GWW_VDB.
+* os_dep.c (DARWIN_EXC_STATE, DARWIN_EXC_STATE_COUNT,
+DARWIN_EXC_STATE_T, DARWIN_EXC_STATE_DAR): New macros.
+* os_dep.c (catch_exception_raise): Use DARWIN_EXC_STATE,
+DARWIN_EXC_STATE_COUNT, DARWIN_EXC_STATE_T, DARWIN_EXC_STATE_DAR.
+* pthread_support.c (GC_thr_init): Define "dummy" local variable
+only unless GC_DARWIN_THREADS.
+* include/private/gcconfig.h (MPROTECT_VDB): Define for Darwin
+even in the single-threaded mode; define for iPhone/iPad.
+* include/private/gcconfig.h (IA64): Remove unnecessary "ifdef"
+around "undef".
+* include/private/gcconfig.h (HEURISTIC1): Remove unused for
+Cygwin.
+* include/private/gcconfig.h (STACKBOTTOM): Use fixed address for
+Darwin/arm (instead of HEURISTIC1).
+
+* misc.c (GC_write): Replace multiple "ifdef/endif" with "elif"
+(for ECOS and NOSYS).
+* os_dep.c (GC_get_main_stack_base): Likewise.
+* os_dep.c (GC_get_main_stack_base): Check
+USE_GET_STACKBASE_FOR_MAIN macro before checking STACKBOTTOM one;
+remove "dummy" variable (use result one instead).
+* doc/README.macros (SN_TARGET_PS3): Document.
+* extra/threadlibs.c (main): Don't output "-lpthread" (and "-ldl")
+for Android.
+* include/private/pthread_support.h: Fix comment for "endif".
+
+* misc.c (GC_allocate_ml): Define global variable if SN_TARGET_PS3.
+* misc.c (GC_init): Initialize GC_allocate_ml if SN_TARGET_PS3.
+* os_dep.c (SIGSEGV): Define to dummy zero if SN_TARGET_PS3.
+* os_dep.c (GC_unix_mmap_get_mem): Don't define if SN_TARGET_PS3.
+* os_dep.c (GC_default_push_other_roots,
+GC_push_thread_structures): Define for SN_TARGET_PS3.
+* include/private/gc_locks.h (GC_allocate_ml, LOCK, UNLOCK): Define
+for SN_TARGET_PS3.
+* include/private/gcconfig.h (SN_TARGET_PS3): Recognize new macro
+(Sony PS/3 target).
+* include/private/gcconfig.h (THREADS): Define unconditionally if
+SN_TARGET_PS3.
+* include/private/gcconfig.h (GET_MEM): Define for SN_TARGET_PS3.
+
+* alloc.c (GC_collect_or_expand): Replace NIL with NULL in message.
+* dbg_mlc.c (GC_debug_malloc, GC_debug_malloc_ignore_off_page,
+GC_debug_malloc_atomic_ignore_off_page,
+GC_debug_generic_malloc_inner,
+GC_generic_malloc_inner_ignore_off_page, GC_debug_malloc_stubborn,
+GC_debug_malloc_atomic, GC_debug_malloc_uncollectable,
+GC_debug_malloc_atomic_uncollectable): Likewise.
+* gcj_mlc.c (GC_debug_gcj_malloc): Likewise.
+* dbg_mlc.c (GC_check_annotated_obj): Replace NIL with NULL in a
+comment.
+* dyn_load.c (GC_FirstDLOpenedLinkMap): Likewise.
+* mark_rts.c (GC_roots_present): Likewise.
+* doc/README: Likewise.
+* include/private/gc_hdrs.h (IS_FORWARDING_ADDR_OR_NIL): Likewise.
+* include/private/gc_priv.h (_GC_arrays): Likewise.
+
+* configure.ac: Use AC_CHECK_LIB() to check for pthread instead of
+just blindly linking to -lpthread, as Android includes pthread
+support within libc and does not provide a separate libpthread.
+* dyn_load.c (GC_register_dynamic_libraries): Skip current link map
+entry if l_addr is NULL (Android/bionic only).
+* pthread_stop_world.c (android_thread_kill): New internal function
+(Android only).
+* pthread_stop_world.c (GC_suspend_all, GC_start_world): Call
+android_thread_kill (based on tkill) instead of pthread_kill on
+Android (since pthread_kill cannot be used safely on the platform).
+* pthread_support.c (GC_new_thread): Store thread Id (obtained from
+gettid) for use by android_thread_kill (Android only).
+* include/private/pthread_support.h (GC_Thread_Rep): Add kernel_id
+structure member (Android only).
+* include/private/gcconfig.h: Recognize __x86_64 macro as a synonym
+of __x86_64__ (Darwin); define __environ macro (Android on M68K).
+
+* allchblk.c (GC_freehblk): Print extended error message (done via
+GC_printf() before aborting with a short message) only if
+GC_print_stats.
+* dyn_load.c (GC_register_dynamic_libraries): Likewise.
+* os_dep.c (GC_get_maps, GC_register_data_segments, GC_remap,
+PROTECT, GC_write_fault_handler, GC_mprotect_thread): Likewise.
+* pthread_stop_world.c (GC_start_world): Likewise.
+* win32_threads.c (GC_register_my_thread_inner): Likewise.
+* os_dep.c (GC_get_main_stack_base, GC_register_data_segments,
+GC_dirty_init): Remove redundant print of an error message before
+aborting with the same message.
+* os_dep.c (GC_register_data_segments): Remove format specifier
+from the string passed to GC_err_puts(); use ABORT instead of EXIT
+(if invalid executable type).
+* os_dep.c (GC_remap): Adjust printf format specifier (for long
+type).
+* os_dep.c (GC_dirty_init): Print a message about SIG_IGN detected
+(for SIGSEGV/BUS) only if GC_print_stats.
+* os_dep.c (catch_exception_raise): Join 2 adjacent GC_err_printf
+calls.
+
+* tests/test.c (main): Print the relevant message if GWW_VDB.
+* include/private/gcconfig.h: Don't define MPROTECT_VDB for Win32
+on x64 if compiled by GCC.
+
+* tests/staticrootstest.c: Include string.h for memset() prototype.
+* tests/thread_leak_test.c (main): Fix printf() format specifiers.
+
+* CMakeLists.txt: Check enable_parallel_mark on Darwin.
+* configure.ac: Likewise.
+* darwin_stop_world.c (DARWIN_SUSPEND_GC_THREADS,
+DARWIN_QUERY_TASK_THREADS): Rename to GC_NO_THREADS_DISCOVERY and
+GC_DISCOVER_TASK_THREADS, respectively.
+* os_dep.c (DARWIN_SUSPEND_GC_THREADS): Likewise.
+* pthread_support.c (DARWIN_SUSPEND_GC_THREADS): Likewise.
+* darwin_stop_world.c (DARWIN_QUERY_TASK_THREADS): Don't define
+(and remove FIXME).
+* darwin_stop_world.c (GC_use_threads_discovery): Add GC_API;
+comment; remove FIXME.
+* win32_threads.c (GC_NO_DLLMAIN): Rename to
+GC_NO_THREADS_DISCOVERY.
+* tests/test.c (GC_NO_DLLMAIN): Likewise.
+* doc/README.macros (GC_NO_DLLMAIN): Likewise.
+* doc/README.win32 (GC_NO_DLLMAIN): Likewise.
+* doc/README.macros (GC_NO_THREADS_DISCOVERY): Update the comment.
+* win32_threads.c (GC_win32_dll_threads): Define as macro to true
+if GC_DISCOVER_TASK_THREADS (and not GC_NO_THREADS_DISCOVERY);
+update the comment.
+* win32_threads.c (GC_use_DllMain): Rename to
+GC_use_threads_discovery; do not set GC_win32_dll_threads if
+GC_DISCOVER_TASK_THREADS.
+* win32_threads.c (GC_started_thread_while_stopped,
+GC_lookup_thread_inner, UNPROTECT_THREAD, GC_lookup_pthread,
+GC_thr_init, GC_pthread_create, DllMain): Rewrite some expressions
+which use GC_win32_dll_threads to minimize the possibility of
+an "unreachable code" compiler warning when GC_win32_dll_threads
+is defined as a macro.
+* win32_threads.c (GC_unregister_my_thread): Don't call
+GC_delete_thread() if GC_win32_dll_threads and THREAD_LOCAL_ALLOC
+(since can't happen); use "t" local variable only if not
+GC_win32_dll_threads.
+* doc/README.macros (GC_DISCOVER_TASK_THREADS): Document.
+* include/gc.h (GC_use_DllMain): Rename to
+GC_use_threads_discovery but keep old name as a macro definition.
+* include/gc.h (GC_use_threads_discovery): Declare also for
+Darwin; update the comment.
+* tests/test.c (main): Call GC_use_threads_discovery for Darwin
+(to test the mode if possible).
+
+* darwin_stop_world.c (DARWIN_SUSPEND_GC_THREADS,
+DARWIN_QUERY_TASK_THREADS): New macro recognized.
+* darwin_stop_world.c (GC_query_task_threads): add STATIC;
+initialize to false; define as macro if DARWIN_SUSPEND_GC_THREADS
+or DARWIN_QUERY_TASK_THREADS; remove FIXME.
+* darwin_stop_world.c (GC_use_threads_discovery): New function
+(for setting GC_query_task_threads value).
+* darwin_stop_world.c (GC_mach_handler_thread,
+GC_use_mach_handler_thread, GC_mach_thread, GC_MAX_MACH_THREADS,
+GC_mach_threads, GC_mach_threads_count, GC_suspend_thread_list,
+GC_darwin_register_mach_handler_thread): Define only if not
+DARWIN_SUSPEND_GC_THREADS.
+* darwin_stop_world.c (GC_stop_world, GC_start_world): Exclude
+the code for GC_query_task_threads case from compilation unless
+DARWIN_SUSPEND_GC_THREADS.
+* os_dep.c (GC_darwin_register_mach_handler_thread): Declared only
+if Darwin threads and not DARWIN_SUSPEND_GC_THREADS.
+* os_dep.c (GC_mprotect_thread): Call
+GC_darwin_register_mach_handler_thread only if THREADS and not
+DARWIN_SUSPEND_GC_THREADS.
+* pthread_support.c (marker_mach_threads): Don't define if
+DARWIN_SUSPEND_GC_THREADS.
+* pthread_support.c (GC_mark_thread): Don't fill in
+marker_mach_threads if DARWIN_SUSPEND_GC_THREADS.
+* include/private/gc_locks.h (GC_need_to_lock): Always declare for
+THREADS case.
+
+* darwin_stop_world.c (GC_query_task_threads): Don't define to
+false for DARWIN_DONT_PARSE_STACK case; unconditionally initialize
+the variable to false (for now).
+* darwin_stop_world.c (GC_push_all_stacks): Call task_threads()
+only if not DARWIN_DONT_PARSE_STACK.
+* darwin_stop_world.c (GC_stop_world, GC_start_world): Use the
+approach based on task_threads() only if GC_query_task_threads
+else use GC_threads table.
+
+* darwin_stop_world.c (GC_mach_threads): Remove static qualifier.
+* darwin_stop_world.c (GC_stop_init): Remove (as we do not need to
+really clear GC_mach_threads[]).
+* darwin_stop_world.c (GC_stop_world): Reset GC_mach_threads_count
+(instead of calling GC_stop_init).
+* include/private/pthread_support.h (GC_stop_init): Remove proto.
+* pthread_support.c (GC_stop_init): Add proto (unless Darwin).
+* pthread_support.c (GC_thr_init): Don't call GC_stop_init() if
+GC_DARWIN_THREADS.
+
+* darwin_stop_world.c (GC_stack_range_for): New static function
+(move the code from GC_push_all_stacks).
+* darwin_stop_world.c (GC_push_all_stacks): Call
+GC_stack_range_for(); rename kern_return local variable to
+kern_result.
+* darwin_stop_world.c (GC_is_mach_marker): Change argument type
+from mach_port_t to thread_act_t.
+* pthread_support.c (GC_is_mach_marker): Likewise.
+
+* darwin_stop_world.c (GC_push_all_stacks): Fix "my_task" local
+variable initialization (always call current_task()).
+* pthread_support.c (GC_thr_init, GC_register_my_thread_inner):
+Don't set thread's stop_info.stack_ptr value for Darwin.
+* include/private/darwin_stop_world.h (thread_stop_info): Update
+the comment for stack_ptr.
+
+* darwin_stop_world.c (GC_push_all_stacks): Rename "r", "me" local
+variables to "kern_return" and "my_thread" ones, respectively;
+call mach_port_deallocate() unconditionally.
+* darwin_stop_world.c (GC_stop_world): Don't call mach_thread_self
+if DEBUG_THREADS.
+
+* darwin_stop_world.c (GC_mach_thread): Move from
+darwin_stop_world.h.
+* include/private/darwin_stop_world.h (GC_mach_thread): Remove.
+* win32_threads.c (GC_start_world): Define "thread_id" local
+variable only if GC_ASSERTIONS; decide whether to resume a thread
+based on its "suspended" field value; assert that suspended thread
+stack_base is non-zero and the thread is not our one.
+
+* darwin_stop_world.c (GC_thread_resume): New inline function
+(move code from GC_thread_resume).
+* darwin_stop_world.c (GC_start_world): Check result of
+task_threads(); call GC_thread_resume().
+* os_dep.c (GC_malloc_heap_l, GC_is_malloc_heap_base): Define
+only if not CYGWIN32.
+* os_dep.c (GC_is_heap_base): Call GC_is_malloc_heap_base() only
+if not CYGWIN32.
+
+* darwin_stop_world.c (FindTopOfStack): Change return type to
+ptr_t (from long); make GC_INNER; add GC_ prefix.
+* darwin_stop_world.c (GC_push_all_stacks): Add thread_blocked
+local variable (initialized from the corresponding GC_thread
+field unless GC_query_task_threads); add assertion that our
+thread is not blocked; prefix FindTopOfStack with GC_ and remove
+no longer needed cast to ptr_t of the result; handle thread
+blocked case (and remove FIXME); use GC_push_all_stack_sections
+unless GC_query_task_threads (and remove FIXME).
+* pthread_support.c (GC_FindTopOfStack): Declare (if needed).
+* pthread_support.c (GC_do_blocking_inner): Call
+GC_save_regs_in_stack (if needed) before acquiring the lock.
+* win32_threads.c (GC_do_blocking_inner): Likewise.
+* pthread_support.c (GC_do_blocking_inner): Set/clear topOfStack
+field of GC_thread (Darwin only).
+* include/private/pthread_support.h (GC_thread): Add topOfStack
+field for Darwin (unless DARWIN_DONT_PARSE_STACK).
+
+* finalize.c (GC_check_finalizer_nested): Change return type to
+char pointer (instead of int pointer); use explicit cast for
+GC_finalizer_nested assignment.
+* pthread_support.c (GC_check_finalizer_nested): Likewise.
+* win32_threads.c (GC_check_finalizer_nested): Likewise.
+* finalize.c (GC_finalizer_nested): Change type to unsigned char.
+* finalize.c (GC_notify_or_invoke_finalizers): Change type of
+"pnested" local variable to char pointer.
+* pthread_support.c (GC_do_blocking_inner,
+GC_call_with_gc_active): Use explicit cast for "thread_blocked"
+field assignment.
+* win32_threads.c (GC_lookup_pthread): Use explicit cast for
+"suspended" field assignment.
+* win32_threads.c (GC_Thread_Rep): Use short type for
+finalizer_skipped; use char type for finalizer_nested and flags
+fields and reorder some fields (to minimize GC_Thread_Rep
+structure size).
+* include/private/pthread_support.h (GC_Thread_Rep): Likewise.
+* win32_threads.c (GC_Thread_Rep): Use char type for suspended
+field (instead of GC_bool).
+* include/private/pthread_support.h (GC_Thread_Rep): Use char type
+for thread_blocked field (instead of short).
+
+* darwin_stop_world.c (GC_query_task_threads): New variable (or
+macro).
+* darwin_stop_world.c (GC_push_all_stacks): Use
+GC_query_task_threads (to choose between algorithms based on
+kernel task_threads and based on GC_threads table); update FIXME;
+remove commented out GC_push_one statements.
+* pthread_support.c (GC_thr_init, GC_do_blocking_inner,
+GC_call_with_gc_active, GC_register_my_thread_inner): Initialize
+stack_ptr field for all platforms.
+* pthread_support.c (GC_call_with_gc_active): Initialize
+saved_stack_ptr field for all platforms.
+* include/private/darwin_stop_world.h (thread_stop_info): Add
+stack_ptr field; change type of already_suspended from int to
+GC_bool.
+
+* darwin_stop_world.c (GC_MAX_MACH_THREADS): New macro.
+* darwin_stop_world.c (GC_mach_threads, GC_stop_init): Use
+GC_MAX_MACH_THREADS instead of THREAD_TABLE_SZ.
+* darwin_stop_world.c (GC_mach_threads): Add FIXME.
+* darwin_stop_world.c (GC_stop_init, GC_suspend_thread_list,
+GC_stop_world): Use FALSE and TRUE for already_suspended field and
+"changed", "found" variables.
+* darwin_stop_world.c (GC_is_mach_marker): New prototype (only if
+PARALLEL_MARK).
+* darwin_stop_world.c (GC_suspend_thread_list): Change return type
+to GC_bool; change type of "changed", "found" to GC_bool; make
+"my_thread" as an argument (instead of acquiring/deallocating it
+locally); do not add my_thread, GC_mach_handler_thread and marker
+threads to GC_mach_threads table; check for overflow of
+GC_mach_threads table; increase GC_mach_threads_count if "found"
+is true and info.suspend_count is non-zero.
+* darwin_stop_world.c (GC_suspend_thread_list, GC_start_world):
+Adjust "thread" format specifiers for GC_printf(); search thread
+in "old_list" starting from the previous found one.
+* darwin_stop_world.c (GC_stop_world): Rename "changes" to
+"changed" local variable; remove "result" variable; adjust
+GC_printf debugging message.
+* darwin_stop_world.c (GC_start_world): Do not check for
+my_thread and GC_use_mach_handler_thread (since they are not added
+to GC_mach_threads table); call thread_info() only if
+DEBUG_THREADS or GC_ASSERTIONS.
+* pthread_support.c (marker_mach_threads): New static variable (if
+Darwin).
+* pthread_support.c (GC_is_mach_marker): New function (if Darwin).
+* pthread_support.c (GC_mark_thread): Fill in marker_mach_threads
+table (if Darwin).
+
+* alloc.c (GC_parallel): Define only if THREADS.
+* misc.c (GC_get_parallel): Likewise.
+* include/gc.h (GC_parallel, GC_get_parallel,
+GC_get_suspend_signal, GC_allow_register_threads,
+GC_register_my_thread, GC_unregister_my_thread): Define only if
+GC_THREADS.
+* include/gc.h (GC_get_heap_size): Fix a typo in a comment.
+
+* configure.ac: Use `AC_C_INLINE'.
+* include/private/gc_priv.h (GC_INLINE): Use "inline" keyword
+(determined by configure AC_C_INLINE) if HAVE_CONFIG_H is defined.
+
+* dyn_load.c (DL_ITERATE_PHDR_STRONG): New macro (define for
+FreeBSD).
+* dyn_load.c (GC_register_main_static_data): Move the definition
+above GC_register_dynamic_libraries_dl_iterate_phdr one (FreeBSD
+case); unconditionally return FALSE if DL_ITERATE_PHDR_STRONG.
+* dyn_load.c (GC_register_dynamic_libraries_dl_iterate_phdr): Test
+GC_register_main_static_data() result (instead of direct testing
+of dl_iterate_phdr (to prevent a compiler warning).
+* os_dep.c (CODE_OK): Test si_code also for the value of 2
+(FreeBSD case; required for FreeBSD v7+).
+* os_dep.c (CODE_OK): Properly use parentheses (HPUX case).
+* include/private/gcconfig.h (DATASTART): Cast etext argument in
+GC_FreeBSDGetDataStart() call; remove unnecessary "&" (FreeBSD
+case).
+
+* include/private/specific.h (quick_thread_id): Define thru
+GC_approx_sp(); define as a macro.
+* include/private/specific.h (getspecific): Use GC_INLINE instead
+of __inline__ (to work around Sun CC which does not recognize
+inline keyword surrounded with underscores).
+
+* darwin_stop_world.c (FindTopOfStack): Simplify condition
+expressions.
+* darwin_stop_world.c (GC_push_all_stacks): Merge two variants
+of this function (DARWIN_DONT_PARSE_STACK).
+* darwin_stop_world.c (GC_push_all_stacks): Add a check for our
+thread is found (same as in pthread_stop_world.c).
+* darwin_stop_world.c (GC_push_all_stacks): Print the number of
+scanned threads if verbose (same as in pthread_stop_world.c).
+
+* darwin_stop_world.c (GC_push_all_stacks): Reset
+thread_state_count value before every thread_get_state call;
+refine the comment for thread_state_count.
+* darwin_stop_world.c (GC_push_all_stacks): Ignore rsp, rip/eip,
+rflags, cs, fs, gs, ss, ds, es, __pc registers; uncomment ebp
+register pushing.
+* darwin_stop_world.c (GC_push_all_stacks): Set outCount to
+GC_MACH_THREAD_STATE_COUNT (instead of THREAD_STATE_MAX).
+* darwin_stop_world.c (GC_push_all_stacks): Remove FIXME and WARN
+for i386.
+
+* doc/README.macros (DARWIN_DONT_PARSE_STACK): Fix a typo.
+* darwin_stop_world.c (GC_use_mach_handler_thread): Change type
+to GC_bool.
+* darwin_stop_world.c (GC_suspend_thread_list, GC_start_world):
+Simplify the expressions involving GC_use_mach_handler_thread.
+* darwin_stop_world.c (GC_darwin_register_mach_handler_thread):
+Initialize GC_use_mach_handler_thread to TRUE (instead of 1).
+
+* include/gc_pthread_redirects.h (GC_pthread_sigmask, GC_dlopen,
+pthread_sigmask, dlopen): Don't define for Win32 pthreads (and
+don't include signal.h and dlfcn.h).
+
+* dyn_load.c (GC_register_dynlib_callback): Add FIXME.
+
+* include/private/gcconfig.h: Add support for FreeBSD on ppc64.
+
+* os_dep.c (PROTECT, UNPROTECT): Correct VM_PROT_EXEC to
+VM_PROT_EXECUTE.
+
+* os_dep.c (os2_alloc): Don't set PAG_EXECUTE unless
+pages_executable is on.
+* os_dep.c (os2_alloc): Add FIXME (for recursion).
+* os_dep.c (UNPROTECT): Abort with a more informative message if
+pages_executable is on ("mprotect" case).
+* os_dep.c (PROTECT, UNPROTECT): Set VM_PROT_EXEC if
+pages_executable is on (Darwin case).
+* pthread_support.c (GC_init_real_syms): Abort with an informative
+message if libgc is linked after libpthread.
+
+* dyn_load.c (GC_register_dynlib_callback): Adjust "start" pointer
+for 64-bit targets.
+* pthread_support.c (start_mark_threads): Expand PTHREAD_CREATE
+macro.
+* pthread_support.c (start_mark_threads): Call INIT_REAL_SYMS()
+since REAL(pthread_create) is used.
+* pthread_support.c (PTHREAD_CREATE): Remove unused.
+
+* extra/threadlibs.c (main): Remove --wrap for "read" (since not
+wrapped anymore).
+* doc/README.linux (GC_USE_LD_WRAP): Likewise.
+* os_dep.c (__wrap_read): Likewise.
+
+* include/gc_pthread_redirects.h: Test GC_PTHREADS and GC_H at the
+beginning of the file.
+* include/gc_pthread_redirects.h (GC_PTHREAD_EXIT_ATTRIBUTE): New
+macro (defined only for Linux and Solaris).
+* include/gc_pthread_redirects.h (GC_pthread_cancel,
+GC_pthread_exit): Declare new API function (only if
+GC_PTHREAD_EXIT_ATTRIBUTE).
+* include/gc_pthread_redirects.h (pthread_cancel, pthread_exit):
+Redirect (if GC_PTHREAD_EXIT_ATTRIBUTE).
+* include/private/pthread_support.h (DISABLED_GC): New macro.
+* pthread_support.c (pthread_cancel, pthread_exit): Restore
+original definition or declare "real" function (if needed and
+GC_PTHREAD_EXIT_ATTRIBUTE).
+* pthread_support.c (GC_pthread_cancel_t, GC_pthread_exit_t):
+Declare new types if needed.
+* pthread_support.c (GC_pthread_cancel, GC_pthread_exit): New
+function definition (only if GC_PTHREAD_EXIT_ATTRIBUTE).
+* pthread_support.c (GC_init_real_syms): Initialize pointers to
+the "real" pthread_cancel and pthread_exit (only if
+GC_PTHREAD_EXIT_ATTRIBUTE).
+* pthread_support.c (GC_unregister_my_thread): Enable collections
+if DISABLED_GC was set (only if GC_PTHREAD_EXIT_ATTRIBUTE).
+* pthread_support.c (pthread_cancel, pthread_exit): New wrapped
+function definition (only if GC_PTHREAD_EXIT_ATTRIBUTE defined).
+* pthread_support.c (GC_start_routine): Refine the comment.
+* extra/threadlibs.c (main): Adjust --wrap (add "read",
+"pthread_exit", "pthread_cancel" but remove "sleep").
+* doc/README.linux (GC_USE_LD_WRAP): Likewise.
+
+* include/gc.h (GC_MALLOC_STUBBORN): Remove trailing ';' in the
+macro definition.
+* include/gc.h (GC_reachable_here): Likewise.
+* include/gc.h (GC_reachable_here): Prefix and postfix "volatile"
+with double '_'.
+
+* pthread_start.c: New file.
+* CMakeLists.txt (SRC): Add pthread_start.c.
+* Makefile.am (libgc_la_SOURCES): Likewise.
+* Makefile.direct (CSRCS): Likewise.
+* Makefile.direct (OBJS): Add pthread_start.obj.
+* extra/gc.c: Add a comment; include pthread_start.c.
+* pthread_support.c (start_info): Move the struct definition down
+closer to its usage.
+* pthread_support.c (GC_thread_exit_proc): Replace STATIC with
+GC_INNER.
+* pthread_support.c (GC_inner_start_routine): Move to the
+definition to pthread_start.c; leave only the prototype; remove
+STATIC.
+* pthread_support.c (GC_start_rtn_prepare_thread): New function
+(contains parts of the original GC_inner_start_routine).
+
+* configure.ac (NO_EXECUTE_PERMISSION): Add comment.
+* doc/README.macros (NO_EXECUTE_PERMISSION): Update the
+documentation.
+* include/gc.h (GC_set_pages_executable, GC_get_pages_executable):
+New API function declaration.
+* os_dep.c (OPT_PROT_EXEC): Remove (superseded by
+pages_executable).
+* os_dep.c (pages_executable): New static variable.
+* os_dep.c (IGNORE_PAGES_EXECUTABLE): New macro (used by
+GC_get_pages_executable only).
+* os_dep.c (GC_unix_mmap_get_mem, GC_remap, PROTECT, UNPROTECT):
+Replace OPT_PROT_EXEC with pages_executable.
+* os_dep.c (GC_unix_mmap_get_mem, GC_remap, GC_win32_get_mem,
+GC_wince_get_mem, UNPROTECT): Undefine IGNORE_PAGES_EXECUTABLE.
+* os_dep.c (GC_win32_get_mem, GC_wince_get_mem, GC_remap, PROTECT,
+UNPROTECT): Use PAGE_EXECUTE_... only if pages_executable is on.
+* os_dep.c (GC_set_pages_executable, GC_get_pages_executable): New
+API function definition.
+
+* tests/test.c (check_heap_stats): Increase max_heap_sz by 20% for
+64-bit CPUs (to prevent "Unexpected heap growth" failure on Win64,
+at least).
+
+* tests/test.c (check_heap_stats): Increase max_heap_sz by 25% for
+32-bit CPUs (to prevent "Unexpected heap growth" failure).
+
+* gc_dlopen.c (dlopen): Prototype REAL_DLFUNC if GC_USE_LD_WRAP.
+* pthread_support.c (pthread_create, pthread_join, pthread_detach,
+pthread_sigmask): Likewise.
+* gc_dlopen.c (dlopen): Remove cast (redundant since the prototype
+is added).
+* gc_dlopen.c (GC_dlopen): Fix return type.
+* pthread_support.c (GC_init_real_syms): Don't define
+LIBPTHREAD_NAME, LIBPTHREAD_NAME_LEN, len, namebuf and
+libpthread_name if RTLD_NEXT.
+
+* gc_dlopen.c (disable_gc_for_dlopen): Update the comment.
+* gc_dlopen.c (dlopen): Likewise.
+* include/gc.h (GC_enable_incremental): Refine the comment.
+* include/gc.h (DECLSPEC_NORETURN): Define macro as empty if
+missing (only for Win32).
+* include/gc.h (GC_ExitThread): Use DECLSPEC_NORETURN.
+* win32_threads.c (GC_ExitThread): Likewise.
+* include/gc.h (GC_endthreadex): Add a comment.
+
+* include/cord.h: Fix typos.
+
+* Makefile.am (EXTRA_DIST): Add "CMakeLists.txt" and
+"tests/CMakeLists.txt".
+* doc/doc.am (dist_pkgdata_DATA): Add "doc/README.cmake".
+
+* mach_dep.c (NO_GETCONTEXT): Also define if AVR32.
+* include/private/gcconfig.h (AVR32): New macro (also define the
+supplementary macros for the target).
+* include/private/thread_local_alloc (USE_COMPILER_TLS): Don't
+define for AVR32.
+
+* tests/leak_test.c (main): Explicitly define as returning int
+(to prevent a spurious test failure on some Linux/alpha targets).
+* tests/thread_leak_test.c (main): Likewise.
+* tests/thread_leak_test.c: Initialize GC_find_leak in the main
+thread (before GC_INIT) only.
+* tests/leak_test.c (main): Use GC_set_find_leak() instead of
+accessing GC_find_leak directly.
+* tests/thread_leak_test.c (main): Likewise.
+
+* include/gc.h (GC_find_leak, GC_finalize_on_demand,
+GC_java_finalization, GC_dont_expand, GC_no_dls,
+GC_dont_precollect): Simplify the comment (remove the information
+about data races since the value is boolean).
+
+* os_dep.c (GC_get_stack_base, GC_get_main_stack_base): New
+Solaris-specific implementation (based on thr_stksegment).
+* os_dep.c (stackbase_main_self, stackbase_main_ss_sp): New static
+variable used by the Solaris-specific GC_get_stack_base().
+
+* pthread_support.c (GC_mark_thread_local_free_lists,
+GC_check_tls): Mark (and check) only for live threads (in case of
+GC_destroy_thread_local() is called already but GC_delete_thread()
+is not yet).
+* win32_threads.c (GC_mark_thread_local_free_lists, GC_check_tls):
+Likewise.
+
+* NT_MAKEFILE: Remove the comment about DLL and Win32S.
+* NT_STATIC_THREADS_MAKEFILE: Likewise.
+* NT_X64_STATIC_THREADS_MAKEFILE: Likewise.
+* NT_MAKEFILE: Add ".SUFFIXES" directive (to handle gc_cpp.cc
+properly on VS 2005+).
+* NT_MAKEFILE: Update GC log file name in comments.
+* NT_STATIC_THREADS_MAKEFILE: Likewise.
+* NT_X64_STATIC_THREADS_MAKEFILE: Likewise.
+* NT_X64_THREADS_MAKEFILE: Likewise.
+* doc/README.win32: Likewise.
+* NT_MAKEFILE: Remove ":full" for "-debug" option (since no
+longer supported by VS).
+* NT_STATIC_THREADS_MAKEFILE: Likewise.
+* NT_MAKEFILE: Commented out copying of gc_cpp.cc to gc_cpp.cpp.
+* NT_STATIC_THREADS_MAKEFILE: Likewise.
+* NT_X64_STATIC_THREADS_MAKEFILE: Likewise.
+* NT_X64_THREADS_MAKEFILE: Likewise.
+* NT_STATIC_THREADS_MAKEFILE: Add -D PARALLEL_MARK option.
+* NT_STATIC_THREADS_MAKEFILE: Increase stack size for gctest.exe.
+* NT_X64_STATIC_THREADS_MAKEFILE: Remove "-stack" option (use the
+default stack size limit).
+* NT_X64_THREADS_MAKEFILE: Rename "gc64_dll.dll" to "gc64.dll".
+* win32_threads.c (GC_get_next_stack): Always define (since it is
+also used for Cygwin now).
+
+* alloc.c (GC_maybe_gc): Move GC_notify_full_gc() call upper to
+be just before GC_clear_marks() call.
+* include/gc_mark.h (GC_start_callback_proc): Refine the comment.
+
+* Makefile.am (check_LTLIBRARIES): Initialize to empty.
+* tests/tests.am (TESTS, check_PROGRAMS): Add staticrootstest.
+* tests/tests.am (staticrootstest_SOURCES, staticrootstest_LDADD,
+libstaticrootslib_la_SOURCES, libstaticrootslib_la_LIBADD,
+libstaticrootslib_la_LDFLAGS, libstaticrootslib_la_DEPENDENCIES):
+Define.
+* tests/tests.am (check_LTLIBRARIES): Add libstaticrootslib.la.
+
+* tests/staticrootstest.c: New file.
+* tests/staticrootslib.c: Likewise.
+
+* dyn_load.c (GC_get_next_stack, GC_cond_add_roots): Define for
+Cygwin as well as other win32 targets.
+* dyn_load.c (GC_wnt): Define to constant true.
+* dyn_load.c (GC_register_dynamic_libraries): Define for Cygwin as
+well as other win32 targets.
+* mark_rts.c (rt_hash, GC_roots_present, add_roots_to_index):
+Don't define for Cygwin, as on other win32.
+* mark_rts.c (GC_add_roots_inner, GC_clear_roots): Handle on
+Cygwin as for other win32 targets.
+* mark_rts.c (GC_rebuild_root_index): Don't declare on Cygwin, as
+other win32.
+* mark_rts.c (GC_remove_tmp_roots): Do declare on Cygwin as on
+other win32.
+* mark_rts.c (GC_remove_roots, GC_remove_roots_inner): Don't
+declare on Cygwin as on other win32.
+* mark_rts.c (GC_is_tmp_root): Do declare on Cygwin when
+!NO_DEBUGGING, as on other win32 targets.
+* mark_rts.c (GC_cond_register_dynamic_libraries): Handle on
+Cygwin as for other win32 targets.
+* os_dep.c (GC_setpagesize): Handle on Cygwin as on other win32.
+* os_dep.c (GC_get_main_stack_base): Don't declare on Cygwin, as
+other win32.
+* os_dep.c (GC_sysinfo): Declare on Cygwin, as other win32.
+* os_dep.c (GC_win32_get_mem): Declare on Cygwin, as on other
+Win32, but call GC_unix_get_mem instead of GlobalAlloc.
+* os_dep.c (GC_win32_free_heap): Declare on Cygwin (as empty).
+* ptr_chck.c (GC_is_visible): Register dynamic libraries on Cygwin
+as on other win32 platforms.
+* win32_threads.c (GC_get_next_stack): Define on Cygwin as well as
+for dynamic loading targets.
+* include/private/gc_priv.h (GC_INNER): Don't try to use
+visibility on Cygwin which does not support it.
+* include/private/gc_priv.h (struct roots): Don't declare r_next
+member on Cygwin as on other windows hosts.
+* include/private/gc_priv.h (LOG_RT_SIZE, RT_SIZE): Don't define
+likewise.
+* include/private/gc_priv.h (struct _GC_arrays): Do declare
+_heap_bases[] member and don't declare _root_index likewise.
+* include/private/gc_priv.h (GC_heap_bases): Do define likewise.
+* include/private/gc_priv.h (_SYSTEM_INFO): Do forward-declare
+likewise.
+* include/private/gc_priv.h (GC_sysinfo): Do declare extern
+likewise.
+* include/private/gcconfig.h (GC_win32_get_mem, GET_MEM): Do
+prototype on Cygwin as other win32 platforms.
+
+* os_dep.c (GC_get_main_stack_base): Use pthread_getattr_np() and
+pthread_attr_getstack() instead of GC_get_stack_base() (and check
+returned stackaddr for NULL); output a warning on failure.
+
+* alloc.c (GC_start_call_back): Replace the definition type to
+GC_start_callback_proc.
+* alloc.c (GC_set_start_callback, GC_get_start_callback): New
+setter/getter function.
+* alloc.c (GC_try_to_collect_inner): Call GC_notify_full_gc()
+unconditionally (because GC_try_to_collect_inner always does full
+GC).
+* include/gc_mark.h (GC_start_callback_proc): New type.
+* include/gc_mark.h (GC_set_start_callback,
+GC_get_start_callback): New API function declaration.
+
+* doc/README.macros (USE_GET_STACKBASE_FOR_MAIN): Document.
+* os_dep.c (GC_get_main_stack_base): Recognize
+USE_GET_STACKBASE_FOR_MAIN (only if THREADS and LINUX_STACKBOTTOM)
+and use GC_get_stack_base() in this case.
+
+* os_dep.c (GC_get_stack_base): Add LOCK/UNLOCK() (since
+GC_find_limit_with_bound() should be called with the lock held).
+* backgraph.c (FOR_EACH_PRED): Fix a typo.
+
+* alloc.c (GC_set_stop_func, GC_get_stop_func): Add
+DCL_LOCK_STATE.
+* finalize.c (GC_notify_or_invoke_finalizers): Likewise.
+* gc_dlopen.c (disable_gc_for_dlopen): Likewise.
+* gcj_mlc.c (maybe_finalize, GC_debug_gcj_malloc): Likewise.
+* mark.c (GC_print_trace): Likewise.
+* misc.c (GC_set_warn_proc, GC_get_warn_proc, GC_enable,
+GC_disable, GC_new_free_list, GC_new_kind, GC_new_proc,
+GC_set_oom_fn, GC_get_oom_fn, GC_set_finalizer_notifier,
+GC_get_finalizer_notifier): Likewise.
+* os_dep.c (GC_get_stack_base, GC_print_callers): Likewise.
+* pthread_support.c (GC_is_thread_tsd_valid,
+GC_wait_for_gc_completion, GC_init_parallel, GC_do_blocking_inner,
+GC_call_with_gc_active, GC_unregister_my_thread, pthread_join,
+pthread_detach, GC_register_my_thread, GC_inner_start_routine,
+pthread_create): Likewise.
+* reclaim.c (GC_print_all_errors): Likewise.
+* win32_threads.c (GC_is_thread_tsd_valid, GC_register_my_thread,
+GC_unregister_my_thread, GC_do_blocking_inner,
+GC_call_with_gc_active, GC_lookup_pthread, GC_pthread_join,
+GC_pthread_start_inner, GC_thread_exit_proc, GC_pthread_detach,
+GC_init_parallel): Likewise.
+
+* doc/README.darwin: Update.
+
+* CMakeLists.txt: Adjust INCLUDE_DIRECTORIES and SRC (to make it
+usable on Mac OS X).
+* doc/README.cmake: Update.
+
+* CMakeLists.txt: New file (adding CMake support).
+* tests/CMakeLists.txt: Likewise.
+* doc/README.cmake: Likewise.
+
+* configure.ac (darwin): Don't define HAS_PPC_THREAD_STATE...
+macros.
+* include/private/gc_priv.h (THREAD_FLD): Recognize
+__DARWIN_UNIX03 instead of HAS_PPC_THREAD_STATE... macros.
+
+* pthread_support.c: Include <sys/param.h> and <sys/sysctl.h> for
+OpenBSD.
+* pthread_support.c (get_ncpu): Define also for Darwin, NetBSD and
+OpenBSD.
+* pthread_support.c (GC_thr_init): Use get_ncpu() for Darwin,
+NetBSD and OpenBSD.
+
+* mallocx.c (GC_generic_malloc_many, GC_malloc_many): Define even
+if THREADS is undefined.
+* include/gc.h (GC_malloc_many): Update the comment.
+
+* include/gc_cpp.h (GC_PLACEMENT_DELETE): Define for Embarcadero
+(formerly known as Borland) C++ compiler v6.21+.
+* include/gc_cpp.h (GC_NO_OPERATOR_NEW_ARRAY): Define for ancient
+VC++ compilers.
+
+* win32_threads.c (GC_register_my_thread_inner,
+GC_pthread_start_inner): Undo the previous commit changes for
+the thread flags and DETACHED state (since the state is only
+tested in GC_thread_exit_proc).
+
+* include/gc.h (GC_unregister_my_thread): Fix a typo; update the
+comment.
+* pthread_support.c (GC_delete_thread): Allow to delete the main
+thread (don't call GC_INTERNAL_FREE for it); update the comment.
+* win32_threads.c (GC_delete_thread): Likewise.
+* pthread_support.c (GC_unregister_my_thread): Add an assertion
+for FINISHED flag is unset.
+* tests/test.c (check_heap_stats): Test the main thread
+unregistering (only if THREADS).
+* win32_threads.c (GC_register_my_thread_inner): Set flags to
+DETACHED (only if GC_PTHREADS).
+* win32_threads.c (GC_unregister_my_thread): Add FIXME (for
+GC_wait_for_gc_completion).
+* win32_threads.c (GC_pthread_start_inner): Clear flags detached
+state if needed; set pthread_id and flags while holding the lock.
+
+* include/private/gc_priv.h (SIG_SUSPEND): Don't define for
+OpenBSD and Darwin.
+
+* include/gc.h: Recognize _M_X64 (as an alias for _AMD64_).
+
+* test.c (main, WinMain): Consistently don't invoke
+GC_enable_incremental() if MAKE_BACKGRAPH is defined, but
+do invoke it even if parallel marking is enabled.
+
+* tests/test.c (reverse_test): Comment out a check for MSWIN32
+(when determining BIG value) assuming outdated win32S.
+* tests/test.c (reverse_test): Rename to reverse_test_inner;
+change the declaration (to be of GC_fn_type); call itself thru
+GC_call_with_gc_active() if the argument is zero.
+* tests/test.c (reverse_test): New function added calling
+reverse_test_inner thru GC_do_blocking (to test GC_do_blocking and
+GC_call_with_gc_active).
+
+* doc/README.macros (IGNORE_DYNAMIC_LOADING, PLATFORM_ANDROID):
+Document.
+* dyn_load.c: Don't include <elf.h> if PLATFORM_ANDROID.
+* dyn_load.c: Include bionic <linker.h> (instead of <link.h>) if
+PLATFORM_ANDROID.
+* include/private/gcconfig.h (LINUX): Define also if
+PLATFORM_ANDROID (for the windows-based toolkit).
+* include/private/gcconfig.h (SEARCH_FOR_DATA_START): Explicitly
+define for Android/x86 platform.
+* include/private/gcconfig.h (IGNORE_DYNAMIC_LOADING): Recognize
+new macro (undefine DYNAMIC_LOADING in this case).
+* include/private/gcconfig.h (CANCEL_SAFE): Don't define if
+PLATFORM_ANDROID.
+* include/private/gcconfig.h (IF_CANCEL): Fix definition for the
+explicitly defined CANCEL_SAFE.
+
+* allchblk.c (GC_allochblk_nth): Don't call GC_remove_protection()
+if GC_DISABLE_INCREMENTAL.
+* reclaim.c (GC_reclaim_generic): Likewise.
+* checksums.c (GC_page_was_ever_dirty): Add prototype.
+* include/private/gc_locks.h (GC_mark_lock_holder): Don't declare
+unless PARALLEL_MARK.
+* include/private/gc_priv.h (GC_dirty_maintained,
+GC_page_was_dirty, GC_remove_protection, GC_dirty_init): Don't
+declare if GC_DISABLE_INCREMENTAL.
+* include/private/gc_priv.h (GC_print_finalization_stats): Don't
+declare if SMALL_CONFIG.
+* include/private/gcconfig.h (CHECKSUMS): Explicitly undefine if
+GC_DISABLE_INCREMENTAL (since nothing to check).
+* include/private/gcconfig.h (DEFAULT_VDB): Don't define if
+GC_DISABLE_INCREMENTAL.
+* os_dep.c (GC_dirty_maintained): Likewise.
+* mark.c (GC_initiate_gc): Don't call GC_read_dirty() if
+GC_DISABLE_INCREMENTAL.
+* os_dep.c (GC_gww_page_was_ever_dirty, GC_page_was_ever_dirty):
+Uncomment; define only if CHECKSUMS.
+
+* darwin_stop_world.c (GC_push_all_stacks): Fix a bug (call
+GC_push_all_stack() instead of GC_push_all_stack_frames()).
+* include/private/gc_priv.h (GC_push_all_stack_frames,
+GC_push_all_register_frames): Rename to
+GC_push_all_stack_sections and GC_push_all_register_sections,
+respectively.
+* mark_rts.c (GC_push_all_stack_frames,
+GC_push_all_register_frames, GC_push_all_stack_part_eager_frames,
+GC_push_current_stack): Likewise.
+* pthread_stop_world.c (GC_push_all_stacks): Likewise.
+* win32_threads.c (GC_push_stack_for): Likewise.
+* misc.c (GC_call_with_gc_active): Rename "frame" local variable
+to "stacksect".
+* pthread_support.c (GC_call_with_gc_active): Likewise.
+* win32_threads.c (GC_call_with_gc_active): Likewise.
+* pthread_support.c (GC_call_with_gc_active): Update FIXME for
+Darwin.
+* win32_threads.c (GC_Thread_Rep): Update the comment for
+traced_stack_sect.
+
+* darwin_stop_world.c (GC_push_all_stacks): Rename
+activation_frame to traced_stack_sect.
+* include/private/gc_priv.h (GC_push_all_stack_frames,
+GC_push_all_register_frames): Likewise.
+* include/private/pthread_support.h (GC_Thread_Rep): Likewise.
+* mark_rts.c (GC_push_all_register_frames,
+GC_push_all_stack_frames, GC_push_all_stack_part_eager_frames,
+GC_push_current_stack): Likewise.
+* pthread_stop_world.c (GC_push_all_stacks): Likewise.
+* pthread_support.c (GC_call_with_gc_active): Likewise.
+* win32_threads.c (GC_Thread_Rep, GC_call_with_gc_active,
+GC_push_stack_for): Likewise.
+* include/private/gc_priv.h (GC_activation_frame_s): Rename to
+GC_traced_stack_sect_s.
+* include/private/gc_priv.h (GC_activation_frame): Rename to
+GC_traced_stack_sect.
+* misc.c (GC_activation_frame, GC_call_with_gc_active): Likewise.
+* doc/README.macros (UNICODE): Document.
+
+* doc/README.macros (GC_READ_ENV_FILE): Document (new macro).
+* include/private/gc_priv.h (GETENV): Recognize GC_READ_ENV_FILE;
+declare and use GC_envfile_getenv().
+* misc.c (GC_envfile_content, GC_envfile_length): New static
+variable (only if GC_READ_ENV_FILE).
+* misc.c (GC_ENVFILE_MAXLEN): New macro (used in GC_envfile_init).
+* misc.c (GC_envfile_init, GC_envfile_getenv): New function (only
+if GC_READ_ENV_FILE).
+* misc.c (GC_init): Call GC_envfile_init() (before using GETENV)
+if GC_READ_ENV_FILE.
+* misc.c (GC_init): Move GC_setpagesize() and GC_init_win32()
+calls to be just before GC_envfile_init() one (since the latter
+uses GET_MEM).
+* misc.c (GC_abort): use ExitProcess() (instead of DebugBreak) for
+WinCE if NO_DEBUGGING; add a comment for DebugBreak() (for WinCE).
+* mark_rts.c (GC_add_roots_inner): Remove redundant trailing '\n'
+from the ABORT message.
+* misc.c (GC_init): Likewise.
+* os_dep.c (GC_get_main_stack_base, GC_register_data_segments):
+Likewise.
+* pthread_stop_world.c (GC_push_all_stacks): Likewise.
+* pthread_support.c (GC_init_real_syms, start_mark_threads):
+Likewise.
+
+* win32_threads.c (GC_get_next_stack): Don't define for Cygwin
+(since unused for now).
+
+* dyn_load.c (HAVE_REGISTER_MAIN_STATIC_DATA): Don't define unless
+GC_register_main_static_data() is defined.
+* dyn_load.c (GC_register_dynamic_libraries): Define only if used
+(if DYNAMIC_LOADING or PCR or Win32/CE).
+* dyn_load.c (GC_register_main_static_data): Define the default
+one only if DYNAMIC_LOADING.
+* include/private/gc_priv.h (GC_register_dynamic_libraries):
+Declare only if used (to prevent compiler warning).
+
+* mark_rts.c (GC_approx_sp): Add a comment (for GCC).
+
+
+== [7.2alpha4] 2009-12-01 ==
+
+* configure.ac (AC_CONFIG_COMMANDS): Quote srcdir value.
+
+* include/gc.h (GC_get_suspend_signal): New function declaration.
+* misc.c (GC_get_suspend_signal): New API function (only if
+THREADS).
+
+* alloc.c (min_bytes_allocd): Multiply GC_free_space_divisor by
+two if GC_incremental (instead of TRUE_INCREMENTAL).
+
+* sparc_mach_dep.S (GC_push_regs): Remove the reference.
+
+* os_dep.c (SIZE_T, PULONG_PTR): Remove.
+* os_dep.c (ULONG_PTR): Replace with GC_ULONG_PTR (defined as GC
+"word"); add the comment.
+* os_dep.c (GetWriteWatch_type, detect_GetWriteWatch,
+GC_gww_read_dirty): Prefix ULONG_PTR with "GC_".
+
+* win32_threads.c (THREAD_TABLE_SZ): Change back to a power-of-two
+const value (for speed).
+* win32_threads.c (THREAD_TABLE_INDEX): New macro.
+* win32_threads.c (GC_new_thread, GC_lookup_thread_inner,
+GC_delete_gc_thread, GC_delete_thread, GC_lookup_pthread): Use
+THREAD_TABLE_INDEX instead of THREAD_TABLE_SZ.
+* win32_threads.c (PTHREAD_MAP_HASH): Rename to PTHREAD_MAP_INDEX.
+
+* win32_threads.c (THREAD_TABLE_SZ): Make the const value prime.
+
+* backgraph.c: Remove apostrophe char from "#error".
+
+* doc/README.macros (GC_DISABLE_INCREMENTAL): Document.
+* include/private/gcconfig.h (GC_DISABLE_INCREMENTAL): Recognize
+new macro; implicitly define it if SMALL_CONFIG.
+* alloc.c (GC_incremental, GC_timeout_stop_func): Check for
+GC_DISABLE_INCREMENTAL instead of SMALL_CONFIG.
+* include/private/gc_priv.h (GC_incremental, TRUE_INCREMENTAL,
+GC_push_conditional): Likewise.
+* mark.c (GC_push_next_marked_dirty, GC_push_selected,
+GC_push_conditional, GC_block_was_dirty): Likewise.
+* misc.c (GC_enable_incremental): Likewise.
+* misc.c (GC_init): Likewise.
+
+* dyn_load.c (WIN32_LEAN_AND_MEAN): Guard with ifndef.
+* misc.c (WIN32_LEAN_AND_MEAN): Likewise.
+* os_dep.c (WIN32_LEAN_AND_MEAN): Likewise.
+* allchblk.c (GC_allochblk_nth): Fix a minor typo (don't/doesn't)
+in a comment.
+* backgraph.c: Likewise.
+* dyn_load.c (GC_register_dynamic_libraries): Likewise.
+* extra/threadlibs.c (main): Likewise.
+* pthread_support.c (pthread_join): Likewise.
+* tests/test.c (main): Likewise.
+
+* mach_dep.c (GC_push_regs): Remove STATIC (just to catch
+a duplicate symbol definition linker error).
+* misc.c (GC_clear_stack_inner): Likewise.
+* sparc_mach_dep.S (GC_push_regs): Comment out the reference.
+
+* include/private/gc_priv.h (GC_write_disabled): New variable
+declaration (only if GC_ASSERTIONS and Win32 threads).
+* misc.c (GC_write): Add assertion for GC_write_disabled value is
+not on (only if THREADS).
+* win32_threads.c (GC_write_disabled): New variable (only if
+GC_ASSERTIONS and not Cygwin).
+* win32_threads.c (GC_stop_world): Set and clear GC_write_disabled
+(while holding GC_write_cs).
+
+* win32_threads.c (GC_please_stop): If DllMain-based thread
+registration is not compiled in then define GC_please_stop as
+a non-volatile variable for assertion only.
+* win32_threads.c (GC_stop_world): Set and clear only if defined.
+* win32_threads.c (GC_stop_world): Add the comment for GC_printf()
+usage (while holding GC_write_cs).
+* win32_threads.c (GC_delete_gc_thread): Likewise.
+* os_dep.c (GC_remove_protection): Likewise.
+
+* pthread_support.c (GC_inner_start_routine): Join 3 sequential
+GC_printf() calls into a single one (for DEBUG_THREADS).
+
+* include/private/gc_priv.h (GC_total_stacksize): New variable
+declaration (only if THREADS).
+* alloc.c (GC_total_stacksize): New variable (only if THREADS).
+* alloc.c (min_bytes_allocd): Calculate stack_size using
+GC_stackbottom only in the single-threaded case; otherwise use
+GC_total_stacksize; print GC_total_stacksize value if
+DEBUG_THREADS.
+* darwin_stop_world.c (GC_push_all_stacks): Use "%p" printf type
+specifier for lo/hi values (instead of "%lx").
+* darwin_stop_world.c (GC_push_all_stacks): Use
+GC_push_all_stack_frames() instead of GC_push_all_stack().
+* darwin_stop_world.c (GC_push_all_stacks): Recalculate
+GC_total_stacksize value.
+* pthread_stop_world.c (GC_push_all_stacks): Likewise.
+* win32_threads.c (GC_push_all_stacks): Likewise.
+* win32_threads.c (GC_push_stack_for): Pass "me" argument; return
+stack size; don't check for non-zero value of thread->stack_base.
+* win32_threads.c (GC_push_all_stacks): Don't call
+GC_push_stack_for() and don't check for "t->id == me" if
+thread->stack_base is zero.
+
+* dyn_load.c (GC_dump_meminfo): Prefix "%lx" printf type specifier
+with "0x".
+* os_dep.c (PROTECT): Likewise.
+* win32_threads.c (GC_mark_thread_local_free_lists): Cast p->id to
+int (to match printf type specifier).
+
+* tests/test.c (check_heap_stats): Take into account the unmapped
+memory size when checking for "Unexpected heap growth"; remove
+FIXME.
+
+* alloc.c: Revert last change.
+
+* include/private/gcconfig.h (STACKBOTTOM): Add a presence check
+for eCos/NOSYS.
+* misc.c (GC_write): Comment out _Jv_diag_write() call (since no
+longer defined in GCJ).
+
+* os_dep.c (brk): Rename to ecos_gc_brk.
+
+* alloc.c (min_bytes_allocd): Use GC_stackbottom value to compute
+stack_size even if THREADS.
+* doc/README.macros (DEBUG_THREADS): Document.
+* pthread_support.c (DEBUG_THREADS): Remove the commented out
+definition.
+* win32_threads.c (DEBUG_WIN32_THREADS): Remove duplicate
+definition.
+* win32_threads.c: Include errno.h (except for WinCE).
+* win32_threads.c (GC_win32_start_inner): Copy "start" and "param"
+to local variables, and free "arg" parameter before "start"
+invocation.
+* win32_threads.c (GC_beginthreadex): Set errno to EAGAIN on error
+(instead of calling SetLastError(ERROR_NOT_ENOUGH_MEMORY)).
+* win32_threads.c (GC_beginthreadex): Return 0 on error (instead
+of -1).
+
+* darwin_stop_world.c (GC_darwin_register_mach_handler_thread):
+Use GC_INNER for the function definition.
+* include/private/darwin_stop_world.h
+(GC_darwin_register_mach_handler_thread): Remove the prototype.
+* os_dep.c (GC_darwin_register_mach_handler_thread): Use GC_INNER
+for the function prototype.
+* include/private/gc_priv.h (NDEBUG): Explicitly define if
+NO_DEBUGGING and not GC_ASSERTIONS (before the standard headers
+inclusion).
+
+* include/private/gcconfig.h: Move DebugBreak() workaround (for
+x86mingw32ce toolchain) to gc_priv.h (after windows.h inclusion).
+
+* allchblk.c (GC_unmap_old, GC_merge_unmapped, GC_allochblk,
+GC_freehblk): Use GC_INNER for the function definition.
+* alloc.c (GC_never_stop_func, GC_should_collect,
+GC_try_to_collect_inner, GC_collect_a_little_inner,
+GC_set_fl_marks, GC_add_to_our_memory, GC_add_to_heap,
+GC_expand_hp_inner, GC_collect_or_expand, GC_allocobj): Likewise.
+* backgraph.c (GC_build_back_graph, GC_traverse_back_graph):
+Likewise.
+* blacklst.c (GC_default_print_heap_obj_proc, GC_bl_init,
+GC_promote_black_lists, GC_unpromote_black_lists,
+GC_add_to_black_list_normal, GC_add_to_black_list_stack,
+GC_is_black_listed): Likewise.
+* darwin_stop_world.c (GC_push_all_stacks, GC_push_all_stacks,
+GC_stop_init, GC_stop_world, GC_start_world): Likewise.
+* dbg_mlc.c (GC_has_other_debug_info, GC_store_back_pointer,
+GC_marked_for_finalization, GC_generate_random_backtrace_no_gc,
+GC_store_debug_info, GC_start_debugging,
+GC_debug_generic_malloc_inner,
+GC_debug_generic_malloc_inner_ignore_off_page,
+GC_debug_malloc_uncollectable, GC_debug_free_inner): Likewise.
+* dyn_load.c (GC_register_dynamic_libraries,
+GC_register_main_static_data, GC_init_dyld): Likewise.
+* finalize.c (GC_push_finalizer_structures, GC_finalize,
+GC_notify_or_invoke_finalizers, GC_print_finalization_stats):
+Likewise.
+* gcj_mlc.c (GC_core_gcj_malloc): Likewise.
+* headers.c (GC_find_header, GC_header_cache_miss,
+GC_scratch_alloc, GC_init_headers, GC_install_header,
+GC_install_counts, GC_remove_header, GC_remove_counts,
+GC_next_used_block, GC_prev_block): Likewise.
+* mach_dep.c (GC_with_callee_saves_pushed): Likewise.
+* malloc.c (GC_collect_or_expand, GC_alloc_large,
+GC_generic_malloc_inner, GC_generic_malloc_inner_ignore_off_page,
+GC_core_malloc_atomic, GC_core_malloc, GC_free_inner): Likewise.
+* mallocx.c (GC_generic_malloc_ignore_off_page): Likewise.
+* mark.c (GC_collection_in_progress, GC_clear_hdr_marks,
+GC_set_hdr_marks, GC_set_mark_bit, GC_clear_mark_bit,
+GC_clear_marks, GC_initiate_gc, GC_mark_some,
+GC_mark_stack_empty, GC_invalidate_mark_state,
+GC_signal_mark_stack_overflow, GC_mark_from, GC_help_marker,
+GC_mark_init, GC_push_all, GC_push_conditional,
+GC_mark_and_push_stack, GC_push_all_eager, GC_push_all_stack):
+Likewise.
+* mark_rts.c (GC_is_static_root, GC_roots_present, GC_approx_sp,
+GC_exclude_static_roots_inner, GC_push_all_register_frames,
+GC_push_all_stack_frames, GC_cond_register_dynamic_libraries,
+GC_push_roots): Likewise.
+* misc.c (GC_extend_size_map, GC_clear_stack, GC_err_write):
+Likewise.
+* new_hblk.c (GC_build_fl, GC_new_hblk): Likewise.
+* obj_map.c (GC_register_displacement_inner, GC_add_map_entry,
+GC_initialize_offsets): Likewise.
+* os_dep.c (GC_get_maps, GC_parse_map_entry, GC_text_mapping,
+GC_init_linux_data_start, GC_init_netbsd_elf, GC_setpagesize,
+GC_set_and_save_fault_handler, GC_setup_temporary_fault_handler,
+GC_reset_fault_handler, GC_get_register_stack_base, GC_init_win32,
+GC_add_current_malloc_heap, GC_is_heap_base, GC_unmap, GC_remap,
+GC_unmap_gap, GC_push_all_stacks, GC_gww_dirty_init,
+GC_dirty_init, GC_read_dirty, GC_page_was_dirty,
+GC_page_was_ever_dirty, GC_remove_protection,
+GC_write_fault_handler, GC_mprotect_stop, GC_mprotect_resume,
+GC_save_callers, GC_print_callers): Likewise.
+* pthread_stop_world.c (GC_push_all_stacks, GC_stop_world,
+GC_start_world, GC_stop_init): Likewise.
+* pthread_support.c (GC_mark_thread_local_free_lists,
+GC_lookup_thread, GC_reset_finalizer_nested,
+GC_check_finalizer_nested, GC_segment_is_thread_stack,
+GC_greatest_stack_base_below, GC_thr_init, GC_init_parallel,
+GC_do_blocking_inner, GC_lock, GC_acquire_mark_lock,
+GC_release_mark_lock, GC_wait_for_reclaim, GC_notify_all_builder,
+GC_wait_marker, GC_notify_all_marker): Likewise.
+* reclaim.c (GC_print_all_errors, GC_block_empty,
+GC_reclaim_generic, GC_start_reclaim, GC_continue_reclaim,
+GC_reclaim_all): Likewise.
+* thread_local_alloc.c (GC_init_thread_local,
+GC_destroy_thread_local, GC_mark_thread_local_fls_for): Likewise.
+* win32_threads.c (GC_reset_finalizer_nested,
+GC_check_finalizer_nested, GC_do_blocking_inner, GC_stop_world,
+GC_start_world, GC_push_all_stacks, GC_get_next_stack,
+GC_acquire_mark_lock, GC_release_mark_lock, GC_wait_for_reclaim,
+GC_notify_all_builder, GC_wait_marker, GC_notify_all_marker,
+GC_thr_init, GC_init_parallel, GC_lock,
+GC_mark_thread_local_free_lists): Likewise.
+* alloc.c (GC_add_current_malloc_heap, GC_build_back_graph,
+GC_traverse_back_graph): Use GC_INNER for the function prototype.
+* darwin_stop_world.c (GC_mprotect_stop, GC_mprotect_resume):
+Likewise.
+* dbg_mlc.c (GC_default_print_heap_obj_proc): Likewise.
+* dyn_load.c (GC_parse_map_entry, GC_get_maps,
+GC_segment_is_thread_stack, GC_roots_present, GC_is_heap_base,
+GC_get_next_stack): Likewise.
+* finalize.c (GC_reset_finalizer_nested,
+GC_check_finalizer_nested): Likewise.
+* gcj_mlc.c (GC_start_debugging): Likewise.
+* include/private/dbg_mlc.h (GC_save_callers, GC_print_callers,
+GC_has_other_debug_info, GC_store_debug_info): Likewise.
+* include/private/gc_hdrs.h (GC_header_cache_miss): Likewise.
+* include/private/gc_locks.h (GC_lock): Likewise.
+* include/private/gc_pmark.h (GC_signal_mark_stack_overflow,
+GC_mark_from): Likewise.
+* include/private/pthread_support.h (GC_lookup_thread,
+GC_stop_init): Likewise.
+* include/private/thread_local_alloc.h (GC_init_thread_local,
+GC_destroy_thread_local, GC_mark_thread_local_fls_for): Likewise.
+* malloc.c (GC_extend_size_map, GC_text_mapping): Likewise.
+* mark.c (GC_page_was_ever_dirty): Likewise.
+* mark_rts.c (GC_mark_thread_local_free_lists): Likewise.
+* misc.c (GC_register_main_static_data, GC_init_win32,
+GC_setpagesize, GC_init_linux_data_start,
+GC_set_and_save_fault_handler, GC_init_dyld, GC_init_netbsd_elf,
+GC_do_blocking_inner): Likewise.
+* os_dep.c (GC_greatest_stack_base_below): Likewise.
+* win32_threads.c (GC_write_fault_handler, GC_gww_dirty_init):
+Likewise.
+* include/private/gc_priv.h: Likewise.
+* include/private/gc_priv.h (GC_INNER): Update the comment.
+* doc/README.macros (GC_DLL): Update.
+
+* alloc.c (GC_collection_in_progress): Move the prototype to
+gc_priv.h.
+* gc_dlopen.c (GC_collection_in_progress): Likewise.
+* pthread_support.c (GC_collection_in_progress): Likewise.
+* misc.c (GC_init_parallel): Likewise.
+* pthread_support.c (GC_init_parallel): Likewise.
+* win32_threads.c (GC_init_parallel): Likewise.
+* darwin_stop_world.c (GC_thr_init): Likewise.
+* misc.c (GC_thr_init): Likewise.
+* pthread_stop_world.c (GC_thr_init): Likewise.
+* pthread_support.c (GC_thr_init): Likewise.
+* blacklst.c (GC_clear_bl, GC_copy_bl,
+GC_number_stack_black_listed): Make STATIC.
+* dbg_mlc.c (GC_print_obj, GC_make_closure,
+GC_debug_invoke_finalizer): Likewise.
+* malloc.c (GC_alloc_large_and_clear): Likewise.
+* mark.c (GC_push_selected, GC_push_marked1, GC_push_marked2,
+GC_push_marked4, GC_push_marked, GC_push_next_marked,
+GC_push_next_marked_dirty, GC_push_next_marked_uncollectable):
+Likewise.
+* misc.c (GC_clear_stack_inner): Likewise.
+* os_dep.c (GC_repeat_read, GC_default_push_other_roots): Likewise.
+* darwin_stop_world.c (FindTopOfStack): Make static; define only
+if not DARWIN_DONT_PARSE_STACK.
+* dbg_mlc.c (GC_debug_free_inner): Define only if DBG_HDRS_ALL.
+* dyn_load.c (GC_repeat_read): Remove unused prototype.
+* include/private/gc_pmark.h (GC_find_start): Likewise.
+* misc.c (GC_read, GC_register_finalizer_no_order): Likewise.
+* dyn_load.c (GC_segment_is_thread_stack): Add prototype (only if
+THREADS).
+* dyn_load.c (GC_register_main_static_data): Define only if
+DYNAMIC_LOADING.
+* finalize.c (GC_enqueue_all_finalizers): Remove unnecessary tail
+"return" statement.
+* gc_dlopen.c (GC_SOLARIS_THREADS): Don't recognize (since implies
+GC_PTHREADS).
+* include/gc.h: Fix a typo.
+* include/gc_inline.h (GC_ASSERT): Define (if not defined) since
+the header is public.
+* include/gc_inline.h (GC_generic_malloc_many): New public
+function declaration.
+* mallocx.c (GC_generic_malloc_many): Make public.
+* include/private/gc_priv.h (GC_INNER): Use visibility attribute
+(if available).
+* include/private/gc_priv.h (GC_EXTERN): Define using GC_INNER.
+* include/private/gc_priv.h: Include atomic_ops.h if THREADS and
+MPROTECT_VDB.
+* os_dep.c: Don't include atomic_ops.h
+* win32_threads.c: Likewise.
+* include/private/gc_priv.h (GC_push_selected, GC_push_regs,
+GC_push_marked, GC_number_stack_black_listed,
+GC_alloc_large_and_clear, GC_reclaim_or_delete_all,
+GC_generic_malloc_many, GC_make_closure,
+GC_debug_invoke_finalizer, GC_print_obj, GC_page_was_ever_dirty):
+Remove the prototype.
+* mark.c (GC_page_was_ever_dirty): Add prototype (only if
+PROC_VDB).
+* include/private/gc_priv.h (GC_push_next_marked_dirty,
+GC_push_next_marked, GC_push_next_marked_uncollectable): Move
+the prototype to mark.c.
+* include/private/gc_priv.h (GC_is_static_root): Declare only if
+not THREADS.
+* include/private/gc_priv.h (GC_free_inner): Declare only if
+THREADS.
+* include/private/gc_priv.h (GC_debug_free_inner): Declare only if
+THREADS and DBG_HDRS_ALL.
+* include/private/gc_priv.h (GC_markers): Declare GC_markers only
+if PARALLEL_MARK.
+* include/private/gc_priv.h (GC_register_main_static_data): Move
+the prototype to misc.c.
+* mach_dep.c (GC_push_regs): Make STATIC; define only along with
+HAVE_PUSH_REGS definition.
+* mach_dep.c (GC_clear_stack_inner): Replace K&R-style function
+definition with the ANSI C one.
+* mark.c (GC_started_thread_while_stopped): Declared only if not
+GNU C.
+* win32_threads.c (GC_started_thread_while_stopped): Don't define
+if GNU C.
+* mark.c (GC_mark_from): Avoid unbalanced brackets in
+#if-#else-#endif blocks.
+* mark_rts.c (GC_is_static_root): Define only if not THREADS.
+* os_dep.c (GC_get_stack_base): Make public (for OpenBSD).
+* os_dep.c (GC_page_was_ever_dirty): Comment out the function
+except for PROC_VDB.
+* tests/test.c (main): Don't reference GC_print_obj,
+GC_make_closure, GC_debug_invoke_finalizer,
+GC_page_was_ever_dirty, GC_is_fresh (in GC_noop).
+* thread_local_alloc.c: Don't include "gc_inline.h".
+* win32_threads.c (GC_write_fault_handler): Declare only if
+MPROTECT_VDB.
+
+* allchblk.c (DEBUG): Remove macro (since unused).
+* allchblk.c: Include private/gc_priv.h before other includes and
+definitions.
+* alloc.c: Likewise.
+* gc_dlopen.c: Likewise.
+* headers.c: Likewise.
+* mallocx.c: Likewise.
+* mark_rts.c: Likewise.
+* new_hblk.c: Likewise.
+* reclaim.c: Likewise.
+* mark.c: Include private/gc_pmark.h before other includes.
+* misc.c: Likewise.
+* dyn_load.c (_GNU_SOURCE): Move the definition to gc_priv.h.
+* pthread_support.c (_USING_POSIX4A_DRAFT10): Likewise.
+* pthread_support.c (_POSIX4A_DRAFT10_SOURCE): Remove (since
+already defined in gc_config_macros.h).
+* dyn_load.c (GC_init_dyld): Remove parameter cast for
+_dyld_register_func_for_add_image() and
+_dyld_register_func_for_remove_image(); add the comment about
+possible warnings; add FIXME for the deprecated
+_dyld_bind_fully_image_containing_address().
+* include/private/gc_priv.h: Include gc.h before the standard
+headers inclusion.
+* tests/test.c: Likewise.
+* include/private/gcconfig.h (DebugBreak): Update the comment.
+* typd_mlc.c (ED_INITIAL_SIZE): Remove ';'.
+
+* configure.ac (openbsd): Define GC_OPENBSD_THREADS.
+* configure.ac: Add AM_CONDITIONAL(OPENBSD_THREADS).
+* configure.ac: Add sparc-openbsd case.
+* doc/README.macros (GC_NETBSD_THREADS, GC_OPENBSD_THREADS):
+Document.
+* tests/test.c (main): Handle OpenBSD case.
+* include/private/pthread_stop_world.h: Likewise.
+* extra/threadlibs.c (main): Replace K&R-style function definition
+with the ANSI C one.
+* extra/threadlibs.c (main): Handle GC_OPENBSD_THREADS case.
+* dyn_load.c (OPENBSD): Recognize (similar to NETBSD).
+* include/gc_config_macros.h (GC_SOLARIS_THREADS): Recognize;
+define it for OpenBSD.
+* include/gc_pthread_redirects.h (GC_pthread_sigmask,
+pthread_sigmask): Don't declare and redefine for OpenBSD.
+* include/private/gcconfig.h: Handle OpenBSD (on arm, sh, i386,
+amd64, powerpc).
+* mach_dep.c (NO_GETCONTEXT): Likewise.
+* include/private/pthread_stop_world.h (thread_stop_info): Don't
+define last_stop_count field if OpenBSD.
+* misc.c (GC_init_dyld): Add declaration (if NetBSD).
+* misc.c (GC_init): Don't call GC_init_netbsd_elf() for OpenBSD.
+* os_dep.c (GC_init_netbsd_elf): Don't define for OpenBSD.
+* os_dep.c (old_segv_act, GC_jmp_buf_openbsd): New static variable
+(only if OpenBSD).
+* os_dep.c (GC_fault_handler_openbsd, GC_find_limit_openbsd,
+GC_skip_hole_openbsd): New static function (only if OpenBSD).
+* os_dep.c (GC_get_stack_base, GC_get_main_stack_base,
+GC_register_data_segments): Define specially for OpenBSD case.
+* os_dep.c (GC_fault_handler_lock): Initialize to
+AO_TS_INITIALIZER (instead of 0).
+* pthread_support.c (GC_allocate_lock): Likewise.
+* pthread_stop_world.c (NSIG, GC_print_sig_mask,
+GC_remove_allowed_signals, suspend_handler_mask, GC_stop_count,
+GC_world_is_stopped, GC_retry_signals, SIG_THR_RESTART,
+GC_suspend_ack_sem, GC_suspend_handler_inner, GC_suspend_handler,
+GC_restart_handler): Don't define and use if OpenBSD.
+* pthread_stop_world.c (GC_suspend_all, GC_stop_world,
+GC_start_world): Handle OpenBSD case.
+* pthread_stop_world.c (GC_stop_init): Define as empty if OpenBSD.
+* pthread_support.c (pthread_sigmask): Don't undefine the macro and
+don't define the wrapper function if OpenBSD.
+* pthread_support.c (GC_thr_init): Handle OpenBSD case.
+
+* dyn_load.c: Move the inclusion of private/gc_priv.h below
+definition of a feature macro (_GNU_SOURCE).
+
+* include/gc.h (REVEAL_POINTER): Remove redundant parentheses.
+* include/gc.h (GC_HIDE_POINTER, GC_REVEAL_POINTER): New macros
+(only if GC_I_HIDE_POINTERS).
+* backgraph.c (GET_OH_BG_PTR): Prefix REVEAL_POINTER() with "GC_".
+* dbg_mlc.c (GC_get_back_ptr_info): Likewise.
+* finalize.c (GC_grow_table, GC_dump_finalization, GC_finalize,
+GC_enqueue_all_finalizers): Likewise.
+* backgraph.c (SET_OH_BG_PTR): Prefix HIDE_POINTER() with "GC_".
+* finalize.c (GC_general_register_disappearing_link,
+GC_unregister_disappearing_link, GC_register_finalizer_inner,
+GC_finalize): Likewise.
+* include/private/dbg_mlc.h (HIDE_BACK_PTR): Likewise.
+* include/private/dbg_mlc.h (GC_I_HIDE_POINTERS): Define instead
+of I_HIDE_POINTERS.
+* include/private/gc_priv.h (GC_I_HIDE_POINTERS): Likewise.
+* include/gc.h (_GC_H): Strip leading underscore.
+* include/gc_backptr.h (_GC_H): Likewise.
+* include/gc_gcj.h (_GC_H): Likewise.
+* include/gc_mark.h (_GC_H): Likewise.
+* include/gc_typed.h (_GC_TYPED_H, _GC_H): Likewise.
+* include/javaxfc.h (_GC_H): Likewise.
+* include/new_gc_alloc.h (__GC_SPECIALIZE): Likewise.
+* include/private/dbg_mlc.h (_GC_H): Likewise.
+* include/private/gc_priv.h (_GC_H): Likewise.
+
+* gc_cpp.cc: Include "gc_cpp.h" instead of <gc_cpp.h>.
+
+* include/private/gc_priv.h (GC_INNER): New macro (for GC-scope
+variable definitions).
+* include/private/gc_priv.h (GC_EXTERN): Update the comment.
+* allchblk.c (GC_unmap_threshold): Define as GC_INNER.
+* alloc.c (GC_incremental, GC_world_stopped, GC_n_heap_sects,
+GC_n_memory, GC_fail_count): Likewise.
+* blacklst.c (GC_black_list_spacing, GC_print_heap_obj): Likewise.
+* gcj_mlc.c (GC_gcj_malloc_initialized, GC_gcjobjfreelist): Likewise.
+* mach_dep.c (GC_save_regs_ret_val): Likewise.
+* mark.c (GC_n_mark_procs, GC_obj_kinds, GC_n_kinds,
+GC_mark_stack, GC_mark_stack_limit, GC_mark_stack_size,
+GC_mark_stack_top, GC_mark_state, GC_mark_stack_too_small,
+GC_mark_no, GC_markers): Likewise.
+* mark_rts.c (GC_root_size, GC_push_typed_structures): Likewise.
+* misc.c (GC_allocate_ml, GC_debugging_started, GC_check_heap,
+GC_print_all_smashed, GC_print_back_height, GC_dump_regularly,
+GC_backtraces, GC_force_unmap_on_gcollect,
+GC_large_alloc_warn_interval, GC_is_initialized, GC_write_cs,
+GC_current_warn_proc, GC_blocked_sp, GC_activation_frame): Likewise.
+* os_dep.c (GC_page_size, GC_dont_query_stack_min,
+GC_no_win32_dlls, GC_wnt, GC_sysinfo, GC_push_other_roots,
+GC_dirty_maintained, GC_fault_handler_lock): Likewise.
+* pthread_support.c (GC_allocate_ml, GC_lock_holder,
+GC_need_to_lock, GC_thr_initialized, GC_threads,
+GC_in_thread_creation, GC_collecting, GC_allocate_lock,
+GC_mark_lock_holder): Likewise.
+* reclaim.c (GC_bytes_found, GC_fl_builder_count, GC_have_errors):
+Likewise.
+* win32_threads.c (GC_allocate_ml, GC_lock_holder,
+GC_need_to_lock, GC_mark_lock_holder, GC_collecting): Likewise.
+* extra/gc.c (GC_INNER, GC_EXTERN): Define as STATIC.
+* mach_dep.c (GC_with_callee_saves_pushed): Remove redundant {}.
+
+* include/private/gc_priv.h (GC_bytes_allocd, GC_objfreelist,
+GC_aobjfreelist): Replace GC_EXTERN to extern for SEPARATE_GLOBALS
+case (since they are not defined inside GC at present).
+* include/private/gc_priv.h (GC_objects_are_marked): Remove the
+declaration (since made static).
+* mark.c (GC_objects_are_marked): Define as STATIC.
+* win32_threads.c (GC_thr_initialized, GC_in_thread_creation):
+Likewise.
+* mark.c (GC_N_KINDS_INITIAL_VALUE): New macro (defined and used
+to initialize GC_n_kinds).
+* win32_threads.c (start_mark_threads): Adjust the comment.
+
+* alloc.c (GC_notify_full_gc): Use GC_INLINE for a tiny static
+function.
+* backgraph.c (pop_in_progress, GC_apply_to_each_object): Likewise.
+* mark_rts.c (add_roots_to_index): Likewise.
+
+* extra/gc.c: New file.
+* Makefile.am (EXTRA_DIST): Add "extra/gc.c".
+
+* misc.c (GC_log): Remove the declaration; move the definition (to
+the place where it is used); make STATIC.
+* misc.c (GC_init): Use GC_err_printf() instead of GC_log_printf()
+to print open log failure.
+* misc.c (GC_write): Don't abort on open log failure if the GC is
+compiled with GC_PRINT_VERBOSE_STATS (useful for WinCE).
+
+* include/private/gcconfig.h (USE_MMAP): Guard with ifndef.
+
+* allchblk.c (GC_fail_count, GC_large_alloc_warn_interval): Move
+the variable declaration to gc_priv.h.
+* alloc.c (GC_bytes_found, GC_unmap_threshold,
+GC_force_unmap_on_gcollect): Likewise.
+* dyn_load.c (GC_no_win32_dlls, GC_wnt): Likewise.
+* finalize.c (GC_fail_count): Likewise.
+* include/private/gc_locks.h (GC_allocate_ml, GC_lock_holder,
+GC_collecting, GC_mark_lock_holder, GC_need_to_lock): Likewise.
+* include/private/gc_pmark.h (GC_n_mark_procs, GC_mark_stack_size,
+GC_mark_stack_limit, GC_mark_stack_top, GC_mark_stack,
+GC_mark_stack_too_small, GC_mark_state): Likewise.
+* include/private/pthread_support.h (GC_threads,
+GC_thr_initialized, GC_in_thread_creation): Likewise.
+* mallocx.c (GC_bytes_found): Likewise.
+* mark_rts.c (GC_save_regs_ret_val, GC_world_stopped): Likewise.
+* misc.c (GC_unmap_threshold): Likewise.
+* os_dep.c (GC_unmap_threshold): Likewise.
+* pthread_support.c (GC_markers): Likewise.
+* thread_local_alloc.c (GC_gcjobjfreelist,
+GC_gcj_malloc_initialized, GC_gcj_kind): Likewise.
+* win32_threads.c (GC_fault_handler_lock, GC_write_cs,
+GC_dont_query_stack_min, GC_markers, GC_wnt): Likewise.
+* include/private/gc_priv.h (GC_EXTERN): New macro (used mostly as
+a tag for now); defined after "gcconfig.h" inclusion.
+* include/private/gc_priv.h: Use GC_EXTERN instead of "extern"
+keyword for most global variables.
+* alloc.c (GC_copyright): Add the comment about the symbol
+visibility.
+* finalize.c (GC_fo_entries): Likewise.
+* include/private/gc_priv.h (GC_print_stats): Likewise.
+* misc.c (GC_quiet): Likewise.
+* mallocx.c (GC_bytes_allocd_tmp): Make the volatile variable
+STATIC.
+* pthread_support.c (GC_threads): Add explicit zero initializer
+(to make the variable definition differ from the declaration).
+
+* backgraph.c (GC_quiet): Remove the declaration (not needed
+anymore since gc_priv.h is always included).
+* checksums.c (GC_quiet): Likewise.
+* gcj_mlc.c (GC_quiet): Likewise.
+* headers.c (GC_hdr_cache_hits, GC_hdr_cache_misses): Add the
+comment.
+* include/private/gc_hdrs.h (GC_hdr_cache_hits,
+GC_hdr_cache_misses): Likewise.
+* mark.c (GC_first_nonempty): Make the volatile variable STATIC.
+* pthread_stop_world.c (GC_stop_count, GC_world_is_stopped):
+Likewise.
+* win32_threads.c (GC_please_stop, GC_max_thread_index,
+GC_mark_mutex_waitcnt): Likewise.
+
+* pthread_support.c (GC_USE_LD_WRAP): Fix a typo (swapped 'L' and
+'D') in the name.
+
+* gc_dlopen.c (GC_MUST_RESTORE_REDEFINED_DLOPEN): Define if dlopen
+redirection is turned off; turn it on later when dlopen real
+symbol is no longer needed (according to the comment and the same
+as in dyn_load.c).
+* gc_dlopen.c (WRAP_FUNC, REAL_FUNC): Rename to WRAP_DLFUNC and
+REAL_DLFUNC, respectively (to have unique names since the
+definitions may differ from that of the similar ones in
+pthread_support.c).
+* mark.c (source): Undefine the macro when no longer needed.
+* os_dep.c (handler): Rename the type to GC_fault_handler_t (to
+have the unique name across the project).
+* os_dep.c (STAT_BUF_SIZE, STAT_READ); Guard with ifndef; add the
+comment.
+* pthread_support.c (STAT_BUF_SIZE, STAT_READ): Likewise.
+* os_dep.c (sbrk): Undo sbrk() redirection (for ECOS) when no
+longer needed.
+
+* pthread_stop_world.c (pthread_sigmask): Undefine before using
+in GC_print_sig_mask() (only if DEBUG_THREADS); add the comment.
+* win32_threads.c (dlopen, _beginthread): Don't undefine (since
+neither redirected nor used here).
+* win32_threads.c (GC_Thread_Rep): Rename "table_management" to
+"tm" for short; remove "tm_" prefix.
+* win32_threads.c (in_use, next): Don't define the macros; use
+tm.in_use and tm.next fields, respectively (to ease debugging).
+* win32_threads.c (HASH): Rename to PTHREAD_MAP_HASH (to have
+unique name across the project).
+
+* include/private/gc_priv.h (I_HIDE_POINTERS): Define before gc.h
+inclusion.
+* include/private/gc_pmark.h (I_HIDE_POINTERS): Define if gc.h is
+not included yet.
+* finalize.c (I_HIDE_POINTERS): Don't define.
+* include/private/dbg_mlc.h (I_HIDE_POINTERS): Likewise.
+* misc.c (I_HIDE_POINTERS): Likewise.
+* include/private/dbg_mlc.h (HIDE_POINTER, REVEAL_POINTER,
+GC_hidden_pointer): Don't define if HIDE_POINTER is undefined.
+* include/private/gc_pmark.h: Remove the comment about gc_priv.h
+inclusion order.
+
+* dyn_load.c: Include gc_priv.h before using configuration
+information (MACOS).
+* dyn_load.c (GC_must_restore_redefined_dlopen): Rename to
+GC_MUST_RESTORE_REDEFINED_DLOPEN.
+
+* backgraph.c (SET_OH_BG_PTR): Place outermost parenthesis
+properly.
+* darwin_stop_world.c: Replace "if DEBUG_THREADS" with
+"ifdef DEBUG_THREADS".
+* pthread_stop_world.c: Likewise.
+* pthread_support.c: Likewise.
+* include/gc_inline.h: Guard with GC_INLINE_H.
+
+* alloc.c (GC_copyright): Define as const.
+* alloc.c (GC_collect_at_heapsize): Replace "static" with "STATIC"
+(since the name starts with "GC_" prefix).
+* dbg_mlc.c (GC_describe_type_fns): Likewise.
+* dyn_load.c (GC_FirstDLOpenedLinkMap,
+GC_register_dynlib_callback, GC_dyld_sections,
+GC_dyld_name_for_hdr, GC_dyld_image_add, GC_dyld_image_remove):
+Likewise.
+* malloc.c (GC_libpthread_start, GC_libpthread_end,
+GC_libld_start, GC_libld_end): Likewise.
+* mark_rts.c (GC_remove_root_at_pos, GC_rebuild_root_index):
+Likewise.
+* os_dep.c (GC_gww_read_dirty, GC_gww_page_was_dirty,
+GC_gww_page_was_ever_dirty, GC_mprotect_thread_notify,
+GC_mprotect_thread_reply, GC_mprotect_thread, GC_darwin_sigbus,
+GC_forward_exception): Likewise.
+* pthread_support.c (GC_syms_initialized): Likewise.
+* typd_mlc.c (GC_push_typed_structures_proc): Likewise.
+* win32_threads.c (GC_win32_dll_threads,
+GC_register_my_thread_inner, GC_lookup_pthread, GC_get_stack_min,
+GC_waitForSingleObjectInfinite): Likewise.
+* darwin_stop_world.c (GC_use_mach_handler_thread,
+GC_use_mach_handler_thread, GC_mach_threads_count): Replace
+"static" with "STATIC" and add zero initializer.
+* os_dep.c (GC_task_self, GC_ports, GC_mprotect_state,
+GC_sigbus_count): Likewise.
+* headers.c (free_hdr): Replace "static" with GC_INLINE.
+* misc.c (GC_tmp): Rename static variable to fwrite_gc_res.
+* os_dep.c (memory): Rename static variable to ecos_gc_memory.
+* os_dep.c (async_set_pht_entry_from_index): Make static (for
+MPROTECT_VDB case).
+* pthread_support.c (GC_real_pthread_create,
+GC_real_pthread_sigmask, GC_real_pthread_join,
+GC_real_pthread_detach, GC_init_real_syms): Use REAL_FUNC() macro
+for static GC_real_XXX symbols.
+* win32_threads.c (GC_may_be_in_stack): Remove "GC_" prefix.
+
+* alloc.c (GC_finish_collection): Replace getenv() with GETENV().
+* dyn_load.c (GC_init_dyld): Likewise.
+* os_dep.c (GC_print_callers): Likewise.
+* dyn_load.c (GC_dyld_name_for_hdr): Cast _dyld_get_image_name()
+result (since it's always of "struct mach_header" type).
+* dyn_load.c (GC_init_dyld): Cast GC_dyld_image_add and
+GC_dyld_image_remove (to always have the first argument of
+"struct mach_header" pointer type).
+
+* configure.ac: Add threads support for OpenBSD case (threads may
+not work correctly for it).
+
+* acinclude.m4: Rename to m4/gc_set_version.m4.
+* m4/libtool.m4: Delete the file.
+* m4/lt~obsolete.m4: Likewise.
+* m4/ltoptions.m4: Likewise.
+* m4/ltsugar.m4: Likewise.
+* m4/ltversion.m4: Likewise.
+
+* include/private/gcconfig.h: Define DebugBreak() as _exit(-1) for
+x86mingw32ce toolchain to workaround the incorrect DebugBreak()
+declaration in winbase.h (the workaround would turn into a no-op
+when DebugBreak() will be defined as a macro in the toolchain).
+
+* include/private/gcconfig.h: Recognize __i386__ if WinCE (for
+x86mingw32ce toolchain).
+* include/private/gcconfig.h (NO_GETENV): Don't define for CeGCC
+toolchain (or if already defined).
+* include/private/gcconfig.h (NO_GETENV_WIN32): New macro (always
+defined for WinCE or if NO_GETENV is defined).
+* misc.c (GC_CreateLogFile): Use NO_GETENV_WIN32 macro instead of
+NO_GETENV one.
+
+* configure.ac: Add AC_CONFIG_MACRO_DIR([m4]).
+* Makefile.am: Add "ACLOCAL_AMFLAGS = -I m4".
+* libtool.m4: Remove.
+* m4/libtool.m4: New file (generated).
+* m4/lt~obsolete.m4: Likewise.
+* m4/ltoptions.m4: Likewise.
+* m4/ltsugar.m4: Likewise.
+* m4/ltversion.m4: Likewise.
+
+* include/gc.h (GC_UNDERSCORE_STDCALL): Recognize new macro;
+prefix GC_CreateThread and GC_ExitThread with '_' if defined.
+* doc/README.macros (GC_UNDERSCORE_STDCALL): Document.
+
+* alloc.c (GC_collect_or_expand): Add "retry" argument; add the
+comments; don't use "default" stop_func on a retry if
+GC_dont_expand.
+* alloc.c (GC_allocobj): Pass "retry" argument to
+GC_collect_or_expand().
+* malloc.c (GC_alloc_large): Likewise.
+* include/private/gc_priv.h (GC_collect_or_expand): Move the
+declaration to malloc.c; add "retry" argument.
+
+* alloc.c (GC_start_call_back): Move the variable definition from
+misc.c.
+* include/private/gc_priv.h (GC_start_call_back): Remove the
+declaration.
+* alloc.c (GC_notify_full_gc): Remove unnecessary cast of 0.
+* alloc.c (GC_try_to_collect_inner): Also call stop_func at the
+beginning of the function.
+* include/gc.h (GC_try_to_collect): Refine the comment about
+stop_func.
+
+* alloc.c (GC_default_stop_func, GC_try_to_collect_general,
+GC_gcollect): Add the comment.
+* alloc.c (GC_try_to_collect_general): Move the assertion on
+stop_func != 0 to GC_try_to_collect().
+* alloc.c (GC_try_to_collect_general): If stop_func == 0 then use
+GC_default_stop_func instead (holding the lock).
+* alloc.c (GC_gcollect): Pass 0 as stop_func instead of
+GC_default_stop_func (to prevent data races).
+
+* Makefile.direct: Move "define arguments" documentation to
+doc/README.macros; add reference to doc/README.macros.
+* Makefile.dj: Change the documentation reference to
+doc/README.macros.
+* README.QUICK: Likewise.
+* configure.ac: Likewise.
+* allchblk.c: Remove unnecessary "-D" from the comment.
+* doc/README.macros: Likewise.
+* README.environment: Likewise.
+* include/gc.h: Likewise.
+* include/gc_inline.h: Likewise.
+* include/private/gcconfig.h: Likewise.
+* README.QUICK: Fix a typo.
+
+* misc.c (GC_CreateLogFile): Use FILE_ATTRIBUTE_NORMAL for
+CreateFile(); don't immediately flush every write if very verbose.
+
+* doc/README.win32: Replace ".exe.log" to ".gc.log".
+* doc/README.win64: Likewise.
+* doc/README.win64: Fix a typo.
+* misc.c (GC_CreateLogFile): Strip executable file extension for
+the log file; use ".gc.log" extension (instead of ".log").
+
+* include/gc_config_macros.h: Avoid the redefinition of
+GC_xxx_THREADS macros.
+
+* alloc.c (GC_try_to_collect_general): Change the type of "result"
+local variable to GC_bool.
+
+* include/gc_config_macros.h: Use old behavior for FreeBSD and
+NetBSD platform detection code (check that other GC_xxx_THREADS
+are undefined); add FIXME.
+
+* include/gc_config_macros.h: Rearrange the platform detection
+code (GC_WIN32_PTHREADS implies GC_WIN32_THREADS; define
+GC_THREADS first if GC_XXX_THREADS already set; define proper
+GC_XXX_THREADS if GC_THREADS; define GC_PTHREADS in a single
+place; define _REENTRANT if posix threads except for Win32).
+
+* alloc.c (GC_try_to_collect_general): New function (move the code
+from GC_try_to_collect, pass force_unmap argument).
+* alloc.c (GC_try_to_collect, GC_gcollect): Call
+GC_try_to_collect_general().
+* alloc.c (GC_gcollect_and_unmap): New public function.
+* include/gc.h (GC_gcollect_and_unmap): New function declaration.
+* tests/test.c (window_proc): Call GC_gcollect_and_unmap() on
+WM_HIBERNATE event (instead of GC_set_force_unmap_on_gcollect()
+and GC_gcollect()).
+
+* include/gc.h (GC_allow_register_threads, GC_register_my_thread,
+GC_unregister_my_thread, GC_malloc_many): Refine the comment.
+* include/gc.h (GC_malloc_many, GC_NEXT): Declare unconditionally
+(that is, don't depend on GC_THREADS macro).
+* include/gc.h: Don't check for __CYGWIN32__ and __CYGWIN__ along
+with a check for GC_PTHREADS (since the former implies the
+latter).
+
+* include/gc.h (GC_SOLARIS_THREADS): Don't check for.
+* include/gc.h (GC_MIN, GC_MAX): Don't define.
+* mallocx.c (GC_malloc_many): Add comment to #endif.
+
+* configure.ac: Drop the subdir-objects Automake option, since
+it's incompatible with picking source files from libatomic_ops.
+
+* allchblk.c (GC_fail_count, GC_large_alloc_warn_interval): Add
+"extern" keyword to a global variable declaration (some compilers
+require it).
+* alloc.c (GC_bytes_found, GC_unmap_threshold,
+GC_force_unmap_on_gcollect): Likewise.
+* dyn_load.c (GC_no_win32_dlls, GC_wnt): Likewise.
+* finalize.c (GC_fail_count): Likewise.
+* include/private/gc_hdrs.h (GC_hdr_cache_hits,
+GC_hdr_cache_misses): Likewise.
+* mallocx.c (GC_bytes_found): Likewise.
+* mark_rts.c (GC_save_regs_ret_val, GC_world_stopped): Likewise.
+* misc.c (GC_unmap_threshold): Likewise.
+* os_dep.c (GC_unmap_threshold, GC_old_allocator): Likewise.
+* pthread_support.c (GC_markers): Likewise.
+* thread_local_alloc.c (GC_gcjobjfreelist,
+GC_gcj_malloc_initialized, GC_gcj_kind): Likewise.
+* win32_threads.c (GC_fault_handler_lock, GC_write_cs,
+GC_dont_query_stack_min, GC_markers, GC_wnt): Likewise.
+
+* tests/huge_test.c: Define GC_IGNORE_WARN (if not defined) to
+suppress misleading GC "Out of Memory!" warning printed on every
+GC_MALLOC(LONG_MAX) call.
+* tests/huge_test.c: Include "gc.h" instead of <gc.h>.
+* tests/huge_test.c (main): Replace K&R-style function definition
+with the ANSI C one.
+
+* dyn_load.c (GC_register_dynamic_libraries): Always use
+lpMaximumApplicationAddress value for WinCE (even for old
+versions).
+* os_dep.c (VER_PLATFORM_WIN32_CE): Define if not in winbase.h.
+* os_dep.c (GC_dont_query_stack_min): New global variable (only if
+WinCE and THREADS).
+* os_dep.c (GC_setpagesize): Adjust lpMaximumApplicationAddress
+for WinCE (prior to version 6) if not _WIN32_WCE_EMULATION; set
+GC_dont_query_stack_min for older WinCE (prior to version 5).
+* win32_threads.c (GC_dont_query_stack_min): Declare.
+* win32_threads.c (GC_get_stack_min): Rename the macro to
+GC_wince_evaluate_stack_min for WinCE; update the comment.
+* win32_threads.c (GC_push_stack_for, GC_get_next_stack): Use
+GC_wince_evaluate_stack_min() instead of GC_get_stack_min() for
+WinCE and don't update thread's last_stack_min value (only if
+GC_dont_query_stack_min).
+* win32_threads.c (GC_push_stack_for): Skip assertion for WinCE if
+GC_dont_query_stack_min (since the evaluated stack_min value may
+be incorrect if the stack is bigger than 64 KiB).
+
+* gc_dlopen.c (GC_dlopen): Add function redirector (only if
+GC_USE_LD_WRAP).
+* include/gc.h: Include "gc_pthread_redirects.h" even if
+GC_USE_LD_WRAP or GC_NO_THREAD_REDIRECTS.
+* include/gc_pthread_redirects.h (GC_PTHREAD_REDIRECTS_H): Don't
+define and check for (since included only from gc.h).
+* include/gc_pthread_redirects.h: Declare "GC_" symbols even if
+GC_USE_LD_WRAP or GC_NO_THREAD_REDIRECTS.
+* include/gc_pthread_redirects.h: Include signal.h only to get
+sigset_t definition.
+
+* Makefile.direct: Document GC_REGISTER_MEM_PRIVATE.
+* mark_rts.c (GC_is_tmp_root): Define also for WinCE unless
+NO_DEBUGGING (that is, replace _WIN32_WCE_EMULATION with MSWINCE).
+* os_dep.c (GC_sysinfo): Remove explicit global variable
+initialization to "{0}" (revert back the previous change) since it
+might produce a warning.
+
+* allchblk.c (GC_large_alloc_warn_interval): Move declaration from
+gc_priv.h.
+* allchblk.c (GC_large_alloc_warn_suppressed): Move definition
+from misc.c; define as STATIC.
+* include/private/gc_priv.h (GC_large_alloc_warn_interval,
+GC_large_alloc_warn_suppressed): Remove declaration.
+* alloc.c (GC_bytes_found): Add "defined in" comment.
+* mallocx.c (GC_bytes_found): Likewise.
+* misc.c (GC_unmap_threshold): Likewise.
+* os_dep.c (GC_old_allocator): Likewise.
+* pthread_support.c (GC_markers): Likewise.
+* thread_local_alloc.c (GC_gcjobjfreelist,
+GC_gcj_malloc_initialized, GC_gcj_kind): Likewise.
+* win32_threads.c (GC_markers): Likewise.
+* alloc.c (GC_start_time): Explicitly initialize to 0 or NULL (to
+be distinctive from a variable declaration).
+* backgraph.c (GC_max_height, GC_deepest_obj): Likewise.
+* blacklst.c (GC_old_normal_bl, GC_incomplete_normal_bl,
+GC_old_stack_bl, GC_incomplete_stack_bl): Likewise.
+* checksums.c (GC_faulted, GC_n_dirty_errors,
+GC_n_faulted_dirty_errors, GC_n_changed_errors, GC_n_clean,
+GC_n_dirty, GC_bytes_in_used_blocks): Likewise.
+* dbg_mlc.c (GC_smashed): Likewise.
+* finalize.c (GC_old_dl_entries): Likewise.
+* gcj_mlc.c (GC_gcj_kind, GC_gcj_debug_kind, GC_gcjobjfreelist,
+GC_gcjdebugobjfreelist): Likewise.
+* mach_dep.c (GC_save_regs_ret_val): Likewise.
+* mark.c (GC_n_rescuing_pages, GC_mark_stack, GC_mark_stack_limit,
+GC_mark_stack_top): Likewise.
+* misc.c (GC_min_sp, GC_high_water, GC_bytes_allocd_at_reset):
+Likewise.
+* os_dep.c (GC_data_start, GC_page_size, GC_sysinfo,
+GC_old_segv_handler, GC_old_bus_handler,
+GC_old_bus_handler_used_si, GC_old_segv_handler_used_si,
+GC_proc_buf, GC_proc_fd, GC_vd_base): Likewise.
+* pthread_stop_world.c (GC_stop_count, GC_stopping_pid): Likewise.
+* reclaim.c (GC_leaked): Likewise.
+* typd_mlc.c (GC_explicit_kind, GC_array_kind, GC_ext_descriptors,
+GC_typed_mark_proc_index, GC_array_mark_proc_index,
+GC_eobjfreelist, GC_arobjfreelist): Likewise.
+* win32_threads.c (GC_pthread_map_cache, GC_marker_cv,
+GC_marker_Id): Likewise.
+* dbg_mlc.c (GC_smashed, GC_n_smashed): Define as STATIC.
+* gcj_mlc.c (GC_gcjdebugobjfreelist): Likewise.
+* os_dep.c (GC_vd_base): Likewise.
+* pthread_support.c (GC_mark_threads): Likewise.
+* reclaim.c (GC_leaked): Likewise.
+* typd_mlc.c (GC_bm_table): Likewise.
+* mark_rts.c (GC_save_regs_ret_val): Change declaration type to
+that of definition; add "defined in" comment.
+* mark_rts.c (GC_push_current_stack): Remove unnecessary cast for
+GC_save_regs_ret_val.
+* misc.c (GC_check_heap, GC_print_all_smashed,
+GC_start_call_back): Remove unnecessary cast (of 0).
+* misc.c (GC_LARGE_ALLOC_WARN_INTERVAL): New tuning macro.
+* misc.c (GC_large_alloc_warn_interval): Initialize to
+GC_LARGE_ALLOC_WARN_INTERVAL value.
+* misc.c (GC_tmp): Change to "static".
+* os_dep.c (GC_mprotect_state): Define as static.
+* pthread_support.c (dummy_thread_local): Prefix with "GC_".
+* win32_threads.c (WinMain): Remove FIXME for WinCE.
+
+* os_dep.c (PROTECT, UNPROTECT): Use distinct ABORT messages.
+
+* configure.ac: Rewrite the tests for external or internal
+libatomic_ops.
+* configure.ac: In particular, drop the symbolic links. Add option
+--with-libatomic-ops for forced selection.
+* Makefile.am: Adjust the path of source files from libatomic_ops
+to not use the links.
+* Makefile.am (libgc_la_LIBADD): Add $(ATOMIC_OPS_LIBS). This will
+be empty if we use the bundled AO sources.
+
+* Makefile.am: Strip version suffix for libatomic_ops directory.
+* build_atomic_ops.sh: Likewise.
+* build_atomic_ops.sh.cygwin: Likewise.
+* configure_atomic_ops.sh: Likewise.
+* Makefile.direct: Remove AO_VERSION definition; strip version
+suffix for libatomic_ops directory.
+* NT_STATIC_THREADS_MAKEFILE: Likewise.
+* NT_X64_STATIC_THREADS_MAKEFILE: Likewise.
+* NT_X64_THREADS_MAKEFILE: Likewise.
+* gc.mak: Likewise.
+
+* libatomic_ops: Rename from "libatomic_ops-1.2".
+
+* alloc.c (GC_version): Add "const" keyword.
+* alloc.c (GC_get_version): New public function.
+* include/gc.h (GC_get_version): New function declaration; update
+the comment for the GC version.
+
+* include/private/gc_locks.h (GC_allocate_ml, GC_lock_holder,
+GC_collecting, GC_mark_lock_holder, GC_need_to_lock): Use "extern"
+(for the global variable declaration) again.
+* include/private/gc_pmark.h (GC_n_mark_procs, GC_mark_stack_size,
+GC_mark_stack_limit, GC_mark_stack_top, GC_mark_stack,
+GC_mark_stack_too_small, GC_mark_state): Likewise.
+* include/private/gcconfig.h (GC_register_stackbottom): Likewise.
+* include/private/pthread_support.h (GC_threads,
+GC_thr_initialized, GC_in_thread_creation): Likewise.
+* include/private/gc_priv.h: Likewise.
+
+* real_malloc.c: Include private/config.h if HAVE_CONFIG_H.
+
+* allchblk.c (GC_hblkfreelist): Define as STATIC.
+* blacklst.c (GC_total_stack_black_listed): Likewise.
+* include/private/gc_priv.h (GC_hblkfreelist, GC_stopped_mark,
+GC_total_stack_black_listed, GC_push_stubborn_structures): Remove
+declaration.
+* mark_rts.c (GC_stopped_mark): Add declaration (only if
+THREAD_LOCAL_ALLOC).
+* allchblk.c (GC_fail_count): Move the declaration out of
+GC_allochblk_nth(); remove "extern".
+* alloc.c (IF_THREADS): Remove unused macro.
+* alloc.c (GC_world_stopped): Define only if THREAD_LOCAL_ALLOC.
+* alloc.c (GC_stopped_mark): Set GC_world_stopped value only if
+THREAD_LOCAL_ALLOC.
+* alloc.c (GC_bytes_found, GC_collection_in_progress,
+GC_check_tls, GC_unmap_threshold, GC_force_unmap_on_gcollect):
+Remove K&R-style "extern" for the declaration.
+* dbg_mlc.c (GC_free_inner): Likewise.
+* dyn_load.c (GC_repeat_read, GC_roots_present, GC_is_heap_base,
+GC_get_next_stack, GC_no_win32_dlls, GC_wnt): Likewise.
+* finalize.c (GC_fail_count): Likewise.
+* include/private/gc_hdrs.h (GC_hdr_cache_hits,
+GC_hdr_cache_misses): Likewise.
+* include/private/gc_locks.h (GC_allocate_ml, GC_lock_holder,
+GC_lock, GC_collecting, GC_mark_lock_holder, GC_need_to_lock):
+Likewise.
+* include/private/gc_pmark.h (GC_mark_procs, GC_n_mark_procs,
+GC_mark_stack_size, GC_mark_stack_limit, GC_mark_stack_top,
+GC_mark_stack, GC_mark_stack_too_small, GC_mark_state): Likewise.
+* include/private/gc_priv.h (GC_current_warn_proc, GC_obj_kinds,
+GC_n_kinds, GC_fo_entries, GC_n_heap_sects, GC_n_memory,
+GC_page_size, GC_sysinfo, GC_black_list_spacing,
+GC_objects_are_marked, GC_incremental, GC_dirty_maintained,
+GC_root_size, GC_debugging_started, GC_large_alloc_warn_interval,
+GC_large_alloc_warn_suppressed, GC_blocked_sp,
+GC_activation_frame, GC_push_other_roots,
+GC_push_finalizer_structures, GC_push_thread_structures,
+GC_push_typed_structures, GC_start_call_back, GC_is_initialized,
+GC_check_heap, GC_print_all_smashed, GC_print_all_errors,
+GC_print_heap_obj, GC_have_errors, GC_print_stats,
+GC_dump_regularly, GC_backtraces, GC_print_back_height,
+GC_debug_generic_malloc_inner,
+GC_debug_generic_malloc_inner_ignore_off_page,
+GC_fl_builder_count, GC_mark_no, GC_help_marker,
+GC_setup_temporary_fault_handler, GC_reset_fault_handler): Likewise.
+* include/private/gcconfig.h (GC_SysVGetDataStart,
+GC_FreeBSDGetDataStart, GC_register_stackbottom,
+GC_MacTemporaryNewPtr, GC_amiga_get_mem): Likewise.
+* include/private/pthread_support.h (GC_threads,
+GC_thr_initialized, GC_in_thread_creation): Likewise.
+* malloc.c (GC_text_mapping): Likewise.
+* mallocx.c (GC_bytes_found): Likewise.
+* mark.c (GC_check_dirty, GC_started_thread_while_stopped): Likewise.
+* mark_rts.c (GC_save_regs_ret_val): Likewise.
+* misc.c (GC_clear_stack_inner, GC_init_parallel, GC_init_win32,
+GC_setpagesize, GC_init_linux_data_start,
+GC_set_and_save_fault_handler, GC_unmap_threshold): Likewise.
+* os_dep.c (GC_unmap_threshold, GC_push_all_stacks,
+GC_darwin_register_mach_handler_thread): Likewise.
+* pthread_support.c (GC_markers, GC_collection_in_progress):
+Likewise.
+* tests/test.c (GC_amiga_free_all_mem): Likewise.
+* thread_local_alloc.c (GC_gcjobjfreelist,
+GC_gcj_malloc_initialized, GC_gcj_kind): Likewise.
+* win32_threads.c (GC_write_fault_handler, GC_gww_dirty_init,
+GC_fault_handler_lock, GC_write_cs, GC_markers): Likewise.
+* misc.c (GC_read, GC_register_finalizer_no_order, GC_init_dyld):
+Move the declaration out of GC_init(); remove "extern".
+* os_dep.c (GC_abort): Add the comment; add workaround to suppress
+compiler "unreachable code" warnings for ABORT callers (where
+ABORT is followed by a dummy return statement).
+* os_dep.c (GC_old_allocator): Move the declaration out of
+GC_default_push_other_roots(); remove "extern".
+* darwin_stop_world.c (GC_mprotect_stop, GC_mprotect_resume):
+Move the declaration out of GC_stop_world() and GC_start_world()
+(only if MPROTECT_VDB); remove "extern".
+
+* win32_threads.c (GC_get_stack_min, GC_push_stack_for,
+GC_get_next_stack): Recognize _WIN32_WCE_EMULATION macro (used for
+WinCE emulation and for custom WinCE 6 devices); add the comment.
+* win32_threads.c (GC_get_stack_min): Cast pointer to word instead
+of DWORD.
+* win32_threads.c (GC_get_next_stack): Don't use and maintain the
+latest known stack_min value for WinCE (if GC_get_stack_min is
+defined as a macro); update the comments.
+* win32_threads.c (GC_wnt): Don't declare for WinCE.
+
+* Makefile.direct: Document EMPTY_GETENV_RESULTS.
+* gcj_mlc.c (GC_clear_stack): Remove declaration.
+* malloc.c (GC_clear_stack): Likewise.
+* mallocx.c (GC_clear_stack): Likewise.
+* typd_mlc.c (GC_clear_stack): Likewise.
+* gcj_mlc.c (GENERAL_MALLOC, GENERAL_MALLOC_IOP): Rename to
+GENERAL_MALLOC_INNER and GENERAL_MALLOC_INNER_IOP, respectively;
+remove "lb" unnecessary cast to word.
+* include/private/gc_priv.h (GC_clear_stack): Add declaration.
+* include/private/gc_priv.h (GENERAL_MALLOC, GENERAL_MALLOC_IOP):
+Move common declaration from typd_mlc.c and malloc.c; remove
+unnecessary result and "lb" parameter casts.
+* include/private/thread_local_alloc.h: Guard against duplicate
+header file inclusion.
+* os_dep.c (USE_MUNMAP): Replace "-->" with an error directive for
+the case when USE_MMAP is not defined.
+* pthread_support.c (GC_is_thread_tsd_valid): New internal
+function (only if GC_ASSERTIONS and THREAD_LOCAL_ALLOC); move the
+code from thread-local GC_malloc(); add FIXME for the condition.
+* win32_threads.c (GC_is_thread_tsd_valid): Likewise.
+* thread_local_alloc.c (GC_gcjobjfreelist): Change the type (to
+match that of its definition).
+* thread_local_alloc.c (GC_destroy_thread_local): Add a cast for
+GC_gcjobjfreelist.
+* thread_local_alloc.c (GC_lookup_thread, GC_lookup_thread_inner):
+Remove unused declaration; don't include pthread.h.
+* thread_local_alloc.c (GC_is_thread_tsd_valid): New declaration
+(only if GC_ASSERTIONS).
+* thread_local_alloc.c (GC_malloc): Use GC_is_thread_tsd_valid()
+instead of GC_lookup_thread().
+* win32_threads.c (GC_lookup_thread_inner): Define as STATIC.
+* win32_threads.c (UNPROTECT): Rename to UNPROTECT_THREAD (to have
+id different from that in os_dep.c).
+
+* allchblk.c (GC_enough_large_bytes_left): Replace "inline static"
+with GC_INLINE.
+* include/private/gc_priv.h (fixed_getenv): Likewise.
+* alloc.c (GC_max, GC_min): Replace "static INLINE" with
+GC_INLINE.
+* mark_rts.c (rt_hash): Likewise.
+* win32_threads.c (GC_get_max_thread_index): Likewise.
+* include/private/gc_priv.h (INLINE): Prefix with "GC_"; include
+"static"; define for Sun CC; define for VC++ (and other
+compilers).
+* pthread_support.c: Don't define __inline__ for non-GNU compilers
+(not needed anymore).
+
+* NT_THREADS_MAKEFILE: Remove file (since it duplicates gc.mak).
+* Makefile.in: Remove reference to NT_THREADS_MAKEFILE.
+* Makefile.am: Likewise.
+* Makefile.dj: Likewise.
+* Makefile.direct: Likewise.
+* doc/README.win32: Add reference to gc.mak.
+* NT_X64_THREADS_MAKEFILE: Likewise.
+
+* Makefile.direct: Remove references to acinclude.m4, libtool.m4.
+
+* autogen.sh: Update.
+
+* Makefile.am: Don't add libtool.m4 to EXTRA_DIST.
+* acinclude.m4: Fix underquoting of GC_SET_VERSION.
+* README.QUICK: Update information for Makefile.
+* Makefile.am: Do not distribute the substituted bdw-gc.pc.
+* configure.ac: Add AM conditional analog to KEEP_BACK_PTRS.
+* tests/tests.am: Use it here to conditionally enable tracetest
+when possible.
+
+* dyn_load.c (GC_wnt): Update the comment.
+* dyn_load.c (GC_register_dynamic_libraries): Add the comment for
+_WIN32_WCE_EMULATION; recognize GC_REGISTER_MEM_PRIVATE (new
+macro); call GC_is_heap_base() only if check for Type succeeded.
+
+* mark_rts.c (GC_is_tmp_root): Don't define unless NO_DEBUGGING;
+update the comment.
+* include/private/gc_priv.h (GC_is_tmp_root): Remove declaration.
+
+* include/private/gcconfig.h (CANCEL_SAFE, IF_CANCEL): new macros.
+* include/private/gc_priv.h (DISABLE_CANCEL, RESTORE_CANCEL,
+ASSERT_CANCEL_DISABLED): New macros.
+* alloc.c (GC_maybe_gc): Assert cancellation disabled.
+(GC_collect_a_little_inner,GC_try_to_collect, GC_collect_or_expand):
+Disable cancellation.
+(GC_add_to_our_memory): Check for overflow.
+* misc.c (GC_cancel_disable_count): declare.
+(GC_init, GC_write): Disable cancellation.
+(GC_init): Remove redundant GC_is_initialized test.
+* os_dep.c (GC_repeat_read): Assert cancellation disabled.
+(GC_get_stack_base): Disable cancellation.
+* pthread_stop_world.c (GC_suspend_handler_inner): Disable
+cancellation.
+* pthread_support.c (GC_mark_thread): Permanently disable
+cancellation.
+(GC_wait_for_gc_completion, GC_wait_builder, GC_wait_marker):
+Assert cancellation disabled.
+(fork handling): Disable cancellation, fix comment.
+(GC_pthread_create): Disable cancellation.
+(GC_unregister_my_thread): Disable cancellation.
+* Makefile.direct: Document NO_CANCEL_SAFE.
+
+* Makefile: Remove outdated file (Makefile.direct should be used
+instead).
+
+* include/gc.h (GC_use_DllMain): Refine the comment.
+
+* configure.ac: Add documentation to AC_DEFINE for GC_THREADS and
+EMPTY_GETENV_RESULTS.
+* configure.ac: Fix a typo.
+* Makefile.am: Likewise.
+
+* checksums.c (GC_checksum, GC_update_check_page): Remove
+"register" keyword in local variable declarations (for the code
+used only for debugging or which is not time-critical).
+* dbg_mlc.c (GC_has_other_debug_info, GC_store_debug_info,
+GC_store_debug_info_inner, GC_check_annotated_obj, GC_print_obj,
+GC_print_smashed_obj, GC_debug_end_stubborn_change,
+GC_debug_invoke_finalizer): Likewise.
+* dyn_load.c (GC_register_dynamic_libraries): Likewise.
+* mallocx.c (GC_realloc): Likewise.
+* mark_rts.c (GC_print_static_roots, GC_is_static_root,
+GC_clear_roots): Likewise.
+* misc.c (GC_write): Likewise.
+* os_dep.c (GC_print_callers): Likewise.
+* dyn_load.c (GC_register_dynamic_libraries): Rename "i" local
+variable to "j" for the nested loop (just not to hide the similar
+variable in the outer one).
+* mark_rts.c (GC_print_static_roots): Output an error message
+using GC_err_printf() (instead of GC_printf()).
+
+* configure.ac: Move include flag from ${INCLUDE} ...
+* Makefile.am: ... to AM_CPPFLAGS and also add the build directory.
+* configure.ac: Call AM_CONFIG_HEADER([include/private/config.h]).
+* configure.ac: Add documentation to all AC_DEFINE either directly
+or using AH_TEMPLATE.
+
+* win32_threads.c (GC_waitForSingleObjectInfinite): New static
+function (only if GC_WINMAIN_REDIRECT).
+* win32_threads.c (WinMain): Call GC_waitForSingleObjectInfinite()
+thru GC_do_blocking() instead of calling WaitForSingleObject()
+directly.
+
+* pthread_support.c (start_mark_threads): Refine printed message.
+* win32_threads.c (GC_thr_init): Likewise.
+
+* Makefile.direct (GC_WINMAIN_REDIRECT): Add the comment for.
+* Makefile.direct (NO_GETENV): Update the comment.
+* include/gc.h (GC_WINMAIN_WINCE_LPTSTR): Remove macro.
+* include/gc.h (GC_WinMain): Remove declaration.
+* include/gc.h (WinMain): Define (as GC_WinMain) if and only if
+GC_WINMAIN_REDIRECT.
+* tests/test.c (GC_COND_INIT): Define as GC_INIT() also in case of
+WinCE target unless GC_WINMAIN_REDIRECT is defined.
+* tests/test.c (WINMAIN_LPTSTR): New macro.
+* tests/test.c (WinMain): Use WINMAIN_LPTSTR instead of LP[W]STR
+and GC_WINMAIN_WINCE_LPTSTR.
+* win32_threads.c (start_mark_threads): Add the comment for
+MARK_THREAD_STACK_SIZE.
+* win32_threads.c: Recognize new GC_WINMAIN_REDIRECT macro.
+* win32_threads.c (WINMAIN_LPTSTR, WINMAIN_THREAD_STACK_SIZE): New
+macro (only if GC_WINMAIN_REDIRECT).
+* win32_threads.c: Undefine WinMain macro if GC_WINMAIN_REDIRECT.
+* win32_threads.c (GC_WinMain): Add prototype (only if
+GC_WINMAIN_REDIRECT).
+* win32_threads.c (main_thread_args, WinMain): Rename
+GC_WINMAIN_WINCE_LPTSTR to WINMAIN_LPTSTR.
+* win32_threads.c (WinMain): Call GC_INIT() instead of GC_init();
+use WINMAIN_THREAD_STACK_SIZE.
+* win32_threads.c (WinMain): Call GC_deinit() and
+DeleteCriticalSection() only if WinCE; add FIXME.
+
+* os_dep.c (GC_get_main_stack_base): add assertion for mem_base
+value returned by GC_get_stack_base().
+
+* Makefile.direct (MUNMAP_THRESHOLD, GC_FORCE_UNMAP_ON_GCOLLECT):
+Add the comment for.
+* alloc.c (GC_unmap_threshold, GC_force_unmap_on_gcollect):
+Declare external variable (only if USE_MUNMAP).
+* alloc.c (GC_try_to_collect): Temporarily set GC_unmap_threshold
+value to 1 if GC_force_unmap_on_gcollect and restore it before
+unlocking (only if USE_MUNMAP).
+* doc/README.environment (GC_FORCE_UNMAP_ON_GCOLLECT): Add
+information for.
+* include/gc.h (GC_set_force_unmap_on_gcollect,
+GC_get_force_unmap_on_gcollect): New public function prototype.
+* include/gc.h (GC_FORCE_UNMAP_ON_GCOLLECT): New macro is
+recognized.
+* misc.c (GC_FORCE_UNMAP_ON_GCOLLECT): Likewise.
+* include/gc.h (GC_INIT_CONF_FORCE_UNMAP_ON_GCOLLECT): New
+internal macro (used by GC_INIT only).
+* misc.c (GC_force_unmap_on_gcollect): New global variable.
+* misc.c (GC_init): Recognize new "GC_FORCE_UNMAP_ON_GCOLLECT"
+environment variable (and set GC_force_unmap_on_gcollect).
+* misc.c (GC_set_force_unmap_on_gcollect,
+GC_get_force_unmap_on_gcollect): New public function.
+* tests/test.c (window_proc): Call GC_set_force_unmap_on_gcollect
+to force the mode on if WM_HIBERNATE; restore the mode after
+GC_gcollect().
+
+* Makefile.direct (LARGE_CONFIG): Update information.
+* include/gc.h (GC_stop_func): Refine the comment.
+
+* configure.ac: Use EMPTY_GETENV_RESULTS instead of NO_GETENV for
+Win32 (workaround for Wine bug).
+
+* allchblk.c (GC_freehblk): Adjust local variables indentation.
+* mallocx.c (GC_generic_malloc_many): Likewise.
+* typd_mlc.c (GC_malloc_explicitly_typed_ignore_off_page,
+GC_calloc_explicitly_typed): Likewise.
+* typd_mlc.c (GC_make_array_descriptor): Remove unnecessary
+brackets.
+
+* configure.ac: Replace GC_WIN32_THREADS with GC_THREADS.
+* configure.ac: Process enable_parallel_mark option for Cygwin and
+Win32; define THREAD_LOCAL_ALLOC for Win32.
+
+* include/private/gc_priv.h: Define AO_ASSUME_WINDOWS98 if
+PARALLEL_MARK (required for VC++ x86).
+
+* dbg_mlc.c (GC_generate_random_backtrace): Call
+GC_try_to_collect(GC_never_stop_func) instead of GC_gcollect();
+if GC is disabled then print error message and return.
+* include/gc.h (GC_try_to_collect): Refine the comment.
+* include/private/gc_priv.h (GC_never_stop_func): Fix return type;
+refine the comment.
+
+* add_gc_prefix.c: Move the file to the new "extra" directory.
+* AmigaOS.c: Likewise.
+* gcname.c: Likewise.
+* if_mach.c: Likewise.
+* if_not_there.c: Likewise.
+* MacOS.c: Likewise.
+* msvc_dbg.c: Likewise.
+* setjmp_t.c: Likewise.
+* threadlibs.c: Likewise.
+* EMX_MAKEFILE: Prepend setjmp_t.c with "extra" directory.
+* Makefile: Prepend AmigaOS.c, MacOS.c, add_gc_prefix.c, gcname.c,
+if_mach.c, if_not_there.c, msvc_dbg.c, setjmp_t.c, threadlibs.c
+with "extra" directory.
+* Makefile.am: Likewise.
+* Makefile.direct: Likewise.
+* Makefile.dj: Likewise.
+* Makefile.in: Likewise.
+* NT_MAKEFILE: Prepend msvc_dbg.obj with "extra" directory.
+* NT_STATIC_THREADS_MAKEFILE: Likewise.
+* NT_X64_STATIC_THREADS_MAKEFILE: Likewise.
+* NT_X64_THREADS_MAKEFILE: Likewise.
+* NT_THREADS_MAKEFILE: Prepend msvc_dbg.c with "extra" directory.
+* gc.mak: Likewise.
+* PCR-Makefile: Prepend if_mach.c, if_not_there.c with "extra"
+directory.
+* SMakefile.amiga: Prepend AmigaOS.c, setjmp_t.c with "extra"
+directory.
+* doc/simple_example.html: Update for threadlibs.c.
+* os_dep.c: Prepend included AmigaOS.c with "extra" directory.
+
+* include/gc.h (GC_do_blocking, GC_call_with_gc_active): New
+function prototype.
+* include/private/gc_priv.h (STOP_WORLD): Replace a no-op (for the
+single-threaded case) with an assertion check for the state to be
+not a "do-blocking" one.
+* include/private/gc_priv.h (blocking_data): Move the structure
+definition from pthread_support.c; change "fn" return type to void
+pointer.
+* include/private/gc_priv.h (GC_activation_frame_s): New structure
+type.
+* include/private/gc_priv.h (GC_push_all_stack_frames): New
+function declaration (only if THREADS).
+* include/private/gc_priv.h (GC_world_stopped): Don't declare
+unless THREADS.
+* include/private/gc_priv.h (GC_blocked_sp,
+GC_activation_frame_s): New declaration (only if not THREADS).
+* include/private/gc_priv.h (GC_push_all_register_frames): New
+function declaration (only for IA-64).
+* include/private/gc_priv.h (NURSERY, GC_push_proc): Remove
+obsolete (unused) symbols.
+* include/private/gc_priv.h (GC_push_all_stack_partially_eager):
+Remove declaration (since it is static now).
+* mark_rts.c (GC_push_all_stack_partially_eager): Move from mark.c
+(for code locality) and make STATIC.
+* mark_rts.c (GC_push_all_register_frames): New function (only for
+IA-64).
+* mark_rts.c (GC_push_all_stack_frames): New function (only if
+THREADS).
+* mark_rts.c (GC_add_trace_entry): New function prototype (used by
+GC_push_all_stack_partially_eager(), only if TRACE_BUF).
+* mark_rts.c (GC_push_all_stack_part_eager_frames): New function.
+* mar_rts.c (GC_save_regs_ret_val): Move the declaration out of a
+function body (only for IA-64).
+* mark_rts.c (GC_push_current_stack): Call
+GC_push_all_stack_part_eager_frames() instead of
+GC_push_all_stack_partially_eager().
+* mark_rts.c (GC_push_current_stack): Call
+GC_push_all_register_frames() instead of GC_push_all_eager() for
+IA-64 backing store.
+* misc.c (GC_do_blocking_inner): Declare function (if THREADS
+only).
+* misc.c (GC_blocked_sp, GC_blocked_register_sp,
+GC_activation_frame): New global variables (only if not THREADS).
+* misc.c (GC_call_with_gc_active, GC_do_blocking_inner): New API
+function (only if not THREADS).
+* misc.c (GC_do_blocking): Move the function from
+pthread_support.c.
+* include/private/pthread_support.h (GC_Thread_Rep): Add
+"activation_frame" field.
+* pthread_stop_world.c (GC_push_all_stacks): Call
+GC_push_all_stack_frames() and GC_push_all_register_frames instead
+of GC_push_all_stack() and/or GC_push_all_eager(); don't check for
+STACK_GROWS_UP here.
+* pthread_support.c (GC_do_blocking_inner): Remove "static"; store
+"fn" result back to "client_data" field.
+* pthread_support.c (GC_call_with_gc_active): New API function.
+* win32_threads.c (GC_call_with_gc_active): Likewise.
+* win32_threads.c (GC_Thread_Rep): Add "thread_blocked_sp" and
+"activation_frame" fields.
+* win32_threads.c (GC_new_thread): Add assertion checking for
+thread_blocked_sp is NULL.
+* win32_threads.c (GC_do_blocking_inner): New function.
+* win32_threads.c (GC_stop_world): Don't suspend a thread if its
+thread_blocked_sp is non-NULL.
+* win32_threads.c (GC_push_stack_for): Use thread
+"activation_frame" (if non-NULL); use "thread_blocked_sp" if
+non-NULL (instead of calling GetThreadContext()); "UNPROTECT" the
+thread before modifying its last_stack_min; call
+GC_push_all_stack_frames() instead of GC_push_all_stack(); update
+the comments.
+
+* alloc.c (GC_default_stop_func): New static variable (initialized
+to GC_never_stop_func).
+* alloc.c (GC_set_stop_func, GC_get_stop_func): New function.
+* alloc.c (GC_timeout_stop_func): Define as GC_default_stop_func
+(instead of GC_never_stop_func) if SMALL_CONFIG (or NO_CLOCK),
+else call GC_default_stop_func() before getting "current_time".
+* alloc.c (GC_maybe_gc): Expand GC_gcollect_inner() macro (for
+FIXME comment).
+* alloc.c (GC_maybe_gc, GC_collect_a_little_inner): add FIXME for
+replacing GC_never_stop_func with GC_default_stop_func (if
+possible).
+* alloc.c (GC_gcollect): Use GC_default_stop_func.
+* alloc.c (GC_collect_or_expand): Use GC_default_stop_func
+(instead of GC_never_stop_func) unless it is trigged due to out of
+memory; don't increment GC_fail_count and don't output warning
+(before trying to collect again) in case the collection has been
+interrupted (by GC_default_stop_func) and the heap expansion has
+failed too.
+* include/gc.h (GC_set_stop_func, GC_get_stop_func): New function
+prototypes.
+
+* os_dep.c (GC_get_stack_base): Add FIXME; add assertion for
+GC_get_writable_length() result.
+
+* configure.ac: Don't use -lpthread -ldl for Cygwin.
+
+* NT_THREADS_MAKEFILE: Make it back equal to gc.mak.
+
+* include/private/gcconfig.h (GWW_VDB): Undefine if
+USE_GLOBAL_ALLOC (since incompatible).
+* os_dep.c (GetWriteWatch_alloc_flag): Define as 0 unless GWW_VDB
+is defined.
+* os_dep.c (GC_unmap_threshold): Declare (for use in
+GC_init_win32) if USE_MUNMAP.
+* os_dep.c (GC_init_win32): Turn off memory unmapping if
+GlobalAlloc() is used.
+* os_dep.c (GC_win32_get_mem): Define and use new
+VIRTUAL_ALLOC_PAD macro; don't waste an extra memory page unless
+MPROTECT_VDB is in use.
+
+* Makefile: Replace "version.h" with "include/gc_version.h".
+* include/gc_version.h: Likewise.
+
+* alloc.c (GC_collect_or_expand): Output heap size in WARN()
+(before returning FALSE) for convenience.
+
+* allchblk.c (GC_allochblk_nth): Use GC_PRIdPTR in WARN() format
+string.
+* pthread_support.c (start_mark_threads, GC_thr_init): Likewise.
+* win32_threads.c (GC_delete_thread): Likewise.
+* include/private/gc_priv.h (GC_PRIdPTR): New macro.
+* pthread_stop_world.c (GC_suspend_handler_inner): Remove
+unnecessary cast for WARN argument.
+* pthread_support.c (start_mark_threads): if pthread_create()
+failed then don't try to create other marker threads and (after
+printing a warning) adjust GC_markers and GC_parallel values; log
+GC_markers value (possibly adjusted) after that.
+
+* win32_threads.c (start_mark_threads): if pthread_create() is
+failed then don't try to create other marker threads and (after
+printing a warning) adjust GC_markers and GC_parallel values.
+* win32_threads.c (mark_mutex_event, builder_cv, mark_cv): Move
+the definition upper (to be visible in start_mark_threads()).
+* win32_threads.c (start_mark_threads): if CreateThread() or
+_beginthreadex() is failed then don't try to create other marker
+threads and (after printing a warning) adjust GC_markers,
+GC_parallel values, and destroy the event objects (either only
+some for the uncreated threads if DONT_USE_SIGNALANDWAIT or all if
+not a single thread is created).
+* win32_threads.c (GC_thr_init): Log GC_markers value (possibly
+adjusted) after start_mark_threads() call.
+
+* Makefile.am: Back remove "GC_" prefix for PTHREADS,
+DARWIN_THREADS, WIN32_THREADS (for configure.ac).
+
+* include/private/gc_priv.h: Change include of config.h to
+private/config.h.
+* include/private/gc_pmark.h: Likewise.
+* gc_cpp.cc: Likewise.
+* tests/test.c: Likewise.
+* tests/test_cpp.cc: Include private/config.h (if HAVE_CONFIG_H);
+undefine GC_BUILD.
+
+* finalize.c (GC_general_register_disappearing_link): Return
+GC_SUCCESS, GC_DUPLICATE, GC_NO_MEMORY (instead of 0, 1 and 2,
+respectively).
+* include/gc.h (GC_NO_MEMORY): New macro (defined as 2).
+* include/gc.h (GC_register_disappearing_link,
+GC_general_register_disappearing_link): Update the comment.
+* typd_mlc.c (GC_calloc_explicitly_typed): Use GC_NO_MEMORY macro.
+* finalize.c (GC_general_register_disappearing_link,
+GC_register_finalizer_inner): Recalculate the hash table index
+after GC_oom_fn succeeded (since the table may grow while not
+holding the lock) and check again that the entry is still not in
+the table (free the unused entry otherwise unless DBG_HDRS_ALL).
+* finalize.c (GC_register_finalizer_inner): Initialize "hhdr"
+local variable (to prevent a compiler warning).
+* finalize.c (GC_register_finalizer_inner): Don't modify the data
+pointed by "ocd" and "ofn" in GC_register_finalizer_inner() failed
+(due to out of memory).
+
+* alloc.c (GC_set_fl_marks, GC_clear_fl_marks): Transform loop to
+suppress compiler "variable might be uninitialized" warnings.
+
+* Makefile.direct (DONT_USE_SIGNALANDWAIT): Add the comment for.
+* win32_threads.c (DONT_USE_SIGNALANDWAIT): Always define for
+WinCE.
+* win32_threads.c (THREAD_HANDLE): Cast Id (of DWORD type) to
+HANDLE thru word type (to avoid a compiler warning) for WinCE.
+* win32_threads.c (GC_marker_cv, GC_marker_Id): New static array
+(only if DONT_USE_SIGNALANDWAIT).
+* win32_threads.c (start_mark_threads): Initialize GC_marker_Id
+and GC_marker_cv for each helper thread (only if
+DONT_USE_SIGNALANDWAIT).
+* win32_threads.c (GC_mark_mutex_state): New static variable (only
+if DONT_USE_SIGNALANDWAIT).
+* win32_threads.c (GC_mark_mutex_waitcnt,
+signalObjectAndWait_func): Don't define if DONT_USE_SIGNALANDWAIT.
+* win32_threads.c (GC_acquire_mark_lock, GC_release_mark_lock):
+Use InterlockedExchange() over GC_mark_mutex_state (instead of
+AO_fetch_and_add()) if DONT_USE_SIGNALANDWAIT.
+* win32_threads.c (GC_wait_marker, GC_notify_all_marker):
+Implement wait/broadcast primitives using Win32 multiple events
+(one for each marker thread) if DONT_USE_SIGNALANDWAIT (instead of
+using Win32 SignalObjectAndWait).
+* win32_threads.c (GC_thr_init): Don't declare hK32 local
+variable, don't check for GC_wnt, and don't initialize
+signalObjectAndWait_func if DONT_USE_SIGNALANDWAIT.
+
+* alloc.c (GC_finish_collection): Call GC_print_finalization_stats
+if GC_print_stats (after getting "done_time").
+* finalize.c (GC_old_dl_entries): New static variable (only if not
+SMALL_CONFIG).
+* finalize.c (GC_finalize): Save current GC_dl_entries value (only
+if not SMALL_CONFIG).
+* finalize.c (GC_print_finalization_stats): Define if and only if
+not SMALL_CONFIG; use GC_old_dl_entries value; use GC_log_printf()
+instead of GC_printf(); use "%lu" (instead of "%u") print format
+specifier; use unsigned long type for "ready" counter (for LP64
+targets).
+* misc.c (GC_dump): No longer call GC_print_finalization_stats()
+here (since it is called from GC_finish_collection()).
+* misc.c (STACKBASE): Remove unused macro undef (for NOSYS and
+ECOS).
+
+* alloc.c (GC_expand_hp): Replace GC_init_inner() call with
+GC_init() one.
+* malloc.c (GC_alloc_large, GC_generic_malloc_inner): Likewise.
+* mallocx.c (GC_generic_malloc_many): Likewise.
+* misc.c (GC_enable_incremental): Likewise.
+* alloc.c (GC_expand_hp): Update the comment.
+* mark.c (GC_obj_kinds): Likewise.
+* win32_threads.c (GC_allow_register_threads): Likewise.
+* private/gc_priv.h (GC_init_inner): Remove function declaration.
+* misc.c (GC_init_inner): Replace with public GC_init().
+
+* gcj_mlc.c (GC_gcj_fake_mark_proc): New static function.
+* gcj_mlc.c (GC_init_gcj_malloc): If mp is 0 then supply
+GC_gcj_fake_mark_proc (aborting with the appropriate message)
+instead.
+
+* os_dep.c (GC_wince_get_mem): If VirtualAlloc() returns NULL (due
+to out of memory) then don't increment GC_n_heap_bases and don't
+call VirtualAlloc() again (with MEM_COMMIT).
+* os_dep.c (GC_remap): Abort with a more informatory message if
+VirtualAlloc() fails due to out of memory; update FIXME.
+
+* Makefile: Fix typo for msvc_dbg.c.
+* Makefile.direct: Likewise.
+* Makefile.am: Prefix PTHREADS, DARWIN_THREADS, WIN32_THREADS with
+"GC_".
+* Makefile.dj: Don't reference remove files (nursery.c,
+gc_nursery.h, gc_copy_descr.h).
+* NT_MAKEFILE: Don't define __STDC__ macro (no longer used).
+* NT_STATIC_THREADS_MAKEFILE: Likewise.
+* NT_THREADS_MAKEFILE: Likewise.
+* NT_X64_STATIC_THREADS_MAKEFILE: Likewise.
+* NT_X64_THREADS_MAKEFILE: Likewise.
+* gc.mak: Likewise.
+* NT_MAKEFILE: Remove unnecessary -DGC_BUILD (since it is always
+defined in the source files).
+* NT_THREADS_MAKEFILE: Likewise.
+* NT_X64_THREADS_MAKEFILE: Likewise.
+* gc.mak: Likewise.
+* NT_X64_THREADS_MAKEFILE: Fix typo for -DGC_NOT_DLL.
+* NT_STATIC_THREADS_MAKEFILE: Replace GC_WIN32_THREADS with
+GC_THREADS.
+* NT_THREADS_MAKEFILE: Likewise.
+* NT_X64_STATIC_THREADS_MAKEFILE: Likewise.
+* NT_X64_THREADS_MAKEFILE: Likewise.
+* gc.mak: Likewise.
+* NT_MAKEFILE: Define _CRT_SECURE_NO_DEPRECATE to suppress the
+compiler warnings.
+* NT_STATIC_THREADS_MAKEFILE: Likewise.
+* NT_X64_STATIC_THREADS_MAKEFILE: Place -D_CRT_SECURE_NO_DEPRECATE
+before "$*.C" (and "$*.CPP").
+* NT_X64_THREADS_MAKEFILE: Likewise.
+
+* doc/README.solaris2: Replace GC_SOLARIS_THREADS with GC_THREADS.
+* doc/README.win32: Replace GC_WIN32_THREADS with GC_THREADS.
+* doc/README.win64: Add info about mingw-w64; add note for VC++
+warnings suppression.
+
+* os_dep.c (GC_forward_exception): Fix logic in several places.
+(OSX-specific)
+
+* include/private/gc_priv.h (MAX_HEAP_SECTS): Guard with ifndef.
+
+* Makefile.direct: Copy missing information for -DSHORT_DBG_HDRS
+from Makefile.
+* Makefile: Remove the information about "define arguments" (which
+is incomplete and outdated compared to that in Makefile.direct);
+add help reference to Makefile.direct.
+* Makefile.dj: Likewise.
+
+* alloc.c (world_stopped_total_time, world_stopped_total_divisor):
+Replace "STATIC" with "static" in the definition (since the
+symbols aren't prefixed with "GC_").
+* win32_threads.c (marker_sp, marker_bsp, marker_last_stack_min,
+start_mark_threads, mark_mutex, builder_cv, mark_cv,
+mark_mutex_event, signalObjectAndWait_func, main_thread_start):
+Likewise.
+* pthread_support.c (GC_wait_builder): Define as STATIC.
+* win32_threads.c (GC_wait_builder): Likewise.
+
+* misc.c (GC_get_heap_size_inner, GC_get_free_bytes_inner): New
+API function.
+* include/gc_pmark.h (GC_get_heap_size_inner,
+GC_get_free_bytes_inner): New function declaration.
+
+* include/gc.h: Recognize __CEGCC__ (as a synonym for _WIN32_WCE).
+* include/gc_config_macros.h: Likewise.
+* include/gc.h (GC_MAXIMUM_HEAP_SIZE): Recognize new macro.
+* include/gc.h (GC_INIT_CONF_MAXIMUM_HEAP_SIZE): New macro (for
+internal use).
+* include/gc_config_macros.h: Always include stddef.h if GCC.
+* include/gc_config_macros.h (GC_API): Define for CeGCC in the
+same way as for MinGW.
+* include/gc_config_macros.h (GC_API): Group the definition for
+all cases together (check for GC_DLL only once).
+* include/gc_pthread_redirects.h: Group non-Darwin code together.
+* tests/test.c: Recognize GC_PRINT_VERBOSE_STATS (only if GC_DLL).
+
+* Makefile.direct (GC_PTHREADS_PARAMARK, GC_IGNORE_GCJ_INFO,
+GC_PRINT_VERBOSE_STATS, GC_DONT_EXPAND, GC_INITIAL_HEAP_SIZE,
+GC_FREE_SPACE_DIVISOR, GC_TIME_LIMIT, GC_FULL_FREQ): Add the
+comment for.
+* misc.c (GC_init_inner): Recognize GC_PRINT_VERBOSE_STATS (new
+macro).
+* dyn_load.c (GC_wnt): Change definition to TRUE for WinCE; add
+FIXME and the comment for WinCE.
+* gcj_mlc.c (GC_init_gcj_malloc): Recognize GC_IGNORE_GCJ_INFO
+(new macro).
+* include/gc.h (GC_HAVE_BUILTIN_BACKTRACE): Don't define for VC++
+WinCE (since backtrace() is unimplemented).
+* include/private/gc_priv.h (GC_n_heap_bases): Remove declaration
+(since static).
+* os_dep.c (GC_n_heap_bases): Define as STATIC; move the
+definition to be above GC_is_heap_base().
+* include/private/gcconfig.h: Don't define NOSYS for WinCE on ARM
+(both for MinGW and CeGCC toolchains).
+* include/private/gcconfig.h: Recognize __CEGCC__ and
+__MINGW32CE__ (as synonyms for __WIN32_WCE).
+* include/private/gcconfig.h: If SH4 then don't set config
+parameters for SH.
+* include/private/thread_local_alloc.h (GC_key_create): Don't
+abort on failures, just return -1 in these cases (this also
+prevents compilation error for targets where ABORT is defined
+indirectly as an inline assembler sequence).
+* mark.c (WRAP_MARK_SOME): Also define for WinCE; add FIXME for
+the GCC-based cross-compiler.
+* mark.c (ext_ex_regn, mark_ex_handler): Don't define unless
+WRAP_MARK_SOME is defined; define also for WinCE case; don't
+check for _WIN64 (since WRAP_MARK_SOME is undefined for it).
+* mark.c (GC_mark_some): Use __try/__except also for WinCE; update
+the comment.
+* misc.c: Include signal.h after gc_pmark.h included; check for
+MSWINCE instead of _WIN32_WCE.
+* misc.c (GC_init_inner): Remove duplicate GC_setpagesize() call.
+* misc.c: Don't include <crtdbg.h> for WinCE targets.
+* misc.c (GC_write): Define _MAX_PATH if undefined (workaround for
+CeGCC toolchain).
+* misc.c (GC_write): Use OutputDebugStringW() instead of
+_CrtDbgReport() for WinCE targets.
+* os_dep.c (GC_least_described_address): Define as STATIC.
+* os_dep.c (GC_register_data_segments): Fix code indentation.
+* os_dep.c (GC_wince_get_mem): Initialize "result" local variable
+(to prevent a compiler warning).
+* os_dep.c (GC_dirty_init): Add comment for WinCE target.
+* tests/test.c: Don't include winbase.h directly if GCC for WinCE,
+include assert.h instead.
+* tests/test.c (tiny_reverse_test): Define and use
+TINY_REVERSE_UPPER_VALUE macro (4 if VERY_SMALL_CONFIG else 10);
+useful for WinCE.
+* win32_threads.c (GC_Thread_Rep): Don't declare "handle" field
+for WinCE (since thread Id is used as a "real" thread handle).
+* win32_threads.c (THREAD_HANDLE): New macro.
+* win32_threads.c (GC_register_my_thread_inner): Don't recognize
+DONT_IMPORT_GETCURTHREAD anymore; don't record thread handle on
+WinCE.
+* Makefile.direct (DONT_IMPORT_GETCURTHREAD): Remove comment for.
+* win32_threads.c (UNPROTECT, GC_fault_handler_lock): Don't check
+for MSWINCE.
+* win32_threads.c (GC_delete_gc_thread, GC_delete_thread): Don't
+close thread handle on WinCE (since it's a thread Id).
+* win32_threads.c (GC_suspend): Don't check for MSWINCE in the
+MPROTECT-related code (for the case if MPROTECT_VDB would be
+implemented for WinCE).
+* win32_threads.c (GC_suspend, GC_start_world, GC_push_stack_for):
+Use THREAD_HANDLE(t) to obtain thread handle.
+* win32_threads.c (GC_PTHREADS_PARAMARK): New macro recognized;
+implicitly define GC_PTHREADS_PARAMARK if GC_PTHREADS; include
+pthread.h; define NUMERIC_THREAD_ID(id) if undefined yet; replace
+GC_PTHREADS with GC_PTHREADS_PARAMARK where appropriate (for the
+parallel mark support).
+* win32_threads.c (start_mark_threads): Use int type for "i" local
+variable (instead of "unsigned") to prevent a compiler warning.
+* win32_threads.c (start_mark_threads): Don't check CreateThread()
+result for -1; call CloseHandle() for the handle created by
+CreateThread() (on WinCE); don't use errno (since errno.h is
+missing on some targets like WinCE) when printing warning on a
+marker thread creation failure.
+* win32_threads.c (signalObjectAndWait_func): Define for WinCE.
+* win32_threads.c (GC_wait_marker): Remove unnecessary assertion
+for non-zero signalObjectAndWait_func (to make the code compilable
+for WinCE).
+* win32_threads.c (GC_thr_init): Allow PARALLEL_MARK for WinCE;
+use GC_sysinfo to get processors count if WinCE; don't check for
+SignalObjectAndWait() if WinCE; replace GC_PTHREADS with
+GC_PTHREADS_PARAMARK.
+* win32_threads.c (GC_thr_init): Recognize GC_MIN_MARKERS new
+macro (useful for testing parallel marking on WinCE).
+* win32_threads.c (GC_win32_start, main_thread_start): Define as
+STATIC.
+* win32_threads.c: Don't define main_thread_args,
+main_thread_start(), WinMain() for WinCE if GC_DLL.
+* win32_threads.c (WINCE_MAIN_STACK_SIZE): Remove useless macro
+(since the stack size parameter is ignored on WinCE).
+* win32_threads.c (main_thread_start): Remove forward declaration;
+place its definition before WinMain() one.
+* win32_threads.c (WinMain): Abort if GC_CreateThread() or
+WaitForSingleObject() failed (for the main thread).
+
+* allchblk.c (MUNMAP_THRESHOLD): Move macro definition out of
+a function.
+* allchblk.c (GC_unmap_threshold): New global variable definition
+(initialized to MUNMAP_THRESHOLD).
+* allchblk.c (GC_unmap_old): Use GC_unmap_threshold instead of
+MUNMAP_THRESHOLD; skip unmapping if GC_unmap_threshold is 0.
+* doc/README.environment (GC_UNMAP_THRESHOLD): Add information.
+* misc.c (GC_unmap_threshold): New variable declaration.
+* misc.c (GC_init_inner): Recognize "GC_UNMAP_THRESHOLD"
+environment variable to set GC_unmap_threshold value (only if
+USE_MUNMAP).
+
+* dbg_mlc.c (OFN_UNSET): New macro (to detect
+GC_register_finalizer() failures).
+* dbg_mlc.c (store_old): Add a check for register_finalizer()
+failure caused by an out-of-memory event (leave *ofn and *ocd
+unmodified in that case).
+* dbg_mlc.c (GC_debug_register_finalizer,
+GC_debug_register_finalizer_no_order,
+GC_debug_register_finalizer_unreachable,
+GC_debug_register_finalizer_ignore_self): Initialize my_old_fn
+to OFN_UNSET; clear *ocd and *ofn for non-heap objects (the same
+as in GC_register_finalizer_inner()).
+
+* Makefile.direct (GC_DLL): Add the comment for.
+* doc/README.macros: Fix a typo.
+* doc/README.macros (_DLL, GC_DLL, GC_NOT_DLL): Update info.
+* doc/README.macros (__STDC__): Remove info.
+* dbg_mlc.c (GC_get_back_ptr_info, GC_generate_random_heap_address,
+GC_generate_random_valid_address, GC_print_backtrace,
+GC_generate_random_backtrace, GC_register_describe_type_fn): Add
+GC_API and GC_CALL to function definition.
+* malloc.c (GC_generic_malloc): Likewise.
+* mallocx.c (GC_incr_bytes_allocd, GC_incr_bytes_freed): Likewise.
+* mark.c (GC_mark_and_push): Likewise.
+* misc.c (GC_new_free_list_inner, GC_new_free_list,
+GC_new_kind_inner, GC_new_kind, GC_new_proc_inner, GC_new_proc):
+Likewise.
+* include/gc_backptr.h (GC_get_back_ptr_info,
+GC_generate_random_heap_address, GC_generate_random_valid_address,
+GC_generate_random_backtrace, GC_print_backtrace): Add GC_API and
+GC_CALL to function prototype.
+* include/gc_mark.h (GC_mark_and_push, GC_new_free_list,
+GC_new_free_list_inner, GC_new_kind, GC_new_kind_inner,
+GC_new_proc, GC_new_proc_inner, GC_generic_malloc,
+GC_register_describe_type_fn): Likewise.
+* include/new_gc_alloc.h (GC_incr_bytes_allocd, GC_incr_mem_freed,
+GC_generic_malloc_words_small): Likewise.
+* gc_cpp.cc: Include "config.h" (if HAVE_CONFIG_H defined).
+* include/private/gc_pmark.h: Likewise.
+* include/private/gc_priv.h: Likewise.
+* tests/test.c: Likewise.
+* gc_cpp.cc: Define GC_BUILD.
+* include/private/gc_pmark.h: Likewise.
+* include/private/gc_priv.h: Likewise.
+* gc_dlopen.c (WRAP_FUNC, REAL_FUNC): New macro.
+* gc_dlopen.c (dlopen): Add GC_API to the wrapper function
+definition.
+* pthread_support.c (GC_pthread_create, GC_pthread_sigmask,
+GC_pthread_join, GC_pthread_detach, pthread_sigmask, pthread_join,
+pthread_detach, pthread_create): Likewise.
+* win32_threads.c (GC_pthread_join, GC_pthread_create,
+GC_pthread_sigmask, GC_pthread_detach): Likewise.
+* gc_dlopen.c (dlopen): Use WRAP_FUNC and REAL_FUNC macros.
+* include/gc_backptr.h: Include "gc.h".
+* include/gc_backptr.h: Use extern "C" for the exported functions.
+* include/gc_mark.h: Likewise.
+* include/gc_config_macros.h (GC_THREADS): Define the macro if any
+GC_XXX_THREADS is defined.
+* include/gc_config_macros.h (_PTHREADS, _POSIX4A_DRAFT10_SOURCE):
+Move the definitions below the place where GC_NETBSD_THREADS and
+GC_DGUX386_THREADS are defined.
+* include/gc_config_macros.h (GC_DLL): Don't define (even if _DLL
+is defined) for GCC.
+* include/gc_config_macros.h (GC_API): Define for Cygwin (in the
+same way as for VC++); define for GCC v4+ (other than already
+recognized MinGW/Cygwin) as a "default" visibility attribute if
+GC_DLL is defined.
+* include/gc_config_macros.h (GC_ATTR_MALLOC, GC_ATTR_ALLOC_SIZE):
+New macro.
+* include/gc.h (GC_malloc, GC_malloc_atomic, GC_strdup,
+GC_malloc_uncollectable, GC_malloc_stubborn, GC_memalign,
+GC_malloc_atomic_uncollectable, GC_malloc_ignore_off_page,
+GC_malloc_atomic_ignore_off_page, GC_debug_malloc,
+GC_debug_malloc_atomic, GC_debug_strdup,
+GC_debug_malloc_uncollectable, GC_debug_malloc_stubborn,
+GC_debug_malloc_ignore_off_page,
+GC_debug_malloc_atomic_ignore_off_page,
+GC_debug_malloc_replacement): Add GC_ATTR_MALLOC attribute.
+* include/gc_gcj.h (GC_gcj_malloc, GC_debug_gcj_malloc,
+GC_gcj_malloc_ignore_off_page): Likewise.
+* include/gc.h (GC_malloc, GC_malloc_atomic,
+GC_malloc_uncollectable, GC_malloc_stubborn,
+GC_malloc_atomic_uncollectable, GC_malloc_ignore_off_page,
+GC_malloc_atomic_ignore_off_page, GC_debug_malloc,
+GC_debug_malloc_atomic, GC_debug_malloc_uncollectable,
+GC_debug_malloc_stubborn, GC_debug_malloc_ignore_off_page,
+GC_debug_malloc_atomic_ignore_off_page,
+GC_debug_malloc_replacement: Add GC_ATTR_ALLOC_SIZE attribute
+(for the first argument).
+* include/gc_gcj.h (GC_gcj_malloc, GC_debug_gcj_malloc,
+GC_gcj_malloc_ignore_off_page): Likewise.
+* include/gc.h (GC_memalign, GC_realloc, GC_debug_realloc,
+GC_debug_realloc_replacement): Add GC_ATTR_ALLOC_SIZE attribute
+(for the second argument).
+* include/gc.h (GC_malloc, GC_malloc_atomic, GC_strdup,
+GC_malloc_uncollectable, GC_malloc_stubborn, GC_memalign,
+GC_malloc_atomic_uncollectable, GC_free, GC_base, GC_size,
+GC_realloc, GC_expand_hp, GC_set_max_heap_size,
+GC_exclude_static_roots, GC_add_roots, GC_remove_roots,
+GC_register_displacement, GC_debug_register_displacement,
+GC_try_to_collect, GC_malloc_ignore_off_page,
+GC_malloc_atomic_ignore_off_page, GC_debug_malloc,
+GC_debug_malloc_atomic, GC_debug_strdup,
+GC_debug_malloc_uncollectable, GC_debug_malloc_stubborn,
+GC_debug_malloc_ignore_off_page,
+GC_debug_malloc_atomic_ignore_off_page, GC_debug_free,
+GC_debug_realloc, GC_debug_malloc_replacement,
+GC_debug_realloc_replacement, GC_finalization_proc,
+GC_register_finalizer, GC_debug_register_finalizer,
+GC_register_finalizer_ignore_self,
+GC_debug_register_finalizer_ignore_self,
+GC_register_finalizer_no_order,
+GC_debug_register_finalizer_no_order,
+GC_register_finalizer_unreachable,
+GC_debug_register_finalizer_unreachable,
+GC_register_disappearing_link,
+GC_general_register_disappearing_link,
+GC_unregister_disappearing_link, GC_noop1, GC_warn_proc,
+GC_set_warn_proc, GC_ignore_warn_proc, GC_fn_type,
+GC_call_with_alloc_lock, GC_stack_base_func,
+GC_call_with_stack_base, GC_same_obj, GC_pre_incr, GC_post_incr,
+GC_is_visible, GC_is_valid_displacement, GC_same_obj_print_proc,
+GC_is_valid_displacement_print_proc, GC_is_visible_print_proc,
+GC_malloc_many, GC_CreateThread, GC_beginthreadex,
+GC_endthreadex): Comment out (or remove if single and meaningless)
+function argument names (to avoid identifiers out of the name
+space).
+* include/gc_gcj.h (GC_init_gcj_malloc, GC_gcj_malloc,
+GC_debug_gcj_malloc, GC_gcj_malloc_ignore_off_page): Likewise.
+* include/gc.h (GC_try_to_collect): Update the comment.
+* include/gc.h (GC_size, GC_register_my_thread): Add const
+qualifier for the argument referent.
+* misc.c (GC_size): Likewise.
+* pthread_support.c (GC_register_my_thread_inner,
+GC_register_my_thread): Likewise.
+* win32_threads.c (GC_register_my_thread_inner,
+GC_register_my_thread): Likewise.
+* include/gc.h (GC_INIT_CONF_ROOTS): New macro for internal use
+(define instead of GC_INIT() for Cygwin and AIX).
+* include/gc.h (GC_DONT_EXPAND, GC_MAX_RETRIES,
+GC_FREE_SPACE_DIVISOR, GC_FULL_FREQ, GC_TIME_LIMIT, GC_IGNORE_WARN,
+GC_INITIAL_HEAP_SIZE): Recognize new macro.
+* include/gc.h (GC_INIT_CONF_DONT_EXPAND, GC_INIT_CONF_MAX_RETRIES,
+GC_INIT_CONF_FREE_SPACE_DIVISOR, GC_INIT_CONF_FULL_FREQ,
+GC_INIT_CONF_TIME_LIMIT, GC_INIT_CONF_IGNORE_WARN,
+GC_INIT_CONF_INITIAL_HEAP_SIZE): New macro for internal use.
+* include/gc.h (GC_INIT): Use GC_INIT_CONF_XXX macros.
+* include/gc_mark.h: Prefix GC_H with '_'.
+* include/gc_mark.h (GC_least_plausible_heap_addr,
+GC_greatest_plausible_heap_addr, GC_debug_header_size): Use GC_API
+for the public variable declaration.
+* include/new_gc_alloc.h (GC_objfreelist_ptr, GC_aobjfreelist_ptr,
+GC_uobjfreelist_ptr, GC_auobjfreelist_ptr): Likewise.
+* include/gc_pthread_redirects.h (GC_pthread_create,
+GC_pthread_sigmask, GC_dlopen, GC_pthread_join, GC_pthread_detach):
+Use GC_API for the wrapper prototype.
+* include/gc_pthread_redirects.h (pthread_create, pthread_join,
+pthread_detach, pthread_sigmask, dlopen): Undefine unconditionally
+before redirecting.
+* include/new_gc_alloc.h: Replace GC_incr_mem_freed() with
+GC_incr_bytes_freed(); remove FIXME.
+* include/private/gc_priv.h (GC_make_closure,
+GC_debug_invoke_finalizer, GC_noop): Remove GC_API for the private
+function.
+* tests/test.c (GC_print_stats): Handle GC_DLL case regardless of
+the target.
+
+* finalize.c (GC_general_register_disappearing_link,
+GC_register_finalizer_inner): Remove unnecessary "ifdef THREADS"
+guard for LOCK/UNLOCK().
+* finalize.c (GC_general_register_disappearing_link,
+GC_register_finalizer_inner): Get GC_oom_fn value before releasing
+the lock (to prevent data races).
+* gcj_mlc.c (GC_gcj_malloc, GC_debug_gcj_malloc,
+GC_gcj_malloc_ignore_off_page): Likewise.
+* mallocx.c (GC_generic_malloc_ignore_off_page): Likewise.
+* include/gc_inline.h (GC_FAST_MALLOC_GRANS): Use GC_get_oom_fn()
+instead of GC_oom_fn (to prevent data races).
+* malloc.c (GC_generic_malloc): Likewise.
+* mallocx.c (GC_memalign): Likewise.
+* pthread_support.c (pthread_create): Likewise.
+* gcj_mlc.c (maybe_finalize): Acquire the lock before setting
+last_finalized_no value to prevent data races.
+* include/gc.h (GC_gc_no, GC_get_gc_no, GC_oom_fn, GC_set_oom_fn,
+GC_set_find_leak, GC_set_finalize_on_demand,
+GC_set_java_finalization, GC_set_finalizer_notifier,
+GC_set_dont_expand, GC_set_full_freq, GC_set_non_gc_bytes,
+GC_set_no_dls, GC_set_free_space_divisor, GC_set_max_retries,
+GC_set_dont_precollect, GC_set_time_limit, GC_warn_proc): Refine
+the comment.
+* misc.c (GC_set_oom_fn): Likewise.
+* include/gc.h (GC_general_register_disappearing_link): Refine the
+comment (replace "soft" word with "weak").
+* misc.c (GC_oom_fn, GC_get_gc_no, GC_get_parallel,
+GC_set_finalizer_notifier, GC_set_find_leak): Add the comment.
+* misc.c (GC_set_oom_fn, GC_get_oom_fn, GC_set_finalizer_notifier,
+GC_get_finalizer_notifier): Use LOCK/UNLOCK to prevent data races.
+
+* dbg_mlc.c: Guard include <errno.h> with ifndef MSWINCE; include
+"private/dbg_mlc.h" before it.
+* malloc.c: Likewise.
+* dbg_mlc.c (GC_debug_strdup): Use memcpy() instead of strcpy()
+for WinCE (since deprecated); evaluate strlen() only once; don't
+set errno for WinCE.
+* malloc.c (GC_strdup): Likewise.
+* dyn_load.c (GC_wnt): Define as macro (FALSE) for WinCE.
+* include/gc.h (GC_unregister_my_thread): Refine the comment.
+* include/gc.h (GC_uintptr_t, GC_beginthreadex, GC_endthreadex):
+Don't declare for WinCE.
+* include/gc.h (GC_WINMAIN_WINCE_LPTSTR): New macro (WinCE only).
+* include/gc.h (GC_WinMain): Remove GC_API.
+* include/gc.h (GC_WinMain): Use GC_WINMAIN_WINCE_LPTSTR for
+lpCmdLine.
+* tests/test.c (GC_WinMain): Likewise.
+* win32_threads.c (main_thread_args, GC_WinMain): Likewise.
+* include/gc_config_macros.h (ptrdiff_t): Guard with
+ifndef _PTRDIFF_T_DEFINED; define _PTRDIFF_T_DEFINED macro.
+* include/private/gc_locks.h: Guard include "atomic_ops.h" with
+ifdef GC_PTHREADS (and not GC_WIN32_THREADS).
+* mark.c: Include "atomic_ops.h" if PARALLEL_MARK.
+* thread_local_alloc.c: Include "atomic_ops.h" if GC_GCJ_SUPPORT.
+* win32_threads.c: Include "atomic_ops.h" if MPROTECT_VDB.
+* include/private/gc_locks.h: Use include "atomic_ops.h" instead
+of include <atomic_ops.h>.
+* include/private/gc_priv.h: Likewise.
+* include/private/gc_locks.h (GC_allocate_ml, GC_need_to_lock):
+Don't export (replace GC_API to "extern").
+* win32_threads.c (GC_allocate_ml): Don't export.
+* include/private/gc_priv.h (DebugBreak): Define as macro for
+WinCE (if not UNDER_CE and DebugBreak is not defined yet).
+* include/private/gc_priv.h (UNALIGNED): Rename to UNALIGNED_PTRS
+(since "UNALIGNED" is defined in winnt.h of WinCE).
+* mark.c (UNALIGNED): Likewise.
+* include/private/gcconfig.h (ARM32): Recognize _M_ARM and _ARM_.
+* include/private/gcconfig.h (ALIGNMENT): Check always defined.
+* include/private/gcconfig.h: Allow GC_WIN32_THREADS for WinCE.
+* include/private/thread_local_alloc.h: Define USE_WIN32_SPECIFIC
+for WinCE (since __declspec(thread) is unsupported).
+* include/private/thread_local_alloc.h (TLS_OUT_OF_INDEXES):
+Define for WinCE (if undefined).
+* malloc.c (GC_malloc): Remove outdated comment about disabling
+signals.
+* misc.c: Don't include <tchar.h> (since not used anymore and may
+break TEXT() macro defined in winnt.h).
+* misc.c (GC_init_inner): Don't use GetModuleHandle() and
+InitializeCriticalSectionAndSpinCount() for WinCE.
+* misc.c (GC_init_inner): Replace GetModuleHandleA() with
+GetModuleHandle() (and use TEXT() macro controlled by UNICODE).
+* misc.c (LOG_FILE): Remove unused macro; don't use _T() macro.
+* misc.c (GC_CreateLogFile): New static function (Win32/WinCE
+only); move the code from GC_write(); replace GETENV() with
+GetEnvironmentVariable(); replace CreateFileA() with
+CreateFile(); use TEXT() macro (for Unicode support); replace
+strcat() with memcpy() (since deprecated in WinCE).
+* misc.c (GC_write): Define as STATIC.
+* win32_threads.c (GC_attached_thread): Likewise.
+* misc.c (GC_write): Use GC_CreateLogFile().
+* misc.c: Define vsnprintf macro as StringCchVPrintfA for WinCE.
+* misc.c (GC_abort): Try to invoke MessageBoxA() dynamically
+(Win32 only) if DONT_USE_USER32_DLL is defined.
+* misc.c (GC_abort): Duplicate msg to GC log file (for Win32 and
+WinCE).
+* misc.c (GC_abort): Use a more user-friendly abort if
+NO_DEBUGGING (Win32 only).
+* os_dep.c: Include "atomic_ops.h" only if MPROTECT_VDB (and
+THREADS).
+* os_dep.c (detect_GetWriteWatch): Use TEXT() for GetModuleHandle
+(for Unicode support); check GetModuleHandle() result.
+* tests/test.c: Don't define assert for WinCE (since may be
+redefined by "assert.h" included from libatomic_ops).
+* tests/test.c (FAIL): Define as ABORT for all targets (except
+for PCR).
+* tests/test.c (n_tests): Don't use AO_t.
+* tests/test.c (check_heap_stats): Don't cast n_tests.
+* tests/test.c (inc_int_counter): New function (for n_tests atomic
+incrementation).
+* tests/test.c (run_one_test): Test GC_memalign() for all targets.
+* tests/test.c (run_one_test): Avoid unbalanced brackets in
+#if-#else-#endif blocks.
+* tests/test.c (run_one_test): Replace AO_fetch_and_add1() and
+private LOCK/UNLOCK with GC_call_with_alloc_lock(inc_int_counter).
+* tests/test.c (check_heap_stats): Replace
+"if (sizeof(char *) > 4)" with "#if CPP_WORDSZ == 64" to suppress
+"unreachable code" compiler warning.
+* tests/test.c (WinMain): Set cmd type to LPWSTR (for WinCE
+"UNDER_CE" mode); else use LPSTR type (for Win32 and WinCE).
+* tests/test.c (thr_window): Replace "L" string prefix with
+TEXT().
+* thread_local_alloc.c: Check THREADS is defined (to prevent other
+compiler errors and warnings otherwise).
+* tests/test.c (WinMain): Recognize GC_NO_DLLMAIN macro (for
+GC_use_DllMain()).
+* Makefile.direct (GC_NO_DLLMAIN, DONT_IMPORT_GETCURTHREAD): Add
+the comments for.
+* win32_threads.c (GC_register_my_thread_inner): Recognize
+DONT_IMPORT_GETCURTHREAD macro.
+* win32_threads.c: Recognize GC_NO_DLLMAIN macro (to exclude
+DllMain support if needed).
+* win32_threads.c (GC_NO_DLLMAIN): Define implicitly if DllMain
+thread registration is unsupported for a given configuration.
+* win32_threads.c (GC_use_DllMain): Update the comment; refine
+ABORT message.
+* win32_threads.c (GC_use_DllMain,
+GC_started_thread_while_stopped, GC_register_my_thread_inner,
+GC_lookup_thread_inner, GC_delete_gc_thread,
+GC_allow_register_threads, GC_lookup_pthread,
+GC_push_thread_structures, GC_stop_world, GC_push_all_stacks):
+Check for GC_NO_DLLMAIN.
+* win32_threads.c (GC_Thread_Rep.tm_in_use, GC_attached_thread,
+DllMain): Don't define if GC_NO_DLLMAIN.
+* win32_threads.c (GC_stop_world): Declare "i" and "max" local
+variables only if not GC_NO_DLLMAIN (to suppress compiler
+warning).
+* win32_threads.c (GC_mark_thread, start_mark_threads): Use
+CreateThread() instead of _beginthreadex() for WinCE.
+* win32_threads.c (MARK_THREAD_STACK_SIZE, WINCE_MAIN_STACK_SIZE):
+New macros defined (used by start_mark_threads(), WinMain()).
+* win32_threads.c (GC_thr_init): Exclude parallel-specific code on
+WinCE for now (since getenv(), GetProcessAffinityMask() and
+SignalObjectAndWait() are missing on WinCE).
+* win32_threads.c (GC_thr_init): replace GetModuleHandleA() with
+GetModuleHandle(); replace CreateEventA() with CreateEvent(); use
+TEXT() macro (for Unicode support).
+
+* include/gc.h (GC_has_static_roots_func): New typedef (user filter
+callback).
+* include/gc.h (GC_register_has_static_roots_callback): Use
+GC_has_static_roots_func type.
+* dyn_load.c (GC_has_static_roots,
+GC_register_has_static_roots_callback): Likewise.
+* dyn_load.c (GC_has_static_roots,
+GC_register_has_static_roots_callback): Define on all platforms.
+* dyn_load.c (GC_register_dynlib_callback,
+GC_register_dynamic_libraries, GC_init_dyld): Replace K&R-style
+functions definition with the ANSI C one.
+* dyn_load.c (GC_register_dynlib_callback): Use new local variable
+"callback" (initialized from GC_has_static_roots) to minimize data
+races.
+* dyn_load.c (GC_register_dynamic_libraries_dl_iterate_phdr,
+GC_cond_add_roots): Define as STATIC.
+* mark_rts.c (GC_remove_roots_inner): Likewise.
+* dyn_load.c (GC_dyld_image_add): Don't call GC_add_roots() for
+sections smaller than pointer size (just to avoid acquiring the
+lock unnecessarily).
+* dyn_load.c (GC_dyld_name_for_hdr): Define unconditionally (not
+only for DARWIN_DEBUG).
+* dyn_load.c (GC_dyld_image_add): Replace GC_add_roots() call with
+LOCK + GC_add_roots_inner() + UNLOCK.
+* dyn_load.c (GC_dyld_image_add): Call GC_has_static_roots() user
+callback (if set) holding the lock; if it returns 0 then don't call
+GC_add_roots_inner() for that region.
+* dyn_load.c (GC_register_has_static_roots_callback): Put
+"callback" value to GC_has_static_roots on all platforms.
+* dyn_load.c (GC_has_static_roots): Update the comments.
+* include/gc.h (GC_exclude_static_roots, GC_add_roots,
+GC_remove_roots, GC_register_has_static_roots_callback): Likewise.
+* include/private/gc_priv.h (struct roots): Likewise.
+* include/private/gc_priv.h (GC_remove_roots_inner): Move prototype
+to mark_rts.c and declare it as STATIC.
+* include/private/gc_priv.h (GC_exclude_static_roots_inner): New
+prototype.
+* dyn_load.c (GC_register_dynamic_libraries_dl_iterate_phdr): Use
+GC_exclude_static_roots_inner() instead of GC_exclude_static_roots.
+* misc.c (GC_init_inner): Likewise.
+* mark_rts.c (GC_exclude_static_roots_inner): New function (move
+all the code from GC_exclude_static_roots(); add the comment.
+* mark_rts.c (GC_add_roots_inner, GC_exclude_static_roots_inner):
+add alignment assertion for the lower bound; add assertion for the
+lower bound to be less than the upper one.
+* mark_rts.c (GC_add_roots_inner, GC_exclude_static_roots): Adjust
+the upper bound (round down to be of a pointer-aligned value);
+return in case of an empty range.
+* mark_rts.c (GC_exclude_static_roots): Acquire the lock and call
+GC_exclude_static_roots_inner().
+* mark_rts.c (GC_remove_roots): Quickly check the bounds and return
+in case of a do-nothing case (before acquiring the lock).
+
+* finalize.c (GC_fail_count): New external variable declaration.
+* finalize.c (GC_reset_finalizer_nested,
+GC_check_finalizer_nested): New function declarations (if THREADS
+only).
+* finalize.c (GC_finalizer_nested, GC_finalizer_skipped): New
+static global variables (used internally by GC_finalize() and
+GC_check_finalizer_nested()).
+* finalize.c (GC_check_finalizer_nested): New static function
+definition (only if not THREADS, used internally by
+GC_notify_or_invoke_finalizers() to minimize the probability of
+a deep recursion when a client finalizer tries to allocate GC
+memory).
+* finalize.c (GC_finalize): Reset GC_finalizer_nested value (or
+call GC_reset_finalizer_nested()) if last heap expansion failed.
+* finalize.c (GC_notify_or_invoke_finalizers): Access GC_gc_no,
+GC_finalizer_now, GC_finalize_on_demand, GC_finalizer_notifier,
+last_finalizer_notification variables holding the lock (to avoid
+data races).
+* finalize.c (GC_finalizer_notifier): Add comment.
+* finalize.c (GC_notify_or_invoke_finalizers): Add "quick" check
+for an empty finalization queue (only if THREADS and not
+KEEP_BACK_PTRS/MAKE_BACK_GRAPH).
+* finalize.c (GC_notify_or_invoke_finalizers): Call
+GC_check_finalizer_nested() and skip GC_invoke_finalizers() call
+if appropriate.
+* include/private/pthread_support.h (GC_Thread_Rep): Add unsigned
+finalizer_nested and finalizer_skipped fields (for internal use
+by the multi-threaded GC_check_finalizer_nested()).
+* win32_threads.c (GC_Thread_Rep): Likewise.
+* pthread_support.c (GC_reset_finalizer_nested,
+GC_check_finalizer_nested): New function definitions (the
+multi-threaded variants of that in finalize.c).
+* win32_threads.c (GC_reset_finalizer_nested,
+GC_check_finalizer_nested): Likewise.
+
+* alloc.c (GC_stopped_mark): Remove GC_log_printf("") (not needed
+anymore and GCC produces a warning for it).
+* alloc.c (GC_stopped_mark): Adjust printf argument type
+specifier.
+* backgraph.c: Include dbg_mlc.h before ifdef MAKE_BACK_GRAPH (for
+the case when the configuration information comes from a config.h
+file).
+* checksums.c: Likewise.
+* include/gc_allocator.h (GC_ATTR_UNUSED): Use "__unused__"
+keyword instead of "unused".
+* include/gc_allocator.h: Fix typos in comments.
+* thread_local_alloc.c: Likewise.
+* include/javaxfc.h (GC_finalize_all): Update comment.
+* include/private/gc_priv.h (GC_API_PRIV): New macro (defined as
+GC_API and serves only as a marker for the private but exported
+symbols used by test.c only).
+* include/private/gc_priv.h (GC_abort, GC_arrays, GC_is_marked,
+GC_printf, GC_err_printf, GC_log_printf): Replace GC_API decl with
+GC_API_PRIV one.
+* include/private/gc_priv.h (GC_fo_entries): Don't export it
+outside a DLL.
+* include/private/gc_priv.h (GC_ATTR_FORMAT_PRINTF): New macro
+designated to check the arguments correctness of printf-like
+functions (currently works only for GCC v3+).
+* include/private/gc_priv.h (GC_printf, GC_err_printf,
+GC_log_printf): Use GC_ATTR_FORMAT_PRINTF attribute.
+
+* dyn_load.c (HAVE_DL_ITERATE_PHDR): Break definition from use.
+Define for FreeBSD 7.0+.
+
+* mach_dep.c: Don't include ucontext.h with NO_GETCONTEXT.
+
+* include/gc_gcj.h (GC_init_gcj_malloc): Improve descriptive
+comment.
+
+* allchblk.c (GC_merge_unmapped): Don't assume that adjacent
+free blocks have different mapping status.  Correctly handle gap
+between blocks.
+(GC_split_block): Remove dead code setting hb_flags.  Add comment.
+(GC_allochblk): Split blocks also in generational-only mode.
+* os_dep.c (GC_unmap_gap): Don't really use munmap.
+
+* include/private/gc_priv.h (GC_unmapped_bytes): Define as 0 for
+not USE_MUNMAP case.
+
+* Makefile.direct (MARK_BIT_PER_OBJ, PRINT_BLACK_LIST,
+USE_PROC_FOR_LIBRARIES): Fix typo in the comments.
+* Makefile.direct (USE_MMAP, USE_MUNMAP, THREAD_LOCAL_ALLOC,
+PARALLEL_MARK, STATIC): Update the comments.
+* include/private/gcconfig.h (GC_PREFER_MPROTECT_VDB): New macro
+recognized (only if MPROTECT_VDB).
+* Makefile.direct (DONT_USE_USER32_DLL, GC_PREFER_MPROTECT_VDB):
+Add the comments for.
+* os_dep.c (detect_GetWriteWatch): Recognize "GC_USE_GETWRITEWATCH"
+environment variable (only if MPROTECT_VDB, if the variable is
+unset when GC_PREFER_MPROTECT_VDB macro controls the strategy).
+* doc/README.environment (GC_USE_GETWRITEWATCH): New variable.
+* include/private/gcconfig.h (MPROTECT_VDB): Add FIXME for
+USE_MUNMAP and PARALLEL_MARK cases (to relax the conditions in
+the future).
+* misc.c (GC_get_heap_size, GC_get_free_bytes): Ignore the memory
+space returned to OS (GC_unmapped_bytes).
+* include/gc.h (GC_get_heap_size, GC_get_free_bytes): Update the
+comments.
+* misc.c (GC_get_unmapped_bytes): New API function.
+* include/gc.h (GC_get_unmapped_bytes): New API prototype.
+* os_dep.c (GC_dirty_init): Move "ifdef GWW_VDB" block out of
+"ifdef MSWIN32" one (for Cygwin).
+
+* pthread_support.c (GC_allow_register_threads): New API function.
+* win32_threads.c (GC_allow_register_threads): Likewise.
+* include/gc.h (GC_allow_register_threads): New API prototype.
+* include/gc.h (GC_register_my_thread, GC_unregister_my_thread):
+Update the comments.
+* pthread_support.c (GC_register_my_thread): Check the collector
+is in the multi-threaded mode.
+* win32_threads.c (GC_register_my_thread): Likewise.
+
+* finalize.c (GC_finalize_all): Always call GC_invoke_finalizers
+instead, following Ivan's original patch.
+
+* allchblk.c (GC_allochblk_nth): Add assertion.
+* checksums.c: Add GC_record_fault, GC_was_faulted,
+CC_n_faulted_dirty_errors.
+(GC_check_dirty): Remove register declarations, print
+dirty bit errors on faulted pages.
+* os_dep.c (GC_write_fault_handler): Call GC_record_fault().
+* os_dep.c (GC_remove_protection): Compute index correctly.
+
+
+== [7.2alpha2] 2009-06-12 ==
+
+* dbg_mlc.c (GC_print_smashed_obj): Convert a group of printf()
+calls into a single one (for output atomicity).
+* typd_mlc.c (GC_calloc_explicitly_typed): Don't declare and use
+GC_finalization_failures variable; check the result of
+GC_general_register_disappearing_link() (for lack of memory)
+instead.
+* finalize.c (GC_finalization_failures): Remove unused global
+variable.
+* finalize.c (GC_general_register_disappearing_link,
+GC_general_register_disappearing_link): Don't update the value of
+GC_finalization_failures (since unused).
+* include/private/gc_pmark.h (PUSH_ONE_CHECKED_STACK,
+GC_PUSH_ONE_STACK, GC_PUSH_ONE_HEAP): The first parameter is of
+word type now (as FIXUP_POINTER requires numeric argument).
+* finalize.c (GC_ignore_self_finalize_mark_proc): GC_PUSH_ONE_HEAP
+requires the first parameter of word type.
+* mark.c (PUSH_GRANULE): Likewise.
+* mark.c (GC_push_one, GC_push_all_eager): Likewise.
+* finalize.c (GC_finalize_all): Call GC_invoke_finalizers() or
+GC_finalizer_notifier directly, instead
+of GC_INVOKE_FINALIZERS() to prevent infinite looping.
+* include/javaxfc.h: Clarify GC_finalize_all comment.
+* gcj_mlc.c: Include gc_pmark.h before "ifdef GC_GCJ_SUPPORT" (not
+after) for configuration information.
+* gcj_mlc.c (GC_gcj_malloc_ignore_off_page): Add comment.
+* gcj_mlc.c (GC_gcj_malloc_ignore_off_page): Check "op" local
+variable for NULL before dereferencing it, return GC_oom_fn() in
+this case.
+* typd_mlc.c (GC_malloc_explicitly_typed,
+GC_malloc_explicitly_typed_ignore_off_page): Transform the code to
+suppress compiler warning (for uninitialized "lg" variable).
+
+* win32_threads.c (GC_unregister_my_thread): add false assertion
+in unreachable code.
+
+* pthread_support.c (GC_inner_start_routine): Don't release the
+GC lock between GC_register_my_thread_inner() and
+GC_init_thread_local() calls (post the "registered" even after
+calling GC_init_thread_local()).
+* win32_threads.c (GC_register_my_thread, GC_unregister_my_thread):
+Use GC_lookup_thread_inner() instead of GC_lookup_thread() and
+acquire the GC lock only once.
+* win32_threads.c (GC_thr_init): Call GC_register_my_thread_inner()
+directly instead of GC_register_my_thread() since I_HOLD_LOCK
+and our (main) thread is not registered yet (add assertion for it).
+* win32_threads.c (GC_init_parallel): Call GC_lookup_thread_inner()
+directly instead of GC_lookup_thread() (since I_HOLD_LOCK).
+* win32_threads.c (GC_lookup_thread): Remove unused function.
+* win32_threads.c: Remove "#error GC_DLL untested with Cygwin".
+* win32_threads.c (GC_win32_dll_threads): Define as FALSE macro
+also if THREAD_LOCAL_ALLOC or GC_PTHREADS.
+* win32_threads.c (GC_use_DllMain): Call ABORT also if GC_PTHREADS
+(for Cygwin).
+* win32_threads.c (GC_push_stack_for): Add parentheses around "&&"
+(inside GC_ASSERT) to prevent compiler warning.
+* win32_threads.c (GC_push_all_stacks): Remove FIXME for
+PARALLEL_MARK.
+* win32_threads.c (MAX_MARKERS, GC_markers): Move the definitions
+to a place before GC_get_next_stack().
+* win32_threads.c (marker_sp, marker_bsp): New static arrays (same
+as in pthread_support.c).
+* win32_threads.c (marker_last_stack_min): New static arrays (the
+same semantics as for last_stack_min of GC_Thread_Rep).
+* win32_threads.c (GC_get_next_stack): Handle marker threads.
+* win32_threads.c (GC_mark_thread): Save the current stack pointer
+to marker_[b]sp.
+* win32_threads.c (start_mark_threads): Initialize
+marker_last_stack_min elements (to "unset" value).
+
+* misc.c (GC_set_oom_fn, GC_set_all_interior_pointers,
+GC_set_finalize_on_demand, GC_set_java_finalization,
+GC_set_finalizer_notifier, GC_set_dont_expand, GC_set_full_freq,
+GC_set_no_dls, GC_set_free_space_divisor, GC_set_max_retries,
+GC_set_dont_precollect, GC_set_time_limit, GC_set_warn_proc):
+Change return type to void (these API functions no longer return
+the old value).
+* include/gc.h: Likewise.
+* tests/test.c (main, WinMain, test): Remove explicit cast to void
+for GC_set_warn_proc().
+* misc.c (GC_get_oom_fn, GC_get_all_interior_pointers,
+GC_get_finalize_on_demand, GC_get_java_finalization,
+GC_get_finalizer_notifier, GC_get_dont_expand, GC_get_full_freq,
+GC_get_no_dls, GC_get_free_space_divisor, GC_get_max_retries,
+GC_get_dont_precollect, GC_get_time_limit, GC_get_warn_proc): New
+API functions (to get the current value of the corresponding R/W
+public variables).
+* include/gc.h: Likewise.
+* include/gc.h (GC_set_warn_proc, GC_set_free_space_divisor):
+Update the comment.
+* misc.c (GC_ignore_warn_proc): New API call-back function.
+* include/gc.h (GC_ignore_warn_proc): Likewise.
+* misc.c (GC_set_find_leak, GC_get_find_leak, GC_set_non_gc_bytes,
+GC_get_non_gc_bytes): New API setter and getter functions (for the
+public GC_find_leak and GC_non_gc_bytes variables, respectively).
+* include/gc.h: Likewise.
+* include/gc.h (GC_memalign): Add proto to GC API.
+* mallocx.c (GC_memalign): Use GC_API, GC_CALL for the definition.
+* tests/test.c (run_one_test): Test GC_memalign() on Win32 too,
+remove GC_memalign() proto.
+* misc.c (GC_write): Use multi-byte (A) variants of Win32
+GetModuleFileName() and CreateFile().
+* tests/test.c (main): Replace K&R-style function definition with the
+ANSI C one.
+
+* include/private/gcconfig.h (PLATFORM_ANDROID): New macro
+recognized (for Linux on ARM32 without glibc).
+* include/private/gcconfig.h (STRTOULL): Define for all targets
+(define as "strtoul" for most targets except for LLP64/Win64).
+* misc.c (GC_init_inner): Use STRTOULL instead of atoi/atol()
+(cast the result to word type) to decode values of "GC_TRACE",
+"GC_INITIAL_HEAP_SIZE", "GC_MAXIMUM_HEAP_SIZE" environment
+variables.
+
+* include/gc_allocator.h: Add gc_allocator_ignore_off_page.
+* tests/test_cpp.cc: Add call to gc_allocator_ignore_off_page.
+
+* win32_threads.c (GC_release_mark_lock): Correct misspelling of
+AO_load in assertion.
+
+* win32_threads.c (MAX_THREADS): Define as 1 if GC_win32_dll_threads
+is defined as FALSE (otherwise the size of dll_thread_table is near
+200 KiB for 32-bit).
+* win32_threads.c (GC_use_DllMain): Optimize for THREAD_LOCAL_ALLOC.
+* win32_threads.c (GC_Thread_Rep): Add backing_store_end and
+backing_store_ptr fields for IA64 support.
+* win32_threads.c (GC_register_my_thread_inner): Set
+backing_store_end field to reg_base value for IA64 (same as in
+pthread_support.c).
+* win32_threads.c (SET_PTHREAD_MAP_CACHE): Put parentheses in the
+"right" places, remove ';'.
+* win32_threads.c (GC_fault_handler_lock): Declare only
+if MPROTECT_VDB (and not WinCE).
+* win32_threads.c (GC_suspend): Acquire and release
+GC_fault_handler_lock only if MPROTECT_VDB (and not WinCE).
+* win32_threads.c (GC_suspend): Define as STATIC.
+* win32_threads.c (GC_push_stack_for): Fix WARN() format specifier
+(should be word-compliant, "%p" is used w/o "0x"), don't cast sp.
+* win32_threads.c (GC_push_all_stacks): Convert a group of printf()
+calls into a single one (for output atomicity).
+* win32_threads.c (GC_get_next_stack): Unprotect thread descriptor
+before altering its last_stack_min ("thread" variable is added).
+* win32_threads.c (GC_get_next_stack): Remove unnecessary checks for
+"s" is non-NULL.
+* win32_threads.c (GC_get_next_stack): Don't call GC_may_be_in_stack
+if WinCE.
+* win32_threads.c (GC_get_next_stack): Pass current_min value to
+GC_get_stack_min as-is (without -1).
+* win32_threads.c (GC_wait_marker): Remove FIXME and use "release"
+version of AO_fetch_and_sub1().
+* win32_threads.c (GC_win32_start_inner, GC_win32_start): convert int
+to pointer (and vice versa) thru word type to suppress warnings.
+* win32_threads.c (GC_mark_mutex_waitcnt): Fix comment, always
+access atomically.
+* misc.c: Change GC_THREADS tests back to THREADS.
+
+* allchblk.c (GC_print_hblkfreelist, GC_dump_regions): Convert
+a group of printf() calls into a single one (for output atomicity).
+* include/gc.h (GC_set_all_interior_pointers, GC_set_full_freq,
+GC_set_time_limit): New prototypes.
+* misc.c (GC_set_all_interior_pointers, GC_set_full_freq,
+GC_set_time_limit): New public setter/getter functions.
+* include/gc.h: Fix (and remove outdated) comments for thread-local
+allocation.
+* include/gc.h: Fix typos in comments.
+* misc.c (GC_init_inner, GC_printf): Likewise.
+* include/gc.h (GC_unregister_disappearing_link): Refine comment.
+* include/gc.h (GC_stack_base): Recognize _M_IA64 macro.
+* misc.c (GC_stack_last_cleared, GC_min_sp, GC_high_water,
+GC_bytes_allocd_at_reset, DEGRADE_RATE): Define only if THREADS.
+* misc.c (GC_stack_last_cleared, GC_min_sp, GC_high_water,
+GC_bytes_allocd_at_reset): Define as STATIC.
+* misc.c (GC_get_heap_size, GC_get_free_bytes,
+GC_get_bytes_since_gc, GC_get_total_bytes): Acquire the GC lock to
+avoid data races.
+* misc.c (GC_write_cs): Define only if THREADS (Win32/WinCE only).
+* misc.c (GC_init_inner): Initialize GC_write_cs only if THREADS.
+* misc.c (GC_init_inner): Use GC_INITIAL_HEAP_SIZE (if available) to
+set the default initial value of initial_heap_sz.
+* misc.c (GC_deinit): Destroy GC_write_cs only if THREADS.
+* misc.c (GC_init_inner): Fix WARN() format specifier (should be
+word-compliant, "%p" is used w/o "0x").
+* misc.c (GC_init_inner): Don't recognize "GC_PAUSE_TIME_TARGET"
+environment variable if SMALL_CONFIG.
+* misc.c (GC_init_inner): Recognize "GC_FULL_FREQUENCY" environment
+variable to set initial GC_full_freq value (if not SMALL_CONFIG).
+* doc/README.environment (GC_FULL_FREQUENCY): Add information.
+* doc/README.environment (GC_MARKERS): Refine information.
+* misc.c (GC_init_inner): Change GC_ASSERT to GC_STATIC_ASSERT where
+possible.
+* misc.c (IF_NEED_TO_LOCK): New macro (instead of GC_need_to_lock).
+* misc.c (GC_write): Use IF_NEED_TO_LOCK for handling GC_write_cs.
+* misc.c (GC_abort): Don't define if SMALL_CONFIG.
+* misc.c (GC_abort): Directly use WRITE() instead of GC_err_printf()
+(to prevent possible infinite recursion).
+
+* finalize.c (finalization_mark_proc): Replace K&R-style declaration
+with ANSI C one.
+* finalize.c (GC_grow_table, GC_register_finalizer_inner,
+GC_enqueue_all_finalizers): Remove outdated comments about disabling
+signals.
+* finalize.c (GC_general_register_disappearing_link): Fix assertion
+to catch NULL "obj" value.
+* finalize.c (GC_unregister_disappearing_link): Check "link"
+alignment before gaining the lock.
+* finalize.c (GC_finalize): Refine comment.
+* finalize.c (GC_finalize): Fix WARN() format specifier (should be
+word-compliant, "%p" is used w/o "0x").
+* finalize.c (GC_invoke_finalizers): Initialize "bytes_freed_before"
+variable (to 0) to suppress compiler warning.
+* include/gc_gcj.h (MARK_DESCR_OFFSET): Move to private/gc_pmark.h.
+* include/gc_gcj.h: add "extern C" header and tail.
+* include/private/gc_pmark.h: Remove GC_do_parallel_mark(),
+GC_help_wanted, GC_helper_count, GC_active_count declarations (move
+the comments to the place where these symbols are defined in mark.c).
+* mark.c: Add STATIC GC_do_parallel_mark() declaration (for use by
+GC_mark_some_inner, if PARALLEL_MARK only).
+* mark.c (GC_mark_some_inner, GC_help_wanted, GC_helper_count,
+GC_active_count, GC_do_parallel_mark): Define as STATIC.
+* pthread_support.c (GC_mark_thread): Likewise.
+* typd_mlc.c (GC_explicit_typing_initialized, GC_explicit_kind,
+GC_array_kind, GC_ext_descriptors, GC_ed_size, GC_avail_descr,
+GC_typed_mark_proc_index, GC_array_mark_proc_index, GC_eobjfreelist,
+GC_arobjfreelist): Likewise.
+* include/private/gc_pmark.h (PUSH_CONTENTS_HDR): Change GC_ASSERT
+for HBLKSIZE to GC_STATIC_ASSERT.
+* mark.c (GC_noop): Define for Borland C the same as for Watcom.
+* mark.c (GC_noop, GC_mark_and_push): Add ARGSUSED tag.
+* pthread_support.c (GC_do_blocking_inner): Likewise.
+* mark.c (GC_mark_from): Initialize "limit" (to 0) in the default
+switch branch to suppress compiler warning.
+* mark.c (GC_return_mark_stack): Append new-line to printf message.
+* mark.c: Remove unused GC_true_func(), GC_PUSH_ALL().
+* pthread_support.c (GC_mark_thread): Add dummy "return 0" to
+suppress compiler warning.
+* pthread_support.c (start_mark_threads): Move the code limiting
+"GC_markers" value (and printing a warning) to GC_thr_init().
+* pthread_support.c (GC_thr_init): Silently limit "GC_markers" value
+if based on the number of CPUs.
+* pthread_support.c (GC_thr_init): Treat incorrect "GC_markers"
+values as one.
+* pthread_support.c (GC_register_my_thread_inner): Add a check for
+"stack_end" is non-NULL (the same as in win32_threads.c).
+* pthread_support.c (pthread_create): Call GC_oom_fn before giving up
+with ENOMEM.
+* thread_local_alloc.c (return_single_freelist): Convert "for" loop
+to "while" one to suppress "possible extraneous ';'" warning.
+
+* darwin_stop_world.c (GC_push_all_stacks): Recognize ARM32.
+* include/private/gc_priv.h (GC_THREAD_STATE_T): Define for ARM32
+(Darwin only).
+* include/private/gcconfig.h: Add machine-specific part for DARWIN.
+* include/private/gcconfig.h (ARM32): Define config parameters for
+DARWIN (iPhone).
+
+* alloc.c (GC_FULL_FREQ, GC_DONT_EXPAND, GC_FREE_SPACE_DIVISOR,
+GC_TIME_LIMIT): New macros (used to control the default initial
+values of GC_full_freq variable, GC_dont_expand,
+GC_free_space_divisor, GC_time_limit respectively).
+* include/private/gc_priv.h (TIME_LIMIT): Remove macro (replaced
+with GC_TIME_LIMIT in alloc.c).
+* alloc.c (GC_need_full_gc, GC_stopped_mark, GC_finish_collection):
+Define as STATIC.
+* mark_rts.c (GC_push_current_stack, GC_push_gc_structures): Likewise.
+* include/private/gc_priv.h (GC_stopped_mark, GC_finish_collection):
+Move the prototypes to alloc.c, make STATIC.
+* include/private/gc_priv.h (GC_push_current_stack,
+GC_push_gc_structures, GC_push_regs_and_stack): Remove prototypes
+(move the comments to the places where these functions are defined).
+* mach_dep.c (GC_push_regs_and_stack): Move to mark_rts.c and define
+as STATIC.
+* alloc.c (GC_timeout_stop_func, GC_stopped_mark,
+GC_print_heap_sects): Convert a group of printf() calls into
+a single one (for output atomicity).
+* mark_rts.c (GC_print_static_roots): Likewise.
+* alloc.c (GC_stopped_mark): Output blank line (when logging) for
+convenience to delimit collections.
+* alloc.c (GC_clear_a_few_frames): Rename NWORDS to CLEAR_NWORDS;
+make "frames" local variable volatile (to prevent optimization).
+* alloc.c (GC_try_to_collect_inner, GC_stopped_mark,
+GC_finish_collection, GC_allocobj): Remove outdated comments about
+disabling signals.
+* include/private/gc_priv.h (GC_register_displacement_inner,
+GC_gcollect_inner): Likewise.
+* alloc.c (GC_try_to_collect_inner, GC_stopped_mark,
+GC_finish_collection): Initialize "start_time" local variable (to 0)
+to suppress compiler warning.
+* mark_rts.c (GC_add_roots_inner): Likewise.
+* alloc.c (GC_RATE, MAX_PRIOR_ATTEMPTS): Guard with "ifndef".
+* include/private/gc_priv.h (clock, GC_stop_world, GC_start_world,
+GC_acquire_mark_lock, GC_release_mark_lock, GC_notify_all_builder,
+GC_wait_for_reclaim, GC_notify_all_marker, GC_wait_marker): Replace
+K&R-style function prototypes with ANSI C one.
+* include/private/gc_priv.h (ABORT): Define as DebugBreak() for
+Win32/WinCE if SMALL_CONFIG (the same as in GC_abort()).
+* include/private/gc_priv.h (ROUNDED_UP_WORDS, abs): Remove unused
+macros.
+* include/private/gc_priv.h (GC_noop): Declare for Borland C the
+same as for Watcom.
+* mark_rts.c (GC_push_conditional_with_exclusions): Add ARGSUSED tag.
+
+* dbg_mlc.c (GC_store_debug_info, GC_store_debug_info_inner): Remove
+outdated comment about disabling signals.
+* mallocx.c (GC_malloc_uncollectable,
+GC_malloc_atomic_uncollectable): Likewise.
+* os_dep.c: Likewise.
+* dbg_mlc.c (GC_debug_change_stubborn, GC_debug_end_stubborn_change):
+Add ARGSUSED tag.
+* pthread_stop_world.c (GC_suspend_handler,
+GC_suspend_handler_inner): Likewise.
+* dbg_mlc.c (GC_debug_free, GC_debug_realloc): Fix printf message.
+* dbg_mlc.c (GC_debug_realloc): Set "result" to NULL in the default
+switch branch to suppress compiler warning.
+* dyn_load.c (GC_init_dyld): Use ABORT() instead of GC_abort().
+* include/private/darwin_semaphore.h (sem_init): Likewise.
+* include/javaxfc.h: Replace "GC_H" with "_GC_H".
+* include/private/dbg_mlc.h (GC_has_other_debug_info,
+GC_store_debug_info): Replace K&R-style function prototypes with ANSI
+C one.
+* include/private/gcconfig.h (GC_FreeBSDGetDataStart, real_malloc,
+GC_win32_get_mem, GC_wince_get_mem, GC_unix_get_mem): Likewise.
+* include/private/pthread_support.h (GC_stop_init): Likewise.
+* include/private/gcconfig.h: Refine comment about setting
+GC_stackbottom.
+* include/private/gcconfig.h (FIXUP_POINTER): Put parentheses in the
+"right" places.
+* include/private/pthread_support.h (GC_Thread_Rep): Refine comment
+for "stack_end" field.
+* mallocx.c (GC_malloc_uncollectable,
+GC_malloc_atomic_uncollectable): Remove cast to undefined "hbklk".
+* os_dep.c (GC_USE_MEM_TOP_DOWN): New macro (for setting
+GC_mem_top_down to MEM_TOP_DOWN for debug purposes).
+* os_dep.c (GC_gww_read_dirty, catch_exception_raise): Fix WARN()
+format specifier (should be word-compliant, "%p" is used w/o "0x").
+* pthread_stop_world.c (GC_suspend_handler_inner): Likewise.
+* os_dep.c (GC_dirty_init): Append new-line to printf messages.
+* os_dep.c (GC_mprotect_thread): Fix GC_err_printf message.
+* os_dep.c (GC_save_callers): Change GC_ASSERT to GC_STATIC_ASSERT.
+* pthread_stop_world.c (GC_retry_signals, GC_suspend_ack_sem): Define
+as STATIC.
+* pthread_stop_world.c (GC_push_all_stacks): Add assertion for that
+"thread_blocked" is not set for the current thread.
+* real_malloc.c: Add "extern GC_quiet" to suppress compiler warning.
+* reclaim.c (GC_reclaim_all): Initialize "start_time" (to 0) to
+suppress compiler warning.
+
+* tests/test.c (check_heap_stats): Avoid unbalanced brackets in ifdef.
+
+* win32_threads.c: restructure parallel marking mutex initialization.
+* win32_threads.c, alloc.c, darwin_stop_world.c, mallocx.c, mark.c,
+pthread_stop_world.c, pthread_support.c: Add runtime conditions
+on GC_parallel were appropriate.
+* pthread_support.c: Condition marker_bsp on ia64.
+(GC_segment_is_thread_stack): Fix loop upper bound.
+* reclaim.c: Limit some assertions to PARALLEL_MARK.
+* pthread_support.c: Don't acquire mark lock for thread-local
+allocation.
+* include/private/gc_priv.h: Don't define parallel mark sync
+support just for THREAD_LOCAL_ALLOC.
+
+* include/private/gcconfig.h: refine MINGW32 test.
+* mark.c: Add win64/gcc tests.
+
+* test.c (fork_a_thread, reverse_test, alloc8bytes, tree_test,
+typed_test, run_one_test, check_heap_stats, main, test): Replace
+all K&R-style function definitions with ANSI C ones.
+* trace_test.c (main): Likewise.
+* test.c (GC_COND_INIT): Define as GC_INIT() also in case of
+THREAD_LOCAL_ALLOC.
+* test.c (reverse_test): Call fork_a_thread() only if GC_PTHREADS
+or GC_WIN32_THREADS; remove fork_a_thread() macros definition.
+* test.c (reverse_test): Use "volatile" when clearing "b" and "c"
+local variables (to suppress "assigned value is never used"
+compiler warning).
+* test.c (tree_test): Use public GC_noop1() instead of private
+GC_noop().
+* test.c (typed_test): Likewise.
+* test.c (check_heap_stats): Define and assign value to
+"late_finalize_count" local variable only if its value is used
+(if FINALIZE_ON_DEMAND defined).
+* test.c (main): Remove DJGPP-specific initialization of
+GC_stackbottom (not needed anymore, handled in gcconfig.h).
+* trace_test.c: Guard #define GC_DEBUG with #ifndef.
+* trace_test.c: Include "gc_backptr.h".
+* trace_test.c (main): Call GC_INIT().
+* trace_test.c (main): Add "return 0" statement.
+
+* dyn_load.c (GC_register_dynlib_callback): Use new index j
+instead of i in the inner loop.
+
+* tests/test.c: Increment n_tests with fetch_and_add when possible,
+avoiding need to export lock.
+
+* include/gc_pthread_redirects.h:
+- dlfcn.h is included for dlopen() proto before undefining
+"dlopen" (so, it's possible now to include dlfcn.h after
+gc.h from user code);
+- GC_dlopen() proto is added (except for Darwin as
+it's missing there);
+- "dlopen" is explicitly undefined (before its redefinition).
+* include/gc.h:
+- "process.h" is included besides "windows.h"
+(for _beginthreadex/_endthreadex); win32 only.
+- GC_NO_THREAD_DECLS is moved to the right place
+(before closing "extern C").
+* pthread_support.c: Fix out of memory handling for Thread_Reps.
+* win32_threads.c: Don't include process.h on winCE,
+improve out of memory handling for thread structures, don't
+define GC_beginthreadex and GC_endthreadex for winCE.
+
+* tests/test.c: Change gcj vtable decriptor type from size_t to
+GC_word.
+
+* gcj_mlc.c: Add comment.
+* tests/test.c: Change NTEST to NTHREADS.  Fork 5 threads by default.
+Run reverse_test a second time in each thread.Add comments.
+Don't rely on AO_fetch_and_add.
+
+* dyn_load.c (GC_register_dynlib_callback,
+GC_register_dynamic_libraries_dl_iterate_phdr): Add support
+for GNU_PT_RELRO relocations.
+
+* Makefile, Makefile.direct: GC_SOLARIS_PTHREADS was replaced
+by GC_SOLARIS_THREADS.
+* include/gc.h: Improve finalizer documentation.
+* mips_sgi_mach_dep.s: Replace _MIPS_SIM_ABI32 with _ABIO32.
+* pthread_stop_world.c, Makefile.dj: Fix typos.
+
+* win32_threads.c (GC_new_thread): Make first_thread
+visible to the whole file.
+(UNPROTECT): New macro.
+(GC_push_stack_for, GC_suspend, GC_start_world): unprotect
+thread structures before writing.
+(GC_suspend): Acquire GC_fault_handler_lock before suspending
+thread.
+* os_dep.c: export GC_fault_handler_lock.
+(GC_remove_protection): Check if already unprotected.
+
+* doc/README.win32: Add OpenWatcom warning.
+* include/private/gcconfig.h: Really check it in.
+
+* os_dep.c (GC_get_stack_base, windows): Replace with Dave Korn's
+code from gcc version.
+* os_dep.c: make gc compilable (optionally) for Cygwin with
+GetWriteWatch-based virtual dirty bit implementation ("os_dep.c" file).
+* os_dep.c: Make non-win32 GC_write_fault_handler STATIC.
+* mark.c (GC_noop): fix declaration definition mismatch for DMC.
+* include/private/gcconfig.h: Enable MPROTECT_VDB and GWW_VDB for
+Watcom (Win32 only).  It works.
+
+* mach_dep.c: Don't use __builtin_unwind_init for register
+state on PowerPC/Darwin.
+
+* doc/gcdescr.html: Improve description of object freelist
+structure.
+* include/private/gc_priv.h: Fix comment for _size_map.
+
+* os_dep.c (GC_linux_stack_base): Relax sanity test.
+
+* include/private/gc_pmark.h (PUSH_CONTENTS_HDR for
+MARK_BIT_PER_OBJ): Add missing backslash before eoln.
+
+* misc.c (GC_set_warn_proc): Implicitly initialize GC on
+non-Cygwin win32.
+
+* configure.ac: Enable thread-local allocation for sparc-linux.
+
+* alloc.c (GC_try_to_collect): Remove duplicate initialization
+check.
+* malloc.c (GC_generic_malloc): Remove lw to eliminate single-
+threaded warnings.
+* mallocx.c (GC_generic_malloc_ignore_off_page): Likewise.
+
+* allchblk.c, backgraph.c, dbg_mlc.c, dyn_load.c,
+finalize.c, include/private/gc_pmark.h, malloc.c, mark.c,
+os_dep.c, pthread_stop_world.c, pthread_support.c, reclaim.c,
+thread_local_alloc.c.
+* misc.c: Refine comment.
+
+* os_dep.c: Define GC_GWW_BUF_LEN more intelligently.  Add FIXME
+comment.
+
+* win32_threads.c (GC_push_stack_for): Yet another attempt
+at the stack_min finding logic.  Try to clean up the existing code
+while minimizing VirtualQuery calls.
+(GC_win32_start_inner): Register thread before GC_printf.
+Produce more output with DEBUG_THREADS.
+*include/gc.h: Update obsolete comments.
+
+* tests/test.c:
+(gcj_class_struct2): Use cast instead of l suffix.
+Cast GetLastError to int in various places.
+Avoid unused result warning from incr/decr macros.
+Add cast for fake_gcj_mark_proc.
+Cast GC_gc_no to unsigned in printf.
+
+* include/gc.h: Fix two typos in comments.
+
+* finalize.c: Fix typo in comment.
+
+* blacklst.c (GC_print_source_pointer): Don't call GC_print_heap_obj
+with lock.
+
+* reclaim.c: (GC_reclaim_block): Scan even nearly full blocks
+if we are checking for leaks.
+
+* win32_threads.c: Remove mark lock spinning.
+* win32_threads.c, pthread_support.c: Update GC_unlocked_count,
+GC_spin_count, and GC_block_count using atomic operations.
+* tests/test.c: Declare n_tests as AO_t only if we have threads.
+
+* win32_threads.c: Support PARALLEL_MARK.  Make printf arg
+types agree with format specifiers.
+Add STATIC for GC_threads.
+* include/private/gcconfig.h: Add FIXME comment.
+* tests/test.c (run_ine_test): Replace LOCK/UNLOCK use with
+AO_fetch_and_add1_full.  Declare n_tests as AO_t.
+(WinMain): Don't call GC_use_DllMain.
+with PARALLEL_MARK or THREAD_LOCAL_ALLOC.
+
+* alloc.c (GC_try_to_collect_inner): Don't print redundant
+GC_bytes_allocd and GC_gc_no.
+(GC_stopped_mark): Print average world stop time.
+* include/private/gc_priv.h (MS_TIME_DIFF): Add cast.
+
+* misc.c, doc/README.environment: Add support  for
+GC_FREE_SPACE_DIVISOR and GC-disable-incremental.
+* include/gc.h: Make GC_set_free_space_divisor correspond to
+(somewhat unfortunate) reality.
+
+(Mostly improves LLP64 support.)
+* backgraph.c, checksums.c, dbg_mlc.c, finalize.c, mark.c,
+misc.c, reclaim.c: Changed some int and long type to word or size_t
+(and vice versa where appropriate)
+* gcj_mlc.c, include/private/dbg_mlc.h, include/private/gcconfig.h,
+include/private/thread_local_alloc.h, mark.c,
+misc.c, thread_local_alloc.c, win32_threads.c: Added intermediate
+casts to word type when casting from int to pointer (or pointer
+to int, or data pointer to code pointer) - just to remove the
+corresponding compiler warning.
+* ptr_chck.c (GC_is_visible): cast int const to word type to
+prevent left shift overflow.
+* os_dep.c: change the type of GC_mem_top_down global variable
+(containing a flag) to DWORD.
+* include/gc_config_macros.h: define GC_SOLARIS_THREADS if GC_THREADS
+is defined on SunOS x86_64.
+* misc.c (GC_init_size_map): Ifdef out GC_ASSERT as a workaround
+for VC++ 2008 amd64 (v15.00.21022.08 for x64) compiler bug
+(the compiler gets hung if invoked with -Ox -D
+ALL_INTERIOR_POINTERS -D GC_ASSERTIONS)
+* backgraph.c: cast GC_gc_no value to unsigned short when
+assigned/compared to height_gc_no field of back_edges.
+* os_dep.c (GC_remove_protection): Add ARGSUSED.
+* win32_threads.c (GC_thread_exit_proc): Remove unused local
+variable.
+* mark.c (GC_check_dirty): Move declaration out of func body.
+
+* doc/gcinterface.html: Improve REDIRECT_MALLOC documentation.
+* include/gc.h (GC_register_my_thread): Improve comment.
+
+* Makefile.direct: Add comment for -DCHECKSUMS.
+
+* thread_local_alloc.c, include/private/thread_local_alloc.h:
+Fix typos in comments.
+* finalize.c: Declare mark_procs and GC_register_finalizer_inner
+STATIC.
+* malloc.c (GC_free): Move size calculation below assertion.
+
+* win32_threads.c (GC_get_stack_min, GC_may_be_in_stack):
+Add one entry VirtualQuery cache, I_HOLD_LOCK assertions.
+(GC_push_stack_for, GC_get_next_stack) : Hopefully fix WINCE support.
+
+* finalize.c (GC_general_register_disappearing_link): Add
+assertion.
+* malloc.c (GC_generic_malloc): Round lb to granules, not words.
+* mallocx.c (GC_generic_malloc_ignore_off_page): Round lb to
+granules, not words.
+
+* mach_dep.c (NO_GETCONTEXT): Define for sparc linux.
+* configure.ac: Define mach_dep for sparc-linux.
+
+* mark_rts.c (GC_approx_sp): Use volatile to avoid common
+warning.
+
+* dyn_load.c (GC_cond_add_roots): Fix GC_get_next_stack argument
+order.
+
+* alloc.c, dbg_mlc.c, dyn_load.c, finalize.c, gcj_mlc.c,
+include/gc.h, include/gc_config_macros.h, include/gc_cpp.h,
+include/gc_gcj.h, include/gc_mark.h, include/gc_typed.h,
+include/javaxfc.h, include/private/gc_locks.h,
+include/private/gc_priv.h, malloc.c, mallocx.c, mark.c, mark_rts.c,
+misc.c, obj_map.c, os_dep.c, pthread_support.c, ptr_chck.c,
+stubborn.c, tests/test.c, thread_local_alloc.c, typd_mlc.c
+win32_threads.c: Add GC_CALL and GC_CALLBACK macro invocations.
+* test.c: Remove some old K&R code.
+
+* win32_threads.c (GC_may_be_in_stack): New.  (GC_Thread_Rep):
+Add last_stack_min.  (GC_push_stack_for): Use last_stack_min.
+(GC_get_next_stack): Add limit argument, use_last_stack_min.
+(GC_suspend): make stack_base assignment conditional.
+* dyn_load.c (win32 GC_cod_add_roots): Pass limit to
+GC_get_next_stack.
+* configure_atomic_ops.sh: Remove.
+* build_atomic_ops.sh, build_atomic_ops.sh.cygwin, doc/README.win32,
+Makefile.direct: Partially support build directories whose path
+name contains blanks.
+* Makefile.am: Support new files (build_atomic_ops.sh,
+build_atomic_ops.sh.cygwin)
+
+* include/private/gc_locks.h, include/private/gc_pmark.h,
+include/private/gc_priv.h, include/private/gcconfig.h,
+mach_dep.c, mark_rts.c, misc.c, os_dep.c, pthread_stop_world.c,
+pthread_support.c, thread_local_alloc.c, typd_mlc.c, win32_threads.c:
+Fix comments.
+
+* pthread_support.c: Comment out LOCK_STATS.
+* include/gc.h: Fix comments.
+
+* misc.c (GC_init_inner): Enable GC_LOG_FILE on Cygwin.
+* include/private/gcconfig.h: Consider USE_MMAP for Cygwin.
+* os_dep.c (GC_get_main_stack_base): Use alternate definition
+with USE_MMAP.
+* include/private/gc_priv.h: Sometimes define SETJMP on Cygwin.
+
+* doc/README: Make it clearer when Makefile.direct is assumed.
+* cord/cord.am: install include/cord.h.
+
+* win32_threads.c (GC_pthread_join, GC_pthread_start_inner):
+Remove unused variables.
+* darwin_stop_world.c: Always declare GC_thr_init().
+* dbg_mlc.c (GC_debug_free_inner): Don't touch oh_sz if
+SHORT_DBG_HDRS is defined.
+* include/private/gc_pmark.h (OR_WORD_EXIT_IF_SET, parallel
+mark, USE_MARK_BITS version): Refer to correct parameter name.
+
+* finalize.c (GC_general_register_disappearing_link): Remove
+redundant code.
+* gcj_mlc.c (GC_init_gcj_malloc): Add cast to signed.
+* os_dep.c: (GC_write_fault_handler): Remove remaining
+references to deleted variable "code".  Remove redundant
+FREEBSD definitions.
+* include/private/gcconfig.h (GWW_VDB): Define for X86_64 when
+defined for X86. (STATIC): Define as "static" with NO_DEBUGGING.
+
+* include/private/gc_priv.h: Update MAX_HEAP_SECTS.
+
+* dbg_mlc.c (GC_print_smashed_obj): Increase robustness with
+smashed string, (GC_debug_free_inner): Mark as free.
+* mallocx.c (GC_malloc_many): Always clear new block if
+GC_debugging_started.
+* reclaim.c: Move GC_debugging_started from
+GC_reclaim_small_nonempty_block() to GC_reclaim_generic(),
+which is also called directly.
+* doc/README: Fix spelling error.  Update license summary.
+* include/gc.h (GC_PRE_INCR3, GC_POST_INCR3): add (void **) casts.
+* tests/test.c: Don't define GC_DEBUG if already defined.
+
+* doc/simple_example.html: update --enable-full-debug reference,
+Make HTML formatting standards compliant.
+* doc/debugging.html, doc/leak.html: Fix HTML formatting bugs.
+* doc/gcinterface.html: specify encoding.
+
+* doc/simple_example.html: Update thread-local allocation
+description.
+
+* configure.ac: Check for gc-debug earlier; replace remaining
+full-debug tests.
+* include/gc.h, ptr_chck.c (GC_pre_incr, GC_post_incr):
+Use signed offset type.  Use ptr_t internally.
+* doc/gcinterface.html: Update LOCAL_MALLOC description.
+* doc/README.autoconf, doc/leak.html, doc/README.DGUX386:
+Fix full-debug reference.
+* include/gc.h: Rewrite GC_..._INCR and friends.
+* tests/test.c: Minimally test GC_..._INCR and friends.
+
+* mark.c: (GC_push_next_marked, GC_push_next_marked_dirty,
+GC_push_next_marked_uncollectable): Never invoke GC_push_marked
+on free hblk.
+* headers.c: Test COUNT_HDR_CACHE_HITS not USE_HDR_CACHE.
+(GC_header_cache_miss): Always blacklist pointers for free
+hblks.  Add assertion and comment.
+* pthread_support.c (GC_register_my_thread): Fix #if indentation.
+* include/private/gc_hdrs.h: USE_HDR_CACHE is no longer tested.
+Delete it.
+* include/private/gc_pmark.h: (PUSH_OBJ): Add assertion.
+
+* alloc.c, include/gc_mark.h, Makefile.direct: Improve comments.
+
+* configure.ac: Set win32_threads on MinGW.
+
+Ivan's description of the patch follows. Note that a few pieces like
+the GC_malloc(0) patch, were not applied since an alternate had been
+previously applied.  A few differed stylistically from the rest of
+the code (mostly casts to void * instead of target type),
+or were classified as too minor to bother.  Note that
+all of Ivan's static declarations which did not correct outright
+naming bugs (as a few did), where replaced by STATIC, which is
+ignored by default.
+
+- minor bug fixing (for FreeBSD, for THREAD_LOCAL_ALLOC and for
+GC_malloc(0));
+- addition of missing getter/setter functions for public variables
+(may be useful if compiled as Win32 DLL);
+- addition of missing GC_API for some exported functions;
+- addition of missing "static" declarator for internal functions
+and variables (where possible);
+- replacement of all remaining K&R-style definitions with ANSI
+C ones (__STDC__ macro is not used anymore);
+- addition of some Win32 macro definitions (that may be missing in
+the standard headers supplied with a compiler) for GWW_VDB mode;
+- elimination of most compiler warnings (except for
+"uninitialized data" warning);
+- several typos correction;
+- missing parenthesis addition in macros in some header files of
+"libatomic_ops" module.
+
+My highlights based on reading the patch:
+
+* allchblk.c: Remove GC_freehblk_ptr decl.
+Make free_list_index_of() static.
+* include/gc.h: Use __int64 on win64, define GC_oom_func,
+GC_finalizer_notifier_proc, GC_finalizer_notifier_proc,
+add getter and setters: GC_get_gc_no, GC_get_parallel,
+GC_set_oom_fn, GC_set_finalize_on_demand,
+GC_set_java_finalization, GC_set_dont_expand,
+GC_set_no_dls, GC_set_max_retries, GC_set_dont_precollect,
+GC_set_finalizer_notifier.  Always define GC_win32_free_heap.
+gc_config_macros.h: Define _REENTRANT after processing
+GC_THREADS.
+* include/gc_cpp.h: Improve GC_PLACEMENT_DELETE test,
+handling of operator new[] for old Windows compilers.
+* include/gc_inline.h (GC_MALLOC_FAST_GRANS): Add parentheses
+around arguments.
+* dbg_mlc.c, malloc.c, misc.c: Add many GC_API specs.
+* mark.c (GC_mark_and_push_stack): Fix source argument for
+blacklist printing.
+* misc.c: Fix log file naming based on environment variable
+for Windows.  Make GC_set_warn_proc and GC_set_free_space_divisor
+just return current value with 0 argument.  Add DONT_USE_USER32_DLL.
+Add various getters and setters as in gc.h.
+* os_dep.c: Remove no longer used GC_disable/enable_signals
+implementations.  (GC_get_stack_base): Add pthread_attr_destroy
+call.  No longer set GC_old_bus_handler in DARWIN workaround.
+* pthread_support.c: GC_register_my_thread must also
+call GC_init_thread_local.
+
+* Makefile.direct, mach_dep.c: Add support for NO_GETCONTEXT.
+* mach_dep.c: Include signal.h.
+* gc_priv.h: Factor out INLINE declaration.
+
+* include/private/gcconfig.h: Update MIPS/LINUX config.
+* doc/gcdescr.html: Fix typo.
+* mach_dep.c (GC_with_callee_saves_pushed): Don't rely on getcontext
+for MIPS/LINUX.
+
+* configure.ac: SPARC fixes.
+* thread_local_alloc.c(GC_mark_thread_local_fls_for): Include
+size 0, except for gcj.
+* doc/gc.man: Expand C++ cautions.
+* include/gc_inline.h: Fix comments.
+
+
+== [7.1] 2008-05-03 ==
+
+* doc/gcinterface.html: Improve C++ interface documentation.
+
+* allchblk.c (GC_allochblk): Check for overflow during size
+rounding.
+* tests/huge_test.c: New.
+* Makefile.direct, tests/tests.am: Add huge_test.c
+
+* pthread_support.c: Fix typo in comment.
+* os_dep.c (GC_win32_get_mem): Add heap section only if
+allocation succeeded.
+
+* malloc.c: (free replacement) Fix caller address space check.
+
+* finalize.c (GC_grow_table): Dereference table in null-check.
+
+* win32_threads.c (GC_delete_gc_thread, GC_delete_thread):
+Consistently call CloseHandle. (GC_suspend): Call
+GC_delete_gc_thread.
+* tests/test.c: Don't reference GC_print_stats if not exported.
+
+* tests/test.c (run_one_test): Don't mention pthread_self().
+* misc.c: Declare GC_thr_init().
+
+* allchblk.c (add_to_fl): disable assertions with USE_MUNMAP,
+and refine assertions to handle huge unmergable blocks.
+(GC_allochblk_nth): Add comment.
+
+* include/private/gcconfig.h: Add missing FREEBSD macro
+consistency test.
+
+* allchblk.c (GC_enough_large_bytes_left): No longer take
+parameters; return free list index bound.
+(GC_merge_unmapped): Don't access nexthdr until after null test.
+(Fixes bug in 1/29/08 check-in.)  (GC_allochblk): Calculate
+when splitting is allowable only once here, not when considering each
+block. (GC_allchblk_nth): Accept new may_split parameter.
+Avoid some redundant tests for exact size matches.
+* alloc.c (GC_should_collect): Cache min_bytes_allocd.
+(GC_maybe_gc): Make locking assertion testable.
+* mark_rts.c: Fix indentation.
+* pthread_stop_world.c: Replace old GC_err_printf1 reference.
+* tests/test.c: Remove (void) casts.  Optionally print some
+timing information.
+
+* windows-untested/gc.def: Remove CreateThread line.
+* windows-untested/README: New file.
+* win32_threads.c (GC_use_DllMain): Force collector initialization.
+* include/gc.h (GC_use_DllMain): Clarify usage rules in comment.
+* mark.c (GC_mark_from): Slightly simplify GC_DS_PER_OBJECT code.
+* include/gc_cpp.h: Add matching placement delete overloads
+everywhere.
+* include/private/gc_locks.h (NO_THREAD): Add cast.
+* include/private/gcconfig.h: Add test for __HP_aCC.
+* configure.ac, tests/tests.am:  Avoid libgccpp on HP/UX.
+
+* doc/README.win32: Fix typo.
+* configure.ac: Fix printing of enable-shared result.
+
+* misc.c (GC_init_inner): Assert !GC_need_to_lock only when
+defined.  (GC_call_with_stack_base): Add GC_API.
+* os_dep.c (GC_get_stack_base): Add GC_API.
+* win32_threads.c: (GC_register_my_thread, GC_unregister_my_thread):
+Add GC_API.
+* include/gc.h: Add GC_API annotations.
+* include/private/gc_locks.h: Define UNCOND_LOCK etc. also for
+PCR.
+* include/private/gc_pmark.h: Fix comments.
+
+* include/private/gc_priv.h, mark_rts.c, typd_mlc.c:
+Add GC_push_typed_structures() to push GC_ext_descriptors.
+
+* tests/test.c: Call GC_INIT for DARWIN; test system type using
+gcconfig.h-defined macros.
+
+* allchblk.c (GC_merge_unmapped, GC_freehblk): Refuse to create
+blocks large enough that their size, when interpreted as a signed
+value, would be negative.
+* include/private/gc_priv.h: Comment hb_sz range limit.
+
+* mark.c (GC_push_next_marked): correct comment.
+* Makefile.direct: document NO_PROC_STAT.
+* include/private/gcconfig.h: Accommodate NO_PROC_STAT.
+
+
+== [7.1alpha2] 2008-01-10 ==
+
+* Makefile.am: Mention atomic_ops.c and atomic_ops_sysdeps.S
+again.  Refer to build directory as ".".
+
+* configure.ac: Ignore --enable-parallel-mark on Darwin for now.
+* darwin_stop_world.c: Add FIXME comment for parallel marker.
+
+* include/private/gc_priv.h: Update MAX_ROOT_SETS
+and LOG_PHT_ENTRIES to handle larger heaps.
+
+* include/gc.h (GC_INIT,GC_init): Update comments.
+
+* allchblk.c, alloc.c, include/private/gc_priv.h:
+Track GC_bytes_dropped and use in GC triggering decisions.
+* alloc.c (min_bytes_allocd): Weight atomic blocks less.
+
+* alloc.c (GC_add_to_heap): Call GC_install_header(p) AFTER
+adjusting p.
+
+* Makefile.am: Add NT_X64_THREADS_MAKEFILE.
+
+* NT_X64_STATIC_THREADS_MAKEFILE: Clean up obsolete comment.
+* alloc.c: Add declaration for GC_add_current_malloc_heap.
+* win32_threads.c (GC_beginthreadex): Clean up error
+return code.
+* doc/README.win64, NT_X64_THREADS_MAKEFILE, Makefile.direct:
+Add NT_X64_THREADS_MAKEFILE.
+
+* alloc.c: Define GC_version instead of in version.h.
+* version.h: Remove.
+* include/gc_version.h: Move most of version.h here.
+* include/gc.h: Include gc_version.h.
+* gcname.c, add_gc_prefix.c: include gc.h instead of version.h.
+* Makefile.direct, Makefile.dj, Makefile.am, include/include.am:
+Adjust for version.h rename.
+
+* configure.ac: Put libatomic_ops links in build directory.
+* Makefile.am: Don't mention atomic_ops.c and atomic_ops_sysdeps.S
+as nodist sources.
+
+* include/gc.h, doc/README.macros: Add GC_NO_THREAD_REDIRECTS,
+GC_NO_THREAD_DECLS, don't test explicitly for GC_SOLARIS_THREADS.
+
+* alloc.c: Deal correctly with address wrapping for
+GC_greatest_plausible_heap_addr and GC_least_plausible_heap_addr.
+* finalize.c, include/gc.h (GC_register_disappearing_link,
+GC_register_finalizer_inner): Improve out-of-memory handling.
+* include/private/gc_pmark.h: Fix comment spelling.
+
+* include/gc_inline.h, include/gc_tiny_fl.h: cleanups to make usable
+in other contexts.
+
+* include/gc.h: Don't define GC_HAVE_BUILTIN_BACKTRACE for uclibc.
+
+* gc_cpp.cc: Don't include gc_cpp.h from local directory.
+
+* allchblk.c, configure.ac (add --enable-munmap)
+
+* dyn_load.c (GC_dyld_image_add): Remove ifdef clause and use the macro
+GC_GETSECTBYNAME instead.
+* include/private/gc_priv.h: Define GC_GETSECTBYNAME according to the
+architecture (Darwin).
+
+* reclaim.c (GC_bytes_found): Expand comment.
+* thread_local_alloc.c (GC_malloc_atomic, GC_gcj_malloc): Pass
+granules, not bytes, to GC_FAST_MALLOC_GRANS.
+* include/gc.h: Never include gc_local_alloc.h.
+* tests/test.c: Add size zero allocation tests.
+
+* malloc.c: Update GC_large_allocd_bytes on explicit deallocation.
+* allchblk.c: Sanity check GC_max_large_allocd_bytes.
+
+* Makefile.direct: Invoke $(MAKE) instead of make.
+
+* doc/scale.html: Reflect gc7 thread local allocation behavior.
+
+* include/extra/gc.h, include/extra/gc_cpp.h: New.
+* include/include.am: Install gc.h and gc_cpp.h in $(prefix)/include
+again.
+
+* pthread_support.c (GC_thr_init): Use sysconf(_SC_NPROCESSORS_ONLN)
+for HURD.
+
+* include/private/gcconfig.h: Add Linux/mips-64 support.
+
+* dbg_mlc.c: Use random() on all glibc systems.
+* mach_dep.c (GC_with_callee_saves_pushed): Don't use getcontext() on
+HURD.  Add comment.
+* pthread_stop_world.c (GC_suspend_handler, GC_stop_init): Accommodate
+systems without SA_SIGINFO.
+
+* include/gc.h (GC_PTR_STORE): Fix non-DEBUG parentheses.
+* tests/test.c (run_one_test): Add GC_PTR_STORE test.
+No longer test for RS6000.
+
+* alloc.c, backgraph.c, headers.c, include/private/gc_priv.h:
+Maintain GC_our_memory and GC_n_memory.
+* dbg_mlc.c (GC_print_smashed_obj): Improve message.
+(GC_print_all_smashed_proc): Pass client object address instead of
+base.
+* dyn_load.c (sort_heap_sects): New.  (GC_register_map_entries):
+Register sections that are contiguous and merged with our heap.
+* malloc.c, os_dep.c (GC_text_mapping): Check for just base name
+of libraries.
+* malloc.c (calloc): Check for special callers even with
+USE_PROC_FOR_LIBRARIES. Move assertion.  Add rudimentary
+malloc/free tracing.
+* misc.c: No longer call GC_init_lib_bounds explicitly.
+* thread_local_alloc.c (GC_malloc, GC_malloc_atomic): Always
+initialize on demand.
+* tests/test.c: Call GC_INIT only when required.
+
+* Makefile.direct: Remove comment fragment.
+* tests/tests.am: Add smashtest.
+* configure.ac: Define GC_USE_DLOPEN_WRAP with redirect-malloc.
+* pthread_support.c: Fix comment spelling.
+* include/private/gcconfig.h: Define USE_PROC_FOR_LIBRARIES with
+GC_LINUX_THREADS and REDIRECT_MALLOC.
+* tests/smash_test.c: Initial check-in.
+* obj_map.c: Print log entry to correct file.
+* include/private/thread_local_alloc.h: Add TlsAlloc error check.
+
+* alloc.c (GC_stopped_mark): Call GC_add_current_malloc_heap()
+while world is still running.
+* os_dep.c (GC_is_heap_base): Don't call GC_add_current_malloc_heap()
+with world stopped.
+* include/gc.h (GC_INIT for cygwin): Always call GC_add_roots.
+* misc.c (GC_init/GC_init_inner): Perform all work in
+GC_init_inner.
+* Makefile.direct: Expand -DUSE_MUNMAP comment.
+
+* include/gc.h: Define uintptr_t explicitly for VC++6.
+* msvc_dbg.c (GetModuleBase): Revert to strcat if strcat_s doesn't
+exist.
+
+
+== [7.0] 2007-07-02 ==
+
+* include/gc_config_macros.h: Also check for IA64 when setting
+GC_HPUX_THREADS.
+* mallocx.c: Change my_bytes_allocd to signed_word.
+* include/gc_pthread_redirects.h: Remove obsolete Solaris threads
+(as opposed to pthreads) support.
+
+* mach_dep.c (GC_with_callee_saves_pushed): Don't use getcontext()
+on ARM/Linux.  Check getcontext() return value.
+
+* backgraph.c (per_object_func): Make argument types consistent.
+(GC_traverse_back_graph): Mark GC_deepest_obj.
+
+* finalize.c (GC_finalize): Change dl_size and fo_size to size_t.
+* os_dep.c (GC_win32_get_mem): Add GC_mem_top_down option.
+
+* doc/README.win32, doc/README, README.QUICK: Fix some of the worst
+anachronisms.
+* dyn_load.c: Partially support cygwin, but don't enable it yet.
+
+* Makefile.am: Use -no-undefined for libgc.
+* Makefile.direct: Document USE_PROC_FOR_LIBRARIES.
+* dyn_load.c (GC_register_map_entries): Rename prot_buf to prot
+consistently.
+* misc.c: Fix some WARN calls.  Move GC_is_initialized setting and
+GC_thr_init() call.
+* os_dep.c: Consistently use WARN where appropriate.
+* thread_local_alloc.c: Revert change to GC_WIN32_THREADS test.  Instead
+remove inappropriate pthread.h include.
+* doc/README.linux: Remove some anachronisms.
+
+* alloc.c: Also use GC_check_tls on non-Linux systems.
+* mallocx.c (GC_reclaim_generic): Remove bogus declaration.
+* include/private/gc_priv.h (GC_reclaim_generic): Declare correctly
+with prototype.
+
+* alloc.c (GC_adj_bytes_allocd): Avoid (long) casts, fix comment.
+(GC_print_heap_sects): Use size_t instead of unsigned long.
+* thread_local_alloc.c (GC_lookup_thread): Define in the correct
+context.
+* win32_threads.c, include/gc_config_macros.h: The last of Romano
+Paolo Tenca's patch.  Move stdint.h include to gc_config_macros.h.
+* include/gc_inline.h: Avoid gc_priv.h dependencies.
+* tests/test.c (check_heap_stats): Replace unsigned long with size_t.
+
+* NT_X64_STATIC_THREADS_MAKEFILE: Replace obsolete -debugtype:cv.
+* mark_rts.c (GC_push_roots): Fix kind type.
+
+* doc/README.win64: New file.
+* doc/doc.am, Makefile.direct: Add README.win64.
+
+* Makefile.am, Makefile.direct: Add NT_X64_STATIC_THREADS_MAKEFILE.
+* NT_X64_STATIC_THREADS_MAKEFILE: Fix warning flags.
+* allochblk.c, alloc.c, blacklst.c, dbg_mlc.c, dyn_load.c,
+finalize.c, headers.c, mach_dep.c, malloc.c, mark.c, misc.c,
+obj_map.c, os_dep.c, ptr_chck.c, reclaim.c, typd_mlc.c,
+win32_threads.c, cord/de_win.c, include/gc_mark.h,
+include/private/gc_hdrs.h, include/private/gc_pmark.h,
+include/private/gc_priv.h, tests/test_cpp.cc:
+Replace old style function declarations.  Clean up integral types.
+Remove register declarations.  The change in malloc.c and the
+"int descr" declaration in mark.c are the most likely to have
+been real bugs outside of win64.
+* msvc_dbg.c: Disable on win64.
+* win32_threads.c: Add AMD64 support.
+* include/gc.h: no backtrace on AMD64 for now.
+
+* msvc_dbg.c(GetModuleBase): Replace strcat with strcat_s.
+
+* include/gc.h: (GC_word, GC_signed_word): Fix win64 definitions.
+Don't include windows.h in an extern "C" context.
+* include/private/gcconfig.h: Fix win64/X86_64 configuration.
+* tests/test.c: Eliminate more old style function definitions.
+Cleanup pointer and integer casts for win64.
+* tests/test_cpp.cc: Don't include gc_priv.h.
+* NT_STATIC_THREADS_MAKEFILE: Restrict suffixes for VC++ 2005.
+* NT_X64_STATIC_THREADS_MAKEFILE: New.
+
+* win32_threads.c: Separate out DEBUG_WIN32_PTHREADS_STACK.  Ignore
+FINISHED threads for suspension.  (GC_pthread_join): Add
+pthread_self() cast.  (GC_pthread_start_inner): Execute cleanup
+handler when popping it.
+* include/private/gc_locks.h: Inline THREAD_EQUAL for
+GC_WIN32_PTHREADS.  Define USE_PTHREAD_LOCKS only if we have
+pthreads.
+
+* gc_dlopen.c, thread_local_alloc.c, threadlibs.c, win32_threads.c,
+tests/test.c: Accommodate GC_WIN32_PTHREADS.
+* include/gc.h: Don't include windows.h for GC_WIN32_PTHREADS.
+* include/gc_config_macros.h: Define both PTHREADS and
+GC_WIN32_THREADS.
+* include/private/gc_locks.h: Nonstandard definitions of
+NUMERIC_THREAD_ID for GC_WIN32_PTHREADS.
+* doc/README.win32, Makefile.direct: Include documentation
+for GC_WIN32_PTHREADS.
+* Makefile.direct: Remove some anachronisms in the documentation.
+
+* Makefile.am: Move includes to bottom.  Add better library
+dependencies.  Increment library version.  Remove "SUBDIRS += .".
+* cord/cord.am, tests/tests.am: Add better library dependencies.
+Remove now unnecessary dependencies.
+* include/gc.h (GC_beginthreadex, GC_endthreadex, GC_ExitThread):
+Move to define on all Windows platforms.  (_beginthread): define
+to generate error if used.
+
+* include/private/gc_locks.h: Format to 80 columns.
+
+* malloc.c(GC_free): Ignore bad frees on MSWIN32 with REDIRECT_MALLOC.
+* NT_MAKEFILE: msvc_dbg.h is in include/private.  Don't use cvars
+rc.
+* misc.c (WIN32 GC_write): Define GC_need_to_lock in single-threaded
+case.
+* win32_threads.c: Test for __MINGW32__ in addition to _MINGW_VER.
+(GC_CreateThread, GC_beginthreadex): Deallocate args even if we fail.
+* include/gc.h: Add GC_reachable_here().  (GC_WinMain): Add GC_API.
+(GC_beginthreadex, GC_endthreadex, GC_ExitThread): Declare.
+* tests/test.c: Add GC_reachable_here() call.
+
+* alloc.c (GC_try_to_collect): Call GC_init if necessary.
+* tests/thread_leak_test.c: Don't unconditionally define
+GC_LINUX_THREADS.
+
+* Makefile.am: Remove extra_ldflags_libgc definition.
+
+* include/private/gc_priv.h: Define AO_REQUIRE_CAS.
+
+* finalize.c (GC_unreachable_finalize_mark_proc): Don't return void
+value.
+
+
+== [7.0alpha9] 2007-05-15 ==
+
+* Some gc6.9 changes.
+* Change FindTopOfStack decl in darwin_stop_world.c.
+* Move some static tests from misc.c to gcconfig.h.  Use #error.
+* Add GC_print_free_list() function (thanks to Bruce Hoult).
+* Add GC_GNU_THREADS support on HURD (thanks to Aleksey Demakov,
+Barry DeFreese, and possibly other Debian maintainers).
+* __GNUC__ was misspelled as __GNUC in thread_local_alloc.h (thanks to
+Peter Wang).
+* Integrated various MacOSX patches and tried to reconcile them (thanks to
+Allan Hsu, several contributors at Apple, and probably others).
+* Added some casts to powerpc.h in libatomic_ops to silence warnings.
+
+* Makefile.am: Include NT_STSTIC_THREADS_MAKEFILE in dist.
+* include/private/gc_locks.h: GC_compare_and_exchange, GC_atomic_add:
+remove. NUMERIC_THREAD_ID, THREAD_EQUAL: New.  GC_lock_holder: now
+unsigned long.  I_DONT_HOLD_LOCK, I_HOLD_LOCK: Update.
+* pthread_stop_world.c, pthread_support.c, win32_threads.c: Use
+NUMERIC_THREAD_ID, THREAD_EQUAL.
+* include/private/gcconfig.h: GENERIC_COMPARE_AND_SWAP: Remove.
+* include/private/thread_local_alloc.h: Don't USE_COMPILER_TLS on
+ARM.
+
+* dbg_mlc.c, include/gc.h, finalize.c: Merge Alexandre Oliva's
+GC_debug_register_finalizer_unreachable() patch from gcc tree.
+* thread_local_alloc.c (GC_malloc, GC_malloc_atomic): Add assertions
+to check GC has been initialized.
+
+* include/gc_cpp.h: Documentation updates.
+* include/gc_config_macros.h: Don't check for __ppc__ to set
+DARWIN_THREADS.
+* Makefile.am: Include configure_atomic_ops.sh in dist.
+
+* Makefile.am: Don't distribute copied atomic_ops files.  Include
+libatomic_ops with "make dist".
+* configure.ac: Enable THREAD_LOCAL_ALLOC for Cygwin with threads.
+* win32_threads.c: Report error for Cygwin + GC_DLL.
+
+* Makefile.direct: Update THREAD_LOCAL_ALLOC documentation.
+* cord/de_win.c: Rename and move AboutBox.  Call GC_INIT.  Remove
+MakeProcInstance anachronism.
+* doc/README.macros: Officially remove elif prohibition.
+Remove documentation for defunct SRC_M3 support.
+* include/gc.h: Remove more SRC_M3 references.
+* include/private/gcconfig.h: Remove still more SRC_M3 references.
+GC_SOLARIS_THREADS no longer needs to be checked separately.
+
+* thread_local_alloc.c, include/private/thread_local_alloc.h:
+Spell __declspec correctly.
+* NT_STATIC_THREADS_MAKEFILE: Enable thread-local allocation.
+
+* doc/README.win32: Adjust GC_win32_dll_threads rules again.
+
+* mark.c (GC_mark_some wrapper): Restructure for readability, handle
+GC_started_thread_while_stopped.
+* misc.c (Win32 GC_write): Lock GC_write_cs only if needed.
+* win32_threads.c: (client_has_run): remove,
+GC_started_thread_while_stopped, GC_attached_thread: add.
+(GC_push_all_stacks): Add verbose output.
+(DllMain): Avoid initializing collector or the like.
+Never update both thread tables.
+* doc/README.win32: Adjust GC_win32_dll_threads rules.
+
+* pthread_stop_world.c (GC_push_all_stacks): Print thread count with
+GC_PRINT_VERBOSE_STATS.
+
+* configure.ac: Comment out redundant
+AC_DEFINE(NO_EXECUTE_PERMISSION).
+* sparc_mach_dep.S: Remove single quote in comment.
+* include/private/gcconfig.h: Fix DATAEND for NONSTOP.
+* win32_threads.c: Include stdint.h for Mingw.  Add GC_API for DllMain.
+(GC_use_DllMain): Fix assertion.
+
+* configure.ac: Introduce extra_ldflags_libgc. Use it for Darwin.
+* Makefile.am (libgc_la_LDFLAGS): Use extra_ldflags_libgc.
+* include/private/gcconfig.h: Enable MPROTECT_VDB for all Darwin
+targets. Remove comments.
+Prepare ppc64 support for Darwin.
+
+* darwin_stop_world.c (GC_push_all_stacks): Fix compiler warnings.
+Make i unsigned.
+(GC_stop_world): Likewise. Remove unused GC_thread p.
+(GC_start_world): Likewise.
+
+* os_dep.c: Define GC_darwin_register_mach_handler_thread extern.
+Remove double SIG_HNDLR_PTR definition.
+(GC_forward_exception): Fix compiler warnings, make i unsigned.
+Initialize thread_state to NULL.
+(catch_exception_raise): Fix compiler warnings, make i unsigned.
+
+* include/private/gc_priv.h (NEED_FIND_LIMIT, FREEBSD variant):
+also define for X86_64.
+* configure.ac: Move generic gnu (Hurd) case to below kfreebsd case.
+* README.changes: Point to ChangeLog.
+
+* darwin_stop_world.c: Move THREAD_FLD defines to ...
+* include/private/gc_priv.h: ... here.
+Fix THREAD_STATE definitions for ppc64.
+* os_dep.c (catch_exception_raise): Use THREAD_FLD for exc_state member
+access.
+
+* configure.ac (i586-darwin): Replaced HAS_I386_THREAD_STATE_* with
+HAS_X86_THREAD_STATE32_*.
+(x86_64-*-darwin*): Extended the above check for x86_64-*-darwin* with
+HAS_X86_THREAD_STATE64_*.
+Added value 1 in the above AC_DEFINE's. Important for the upcoming
+Leopard.
+* include/private/gcconfig.h: Modified X86_64 define for Darwin.
+Removed __x86_64__ check in POWERPC section. Added base definitions
+for the X86_64 Darwin port.
+* include/private/gc_priv.h: Added GC_MACH_HEADER and GC_MACH_SECTION
+to distinguish between 32 and 64-bit applications. Added definitions
+for X86_64 Darwin.
+* darwin_stop_world.c: Added HAS_X86_THREAD_STATE64___RAX. And
+replaced HAS_I386_THREAD_STATE___EAX with HAS_X86_THREAD_STATE32___EAX.
+(GC_push_all_stacks): Added code for X86_64 Darwin. Even for the
+!DARWIN_DONT_PARSE_STACK. Maybe obsolete.
+* dyn_load.c (GC_dyld_name_for_hdr): Use GC_MACH_HEADER.
+(GC_dyld_image_add): Use GC_MACH_HEADER and GC_MACH_SECTION.
+Distinguish between getsectbynamefromheader_64 and
+getsectbynamefromheader.
+* os_dep.c (catch_exception_raise): Introduce exception definition for
+X86_64 Darwin. Replaced old i386_EXCEPTION_STATE_* definition with
+x86_EXCEPTION_STATE32_*. Add X86_64 for exc_state.faultvaddr.
+
+
+== [7.0alpha7] 2006-09-19 ==
+
+* More 6.7 changes.
+* Declare GC_dump() in gc.h.
+* Add --enable-large-config, which just defines the LARGE_CONFIG macro.
+* Make GlobalAlloc address alignment a bit more intuitive (thanks to
+Charles Mills).
+* Use #elif in the definitions of GET_MEM.
+* Overhaul porting.html.  Remove corresponding text from README.
+* Fix typo in DARWIN section of gcconfig.h.
+* Fix Darwin thread memory leak (thanks to Bruce Mitchener).
+* Update x86 AO_test_and_set implementation to use "=q".
+* Add $(EXEEXT) to many tests in tests/tests.am.  (Corresponds to a
+6.7 fix, which no longer applied.)
+* Fix Darwin/PPC port.
+* Fix Cygwin/threads port.
+* Fix gcj malloc support.
+* For GNU-style make, don't build libatomic_ops unless threads are requested.
+This should allow single-threaded builds on platforms which do not
+currently support libatomic_ops.
+* Clean up and hopefully fix the CFLAGS calculation for GNU build.
+(Substantially improves things on HP/UX.)
+* Integrated Andrei Polushin's Visual C++ patches.  These provide for
+stack traces, better C++ debug support, and better log file handling.
+Note that these change the location of the log file to a the path of the
+executable with a .log extension.  To get the old behavior back, define
+OLD_WIN32_LOG_FILE.  For the time being, I'm checking his project
+files and the like into a windows-untested subdirectory.  They
+are almost certainly already out of date, but better than what we had
+before.
+* Fixed some win32 threads bugs, and added support for _beginthreadex.
+* Fix zero size thread local allocation so that explicit deallocation
+works correctly.
+* Removed serious bug in GC_malloc_uncollectable(large size).
+* Do not try to do thread-local gcj allocation in incremental mode.  There
+are races in setting up the descriptor.
+* Add GC_INIT() to middle.c, fix some more GC_printfn calls.
+* Some assertions erroneously used I_HOLD_LOCK() negatively, even though
+it can now spuriously return TRUE.
+* Rename SUNOS5 macro and OS name to SOLARIS and SUNOS5DL to SOLARISDL.
+* On Linux and some Un*x variants, allocate memory by first trying sbrk,
+and then switching to mmap if that fails.
+* Fixed /proc/x/maps reading to deal with asynchronous deletions.
+* Fix REDIRECT_MALLOC with threads on Linux.  It now usually seems to work
+with ugly hacks that include having calloc behave differently when it is
+called from ld.so or the pthreads library.  A reasonable amount of
+infrastructure was added to support some of this.  (Thanks to Roland McGrath
+for ideas and information.)
+* Import various updated build scripts.
+* Add GC_register_has_static_roots_callback (thanks to Andrew Haley).
+* Fix serious bugs in GC_malloc_atomic_uncollectable().
+* Return GC_SUCCESS form GC_get_stack_base().
+* Fix several atomic_ops problems on IA64 with HP Compiler.
+* Update to atomic_ops-1.2.
+* Fix hb_n_marks description and reclaim.c assertion.
+* Various additional win32 threads fixes.
+* Enable GC_ASSERTIONS for Debug build with NT_THREADS_MAKEFILE.
+
+
+== [7.0alpha5] 2005-09-29 ==
+
+* More 6.6, 6.7 changes.
+* Some Solaris fixes, including some more general changes in how
+the assembly pieces of mach_dep.c are handled.
+* Removed a lot of SOLARIS_THREADS-specific code that was only
+needed with the old implementation.  This included many (mostly no-op)
+versions of GC_is_fresh.
+* Don't use atomic_ops in gc_locks.h unless we need threads.
+* Fixed USE_MARK_BITS, which is once again the default without PARALLEL_MARK.
+* Removed Solaris GC_INIT hack.  It's a workaround for a long dead bug,
+and it seemed to be wrong anyway.
+* Changed win32_threads.c to require preprocessor-based interception
+of thread routines by default.  A client call to GC_use_DllMain is
+now required to get the old behavior in which DllMain is used to implicitly
+register threads.  This was done for uniformity with other platforms, and
+because the DllMain solution seemed to require very tricky code which,
+at least in the past, imposed hard bounds on the number of threads.
+* Many small changes to make thread support work again on Cygwin.
+* Moved definition of allocator lock etc. to pthread_support.c and
+win32_threads.c for those two cases.
+* Got rid of the FASTLOCK() machinery.  It doesn't seem useful on modern
+platforms.
+* Cleaned up the uncollectible allocation routines, speeding up the
+slower paths.  The code did enough unnecessary work off the critical path
+that the underlying logic was getting hard to extract.
+* No longer turn off THREAD_LOCAL_ALLOC with DBG_HDRS_ALL.  Indications
+are it just works, and I think the reasons for it not working disappeared
+a while ago.
+* Fixed bugs in hb_n_marks calculation and assertion.
+* Don't use __builtin_expect for pre-3.0 gcc.
+* Define GWW_VDB only for recent Microsoft tool chains.
+* Add overview.html to doc directory.
+* Fix NT_STATIC_THREADS_MAKEFILE, various compiler warnings.
+* Made thread local allocation sort of work with Cygwin.  The code should
+be there to deal with other Windows variants, But non-Cygwin Windows
+threads need more bug fixes.
+
+
+== [7.0alpha4] 2005-08-02 ==
+
+* Various 6.5, 6.6 changes.
+* Removed GC_brief_async_signal_safe_sleep and used atomic_ops instead
+(thanks to Ben Maurer).
+* Integrated build patches from Davide Angelocola and Petter Urkedal.
+* Fix dynamic-linker-based pthread call redirection.
+* Renamed RS6000 to POWERPC/AIX.
+* Allow recovery from SIGSEGV in marker on Linux.  This works around
+a race in thread stack marking if /proc is used to find roots.  We do
+that by default with malloc redirection and threads.  This involved
+moving some GC_find_limit and SETJMP related declarations to gc_priv.h.
+* Added doc/porting.html file.
+* Added ADD_HEAP_GUARD_PAGES for sbrk/*nix platforms to debug extreme
+memory overwrite errors.
+* Added trivial NO_INCREMENTAL flag to facilitate debugging.
+* Added GC_getattr_np-based GC_get_stack_base (untested).
+* Separated thread local allocation into a separate file and added the
+beginning of win32 support for that.
+
+
+== [7.0alpha3] 2005-04-28 ==
+
+* Added support for dlopen-based interception of pthread functions.
+This is only half done.  The gc.h redefinitions currently interfere.
+* Integrated major automake overhaul from Petter Urkedal.
+
+
+== [7.0alpha2] 2005-04-07 ==
+
+* GC_bytes_allocd was incremented by a possibly uninitialized variable
+in GC_generic_malloc_inner.  (Bug introduced in gc7.0alpha1.  Thanks
+to Ben Hutchings for tracking it down.)
+* Win32 fixes (thanks to Ben Hutchings and Maurizio Vairani).
+* Integrated Ben Hutchings' GetWriteWatch-based virtual dirty bit
+implementation for win32.
+* Removed pc_gc.tar and floppy targets in Makefile.direct.  Removed
+pc_excludes file.
+* No longer include GC_bytes_wasted when evaluating allocation progress.
+Since we are now counting live memory, it no longer makes sense.
+* Applied Davide Angelocola's configure patch.  There are now separate
+Makefile.am's in the cord and tests subdirectory, more tests, etc.
+* Renamed configure.in to configure.ac.
+* Merged a very small number of Nathanael Nerode's configure.ac
+cleanups from the gcc tree.  Unfortunately, that file is a bit
+different from ours.
+* Changed EINTR handling in sem_wait slightly.
+* Restructure the root marking code.  Remove all traces of
+USE_GENERIC_PUSH_REGS, and effectively make it the default.
+Make it easier to pass a context pointer to the mark routine, in
+case we ever want to do precise stack marking.
+* Replace GC_start_blocking() and GC_end_blocking() with GC_do_blocking().
+This remains undocumented, and only implemented for pthreads.  But it
+removes an otherwise unavoidable race with stores of callee-save
+registers.
+* Fix GC_n_mark_bits for the default MARK_BIT_PER_GRANULE case.  This
+resulted in bogus complaints in heap dumps.
+* Upgrade to libatomic_ops-1.0, and update build structure to match.
+* Remove SRC_M3 support. Clean up lock initialization code in misc.c.
+* Removed gc_local_alloc.h.  If THREAD_LOCAL_ALLOC is defined, the
+thread local allocation routines are now called automatically.
+* Renamed gc_inl.h back to gc_inline.h.  Changed the interface appreciably
+since locking has turned into a dominant issue, and in-line allocation
+only makes sense if it's no worse than thread-local allocation.
+Gc_inline.h is now also used to implement thread-local allocation.
+* Finished replacing stubborn allocation with manual write barrier.
+Untested.
+* Use thread-local allocation code by default.
+* Added GC_register_my_thread and friends for Posix and win32.
+* Patch for GWW_VDB from Ben Hutchings.
+* Removed explicit THREAD_LOCAL_ALLOC tests, since that now always
+redefines GC_malloc.
+* Removed now unused AIX memory allocation code.
+* Various minor fixes for bugs introduced in 7.0alpha1.
+
+
+== [7.0alpha1] 2004-11-09 ==
+
+* Remove GC_PROTO, VOLATILE, GC_PTR, and GC_CONST.  Assume ANSI C compiler
+and use ANSI constructs unconditionally.
+* Introduce #elif and #error in some of the appropriate places.
+* Remove GC_printf cruft. Use stdargs.
+* Remove separate Solaris threads support.  Use the more generic Posix
+implementation.
+* Use atomic_ops for atomic operations and memory barriers.
+* Clean up MPROTECT_VDB implementation.  Use SA_SIGINFO wherever
+possible.
+* Remove broken SIGNALS stuff.
+* Use size_t instead of word, where appropriate.
+* Add .S.o rule to Makefile.am.
+* Officially discontinue SunOS4, several old flavors of M68K (SunOS4,
+A/UX, HP), IBM PC/RTs and RISCOS/Irix4.  (I doubt the old code worked.
+If anyone cares, these should be easy to resurrect.)
+* Add EXPECT() in some critical places.
+* Redefined hb_sz and hb_body to deal with bytes rather than words.
+This affected a great deal of code.  I would like to consistently use
+byte offsets and sizes where there's not a convincing reason to do
+otherwise.
+* Redefined several other variables (GC_mem_found, GC_words_allocd)
+etc. to use units of bytes.  Most of these were also renamed to
+reflect that fact.
+* Killed as many "register" declarations as possible.
+* Partially replaced stubborn allocation with manual write barrier.
+It's currently broken.
+* Restructured mark code, to allow mark bits to be kept either on
+a per allocation granule or per object basis.  The emphasis is
+now on the -DUSE_MARK_BYTES option, since individual bits perform
+quite badly on hyper-threaded P4s, and are probably suboptimal on
+other architectures.  -DUSE_MARK_BITS is currently broken, and may
+be resurrected only for the single-threaded case.  This significantly
+reduced the cache footprint required by auxiliary GC data structures.
+It also reduces space overhead for small heaps.  It probably slows
+things down slightly if interior pointers are very common.
+* As part of the above, we now maintain an approximate count of set
+mark bits in each heap block.
+* As part of the above, the semantics of hb_map changed drastically.
+For MARK_BIT_PER_OBJ, it doesn't exist.  For MARK_BIT_PER_GRANULE,
+it is purely a way to replace a mod instruction with a table lookup.
+(Somewhat to my surprise, this still wins on modern hardware.)
+* Removed PRINTSTATS, GATHERSTATS, and SILENT macros.  Everything is
+now controlled by GC_print_stats variable and GC_PRINT_STATS
+and new GC_PRINT_VERBOSE_STATS environment variables.
+* Add GC_log_printf and use it consistently for logging output.
+* Unconditionally count the objects we reclaim in the sweep phase.
+For thread local allocation, we need that anyway, and we expect
+that's increasingly the only case that matters.  And it simplifies
+the code.  In general expect minor performance hacks that benefit
+only the single-threaded case to disappear.
+* Remove GC_quiet from gc.h and elsewhere.
+* Changed the heap expansion heuristic, and the definition of
+GC_free_space_divisor, to refer to live data size, instead of total
+heap size.  I believe this is much more robust.  It wasn't previously
+possible, because we didn't have access to live data size.
+* Thread local allocation added the extra byte in twice: Once in
+thread_local_alloc, and once in malloc_many.
+* Removed GC_malloc_words_small and GC_gcj_fast_malloc.  A new
+mechanism based on the thread local allocation data structures
+is expected to be added instead.  This should allow inlined code
+that is both fast and doesn't rely on collector internals.
+* Changed both free lists and reclaim lists to be indexed by granules
+instead of words, norming halving their size.
+* MERGE_SIZE is now the only option, and the macro was removed.
+(Without it, we need a memory reference to GC_all_interior_pointers
+anyway.  Thus it costs us nothing.)
+* Change GC_size_map to map to granules instead of words.  Make sure
+that every possible size up to TINY_FREELISTS is present.
+* Split of macros need for fast inline allocation into gc_tiny_fl.h
+in anticipation of a new inline allocator that doesn't rely on GC
+internals.
+* Changed thread local allocation to use GRANULE_BYTES and TINY_FREELISTS
+in anticipation of a merge with the inline allocation code.
+* Removed ALIGN_DOUBLE.  This is mostly handled by GRANULE_BYTES.
+* Make locking on most platforms conditional on GC_need_to_lock.
+
+
+== [6.9] ==
+
+* Fix typo in PREFETCH implementation for X86_64 (thanks to Peter Wang).
+* Fix M68K LINUX port (thanks to Debian packagers).
+* __GNUC__ was misspelled as __GNUC in new_gc_alloc.h (thanks to Peter Wang).
+* Integrated Allan Hsu's patch for OS X VM deallocation problems.
+* Applied FreeBSD/X86_64 patch.
+
+
+== [6.8] 2006-07-08 ==
+
+* Added some support for Dragonfly BSD (thanks to Joerg Sonnenberger and
+Thomas Klausner).
+* Improvements to the HP/UX section of configure.in/configure.ac (thanks
+to Andreas Tobler).
+* GC_unix_get_mem could neglect to release the malloc lock on Irix, under
+extremely unlikely circumstances.  (Thanks to Jean-Baptiste Nivois for
+some careful code inspection.)
+* Added support for kFreeBSD + glibc (thanks to Petr Salinger).
+* Fix more MacOS threads memory leaks (thanks to Allan Hsu).
+* Added initial Solaris/X86-64 support (thanks to Rainer Orth).
+
+
+== [6.7] 2006-03-03 ==
+
+* Add "int" to Solaris "end" and "etext" declaration in gc.h.  Declared
+the symbols with underscores and as arrays, since that's what's actually
+used.  Perhaps this could all just be removed.  (Thanks to John Bowman.)
+* Fixed ARM GC_test_and_set code (thanks to Kazu Hirata and Paul Brook).
+* Added casts for assignments to hb_last_reclaimed, which truncate the
+value.  Added a cast to GC_adj_words_allocd.  Use GetModuleHandleA
+when retrieving a handle to kernel32.dll under win32.
+* Added Tandem S-Series support.  (Thanks to Craig McDaniel.  A modified
+version of his patch was applied, and hence breakage is probably not
+his fault.)
+* Remove spurious gc:: qualifier for operator delete[] in gc_cpp.h (thanks
+to Hanno Boeck).
+* Changed a test for LINUX in config_macros.h to one for __linux__.
+* Add prototypes for GC_finalizer_notifier and GC_thr_init (thanks to
+David Ayers).
+* Use ld instead of nonexistent ldz instruction in Darwin FindTopOfStack
+(thanks to Andreas Tobler).
+* Add support for Darwin/X86 (thanks to Geoff Norton and the Mono
+developers).
+* Merge in some recent gcc fixes.  Add ppc64 asm code.  (Thanks to
+Bryce McKinlay and other GCJ developers.)
+* Scan MEM_PRIVATE sections under Windows ME and predecessors.
+* Interior pointers with some largish offsets into large objects could
+be ignored, if GC_all_interior_pointers was set.  (Oddly this worked
+correctly for stack references if it was not set.  Otherwise it failed
+for both stack and heap references.  Thanks to Andrew McKinlay for the
+critical test case.)
+* Integrated Tatsuya Bizenn's NETBSD threads support, with some
+untested changes.
+* Added GC_strdup and friends to make leak detection work correctly
+for strdup clients (thanks to Jon Moore).  Fixed the existing strdup
+with malloc redirection to handle a null malloc return correctly.
+
+
+== [6.6] 2005-09-09 ==
+
+* Fix CPU count detection for Irix and FreeBSD (thanks to Dan Bonachea).
+* Integrate Dan Bonachea's patch for the IBM XLC compiler on Darwin.
+* Integrated Andreas Tobler's FreeBSD/PowerPC patch.
+* Don't access the GC thread structure from the restart handler.  It's
+unsafe, since the handler may run too late.  (Thanks to Ben Maurer for
+tracking this down.)
+* Applied Christian Thalinger's patch to change comment syntax in
+alpha_mach_dep.S.
+* Added test for GC_no_dls in GC_dyld_image_add for DARWIN (thanks to
+Juan Jose Garcia-Ripoll).
+* Use LINUX_STACKBOTTOM for Linux/SH and LINUX/ARM (thanks to
+Sugioka Toshinobu and Christian Thalinger).
+* Rewrote GC_parse_map_entry.  This assumed a fixed column layout of
+/proc/self/maps on Linux.  This ceased to be true about 2 years ago.
+The old code is probably quite problematic with -DREDIRECT_MALLOC.  It
+is also used by default for IA64, though I haven't seen actual failures
+there.
+* More consistently define HBLKSIZE to 4096 on 64 bit architectures with
+4K pages (thanks to Andrew Haley).
+* With win32 threads, GC_stop_world needs to acquire GC_write_cs (thanks
+to Ben Hutchings for the observation and patch).
+* Move up struct callinfo declaration to make gcc 4.0.2 happy.
+
+
+== [6.5] 2005-05-22 ==
+
+* Integrated Paolo Molaro's patch to deal with EINTR in sem_wait.
+* Make GC_approx_sp() write to dummy location to ensure that stack
+is grown here, when sp looks reasonable, rather than later, when
+it might look like a bad memory reference.  (Problem was never
+observed that I know of.  But on rereading the code it seemed
+dubious.)
+* Separate out GC_with_callee_saves_pushed and sometimes call
+it from GC_suspend_handler in pthread_stop_world.c.  Callee-save
+register values sometimes failed to get traced under HP/UX on
+PA-RISC.  Linux/IA64 had the same problem, though non-stacked
+callee-save registers seem to be so rarely used there that nobody
+ever noticed.
+* Integrated an ancient Darwin powerpc_darwin_machine_dep.s patch
+from Andreas Tobler, which I had lost.
+* Fix compare_and_exchange implementation for gcc/IA64 to deal with
+pickier compiler versions.
+* Fixed Itanium 32-bit ABI support (HP/UX).  In particular, the
+compare_and_exchange implementation didn't consider that possibility.
+* Undefine GC_pthread_detach in win32_threads.c (thanks to
+Tommaso Tagliapietra).
+* Fixed inclusion of frame.h for NETBSD in os_dep.c.
+* Applied Dan Bonachea's patch to use mmap on AIX.
+* Several fixes to resurrect the Irix port on recent OS versions.
+* Change ALPHA to use LINUX_STACKBOTTOM.
+* Change SPARC64/LINUX to also use LINUX_STACKBOTTOM.  Deal with potential
+bad values of __libc_stack_end on that platform (thanks to David Miller).
+* Relax gctest to allow larger heap if ALIGN_DOUBLE isn't set.
+(Unnecessary in 7.0)
+* Force a define of __STDC__=0 for the IBM compiler on AIX, so that
+we get prototypes.  (Unnecessary in 7.0)
+* GC_INIT definition for AIX and CYGWIN referred to DATASTART and DATAEND
+which are only defined in private include files.
+* Integrated some small gcconfig.h patches from Dan Bonachea.  Also
+relaxed assertion about FreeBSD stack size in pthread_support.c.
+* Integrated Andrew Begel's darwin_stop_world.c patch for 64-bit
+support.  This may need additional work.
+* Avoided potentially infinite recursion in GC_save_callers if
+the system backtrace calls malloc.  The workaround currently requires
+__thread support if this code is used with threads.
+* Avoided another similar infinite recursion by conditionally
+invoking GC_save_callers in alloc.c (thanks to Matthias Andree
+for helping to track down both of these).
+* Removed all traces of aix_irix_threads.c.  AIX and Irix now use
+pthread_support.c and pthread_stop_world.c.  The old code appeared
+to be unreliable for AIX, and was not regularly maintained.
+* On Irix, ignore segments with MA_FETCHOP or MA_NOTCACHED attributed;
+they're not always safe to read.
+* Fixed a previously vacuous assertion (diagnosed by the SGI compiler)
+in GC_remove_from_fl.
+* Fix stack_size assertion in GC_pthread_create.
+* Fix assertion in GC_steal_mark_stack.
+
+
+== [6.4] 2004-12-21 ==
+
+* Merge gcconfig.h changes from gcc tree.
+* Unconditionally include gc_priv.h in solaris_pthreads.c, win32_threads.h,
+aix_irix_threads.c, and solaris_threads.c to get thread definitions.
+* Start marker threads in GC_thr_init, so that they get started even
+if no other threads are ever started.  (Oddly enough, the parallel
+collector worked correctly, though not well, with no helper threads.)
+* Go ahead and split large blocks in GC_allochblk_nth if GC_dont_gc
+is set (thanks to Alexander Petrossian).
+* GC_PRINT_BACK_HEIGHT would deadlock with thread support.
+* Let in_progress_space in backgraph.s grow dynamically.
+* Fix README.solaris2.  The GC_thr_init() hack doesn't work anymore.
+* Convert GC_finalizer_mem_freed to bytes in allchblk.c.
+* Add missing declaration for GC_generic_malloc_words_small_inner.
+Without it, s390x breaks.  (Thanks to Ulrich Weigand.)
+* Applied several MacOSX patches to support older tool chains (thanks
+to Stefan Ring).
+* Bug fix for NetBSD/amd64 (thanks to Marc Recht).
+* Add NetBSD/sh3 support (thanks to Uchiyama Yasushi).
+* Fixed an uninitialized variable in cordprnt.c.
+* Eliminated some, but not all, gcc -Wall warnings.
+* Changed some old style casts to reinterpret_cast in new_gc_alloc.h
+(thanks to Dan Grayson).
+* GC_extend_size_map shouldn't adjust for GC_all_interior_pointers if
+GC_DONT_ADD_BYTE_AT_END is set.
+* Changed some (long) casts to (word) in preparation for win64 (thanks
+to Peter Colson).
+* Changed "int stack_size" declaration in pthread_support.c to use
+size_t.  (Only mattered with GC_ASSERTIONS enabled.)
+* Added CRIS (etrax) support (thanks to Simon Posnjak and Hans-Peter Nilsson).
+* Removed GC_IGNORE_FB frame buffer recognition, and replaced
+it with a check that the mapping type is MEM_IMAGE.
+In theory, this should work much better, but it is a high
+risk change for win32.  (Thanks to Ashley Bone for the crucial
+experimental data behind this, and to Rutger Ovidius for
+some further experiments.)
+* GC_allochblk_nth incremented GC_words_wasted by bytes rather than
+words.
+* Consider GC_words_wasted in GC_adj_words_allocd only if it is within
+reason.  (A hack to avoid some extremely unlikely scenarios in which
+we manage to allocate only "wasted" space.  7.0 has a better fix.)
+* Changed PowerPC GC_clear implementation to use lwsync instead of
+eieio, since the documentation recommends against eieio, and
+it seems to be incorrect if the preceding memory op is a load.
+* Fixed print_block_list to print the correct kind number for
+STUBBORN (thanks to Rutger Ovidius).
+* Have configure.in generate an error if it is asked to support
+pthreads, but doesn't know how to.
+* Added Kazuhiro Inaoka's patch for Renesas M32R support.
+* Have the GNU build mechanism link with -ldl.  Rename THREADLIBS
+to THREADDLLIBS to reflect this.  (Thanks to Sven Verdoolaege.)
+* Added Hannes Mehnert's patch for FreeBSD/SPARC support.
+* Merged some FreeBSD specific patches to threadlibs.c and dyn_load.c.
+(Thanks to John Merryweather Cooper.)
+* Define MPROTECT_VDB on MACOSX only if threads are being used, since the
+dirty page tracking mechanism uses threads.  (This avoids an undefined
+reference to _GC_darwin_register_mach_handler_thread.)
+* By popular demand, use __libc symbols only if we are built with
+USE_LIBC_PRIVATES, which is off by default, and not otherwise documented.
+* Ignore GC_enable_incremental() requests when KEEP_BACK_PTRS is set.
+The GC itself will dirty lots of pages in this cases, probably making
+it counterproductive on all platforms.  And the DARWIN port crashes.
+
+
+== [6.3] 2004-07-08 ==
+
+* Compile test_cpp.cc with CXXCOMPILE instead of COMPILE.
+* Very large allocations could cause a collector hang.  Correct
+calculation of GC_collect_at_heapsize.
+* GC_print_hblkfreelist printed some bogus results if USE_MUNMAP
+was defined.
+* Include gc_config_macros.h in threadlibs.c.
+* Correct MacOSX thread stop code (thanks to Dick Porter).
+* SMALL_OBJ definition was off by one.  This could cause crashes
+at startup.  (Thanks to Zoltan Varga for narrowing this down to
+a trivial test case.)
+* Integrate Paolo Molaro's patch to deal with a race in the Darwin
+thread stopping code.
+* Changed X86_64 implementation to use SA_SIGINFO in the MPROTECT_VDB
+implementation.  The old approach appears to have been broken by
+recent kernels.
+* Added GC_ATTR_UNUSED to eliminate a warning in gc_allocator.h (thanks
+to Andrew Begel).
+* Fix GC_task_self declaration in os_dep.c (thanks to Andrew Pinski).
+* Increase INITIAL_BUF_SZ in os_dep.c for Solaris /proc reads.
+
+
+== [6.3alpha6] 2004-05-06 ==
+
+* Define USE_GENERIC_PUSH_REGS for NetBSD/M68K.
+* Fixed the X86_64 PREFETCH macros to correctly handle ia32e (which uses
+different prefetch instructions from AMD64).  (Thanks to H.J. Lu.)
+* GC_config_macros.h did not correctly define GC_WIN32_THREADS from
+GC_THREADS.
+* Added simple_example.html.
+* Merged Andrew Gray's patch to correctly restore signal handlers on
+FreeBSD.
+* Merged a patch from Andreas Jaeger to deal with prefetch-related warnings
+on x86-64.  Added some other casts so that the PREFETCH macros
+always get a ptr_t argument.  Removed some casts in the PREFETCH
+implementations.
+* Added a header guard for gc_allocator.h and changed GC_debug_free to
+clobber contents of deallocated object (suggested by Jesse Jones).
+* The signal masking code in pthread_stop_world.c contained some errors.
+In particular SIGSEGV was masked in the handler, in spite of the fact that
+it wrote to the heap.  This could lead to an uncaught SIGSEGV, which
+apparently became much more likely in Linux 2.6.  Also fixed some
+typos, and reduced code duplication in the same area.
+* Remove ltconfig, clean up configure messages for DG/UX (thanks to
+Adrian Bunk for the patches).
+* Integrated NetBSD/OpenBSD patches from Marc Recht and Matthias Drochner.
+
+
+== [6.3alpha5] 2004-03-30 ==
+
+* Fix & vs && typo in GC_generic_malloc and
+GC_generic_malloc_ignore_off_page.  (Propagated from the gcc tree.)
+* Removed SA_NODEFER hack from NetBSD and Solaris write-protect handler.
+(According to Christian Limpach, the NetBSD problem is fixed.
+Presumably so is the Solaris 2.3 problem.)
+* Removed placement delete from gc_cpp.h for the SGI compiler (thanks
+to Simon Gornall for the patch).
+* Changed semantics of the GC_IGNORE_FB environment variable, based
+on experimentation by Nicolas Cannasse pointing out that the old
+interpretation was useless.  We still need help in identifying win32
+graphics memory mappings.  The current "solution" is a hack.
+* Removed "MAKEOVERRIDES =" from Makefile.am and thus Makefile.in.
+It probably made more sense in the gcc context.
+* Explicitly ensure that NEED_FIND_LIMIT is defined for {Open,Net}BSD/ELF.
+* Replaced USE_HPUX_TLS macro by USE_COMPILER_TLS, since gcc often
+supports the same extension on various platforms.
+* Added some basic (completely untested) defines for win64, in support
+of future work.
+* Declared GC_jmp_buf in os_dep.s as JMP_BUF instead of jmp_buf, fixing
+a memory overwrite bug on Solaris and perhaps other platforms.
+* Added 0 != __libc_stack_end test to GC_linux_stack_base (thanks to
+Jakub Jelinek for the patch and explaining the problem).
+Otherwise pre-linking could cause the collector to fail.
+* Changed default thread local storage implementation to USE_PTHREAD_SPECIFIC
+for HP/UX with gcc.  The compiler-based implementation appears to work
+only with the vendor compiler.
+* Export GC_debug_header_size and GC_USR_PTR_FROM_BASE from gc_mark.h,
+making client mark code cleaner and less dependent on GC version.
+* Export several new procedures and GC_generic_malloc from gc_mark.h
+to support user-defined kinds.  Use the new procedures to replace existing
+code in gcj_mlc.c and typd_mlc.c.
+* Added support for GC_BACKTRACES.
+* Fixed a remaining problem in CORD_str with signed characters (thanks
+to Alexandr Petrosian for the patch).
+* Removed supposedly redundant, but very buggy, definitions of finalizer
+macros from javaxfc.h.  Fortunately this file probably has no users.
+The correct declarations were already in gc.h.
+* Also need to set GC_in_thread_creation while waiting for GC during
+thread termination, since it is also possible to collect from an
+unregistered thread in that case.
+* Define NO_GETENV for Windows CE, since getenv doesn't appear to exist.
+Plus some other minor WinCE fixes (thanks to Alain Novak).
+* Added GC_register_describe_type_fn.
+* Arrange for debugging finalizer registration to ignore non-heap
+registrations, since the regular version of the routine also behaves
+that way.
+* GC_gcj_malloc and friends need to check for finalizers waiting to be run.
+One of the more obscure allocation routines with missing a LOCK() call.
+* Fixed cvtres invocations in NT_MAKEFILE and NT_STATIC_THREADS_MAKEFILE
+to work with VS.NET.
+* Cleaned up GC_INIT calls in test.  Updated gc.man to encourage GC_INIT
+use in portable code.
+* Taught the GC to use libunwind if --enable-full-debug is specified on
+IA64 and libunwind is present.
+* The USE_MUNMAP code could get confused about the age of a block and
+prematurely unmap it.  GC_unmap_old had a bug related to wrapping of
+GC_gc_no.  GC_freehblk and GC_merge_unmapped didn't maintain
+hb_last_reclaimed reasonably when blocks were merged.  The code was
+fixed to reflect original intent, but that may not always be an
+improvement.
+
+
+== [6.3alpha4] 2004-01-01 ==
+
+* USE_MMAP was broken by confusion in the code dealing with USE_MMAP_ANON.
+* Darwin support was broken in alpha3 as a result of my mis-integration of
+Andrew Begel's patches.  Fixed with another patch from Andrew Begel.
+* A new sanity check in pthread_stop_world.c:GC_push_all_stacks() was
+overly aggressive.  We may collect from an unregistered thread during
+thread creation.  Fixed by explicitly checking for that case.  (Added
+GC_in_thread_creation.)
+
+
+== [6.3alpha3] 2003-12-20 ==
+
+* Removed -DSMALL_CONFIG from BCC_MAKEFILE.
+* Changed macros to test for an ARM processor (Patch from Richard Earnshaw.)
+* Mostly applied a DJGPP patch from Doug Kaufman.  Especially Makefile.dj
+had suffered from serious bit rot.
+* Rewrote GC_apply_to_maps, eliminating an off-by-one subscript error,
+and a call to alloca (for lcc compatibility).
+* Changed USE_MUNMAP behavior on POSIX platforms to immediately remap
+the memory with PROT_NONE instead of unmapping it.  The latter risks
+an intervening mmap grabbing the address space out from underneath us.
+Updated this code to reflect a cleaner patch from Ulrich Drepper.
+* Replaced _T with _Tp in new_gc_alloc.h to avoid a MACOS X conflict.
+(Patch from Andrew Begel.)
+* Dynamically choose whether or not lock should spin on win32 (thanks
+to Maurizio Vairani for the patch).  This may be a significant performance
+improvement for win32.
+* Fix Makefile.direct to actually include NT_STATIC_THREADS_MAKEFILE
+in the distribution (thanks to Maurizio Vairani).
+* Maybe_install_looping_handler() was accidentally exported, violating
+our name space convention.
+* Made os_dep.c use sigsetjmp and SA_NODEFER for NetBSD.  (Thanks to
+Christian Limpach.  I generalized the patch to use sigsetjmp on all
+UNIX_LIKE platforms, admittedly a slightly risky move.  But it may avoid
+similar problems on some other platforms.  I also cleaned up the definition
+of UNIX_LIKE a bit.)
+* Integrated Andrew Begel's Darwin threads patch, adjusted according to
+some of Fergus Hendersons's comments.  (Patch didn't apply cleanly,
+errors are possible.)
+* Added another test or two for the Intel 8.0 compiler to avoid
+confusing it with gcc.  The single-threaded collector should now build
+with icc, at least on ia64.
+
+
+== [6.3alpha2] 2003-11-04 ==
+
+* Re-enabled I_HOLD_LOCK assertion in aix_irix_threads.h.
+* Put back the WINABI qualifier for GC_CreateThread.  (Thanks to
+Danny Smith for the patch.  6.3alpha1 had the qualifier in one place
+but not elsewhere, which was clearly wrong.)
+* Sometimes explicitly define __private_extern__ before DARWIN dyld.h
+include.  (Thanks to Andreas Tobler for posting the patch.)
+* Included signal.h from pthread_support.c.  Removed GC_looping_handler,
+which was dead code.
+* GC_find_start was misdeclared by gc_pmark.h if PRINT_BLACK_LIST was
+defined (thanks to Glauco Masotti for testing and reporting this).
+Changed GC_find_start to never just return 0.  According to its
+comment it doesn't, and it's unclear that's correct.
+* GC_alloc_large had several largely compensating bugs in the
+computation of GC_words_wasted.  (It was confused about bytes vs.
+words in two places.)
+* Integrated Slava Sysoltsev's patch to support more recent versions of
+the Intel compiler on IA64/Linux.
+* Changed win32 spinlock initialization to conditionally set a spin count.
+(Emmanual Stumpf pointed out that enabling this makes a large performance
+difference on win32 multiprocessors.)  Also cleaned up the win32 spinlock
+initialization code a bit.
+* Fixed thread support for HP/UX/IA64.  The register backing store base for
+the main thread was sometimes not set correctly.  (Thanks to
+Laurent Morichetti.)
+* Added -DEMPTY_GETENV_RESULTS flag to work around Wine problem.
+* Declare GC_stack_alloc and GC_stack_free in solaris_threads.h to
+avoid 64-bit size mismatches (thanks to Bernie Solomon).
+* Fixed GC_generic_push_regs to avoid a potential and very unfortunate
+tail call optimization.  This could lead to prematurely reclaimed
+objects on configurations that used the generic routine and the new
+build infrastructure (which potentially optimizes mach_dep.c).
+This was a serious bug, but it's unclear whether it has resulted in
+any real failures.
+* Fixed CORD_str to deal with signed characters (thanks to Alexandr Petrosian
+for noticing the problem and supplying the patch).
+* Merged a couple of NOSYS/ECOS tests into os_dep.c from gcj (thanks
+to Anthony Green).
+* Partially merged a win32 patch from Ben Hutchings, and substantially
+revised other parts of win32_threads.c.  It had several problems.
+Under MinGW with a statically linked library, the main thread was
+not registered.  Cygwin detached threads leaked thread descriptors.
+There were several race conditions.  For now, unfortunately the
+static threads limit remains, though we increased it, and made table
+traversal cost depend on the actual thread count.
+There is also still some code duplication with pthread_support.c.
+(Thread descriptors did become much smaller, since Ben Hutchings
+removed the thread context from them.)
+* Integrated a Solaris configure.in patch from Rainer Orth.
+* Added GC_IGNORE_FB and associated warning to very partially address
+the issue of the collector treating a mapped frame buffer as part
+of the root set.  (Thanks to David Peroutka for providing some
+insight.  More would be helpful.  Is there anything that can be used
+to at least partially identify such memory segments?)
+
+
+== [6.3alpha1] 2003-07-26 ==
+
+* Integrated some NetBSD patches by Marc Recht.  These
+were already in the NetBSD package.
+* GC_pthread_create waited for the semaphore even if pthread_create failed.
+(Thanks to Dick Porter for the pthread_support.c patch.)  Applied the
+analogous fix for aix_irix_threads.c.
+* Added Rainer Orth's Tru64 fixes.
+* The check for exceeding the thread table size in win32 threadDetach
+was incorrect (thanks to Alexandr Petrosian for the patch).
+* Applied Andrew Begel's patch to correct some reentrancy issues
+with dynamic loading on Darwin.
+* GC_CreateThread() was neglecting to duplicate the thread handle in
+the table (thanks to Tum Nguyen for the patch).
+* Pass +ESdbgasm only on PA-RISC machines with vendor compiler (thanks to
+Roger Sayle for the patch).
+* Applied more AIX threads patches from Scott Ananian.
+
+
+== [6.2] 2003-06-21 ==
+
+* Integrated a second round of Irix/AIX patches from Dan Bonachea.
+Renamed mips_sgi_mach_dep.S back to mips_sgi_mach_dep.s, since it requires
+the Irix assembler to do the C preprocessing; gcc -E doesn't work.
+* Fixed Makefile.direct for DARWIN (thanks to Manuel Serrano).
+* There was a race between GC_pthread_detach and thread exit that could
+result in a thread structure being deallocated by GC_pthread_detach
+even though it was still needed by the thread exit code (thanks to
+Dick Porter for the small test case that allowed this to be debugged).
+* Fixed version parsing for non-alpha versions in acinclude.m4 and
+version checking in version.h.
+* Issues identified (not yet fixed):
+- A dynamic libgc.so references dlopen unconditionally, but doesn't link
+against libdl.
+- GC_proc_fd for Solaris is not correctly updated in response to a
+fork() call.  Thus incremental collection in the child won't work
+correctly.  (Thanks to Ben Cottrell for pointing this out.)
+- --enable-redirect-malloc is mostly untested and known not to work
+on some platforms.
+- There seem to be outstanding issues on Solaris/X86, possibly with
+finding the data segment starting address.
+- Very large root set sizes (> 16 MB or so) could cause the collector
+to abort with an unexpected mark stack overflow.  (Thanks to
+Peter Chubb.)  NOT YET FIXED.  Workaround is to increase the initial
+size.
+- The SGI version of the collector marks from mmapped pages, even
+if they are not part of dynamic library static data areas.  This
+causes performance problems with some SGI libraries that use mmap
+as a bitmap allocator.  NOT YET FIXED.  It may be possible to turn
+off DYNAMIC_LOADING in the collector as a workaround.  It may also
+be possible to conditionally intercept mmap and use GC_exclude_static_roots.
+The real fix is to walk rld data structures, which looks possible.
+- Incremental collector should handle large objects better.  Currently,
+it looks like the whole object is treated as dirty if any part of it is.
+
+
+== [6.2alpha6] 2003-06-05 ==
+
+* There was an extra underscore in the name of GC_save_registers_in_stack
+for NetBSD/SPARC (thanks to Jaap Boender for the patch).
+* Integrated Brian Alliet's patch for Darwin.  This restructured the
+linuxthreads/pthreads support to separate generic pthreads support
+from more the system-dependent thread-stopping code.  I believe this
+should make it easier to eliminate the code duplication between
+pthreads platforms in the future.  The patch included some other
+code cleanups.
+* Integrated Dan Bonachea's patch to support AIX threads.  This required
+substantial manual integration, mostly due to conflicts with other
+recent threads changes.  It may take another iteration to
+get it to work.
+* Removed HPUX/PA-RISC support from aix_irix_threads.c.  It wasn't used
+anyway and it cluttered up the code.  And anything we can do to migrate
+towards generic pthreads support is a good thing.
+* Added a more explicit test for tracing of function arguments to test.c.
+* Added Akira Tagoh's PowerPC64 patch.
+* Fixed some bit rot in the Cygwin port (thanks to Dan Bonachea for
+pointing it out).  gc.h now includes just windows.h, not winbase.h.
+* Declared GC_save_regs_in_stack() in gc_priv.h.  Remove other declarations.
+* Changed --enable-cplusplus to use automake consistently.  The old way
+confused libtool.  "Make install" didn't work correctly for the old version.
+Previously --enable-cplusplus was broken on cygwin.
+* Changed the C version of GC_push_regs to fail at compile time if it is
+generated with an empty body.  This seems to have been the cause of one
+or two subtle failures on unusual platforms.  Those failures should
+now occur at build time and be easily fixable.
+
+
+== [6.2alpha5] 2003-05-14 ==
+
+* GC_invoke_finalizers could, under rare conditions, set
+GC_finalizer_mem_freed to an essentially random value.  This could
+possibly cause unbounded heap growth for long-running applications
+under some conditions.  (The bug was introduced in 6.1alpha5, and
+is not in gcc3.3.)
+* Attempted to sanitize the various DLL macros.  GC_USE_DLL disappeared.
+GC_DLL is used instead.  All internal tests are now on GC_DLL.
+README.macros is now more precise about the intended meaning.
+* Include DllMain in the multi-threaded win32 version only if the
+collector is actually built as a dll (thanks to Mohan Embar for
+a version of the patch).
+* Hide the cygwin threadAttach/Detach functions.  They were violating our
+namespace rules.
+* Fixed an assertion in GC_check_heap_proc.  Added GC_STATIC_ASSERT
+(thanks again to Ben Hutchings).
+* Removed some obsolete definitions for Linux/PowerPC in gcconfig.h.
+* CORD_cat was not rebalancing unbalanced trees in some cases, violating
+a CORD invariant.  Also tweaked the re-balancing rule for
+CORD_cat_char_star.  (Thanks to Alexandr Petrosian for the bug report
+and patch.)
+* Added hand-coded structured exception handling support to mark.c.
+This should enable support of dynamic libraries under win32 with
+gcc-compiled code.  (Thanks to Ranjit Mathew for the patch.)
+Turned on dynamic library scanning for win32/gcc.
+* Removed some remnants of read wrapping (thanks to Kenneth Schalk).
+GC_USE_LD_WRAP was probably broken in recent versions.
+* The build could fail on some platforms since gcconfig.h could include
+declarations mentioning ptr_t, which was not defined, e.g. when if_mach
+was built (thanks to Yann Dirson for pointing this out).  Also
+cleaned up tests for GC_PRIVATE_H in gcconfig.h a bit.
+* The GC_LOOP_ON_ABORT environment variable interfered with incremental
+collection, since the write fault handler was erroneously overridden.
+Handlers are now set up in the correct order.
+* It used to be possible to call GC_mark_thread_local_free_lists() while
+the world was not stopped during an incremental GC.  This was not safe.
+Fortunately, it was also unnecessary.  Added GC_world_stopped flag
+to avoid it.  (This caused occasional crashes in GC_set_fl_marks
+with thread local allocation and incremental GC.  This probably happened
+primarily on old, slow multiprocessors.)
+* Allowed overriding of MAX_THREADS in win32_threads.c from the build
+command line (thanks to Yannis Bres for the patch).
+* Taught the IA64/linux code to determine the register backing store base from
+/proc/self/maps after checking the __libc symbol, but before guessing.
+(__libc symbols are on the endangered list, and the guess is likely to not
+always be right for 2.6 kernels.)  Restructured the code to read and parse
+/proc/self/maps so it only exists in one place (all platforms).
+* The -DUSE_PROC_FOR_LIBRARIES code was broken on Linux.  It claimed that it
+also registered the main data segment, but didn't actually do so.  (I don't
+think anyone actually uses this configuration, but ...)
+* Made another attempt to get --enablecplusplus to do the right thing.
+Since there are unavoidable problems with C programs linking against a
+dynamic library that includes C++ code, I separated out the c++ code into
+libgccpp.
+
+
+== [6.2alpha4] 2003-03-10 ==
+
+* Use LINUX_STACKBOTTOM for >= glibc2.2 on Linux/MIPS.  (See Debian bug
+# 177204)
+* Integrated Jeff Sturm and Jesse Rosenstock's MACOSX threads patches.
+* Integrated Grzegorz Jakacki's substantial GNU build patch.  "Make dist"
+should now work for the GNU build process.  Documentation files
+are installed under share/gc.
+* Tweaked gc_cpp.h to again support the Borland compiler (thanks to
+Rene Girard for pointing out the problems).
+* Updated BCC_MAKEFILE (thanks to Rene Girard).
+* Added GC_ASSERT check for minimum thread stack size.
+* Added --enable-gc-assertions.
+* Added some web documentation to the distribution.  Updated it in the
+process.
+* Separate gc_conf_macros.h from gc.h.
+* Added generic GC_THREADS client-defined macro to set the appropriate
+GC_XXX_THREADS internal macro.  (gc_config_macros.h.)
+* Add debugging versions of _ignore_off_page allocation primitives.
+* Moved declarations of GC_make_closure and GC_debug_invoke_finalizer
+from gc.h to gc_priv.h.
+* Reset GC_fail_count even if only a small allocation succeeds.
+* Integrated Brian Alliet's patch for dynamic library support on Darwin.
+* gc_cpp.h's gc_cleanup destructor called GC_REGISTER_FINALIZER_IGNORE_SELF
+when it should have called the lower case version, since it was
+explicitly computing a base pointer.
+
+
+== [6.2alpha3] 2003-01-30 ==
+
+* Don't include execinfo.h in os_dep.c when it's not needed, and may not
+exist.
+
+
+== [6.2alpha2] ==
+
+* Fixed the completely broken FreeBSD code in 6.2alpha1 (thanks to
+Hironori Sakamoto for the patch).
+* Changed IRIX reference in dbg_mlc.c to IRIX5 (thanks to Marcus Herbert).
+* Attempted to work around the problems with .S filenames and the SGI
+compiler.  (Untested.)
+* Worked around an HP/UX make issue with the GNU-style build process.
+* Fixed the --enable-cplusplus build machinery to allow builds without
+a C++ compiler.  (That was always the intent ...)
+* Changed the debugging allocation macros to explicitly pass the return
+address for Linux and XXXBSD on hardware for which we can't get stack
+traces.  Use __builtin_return_address(0) to generate it when possible.
+Some of the configuration work was cleaned up (good) and moved to gc.h
+(bad, but necessary).  This should make leak detection more useful
+on a number of platforms.  (Thanks to Fabian Thylman for the suggestion.)
+* Fixed compilation problems in dbg_mlc.c with GC_ADD_CALLER.
+* Bumped revision number for dynamic library.
+
+
+== [6.2alpha1] 2003-01-23 ==
+
+* Guard the test for GC_DUMP_REGULARLY in misc.c with
+"#ifndef NO_DEBUGGING".  Otherwise it fails to build with NO_DEBUGGING
+defined.  (Thanks to Manuel Serrano.)
+* Message about retrying suspend signals was incorrectly generated even when
+flag was not set.
+* Cleaned up MACOSX/NEXT root registration code.  There was apparently a
+separate ifdef case in GC_register_data_segments() for no reason.
+* Removed MPROTECT_VDB for MACOSX port, based on one negative report.
+* Arrange for gc.h and friends to be correctly installed with GNU-style
+"make install".
+* Enable the GNU-style build facility include C++ support in the library
+with --enable-cplusplus (thanks to Thomas Maier for some of the patch).
+* Mark from GC_thread_key in linux_threads.c, in case that's allocated
+from the garbage collected heap, as it is with our own thread-specific
+storage implementation (thanks to Jeff Sturm).
+* Mark all free list header blocks if they are heap allocated.  This avoids
+some unnecessary tracing.  And it remains correct if we clear the
+root set.  (Thanks to Jeff Sturm for identifying the bug.)
+* Improved S390/Linux support.  Add S390/Linux 64-bit support (thanks to
+Ulrich Weigand).
+* Corrected the spelling of GC_{M,C}ALLOC_EXPLICTLY_TYPED to
+GC_{M,C}ALLOC_EXPLICITLY_TYPED in gc_typed.h.  This is technically
+an interface change.  Based on the fact that nobody reported this,
+I suspect/hope there were no clients.
+* Cleaned up gc_typed.h so that (1) it adds an extern "C" declaration
+when appropriate, (2) doesn't generate references to undefined internal
+macros, and (3) allows easier manual construction of descriptors.
+* Close the file descriptor used by GC_print_address_map().
+* Set the "close-on-exec" bit for various file descriptors maintained
+for the collector's internal use.
+* Added a hack to find memory segments owned by the system allocator
+under win32.  Based on my tests, this tends to eventually find all
+segments, though it may take a while.  There appear to be cleaner,
+but slower solutions under NT/XP.  But they rely on an API that's
+unsupported under 9X.
+* Changed Linux PowerPC stack finding to LINUX_STACKBOTTOM.  (Thanks
+to Akira Tagoh for pointing out that HEURISTIC1 does not work on
+64-bit kernels.)
+* Added GC_set_free_space_divisor to avoid some Windows dll issues.
+* Added FIXUP_POINTER, POINTER_SHIFT, POINTER_MASK to allow preprocessing
+of candidate pointers for tagging, etc.
+* Always lock around GC_notify_full_gc().  Simplified code for
+invoking GC_notify_full_gc().
+* Changed the way DATASTART is defined on FreeBSD to be robust against
+an unmapped page after etext.  (Thanks to Hironori Sakamoto for
+tracking down the intermittent failure.)
+* Made GC_enable() and GC_disable() official.  Deprecated direct update
+of GC_dont_gc.  Changed GC_gcollect to be a noop when garbage collection
+is disabled.
+* Call GC_register_dynamic_libraries before stopping the world on Linux,
+in order to avoid a potential deadlock due to the dl_iterate_phdr lock.
+* Introduced a more general mechanism for platform-dependent code to
+decide whether the main data segment should be handled separately
+from dynamic libraries, or registered by GC_register_dynamic_libraries.
+The latter is more reliable and easier on Linux with dl_iterate_phdr.
+
+
+== [6.1] ==
+
+* Added GC_MAXIMUM_HEAP_SIZE environment variable.
+* Fix configure.in for MIPS/LINUX (thanks to H.J. Lu).
+* Double page hash table size for -DLARGE_CONFIG.
+* Integrated Bo Thorsen's X86-64 support.
+* STACKBOTTOM definition for LINUX/MIPS was partially changed back
+(thanks to H.J. Lu and Hiroshi Kawashima for resolving this).
+* Replaced all occurrences of LINUX_DATA_START in gcconfig.h with
+SEARCH_FOR_DATA_START.  It doesn't hurt to fall back to a search.
+And __data_start doesn't seem to get defined correctly of the GC
+library is loaded with LD_PRELOAD, e.g. for leak detection.
+* If the GC_find_leak environment variable is set, do a
+atexit(GC_gcollect) to give us at least one chance to detect leaks.
+This may report some very benign leaks, but ...
+* Addeded REDIRECT_FREE.  It's necessary if we want leak detection with
+LD_PRELOAD.
+* Defer printing of leaked objects, as for smashed objects.
+* Fixed process and descriptor leak in GC_print_callers.  Try for
+line number even if we got function name.)
+* Ported parallel GC support and thread local allocation to Alpha.
+Not yet well-tested.
+* Added GC_DUMP_REGULARLY and added finalization statistics to GC_dump().
+* Fixed Makefile.am to mention alpha_mach_dep.S instead of the defunct
+alpha_mach_dep.s.
+* Incorporated a change to new_gc_alloc.h,
+which should make it work with gcc3.1.
+* Use alpha_mach_dep.S only on Linux.  (It's not clear that this is
+optimal, but it otherwise didn't build on Tru64.  Thanks to Fergus Henderson.)
+* Added ifdef to guard free() in os_dep.c.  Otherwise we get a
+compilation error on Irix (thanks to Dai Sato).
+* Added an experimental version of GC_memalign to mallocx.c.  This can't
+always work, since we don't handle alignment requests in the hblk-level
+allocator, and we can't handle arbitrary pointer displacements unless
+GC_all_interior_pointers is enabled.  But it should work for alignment
+requests up to HBLKSIZE.  This is not yet documented in the standard
+places.
+* Finally debugged the OSF1/Tru64 thread support.  This needs more testing,
+since I needed to add a somewhat unconvincing workaround for signal
+delivery issues that I don't yet completely understand.  But it does
+pass my tests, even in parallel GC mode.  Incremental GC support is
+disabled if thread support is enabled, due to the signal issues.
+* Eliminated name-space-incorrect definition of _cdecl from gc_cpp.h.
+* Added GC_debug_malloc_replacement and GC_debug_realloc_replacement
+declarations to gc.h.  On IA64, this is required for REDIRECT_MALLOC
+to work correctly with these.
+* Fixed Linux USE_PROC_FOR_LIBRARIES to work with a 64-bit /proc format.
+
+
+== [6.1alpha5] 2002-06-19 ==
+
+* Added GC_finalizer_mem_freed, and changed some of the code that
+decided on heap expansion to look at it.  Memory explicitly
+deallocated by finalizers essentially needs to be counted as reclaimed
+by the GC.  Otherwise there are cases in which the heap can grow
+infinitely.  (Thanks to Mark Reichert for the test case.)
+* Integrated Adam Megacz patches to not scan dynamic libraries if
+we are compiling with gcc on win32.  Otherwise we need structured
+exception handling to deal with asynchronously unmapped root
+segments, and gcc doesn't directly support that.
+* Integrated Anthony Green's patch to support Wine.
+* GC_OPERATOR_NEW_ARRAY was misspelled OPERATOR_NEW_ARRAY in several
+places, including gc_cpp.cc (thanks to Wink Saville for pointing this out).
+* Integrated Loren J. Rittle's Alpha FreeBSD patches.  These also
+changed the declarations of symbols like _end on many platforms to
+that they wouldn't mistakenly be declared as short data symbols (suggested by
+Richard Henderson).
+* Integrated changes from the Debian distribution (thanks to Ryan Murray
+for pointing these out).
+Fix C++ comments in POWERPC port.  Add ARM32
+incremental GC support.  Get rid of USE_GENERIC_PUSH_REGS for alpha/Linux,
+this time for real.  Use va_copy to get rid of cord printf problems
+(finally).
+* Close file descriptor used to count CPUs (thanks to Jeff Sturm for
+pointing out the omission).
+* Don't just drop gcj free lists in GC_start_reclaim, since that can
+eventually cause the marker to see a bogus mark descriptor in the
+dropped objects.  The usual symptom was a very intermittent segmentation
+fault in the marker.  This mattered only if one of the GC_gcj_malloc
+variants was used (thanks to Michael Smith, Jeff Sturm, Bryce McKinlay and
+Tom Tromey for helping to track this down).
+* Fixed Linux and Solaris/64 SPARC configuration (thanks to David Miller,
+Jeff Sturm, Tom Tromey, and Christian Joensson).
+* Fixed a typo in strdup definition (thanks to Gerard A Allan).
+* Changed Makefile.direct to invoke $(CC) to assemble alpha_mach_dep.S.
+This is needed on Linux.  I'm not sure whether it's better or worse
+on Tru64.
+* Changed gc_cpp.h once more to declare operator new and friends only in
+a Microsoft environment.  This may need further fine tuning (thanks to
+Johannes Schmidt for pointing out that the older code breaks on gcc3.0.4).
+* Don't ever override strdup if it's already macro defined (thanks to
+Adnan Ali for pointing out the problem).
+* Changed gc_cpp.h yet again to also overload placement new.  Due to the
+C++ overloading rules, the other overloaded new operations otherwise hide
+placement new, which causes many STL uses to break (thanks to Reza Shahidi
+for reporting this, and to Matt Austern for proposing a fix).
+* Integrated cygwin pthreads support from Dan Bonachea.
+* Turn on DYNAMIC_LOADING for NetBSD (thanks to Krister Walfridsson).
+* Changed printing code to print more complete GC times.
+* Applied Mark Mitchell's Irix patch to correct some bit rot.
+* Clarified which object-printing routines in dbg_mlc.c should hold
+the allocation lock.  Restructured the code to allow reasonable object
+printing with -DREDIRECT_MALLOC.
+* Fix the Linux mmap code to always start with 0x1000 as the initial hint.
+Minor patches for 64-bit AIX, particularly to STACKBOTTOM (thanks to
+Jeffrey Mark Siskind).
+* Renamed "SUSPENDED" flag for Solaris threads support to avoid a conflict
+with a system header (thanks to Philip Brown).
+* Cause win32_threads.c to handle an out of range stack pointer correctly,
+though currently with a warning.  (Thanks to Jonathan Clark for
+observing that win32 applications may temporarily use the stack
+pointer for other purposes, and suggesting a fix.  Unfortunately, it's
+not clear that there is a complete solution to this problem.)
+
+
+== [6.1alpha4] 2002-06-16 ==
+
+* Fixed typo in sparc_mach_dep.S, preventing the 64-bit version from
+building.  Increased 64-bit heap size limit in test.c slightly, since
+a functional SPARC collector seems to slightly exceed the old limits.
+* Use NPRGREG in solaris_threads.c, thus printing all registers if things
+go wrong.
+* Added GC_MARKERS environment variable to allow use of a single marker
+thread on an MP without confusing the lock implementation.
+* Collect much less aggressively in incremental mode with GC_TIME_UNLIMITED.
+This is really a purely generational mode, and we can afford to
+postpone the collection until the heap is (nearly) full.
+* Remove read() wrapper for MPROTECT_VDB.  It was causing more harm than
+good.  It is often no longer needed if system calls avoid writing to
+pointerful heap objects.
+* Fix MACOSX test in gcconfig.h (thanks to John Clements).
+* Change GC_test_and_set so that it consistently has one argument.
+Add spaces to ::: in powerpc assembly code in gc_locks.h (thanks to
+Ryan Murray).
+* Fixed a formatting error in dbg_mlc.c.  Added prototype to GC_abort()
+declaration (thanks to Michael Smith).
+* Removed "source" argument to GC_find_start().  Eliminate GC_FIND_START().
+* Added win32 recognition code in configure.in.  Changed some of the
+dllimport/export defines in gc.h (thanks to Adam Megacz).
+* GC_malloc_many didn't set hb_last_reclaimed when it called
+GC_reclaim_generic.  (I'm not sure this matters much, but ...)
+* Allocating uncollectible objects with debug information sometimes
+allocated objects that were one byte too small, since uncollectible
+objects don't have the extra byte added at the end (thanks to
+Wink Saville for pointing this out).
+* Added a bit more assertion checking to make sure that gcj objects
+on free lists never have a nonzero second word.
+* Replaced BCC_MAKEFILE with an up-to-date one (thanks to Andre Leiradella).
+* Upgraded libtool, configure.in and some related files to hopefully
+support NetBSD/SPARC (thanks to Adrian Bunk).  Unfortunately,
+libtool 1.4.2 seemed to be buggy due to missing quotes in several
+"test" invocations.  Fixed those in the ltmain.sh script.
+* Some win32-specific patches, including the introduction of
+GC_CreateThread (thanks to Adam Megacz).
+* Merged in gcj changes from Anthony Green to support embedded systems.
+* Tried to consistently rename preprocessed assembly files with a capital
+.S extension.
+* Use alpha_mach_dep.S on ALPHA again.  It doesn't really matter, but this
+makes our distribution consistent with the gcc one, avoiding future merge
+problems.
+* Move GET_MEM definition into gcconfig.h.  Include gcconfig.h slightly
+later in gc_priv.h to avoid forward references to ptr_t.
+* Add some testing of local allocation to test.c.
+* Change definition of INVALID_QTID in specific.h.  The -1 value was used
+inconsistently, and too likely to collide with a valid stack address.
+Some general clean-up of specific.[ch].  Added assertions.  (Thanks
+to Michael Smith for tracking down an intermittent bug to this
+general area.  I'm not sure it has been squashed yet, however.)
+* On Pthread systems it was not safe to call GC_malloc() between fork()
+and exec().  According to the applicable standards, it doesn't appear
+to be safe to call malloc() or many other libc functions either, thus
+it's not clear this is fixable.  Added experimental support for
+-DHANDLE_FORK in linux_threads.c which tries to support it.  It may
+succeed if libc does the right thing.  I'm not sure whether it does.
+(Thanks to Kenneth Schalk for pointing out this issue.)
+* Documented thread local allocation primitives to require an
+explicit GC_init call.  GC_init_parallel is no longer declared to
+be a constructor function, since that isn't portable and often
+seems to lead to initialization order problems.
+* Changed gc_cpp.cc and gc_cpp.h in one more attempt to make them
+compatible with Visual C++ 6 (thanks to Wink Saville for the patch).
+* Some more patches for Linux on HP PA-RISC.
+* Added include/gc_allocator.h.  It implements (hopefully) standard
+conforming (as opposed to SGI-style) allocators that allocate
+collectible (gc_allocator) or GC-traceable, but not collectible
+(traceable_allocator) objects.  This borrows heavily from libstc++,
+which borrows heavily from the SGI implementation, this part of
+which was written by Matt Austern.  Changed test_cpp.cc to very
+minimally test this.
+* On Linux/X86, retry mmap with a different start argument.  That should
+allow the collector to use more (closer to 3GB) of the address space.
+* Force 64 bit alignment with GCJ support (reflects Bryce McKinlay's
+patch to the gcc tree).
+* Refined the choice of sa_handler vs. sa_sigaction in GC_dirty_init
+to accommodate some glibc5 systems (thanks to Dan Fandrich for the patch).
+* Compensated for the fact that current versions of glibc set
+__libc_stack_end incorrectly on Linux/IA64 while initialization code
+is running.  This could cause the collector to miss 16 bytes of
+the memory stack if GC_malloc or friends where called before main().
+* Mostly integrated Takis Psarogiannakopoulos' port to DG/UX Inix 86.
+This will probably take another iteration to work, since his
+patch conflicted with the libtool upgrade.
+* Added README.arm.cross containing some information about cross-
+compiling to an ARM processor from Margaret Fleck (original code provided by
+Bradley D. LaRonde; edited by Andrej Cedilnik using some of solutions by
+Tilman Vogel; also ported for iPAQ by Oliver Kurth).
+
+
+== [6.1alpha3] 2002-02-07 ==
+
+* Minor cleanup on the gcconfig.h section for SPARC.
+* Minor fix to support Intel compiler for I386/Linux (thanks to
+Sven Hartrumpf).
+* Added SPARC V9 (64-bit) support (thanks to Jeff Sturm).
+* Restructured the way in which we determine whether or not to keep
+call stacks for debug allocation.  By default SAVE_CALL_COUNT is
+now zero on all platforms.  Added SAVE_CALL_NARGS parameters.
+If possible, use execinfo.h to capture call stack.  (This should
+add support for a number of new platforms, though often at
+considerable runtime expense.)
+* Try to print symbolic information for call stacks.  On Linux, we
+do this with a combination of execinfo.h and running addr2line in
+a separate process.  This is both much more expensive and much more
+useful.  Amazingly, it seems to be fast enough for most purposes.
+* Redefined strdup if -DREDIRECT_MALLOC is given.
+* Changed incremental collector and MPROTECT_VDB implementation so that,
+under favorable conditions, pointer-free objects are not protected.
+Added GC_incremental_protection_needs() to determine ahead of time whether
+pointer-free objects may be protected.  Replaced GC_write_hint() with
+GC_remove_protection().
+* Added test for GC_ENABLE_INCREMENTAL environment variable.
+* Made GC_time_limit runtime configurable.  Added GC_PAUSE_TIME_TARGET
+environment variable.
+* Eliminated GC_page_sz, a duplicate of GC_page_size.
+* Caused the Solaris and Irix thread creation primitives to call
+GC_init_inner().
+
+
+== [6.1alpha2] 2001-12-20 ==
+
+* No longer wrap read by default in multi-threaded applications.  It was
+pointed out on the libgcj list that this holds the allocation lock for
+way too long if the read blocks.  For now, reads into the heap are
+broken with incremental collection.  It's possible to turn this back on
+if you make sure that read calls don't block (e.g. by calling select
+first).
+* Fix ifdef in Solaris_threads.h to refer to GC_SOLARIS_THREADS.
+* Added check for environment variable GC_IGNORE_GCJ_INFO.
+* Added printing of stop-the-world GC times if GC_PRINT_STATS environment
+variable is set.
+* The calloc definition in leak_detector.h was missing parentheses, and
+realloc was missing a second argument to GC_REALLOC (thanks to
+Elvenlord Elrond).
+* Added GC_PRINT_BACK_HEIGHT environment variable and associated
+code, mostly in the new file backgraph.c.  See doc/README.environment.
+* Added -DUSE_GLOBAL_ALLOC to work around a Windows NT issue (thanks to
+Jonathan Clark).
+* Integrated port to NEC EWS4800 (MIPS-based workstation, with somewhat
+different address-space layout).  This may help for other machines with
+holes in the data segment.  (Thanks to Hironori Sakamoto.)
+* Changed the order in which GC_push_roots and friends push things onto
+the mark stack.  GC_push_all calls need to come first, since we can't
+necessarily recover if those overflow the mark stack.  (Thanks to
+Matthew Flatt for tracking down the problem.)
+* Some minor cleanups to mostly support the Intel compiler on Linux/IA64.
+
+
+== [6.1alpha1] 2001-09-22 ==
+
+* Non-debug, atomic allocations could result in bogus smashed object
+reports with debugging on (thanks to Patrick Doyle for the small test case).
+* Fixed GC_get_register_stack_base (Itanium only) to work around a glibc
+2.2.4 bug.
+* Initial port to HP/UX on Itanium.  Thread support and both 32 and 64
+bit ABIs appear to work.  Parallel mark support doesn't yet, due to
+some inline assembly code issues.  Thread local allocation does appear
+to work.
+* ifdef'ed out glibc2.1/Itanium workaround.  I suspect nobody is using
+that combination anymore.
+* Added a patch to make new_gc_alloc.h usable with gcc3.0 (thanks to
+Dimitris Vyzovitis for the patch).
+* Debugged 64-bit support on HP/UX PA-RISC.
+* Turned on dynamic loading support for FreeBSD/ELF (thanks to Peter Housel).
+* Unregistering of finalizers with debugging allocation was broken (thanks
+to Jani Kajala for the test case).
+* Old finalizers were not returned correctly from GC_debug_register_finalizer.
+* Disabled MPROTECT_VDB for Linux/M68K based on a report that it doesn't work.
+* Cleaned up some statistics gathering code in reclaim.c (thanks to
+Walter Bright).
+* Added some support for OpenBSD/ELF/Linux (thanks to Suzuki Toshiya).
+* Added Jakub Jelinek's patch to use dl_iterate_phdr for dynamic library
+traversal to dyn_load.c.  Changed it to weakly reference dl_iterate_phdr,
+so that the old code is still used with old versions of glibc.
+* Cleaned up feature test macros for various threads packages and
+integrated (partially functional) FreeBSD threads code from Loren J. Rittle.
+It's likely that the cleanup broke something, since it touched lots of
+code.  It's also likely that it fixed some unreported bugs in the
+less common thread implementations, since some of the original code
+didn't stand up to close scrutiny.  Support for the next pthreads
+implementation should be easier to add.
+
+
+== [6.0] 2001-07-26 ==
+
+* Two more bug fixes for KEEP_BACK_PTRS and DBG_HDRS_ALL.
+* Fixed a stack clearing problem that resulted in SIGILL with a
+misaligned stack pointer for multi-threaded SPARC builds.
+* Integrated another HURD patch (thanks to Igor Khavkine).
+
+
+== [6.0alpha9] ==
+
+* added README.macros.
+* Made gc.mak a symbolic link to work around winzip's tendency to ignore
+hard links.
+* Simplified the setting of NEED_FIND_LIMIT in os_dep.c, possibly breaking
+it on untested platforms.
+* Integrated initial GNU HURD port (thanks to Chris Lingard and
+Igor Khavkine).
+* A few more fixes for Digital Mars compiler (by Walter Bright).
+* Fixed gcc version recognition.  Renamed OPERATOR_NEW_ARRAY to
+GC_OPERATOR_NEW_ARRAY.  Changed GC_OPERATOR_NEW_ARRAY to be the default.
+It can be overridden with -DGC_NO_OPERATOR_NEW_ARRAY (thanks to
+Cesar Eduardo Barros).
+* Changed the byte size to free-list mapping in thread local allocation
+so that size 0 allocations are handled correctly.
+* Fixed Linux/MIPS stackbottom for new toolchain (thanks to Ryan Murray).
+* Changed finalization registration to invoke GC_oom_fn when it runs out
+of memory.
+* Removed lvalue cast in finalize.c.  This caused some debug configurations
+not to build with some non-gcc compilers.
+
+
+== [6.0alpha8] 2001-06-15 ==
+
+* Changed GC_debug_malloc_replacement and GC_debug_realloc_replacement
+so that they compile under Irix (thanks to Dave Love).
+* Updated powerpc_macosx_mach_dep.s so that it works if the collector
+is in a dynamic library (thanks to Andrew Begel).
+* Transformed README.debugging into debugging.html, updating and
+expanding it in the process.  Added gcdescr.html and tree.html
+from the web site to the GC distribution.
+* Fixed several problems related to PRINT_BLACK_LIST.  This involved
+restructuring some of the marker macros.
+* Fixed some problems with the sizing of objects with debug information.
+Finalization was broken KEEP_BACK_PTRS or PRINT_BLACK_LIST.  Reduced the
+object size with SHORT_DEBUG_HDRS by another word.
+* The "Needed to allocate blacklisted ..." warning had inadvertently
+been turned off by default, due to a buggy test in allchblk.c.  Turned
+it back on.
+* Removed the marker macros to deal with 2 pointers in interleaved fashion.
+They were messy and the performance improvement seemed minimal.  We'll
+leave such scheduling issues to the compiler.
+* Changed Linux/PowerPC test to also check for __powerpc__ in response
+to a discussion on the gcc mailing list.
+* Removed the "static" from the jmp_buf declaration in GC_generic_push_regs
+(suggested by Matthew Flatt).  This was causing problems in
+systems that register all of their own roots.  It looks far more correct
+to me without the "static" anyway.
+* Fixed several problems with thread local allocation of pointer-free or
+typed objects.  The collector was reclaiming thread-local free lists, since
+it wasn't following the link fields.
+* There was apparently a long-standing race condition related to
+multi-threaded incremental collection.  A collection could be started and
+a thread stopped between the memory unprotect system call and the setting of
+the corresponding dirt bit.  I believe this did not affect Solaris or PCR,
+which use a different dirty-bit implementation.  Fixed this by installing
+signal handlers with sigaction instead of signal, and disabling the thread
+suspend signal while in the write-protect handler.  (It is unclear
+whether this scenario ever actually occurred.)
+* Incremental collection did not cooperate correctly with the PARALLEL_MARK
+implementation of GC_malloc_many or the local_malloc primitives.  It still
+doesn't work well, but it shouldn't lose memory anymore.
+* Integrated some changes from the gcc source tree that I had previously
+missed (thanks to Bryce McKinlay for the reminder and patch).
+* Added Makefile.direct as a copy of the default Makefile, which would
+normally be overwritten if configure is run.
+* Changed the gc.tar target in Makefile.direct to embed the version number
+in the gc directory name.  This will affect future tar file distributions.
+* Changed the Irix dynamic library finding code to no longer try to
+eliminate writable text segments under Irix6.x, since that is probably no
+longer necessary, and can apparently be unsafe on occasion (thanks to
+Shiro Kawai for pointing this out).
+* GC_cleanup with GC_DEBUG enabled passed a real object base address to
+GC_debug_register_finalizer_ignore_self, which expected a pointer past the
+debug header.  Call GC_register_finalizer_ignore_self instead, even with
+debugging enabled (thanks to Jean-Daniel Fekete for catching this).
+* The collector didn't build with call chain saving enabled but NARGS=0.
+* Fixed up the GNU-style build files enough so that they work in some
+obvious cases (thanks to Maarten Thibaut).
+* Added initial port to Digital Mars compiler for win32 (thanks to Walter
+Bright).
+
+
+== [6.0alpha7] 2001-04-19 ==
+
+* Added GC_finalizer_notifier.  Fixed GC_finalize_on_demand.  (The variable
+actually wasn't being tested at the right points.  The build-time flag
+was.)
+* Added Tom Tromey's S390 Linux patch.
+* Added code to push GC_finalize_now in GC_push_finalizer_structures
+(thanks to Matthew Flatt).
+* Added GC_push_gc_structures() to push all GC internal roots.
+* Integrated some FreeBSD changes from Matthew Flatt.
+* It looks like USRSTACK is not always correctly defined under Solaris.
+Hacked gcconfig.h to attempt to work around the problem.  The result
+is not well tested.  (Thanks again to Matthew Flatt for pointing this out.)
+* Added Ji-Yong Chung's win32 threads and C++ fixes.
+* Arranged for hpux_test_and_clear.s to no longer be needed or built.
+It was causing build problems with gas, and it's not clear this is
+better than the pthreads alternative on this platform.
+* Some MINGW32 fixes from Hubert Garavel.
+* Added initial Hitachi SH4 port from Kaz Kojima.
+* Ported thread-local allocation and parallel mark code to HP/UX on PA_RISC.
+* Made include/gc_mark.h more public and separated out the really private
+pieces.  This is probably still not quite sufficient for clients that
+want to supply their own kind of type information.  But it's a start.
+This involved lots of identifier renaming to make it namespace clean.
+* Added GC_dont_precollect for clients that need complete control over
+the root set.
+* GC_is_visible didn't do the right thing with gcj objects.  (Not that
+many people are likely to care, but ...)
+* Don't redefine read with GC_USE_LD_WRAP.
+* Initial port to LINUX/HP_PA.  Incremental collection and threads are not
+yet supported.  (Incremental collection should work if you have the
+right kernel.  Threads may work with a sufficiently patched pthread
+library.)
+* Changed gcconfig.h to recognize __i386__ as an alternative to i386 in
+many places (thanks to Benjamin Lerman).
+* Made win32_threads.c more tolerant of detaching a thread that it didn't
+know about (thanks to Paul Nash).
+* Added Makefile.am and configure.in from gcc to the distribution, with
+minimal changes.  For the moment, those are just placeholders.  In the
+future, we're planning to switch to a GNU-style build environment for
+Un*x-like systems, though the old Makefile will remain as a backup.
+* Turned off STUBBORN_ALLOC by default, and added it back as a Makefile
+option.
+* Redistributed some functions between malloc.c and mallocx.c, so that
+simple statically linked apps no longer pull in mallocx.o.
+* Changed large object allocation to clear the first and last few words
+of each block before releasing the lock.  Otherwise the marker could see
+objects with nonsensical type descriptors.
+* Fixed a couple of subtle problems that could result in not recognizing
+interior pointers from the stack.  (I believe these were introduced
+in 6.0alpha6.)
+* GC_debug_free_inner called GC_free, which tried to reacquire the
+allocator lock, and hence deadlocked.  (DBG_HDRS_ALL probably never worked
+with threads.)
+* Fixed several problems with back traces.  Accidental references to a free
+list could cause the free list pointer to be overwritten by a back pointer.
+There seemed to be some problems with the encoding of root and finalizer
+references.
+
+
+== [6.0alpha6] ==
+
+* Changed the definition of DATASTART on ALPHA and IA64, where data_start
+and __data_start are not defined by earlier versions of glibc.  This might
+need to be fixed on other platforms as well.
+* Changed the way the stack base and backing store base are found on IA64.
+This should now remain reliable on future kernels.  But since it relies
+on /proc, it will no longer work in the simulated NUE environment.
+* Made the call to random() in dbg_mlc.c with -DKEEP_BACK_PTRS dependent
+on the OS.  On non-Unix systems, rand() should be used instead.  Handled
+small RAND_MAX (thanks to Peter Ross for pointing this out).
+* Fixed the cord make rules to create the cord subdirectory, if necessary
+(thanks to Doug Moen).
+* Changed fo_object_size calculation in finalize.c.  Turned finalization
+of non-heap object into a no-op.  Removed anachronism from GC_size()
+implementation.
+* Changed GC_push_dirty call in solaris_threads.c to GC_push_selected.
+It was missed in a previous renaming (thanks to Vladimir Tsichevski
+for pointing this out).
+* Arranged to not mask SIGABRT in linux_threads.c (thanks to Bryce McKinlay).
+* Added GC_no_dls hook for applications that want to register their own
+roots.
+* Integrated Kjetil Matheussen's Amiga changes.
+* Added FREEBSD_STACKBOTTOM.  Changed the X86/FreeBSD port to use it
+(thanks to Matthew Flatt).
+* Added pthread_detach interception for platforms supported by linux_threads.c
+and irix_threads.c.
+* Changed the USE_MMAP code to check for the case in which we got the
+high end of the address space, i.e. mem_ptr + mem_sz == 0.  It appears
+that this can happen under Solaris 7.  It seems to be allowed by what
+I would claim is an oversight in the mmap specification.  (Thanks to
+Toshio Endo for pointing out the problem.)
+* Cleanup of linux_threads.c.  Some code was originally cloned from
+irix_threads.c and now unnecessary.  Some comments were obviously wrong.
+* (Mostly) fixed a longstanding problem with setting of dirty bits from
+a signal handler.  In the presence of threads, dirty bits could get lost,
+since the getting of a bit in the bit vector was not atomic with respect
+to other updates.  The fix is 100% correct only for platforms for which
+GC_test_and_set is defined.  The goal is to make that all platforms with
+thread support.  Matters only if incremental GC and threads are both
+enabled.
+* made GC_all_interior_pointers (a.k.a. ALL_INTERIOR_POINTERS) an
+initialization time, instead of build-time option.  This is a
+nontrivial, high risk change.  It should slow down the code measurably
+only if MERGE_SIZES is not defined, which is a very nonstandard
+configuration.
+* Added doc/README.environment, and implemented what it describes.  This
+allows a number of additional configuration options to be set through
+the environment.  It documents a few previously undocumented options.
+* Integrated Eric Benson's leak testing improvements.
+* Removed the option to throw away the beginning of each page (DISCARD_WORDS).
+This became less and less useful as processors enforce stricter alignment.
+And it hadn't been tested in ages, and was thus probably broken anyway.
+
+
+== [6.0alpha5] ==
+
+* Changed the definition of GC_pause in linux_threads.c to use a volatile
+asm.  Some versions of gcc apparently optimize away writes to local volatile
+variables.  This caused poor locking behavior starting at about
+4 processors.
+* Added GC_start_blocking(), GC_end_blocking() calls and wrapper for sleep
+to linux_threads.c.
+The first two calls could be used to generally avoid sending GC signals to
+blocked threads, avoiding both premature wakeups and unnecessary overhead.
+* Fixed a serious bug in thread-local allocation.  At thread termination,
+GC_free could get called on small integers.  Changed the code for thread
+termination to more efficiently return left-over free-lists.
+* Integrated Kjetil Matheussen's BeOS support.
+* Rearranged the directory structure to create the doc and tests
+subdirectories.
+* Sort of integrated Eric Benson's patch for OSF1.  This provided basic
+OSF1 thread support by suitably extending hpux_irix_threads.c.  Based
+on earlier email conversations with David Butenhof, I suspect that it
+will be more reliable in the long run to base this on linux_threads.c
+instead.  Thus I attempted to patch up linux_threads.c based on Eric's code.
+The result is almost certainly broken, but hopefully close enough that
+someone with access to a machine can pick it up.
+* Integrated lots of minor changes from the NetBSD distribution.  (These
+were supplied by David Brownlee.  I'm not sure about the original
+authors.)
+* Hacked a bit more on the HP/UX thread-support in linux_threads.c.  It
+now appears to work in the absence of incremental collection.  Renamed
+hpux_irix_threads.c back to irix_threads.c, and removed the attempt to
+support HPUX there.
+* Changed gc.h to define _REENTRANT in cases in which it should already
+have been defined. It is still safer to also define it on the command
+line.
+
+
+== [6.0alpha4] ==
+
+* Moved up the detection of mostly full blocks to the initiation of the
+sweep phase.  This eliminates some lock contention in the PARALLEL_MARK case,
+as multiple threads try to look at mostly full blocks concurrently.
+* Restored the code in GC_malloc_many that grabs a prefix of the global
+free list.  This avoids the case in which every GC_malloc_many call
+tries and fails to allocate a new heap block, and the returns a single
+object from the global free list.
+* Some minor fixes in new_hblk.c.  (Attempted to build free lists in order
+of increasing addresses instead of decreasing addresses for cache performance
+reasons.  But this seems to be only a very minor gain with -DEAGER_SWEEP,
+and a loss in other cases.  So the change was backed out.)
+* Fixed some of the documentation (thanks in large part to Fergus Henderson).
+* Fixed the Linux USE_PROC_FOR_LIBRARIES code to deal with apps that perform
+large numbers of mmaps (thanks to Eric Benson).  Also fixed that code to
+deal with short reads.
+* Added GC_get_total_bytes().
+* Fixed leak detection mode to avoid spurious messages under linuxthreads.
+(This should also now be easy for the other supported threads packages.
+But the code is tricky enough that I'm hesitant to do it without being able
+to test.  Everything allocated in the GC thread support itself should be
+explicitly deallocated.)
+* Made it possible (with luck) to redirect malloc to GC_local_malloc.
+
+
+== [6.0alpha3] 2000-09-26 ==
+
+* Fixed the /proc/self/maps code to not seek, since that apparently is not
+reliable across all interesting kernels.
+* Fixed some compilation problems in the absence of PARALLEL_MARK
+(introduced in alpha2).
+* Fixed an algorithmic problem with PARALLEL_MARK.  If work needs to
+be given back to the main mark "stack", the BOTTOM entries of the local
+stack should be given away, not the top ones.  This has substantial
+performance impact, especially for > 2 processors, from what I can tell.
+* Extracted gc_lock.h from gc_priv.h.  This should eventually make it a
+bit easier to avoid including gc_priv.h in clients.
+* Moved all include files to include/ and removed duplicate links to the
+same file.  The old scheme was a bad idea because it was too easy to get the
+copies out of sync, and many systems don't support hard links.
+Unfortunately, it's likely that I broke some of the non-Unix Makefiles in
+the process, although I tried to update them appropriately.
+* Removed the partial support for a copied nursery.  It's not clear that
+this would be a tremendous win, since we don't consistently lose to
+generational copying collectors.  And it would significantly complicate
+many things.  May be reintroduced if/when it really turns out to win.
+* Removed references to IRIX_JDK_THREADS, since I believe there never
+were and never will be any clients.
+* Added some code to linux_threads.c to possibly support HPUX threads
+using the Linux code.  Unfortunately, it doesn't work yet, and is
+currently disabled.
+* Added support under Linux/X86 for saving the call chain, both in (debug)
+objects for client debugging, and in GC_arrays._last_stack for GC
+debugging.  This was previously supported only under Solaris.  It is
+not enabled by default under X86, since it requires that code be compiled
+to explicitly gave frame pointers on the call stack.  (With gcc this
+currently happens by default, but is often turned off explicitly.)
+To turn it on, define SAVE_CALL_CHAIN.
+
+
+== [6.0alpha2] ==
+
+* Added USE_MARK_BYTES to reduce the need for compare-and-swap on platforms
+for which that's expensive.
+* Fixed a locking bug ib GC_gcj_malloc and some locking assertion problems.
+* Added a missing volatile to OR_WORD and renamed the parameter to
+GC_compare_and_swap so it's not a C++ reserved word (thanks to
+Toshio Endo for pointing out both of those).
+* Changed Linux dynamic library registration code to look at /proc/self/maps
+instead of the rld data structures when REDIRECT_MALLOC is defined.
+Otherwise some of the rld data data structures may be prematurely garbage
+collected.
+* Fixed USE_LD_WRAP a bit more, so it should now work without threads.
+* Renamed XXX_THREADS macros to GC_XXX_THREADS for namespace correctness.
+Temporarily added some backward compatibility definitions.  Renamed
+USE_LD_WRAP to GC_USE_LD_WRAP.
+* Many MACOSX POWERPC changes, some additions to the gctest output, and
+a few minor generic bug fixes (thanks to Dietmar Planitzer).
+
+
+== [6.0alpha1] ==
+
+* Added HP/PA prefetch support.
+* Added -DDBG_HDRS_ALL and -DSHORT_DBG_HDRS to reduce the cost and improve
+the reliability of generating pointer backtrace information, e.g. in
+the Bigloo environment.
+* Added parallel marking support (-DPARALLEL_MARK).  This currently
+works only under IA32 and IA64 Linux, but it shouldn't be hard to adapt
+to other platforms.  This is intended to be a lighter-weight (less
+new code, probably not as scalable) solution than the work by Toshio Endo
+et al, at the University of Tokyo.  A number of their ideas were
+reused, though the code wasn't, and the underlying data structure
+is significantly different.  In particular, we keep the global mark
+stack as a single shared data structure, but most of the work is done
+on smaller thread-local mark stacks.
+* Changed GC_malloc_many to be cheaper, and to require less mutual exclusion
+with -DPARALLEL_MARK.
+* Added full support for thread local allocation under Linux
+(-DTHREAD_LOCAL_ALLOC).  This is a thin veneer on GC_malloc_many, and
+should be easily portable to other platforms, especially those that
+support pthreads.
+* CLEAR_DOUBLE was not always getting invoked when it should have been.
+* GC_gcj_malloc and friends used different out of memory handling than
+everything else, probably because I forgot about one when I implemented
+the other.  They now both call GC_oom_fn(), not GC_oom_action().
+* Integrated Jakub Jelinek's fixes for Linux/SPARC.
+* Moved GC_objfreelist, GC_aobjfreelist, and GC_words_allocd out of
+GC_arrays, and separately registered the first two as excluded roots.
+This makes code compiled with gc_inl.h less dependent on the
+collector version.  (It would be nice to remove the inclusion of
+gc_priv.h by gc_inl.h completely, but we're not there yet.  The
+locking definitions in gc_priv.h are still referenced.)
+This change was later conditioned on SEPARATE_GLOBALS, which
+is not defined by default, since it involves a performance hit.
+* Register GC_obj_kinds separately as an excluded root region.  The
+attempt to register it with GC_arrays was usually failing.  (This wasn't
+serious, but seemed to generate some confusion.)
+* Moved backptr.h to gc_backptr.h.
+
+
+== [5.4] ==
+
+* Fixed a typo that prevented compilation with -DUSE_3DNOW_PREFETCH (thanks to
+Shawn Wagner for actually testing this).
+* Fixed GC_is_thread_stack in solaris_threads.c.  It forgot to return a value
+in the common case.
+* Fixed another silly syntax problem in GC_double_descr (thanks to
+Fergus Henderson for finding it).
+* Fixed a GC_gcj_malloc bug: It tended to release the allocator lock twice.
+
+
+== [5.3] 2000-09-24 ==
+
+* Fixed _end declaration for OSF1.
+* There were lots of spurious leak reports in leak detection mode, caused
+by the fact that some pages were not being swept, and hence unmarked
+objects weren't making it onto free lists.  (This bug dated back to 5.0.)
+* Fixed a typo in the liblinuxgc.so Makefile rule.
+* Added the GetExitCodeThread to Win32 GC_stop_world to (mostly) work
+around a Windows 95 GetOpenFileName problem (thanks to Jacob Navia).
+
+
+== [5.2] ==
+
+* dyn_load.c declared GC_scratch_last_end_ptr as an extern even if it
+was defined as a macro.  This prevented the collector from building on
+Irix.
+* We quietly assumed that indirect mark descriptors were never 0.
+Our own typed allocation interface violated that.  This could result
+in segmentation faults in the marker with typed allocation.
+* Fixed a _DUSE_MUNMAP bug in the heap block allocation code (thanks to
+Ben Hutchings for the patch).
+* Taught the collector about VC++ handling array operator new (thanks to
+Ben Hutchings for the patch).
+* The two copies of gc_hdrs.h had diverged.  Made one a link to the other
+again.
+
+
+== [5.1] ==
+
+* Fixed a gc.h header bug which showed up under Irix (thanks to Dan Sullivan).
+* Fixed a typo in GC_double_descr in typd_mlc.c.
+This probably could result in objects described by array descriptors not
+getting traced correctly (thanks to Ben Hutchings for pointing this out).
+* The block nearly full tests in reclaim.c were not correct for 64 bit
+environments.  This could result in unnecessary heap growth under unlikely
+conditions.
+
+
+== [5.0] ==
+
+* Fixed threadlibs.c for linux threads.  -DUSE_LD_WRAP was broken and
+-ldl was omitted.  Fixed Linux stack finding code to handle
+-DUSE_LD_WRAP correctly.
+* Added MSWIN32 exception handler around marker, so that the collector
+can recover from root segments that are unmapped during the collection.
+This caused occasional failures under Windows 98, and may also be
+an issue under Windows NT/2000.
+
+
+== [5.0alpha7] ==
+
+* -DREDIRECT_MALLOC was broken in alpha6. Fixed.
+* Cleaned up gc_ccp.h slightly, thus also causing the HP C++ compiler to
+accept it.
+* Removed accidental reference to dbg_mlc.c, which caused dbg_mlc.o to be
+linked into every executable.
+* Added PREFETCH to bitmap marker.  Changed it to use the header cache.
+* GC_push_marked sometimes pushed one object too many, resulting in a
+segmentation fault in GC_mark_from_mark_stack.  This was probably an old
+bug.  It finally showed up in gctest on win32.
+* Gc_priv.h erroneously #defined GC_incremental to be TRUE instead of FALSE
+when SMALL_CONFIG was defined.  This was no doubt a major performance bug for
+the default win32 configuration.
+* Removed -DSMALL_CONFIG from NT_MAKEFILE.  It seemed like an anachronism now
+that the average PC has 64MB or so.
+* Integrated Bryce McKinlay's patches for linux threads and dynamic loading
+from the libgcj tree.  Turned on dynamic loading support for Linux/PPC.
+* Changed the stack finding code to use environ on HP/UX (thanks
+to Gustavo Rodriguez-Rivera for the suggestion).  This should
+probably be done on other platforms, too.  Since I can't test those, that'll
+wait until after 5.0.
+
+
+== [5.0alpha6] ==
+
+* GC_malloc_explicitly_typed and friends sometimes failed to
+initialize first word.
+* Added allocation routines and support in the marker for mark descriptors
+in a type structure referenced by the first word of an object.  This was
+introduced to support gcj, but hopefully in a way that makes it
+generically useful.
+* Added GC_requested_heapsize, and inhibited collections in non-incremental
+mode if the actual used heap size is less than what was explicitly
+requested.
+* The Solaris pthreads version of GC_pthread_create didn't handle a NULL
+attribute pointer.  Solaris thread support used the wrong default thread
+stack size (thanks to Melissa O'Neill for the patch).
+* Changed PUSH_CONTENTS macro to no longer modify first parameter.
+This usually doesn't matter, but it was certainly an accident waiting
+to happen ...
+* Added GC_register_finalizer_no_order and friends to gc.h.  They're
+needed by Java implementations.
+* Integrated a fix for a win32 deadlock resulting from clock() calling
+malloc (thanks to Chris Dodd).
+* Integrated Hiroshi Kawashima's port to Linux/MIPS.  This was designed
+for a handheld platform, and may or may not be sufficient for other
+machines.
+* Fixed a va_arg problem with the %c specifier in cordprnt.c.  It appears
+that this was always broken, but recent versions of gcc are the first to
+report the (statically detectable) bug.
+* Added an attempt at a more general solution to dlopen races/deadlocks.
+GC_dlopen now temporarily disables collection.  Still not ideal, but ...
+* Added -DUSE_I686_PREFETCH, -DUSE_3DNOW_PREFETCH, and support for IA64
+prefetch instructions.  May improve performance measurably, but I'm not
+sure the code will run correctly on processors that don't support the
+instruction.  Won't build except with very recent gcc.
+* Added caching for header lookups in the marker.  This seems to result
+in a barely measurable performance gain.  Added support for interleaved
+lookups of two pointers, but unconfigured that since the performance
+gain is currently near zero, and it adds to code size.
+* Changed Linux DATASTART definition to check both data_start and
+__data_start, since nothing else seems to be portable.
+* Added -DUSE_LD_WRAP to optionally take advantage of the GNU ld function
+wrapping mechanism.  Probably currently useful only on Linux.
+* Moved some variables for the scratch allocator into GC_arrays (suggested
+by Martin Hirzel).
+* Fixed a win32 threads bug that caused the collector to not look for
+interior pointers from one of the thread stacks without
+ALL_INTERIOR_POINTERS (thanks to Jeff Sturm).
+* Added Mingw32 support (thanks to Jeff Sturm for the patch).
+* Changed the alpha port to use the generic register scanning code instead
+of alpha_mach_dep.s.  Alpha_mach_dep.s doesn't look for pointers in fp
+registers, but gcc sometimes spills pointers there (thanks to Manuel Serrano
+for helping debug this).  Changed the IA64 code to
+do something similar for similar reasons.
+
+
+== [5.0alpha4] 1999-10-30 ==
+
+* Added protection fault handling patch for Linux/M68K from Fergus
+Henderson and Roman Hodek.
+* Removed the tests for SGI_SOURCE in new_gc_alloc.h.  This was causing that
+interface to fail on non-SGI platforms.
+* Changed the Linux stack finding code to use /proc, after changing it
+to use HEURISTIC1 (thanks to David Mosberger for pointing out /proc hook).
+* Added HP/UX incremental GC support and HP/UX 11 thread support.
+Thread support is currently still flaky.
+* Added basic Linux/IA64 support.
+* Integrated Anthony Green's PicoJava support.
+* Integrated Scott Ananian's StrongARM/NetBSD support.
+* Fixed some fairly serious performance bugs in the incremental
+collector.  These have probably been there essentially forever.
+(Mark bits were sometimes set before scanning dirty pages.
+The reclaim phase unnecessarily dirtied full small object pages.)
+* Changed the reclaim phase to ignore nearly full pages to avoid
+touching them.
+* Limited GC_black_list_spacing to roughly the heap growth increment.
+* Changed full collection triggering heuristic to decrease full GC
+frequency by default, but to explicitly trigger full GCs during
+heap growth.  This doesn't always improve things, but on average it's
+probably a win.
+* GC_debug_free(0, ...) failed (thanks to Fergus Henderson for the
+bug report and fix).
+
+
+== [5.0alpha3] 1999-09-15 ==
+
+(Also known as 4.15alpha3.)
+* Added some highly incomplete code to support a copied young generation.
+Comments on nursery.h are appreciated.
+* Changed -DFIND_LEAK, -DJAVA_FINALIZATION, and -DFINALIZE_ON_DEMAND,
+so the same effect could be obtained with a runtime switch.   This is
+a step towards standardizing on a single dynamic GC library.
+* Significantly changed the way leak detection is handled, as a consequence
+of the above.
+
+
+== [5.0alpha2] 1999-07-23 ==
+
+* Fixed bugs introduced in alpha1 (OpenBSD & large block initialization).
+* Added -DKEEP_BACK_PTRS and backptr.h interface.  (The implementation
+idea came from Alan Demers.)
+
+
+== [5.0alpha1] 1999-06-30 ==
+
+(Also known as 4.15alpha1.)
+* Reworked large block allocator.  Now uses multiple doubly linked free
+lists to approximate best fit.
+* Changed heap expansion heuristic.  Entirely free blocks are no longer
+counted towards the heap size.  This seems to have a major impact on
+heap size stability; the old version could expand the heap way too
+much in the presence of large block fragmentation.
+* added -DGC_ASSERTIONS and some simple assertions inside the collector.
+This is mainlyt for collector debugging.
+* added -DUSE_MUNMAP to allow the heap to shrink.  Supported on only
+a few UNIX-like platforms for now.
+* added GC_dump_regions() for debugging of fragmentation issues.
+* Changed PowerPC pointer alignment under Linux to 4.
+* Changed the Linux/Alpha port to walk the data segment backwards until
+it encounters a SIGSEGV.  The old way to find the start of the data
+segment broke with a recent release.
+* cordxtra.c needed to call GC_REGISTER_FINALIZER instead of
+GC_register_finalizer, so that it would continue to work with GC_DEBUG.
+* allochblk sometimes cleared the wrong block for debugging purposes
+when it dropped blacklisted blocks.  This could result in spurious
+error reports with GC_DEBUG.
+* added MACOS X Server support (thanks to Andrew Stone).
+* Changed the Solaris threads code to ignore stack limits > 8 MB with
+a warning.  Empirically, it is not safe to access arbitrary pages
+in such large stacks.  And the dirty bit implementation does not
+guarantee that none of them will be accessed.
+* Integrated Martin Tauchmann's Amiga changes.
+* Integrated James Dominy's OpenBSD/SPARC port.
+
+
+== [4.14] 1999-04-16 ==
+
+* changed STACKBOTTOM for DJGPP (thanks to Salvador Eduardo Tropea).
+
+
+== [4.14alpha2] 1999-03-26 ==
+
+* -DSMALL_CONFIG did not work reliably with large (> 4K) pages.
+Recycling the mark stack during expansion could result in a size
+zero heap segment, which confused things.  (This was probably also an
+issue with the normal config and huge pages.)
+* Did more work to make sure that callee-save registers were scanned
+completely, even with the setjmp-based code.  Added USE_GENERIC_PUSH_REGS
+macro to facilitate testing on machines I have access to.
+* Added code to explicitly push register contents for win32 threads.
+This seems to be necessary.  (Thanks to Pierre de Rop.)
+
+
+== [4.14alpha1] 1999-03-10 ==
+
+* Fixed GC_print_source_ptr to not use a prototype.
+* generalized CYGWIN test.
+* gc::new did the wrong thing with PointerFreeGC placement (thanks to
+Rauli Ruohonen).
+* In the ALL_INTERIOR_POINTERS (default) case, some callee-save register
+values could fail to be scanned if the register was saved and
+reused in a GC frame.  This showed up in verbose mode with gctest
+compiled with an unreleased SGI compiler.  I vaguely recall an old
+bug report that may have been related.  The bug was probably quite old.
+(The problem was that the stack scanning could be deferred until
+after the relevant frame was overwritten, and the new save location
+might be outside the scanned area.  Fixed by more eager stack scanning.)
+* PRINT_BLACK_LIST had some problems.  A few source addresses were garbage.
+* Replaced Makefile.dj and added -I flags to cord make targets (thanks to
+Gary Leavens).
+* GC_try_to_collect was broken with the non-incremental collector.
+* gc_cleanup destructors could pass the wrong address to
+GC_register_finalizer_ignore_self in the presence of multiple
+inheritance (thanks to Darrell Schiebel).
+* Changed PowerPC Linux stack finding code.
+
+
+== [4.13] 1999-02-19 ==
+
+* Fixed a crucial bug in the Watcom port.  There was a redundant declaration
+of GC_push_one in gc_priv.h.
+* Added FINALIZE_ON_DEMAND.
+* Fixed some pre-ANSI cc problems in test.c.
+* Removed getpagesize() use for Solaris.  It seems to be missing in one
+or two versions.
+* Fixed bool handling for SPARCCompiler version 4.2.
+* Fixed some files in include that had gotten unlinked from the main
+copy.
+* Some RS/6000 fixes (missing casts).  (Thanks to Toralf Foerster.)
+* Fixed several problems in GC_debug_realloc, affecting mostly the
+FIND_LEAK case.
+* GC_exclude_static_roots contained a buggy unsigned comparison to
+terminate a loop (thanks to Wilson Ho).
+* CORD_str failed if the substring occurred at the last possible position.
+(Only affects cord users.)
+* Fixed Linux code to deal with RedHat 5.0 and integrated Peter Bigot's
+os_dep.c code for dealing with various Linux versions.
+* Added workaround for Irix pthreads sigaction bug and possible signal
+misdirection problems.
+
+
+== [4.13alpha3] 1998-12-08 ==
+
+* Fixed MSWIN32 recognition test, which interfered with cygwin.
+* Removed unnecessary gc_watcom.asm from distribution.  Removed
+some obsolete README.win32 text.
+* Added Alpha Linux incremental GC support (thanks to Philipp Tomsich
+for code for retrieving the fault address in a signal handler).
+Changed Linux signal handler context argument to be a pointer.
+* Took care of some new warnings generated by the 7.3 SGI compiler.
+* Integrated Phillip Musumeci's FreeBSD/ELF fixes.
+* -DIRIX_THREADS was broken with the -o32 ABI (typo in gc_priv.h).
+
+
+== [4.13alpha2] 1998-08-08 ==
+
+* Fixed more Linux threads problems.
+* Changed default GC_free_space_divisor to 3 with new large block allocation
+(thanks to Matthew Flatt for some measurements that suggest the old
+value sometimes favors space too much over time).
+* More CYGWIN32 fixes.
+* Integrated Tyson Dowd's Linux-M68K port.
+* Minor HP PA and DEC UNIX fixes from Fergus Henderson.
+* Integrated Christoffe Raffali's Linux-SPARC changes.
+* Allowed for one more GC fixup iteration after a full GC in incremental
+mode.  Some quick measurements suggested that this significantly
+reduces pause times even with smaller GC_RATE values.
+* Moved some more GC data structures into GC_arrays.  This decreases
+pause times and GC overhead, but makes debugging slightly less convenient.
+* Fixed namespace pollution problem ("excl_table").
+* Made GC_incremental a constant for -DSMALL_CONFIG, hopefully shrinking
+that slightly.
+* Added some win32 threads fixes.
+* Integrated Ivan Demakov and David Stes' Watcom fixes.
+* Various other minor fixes contributed by many people.
+* Renamed config.h to gcconfig.h, since config.h tends to be used for
+many other things.
+* Integrated Matthew Flatt's support for 68K MacOS "far globals".
+* Fixed up some of the dynamic library Makefile targets for consistency
+across platforms.
+* Fixed a USE_MMAP typo that caused out-of-memory handling to fail
+on Solaris.
+* Added code to test.c to test thread creation a bit more.
+* Integrated GC_win32_free_heap (as suggested by Ivan Demakov).
+* Fixed Solaris 2.7 stack base finding problem.  (This may actually
+have been done in an earlier alpha release.)
+
+
+== [4.13alpha1] 1998-02-17 ==
+
+* Changed RS6000 STACKBOTTOM.
+* Integrated Patrick Beard's Mac changes.
+* Alpha1 didn't compile on Irix m.n, m < 6.
+* Replaced Makefile.dj with a new one from Gary Leavens.
+* Added Andrew Stitcher's changes to support SCO OpenServer.
+* Added PRINT_BLACK_LIST, to allow debugging of high densities of false
+pointers.
+* Added code to debug allocator to keep track of return address
+in GC_malloc caller, thus giving a bit more context.
+* Changed default behavior of large block allocator to more
+aggressively avoid fragmentation.  This is likely to slow down the
+collector when it succeeds at reducing space cost.
+* Integrated Fergus Henderson's CYGWIN32 changes.  They are untested,
+but needed for newer versions.
+* USE_MMAP had some serious bugs.  This caused the collector to fail
+consistently on Solaris with -DSMALL_CONFIG.
+* Added Linux threads support (thanks to Fergus Henderson).
+
+
+== [4.12] 1997-08-26 ==
+
+* Fixed ElfW definition in dyn_load.c.
+This prevented the dynamic library support from compiling on some
+older ELF Linux systems.
+* Fixed UTS4 port (which I apparently mangled during the integration).
+(Thanks to Alistair Crooks.)
+* "Make C++" failed on Suns with SC4.0, due to a problem with "bool".
+Fixed in gc_priv.h.
+* Added more pieces for GNU win32 (thanks to Timothy N. Newsham).
+The current state of things should suffice for at least some
+applications.
+* Changed the out of memory retry count handling.  (This matters only
+if GC_max_retries > 0, which is no longer the default.)
+* If a /proc read failed repeatedly, GC_written_pages was not updated
+correctly (thanks to Peter Chubb for diagnosing this).
+* Under unlikely circumstances, the allocator could infinite loop in
+an out of memory situation (thanks to Kenjiro Taura for
+identifying the problem and supplying a fix).
+* Fixed a syntactic error in the DJGPP code.  Also fixed a test program
+problem with DJGPP (thanks to Fergus Henderson and Peter Monks).
+* Atomic uncollectible objects were not treated correctly by the
+incremental collector.  This resulted in weird log statistics and
+occasional performance problems (thanks to Peter Chubb for pointing this out).
+* Fixed some problems resulting from compilers that don't define
+__STDC__.  In this case void * and char * were used inconsistently
+in some cases.  (Void * should not have been used at all.  If
+you have an ANSI superset compiler that does not define __STDC__,
+please compile with -D__STDC__=0.  Thanks to Manuel Serrano and others
+for pointing out the problem.)
+* Fixed a compilation problem on Irix with -n32 and -DIRIX_THREADS.
+Also fixed some other IRIX_THREADS problems which may or may not have
+had observable symptoms.
+* Fixed an HP PA compilation problem in dyn_load.c (thanks to
+Philippe Queinnec).
+* SEGV fault handlers sometimes did not get reset correctly (thanks
+to David Pickens).
+* Added a fix for SOLARIS_THREADS on Intel (thanks to David Pickens).
+This probably needs more work to become functional.
+* Fixed struct sigcontext_struct in os_dep.c for compilation under
+Linux 2.1.X (thanks to Fergus Henderson).
+* Changed the DJGPP STACKBOTTOM and DATASTART values to those ones suggested
+(by Kristian Kristensen).  These may still not be right, but it is
+it is likely to work more often than what was there before.  They may
+even be exactly right.
+* Added a #include <string.h> to test_cpp.cc.  This appears to help
+with HP/UX and gcc (thanks to Assar Westerlund).
+* Version 4.11 failed to run in incremental mode on recent 64-bit Irix
+kernels.  This was a problem related to page unaligned heap segments.
+Changed the code to page align heap sections on all platforms.
+(I had mistakenly identified this as a kernel problem earlier.
+It was not.)
+* Version 4.11 did not make allocated storage executable, except on
+one or two platforms, due to a bug in a #if test (thanks to David Grove
+for pointing this out).
+* Added sparc_sunos4_mach_dep.s to support Sun's compilers under SunOS4.
+* Added GC_exclude_static_roots.
+* Fixed the object size mapping algorithm.  This shouldn't matter,
+but the old code was ugly.
+* Heap checking code could die if one of the allocated objects was
+larger than its base address.  (Unsigned underflow problem.  Thanks
+to Clay Spence for isolating the problem.)
+* Added RS6000 (AIX) dynamic library support and fixed STACK_BOTTOM (thanks
+to Fred Stearns).
+* Added Fergus Henderson's patches for improved robustness with large
+heaps and lots of blacklisting.
+* Added Peter Chubb's changes to support Solaris Pthreads, to support
+MMAP allocation in Solaris, to allow Solaris to find dynamic libraries
+through /proc, to add malloc_typed_ignore_off_page, and a few other
+minor features and bug fixes.
+* The Solaris 2 port should not use sbrk.  I received confirmation from
+Sun that the use of sbrk and malloc in the same program is not
+supported.  The collector now defines USE_MMAP by default on Solaris.
+* Replaced the djgpp makefile with Gary Leavens' version.
+* Fixed MSWIN32 detection test.
+* Added Fergus Henderson's patches to allow putting the collector into
+a DLL under GNU win32.
+* Added Ivan V. Demakov's port to Watcom C on X86.
+* Added Ian Piumarta's Linux/PowerPC port.
+* Added PointerFreeGC to the placement options in gc_cpp.h (suggested by
+Brian Burton).  This is of course unsafe, and may be controversial.
+On the other hand, it seems to be needed often enough that it's worth
+adding as a standard facility.
+* Add Lars Farm's suggestions on building the collector for MacOS.
+
+
+== [4.12alpha2] ==
+
+(Changes not specified.)
+
+
+== [4.11] 1996-12-03 ==
+
+* Rationalized (hopefully) GC_try_to_collect in an incremental collection
+environment.  It appeared to not handle a call while a collection was in
+progress, and was otherwise too conservative.
+* Merged GC_reclaim_or_delete_all into GC_reclaim_all to get rid of some
+code.
+* Added Patrick Beard's Mac fixes, with substantial completely untested
+modifications.
+* Fixed the MPROTECT_VDB code to deal with large pages and imprecise
+fault addresses (as on an UltraSPARC running Solaris 2.5).  Note that this
+was not a problem in the default configuration, which uses PROC_VDB.
+* The DEC Alpha assembly code needed to restore $gp between calls (thanks to
+Fergus Henderson for tracking this down and supplying a patch).
+* The write command for "de" was completely broken for large files.
+I used the easiest portable fix, which involved changing the semantics
+so that f.new is written instead of overwriting f.  That's safer anyway.
+* Added README.solaris2 with a discussion of the possible problems of
+mixing the collector's sbrk allocation with malloc/realloc.
+* Changed the data segment starting address for SGI machines.  The
+old code failed under IRIX6.
+* Required double word alignment for MIPS.
+* Various minor fixes to remove warnings.
+* Attempted to fix some Solaris threads problems (reported by Zhiying Chen).
+In particular, the collector could try to fork a thread with the
+world stopped as part of GC_thr_init.  It also failed to deal with
+the case in which the original thread terminated before the whole
+process did.
+* Added -DNO_EXECUTE_PERMISSION.  This has a major performance impact
+on the incremental collector under Irix, and perhaps under other
+operating systems.
+* Added some code to support allocating the heap with mmap.  This may
+be preferable under some circumstances.
+* Integrated dynamic library support for HP (thanks to Knut Tvedten).
+* Integrated James Clark's win32 threads support, and made a number
+of changes to it (many of which suggested by Pontus Rydin).  This is still
+not 100% solid.
+* Integrated Alistair G. Crooks' support for UTS4 running on an Amdahl
+370-class machine.
+* Fixed a serious bug in explicitly typed allocation.  Objects requiring
+large descriptors where handled in a way that usually resulted in
+a segmentation fault in the marker (thanks to Jeremy Fitzhardinge
+for helping to track this down).
+* Added partial support for GNU win32 development (thanks to
+Fergus Henderson).
+* Added optional support for Java-style finalization semantics (thanks to
+Patrick Bridges).  This is recommended only for Java implementations.
+* GC_malloc_uncollectable faulted instead of returning 0 when out of
+memory (thanks to Daniel R. Grayson for noticing).
+* Calls to GC_base before the collector was initialized failed on a
+DEC Alpha (thanks to Matthew Flatt).
+* Added base pointer checking to GC_REGISTER_FINALIZER in debugging mode
+(thanks to Jeremy Fitzhardinge).
+* GC_debug_realloc failed for uncollectible objects (thanks to
+Jeremy Fitzhardinge).
+* Explicitly typed allocation could crash if it ran out of memory (thanks to
+Jeremy Fitzhardinge).
+* Added minimal support for a DEC Alpha running Linux.
+* Fixed a problem with allocation of objects whose size overflowed
+ptrdiff_t.  (This now fails unconditionally, as it should.)
+* Added the beginning of Irix pthread support.
+* Integrated Xiaokun Zhu's fixes for djgpp 2.01.
+* Added SGI-style STL allocator support (gc_alloc.h).
+* Fixed a serious bug in README.solaris2.
+Multi-threaded programs must include
+gc.h with SOLARIS_THREADS defined.
+* Changed GC_free so it actually deallocates uncollectible objects (thanks
+to Peter Chubb for pointing out the problem).
+* Added Linux ELF support for dynamic libraries (thanks to Patrick Bridges).
+* Changed the Borland cc configuration so that the assembler is not
+required.
+* Fixed a bug in the C++ test that caused it to fail in 64-bit
+environments.
+
+
+== [4.10t3] 1996-11-18 ==
+
+Some changes related to threads support.
+
+
+== [4.10] 1996-02-19 ==
+
+* Fixed a typo around a call to GC_collect_or_expand in alloc.c.  It broke
+handling of out of memory.  (Thanks to Patrick C. Beard for noticing.)
+
+
+== [4.9] 1996-02-12 ==
+
+* More README.debugging fixes.
+* Objects ready for finalization, but not finalized in the same GC
+cycle, could be prematurely collected.  This occasionally happened
+in test_cpp.
+* Too little memory was obtained from the system for very large
+objects.  That could cause a heap explosion if these objects were
+not contiguous (e.g. under PCR), and too much of them was blacklisted.
+* Due to an improper initialization, the collector was too hesitant to
+allocate blacklisted objects immediately after system startup.
+* Moved GC_arrays from the data into the bss segment by not explicitly
+initializing it to zero.  This significantly
+reduces the size of executables, and probably avoids some disk accesses
+on program startup.  It's conceivable that it might break a port that I
+didn't test.
+* Fixed EMX_MAKEFILE to reflect the gc_c++.h to gc_cpp.h renaming which
+occurred a while ago.
+
+
+== [4.8] 1995-11-20 ==
+
+* Changed a "comment" in a MacOS specific part of mach_dep.c that caused
+gcc to fail on other platforms.
+
+
+== [4.7] 1995-11-18 ==
+
+* Fixed some compilation problems with -DCHECKSUMS (thanks to Ian Searle).
+* Updated some Mac specific files (to synchronize with Patrick C. Beard).
+* Fixed a serious bug for machines with non-word-aligned pointers.
+(Thanks to Patrick C. Beard for pointing out the problem.  The collector
+should fail almost any conceivable test immediately on such machines.)
+
+
+== [4.6] 1995-11-09 ==
+
+* Added Linux ELF support (thanks to Arrigo Triulzi).
+* GC_base crashed if it was called before any other GC_ routines.
+This could happen if a gc_cleanup object was allocated outside the heap
+before any heap allocation.
+* The heap expansion heuristic was not stable if all objects had finalization
+enabled.  Fixed finalize.c to count memory in finalization queue and
+avoid explicit deallocation.  Changed alloc.c to also consider this count.
+(This is still not recommended.  It's expensive if nothing else.  Thanks
+to John Ellis for pointing this out.)
+* GC_malloc_uncollectable(0) was broken (thanks to Phong Vo for pointing
+this out).
+* The collector didn't compile under Linux 1.3.X (thanks to Fred Gilham for
+pointing this out).  The current workaround is ugly, but expected to be
+temporary.
+* Fixed a formatting problem for SPARC stack traces.
+* Fixed some '=='s in os_dep.c that should have been assignments.
+Fortunately these were in code that should never be executed anyway (thanks
+to Fergus Henderson).
+* Fixed the heap block allocator to only drop blacklisted blocks in small
+chunks.  Made BL_LIMIT self adjusting.  (Both of these were in response
+to heap growth observed by Paul Graham.)
+* Fixed the Metrowerks/68K Mac code to also mark from a6 (thanks to
+Patrick C. Beard).
+* Significantly updated README.debugging.
+* Fixed some problems with longjmps out of signal handlers, especially under
+Solaris.  Added a workaround for the fact that siglongjmp doesn't appear to
+do the right thing with -lthread under Solaris.
+* Added MSDOS/djgpp port (thanks to Mitch Harris).
+* Added "make reserved_namespace" and "make user_namespace".  The
+first renames ALL "GC_xxx" identifiers as "_GC_xxx".  The second is the
+inverse transformation.  Note that doing this is guaranteed to break all
+clients written for the other names.
+* descriptor field for kind NORMAL in GC_obj_kinds with ADD_BYTE_AT_END
+defined should be -ALIGNMENT not WORDS_TO_BYTES(-1).  This is
+a serious bug on machines with pointer alignment of less than a word.
+* GC_ignore_self_finalize_mark_proc didn't handle pointers to very near the
+end of the object correctly.  Caused failures of the C++ test on a DEC Alpha
+with g++.
+* gc_inl.h still had problems.  Partially fixed.  Added warnings at the
+beginning to hopefully specify the remaining dangers.
+* Added DATAEND definition to config.h.
+* Fixed some of the .h file organization.  Fixed "make floppy".
+
+
+== [4.5] 1995-06-14 ==
+
+* Fixed many minor and one major README bugs (thanks to Franklin Chen
+for pointing out many of them).
+* Fixed ALPHA/OSF/1 dynamic library support (thanks to Jonathan Bachrach).
+* Added incremental GC support (MPROTECT_VDB) for Linux (with some
+help from Bruno Haible).
+* Altered SPARC recognition tests in gc.h and config.h (mostly as
+suggested by Fergus Henderson).
+* Added basic incremental GC support for win32, as implemented by
+Windows NT and Windows 95.  GC_enable_incremental is a no-op
+under win32s, which doesn't implement enough of the VM interface.
+* Added -DLARGE_CONFIG.
+* Fixed GC_..._ignore_off_page to also function without
+-DALL_INTERIOR_POINTERS.
+* (Hopefully) fixed RS/6000 port.  (Only the test was broken.)
+* Fixed a performance bug in the non-incremental collector running
+on machines supporting incremental collection with MPROTECT_VDB
+(e.g. SunOS 4, DEC AXP).  This turned into a correctness bug under
+win32s with win32 incremental collection.  (Not all memory protection
+was disabled.)
+* Fixed some ppcr related bit rot.
+* Caused dynamic libraries to be unregistered before re-registering.
+The old way turned out to be a performance bug on some machines.
+* GC_root_size was not properly maintained under MSWIN32.
+* Added -DNO_DEBUGGING and GC_dump.
+* Fixed a couple of bugs arising with SOLARIS_THREADS +
+REDIRECT_MALLOC.
+* Added NetBSD/M68K port (thanks to Peter Seebach).
+* Fixed a serious realloc bug.  For certain object sizes, the collector
+wouldn't scan the expanded part of the object.  (Thanks to Clay Spence
+for noticing the problem, and helping me to track it down.)
+
+
+== [4.4] 1995-02-18 ==
+
+* ASM_CLEAR_CODE was erroneously defined for HP
+PA machines, resulting in a compile error.
+* Fixed OS/2 Makefile to create a library (thanks to Mark Boulter).
+* Gc_cleanup objects didn't work if they were created on
+the stack.  Fixed.
+* One copy of Gc_cpp.h in the distribution was out of
+synch, and failed to document some known compiler
+problems with explicit destructor invocation.  Partially
+fixed.  There are probably other compilers on which
+gc_cleanup is miscompiled.
+* Fixed Makefile to pass C compiler flags to C++ compiler.
+* Added Mac fixes.
+* Fixed os_dep.c to work around what appears to be
+a new and different VirtualQuery bug under newer
+versions of win32S.
+* GC_non_gc_bytes was not correctly maintained by
+GC_free.  Fixed (thanks to James Clark).
+* Added GC_set_max_heap_size.
+* Changed allocation code to ignore blacklisting if it is preventing
+use of a very large block of memory.  This has the advantage
+that naive code allocating very large objects is much more
+likely to work.  The downside is you might no
+longer find out that such code should really use
+GC_malloc_ignore_off_page.
+* Changed GC_printf under win32 to close and reopen the file
+between calls.  FAT file systems otherwise make the log file
+useless for debugging.
+* Added GC_try_to_collect and GC_get_bytes_since_gc.  These
+allow starting an abortable collection during idle times.
+This facility does not require special OS support.  (Thanks to
+Michael Spertus of Geodesic Systems for suggesting this.  It was
+actually an easy addition.  Kumar Srikantan previously added a similar
+facility to a now ancient version of the collector.  At the time
+this was much harder, and the result was less convincing.)
+* Added some support for the Borland development environment (thanks
+to John Ellis and Michael Spertus).
+* Removed a misfeature from checksums.c that caused unexpected
+heap growth (thanks to Scott Schwartz).
+* Changed finalize.c to call WARN if it encounters a finalization cycle.
+WARN is defined in gc_priv.h to write a message, usually to stdout.
+In many environments, this may be inappropriate.
+* Renamed NO_PARAMS in gc.h to GC_NO_PARAMS, thus adhering to my own
+naming convention.
+* Added GC_set_warn_proc to intercept warnings.
+* Fixed Amiga port (thanks to Michel Schinz).
+* Fixed a bug in mark.c that could result in an access to unmapped
+memory from GC_mark_from_mark_stack on machines with unaligned
+pointers.
+* Fixed a win32 specific performance bug that could result in scanning of
+objects allocated with the system malloc.
+* Added REDIRECT_MALLOC.
+
+
+== [4.3] 1994-12-23 ==
+
+* Fixed SPARC alignment problem with GC_DEBUG.
+* Fixed Solaris threads /proc workaround.  The real
+problem was an interaction with mprotect.
+* Incorporated fix from Patrick Beard for gc_c++.h (now gc_cpp.h).
+* Slightly improved allocator space utilization by
+fixing the GC_size_map mechanism.
+* Integrated some Sony News and MIPS RISCos 4.51
+patches (thanks to Nobuyuki Hikichi at Software Research Associates,
+Inc., Japan).
+* Fixed HP_PA alignment problem (thanks to Brian F. Dennis).
+* Added GC_same_obj and friends.  Changed GC_base
+to return 0 for pointers past the end of large objects.
+Improved GC_base performance with ALL_INTERIOR_POINTERS
+on machines with a slow integer mod operation.
+Added GC_PTR_ADD, GC_PTR_STORE, etc. to prepare
+for preprocessor.
+* changed the default on most UNIX machines to be that
+signals are not disabled during critical GC operations.
+This is still ANSI-conforming, though somewhat dangerous
+in the presence of signal handlers. But the performance
+cost of the alternative is sometimes problematic.
+Can be changed back with a minor Makefile edit.
+* renamed IS_STRING in gc.h, to CORD_IS_STRING, thus
+following my own naming convention.  Added the function
+CORD_to_const_char_star.
+* Fixed a gross bug in GC_finalize.  Symptom: occasional
+address faults in that function (thanks to Anselm Baird-Smith).
+* Added port to ICL DRS6000 running DRS/NX.  Restructured
+things a bit to factor out common code, and remove obsolete
+code.  Collector should now run under SUNOS5 with either
+mprotect or /proc dirty bits.  (Thanks to Douglas Steel.)
+* More bug fixes and workarounds for Solaris 2.X.  (These were
+mostly related to putting the collector in a dynamic library,
+which didn't really work before.  Also SOLARIS_THREADS
+didn't interact well with dl_open.) (Thanks to Brian Lewis.)
+* Fixed a serious performance bug on the DEC Alpha.  The text
+segment was getting registered as part of the root set.
+(Amazingly, the result was still fast enough that the bug
+was not conspicuous.) The fix works on OSF/1, version 1.3.
+Hopefully it also works on other versions of OSF/1 ...
+* Fixed a bug in GC_clear_roots.
+* Fixed a bug in GC_generic_malloc_words_small that broke
+gc_inl.h (reported by Antoine de Maricourt).
+* Fixed some problems with cord/de under Linux.
+* Fixed some cord problems, notably with CORD_riter4.
+* Added DG/UX port (thanks to Ben A. Mesander).
+* Added finalization registration routines with weaker ordering
+constraints.  (This is necessary for C++ finalization with
+multiple inheritance, since the compiler often adds self-cycles.)
+* Filled the holes in the SCO port (thanks to Michael Arnoldus).
+* Completely rewritten the documentation in the interface gc_c++.h
+(later renamed gc_cpp.h) making it both clearer and more precise (done by
+John Ellis).
+* The definition of accessibility now ignores pointers from a finalizable
+object (an object with a clean-up function) to itself (done by John Ellis).
+This allows objects with virtual base classes to be finalizable by the
+collector.  Compilers typically implement virtual base classes using
+pointers from an object to itself, which under the old definition of
+accessibility prevented objects with virtual base classes from ever
+being collected or finalized.
+* gc_cleanup now includes gc as a virtual base.  This was enabled by
+the change in the definition of accessibility (by John Ellis).
+* Added support for operator new[] (by John Ellis).  Since most compilers
+don't yet support operator new[], it is conditionalized on
+-DOPERATOR_NEW_ARRAY.  The code is untested, but its trivial and looks
+correct.
+* The test program test_gc_c++ (later renamed test_cpp.cc)
+tries to test for the C++-specific functionality not tested by the
+other programs.
+* Added unistd.h include to misc.c.  (Needed for ppcr.)
+* Added PowerMac port (thanks to Patrick C. Beard).
+* Fixed "srcdir"-related Makefile problems.  Changed things so
+that all externally visible include files always appear in the
+include subdirectory of the source.  Made gc.h directly
+includable from C++ code (thanks to Per Bothner).
+* Changed Intel code to also mark from ebp (thanks to Kevin Warne).
+* Renamed C++ related files so they could live in a FAT
+file system (thanks to Charles Fiterman).
+* Changed Windows NT Makefile to include C++ support in
+gc.lib.  Added C++ test as Makefile target.
+
+
+== [4.2] 1994-08-03 ==
+
+* Multiple bug fixes/workarounds in the Solaris threads version.
+(It occasionally failed to locate some register contents for
+marking.  It also turns out that thr_suspend and friends are
+unreliable in Solaris 2.3.  Dirty bit reads appear
+to be unreliable under some weird
+circumstances.  My stack marking code
+contained a serious performance bug.  The new code is
+extremely defensive, and has not failed in several CPU
+hours of testing.  But no guarantees ...)
+* Added MacOS support.  (Thanks to Patrick C. Beard.
+David Chase suggested several improvements.)
+* Fixed several syntactic bugs in gc_c++.h and friends.  (These
+didn't bother g++, but did bother most other compilers.)
+Fixed gc_c++.h finalization interface.
+* 64 bit alignment for allocated objects was not guaranteed in a
+few cases in which it should have been.
+* Added GC_malloc_atomic_ignore_off_page.
+* Added GC_collect_a_little.
+* Added some prototypes to gc.h.
+* Some other minor bug fixes (notably in Makefile).
+* Fixed OS/2 / EMX port (thanks to Ari Huttunen).
+* Fixed AmigaDOS port (thanks to Michel Schinz).
+* Fixed the DATASTART definition under Solaris.  There
+was a 1 in 16K chance of the collector missing the first
+64K of static data (and thus crashing).
+* Fixed some blatant anachronisms in the README file.
+* Fixed PCR-Makefile for upcoming PPCR release.
+
+
+== [4.1] 1994-05-20 ==
+
+* Changed finalization implementation to guarantee that
+finalization procedures are called outside of the allocation
+lock, making direct use of the interface a little less dangerous.
+MAY BREAK EXISTING CLIENTS that assume finalizers
+are protected by a lock.  Since there seem to be few multi-threaded
+clients that use finalization, this is hopefully not much of
+a problem.
+* Fixed a gross bug in CORD_prev.
+* Fixed a bug in blacklst.c that could result in unbounded
+heap growth during startup on machines that do not clear
+memory obtained from the OS (e.g. win32S).
+* Ported de editor to win32/win32S.  (This is now the only
+version with a mouse-sensitive UI.  Thanks to Rob Haack for the
+implementation based on the generic Windows application template.)
+* Added GC_malloc_ignore_off_page to allocate large arrays
+in the presence of ALL_INTERIOR_POINTERS.
+* Changed GC_call_with_alloc_lock to not disable signals in
+the single-threaded case.
+* Reduced retry count in GC_collect_or_expand for garbage
+collecting when out of memory.
+* Made uncollectible allocations bypass black-listing, as they
+should.
+* Fixed a bug in typed_test in test.c that could cause (legitimate)
+GC crashes.
+* Fixed some potential synchronization problems in finalize.c
+* Fixed a real locking problem in typd_mlc.c.
+* Worked around an AIX 3.2 compiler feature that results in
+out of bounds memory references.
+* Partially worked around an IRIX5.2 beta problem (which may
+or may not persist to the final release).
+* Fixed a bug in the heap integrity checking code that could
+result in explicitly deallocated objects being identified as
+smashed.  Fixed a bug in the dbg_mlc stack saving code
+that caused old argument pointers to be considered live.
+* Fixed a bug in CORD_ncmp (and hence CORD_str).
+* Repaired the OS2 port, which had suffered from bit rot
+in 4.0.  Worked around what appears to be CSet/2 V1.0
+optimizer bug.
+* Fixed a Makefile bug for target "c++".
+
+
+== [4.0] 1994-04-07 ==
+
+* Added support for Solaris threads (which was possible
+only by reimplementing some fraction of Solaris threads,
+since Sun doesn't currently make the thread debugging
+interface available).
+* Added non-threads win32 and win32S support.
+* (Grudgingly, with suitable muttering of obscenities) renamed
+files so that the collector distribution could live on a FAT
+file system.  Files that are guaranteed to be useless on
+a PC still have long names.  Gc_inline.h and gc_private.h
+still exist, but now just include  gc_inl.h and gc_priv.h.
+* Fixed a really obscure bug in finalization that could cause
+undetected mark stack overflows.  (I would be surprised if
+any real code ever tickled this one.)
+* Changed finalization code to dynamically resize the hash
+tables it maintains.  (This probably does not matter for well-
+-written code.  It no doubt does for C++ code that overuses
+destructors.)
+* Added typed allocation primitives.  Rewrote the marker to
+accommodate them with more reasonable efficiency.  This
+change should also speed up marking for GC_malloc allocated
+objects a little.  See gc_typed.h for new primitives.  (Thanks to
+Zhong Shao performed much of the experimentation that led to the
+current typed allocation facility.)
+* Improved debugging facilities slightly.  Allocation time
+stack traces are now kept by default on SPARC/SUNOS4.  (Thanks to
+Scott Schwartz.)
+* Added better support for small heap applications.
+* Significantly extended cord package.  Fixed a bug in the
+implementation of lazily read files.  Printf and friends now
+have cord variants.  Cord traversals are a bit faster.
+* Made ALL_INTERIOR_POINTERS recognition the default.
+* Fixed de so that it can run in constant space, independent
+of file size.  Added simple string searching to cords and de.
+* Added the Hull-Ellis C++ interface (supplied by Jesse Hull and John Ellis).
+* Added dynamic library support for OSF/1 (thanks to Alan Dosser and
+Tim Bingham at DEC).
+* Changed argument to GC_expand_hp to be expressed
+in units of bytes instead of heap blocks.  (Necessary
+since the heap block size now varies depending on
+configuration.  The old version was never very clean.)
+* Added GC_get_heap_size().  The previous "equivalent"
+was broken.
+* Restructured the Makefile a bit.
+* Added FreeBSD port (provided by Jeffrey Hsu).
+
+
+== [3.7] 1994-03-15 ==
+
+* Added a workaround for an HP/UX compiler bug.
+* Fixed another stack clearing performance bug.  Reworked
+that code once more.
+
+
+== [3.6] 1994-01-14 ==
+
+* fixed a bug in the mark stack growth code that was introduced
+in 3.4.
+* fixed Makefile to work around DEC AXP compiler tail recursion
+bug.
+
+
+== [3.5] ==
+
+* Minor collections now mark from roots only once, if that
+doesn't cause an excessive pause.
+* The stack clearing heuristic was refined to prevent anomalies
+with very heavily recursive programs and sparse stacks.
+* Fixed a bug that prevented mark stack growth in some cases.
+GC_objects_are_marked should be set to TRUE after a call
+to GC_push_roots and as part of GC_push_marked, since
+both can now set mark bits.  I think this is only a performance
+bug, but I wouldn't bet on it.  It's certainly very hard to argue
+that the old version was correct.
+* Fixed an incremental collection bug that prevented it from
+working at all when HBLKSIZE != getpagesize()
+* Changed dynamic_loading.c to include gc_priv.h before testing
+DYNAMIC_LOADING.  SunOS dynamic library scanning
+must have been broken in 3.4.
+* Object size rounding now adapts to program behavior.
+* Added a workaround (provided by Manuel Serrano and
+colleagues) to a long-standing SunOS 4.X (and 3.X) ld bug
+that I had incorrectly assumed to have been squished.
+The collector was broken if the text segment size was within
+32 bytes of a multiple of 8K bytes, and if the beginning of
+the data segment contained interesting roots.  The workaround
+assumes a demand-loadable executable.  The original may have
+have "worked" in some other cases.
+* Added dynamic library support under IRIX5.
+* Added support for EMX under OS/2 (thanks to Ari Huttunen).
+* Added support of Motorola 88K processor running CX/UX (by Brent Benson).
+
+
+== [3.4] ==
+
+* Fixed a performance bug in GC_realloc.
+* Updated the amiga port.
+* Added NetBSD and 386BSD ports (supplied by Alistair G. Crooks).
+* Added cord library.
+* Added trivial performance enhancement for
+ALL_INTERIOR_POINTERS (do not scan last word).
+
+
+== [3.3] 1993-10-02 ==
+
+* PCR-specific bugs (thanks to Neil Sharman).
+* Missing locking in GC_free, redundant FASTUNLOCK
+in GC_malloc_stubborn, and 2 bugs in
+GC_unregister_disappearing_link (pointed out by Neil Sharman).
+* Common symbols allocated by the SunOS4.X dynamic loader
+were not included in the root set.
+* Bug in GC_finalize (reported by Brian Beuning and Alan Dosser).
+* Merged Amiga port from Jesper Peterson (untested).
+* Merged NeXT port from Thomas Funke (significantly
+modified and untested).  (Also thanks to Brian D. Carlstrom for
+the supplied the NeXT ports.)
+
+
+== [3.2] ==
+
+Fixed a serious and not entirely repeatable bug in
+the incremental collector.  It appeared only when dirty bit info
+on the roots was available, which is normally only under Solaris.
+It also added GC_general_register_disappearing_link, and some
+testing code.  Interface.c disappeared.
+
+
+== [3.1] ==
+
+* A workaround for a SunOS 4.X SPARC C compiler
+misfeature that caused problems when the collector was turned into
+a dynamic library.
+* A fix for a bug in GC_base that could result in a memory fault.
+* A fix for a performance bug (and several other misfeatures) pointed
+out by Dave Detlefs and Alan Dosser.
+* Use of dirty bit information for static data under Solaris 2.X.
+* DEC Alpha/OSF1 support (thanks to Alan Dosser).
+* Incremental collection on more platforms.
+* A more refined heap expansion policy.  Less space usage by default.
+* Various minor enhancements to reduce space usage, and to reduce
+the amount of memory scanned by the collector.
+* Uncollectible allocation without per object overhead.
+* More conscientious handling of out-of-memory conditions.
+* Fixed a bug in debugging stubborn allocation.
+* Fixed a bug that resulted in occasional erroneous reporting of smashed
+objects with debugging allocation.
+* Fixed bogus leak reports of size 4096 blocks with FIND_LEAK.
+
+
+== [3.0] ==
+
+Added generational/incremental collection and stubborn objects.
+
+
+== [2.6] 1993-04-27 ==
+
+(Changes not specified.)
+
+
+== [2.5] ==
+
+* Removed an explicit call to exit(1)
+* Fixed calls to GC_printf and GC_err_printf, so the correct number of
+arguments are always supplied.  The OS/2 C compiler gets confused if
+the number of actuals and the number of formals differ.  (ANSI C
+doesn't require this to work.  The ANSI sanctioned way of doing things
+causes too many compatibility problems.)
+
+
+== [2.4] 1993-01-26 ==
+
+Added GC_free_space_divisor as a tuning knob, added
+support for OS/2 and linux, and fixed the following bugs:
+* On machines with unaligned pointers (e.g. Sun 3), every 128th word could
+fail to be considered for marking.
+* Dynamic_load.c erroneously added 4 bytes to the length of the data and
+bss sections of the dynamic library.  This could result in a bad memory
+reference if the actual length was a multiple of a page.  (Observed on
+Sun 3.  Can probably also happen on a Sun 4.)
+(Thanks to Robert Brazile for pointing out that the Sun 3 version
+was broken.  Dynamic library handling is still broken on Sun 3s
+under 4.1.1U1, but apparently not 4.1.1.  If you have such a machine,
+use -Bstatic.)
+
+
+== [2.3] ==
+
+* Added ALL_INTERIOR_POINTERS.
+* Missing declaration of etext in the A/UX version.
+* Some PCR root-finding problems.
+* Blacklisting was not 100% effective, because the plausible future
+heap bounds were being miscalculated.
+* GC_realloc didn't handle out-of-memory correctly.
+* GC_base could return a nonzero value for addresses inside free blocks.
+* test.c wasn't really thread safe, and could erroneously report failure
+in a multi-threaded environment.  (The locking primitives need to be
+replaced for other threads packages.)
+* GC_CONS was thoroughly broken.
+* On a SPARC with dynamic linking, signals stayed disabled while the
+client code was running (thanks to Manuel Serrano).
+
+
+== [2.2] ==
+
+* GC_realloc could fail to extend the size of the object for certain large
+object sizes.
+* A blatant subscript range error in GC_printf, which unfortunately
+wasn't exercised on machines with sufficient stack alignment constraints.
+* GC_register_displacement did the wrong thing if it was called after
+any allocation had taken place.
+* The leak finding code would eventually break after 2048 byte
+byte objects leaked.
+* interface.c didn't compile.
+* The heap size remained much too small for large stacks.
+* The stack clearing code behaved badly for large stacks, and perhaps
+on HP/PA machines.
+
+
+== [2.1] ==
+
+* The first stable version since 1.9.
+* Added support for PPCR.
+
+
+== [2.0] ==
+
+* Introduced a consistent naming convention for collector
+routines and added support for registering dynamic library data segments
+in the standard mark_roots.c (original code supporting the SunOS dynamic
+loader provided by Bill Janssen).  Most of the data structures were revamped.
+The treatment of interior pointers was completely changed.  Finalization
+was added.  Support for locking was added.  Object kinds were added.
+We added a black listing facility to avoid allocating at addresses known
+to occur as integers somewhere in the address space.  Much of this
+was accomplished by adapting ideas and code from the PCR collector.
+The test program was changed and expanded.
+
+
+== [1.9] 1992-01-29 ==
+
+* fixed a major bug in gc_realloc.
+
+
+== [1.8] ==
+
+* added ULTRIX support in gc_private.h.  (Robert Brazile originally supplied
+the ULTRIX code.  Alan Dosser and Regis Cridlig subsequently provided updates
+and information on variation between ULTRIX systems.)
+
+
+== [1.5] ==
+
+* ensure 8 byte alignment for objects allocated on a sparc based machine.
+
+
+== [1.4] ==
+
+* Does not use compile time determined values
+for the stack base.  This no longer works on Sun 3s, since Sun 3/80s use
+a different stack base.  We now use a straightforward heuristic on all
+machines on which it is known to work (incl. Sun 3s) and compile-time
+determined values for the rest.  There should really be library calls
+to determine such values.
+
+
+== [1.3] ==
+
+* Fixed spurious
+assembly language assignments to TMP_SP.  Only the assignment in the PC/RT
+code is necessary.  On other machines, with certain compiler options,
+the assignments can lead to an unsaved register being overwritten.
+Known to cause problems under SunOS 3.5 WITHOUT the -O option.  (With
+-O the compiler recognizes it as dead code.  It probably shouldn't,
+but that's another story.)
+The SPARC-specific code was originally contributed by Mark Weiser.
+The Encore Multimax modifications were supplied by Kevin Kenny.
+The adaptation to the IBM PC/RT is largely
+due to Vernon Lee, on machines made available to Rice by IBM.
+Much of the HP specific code and a number of good suggestions for improving
+the generic code are due to Walter Underwood.
+Parag Patel supplied the A/UX code.
+Manuel Serrano supplied linux and Sony News specific code.

+ 5 - 0
blitz.mod/bdwgc/Config.cmake.in

@@ -0,0 +1,5 @@
+# The BDWgc CMake configuration file.
+
+@PACKAGE_INIT@
+include("${CMAKE_CURRENT_LIST_DIR}/BDWgcTargets.cmake")
+check_required_components(gc)

+ 33 - 0
blitz.mod/bdwgc/LICENSE

@@ -0,0 +1,33 @@
+MIT-style License
+
+Copyright (c) 1988-1989 Hans-J. Boehm, Alan J. Demers
+Copyright (c) 1991-1996 by Xerox Corporation.  All rights reserved.
+Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.
+Copyright (c) 1998 by Fergus Henderson.  All rights reserved.
+Copyright (c) 1999-2001 by Red Hat, Inc.  All rights reserved.
+Copyright (c) 1999-2011 Hewlett-Packard Development Company, L.P.
+Copyright (c) 2004-2005 Andrei Polushin
+Copyright (c) 2007 Free Software Foundation, Inc.
+Copyright (c) 2008-2021 Ivan Maidanski
+Copyright (c) 2011 Ludovic Courtes
+Copyright (c) 2018 Petter A. Urkedal
+
+
+THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+
+Permission is hereby granted to use or copy this program
+for any purpose,  provided the above notices are retained on all copies.
+Permission to modify the code and to distribute modified code is granted,
+provided the above notices are retained, and a notice that the code was
+modified is included with the above copyright notice.
+
+
+Several files (gc/gc_allocator.h, extra/msvc_dbg.c) come with slightly
+different licenses, though they are all similar in spirit (the exact
+licensing terms are given at the beginning of the corresponding source file).
+
+A few of the files needed to use the GNU-style build procedure come with
+a modified GPL license that appears not to significantly restrict use of
+the collector, though use of those files for a purpose other than building
+the collector may require the resulting code to be covered by the GPL.

+ 256 - 0
blitz.mod/bdwgc/Makefile.am

@@ -0,0 +1,256 @@
+# Copyright (c) 1999-2001 by Red Hat, Inc. All rights reserved.
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program
+# for any purpose,  provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is granted,
+# provided the above notices are retained, and a notice that the code was
+# modified is included with the above copyright notice.
+
+## Process this file with automake to produce Makefile.in.
+
+# Info (current:revision:age) for the Libtool versioning system.
+# These numbers should be updated at most once just before the release,
+# and, optionally, at most once during the development (after the release).
+LIBGC_VER_INFO = 6:0:5
+LIBGCCPP_VER_INFO = 6:0:5
+
+## FIXME: `make distcheck' in this directory will not currently work.
+##     This is most likely to the explicit flags passed to submakes.
+
+# We currently use the source files directly from libatomic_ops, if we
+# use the internal version.
+# Thus there seems to be no real reason to recursively build in the
+# libatomic_ops directory.
+SUBDIRS =
+
+ACLOCAL_AMFLAGS = -I m4
+AM_CPPFLAGS = \
+    -I$(top_builddir)/include -I$(top_srcdir)/include \
+    $(ATOMIC_OPS_CFLAGS)
+
+## Initialize variables so that we can declare files locally.
+EXTRA_DIST =
+lib_LTLIBRARIES =
+include_HEADERS =
+pkginclude_HEADERS =
+dist_noinst_HEADERS =
+check_PROGRAMS =
+check_LTLIBRARIES =
+TESTS =
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = bdw-gc.pc
+
+# C Library
+# ---------
+
+lib_LTLIBRARIES += libgc.la
+
+if SINGLE_GC_OBJ
+
+libgc_la_SOURCES = extra/gc.c
+
+if PTHREAD_START_STANDALONE
+AM_CPPFLAGS += -DGC_PTHREAD_START_STANDALONE
+libgc_la_SOURCES += pthread_start.c
+endif
+
+else
+
+EXTRA_DIST += extra/gc.c
+libgc_la_SOURCES = \
+    allchblk.c alloc.c blacklst.c dbg_mlc.c \
+    dyn_load.c finalize.c gc_dlopen.c headers.c \
+    mach_dep.c malloc.c mallocx.c mark.c mark_rts.c misc.c new_hblk.c \
+    obj_map.c os_dep.c ptr_chck.c reclaim.c specific.c typd_mlc.c
+
+# C Library: Architecture Dependent
+# ---------------------------------
+
+if WIN32_THREADS
+libgc_la_SOURCES += win32_threads.c
+else
+if PTHREADS
+# Not Cygwin or MinGW.
+libgc_la_SOURCES += pthread_start.c pthread_support.c
+if DARWIN_THREADS
+libgc_la_SOURCES += darwin_stop_world.c
+else
+libgc_la_SOURCES += pthread_stop_world.c
+endif
+endif
+endif
+
+if THREAD_LOCAL_ALLOC
+libgc_la_SOURCES += thread_local_alloc.c
+endif
+
+if MAKE_BACK_GRAPH
+libgc_la_SOURCES += backgraph.c
+endif
+
+if CHECKSUMS
+libgc_la_SOURCES += checksums.c
+endif
+
+if ENABLE_GCJ_SUPPORT
+libgc_la_SOURCES += gcj_mlc.c
+endif
+
+if ENABLE_DISCLAIM
+libgc_la_SOURCES += fnlz_mlc.c
+endif
+
+## End of !SINGLE_GC_OBJ
+endif
+
+if USE_INTERNAL_LIBATOMIC_OPS
+nodist_libgc_la_SOURCES = libatomic_ops/src/atomic_ops.c
+endif
+
+if NEED_ATOMIC_OPS_ASM
+nodist_libgc_la_SOURCES = libatomic_ops/src/atomic_ops_sysdeps.S
+endif
+
+# Include THREADDLLIBS here to ensure that the correct versions of
+# linuxthread semaphore functions get linked:
+libgc_la_LIBADD = @addobjs@ $(THREADDLLIBS) $(UNWINDLIBS) $(ATOMIC_OPS_LIBS)
+libgc_la_DEPENDENCIES = @addobjs@
+libgc_la_LDFLAGS = $(extra_ldflags_libgc) -version-info $(LIBGC_VER_INFO) \
+    -no-undefined
+
+EXTRA_libgc_la_SOURCES = ia64_save_regs_in_stack.s sparc_mach_dep.S \
+    sparc_netbsd_mach_dep.s
+
+if CPLUSPLUS
+# C++ Interface
+# -------------
+lib_LTLIBRARIES += libgccpp.la
+libgccpp_la_SOURCES = gc_badalc.cc gc_cpp.cc
+libgccpp_la_LIBADD = libgc.la
+libgccpp_la_LDFLAGS = -version-info $(LIBGCCPP_VER_INFO) -no-undefined
+if GC_TBA_LIBRARY
+# The same as libgccpp but contains only gc_badalc.o.
+lib_LTLIBRARIES += libgctba.la
+libgctba_la_SOURCES = gc_badalc.cc
+libgctba_la_LIBADD = libgc.la
+# Set the same version as for libgccpp.
+libgctba_la_LDFLAGS = -version-info $(LIBGCCPP_VER_INFO) -no-undefined
+endif
+endif
+
+EXTRA_DIST += gc_badalc.cpp gc_cpp.cpp
+
+
+# Misc
+# ----
+
+AM_CXXFLAGS = @GC_CFLAGS@
+AM_CFLAGS = $(WERROR_CFLAGS) @GC_CFLAGS@
+
+CFLAGS += $(CFLAGS_EXTRA)
+CXXFLAGS += $(CFLAGS_EXTRA)
+
+## FIXME: relies on internal code generated by automake.
+## FIXME: ./configure --enable-dependency-tracking should be used
+
+## FIXME: we shouldn't have to do this, but automake forces us to.
+## We use -Wp,-P to strip #line directives.  Irix `as' chokes on
+## these.
+if ASM_WITH_CPP_UNSUPPORTED
+  ASM_CPP_OPTIONS =
+else
+  ASM_CPP_OPTIONS = -Wp,-P -x assembler-with-cpp
+endif
+
+.s.lo:
+	$(LTCOMPILE) $(ASM_CPP_OPTIONS) -c $<
+
+.S.lo:
+	$(LTCOMPILE) $(ASM_CPP_OPTIONS) -c $<
+
+## We need to add DEFS to assembler flags
+## :FIXME: what if assembler does not accept -D... ?
+## (use Autoconf to prepare ASDEFS?)
+
+CCASFLAGS += $(DEFS)
+
+# headers which are not installed
+# (see include/include.am for more)
+#
+
+# other makefiles
+EXTRA_DIST += NT_MAKEFILE OS2_MAKEFILE PCR-Makefile digimars.mak \
+    Makefile.direct SMakefile.amiga WCC_MAKEFILE autogen.sh CMakeLists.txt \
+    Config.cmake.in build/s60v3/bld.inf build/s60v3/libgc.mmp
+
+# files used by makefiles other than Makefile.am
+#
+EXTRA_DIST += tools/if_mach.c tools/if_not_there.c tools/setjmp_t.c \
+    tools/threadlibs.c extra/MacOS.c extra/AmigaOS.c \
+    extra/symbian/global_end.cpp extra/symbian/global_start.cpp \
+    extra/symbian/init_global_static_roots.cpp extra/symbian.cpp \
+    extra/pcr_interface.c extra/real_malloc.c \
+    extra/Mac_files/datastart.c extra/Mac_files/dataend.c \
+    extra/Mac_files/MacOS_config.h extra/msvc_dbg.c tools/callprocs.sh
+
+#
+# :GOTCHA: GNU make rule for making .s out of .S is flawed,
+# it will not remove dest if building fails
+.S.s:
+	if $(CPP) $< >$@ ; then :; else rm -f $@; fi
+
+include include/include.am
+include cord/cord.am
+include tests/tests.am
+
+## Putting these at the top causes cord to be built first, and not find
+## libgc.a on HP/UX.  There may be a better fix.
+
+# Installed documentation.
+if ENABLE_DOCS
+dist_doc_DATA = \
+    AUTHORS \
+    LICENSE \
+    README.md \
+    doc/README.DGUX386 \
+    doc/README.Mac \
+    doc/README.OS2 \
+    doc/README.aix \
+    doc/README.amiga \
+    doc/README.arm.cross \
+    doc/README.autoconf \
+    doc/README.cmake \
+    doc/README.cords \
+    doc/README.darwin \
+    doc/README.emscripten \
+    doc/README.environment \
+    doc/README.ews4800 \
+    doc/README.hp \
+    doc/README.linux \
+    doc/README.macros \
+    doc/README.sgi \
+    doc/README.solaris2 \
+    doc/README.symbian \
+    doc/README.uts \
+    doc/README.win32 \
+    doc/README.win64 \
+    doc/debugging.md \
+    doc/finalization.md \
+    doc/gcdescr.md \
+    doc/gcinterface.md \
+    doc/leak.md \
+    doc/overview.md \
+    doc/porting.md \
+    doc/scale.md \
+    doc/simple_example.md \
+    doc/tree.md
+
+dist_man3_MANS = gc.man
+endif
+
+# A dummy target for mono build.
+test-bundle:

+ 436 - 0
blitz.mod/bdwgc/Makefile.direct

@@ -0,0 +1,436 @@
+# This is the original manually generated Makefile.  It may still be used
+# to build the collector.
+#
+# Primary targets:
+# all - builds libgc.a, libgccpp.a, libgctba.a and libcord.a
+# base_lib - builds libgc.a only (basic library)
+# c++ - builds libgccpp.a and libgctba.a only (C++ interface to library)
+# cords - builds libcord.a only (heavyweight strings library)
+# check - same as "all" but also prints porting information, and runs some
+#         tests of collector and cords
+# check-deps - same as check but do not run the tests
+# check-cpp - builds libgc.a, libgccpp.a and libgctba.a, runs C++ only test
+# check-cpp-deps - same as check-cpp but do not run the test
+# cord/de - builds dumb editor based on cords.
+
+ABI_FLAG=
+# ABI_FLAG should be the cc flag that specifies the ABI.  On most
+# platforms this will be the empty string.  Possible values:
+# +DD64 for 64-bit executable on HP/UX.
+# -n32, -n64, -o32 for SGI/MIPS ABIs.
+
+AS_ABI_FLAG=$(ABI_FLAG)
+# ABI flag for assembler.  On HP/UX this is +A64 for 64 bit
+# executables.
+
+CC=cc $(ABI_FLAG)
+# Compiler executable name.  For EMX, replace to "gcc".
+
+CXX=g++ $(ABI_FLAG)
+# Needed only for "make c++", which builds the C++ interface.
+
+AS=as $(AS_ABI_FLAG)
+# The above doesn't work with gas, which doesn't run cpp.
+# Define AS as `gcc -c -x assembler-with-cpp' instead.
+# Under Irix 6, you have to specify the ABI (-o32, -n32, or -64)
+# if you use something other than the default ABI on your machine.
+
+LD=ld
+
+# Redefining srcdir allows object code for the nonPCR version of the collector
+# to be generated in different directories.
+srcdir= .
+VPATH= $(srcdir)
+
+# Path to atomic_ops source.
+AO_SRC_DIR=$(srcdir)/libatomic_ops
+
+CFLAGS_EXTRA=
+# We need CFLAGS_FOR_PIC because we might be building a shared library.
+CFLAGS= -O -I$(srcdir)/include -I$(AO_SRC_DIR)/src \
+  -DALL_INTERIOR_POINTERS -DENABLE_DISCLAIM -DGC_ATOMIC_UNCOLLECTABLE \
+  -DGC_GCJ_SUPPORT -DJAVA_FINALIZATION -DNO_EXECUTE_PERMISSION \
+  -DUSE_MMAP -DUSE_MUNMAP $(CFLAGS_FOR_PIC) $(CFLAGS_EXTRA)
+
+# To build the collector with threads support, add to the above:
+# -DGC_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC
+#
+# To build the preload library that intercepts malloc, add:
+# -DGC_USE_DLOPEN_WRAP -DREDIRECT_MALLOC=GC_malloc -fpic
+
+# To build the collector with fork() support by default, add to the above:
+# -DHANDLE_FORK
+
+# HOSTCC and HOSTCFLAGS are used to build executables that will be run as
+# part of the build process, i.e. on the build machine.  These will usually
+# be the same as CC and CFLAGS, except in a cross-compilation environment.
+# Note that HOSTCFLAGS should include any -D flags that affect thread support.
+HOSTCC=$(CC)
+HOSTCFLAGS=$(CFLAGS)
+
+# For dynamic library builds, it may be necessary to add flags to generate
+# PIC code, e.g. -fPIC on Linux.
+
+# setjmp_test may yield overly optimistic results when compiled
+# without optimization.
+
+# Look into doc/README.macros for the description of the "define arguments"
+# influencing the collector configuration.
+
+CXXFLAGS= $(CFLAGS)
+AR= ar
+
+RANLIB= ranlib
+# For EMX, replace "ranlib" with "ar s".
+
+
+OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o \
+  headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o dbg_mlc.o  \
+  malloc.o checksums.o pthread_support.o pthread_stop_world.o \
+  darwin_stop_world.o typd_mlc.o ptr_chck.o mallocx.o gcj_mlc.o specific.o \
+  gc_dlopen.o backgraph.o win32_threads.o pthread_start.o \
+  thread_local_alloc.o fnlz_mlc.o atomic_ops.o atomic_ops_sysdeps.o
+
+CSRCS= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c \
+  headers.c mark.c obj_map.c blacklst.c finalize.c \
+  new_hblk.c dyn_load.c dbg_mlc.c malloc.c \
+  checksums.c pthread_support.c pthread_stop_world.c darwin_stop_world.c \
+  typd_mlc.c ptr_chck.c mallocx.c gcj_mlc.c specific.c gc_dlopen.c \
+  backgraph.c win32_threads.c pthread_start.c thread_local_alloc.c fnlz_mlc.c
+
+CORD_SRCS= cord/cordbscs.c cord/cordxtra.c cord/cordprnt.c cord/tests/de.c \
+  cord/tests/cordtest.c include/gc/cord.h include/gc/ec.h \
+  include/gc/cord_pos.h cord/tests/de_win.c cord/tests/de_win.h \
+  cord/tests/de_cmds.h cord/tests/de_win.rc
+
+CORD_OBJS= cord/cordbscs.o cord/cordxtra.o cord/cordprnt.o
+
+SRCS= $(CSRCS) \
+  include/gc/gc_typed.h include/gc/gc_tiny_fl.h include/gc/gc_version.h \
+  include/gc.h include/private/gc_hdrs.h include/private/gc_priv.h \
+  include/private/gcconfig.h include/private/gc_pmark.h \
+  include/gc/gc_inline.h include/gc/gc_mark.h include/gc/gc_disclaim.h \
+  tools/threadlibs.c tools/if_mach.c tools/if_not_there.c gc_badalc.cc \
+  gc_cpp.cc include/gc_cpp.h include/private/gc_alloc_ptrs.h \
+  include/gc/gc_allocator.h include/gc/javaxfc.h include/gc/gc_backptr.h \
+  include/gc/gc_gcj.h include/private/gc_locks.h include/private/dbg_mlc.h \
+  include/private/specific.h include/gc/leak_detector.h \
+  include/gc/gc_pthread_redirects.h include/private/gc_atomic_ops.h \
+  include/gc/gc_config_macros.h include/private/pthread_support.h \
+  include/private/pthread_stop_world.h include/private/darwin_semaphore.h \
+  include/private/darwin_stop_world.h include/private/thread_local_alloc.h \
+  ia64_save_regs_in_stack.s sparc_mach_dep.S \
+  sparc_netbsd_mach_dep.s $(CORD_SRCS)
+
+CORD_INCLUDE_FILES= $(srcdir)/include/gc.h $(srcdir)/include/gc/cord.h \
+  $(srcdir)/include/gc/ec.h $(srcdir)/include/gc/cord_pos.h
+
+# Executable file name extension.  For EMX, specify ".exe".
+EXEEXT=
+
+UTILS= if_mach$(EXEEXT) if_not_there$(EXEEXT) threadlibs$(EXEEXT)
+
+# Libraries needed for curses applications.  Only needed for de.
+# It might also require -ltermlib on some targets.
+CURSES= -lcurses
+
+# The following is irrelevant on most systems.  But a few
+# versions of make otherwise fork the shell specified in
+# the SHELL environment variable.
+SHELL= /bin/sh
+
+SPECIALCFLAGS= -I$(srcdir)/include -I$(AO_SRC_DIR)/src $(CFLAGS_FOR_PIC)
+# Alternative flags to the C compiler for mach_dep.c.
+# Mach_dep.c often doesn't like optimization, and it's
+# not time-critical anyway.
+# Set SPECIALCFLAGS to -q nodirect_code on Encore.
+
+all: base_lib cords c++
+
+atomic_ops.o: $(AO_SRC_DIR)/src/atomic_ops.c
+	$(CC) $(CFLAGS) -c -o $@ $(AO_SRC_DIR)/src/atomic_ops.c
+# For some reason, Solaris make does not handle "$<" properly.
+
+atomic_ops_sysdeps.o: $(AO_SRC_DIR)/src/atomic_ops_sysdeps.S
+	$(CC) $(CFLAGS) -c -o $@ $(AO_SRC_DIR)/src/atomic_ops_sysdeps.S
+
+LEAKFLAGS= $(CFLAGS) -DFIND_LEAK
+
+BSD-pkg-all: bsd-libgc.a bsd-libleak.a
+
+bsd-libgc.a bsd-libgccpp.a bsd-libgctba.a:
+	$(MAKE) -f Makefile.direct CFLAGS="$(CFLAGS)" clean c++-t
+	mv libgc.a bsd-libgc.a
+	mv libgccpp.a bsd-libgccpp.a
+	mv libgctba.a bsd-libgctba.a
+
+bsd-libleak.a:
+	$(MAKE) -f Makefile.direct CFLAGS="$(LEAKFLAGS)" clean c++-nt
+	mv libgc.a bsd-libleak.a
+
+BSD-pkg-install: BSD-pkg-all
+	${CP} bsd-libgc.a libgc.a
+	${INSTALL_DATA} libgc.a ${PREFIX}/lib
+	${CP} bsd-libgccpp.a libgccpp.a
+	${INSTALL_DATA} libgccpp.a ${PREFIX}/lib
+	${CP} bsd-libgctba.a libgctba.a
+	${INSTALL_DATA} libgctba.a ${PREFIX}/lib
+	${INSTALL_DATA} gc.h gc_cpp.h ${PREFIX}/include
+	${INSTALL_MAN} gc.man ${PREFIX}/man/man3/gc.3
+
+pcr: PCR-Makefile include/private/gc_private.h include/private/gc_hdrs.h \
+  include/private/gc_locks.h include/gc.h include/private/gcconfig.h \
+  mach_dep.o $(SRCS)
+	$(MAKE) -f PCR-Makefile depend
+	$(MAKE) -f PCR-Makefile
+
+$(OBJS) tests/test.o dyn_load.o dyn_load_sunos53.o: \
+  $(srcdir)/include/private/gc_priv.h \
+  $(srcdir)/include/private/gc_hdrs.h $(srcdir)/include/private/gc_locks.h \
+  $(srcdir)/include/gc.h $(srcdir)/include/gc/gc_pthread_redirects.h \
+  $(srcdir)/include/private/gcconfig.h $(srcdir)/include/gc/gc_typed.h \
+  $(srcdir)/include/gc/gc_config_macros.h
+
+mark.o typd_mlc.o finalize.o ptr_chck.o: $(srcdir)/include/gc/gc_mark.h \
+					 $(srcdir)/include/private/gc_pmark.h
+
+specific.o pthread_support.o thread_local_alloc.o win32_threads.o: \
+  $(srcdir)/include/private/specific.h $(srcdir)/include/gc/gc_inline.h \
+  $(srcdir)/include/private/thread_local_alloc.h
+
+dbg_mlc.o gcj_mlc.o: $(srcdir)/include/private/dbg_mlc.h
+
+tests/test.o: $(srcdir)/tests/test.c
+	mkdir tests || cat /dev/null
+	$(CC) $(CFLAGS) -c $(srcdir)/tests/test.c
+	mv test.o tests/test.o
+
+base_lib libgc.a: $(OBJS) dyn_load.o $(UTILS)
+	rm -f dont_ar_1
+	./if_mach SPARC SOLARIS touch dont_ar_1
+	./if_mach SPARC SOLARIS $(AR) rus libgc.a $(OBJS) dyn_load.o
+	./if_mach M68K AMIGA touch dont_ar_1
+	./if_mach M68K AMIGA $(AR) -vrus libgc.a $(OBJS) dyn_load.o
+	./if_not_there dont_ar_1 || $(AR) ru libgc.a $(OBJS) dyn_load.o
+	./if_not_there dont_ar_1 || $(RANLIB) libgc.a || cat /dev/null
+	echo > base_lib
+#    Ignore ranlib failure; that usually means it doesn't exist, and
+#    isn't needed.
+
+cords libcord.a: $(CORD_OBJS) $(UTILS)
+	rm -f dont_ar_3
+	./if_mach SPARC SOLARIS touch dont_ar_3
+	./if_mach SPARC SOLARIS $(AR) rus libcord.a $(CORD_OBJS)
+	./if_mach M68K AMIGA touch dont_ar_3
+	./if_mach M68K AMIGA $(AR) -vrus libcord.a $(CORD_OBJS)
+	./if_not_there dont_ar_3 || $(AR) ru libcord.a $(CORD_OBJS)
+	./if_not_there dont_ar_3 || $(RANLIB) libcord.a || cat /dev/null
+	echo > cords
+
+gc_badalc.o: $(srcdir)/gc_badalc.cc $(srcdir)/include/gc_cpp.h \
+  $(srcdir)/include/gc.h
+	$(CXX) -c $(CXXFLAGS) $(srcdir)/gc_badalc.cc
+
+gc_cpp.o: $(srcdir)/gc_cpp.cc $(srcdir)/include/gc_cpp.h $(srcdir)/include/gc.h
+	$(CXX) -c $(CXXFLAGS) $(srcdir)/gc_cpp.cc
+
+test_cpp$(EXEEXT): $(srcdir)/tests/test_cpp.cc $(srcdir)/include/gc_cpp.h \
+  $(srcdir)/include/gc.h c++ base_lib $(UTILS)
+	rm -f test_cpp$(EXEEXT)
+	./if_mach HP_PA HPUX $(CXX) $(CXXFLAGS) -o test_cpp $(srcdir)/tests/test_cpp.cc libgc.a libgccpp.a -ldld `./threadlibs`
+	./if_not_there test_cpp$(EXEEXT) || $(CXX) $(CXXFLAGS) -DGC_NOT_DLL -o test_cpp$(EXEEXT) $(srcdir)/tests/test_cpp.cc libgc.a libgccpp.a `./threadlibs`
+
+check-cpp-deps: test_cpp$(EXEEXT)
+
+check-cpp: check-cpp-deps
+	./test_cpp
+
+c++-t: c++ test_cpp$(EXEEXT)
+	./test_cpp 1
+
+c++-nt: c++
+	@echo "Use ./test_cpp 1 to test the leak library"
+
+c++ libgccpp.a libgctba.a: gc_badalc.o gc_cpp.o $(UTILS)
+	rm -f dont_ar_4
+	./if_mach SPARC SOLARIS touch dont_ar_4
+	./if_mach SPARC SOLARIS $(AR) rus libgccpp.a gc_badalc.o gc_cpp.o
+	./if_mach SPARC SOLARIS $(AR) rus libgctba.a gc_badalc.o
+	./if_mach M68K AMIGA touch dont_ar_4
+	./if_mach M68K AMIGA $(AR) -vrus libgccpp.a gc_badalc.o gc_cpp.o
+	./if_mach M68K AMIGA $(AR) -vrus libgctba.a gc_badalc.o
+	./if_not_there dont_ar_4 || $(AR) ru libgccpp.a gc_badalc.o gc_cpp.o
+	./if_not_there dont_ar_4 || $(RANLIB) libgccpp.a || cat /dev/null
+	./if_not_there dont_ar_4 || $(AR) ru libgctba.a gc_badalc.o
+	./if_not_there dont_ar_4 || $(RANLIB) libgctba.a || cat /dev/null
+	echo > c++
+
+dyn_load_sunos53.o: dyn_load.c
+	$(CC) $(CFLAGS) -DSUNOS53_SHARED_LIB -c $(srcdir)/dyn_load.c -o $@
+
+# SunOS5 shared library version of the collector
+sunos5gc.so: $(OBJS) dyn_load_sunos53.o
+	$(CC) -G -o sunos5gc.so $(OBJS) dyn_load_sunos53.o -ldl
+	ln sunos5gc.so libgc.so
+
+# Alpha/OSF shared library version of the collector
+libalphagc.so: $(OBJS)
+	$(LD) -shared -o libalphagc.so $(OBJS) dyn_load.o -lc
+	ln libalphagc.so libgc.so
+
+# IRIX shared library version of the collector
+libirixgc.so: $(OBJS) dyn_load.o
+	$(LD) -shared $(ABI_FLAG) -o libirixgc.so $(OBJS) dyn_load.o -lc
+	ln libirixgc.so libgc.so
+
+# Linux shared library version of the collector
+liblinuxgc.so: $(OBJS) dyn_load.o
+	gcc -shared -o liblinuxgc.so $(OBJS) dyn_load.o
+	ln liblinuxgc.so libgc.so
+
+# Build gctest with dynamic library
+dyn_test:
+	$(CC) $(CFLAGS) -o gctest$(EXEEXT) tests/test.c libgc.so `./threadlibs`
+	./gctest
+
+# Alternative Linux rule.  This is preferable, but is likely to break the
+# Makefile for some non-linux platforms.
+# LIBOBJS= $(patsubst %.o, %.lo, $(OBJS))
+#
+#.SUFFIXES: .lo $(SUFFIXES)
+#
+#.c.lo:
+# $(CC) $(CFLAGS) $(CPPFLAGS) -fPIC -c $< -o $@
+#
+# liblinuxgc.so: $(LIBOBJS) dyn_load.lo
+# 	gcc -shared -Wl,-soname=libgc.so.0 -o libgc.so.0 $(LIBOBJS) dyn_load.lo
+#	touch liblinuxgc.so
+
+mach_dep.o: $(srcdir)/mach_dep.c $(srcdir)/sparc_mach_dep.S \
+  $(srcdir)/ia64_save_regs_in_stack.s \
+  $(srcdir)/sparc_netbsd_mach_dep.s $(UTILS)
+	rm -f mach_dep.o
+	./if_mach SPARC SOLARIS $(CC) -c -o mach_dep2.o $(srcdir)/sparc_mach_dep.S
+	./if_mach SPARC OPENBSD $(CC) -c -o mach_dep2.o $(srcdir)/sparc_mach_dep.S
+	./if_mach SPARC NETBSD $(AS) -o mach_dep2.o $(srcdir)/sparc_netbsd_mach_dep.s
+	./if_mach SPARC "" $(CC) -c -o mach_dep1.o $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
+	./if_mach SPARC "" $(LD) -r -o mach_dep.o mach_dep1.o mach_dep2.o
+	./if_mach IA64 "" $(AS) -o ia64_save_regs_in_stack.o $(srcdir)/ia64_save_regs_in_stack.s
+	./if_mach IA64 "" $(CC) -c -o mach_dep1.o $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
+	./if_mach IA64 "" $(LD) -r -o mach_dep.o mach_dep1.o ia64_save_regs_in_stack.o
+	-./if_not_there mach_dep.o || $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
+	-./if_not_there mach_dep.o || `cygpath -w /bin/sh` $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
+	-./if_not_there mach_dep.o || /bin/sh $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
+
+mark_rts.o: $(srcdir)/mark_rts.c $(UTILS)
+	rm -f mark_rts.o
+	-./if_mach ALPHA OSF1 $(CC) -c $(CFLAGS) -Wo,-notail $(srcdir)/mark_rts.c
+	-./if_not_there mark_rts.o || $(CC) -c $(CFLAGS) $(srcdir)/mark_rts.c
+	-./if_not_there mark_rts.o || `cygpath -w /bin/sh` $(CC) -c $(CFLAGS) $(srcdir)/mark_rts.c
+	-./if_not_there mark_rts.o || /bin/sh $(CC) -c $(CFLAGS) $(srcdir)/mark_rts.c
+#   Work-around for DEC optimizer tail recursion elimination bug.
+#   The ALPHA-specific line should be removed if gcc is used.
+
+alloc.o: include/gc/gc_version.h
+
+cord/cordbscs.o: $(srcdir)/cord/cordbscs.c $(CORD_INCLUDE_FILES)
+	$(CC) $(CFLAGS) -c -I$(srcdir) $(srcdir)/cord/cordbscs.c
+	mkdir cord || cat /dev/null
+	mv cordbscs.o cord/cordbscs.o
+#  not all compilers understand -o filename
+
+cord/cordxtra.o: $(srcdir)/cord/cordxtra.c $(CORD_INCLUDE_FILES)
+	$(CC) $(CFLAGS) -c -I$(srcdir) $(srcdir)/cord/cordxtra.c
+	mkdir cord || cat /dev/null
+	mv cordxtra.o cord/cordxtra.o
+
+cord/cordprnt.o: $(srcdir)/cord/cordprnt.c $(CORD_INCLUDE_FILES)
+	$(CC) $(CFLAGS) -c -I$(srcdir) $(srcdir)/cord/cordprnt.c
+	mkdir cord || cat /dev/null
+	mv cordprnt.o cord/cordprnt.o
+
+cordtest$(EXEEXT): $(srcdir)/cord/tests/cordtest.c cords base_lib $(UTILS)
+	rm -f cordtest$(EXEEXT)
+	./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o cordtest $(srcdir)/cord/tests/cordtest.c libgc.a libcord.a -lucb
+	./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o cordtest $(srcdir)/cord/tests/cordtest.c libgc.a libcord.a -ldld `./threadlibs`
+	./if_mach M68K AMIGA $(CC) $(CFLAGS) -UGC_AMIGA_MAKINGLIB -o cordtest $(srcdir)/cord/tests/cordtest.c libgc.a libcord.a `./threadlibs`
+	./if_not_there cordtest$(EXEEXT) || $(CC) $(CFLAGS) -o cordtest$(EXEEXT) $(srcdir)/cord/tests/cordtest.c libgc.a libcord.a `./threadlibs`
+
+cord/de: de$(EXEEXT)
+
+de$(EXEEXT): $(srcdir)/cord/tests/de.c $(srcdir)/cord/tests/de_win.c \
+  $(srcdir)/cord/tests/de_win.h cords base_lib $(UTILS)
+	rm -f de$(EXEEXT)
+	./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o de $(srcdir)/cord/tests/de.c libgc.a libcord.a -lcurses -ltermlib -lucb `./threadlibs`
+	./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o de $(srcdir)/cord/tests/de.c libgc.a libcord.a -lcurses -ltermlib -ldld `./threadlibs`
+	./if_mach POWERPC AIX $(CC) $(CFLAGS) -o de $(srcdir)/cord/tests/de.c libgc.a libcord.a -lcurses
+	./if_mach POWERPC DARWIN $(CC) $(CFLAGS) -o de $(srcdir)/cord/tests/de.c libgc.a libcord.a
+	./if_mach M68K AMIGA $(CC) $(CFLAGS) -UGC_AMIGA_MAKINGLIB -o de $(srcdir)/cord/tests/de.c libgc.a libcord.a -lcurses
+	./if_not_there de$(EXEEXT) || $(CC) $(CFLAGS) -o de$(EXEEXT) $(srcdir)/cord/tests/de.c $(srcdir)/cord/tests/de_win.c libgc.a libcord.a $(CURSES) `./threadlibs`
+
+if_mach$(EXEEXT): $(srcdir)/tools/if_mach.c \
+  $(srcdir)/include/private/gcconfig.h
+	$(HOSTCC) $(HOSTCFLAGS) -o if_mach$(EXEEXT) $(srcdir)/tools/if_mach.c
+
+threadlibs$(EXEEXT): $(srcdir)/tools/threadlibs.c \
+  $(srcdir)/include/private/gcconfig.h
+	$(HOSTCC) $(HOSTCFLAGS) -o threadlibs$(EXEEXT) $(srcdir)/tools/threadlibs.c
+
+if_not_there$(EXEEXT): $(srcdir)/tools/if_not_there.c
+	$(HOSTCC) $(HOSTCFLAGS) -o if_not_there$(EXEEXT) $(srcdir)/tools/if_not_there.c
+
+clean:
+	rm -f *.a *.i *.o *.exe tests/*.o gctest gctest_dyn_link test_cpp \
+	      setjmp_test mon.out gmon.out a.out core if_not_there if_mach \
+	      base_lib c++ $(CORD_OBJS) cordtest de cords dont_ar_* threadlibs
+	-rm -f *~
+
+gctest$(EXEEXT): tests/test.o base_lib $(UTILS)
+	rm -f gctest$(EXEEXT)
+	./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o gctest tests/test.o libgc.a -lucb
+	./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o gctest tests/test.o libgc.a -ldld `./threadlibs`
+	./if_mach M68K AMIGA $(CC) $(CFLAGS) -UGC_AMIGA_MAKINGLIB -o gctest  tests/test.o libgc.a `./threadlibs`
+	./if_not_there gctest$(EXEEXT) || $(CC) $(CFLAGS) -o gctest$(EXEEXT) tests/test.o libgc.a `./threadlibs`
+
+# If an optimized setjmp_test generates a segmentation fault,
+# odds are your compiler is broken.  gctest may still work.
+# Try compiling setjmp_t.c unoptimized.
+setjmp_test$(EXEEXT): $(srcdir)/tools/setjmp_t.c $(srcdir)/include/gc.h \
+  $(UTILS)
+	$(CC) $(CFLAGS) -o setjmp_test$(EXEEXT) $(srcdir)/tools/setjmp_t.c
+
+check-deps: cordtest$(EXEEXT) gctest$(EXEEXT) setjmp_test$(EXEEXT) \
+  test_cpp$(EXEEXT)
+
+check: check-deps
+	./setjmp_test
+	./gctest
+	./cordtest
+	./test_cpp
+
+# A synonym to "check" (for compatibility with older GC versions).
+test: check
+
+# BTL: added to test shared library version of collector.
+# Currently works only under SunOS5.  Requires GC_INIT call from statically
+# loaded client code.
+ABSDIR= `pwd`
+gctest_dyn_link: tests/test.o libgc.so
+	$(CC) -L$(ABSDIR) -R$(ABSDIR) -o gctest_dyn_link tests/test.o -lgc -ldl -lthread
+
+gctest_irix_dyn_link: tests/test.o libirixgc.so
+	$(CC) -L$(ABSDIR) -o gctest_irix_dyn_link tests/test.o -lirixgc
+
+SYM_PREFIX-libgc=GC
+
+reserved_namespace: $(SRCS)
+	for file in $(SRCS) tests/test.c tests/test_cpp.cc; do \
+		sed s/GC_/_GC_/g < $$file > tmp; \
+		cp tmp $$file; \
+		done
+
+user_namespace: $(SRCS)
+	for file in $(SRCS) tests/test.c tests/test_cpp.cc; do \
+		sed s/_GC_/GC_/g < $$file > tmp; \
+		cp tmp $$file; \
+		done

+ 191 - 0
blitz.mod/bdwgc/NT_MAKEFILE

@@ -0,0 +1,191 @@
+# Makefile for Windows NT.  Assumes Microsoft compiler.
+# Should be invoked as "nmake -f NT_MAKEFILE [<args>]"; the optional arguments
+# are: "cpu=AMD64" - to target x64, "cpu=i386" - to target x86,
+# "enable_static=1" - to build it as a static library, "nodebug=1" - to produce
+# the release variant of the library, "disable_threads=1" - to build the
+# library and the tests without threads support.
+
+cc = cl
+link = link
+rc = rc
+
+!IF !DEFINED(CPU) || "$(CPU)" == ""
+CPU = $(PROCESSOR_ARCHITECTURE)
+!ENDIF
+!IF "$(CPU)" == "I386" || "$(CPU)" == "X86" || "$(CPU)" == "x86"
+CPU = i386
+!ELSEIF "$(CPU)" == "X64" || "$(CPU)" == "x64" || "$(CPU)" == "amd64"
+CPU = AMD64
+!ENDIF
+
+!IF !DEFINED(NMAKE_WINVER)
+NMAKE_WINVER = 0x0600
+!ENDIF
+
+cflags = $(cflags) -c -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -GS -D_WINNT -W4
+!IF "$(CPU)" == "i386"
+cflags = $(cflags) -D_X86_=1  -DWIN32 -D_WIN32
+!ELSEIF "$(CPU)" == "AMD64"
+cflags = $(cflags) -D_AMD64_=1 -DWIN64 -D_WIN64  -DWIN32 -D_WIN32
+!ENDIF
+cflags = $(cflags) -D_WIN32_WINNT=$(NMAKE_WINVER) -DWINVER=$(NMAKE_WINVER)
+
+!IFDEF NODEBUG
+cvarsmt = -D_MT -MT
+cdebug = -Ox -DNDEBUG
+rcvars = -DWIN32 -D_WIN32 -DWINVER=$(NMAKE_WINVER)
+ldebug = /RELEASE
+!ELSE
+cvarsmt = -D_MT -MTd
+cdebug = -Zi -Od -DDEBUG
+rcvars = -DWIN32 -D_WIN32 -DWINVER=$(NMAKE_WINVER) -DDEBUG -D_DEBUG
+ldebug = /DEBUG /DEBUGTYPE:cv
+!ENDIF
+
+!IF "$(CPU)" == "i386"
+CVTRES_CPU=X86
+!ELSEIF "$(CPU)" == "AMD64"
+CVTRES_CPU=X64
+!ENDIF
+
+!IFNDEF NODEBUG
+CFLAGS_DEBUG=-DGC_ASSERTIONS
+!ENDIF
+
+!IFDEF ENABLE_STATIC
+CFLAGS_GCDLL=-DGC_NOT_DLL
+CORDFLAG=
+!ELSE
+CFLAGS_GCDLL=-DGC_DLL
+# cord.dll and its clients should not link C library statically otherwise
+# FILE-related functions might not work (because own set of opened FILEs
+# is maintained by each copy of the C library thus making impossible to pass
+# FILE pointer from .exe code to .dll code).
+cvarsmt=
+!IFDEF NODEBUG
+CORDFLAG=-MD
+!ELSE
+CORDFLAG=-MDd
+!ENDIF
+!ENDIF
+
+!IFNDEF DISABLE_THREADS
+CFLAGS_MT=$(cvarsmt) -DGC_THREADS -DTHREAD_LOCAL_ALLOC -DPARALLEL_MARK
+!ENDIF
+
+# Extra user-defined flags to pass both to C and C++ compilers.
+CFLAGS_EXTRA=
+
+CFLAGS_SPECIFIC=$(CFLAGS_DEBUG) $(CFLAGS_GCDLL) $(CFLAGS_MT)
+
+CFLAGS_DEFAULT=-DALL_INTERIOR_POINTERS -DENABLE_DISCLAIM -DGC_ATOMIC_UNCOLLECTABLE -DGC_GCJ_SUPPORT -DJAVA_FINALIZATION -DNO_EXECUTE_PERMISSION -DUSE_MUNMAP
+
+CXXFLAGS_SPECIFIC=/EHsc
+
+# Make sure that .cc is not viewed as a suffix.  It is for VC++2005, but
+# not earlier versions.  We can deal with either, but not inconsistency.
+.SUFFIXES:
+.SUFFIXES: .obj .cpp .c
+
+# Atomic_ops installation directory.  For win32, the source directory
+# should do, since we only need the headers.
+# We assume this was manually unpacked.
+AO_SRC_DIR=libatomic_ops/src
+AO_INCLUDE_DIR=$(AO_SRC_DIR)
+
+!IFDEF ENABLE_STATIC
+OBJS= misc.obj win32_threads.obj alloc.obj reclaim.obj allchblk.obj mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj obj_map.obj blacklst.obj finalize.obj new_hblk.obj dbg_mlc.obj fnlz_mlc.obj malloc.obj dyn_load.obj typd_mlc.obj ptr_chck.obj gcj_mlc.obj mallocx.obj extra\msvc_dbg.obj thread_local_alloc.obj
+!ELSE
+OBJS= extra\gc.obj extra\msvc_dbg.obj
+!ENDIF
+
+COBJS= cord\cordbscs.obj cord\cordxtra.obj cord\cordprnt.obj
+
+all: gc.lib cord.lib gccpp.lib gctba.lib
+
+check-deps: gctest.exe test_cpp.exe cordtest.exe de.exe
+
+check: check-deps
+	gctest.exe
+	cordtest.exe
+	test_cpp.exe
+
+.c.obj:
+	$(cc) $(cdebug) $(cflags) $(CFLAGS_SPECIFIC) $(CORDFLAG) -Iinclude -I$(AO_INCLUDE_DIR) $(CFLAGS_DEFAULT) -D_CRT_SECURE_NO_DEPRECATE $(CFLAGS_EXTRA) $*.c /Fo$*.obj /wd4100 /wd4127 /wd4701
+# Disable crt security warnings, since unfortunately they warn about all sorts
+# of safe uses of strncpy.  It would be nice to leave the rest enabled.
+
+.cpp.obj:
+	$(cc) $(cdebug) $(cflags) $(CFLAGS_SPECIFIC) -Iinclude $(CFLAGS_DEFAULT) $(CXXFLAGS_SPECIFIC) -D_CRT_SECURE_NO_DEPRECATE $(CFLAGS_EXTRA) $*.cpp /Fo$*.obj
+
+$(OBJS) tests\test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h include\private\gc_locks.h include\private\gc_pmark.h include\gc\gc_mark.h include\gc\gc_disclaim.h
+
+!IFDEF ENABLE_STATIC
+
+gc.lib: $(OBJS)
+	lib /out:gc.lib /MACHINE:$(CPU) $(OBJS)
+
+cord.lib: $(COBJS)
+	lib /out:cord.lib /MACHINE:$(CPU) $(COBJS)
+
+gccpp.lib: gc_badalc.obj gc_cpp.obj
+	lib /out:gccpp.lib /MACHINE:$(CPU) gc_badalc.obj gc_cpp.obj
+
+# The same as gccpp.lib but contains only gc_badalc.obj.
+gctba.lib: gc_badalc.obj
+	lib /out:gctba.lib /MACHINE:$(CPU) gc_badalc.obj
+
+!ELSE
+
+gc.lib: $(OBJS)
+	$(link) $(ldebug) kernel32.lib user32.lib /subsystem:windows /dll /INCREMENTAL:NO /pdb:"gc.pdb" /out:gc.dll /implib:gc.lib /MACHINE:$(CPU) $(OBJS)
+
+cord.lib: $(COBJS) gc.lib
+	$(link) $(ldebug) gc.lib /subsystem:windows /dll /INCREMENTAL:NO /pdb:"cord.pdb" /out:cord.dll /implib:cord.lib /MACHINE:$(CPU) $(COBJS)
+
+gccpp.lib: gc_badalc.obj gc_cpp.obj gc.lib
+	$(link) $(ldebug) gc.lib /subsystem:windows /dll /INCREMENTAL:NO /pdb:"gccpp.pdb" /out:gccpp.dll /implib:gccpp.lib /MACHINE:$(CPU) gc_badalc.obj gc_cpp.obj
+
+gctba.lib: gc_badalc.obj gc.lib
+	$(link) $(ldebug) gc.lib /subsystem:windows /dll /INCREMENTAL:NO /pdb:"gctba.pdb" /out:gctba.dll /implib:gctba.lib /MACHINE:$(CPU) gc_badalc.obj
+
+!ENDIF
+
+gctest.exe: gc.lib tests\test.obj
+	$(link) /MACHINE:$(CPU) /INCREMENTAL:NO $(ldebug) $(lflags) user32.lib -out:$*.exe tests\test.obj gc.lib
+#	mapsympe -n -o gctest.sym gctest.exe
+# This produces a GUI app that opens no window and writes to gctest.gc.log.
+
+cord\tests\de_win.rbj: cord\tests\de_win.res
+	cvtres /MACHINE:$(CVTRES_CPU) /OUT:cord\tests\de_win.rbj cord\tests\de_win.res
+
+cord\tests\de.obj cord\tests\de_win.obj: include\gc\cord.h include\gc\cord_pos.h cord\tests\de_win.h cord\tests\de_cmds.h
+
+cord\tests\de_win.res: cord\tests\de_win.rc cord\tests\de_win.h cord\tests\de_cmds.h
+	$(rc) $(rcvars) -r -fo cord\tests\de_win.res cord\tests\de_win.rc
+
+# Cord/de is a real win32 GUI app.
+de.exe: cord\tests\de.obj cord\tests\de_win.obj cord\tests\de_win.rbj gc.lib cord.lib
+	$(link) /MACHINE:$(CPU) /INCREMENTAL:NO $(ldebug) $(lflags) -out:de.exe cord\tests\de.obj cord\tests\de_win.obj cord\tests\de_win.rbj gc.lib cord.lib gdi32.lib user32.lib
+
+cordtest.exe: cord\tests\cordtest.obj gc.lib cord.lib
+	$(link) /subsystem:console /MACHINE:$(CPU) /INCREMENTAL:NO $(ldebug) $(lflags) -out:cordtest.exe cord\tests\cordtest.obj gc.lib cord.lib user32.lib
+
+gc_badalc.obj: gc_badalc.cc include\gc_cpp.h include\gc.h
+
+gc_cpp.obj: gc_cpp.cc include\gc_cpp.h include\gc.h
+
+test_cpp.cpp: tests\test_cpp.cc
+	copy tests\test_cpp.cc test_cpp.cpp
+
+# This generates the C++ test executable.  The executable expects
+# a single numeric argument, which is the number of iterations.
+# The output appears in test_cpp.gc.log file.
+test_cpp.exe: test_cpp.obj include\gc_cpp.h include\gc.h gc.lib gccpp.lib
+	$(link) /MACHINE:$(CPU) /INCREMENTAL:NO $(ldebug) $(lflags) user32.lib -out:test_cpp.exe test_cpp.obj gc.lib gccpp.lib
+
+$(AO_SRC_DIR):
+	tar xvfz $(AO_SRC_DIR).tar.gz
+
+clean:
+	del *.dll *.exe *.exp *.lib *.log *.obj *.pdb cordtst*.tmp cord\*.obj cord\tests\*.rbj cord\tests\*.res cord\tests\*.obj extra\*.obj test_cpp.cpp tests\*.obj 2> nul

+ 64 - 0
blitz.mod/bdwgc/OS2_MAKEFILE

@@ -0,0 +1,64 @@
+# Makefile for OS/2.  Assumes IBM's compiler, static linking, and a single thread.
+# Adding dynamic linking support seems easy, but takes a little bit of work.
+# Adding thread support may be nontrivial, since we haven't yet figured out how to
+# look at another thread's registers.
+
+# Significantly revised by Mark Boulter (Jan 1994).
+
+OBJS= alloc.obj reclaim.obj allchblk.obj misc.obj mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj obj_map.obj blacklst.obj finalize.obj new_hblk.obj dbg_mlc.obj fnlz_mlc.obj malloc.obj typd_mlc.obj ptr_chck.obj mallocx.obj gcj_mlc.obj
+
+CORDOBJS= cord\cordbscs.obj cord\cordxtra.obj cord\cordprnt.obj
+
+# Extra user-defined flags to pass to the compiler.
+CFLAGS_EXTRA=
+
+CC= icc
+CFLAGS= /O /Q /DALL_INTERIOR_POINTERS /DENABLE_DISCLAIM /DGC_ATOMIC_UNCOLLECTABLE /DGC_GCJ_SUPPORT /DJAVA_FINALIZATION /DNO_EXECUTE_PERMISSION /DSMALL_CONFIG $(CFLAGS_EXTRA)
+# Use /Ti instead of /O for debugging
+# setjmp_test may yield overly optimistic results when compiled
+# without optimization.
+
+all: gc.lib cord.lib
+
+check-deps: gctest.exe cordtest.exe
+
+check: check-deps
+        gctest.exe
+        cordtest.exe
+
+$(OBJS) test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h
+
+## ERASE THE LIB FIRST - if it is already there then this command will fail
+## (make sure it is there or erase will fail!)
+gc.lib: $(OBJS)
+        echo . > gc.lib
+        erase gc.lib
+        LIB gc.lib $(OBJS), gc.lst
+
+mach_dep.obj: mach_dep.c
+        $(CC) $(CFLAGS) /C mach_dep.c
+
+gctest.exe: test.obj gc.lib
+        $(CC) $(CFLAGS) /B"/STACK:524288" /Fegctest test.obj gc.lib
+
+cord\cordbscs.obj: cord\cordbscs.c include\gc\cord.h include\gc\cord_pos.h
+        $(CC) $(CFLAGS) /C /Focord\cordbscs cord\cordbscs.c
+
+cord\cordxtra.obj: cord\cordxtra.c include\gc\cord.h include\gc\cord_pos.h include\gc\ec.h
+        $(CC) $(CFLAGS) /C /Focord\cordxtra cord\cordxtra.c
+
+cord\cordprnt.obj: cord\cordprnt.c include\gc\cord.h include\gc\cord_pos.h include\gc\ec.h
+        $(CC) $(CFLAGS) /C /Focord\cordprnt cord\cordprnt.c
+
+cord.lib: $(CORDOBJS)
+        echo . > cord.lib
+        erase cord.lib
+        LIB cord.lib $(CORDOBJS), cord.lst
+
+cordtest.exe: cord\tests\cordtest.c include\gc\cord.h include\gc\cord_pos.h include\gc\ec.h gc.lib cord.lib
+        $(CC) $(CFLAGS) /B"/STACK:65536" /Fecordtest cord\tests\cordtest.c gc.lib cord.lib
+
+clean:
+        erase gc.lib cord.lib
+        erase gctest.exe cordtest.exe
+        erase $(OBJS) $(CORDOBJS)

+ 47 - 0
blitz.mod/bdwgc/PCR-Makefile

@@ -0,0 +1,47 @@
+#
+# Default target
+#
+
+default: gc.o
+
+include ../config/common.mk
+
+#
+# compilation flags, etc.
+#
+
+CPPFLAGS = $(INCLUDE) $(CONFIG_CPPFLAGS) \
+	-DPCR_NO_RENAME -DPCR_NO_HOSTDEP_ERR
+#CFLAGS	= -DPCR $(CONFIG_CFLAGS)
+CFLAGS	= -DPCR -DENABLE_DISCLAIM $(CONFIG_CFLAGS)
+SPECIALCFLAGS = 	# For code involving asm's
+
+ASPPFLAGS  = $(INCLUDE) $(CONFIG_ASPPFLAGS) \
+	-DPCR_NO_RENAME -DPCR_NO_HOSTDEP_ERR -DASM
+
+ASFLAGS	= $(CONFIG_ASFLAGS)
+
+LDRFLAGS = $(CONFIG_LDRFLAGS)
+
+LDFLAGS = $(CONFIG_LDFLAGS)
+
+#
+# BEGIN PACKAGE-SPECIFIC PART
+#
+
+# Fix to point to local pcr installation directory.
+PCRDIR= ..
+
+COBJ= alloc.o reclaim.o allchblk.o misc.o os_dep.o mark_rts.o headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o extra/pcr_interface.o extra/real_malloc.o dyn_load.o dbg_mlc.o fnlz_mlc.o malloc.o checksums.o typd_mlc.o ptr_chck.o mallocx.o
+
+CSRC= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c blacklst.c finalize.c new_hblk.c extra/pcr_interface.c extra/real_malloc.c dyn_load.c dbg_mlc.c fnlz_mlc.c malloc.c checksums.c typd_mlc.c ptr_chck.c mallocx.c
+
+SHELL= /bin/sh
+
+default: gc.o
+
+gc.o: $(COBJ) mach_dep.o
+	$(LDR) $(CONFIG_LDRFLAGS) -o gc.o $(COBJ) mach_dep.o
+
+mach_dep.o: mach_dep.c
+	$(CC) -c $(SPECIALCFLAGS) mach_dep.c

+ 586 - 0
blitz.mod/bdwgc/README.md

@@ -0,0 +1,586 @@
+# Boehm-Demers-Weiser Garbage Collector
+
+[![Travis-CI build status](https://travis-ci.com/ivmai/bdwgc.svg?branch=master)](https://travis-ci.com/ivmai/bdwgc)
+[![AppVeyor CI build status](https://ci.appveyor.com/api/projects/status/github/ivmai/bdwgc?branch=master&svg=true)](https://ci.appveyor.com/project/ivmai/bdwgc)
+[![Codecov.io](https://codecov.io/github/ivmai/bdwgc/coverage.svg?branch=master)](https://codecov.io/github/ivmai/bdwgc?branch=master)
+[![Coveralls test coverage status](https://coveralls.io/repos/github/ivmai/bdwgc/badge.png?branch=master)](https://coveralls.io/github/ivmai/bdwgc)
+[![Coverity Scan build status](https://scan.coverity.com/projects/10813/badge.svg)](https://scan.coverity.com/projects/ivmai-bdwgc)
+[![LGTM Code Quality: Cpp](https://img.shields.io/lgtm/grade/cpp/g/ivmai/bdwgc.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/ivmai/bdwgc/context:cpp)
+[![LGTM Total Alerts](https://img.shields.io/lgtm/alerts/g/ivmai/bdwgc.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/ivmai/bdwgc/alerts)
+
+[![Hits-of-Code](https://hitsofcode.com/github/ivmai/bdwgc?branch=master)](https://hitsofcode.com/github/ivmai/bdwgc/view)
+[![Lines of code](https://img.shields.io/tokei/lines/github/ivmai/bdwgc)](https://shields.io/category/size)
+[![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/ivmai/bdwgc)](https://shields.io/category/size)
+[![Github All Releases](https://img.shields.io/github/downloads/ivmai/bdwgc/total.svg)](https://shields.io/category/downloads)
+[![Packaging status](https://repology.org/badge/tiny-repos/boehm-gc.svg)](https://repology.org/project/boehm-gc/versions)
+
+This is version 8.3.0 (next release development) of a conservative garbage
+collector for C and C++.
+
+License: [MIT-style](LICENSE)
+
+
+## Download
+
+You might find a more recent/stable version on the
+[Download](https://github.com/ivmai/bdwgc/wiki/Download) page, or
+[BDWGC site](http://www.hboehm.info/gc/).
+
+Also, the latest bug fixes and new features are available in the
+[development repository](https://github.com/ivmai/bdwgc).
+
+
+## Overview
+
+This is intended to be a general purpose, garbage collecting storage
+allocator.  The algorithms used are described in:
+
+ * Boehm, H., and M. Weiser, "Garbage Collection in an Uncooperative
+   Environment", Software Practice & Experience, September 1988, pp. 807-820.
+
+ * Boehm, H., A. Demers, and S. Shenker, "Mostly Parallel Garbage Collection",
+   Proceedings of the ACM SIGPLAN '91 Conference on Programming Language Design
+   and Implementation, SIGPLAN Notices 26, 6 (June 1991), pp. 157-164.
+
+ * Boehm, H., "Space Efficient Conservative Garbage Collection", Proceedings
+   of the ACM SIGPLAN '91 Conference on Programming Language Design and
+   Implementation, SIGPLAN Notices 28, 6 (June 1993), pp. 197-206.
+
+ * Boehm H., "Reducing Garbage Collector Cache Misses", Proceedings of the
+   2000 International Symposium on Memory Management.
+
+Possible interactions between the collector and optimizing compilers are
+discussed in
+
+ * Boehm, H., and D. Chase, "A Proposal for GC-safe C Compilation",
+   The Journal of C Language Translation 4, 2 (December 1992).
+
+ * Boehm H., "Simple GC-safe Compilation", Proceedings of the ACM SIGPLAN '96
+   Conference on Programming Language Design and Implementation.
+
+Unlike the collector described in the second reference, this collector
+operates either with the mutator stopped during the entire collection
+(default) or incrementally during allocations.  (The latter is supported
+on fewer machines.)  On the most common platforms, it can be built
+with or without thread support.  On some platforms, it can take advantage
+of a multiprocessor to speed up garbage collection.
+
+Many of the ideas underlying the collector have previously been explored
+by others.  Notably, some of the run-time systems developed at Xerox PARC
+in the early 1980s conservatively scanned thread stacks to locate possible
+pointers (cf. Paul Rovner, "On Adding Garbage Collection and Runtime Types
+to a Strongly-Typed Statically Checked, Concurrent Language" Xerox PARC
+CSL 84-7).  Doug McIlroy wrote a simpler fully conservative collector that
+was part of version 8 UNIX (tm), but appears to not have received
+widespread use.
+
+Rudimentary tools for use of the collector as a [leak detector](doc/leak.md)
+are included, as is a fairly sophisticated string package "cord" that
+makes use of the collector.  (See [README.cords](doc/README.cords) and
+H.-J. Boehm, R. Atkinson, and M. Plass, "Ropes: An Alternative to Strings",
+Software Practice and Experience 25, 12 (December 1995), pp. 1315-1330.
+This is very similar to the "rope" package in Xerox Cedar, or the "rope"
+package in the SGI STL or the g++ distribution.)
+
+Further collector documentation can be found in the
+[overview](doc/overview.md).
+
+Some of the known uses of the collector are listed on the GitHub
+[Known-clients](https://github.com/ivmai/bdwgc/wiki/Known-clients) page.
+
+
+## General Description
+
+This is a garbage collecting storage allocator that is intended to be
+used as a plug-in replacement for C's malloc.
+
+Since the collector does not require pointers to be tagged, it does not
+attempt to ensure that all inaccessible storage is reclaimed.  However,
+in our experience, it is typically more successful at reclaiming unused
+memory than most C programs using explicit deallocation.  Unlike manually
+introduced leaks, the amount of unreclaimed memory typically stays
+bounded.
+
+In the following, an "object" is defined to be a region of memory allocated
+by the routines described below.
+
+Any objects not intended to be collected must be pointed to either
+from other such accessible objects, or from the registers,
+stack, data, or statically allocated bss segments.  Pointers from
+the stack or registers may point to anywhere inside an object.
+The same is true for heap pointers if the collector is compiled with
+`ALL_INTERIOR_POINTERS` defined, or `GC_all_interior_pointers` is otherwise
+set, as is now the default.
+
+Compiling without `ALL_INTERIOR_POINTERS` may reduce accidental retention
+of garbage objects, by requiring pointers from the heap to the beginning
+of an object.  But this no longer appears to be a significant
+issue for most programs occupying a small fraction of the possible
+address space.
+
+There are a number of routines which modify the pointer recognition
+algorithm.  `GC_register_displacement` allows certain interior pointers
+to be recognized even if `ALL_INTERIOR_POINTERS` is not defined.
+`GC_malloc_ignore_off_page` allows some pointers into the middle of
+large objects to be disregarded, greatly reducing the probability of
+accidental retention of large objects.  For most purposes it seems
+best to compile with `ALL_INTERIOR_POINTERS` and to use
+`GC_malloc_ignore_off_page` if you get collector warnings from
+allocations of very large objects.  See [here](doc/debugging.md) for details.
+
+_WARNING_: pointers inside memory allocated by the standard (system) `malloc`
+are not seen by the garbage collector.  Thus objects pointed to only from such
+a region may be prematurely deallocated.  It is thus suggested that the
+standard `malloc` be used only for memory regions, such as I/O buffers, that
+are guaranteed not to contain pointers to garbage collectible memory.
+Pointers in C language automatic, static, or register variables,
+are correctly recognized.  (Note that `GC_malloc_uncollectable` has
+semantics similar to standard malloc, but allocates objects that are
+traced by the collector.)
+
+_WARNING_: the collector does not always know how to find pointers in data
+areas that are associated with dynamic libraries.  This is easy to remedy
+if you know how to find those data areas on your operating system (see
+`GC_add_roots`).  Code for doing this under SunOS, IRIX 5.X and 6.X, HP/UX,
+Alpha OSF/1, Linux, and Win32 is included and used by default.
+(See [README.win32](doc/README.win32) and [README.win64](doc/README.win64)
+for Windows details.)  On other systems, pointers from dynamic library data
+areas may not be considered by the collector.  If you're writing a program
+that depends on the collector scanning dynamic library data areas, it may
+be a good idea to include at least one call to `GC_is_visible` to ensure
+that those areas are visible to the collector.
+
+Note that the garbage collector does not need to be informed of shared
+read-only data.  However, if the shared library mechanism can introduce
+discontiguous data areas that may contain pointers then the collector does
+need to be informed.
+
+Signal processing for most signals may be deferred during collection,
+and during uninterruptible parts of the allocation process.
+Like standard ANSI C mallocs, by default it is unsafe to invoke
+malloc (and other GC routines) from a signal handler while another
+malloc call may be in progress.
+
+The allocator/collector can also be configured for thread-safe operation.
+(Full signal safety can also be achieved, but only at the cost of two system
+calls per malloc, which is usually unacceptable.)
+
+_WARNING_: the collector does not guarantee to scan thread-local storage
+(e.g. of the kind accessed with `pthread_getspecific`).  The collector
+does scan thread stacks, though, so generally the best solution is to
+ensure that any pointers stored in thread-local storage are also
+stored on the thread's stack for the duration of their lifetime.
+(This is arguably a longstanding bug, but it hasn't been fixed yet.)
+
+
+## Installation and Portability
+
+The collector operates silently in the default configuration.
+In the event of issues, this can usually be changed by defining the
+`GC_PRINT_STATS` or `GC_PRINT_VERBOSE_STATS` environment variables.  This
+will result in a few lines of descriptive output for each collection.
+(The given statistics exhibit a few peculiarities.
+Things don't appear to add up for a variety of reasons, most notably
+fragmentation losses.  These are probably much more significant for the
+contrived program `tests/test.c` than for your application.)
+
+On most Unix-like platforms, the collector can be built either using a
+GNU autoconf-based build infrastructure (type `./configure; make` in the
+simplest case), or using CMake (see the sample below), or with a classic
+makefile by itself (type `make -f Makefile.direct`).
+
+Please note that the collector source repository does not contain configure
+and similar auto-generated files, thus the full procedure of autoconf-based
+build of `master` branch of the collector could look like:
+
+    git clone git://github.com/ivmai/bdwgc.git
+    cd bdwgc
+    git clone git://github.com/ivmai/libatomic_ops.git
+    ./autogen.sh
+    ./configure
+    make -j
+    make check
+
+Cloning of `libatomic_ops` is now optional provided the compiler supports
+atomic intrinsics.  See [README.autoconf](doc/README.autoconf) for details.
+
+As noted above, alternatively, the collector could be built with CMake, like
+this:
+
+    mkdir out
+    cd out
+    cmake ..
+    cmake --build .
+    ctest
+
+See [README.cmake](doc/README.cmake) for details.
+
+Finally, on most targets, the collector could be built and tested directly
+with a single compiler invocation, like this:
+
+    gcc -I include -o gctest tests/test.c extra/gc.c && ./gctest
+
+On Windows, CMake could be used to build the library as described above or
+by typing `nmake -f NT_MAKEFILE`, this assumes you have Microsoft command-line
+tools installed and suitably configured.  See [README.win32](doc/README.win32)
+for details.
+
+The library is built with threads support on (i.e. for thread-safe operation)
+by default, unless `--disable-threads` is passed to `./configure` (or
+`-Denable_threads=OFF` is passed to `cmake` tool).
+
+The library could be configured more precisely during the build by defining
+the macros listed in [README.macros](doc/README.macros) file.
+
+Below we focus on the collector build using classic makefile.  For the
+Makefile.direct-based process, typing `make check` instead of `make` will
+automatically build the collector and then run `setjmp_test` and `gctest`.
+`setjmp_test` will give you information about configuring the collector, which
+is useful primarily if you have a machine that's not already supported.
+gctest is a somewhat superficial test of collector functionality.  Failure is
+indicated by a core dump or a message to the effect that the collector is
+broken.  gctest takes about a second to two to run on reasonable 2007 vintage
+desktops.  It may use up to about 30 MB of memory.  (The multi-threaded
+version will use more.  64-bit versions may use more.) `make check` will also,
+as its last step, attempt to build and test the "cord" string library.)
+
+Makefile.direct will generate a library libgc.a which you should link against.
+Typing `make -f Makefile.direct cords` will build the cord library (libcord.a)
+as well.
+
+The GNU style build process understands the usual targets.  `make check`
+runs a number of tests.  `make install` installs at least libgc, and libcord.
+Try `./configure --help` to see the configuration options.  It is currently
+not possible to exercise all combinations of build options this way.
+
+All include files that need to be used by clients will be put in the
+include subdirectory.  (Normally this is just gc.h.  `make cords` adds
+"cord.h" and "ec.h".)
+
+The collector currently is designed to run essentially unmodified on
+machines that use a flat 32-bit or 64-bit address space.
+That includes the vast majority of Workstations and X86 (X >= 3) PCs.
+
+In a few cases (Amiga, OS/2, PCR, Symbian, Win32) a separate makefile
+or equivalent is supplied.  Many of these have separate a host-specific
+doc/README.* file.
+
+Dynamic libraries are completely supported only under SunOS/Solaris,
+(and even that support is not functional on the last Sun 3 release),
+Linux, FreeBSD, NetBSD, IRIX, HP/UX, Win32 (not Win32s) and OSF/1
+on DEC AXP machines plus perhaps a few others listed near the top
+of dyn_load.c.  On other machines we recommend that you do one of
+the following:
+
+  1. Add dynamic library support (and send us the code).
+  2. Use static versions of the libraries.
+  3. Arrange for dynamic libraries to use the standard malloc. This is still
+  dangerous if the library stores a pointer to a garbage collected object.
+  But nearly all standard interfaces prohibit this, because they deal
+  correctly with pointers to stack allocated objects.  (`strtok` is an
+  exception.  Don't use it.)
+
+In all cases we assume that pointer alignment is consistent with that
+enforced by the standard C compilers.  If you use a nonstandard compiler
+you may have to adjust the alignment parameters defined in gc_priv.h.
+Note that this may also be an issue with packed records/structs, if those
+enforce less alignment for pointers.
+
+A port to a machine that is not byte addressed, or does not use 32 bit
+or 64 bit addresses will require a major effort.  A port to plain MSDOS
+or win16 is hard.
+
+For machines not already mentioned, or for nonstandard compilers,
+some porting suggestions are provided [here](doc/porting.md).
+
+
+## The C Interface to the Allocator
+
+The following routines are intended to be directly called by the user.
+Note that usually only `GC_malloc` is necessary.  `GC_clear_roots` and
+`GC_add_roots` calls may be required if the collector has to trace
+from nonstandard places (e.g. from dynamic library data areas on a
+machine on which the collector doesn't already understand them.)  On
+some machines, it may be desirable to set `GC_stackbottom` to a good
+approximation of the stack base (bottom).
+
+Client code may include "gc.h", which defines all of the following, plus many
+others.
+
+  1. `GC_malloc(bytes)` - Allocate an object of a given size.  Unlike malloc,
+  the object is cleared before being returned to the user.  `GC_malloc` will
+  invoke the garbage collector when it determines this to be appropriate.
+  GC_malloc may return 0 if it is unable to acquire sufficient space from the
+  operating system.  This is the most probable consequence of running out
+  of space.  Other possible consequences are that a function call will fail
+  due to lack of stack space, or that the collector will fail in other ways
+  because it cannot maintain its internal data structures, or that a crucial
+  system process will fail and take down the machine.  Most of these
+  possibilities are independent of the malloc implementation.
+
+  2. `GC_malloc_atomic(bytes)` - Allocate an object of a given size that
+  is guaranteed not to contain any pointers.  The returned object is not
+  guaranteed to be cleared. (Can always be replaced by `GC_malloc`, but
+  results in faster collection times.  The collector will probably run faster
+  if large character arrays, etc. are allocated with `GC_malloc_atomic` than
+  if they are statically allocated.)
+
+  3. `GC_realloc(object, new_bytes)` - Change the size of object to be of
+  a given size.  Returns a pointer to the new object, which may, or may not,
+  be the same as the pointer to the old object.  The new object is taken to
+  be atomic if and only if the old one was.  If the new object is composite
+  and larger than the original object then the newly added bytes are cleared.
+  This is very likely to allocate a new object.
+
+  4. `GC_free(object)` - Explicitly deallocate an object returned by
+  `GC_malloc` or `GC_malloc_atomic`, or friends.  Not necessary, but can be
+  used to minimize collections if performance is critical.  Probably
+  a performance loss for very small objects (<= 8 bytes).
+
+  5. `GC_expand_hp(bytes)` - Explicitly increase the heap size.  (This is
+  normally done automatically if a garbage collection failed to reclaim
+  enough memory.  Explicit calls to `GC_expand_hp` may prevent unnecessarily
+  frequent collections at program startup.)
+
+  6. `GC_malloc_ignore_off_page(bytes)` - Identical to `GC_malloc`, but the
+  client promises to keep a pointer to the somewhere within the first 256
+  bytes of the object while it is live.  (This pointer should normally be
+  declared volatile to prevent interference from compiler optimizations.)
+  This is the recommended way to allocate anything that is likely to be
+  larger than 100 KB or so.  (`GC_malloc` may result in a failure to reclaim
+  such objects.)
+
+  7. `GC_set_warn_proc(proc)` - Can be used to redirect warnings from the
+  collector.  Such warnings should be rare, and should not be ignored during
+  code development.
+
+  8. `GC_enable_incremental()` - Enables generational and incremental
+  collection.  Useful for large heaps on machines that provide access to page
+  dirty information.  Some dirty bit implementations may interfere with
+  debugging (by catching address faults) and place restrictions on heap
+  arguments to system calls (since write faults inside a system call may not
+  be handled well).
+
+  9. `GC_register_finalizer(object, proc, data, 0, 0)` and friends - Allow for
+  registration of finalization code.  User supplied finalization code
+  (`(*proc)(object, data)`) is invoked after object becomes unreachable.
+  For more sophisticated uses, and for finalization ordering issues, see gc.h.
+
+The global variable `GC_free_space_divisor` may be adjusted up from it
+default value of 3 to use less space and more collection time, or down for
+the opposite effect.  Setting it to 1 will almost disable collections
+and cause all allocations to simply grow the heap.
+
+The variable `GC_non_gc_bytes`, which is normally 0, may be changed to reflect
+the amount of memory allocated by the above routines that should not be
+considered as a candidate for collection.  Careless use may, of course, result
+in excessive memory consumption.
+
+Some additional tuning is possible through the parameters defined
+near the top of gc_priv.h.
+
+If only `GC_malloc` is intended to be used, it might be appropriate to define:
+
+    #define malloc(n) GC_malloc(n)
+    #define calloc(m,n) GC_malloc((m)*(n))
+
+For small pieces of VERY allocation intensive code, `gc_inline.h` includes
+some allocation macros that may be used in place of `GC_malloc` and
+friends.
+
+All externally visible names in the garbage collector start with `GC_`.
+To avoid name conflicts, client code should avoid this prefix, except when
+accessing garbage collector routines.
+
+There are provisions for allocation with explicit type information.
+This is rarely necessary.  Details can be found in `gc_typed.h`.
+
+
+## The C++ Interface to the Allocator
+
+The Ellis-Hull C++ interface to the collector is included in the collector
+distribution.  If you intend to use this, type
+`./configure --enable-cplusplus && make` (or
+`cmake -Denable_cplusplus=ON . && cmake --build .`, or
+`make -f Makefile.direct c++` depending on the build system you use).
+This creates libgccpp.a and libgctba.a files, or their shared library
+equivalents (libgccpp.so and libgctba.so).  You should link with either the
+first (gccpp) or the second one (gctba), but not both.  See gc_cpp.h and
+[gcinterface.md](doc/gcinterface.md) for the definition of the interface.
+This interface tries to approximate the Ellis-Detlefs C++ garbage collection
+proposal without compiler changes.
+
+Very often it will also be necessary to use `gc_allocator.h` and the
+allocator declared there to construct STL data structures.  Otherwise
+subobjects of STL data structures will be allocated using a system
+allocator, and objects they refer to may be prematurely collected.
+
+
+## Use as Leak Detector
+
+The collector may be used to track down leaks in C programs that are
+intended to run with malloc/free (e.g. code with extreme real-time or
+portability constraints).  To do so define `FIND_LEAK` in Makefile.
+This will cause the collector to print a human-readable object description
+whenever an inaccessible object is found that has not been explicitly freed.
+Such objects will also be automatically reclaimed.
+
+If all objects are allocated with `GC_DEBUG_MALLOC` (see the next section)
+then, by default, the human-readable object description will at least contain
+the source file and the line number at which the leaked object was allocated.
+This may sometimes be sufficient.  (On a few machines, it will also report
+a cryptic stack trace.  If this is not symbolic, it can sometimes be called
+into a symbolic stack trace by invoking program "foo" with
+`tools/callprocs.sh foo`.  It is a short shell script that invokes adb to
+expand program counter values to symbolic addresses.  It was largely supplied
+by Scott Schwartz.)
+
+Note that the debugging facilities described in the next section can
+sometimes be slightly LESS effective in leak finding mode, since in the latter
+`GC_debug_free` actually results in reuse of the object.  (Otherwise the
+object is simply marked invalid.)  Also, note that most GC tests are not
+designed to run meaningfully in `FIND_LEAK` mode.
+
+
+## Debugging Facilities
+
+The routines `GC_debug_malloc`, `GC_debug_malloc_atomic`, `GC_debug_realloc`,
+and `GC_debug_free` provide an alternate interface to the collector, which
+provides some help with memory overwrite errors, and the like.
+Objects allocated in this way are annotated with additional
+information.  Some of this information is checked during garbage
+collections, and detected inconsistencies are reported to stderr.
+
+Simple cases of writing past the end of an allocated object should
+be caught if the object is explicitly deallocated, or if the
+collector is invoked while the object is live.  The first deallocation
+of an object will clear the debugging info associated with an
+object, so accidentally repeated calls to `GC_debug_free` will report the
+deallocation of an object without debugging information.  Out of
+memory errors will be reported to stderr, in addition to returning `NULL`.
+
+`GC_debug_malloc` checking during garbage collection is enabled
+with the first call to this function.  This will result in some
+slowdown during collections.  If frequent heap checks are desired,
+this can be achieved by explicitly invoking `GC_gcollect`, e.g. from
+the debugger.
+
+`GC_debug_malloc` allocated objects should not be passed to `GC_realloc`
+or `GC_free`, and conversely.  It is however acceptable to allocate only
+some objects with `GC_debug_malloc`, and to use `GC_malloc` for other objects,
+provided the two pools are kept distinct.  In this case, there is a very
+low probability that `GC_malloc` allocated objects may be misidentified as
+having been overwritten.  This should happen with probability at most
+one in 2**32.  This probability is zero if `GC_debug_malloc` is never called.
+
+`GC_debug_malloc`, `GC_debug_malloc_atomic`, and `GC_debug_realloc` take two
+additional trailing arguments, a string and an integer.  These are not
+interpreted by the allocator.  They are stored in the object (the string is
+not copied).  If an error involving the object is detected, they are printed.
+
+The macros `GC_MALLOC`, `GC_MALLOC_ATOMIC`, `GC_REALLOC`, `GC_FREE`,
+`GC_REGISTER_FINALIZER` and friends are also provided.  These require the same
+arguments as the corresponding (nondebugging) routines.  If gc.h is included
+with `GC_DEBUG` defined, they call the debugging versions of these
+functions, passing the current file name and line number as the two
+extra arguments, where appropriate.  If gc.h is included without `GC_DEBUG`
+defined then all these macros will instead be defined to their nondebugging
+equivalents.  (`GC_REGISTER_FINALIZER` is necessary, since pointers to
+objects with debugging information are really pointers to a displacement
+of 16 bytes from the object beginning, and some translation is necessary
+when finalization routines are invoked.  For details, about what's stored
+in the header, see the definition of the type oh in dbg_mlc.c file.)
+
+
+## Incremental/Generational Collection
+
+The collector normally interrupts client code for the duration of
+a garbage collection mark phase.  This may be unacceptable if interactive
+response is needed for programs with large heaps.  The collector
+can also run in a "generational" mode, in which it usually attempts to
+collect only objects allocated since the last garbage collection.
+Furthermore, in this mode, garbage collections run mostly incrementally,
+with a small amount of work performed in response to each of a large number of
+`GC_malloc` requests.
+
+This mode is enabled by a call to `GC_enable_incremental`.
+
+Incremental and generational collection is effective in reducing
+pause times only if the collector has some way to tell which objects
+or pages have been recently modified.  The collector uses two sources
+of information:
+
+  1. Information provided by the VM system.  This may be provided in one of
+  several forms.  Under Solaris 2.X (and potentially under other similar
+  systems) information on dirty pages can be read from the /proc file system.
+  Under other systems (e.g. SunOS4.X) it is possible to write-protect
+  the heap, and catch the resulting faults. On these systems we require that
+  system calls writing to the heap (other than read) be handled specially by
+  client code. See `os_dep.c` for details.
+
+  2. Information supplied by the programmer.  The object is considered dirty
+  after a call to `GC_end_stubborn_change` provided the library has been
+  compiled suitably. It is typically not worth using for short-lived objects.
+  Note that bugs caused by a missing `GC_end_stubborn_change` or
+  `GC_reachable_here` call are likely to be observed very infrequently and
+  hard to trace.
+
+
+## Bugs
+
+Any memory that does not have a recognizable pointer to it will be
+reclaimed.  Exclusive-or'ing forward and backward links in a list
+doesn't cut it.
+
+Some C optimizers may lose the last undisguised pointer to a memory
+object as a consequence of clever optimizations.  This has almost
+never been observed in practice.
+
+This is not a real-time collector.  In the standard configuration,
+percentage of time required for collection should be constant across
+heap sizes.  But collection pauses will increase for larger heaps.
+They will decrease with the number of processors if parallel marking
+is enabled.
+
+(On 2007 vintage machines, GC times may be on the order of 5 ms
+per MB of accessible memory that needs to be scanned and processed.
+Your mileage may vary.)  The incremental/generational collection facility
+may help in some cases.
+
+
+## Feedback, Contribution, Questions and Notifications
+
+Please address bug reports and new feature ideas to
+[GitHub issues](https://github.com/ivmai/bdwgc/issues).  Before the
+submission please check that it has not been done yet by someone else.
+
+If you want to contribute, submit
+a [pull request](https://github.com/ivmai/bdwgc/pulls) to GitHub.
+
+If you need help, use
+[Stack Overflow](https://stackoverflow.com/questions/tagged/boehm-gc).
+Older technical discussions are available in `bdwgc` mailing list archive - it
+can be downloaded as a
+[compressed file](https://github.com/ivmai/bdwgc/files/1038163/bdwgc-mailing-list-archive-2017_04.tar.gz)
+or browsed at [Narkive](http://bdwgc.opendylan.narkive.com).
+
+To get new release announcements, subscribe to
+[RSS feed](https://github.com/ivmai/bdwgc/releases.atom).
+(To receive the notifications by email, a 3rd-party free service like
+[IFTTT RSS Feed](https://ifttt.com/feed) can be setup.)
+To be notified on all issues, please
+[watch](https://github.com/ivmai/bdwgc/watchers) the project on
+GitHub.
+
+
+## Copyright & Warranty, Contributors
+
+Our intent is to make it easy to use bdwgc (libgc), in both free and
+proprietary software.  Hence, the Boehm-Demers-Weiser conservative garbage
+collector code that we expect to be linked dynamically or statically into
+a client application is covered by own license, which is similar in
+spirit to an MIT-style one.
+
+The exact licensing information is provided in [LICENSE](LICENSE) file.
+
+All the contributors are listed in [AUTHORS](AUTHORS) file.

+ 174 - 0
blitz.mod/bdwgc/SMakefile.amiga

@@ -0,0 +1,174 @@
+
+# Rewritten smakefile for amiga / sas/c. -Kjetil M.
+# Don't use the cord-package if you define parm=both or parm=reg.
+
+
+#----------------TOOLS--------------------------------
+CC=sc
+LINKER=slink
+LIBER=oml
+
+#----------------CPU OPTIONS--------------------------
+
+CPU=68060
+
+#----------------FPU OPTIONS--------------------------
+
+MATH=8
+MATHLIB=LIB:scm881.lib
+
+#----------------COMPILER OPTIONS---------------------
+
+IGNORE= IGNORE=85 IGNORE=154 IGNORE=161 IGNORE=100
+
+OPTIMIZE=optimize optimizetime optglobal optimizerdepth=100 optimizerpeephole optloop OPTSCHED optimizerinlocal optimizerrecurdepth=100
+# optimizerinline optimizercomplexity=100
+
+OPT= $(OPTIMIZE) CPU=$(CPU) math=$(MATH) NOSTACKCHECK VERBOSE \
+MAPHUNK NOVERSION NOICONS nodebug \
+parm=reg \
+DEFINE __USE_SYSBASE
+
+
+SOPT= $(OPT) $(IGNORE) \
+DEFINE AMIGA_SKIP_SEG \
+DEFINE GC_ATOMIC_UNCOLLECTABLE \
+DEFINE GC_AMIGA_FASTALLOC \
+DEFINE GC_AMIGA_RETRY \
+DEFINE GC_AMIGA_PRINTSTATS \
+DEFINE GC_AMIGA_GC
+
+
+#DEFINE ALL_INTERIOR_POINTERS \
+
+
+SCOPT= $(SOPT) define GC_AMIGA_MAKINGLIB
+
+CSCOPT= $(OPT) DEFINE AMIGA IGNORE=100 IGNORE=161
+
+#------------------LINKING----------------------------
+
+
+all: gc.lib cord.lib
+
+clean:
+	delete *.lib gctest setjmp_t *.o *.lnk cord/*.o cord/tests/*.o cordtest
+	smake
+
+check-deps: setjmp_t gctest cordtest
+
+check: check-deps
+	setjmp_t
+	gctest
+	cordtest
+
+gctest: gc.lib GCAmigaOS$(CPU).lib test.o
+	$(LINKER) LIB:c.o test.o TO gctest LIB gc.lib LIB:sc.lib $(MATHLIB)
+
+setjmp_t: setjmp_t.o gc.h
+	$(LINKER) LIB:c.o setjmp_t.o to setjmp_t lib LIB:sc.lib
+
+cordtest: cord/tests/cordtest.o cord.lib gc.lib
+	$(LINKER) LIB:c.o cord/tests/cordtest.o LIB $(MATHLIB) gc.lib cord.lib LIB:sc.lib TO cordtest
+
+
+#------------------LIBBING----------------------------
+
+OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o dyn_load.o dbg_mlc.o malloc.o checksums.o typd_mlc.o ptr_chck.o mallocx.o fnlz_mlc.o
+
+gc.lib: $(OBJS)
+	$(LIBER) gc.lib r $(OBJS)
+
+
+COBJS = cord/cordbscs.o cord/cordprnt.o cord/cordxtra.o
+
+cord.lib: $(COBJS)
+	$(LIBER) cord.lib r $(COBJS)
+
+#------------------COMPILING--------------------------
+
+INC=  gc_private.h gc_hdrs.h gc.h gcconfig.h
+
+alloc.o : alloc.c $(INC)
+	$(CC) alloc.c $(SCOPT) ignore=7
+
+reclaim.o : reclaim.c $(INC)
+	$(CC) reclaim.c $(SCOPT)
+
+allchblk.o : allchblk.c $(INC)
+	$(CC) allchblk.c $(SCOPT)
+
+misc.o : misc.c $(INC)
+	$(CC) misc.c $(SCOPT)
+
+os_dep.o : os_dep.c $(INC) extra/AmigaOS.c
+	$(CC) os_dep.c $(SCOPT)
+
+mark_rts.o : mark_rts.c $(INC)
+	$(CC) mark_rts.c $(SCOPT)
+
+headers.o : headers.c $(INC)
+	$(CC) headers.c $(SCOPT)
+
+mark.o : mark.c $(INC)
+	$(CC) mark.c $(SCOPT)
+
+obj_map.o : obj_map.c $(INC)
+	$(CC) obj_map.c $(SCOPT)
+
+blacklst.o : blacklst.c $(INC)
+	$(CC) blacklst.c $(SCOPT)
+
+finalize.o : finalize.c $(INC)
+	$(CC) finalize.c $(SCOPT) noopt
+# Could sas/c still have problems with this one? gctest sometimes fails to finalize all.
+
+new_hblk.o : new_hblk.c $(INC)
+	$(CC) new_hblk.c $(SCOPT)
+
+dyn_load.o : dyn_load.c $(INC)
+	$(CC) dyn_load.c $(SCOPT)
+
+dbg_mlc.o : dbg_mlc.c $(INC)
+	$(CC) dbg_mlc.c $(SCOPT)
+
+fnlz_mlc.o : fnlz_mlc.c $(INC)
+	$(CC) fnlz_mlc.c $(SCOPT)
+
+malloc.o : malloc.c $(INC)
+	$(CC) malloc.c $(SCOPT)
+
+mallocx.o : mallocx.c $(INC)
+	$(CC) mallocx.c $(SCOPT)
+
+checksums.o : checksums.c $(INC)
+	$(CC) checksums.c $(SCOPT)
+
+typd_mlc.o: typd_mlc.c $(INC)
+	$(CC) typd_mlc.c $(SCOPT)
+
+mach_dep.o : mach_dep.c $(INC)
+	$(CC) mach_dep.c $(SCOPT)
+
+ptr_chck.o: ptr_chck.c $(INC)
+	$(CC) ptr_chck.c $(SCOPT)
+
+test.o : test.c $(INC)
+	$(CC) test.c $(SOPT)
+
+setjmp_t: tools/setjmp_t.c gc.h
+	$(CC) tools/setjmp_t.c $(SOPT)
+
+# cords:
+
+cord/cordbscs.o: cord/cordbscs.c
+	$(CC) cord/cordbscs.c $(CSCOPT)
+
+cord/cordprnt.o: cord/cordprnt.c
+	$(CC) cord/cordprnt.c $(CSCOPT)
+
+cord/cordxtra.o: cord/cordxtra.c
+	$(CC) cord/cordxtra.c $(CSCOPT)
+
+cord/tests/cordtest.o: cord/tests/cordtest.c
+	$(CC) cord/tests/cordtest.c $(CSCOPT)

+ 291 - 0
blitz.mod/bdwgc/WCC_MAKEFILE

@@ -0,0 +1,291 @@
+# Makefile for Watcom C/C++ 10.5, 10.6, 11.0 on NT, OS2 and DOS4GW.
+# May work with Watcom 10.0.
+
+# Uncomment one of the lines below for cross compilation.
+SYSTEM=MSWIN32
+#SYSTEM=DOS4GW
+#SYSTEM=OS2
+
+# The collector can be built either as dynamic (the default) or as static
+# library. The latter is selected by setting ENABLE_STATIC variable.
+#ENABLE_STATIC=1
+
+# Select calling conventions.
+# Possible choices are r and s.
+CALLING=s
+
+# Select target CPU.
+# Possible choices are 3, 4, 5, and 6.
+# The last choice available only since version 11.0.
+CPU=5
+
+# Set optimization options.
+# Watcom before 11.0 does not support option "-oh".
+OPTIM=-oneatx -s
+#OPTIM=-ohneatx -s
+
+# Extra user-defined flags to pass both to C and C++ compilers.
+CFLAGS_EXTRA=
+
+DEFS=-DALL_INTERIOR_POINTERS -DENABLE_DISCLAIM -DGC_ATOMIC_UNCOLLECTABLE -DGC_GCJ_SUPPORT -DJAVA_FINALIZATION -DNO_EXECUTE_PERMISSION #-DSMALL_CONFIG
+
+
+#####
+
+!ifndef SYSTEM
+!ifdef __MSDOS__
+SYSTEM=DOS4GW
+!else ifdef __NT__
+SYSTEM=MSWIN32
+!else ifdef __OS2__
+SYSTEM=OS2
+!else
+SYSTEM=Unknown
+!endif
+!endif
+
+!define $(SYSTEM)
+
+!ifdef DOS4GW
+SYSFLAG=-DDOS4GW -bt=dos
+!else ifdef MSWIN32
+SYSFLAG=-DMSWIN32 -bt=nt
+DEFS=$(DEFS) -DUSE_MUNMAP
+!else ifdef OS2
+SYSFLAG=-DOS2 -bt=os2
+!else
+!error undefined or unsupported target platform: $(SYSTEM)
+!endif
+
+!ifdef ENABLE_STATIC
+DLLFLAG=
+TEST_DLLFLAG=-DGC_NOT_DLL
+CORDFLAG=
+!else
+DLLFLAG=-bd -DGC_DLL
+TEST_DLLFLAG=-DGC_DLL
+# cord.dll and its clients should not link C library statically otherwise
+# FILE-related functions might not work (because own set of opened FILEs
+# is maintained by each copy of the C library thus making impossible to pass
+# FILE pointer from, e.g., .exe code to .dll one).
+CORDFLAG=-br
+!endif
+
+CC=wcc386
+CXX=wpp386
+
+CFLAGS=-$(CPU)$(CALLING) $(OPTIM) -iinclude -zp4 -zc $(SYSFLAG) $(DLLFLAG) $(DEFS) $(CFLAGS_EXTRA)
+CXXFLAGS= $(CFLAGS) -xs
+TEST_CFLAGS=-$(CPU)$(CALLING) $(OPTIM) -iinclude -zp4 -zc $(SYSFLAG) $(TEST_DLLFLAG) $(DEFS) $(CFLAGS_EXTRA)
+TEST_CXXFLAGS= $(TEST_CFLAGS) -xs
+
+COBJS= cordbscs.obj cordxtra.obj cordprnt.obj
+
+all: gc.lib gccpp.lib gctba.lib cord.lib
+
+check-deps: gctest.exe test_cpp.exe cordtest.exe .SYMBOLIC
+
+check: check-deps .SYMBOLIC
+        *gctest.exe
+        *test_cpp.exe
+        *cordtest.exe
+
+!ifdef ENABLE_STATIC
+
+OBJS= alloc.obj reclaim.obj allchblk.obj misc.obj &
+      mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj &
+      obj_map.obj blacklst.obj finalize.obj new_hblk.obj &
+      dbg_mlc.obj malloc.obj dyn_load.obj &
+      typd_mlc.obj ptr_chck.obj mallocx.obj fnlz_mlc.obj gcj_mlc.obj
+
+gc.lib: $(OBJS)
+        @%create $*.lb1
+        @for %i in ($(OBJS)) do @%append $*.lb1 +'%i'
+        *wlib -b -c -n -p=512 $@ @$*.lb1
+
+cord.lib: $(COBJS)
+        @%create $*.lb1
+        @for %i in ($(COBJS)) do @%append $*.lb1 +'%i'
+        *wlib -b -c -n -p=512 $@ @$*.lb1
+
+gccpp.lib: gc_badalc.obj gc_cpp.obj
+        @%create $*.lb1
+        @%append $*.lb1 +'gc_badalc.obj'
+        @%append $*.lb1 +'gc_cpp.obj'
+        *wlib -b -c -n -p=512 $@ @$*.lb1
+
+# The same as gccpp.lib but contains only gc_badalc.obj.
+gctba.lib: gc_badalc.obj
+        @%create $*.lb1
+        @%append $*.lb1 +'gc_badalc.obj'
+        *wlib -b -c -n -p=512 $@ @$*.lb1
+
+!else
+
+gc.obj: extra\gc.c .AUTODEPEND
+        $(CC) $(CFLAGS) extra\gc.c
+
+gc.lib: gc.dll
+        *wlib -b -c -n -p=512 $@ +gc.dll
+
+gc.dll: gc.obj .AUTODEPEND
+        @%create $*.lnk
+!ifdef DOS4GW
+        @%append $*.lnk sys os2v2_dll
+!else ifdef MSWIN32
+        @%append $*.lnk sys nt_dll
+!else ifdef OS2
+        @%append $*.lnk sys os2v2_dll
+!endif
+        @%append $*.lnk op case
+        @%append $*.lnk name $*
+        @%append $*.lnk file 'gc.obj'
+        *wlink @$*.lnk
+
+cord.lib: cord.dll
+        *wlib -b -c -n -p=512 $@ +cord.dll
+
+cord.dll: $(COBJS) gc.lib .AUTODEPEND
+        @%create $*.lnk
+!ifdef DOS4GW
+        @%append $*.lnk sys os2v2_dll
+!else ifdef MSWIN32
+        @%append $*.lnk sys nt_dll
+!else ifdef OS2
+        @%append $*.lnk sys os2v2_dll
+!endif
+        @%append $*.lnk op case
+        @%append $*.lnk name $*
+        @for %i in ($(COBJS)) do @%append $*.lnk file '%i'
+        @%append $*.lnk library gc.lib
+        *wlink @$*.lnk
+
+gccpp.lib: gccpp.dll
+        *wlib -b -c -n -p=512 $@ +gccpp.dll
+
+gccpp.dll: gc_badalc.obj gc_cpp.obj gc.lib .AUTODEPEND
+        @%create $*.lnk
+!ifdef DOS4GW
+        @%append $*.lnk sys os2v2_dll
+!else ifdef MSWIN32
+        @%append $*.lnk sys nt_dll
+!else ifdef OS2
+        @%append $*.lnk sys os2v2_dll
+!endif
+        @%append $*.lnk op case
+        @%append $*.lnk name $*
+        @%append $*.lnk file 'gc_badalc.obj'
+        @%append $*.lnk file 'gc_cpp.obj'
+        @%append $*.lnk library gc.lib
+        @%append $*.lnk library wr7$(CALLING)dll.lib
+        *wlink @$*.lnk
+
+gctba.lib: gctba.dll
+        *wlib -b -c -n -p=512 $@ +gctba.dll
+
+gctba.dll: gc_badalc.obj gc.lib .AUTODEPEND
+        @%create $*.lnk
+!ifdef DOS4GW
+        @%append $*.lnk sys os2v2_dll
+!else ifdef MSWIN32
+        @%append $*.lnk sys nt_dll
+!else ifdef OS2
+        @%append $*.lnk sys os2v2_dll
+!endif
+        @%append $*.lnk op case
+        @%append $*.lnk name $*
+        @%append $*.lnk file 'gc_badalc.obj'
+        @%append $*.lnk library gc.lib
+        @%append $*.lnk library wr7$(CALLING)dll.lib
+        *wlink @$*.lnk
+
+!endif
+
+gctest.exe: test.obj gc.lib
+        %create $*.lnk
+!ifdef DOS4GW
+        @%append $*.lnk sys dos4g
+!else ifdef MSWIN32
+        @%append $*.lnk sys nt
+!else ifdef OS2
+        @%append $*.lnk sys os2v2
+!endif
+        @%append $*.lnk op case
+        @%append $*.lnk op stack=256K
+        @%append $*.lnk name $*
+        @%append $*.lnk file test.obj
+        @%append $*.lnk library gc.lib
+        *wlink @$*.lnk
+
+cordtest.exe: cordtest.obj gc.lib cord.lib
+        %create $*.lnk
+!ifdef DOS4GW
+        @%append $*.lnk sys dos4g
+!else ifdef MSWIN32
+        @%append $*.lnk sys nt
+!else ifdef OS2
+        @%append $*.lnk sys os2v2
+!endif
+        @%append $*.lnk op case
+        @%append $*.lnk op stack=256K
+        @%append $*.lnk name $*
+        @%append $*.lnk file cordtest.obj
+        @%append $*.lnk library gc.lib
+        @%append $*.lnk library cord.lib
+        *wlink @$*.lnk
+
+test_cpp.exe: test_cpp.obj gc.lib gccpp.lib
+        %create $*.lnk
+!ifdef DOS4GW
+        @%append $*.lnk sys dos4g
+!else ifdef MSWIN32
+        @%append $*.lnk sys nt
+!else ifdef OS2
+        @%append $*.lnk sys os2v2
+!endif
+        @%append $*.lnk op case
+        @%append $*.lnk op stack=256K
+        @%append $*.lnk name $*
+        @%append $*.lnk file test_cpp.obj
+        @%append $*.lnk library gc.lib
+        @%append $*.lnk library gccpp.lib
+        *wlink @$*.lnk
+
+cordbscs.obj: cord\cordbscs.c .AUTODEPEND
+        $(CC) $(CFLAGS) $(CORDFLAG) cord\cordbscs.c
+cordxtra.obj: cord\cordxtra.c .AUTODEPEND
+        $(CC) $(CFLAGS) $(CORDFLAG) cord\cordxtra.c
+cordprnt.obj: cord\cordprnt.c .AUTODEPEND
+        $(CC) $(CFLAGS) $(CORDFLAG) cord\cordprnt.c
+
+gc_badalc.obj: gc_badalc.cc .AUTODEPEND
+        $(CXX) $(TEST_CXXFLAGS) $*.cc
+gc_cpp.obj: gc_cpp.cc .AUTODEPEND
+        $(CXX) $(TEST_CXXFLAGS) $*.cc
+
+test.obj: tests\test.c .AUTODEPEND
+        $(CC) $(TEST_CFLAGS) /wcd=13 /wcd=201 /wcd=367 /wcd=368 tests\test.c
+cordtest.obj: cord\tests\cordtest.c .AUTODEPEND
+        $(CC) $(TEST_CFLAGS) $(CORDFLAG) cord\tests\cordtest.c
+test_cpp.obj: tests\test_cpp.cc .AUTODEPEND
+        $(CXX) $(TEST_CXXFLAGS) tests\test_cpp.cc
+
+.c.obj: .AUTODEPEND
+        $(CC) $(CFLAGS) $*.c
+
+.cc.obj: .AUTODEPEND
+        $(CXX) $(CXXFLAGS) $*.cc
+
+clean: .SYMBOLIC
+    @if exist *.obj del *.obj
+    @if exist *.map del *.map
+    @if exist *.lnk del *.lnk
+    @if exist *.lb1 del *.lb1
+    @if exist *.sym del *.sym
+    @if exist *.err del *.err
+    @if exist *.tmp del *.tmp
+    @if exist *.lst del *.lst
+    @if exist *.exe del *.exe
+    @if exist *.log del *.log
+    @if exist *.lib del *.lib
+    @if exist *.dll del *.dll

+ 100 - 9
blitz.mod/bdwgc/allchblk.c

@@ -326,8 +326,8 @@ GC_INLINE void GC_remove_from_fl(hdr *hhdr)
   GC_remove_from_fl_at(hhdr, GC_hblk_fl_from_blocks(divHBLKSZ(hhdr->hb_sz)));
 }
 
-/* Return a pointer to the free block ending just before h, if any.     */
-STATIC struct hblk * GC_free_block_ending_at(struct hblk *h)
+/* Return a pointer to the block ending just before h, if any.  */
+static struct hblk * get_block_ending_at(struct hblk *h)
 {
     struct hblk * p = h - 1;
     hdr * phdr;
@@ -338,16 +338,27 @@ STATIC struct hblk * GC_free_block_ending_at(struct hblk *h)
         phdr = HDR(p);
     }
     if (0 != phdr) {
-        if(HBLK_IS_FREE(phdr)) {
+        return p;
+    }
+    p = GC_prev_block(h - 1);
+    if (p) {
+        phdr = HDR(p);
+        if ((ptr_t)p + phdr -> hb_sz == (ptr_t)h) {
             return p;
-        } else {
-            return 0;
         }
     }
-    p = GC_prev_block(h - 1);
+    return NULL;
+}
+
+/* Return a pointer to the free block ending just before h, if any.     */
+STATIC struct hblk * GC_free_block_ending_at(struct hblk *h)
+{
+    struct hblk * p = get_block_ending_at(h);
+
     if (p /* != NULL */) { /* CPPCHECK */
-      phdr = HDR(p);
-      if (HBLK_IS_FREE(phdr) && (ptr_t)p + phdr -> hb_sz == (ptr_t)h) {
+      hdr * phdr = HDR(p);
+
+      if (HBLK_IS_FREE(phdr)) {
         return p;
       }
     }
@@ -395,6 +406,60 @@ STATIC void GC_add_to_fl(struct hblk *h, hdr *hhdr)
 
 GC_INNER int GC_unmap_threshold = MUNMAP_THRESHOLD;
 
+#ifdef COUNT_UNMAPPED_REGIONS
+  /* GC_unmap_old will avoid creating more than this many unmapped regions, */
+  /* but an unmapped region may be split again so exceeding the limit.      */
+
+  /* Return the change in number of unmapped regions if the block h swaps   */
+  /* from its current state of mapped/unmapped to the opposite state.       */
+  static int calc_num_unmapped_regions_delta(struct hblk *h, hdr *hhdr)
+  {
+    struct hblk * prev = get_block_ending_at(h);
+    struct hblk * next;
+    GC_bool prev_unmapped = FALSE;
+    GC_bool next_unmapped = FALSE;
+
+    next = GC_next_block((struct hblk *)((ptr_t)h + hhdr->hb_sz), TRUE);
+    /* Ensure next is contiguous with h.        */
+    if ((ptr_t)next != GC_unmap_end((ptr_t)h, (size_t)hhdr->hb_sz)) {
+      next = NULL;
+    }
+    if (prev != NULL) {
+      hdr * prevhdr = HDR(prev);
+      prev_unmapped = !IS_MAPPED(prevhdr);
+    }
+    if (next != NULL) {
+      hdr * nexthdr = HDR(next);
+      next_unmapped = !IS_MAPPED(nexthdr);
+    }
+
+    if (prev_unmapped && next_unmapped) {
+      /* If h unmapped, merge two unmapped regions into one.    */
+      /* If h remapped, split one unmapped region into two.     */
+      return IS_MAPPED(hhdr) ? -1 : 1;
+    }
+    if (!prev_unmapped && !next_unmapped) {
+      /* If h unmapped, create an isolated unmapped region.     */
+      /* If h remapped, remove it.                              */
+      return IS_MAPPED(hhdr) ? 1 : -1;
+    }
+    /* If h unmapped, merge it with previous or next unmapped region.   */
+    /* If h remapped, reduce either previous or next unmapped region.   */
+    /* In either way, no change to the number of unmapped regions.      */
+    return 0;
+  }
+#endif /* COUNT_UNMAPPED_REGIONS */
+
+/* Update GC_num_unmapped_regions assuming the block h changes      */
+/* from its current state of mapped/unmapped to the opposite state. */
+GC_INLINE void GC_adjust_num_unmapped(struct hblk *h GC_ATTR_UNUSED,
+                                      hdr *hhdr GC_ATTR_UNUSED)
+{
+# ifdef COUNT_UNMAPPED_REGIONS
+    GC_num_unmapped_regions += calc_num_unmapped_regions_delta(h, hhdr);
+# endif
+}
+
 /* Unmap blocks that haven't been recently touched.  This is the only way */
 /* way blocks are ever unmapped.                                          */
 GC_INNER void GC_unmap_old(void)
@@ -403,6 +468,12 @@ GC_INNER void GC_unmap_old(void)
 
     if (GC_unmap_threshold == 0)
       return; /* unmapping disabled */
+# ifdef COUNT_UNMAPPED_REGIONS
+    /* Skip unmapping if we have already exceeded the soft limit.       */
+    /* This forgoes any opportunities to merge unmapped regions though. */
+    if (GC_num_unmapped_regions >= GC_UNMAPPED_REGIONS_SOFT_LIMIT)
+      return;
+# endif
 
     for (i = 0; i <= N_HBLK_FLS; ++i) {
       struct hblk * h;
@@ -416,6 +487,19 @@ GC_INNER void GC_unmap_old(void)
         /* truncated counter value wrapping is handled correctly).      */
         if ((unsigned short)(GC_gc_no - hhdr->hb_last_reclaimed) >
                 (unsigned short)GC_unmap_threshold) {
+#         ifdef COUNT_UNMAPPED_REGIONS
+            /* Continue with unmapping the block only if it will not    */
+            /* create too many unmapped regions, or if unmapping        */
+            /* reduces the number of regions.                           */
+            int delta = calc_num_unmapped_regions_delta(h, hhdr);
+            signed_word regions = GC_num_unmapped_regions + delta;
+
+            if (delta >= 0 && regions >= GC_UNMAPPED_REGIONS_SOFT_LIMIT) {
+              GC_COND_LOG_PRINTF("Unmapped regions limit reached!\n");
+              return;
+            }
+            GC_num_unmapped_regions = regions;
+#         endif
           GC_unmap((ptr_t)h, (size_t)hhdr->hb_sz);
           hhdr -> hb_flags |= WAS_UNMAPPED;
         }
@@ -454,17 +538,21 @@ GC_INNER void GC_merge_unmapped(void)
             if (IS_MAPPED(hhdr) && !IS_MAPPED(nexthdr)) {
               /* make both consistent, so that we can merge */
                 if (size > nextsize) {
+                  GC_adjust_num_unmapped(next, nexthdr);
                   GC_remap((ptr_t)next, nextsize);
                 } else {
+                  GC_adjust_num_unmapped(h, hhdr);
                   GC_unmap((ptr_t)h, size);
                   GC_unmap_gap((ptr_t)h, size, (ptr_t)next, nextsize);
                   hhdr -> hb_flags |= WAS_UNMAPPED;
                 }
             } else if (IS_MAPPED(nexthdr) && !IS_MAPPED(hhdr)) {
               if (size > nextsize) {
+                GC_adjust_num_unmapped(next, nexthdr);
                 GC_unmap((ptr_t)next, nextsize);
                 GC_unmap_gap((ptr_t)h, size, (ptr_t)next, nextsize);
               } else {
+                GC_adjust_num_unmapped(h, hhdr);
                 GC_remap((ptr_t)h, size);
                 hhdr -> hb_flags &= ~WAS_UNMAPPED;
                 hhdr -> hb_last_reclaimed = nexthdr -> hb_last_reclaimed;
@@ -595,6 +683,7 @@ GC_allochblk(size_t sz, int kind, unsigned flags/* IGNORE_OFF_PAGE or 0 */)
     int split_limit; /* Highest index of free list whose blocks we      */
                      /* split.                                          */
 
+    GC_ASSERT(I_HOLD_LOCK());
     GC_ASSERT((sz & (GRANULE_BYTES - 1)) == 0);
     blocks = OBJ_SZ_TO_BLOCKS_CHECKED(sz);
     if ((signed_word)(blocks * HBLKSIZE) < 0) {
@@ -717,6 +806,7 @@ GC_allochblk_nth(size_t sz, int kind, unsigned flags, int n, int may_split)
                   /* Make sure it's mapped before we mangle it. */
 #                   ifdef USE_MUNMAP
                       if (!IS_MAPPED(hhdr)) {
+                        GC_adjust_num_unmapped(hbp, hhdr);
                         GC_remap((ptr_t)hbp, (size_t)hhdr->hb_sz);
                         hhdr -> hb_flags &= ~WAS_UNMAPPED;
                       }
@@ -791,6 +881,7 @@ GC_allochblk_nth(size_t sz, int kind, unsigned flags, int n, int may_split)
             if( size_avail >= size_needed ) {
 #               ifdef USE_MUNMAP
                   if (!IS_MAPPED(hhdr)) {
+                    GC_adjust_num_unmapped(hbp, hhdr);
                     GC_remap((ptr_t)hbp, (size_t)hhdr->hb_sz);
                     hhdr -> hb_flags &= ~WAS_UNMAPPED;
                     /* Note: This may leave adjacent, mapped free blocks. */
@@ -848,7 +939,7 @@ GC_INNER void GC_freehblk(struct hblk *hbp)
 
     GET_HDR(hbp, hhdr);
     size = HBLKSIZE * OBJ_SZ_TO_BLOCKS(hhdr->hb_sz);
-    if ((signed_word)size <= 0)
+    if ((size & SIGNB) != 0)
       ABORT("Deallocating excessively large block.  Too large an allocation?");
       /* Probably possible if we try to allocate more than half the address */
       /* space at once.  If we don't catch it here, strange things happen   */

+ 170 - 46
blitz.mod/bdwgc/alloc.c

@@ -1,9 +1,9 @@
 /*
- * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1988-1989 Hans-J. Boehm, Alan J. Demers
  * Copyright (c) 1991-1996 by Xerox Corporation.  All rights reserved.
- * Copyright (c) 1998 by Silicon Graphics.  All rights reserved.
- * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
- * Copyright (c) 2008-2020 Ivan Maidanski
+ * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.
+ * Copyright (c) 1999-2011 Hewlett-Packard Development Company, L.P.
+ * Copyright (c) 2008-2021 Ivan Maidanski
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
@@ -21,7 +21,7 @@
 #include <stdio.h>
 #if !defined(MACOS) && !defined(MSWINCE)
 # include <signal.h>
-# if !defined(SN_TARGET_ORBIS) && !defined(SN_TARGET_PSP2) \
+# if !defined(GC_NO_TYPES) && !defined(SN_TARGET_PSP2) \
      && !defined(__CC_ARM)
 #   include <sys/types.h>
 # endif
@@ -88,6 +88,7 @@ word GC_gc_no = 0;
 
 #ifndef GC_DISABLE_INCREMENTAL
   GC_INNER GC_bool GC_incremental = FALSE; /* By default, stop the world. */
+  STATIC GC_bool GC_should_start_incremental_collection = FALSE;
 #endif
 
 GC_API int GC_CALL GC_is_incremental_mode(void)
@@ -114,21 +115,29 @@ STATIC GC_bool GC_need_full_gc = FALSE;
   GC_INNER GC_bool GC_world_stopped = FALSE;
 #endif
 
-STATIC word GC_used_heap_size_after_full = 0;
+STATIC GC_bool GC_disable_automatic_collection = FALSE;
+
+GC_API void GC_CALL GC_set_disable_automatic_collection(int value)
+{
+  DCL_LOCK_STATE;
 
-/* GC_copyright symbol is externally visible. */
-EXTERN_C_BEGIN
-extern const char * const GC_copyright[];
-EXTERN_C_END
-const char * const GC_copyright[] =
-{"Copyright 1988, 1989 Hans-J. Boehm and Alan J. Demers ",
-"Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved. ",
-"Copyright (c) 1996-1998 by Silicon Graphics.  All rights reserved. ",
-"Copyright (c) 1999-2009 by Hewlett-Packard Company.  All rights reserved. ",
-"Copyright (c) 2008-2020 Ivan Maidanski ",
-"THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY",
-" EXPRESSED OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.",
-"See source code for details." };
+  LOCK();
+  GC_disable_automatic_collection = (GC_bool)value;
+  UNLOCK();
+}
+
+GC_API int GC_CALL GC_get_disable_automatic_collection(void)
+{
+  int value;
+  DCL_LOCK_STATE;
+
+  LOCK();
+  value = (int)GC_disable_automatic_collection;
+  UNLOCK();
+  return value;
+}
+
+STATIC word GC_used_heap_size_after_full = 0;
 
 /* Version macros are now defined in gc_version.h, which is included by */
 /* gc.h, which is included by gc_priv.h.                                */
@@ -386,15 +395,40 @@ STATIC void GC_clear_a_few_frames(void)
 /* limits used by blacklisting.                                         */
 STATIC word GC_collect_at_heapsize = GC_WORD_MAX;
 
+GC_API void GC_CALL GC_start_incremental_collection(void)
+{
+# ifndef GC_DISABLE_INCREMENTAL
+    DCL_LOCK_STATE;
+
+    if (!GC_incremental) return;
+    LOCK();
+    GC_should_start_incremental_collection = TRUE;
+    ENTER_GC();
+    GC_collect_a_little_inner(1);
+    EXIT_GC();
+    UNLOCK();
+# endif
+}
+
 /* Have we allocated enough to amortize a collection? */
 GC_INNER GC_bool GC_should_collect(void)
 {
     static word last_min_bytes_allocd;
     static word last_gc_no;
+
+    GC_ASSERT(I_HOLD_LOCK());
     if (last_gc_no != GC_gc_no) {
       last_min_bytes_allocd = min_bytes_allocd();
       last_gc_no = GC_gc_no;
     }
+# ifndef GC_DISABLE_INCREMENTAL
+    if (GC_should_start_incremental_collection) {
+      GC_should_start_incremental_collection = FALSE;
+      return TRUE;
+    }
+# endif
+    if (GC_disable_automatic_collection) return FALSE;
+
     return(GC_adj_bytes_allocd() >= last_min_bytes_allocd
            || GC_heapsize >= GC_collect_at_heapsize);
 }
@@ -869,11 +903,17 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func)
         }
 
     GC_gc_no++;
-    GC_DBGLOG_PRINTF("GC #%lu freed %ld bytes, heap %lu KiB"
-                     IF_USE_MUNMAP(" (+ %lu KiB unmapped)") "\n",
+#   ifdef USE_MUNMAP
+      GC_ASSERT(GC_heapsize >= GC_unmapped_bytes);
+#   endif
+    GC_ASSERT(GC_our_mem_bytes >= GC_heapsize);
+    GC_DBGLOG_PRINTF("GC #%lu freed %ld bytes, heap %lu KiB ("
+                     IF_USE_MUNMAP("+ %lu KiB unmapped ")
+                     "+ %lu KiB internal)\n",
                      (unsigned long)GC_gc_no, (long)GC_bytes_found,
                      TO_KiB_UL(GC_heapsize - GC_unmapped_bytes) /*, */
-                     COMMA_IF_USE_MUNMAP(TO_KiB_UL(GC_unmapped_bytes)));
+                     COMMA_IF_USE_MUNMAP(TO_KiB_UL(GC_unmapped_bytes)),
+                     TO_KiB_UL(GC_our_mem_bytes - GC_heapsize));
 
     /* Check all debugged objects for consistency */
     if (GC_debugging_started) {
@@ -1255,6 +1295,7 @@ STATIC GC_bool GC_try_to_collect_general(GC_stop_func stop_func,
 }
 
 /* Externally callable routines to invoke full, stop-the-world collection. */
+
 GC_API int GC_CALL GC_try_to_collect(GC_stop_func stop_func)
 {
     GC_ASSERT(NONNULL_ARG_NOT_NULL(stop_func));
@@ -1282,30 +1323,65 @@ GC_API void GC_CALL GC_gcollect_and_unmap(void)
 
 #ifdef USE_PROC_FOR_LIBRARIES
   /* Add HBLKSIZE aligned, GET_MEM-generated block to GC_our_memory. */
-  /* Defined to do nothing if USE_PROC_FOR_LIBRARIES not set.       */
   GC_INNER void GC_add_to_our_memory(ptr_t p, size_t bytes)
   {
-    if (0 == p) return;
+    GC_ASSERT(p != NULL);
     if (GC_n_memory >= MAX_HEAP_SECTS)
       ABORT("Too many GC-allocated memory sections: Increase MAX_HEAP_SECTS");
     GC_our_memory[GC_n_memory].hs_start = p;
     GC_our_memory[GC_n_memory].hs_bytes = bytes;
     GC_n_memory++;
+    GC_our_mem_bytes += bytes;
   }
 #endif
 
-/*
- * Use the chunk of memory starting at p of size bytes as part of the heap.
- * Assumes p is HBLKSIZE aligned, and bytes is a multiple of HBLKSIZE.
- */
-GC_INNER void GC_add_to_heap(struct hblk *p, size_t bytes)
+/* Use the chunk of memory starting at p of size bytes as part of the heap. */
+/* Assumes p is HBLKSIZE aligned, and bytes is a multiple of HBLKSIZE.      */
+STATIC void GC_add_to_heap(struct hblk *p, size_t bytes)
 {
     hdr * phdr;
     word endp;
+    size_t old_capacity = 0;
+    void *old_heap_sects = NULL;
+#   ifdef GC_ASSERTIONS
+      unsigned i;
+#   endif
 
-    if (GC_n_heap_sects >= MAX_HEAP_SECTS) {
-        ABORT("Too many heap sections: Increase MAXHINCR or MAX_HEAP_SECTS");
+    GC_ASSERT((word)p % HBLKSIZE == 0);
+    GC_ASSERT(bytes % HBLKSIZE == 0);
+    GC_ASSERT(bytes > 0);
+    GC_ASSERT(GC_all_nils != NULL);
+
+    if (GC_n_heap_sects == GC_capacity_heap_sects) {
+      /* Allocate new GC_heap_sects with sufficient capacity.   */
+#     ifndef INITIAL_HEAP_SECTS
+#       define INITIAL_HEAP_SECTS 32
+#     endif
+      size_t new_capacity = GC_n_heap_sects > 0 ?
+                (size_t)GC_n_heap_sects * 2 : INITIAL_HEAP_SECTS;
+      void *new_heap_sects =
+                GC_scratch_alloc(new_capacity * sizeof(struct HeapSect));
+
+      if (EXPECT(NULL == new_heap_sects, FALSE)) {
+        /* Retry with smaller yet sufficient capacity.  */
+        new_capacity = (size_t)GC_n_heap_sects + INITIAL_HEAP_SECTS;
+        new_heap_sects =
+                GC_scratch_alloc(new_capacity * sizeof(struct HeapSect));
+        if (NULL == new_heap_sects)
+          ABORT("Insufficient memory for heap sections");
+      }
+      old_capacity = GC_capacity_heap_sects;
+      old_heap_sects = GC_heap_sects;
+      /* Transfer GC_heap_sects contents to the newly allocated array.  */
+      if (GC_n_heap_sects > 0)
+        BCOPY(old_heap_sects, new_heap_sects,
+              GC_n_heap_sects * sizeof(struct HeapSect));
+      GC_capacity_heap_sects = new_capacity;
+      GC_heap_sects = (struct HeapSect *)new_heap_sects;
+      GC_COND_LOG_PRINTF("Grew heap sections array to %lu elements\n",
+                         (unsigned long)new_capacity);
     }
+
     while ((word)p <= HBLKSIZE) {
         /* Can't handle memory near address zero. */
         ++p;
@@ -1327,6 +1403,18 @@ GC_INNER void GC_add_to_heap(struct hblk *p, size_t bytes)
         return;
     }
     GC_ASSERT(endp > (word)p && endp == (word)p + bytes);
+#   ifdef GC_ASSERTIONS
+      /* Ensure no intersection between sections.       */
+      for (i = 0; i < GC_n_heap_sects; i++) {
+        word hs_start = (word)GC_heap_sects[i].hs_start;
+        word hs_end = hs_start + GC_heap_sects[i].hs_bytes;
+        word p_e = (word)p + bytes;
+
+        GC_ASSERT(!((hs_start <= (word)p && (word)p < hs_end)
+                    || (hs_start < p_e && p_e <= hs_end)
+                    || ((word)p < hs_start && hs_end < p_e)));
+      }
+#   endif
     GC_heap_sects[GC_n_heap_sects].hs_start = (ptr_t)p;
     GC_heap_sects[GC_n_heap_sects].hs_bytes = bytes;
     GC_n_heap_sects++;
@@ -1336,7 +1424,7 @@ GC_INNER void GC_add_to_heap(struct hblk *p, size_t bytes)
     GC_heapsize += bytes;
 
     /* Normally the caller calculates a new GC_collect_at_heapsize,
-     * but this is also called directly from alloc_mark_stack, so
+     * but this is also called directly from GC_scratch_recycle_inner, so
      * adjust here. It will be recalculated when called from
      * GC_expand_hp_inner.
      */
@@ -1355,6 +1443,18 @@ GC_INNER void GC_add_to_heap(struct hblk *p, size_t bytes)
     if ((word)p + bytes >= (word)GC_greatest_plausible_heap_addr) {
         GC_greatest_plausible_heap_addr = (void *)endp;
     }
+
+    if (old_capacity > 0) {
+#     ifndef GWW_VDB
+        /* Recycling may call GC_add_to_heap() again but should not     */
+        /* cause resizing of GC_heap_sects.                             */
+        GC_scratch_recycle_no_gww(old_heap_sects,
+                                  old_capacity * sizeof(struct HeapSect));
+#     else
+        /* TODO: implement GWW-aware recycling as in alloc_mark_stack */
+        GC_noop1((word)old_heap_sects);
+#     endif
+    }
 }
 
 #if !defined(NO_DEBUGGING)
@@ -1404,6 +1504,27 @@ GC_API void GC_CALL GC_set_max_heap_size(GC_word n)
 
 GC_word GC_max_retries = 0;
 
+GC_INNER void GC_scratch_recycle_inner(void *ptr, size_t bytes)
+{
+  size_t page_offset;
+  size_t displ = 0;
+  size_t recycled_bytes;
+
+  if (NULL == ptr) return;
+
+  GC_ASSERT(bytes != 0);
+  GC_ASSERT(GC_page_size != 0);
+  /* TODO: Assert correct memory flags if GWW_VDB */
+  page_offset = (word)ptr & (GC_page_size - 1);
+  if (page_offset != 0)
+    displ = GC_page_size - page_offset;
+  recycled_bytes = bytes > displ ? (bytes - displ) & ~(GC_page_size - 1) : 0;
+  GC_COND_LOG_PRINTF("Recycle %lu/%lu scratch-allocated bytes at %p\n",
+                (unsigned long)recycled_bytes, (unsigned long)bytes, ptr);
+  if (recycled_bytes > 0)
+    GC_add_to_heap((struct hblk *)((word)ptr + displ), recycled_bytes);
+}
+
 /* This explicitly increases the size of the heap.  It is used          */
 /* internally, but may also be invoked from GC_expand_hp by the user.   */
 /* The argument is in units of HBLKSIZE (tiny values are rounded up).   */
@@ -1412,10 +1533,11 @@ GC_INNER GC_bool GC_expand_hp_inner(word n)
 {
     size_t bytes;
     struct hblk * space;
-    word expansion_slop;        /* Number of bytes by which we expect the */
-                                /* heap to expand soon.                   */
+    word expansion_slop;        /* Number of bytes by which we expect   */
+                                /* the heap to expand soon.             */
 
     GC_ASSERT(I_HOLD_LOCK());
+    GC_ASSERT(GC_page_size != 0);
     if (n < MINHINCR) n = MINHINCR;
     bytes = ROUNDUP_PAGESIZE((size_t)n * HBLKSIZE);
     if (GC_max_heapsize != 0
@@ -1425,23 +1547,24 @@ GC_INNER GC_bool GC_expand_hp_inner(word n)
         return(FALSE);
     }
     space = GET_MEM(bytes);
-    GC_add_to_our_memory((ptr_t)space, bytes);
-    if (space == 0) {
+    if (EXPECT(NULL == space, FALSE)) {
         WARN("Failed to expand heap by %" WARN_PRIdPTR " bytes\n",
              (word)bytes);
         return(FALSE);
     }
+    GC_add_to_our_memory((ptr_t)space, bytes);
     GC_INFOLOG_PRINTF("Grow heap to %lu KiB after %lu bytes allocated\n",
                       TO_KiB_UL(GC_heapsize + (word)bytes),
                       (unsigned long)GC_bytes_allocd);
+
     /* Adjust heap limits generously for blacklisting to work better.   */
     /* GC_add_to_heap performs minimal adjustment needed for            */
     /* correctness.                                                     */
-    expansion_slop = min_bytes_allocd() + 4*MAXHINCR*HBLKSIZE;
+    expansion_slop = min_bytes_allocd() + 4 * MAXHINCR * HBLKSIZE;
     if ((GC_last_heap_addr == 0 && !((word)space & SIGNB))
         || (GC_last_heap_addr != 0
             && (word)GC_last_heap_addr < (word)space)) {
-        /* Assume the heap is growing up */
+        /* Assume the heap is growing up. */
         word new_limit = (word)space + (word)bytes + expansion_slop;
         if (new_limit > (word)space) {
           GC_greatest_plausible_heap_addr =
@@ -1449,7 +1572,7 @@ GC_INNER GC_bool GC_expand_hp_inner(word n)
                            (word)new_limit);
         }
     } else {
-        /* Heap is growing down */
+        /* Heap is growing down. */
         word new_limit = (word)space - expansion_slop;
         if (new_limit < (word)space) {
           GC_least_plausible_heap_addr =
@@ -1457,16 +1580,17 @@ GC_INNER GC_bool GC_expand_hp_inner(word n)
                            (word)space - expansion_slop);
         }
     }
-    GC_prev_heap_addr = GC_last_heap_addr;
     GC_last_heap_addr = (ptr_t)space;
+
     GC_add_to_heap(space, bytes);
-    /* Force GC before we are likely to allocate past expansion_slop */
-      GC_collect_at_heapsize =
-         GC_heapsize + expansion_slop - 2*MAXHINCR*HBLKSIZE;
-      if (GC_collect_at_heapsize < GC_heapsize /* wrapped */)
-         GC_collect_at_heapsize = GC_WORD_MAX;
+
+    /* Force GC before we are likely to allocate past expansion_slop.   */
+    GC_collect_at_heapsize =
+        GC_heapsize + expansion_slop - 2 * MAXHINCR * HBLKSIZE;
+    if (GC_collect_at_heapsize < GC_heapsize /* wrapped */)
+        GC_collect_at_heapsize = GC_WORD_MAX;
     if (GC_on_heap_resize)
-      (*GC_on_heap_resize)(GC_heapsize);
+        (*GC_on_heap_resize)(GC_heapsize);
 
     return(TRUE);
 }

+ 18 - 0
blitz.mod/bdwgc/autogen.sh

@@ -0,0 +1,18 @@
+#!/bin/sh
+set -e
+
+# This script creates (or regenerates) configure (as well as aclocal.m4,
+# config.h.in, Makefile.in, etc.) missing in the source repository.
+#
+# If you compile from a distribution tarball, you can skip this.  Otherwise,
+# make sure that you have Autoconf, Automake and Libtool installed
+# on your system, and that the corresponding *.m4 files are visible
+# to the aclocal.  The latter can be achieved by using packages shipped by
+# your OS, or by installing custom versions of all four packages to the same
+# prefix.  Otherwise, you may need to invoke autoreconf with the appropriate
+# -I options to locate the required *.m4 files.
+
+autoreconf -i
+
+echo
+echo "Ready to run './configure'."

+ 8 - 6
blitz.mod/bdwgc/backgraph.c

@@ -30,8 +30,6 @@
 
 #define MAX_IN  10      /* Maximum in-degree we handle directly */
 
-/* #include <unistd.h> */
-
 #if (!defined(DBG_HDRS_ALL) || (ALIGNMENT != CPP_WORDSZ/8) \
      /* || !defined(UNIX_LIKE) */) && !defined(CPPCHECK)
 # error The configuration does not support MAKE_BACK_GRAPH
@@ -90,6 +88,7 @@ static back_edges * new_back_edges(void)
     size_t bytes_to_get = ROUNDUP_PAGESIZE_IF_MMAP(MAX_BACK_EDGE_STRUCTS
                                                    * sizeof(back_edges));
 
+    GC_ASSERT(GC_page_size != 0);
     back_edge_space = (back_edges *)GET_MEM(bytes_to_get);
     if (NULL == back_edge_space)
       ABORT("Insufficient memory for back edges");
@@ -132,6 +131,7 @@ static void push_in_progress(ptr_t p)
   if (n_in_progress >= in_progress_size) {
     ptr_t * new_in_progress_space;
 
+    GC_ASSERT(GC_page_size != 0);
     if (NULL == in_progress_space) {
       in_progress_size = ROUNDUP_PAGESIZE_IF_MMAP(INITIAL_IN_PROGRESS
                                                         * sizeof(ptr_t))
@@ -146,8 +146,9 @@ static void push_in_progress(ptr_t p)
         BCOPY(in_progress_space, new_in_progress_space,
               n_in_progress * sizeof(ptr_t));
     }
-    GC_add_to_our_memory((ptr_t)new_in_progress_space,
-                         in_progress_size * sizeof(ptr_t));
+    if (EXPECT(new_in_progress_space != NULL, TRUE))
+      GC_add_to_our_memory((ptr_t)new_in_progress_space,
+                           in_progress_size * sizeof(ptr_t));
 #   ifndef GWW_VDB
       GC_scratch_recycle_no_gww(in_progress_space,
                                 n_in_progress * sizeof(ptr_t));
@@ -532,8 +533,9 @@ GC_INNER void GC_traverse_back_graph(void)
 void GC_print_back_graph_stats(void)
 {
   GC_ASSERT(I_HOLD_LOCK());
-  GC_printf("Maximum backwards height of reachable objects at GC %lu is %lu\n",
-            (unsigned long) GC_gc_no, (unsigned long)GC_max_height);
+  GC_printf("Maximum backwards height of reachable objects"
+            " at GC #%lu is %lu\n",
+            (unsigned long)GC_gc_no, (unsigned long)GC_max_height);
   if (GC_max_height > GC_max_max_height) {
     ptr_t obj = GC_deepest_obj;
 

+ 10 - 0
blitz.mod/bdwgc/bdw-gc.pc.in

@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Boehm-Demers-Weiser Conservative Garbage Collector
+Description: A garbage collector for C and C++
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} @ATOMIC_OPS_LIBS@ -lgc @THREADDLLIBS@
+Cflags: -I${includedir}

+ 11 - 0
blitz.mod/bdwgc/blacklst.c

@@ -0,0 +1,11 @@
+/*
+ Name : bld.inf
+ Description : This file provides the information required for building the
+ whole of a libgc.
+*/
+
+PRJ_PLATFORMS
+default armv5
+
+PRJ_MMPFILES
+libgc.mmp

+ 78 - 0
blitz.mod/bdwgc/build/s60v3/libgc.mmp

@@ -0,0 +1,78 @@
+TARGET     libgc.dll
+
+TARGETTYPE        dll
+UID       0x1000008d 0x200107C2 // check uid
+
+EXPORTUNFROZEN
+EPOCALLOWDLLDATA
+//ALWAYS_BUILD_AS_ARM
+//nocompresstarget
+//srcdbg
+//baseaddress   00500000
+//LINKEROPTION CW -map libgc.map
+//LINKEROPTION CW -filealign 0x10000
+
+CAPABILITY PowerMgmt ReadDeviceData ReadUserData WriteDeviceData WriteUserData SwEvent LocalServices NetworkServices UserEnvironment
+
+
+MACRO ALL_INTERIOR_POINTERS
+MACRO NO_EXECUTE_PERMISSION
+MACRO USE_MMAP
+MACRO GC_ATOMIC_UNCOLLECTABLE
+MACRO GC_DONT_REGISTER_MAIN_STATIC_DATA
+MACRO GC_DLL
+MACRO JAVA_FINALIZATION
+MACRO SYMBIAN
+MACRO ENABLE_DISCLAIM
+//MACRO GC_GCJ_SUPPORT
+
+USERINCLUDE      ..\..\include
+USERINCLUDE      ..\..\include\private
+
+SYSTEMINCLUDE   \epoc32\include
+SYSTEMINCLUDE   \epoc32\include\stdapis
+
+SOURCEPATH        ..\..\
+
+SOURCE          allchblk.c
+SOURCE          alloc.c
+SOURCE          blacklst.c
+SOURCE          dbg_mlc.c
+SOURCE          dyn_load.c
+SOURCE          finalize.c
+SOURCE          fnlz_mlc.c
+//SOURCE        gc_badalc.cpp
+//SOURCE        gc_cpp.cpp
+SOURCE          gcj_mlc.c
+SOURCE          headers.c
+SOURCE          mach_dep.c
+SOURCE          malloc.c
+SOURCE          mallocx.c
+SOURCE          mark.c
+SOURCE          mark_rts.c
+SOURCE          misc.c
+SOURCE          new_hblk.c
+SOURCE          obj_map.c
+SOURCE          os_dep.c
+SOURCE          extra/symbian.cpp
+SOURCE          ptr_chck.c
+SOURCE          reclaim.c
+SOURCE          typd_mlc.c
+
+/*
+#ifdef ENABLE_ABIV2_MODE
+  DEBUGGABLE_UDEBONLY
+#endif
+*/
+
+// Using main() as entry point
+STATICLIBRARY   libcrt0.lib
+
+// libc and euser are always needed when using main() entry point
+LIBRARY         libc.lib
+
+
+LIBRARY euser.lib
+LIBRARY efsrv.lib
+LIBRARY avkon.lib
+LIBRARY eikcore.lib

+ 2 - 2
blitz.mod/bdwgc/checksums.c

@@ -127,8 +127,8 @@ STATIC void GC_check_blocks(void)
 
     GC_bytes_in_used_blocks = 0;
     GC_apply_to_all_blocks(GC_add_block, (word)0);
-    GC_COND_LOG_PRINTF("GC_bytes_in_used_blocks = %lu,"
-                       " bytes_in_free_blocks = %lu, heapsize = %lu\n",
+    GC_COND_LOG_PRINTF("GC_bytes_in_used_blocks= %lu,"
+                       " bytes_in_free_blocks= %lu, heapsize= %lu\n",
                        (unsigned long)GC_bytes_in_used_blocks,
                        (unsigned long)bytes_in_free_blocks,
                        (unsigned long)GC_heapsize);

+ 1191 - 0
blitz.mod/bdwgc/configure.ac

@@ -0,0 +1,1191 @@
+# Copyright (c) 1999-2001 by Red Hat, Inc. All rights reserved.
+# Copyright (c) 2005-2009 Hewlett-Packard Development Company, L.P.
+# Copyright (c) 2009-2021 Ivan Maidanski
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program
+# for any purpose,  provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is granted,
+# provided the above notices are retained, and a notice that the code was
+# modified is included with the above copyright notice.
+
+dnl Process this file with autoconf to produce configure.
+
+dnl Initialization.
+AC_INIT(gc,8.3.0,https://github.com/ivmai/bdwgc/issues)
+dnl Version must conform to: [0-9]+[.][0-9]+[.][0-9]+
+
+AC_CONFIG_SRCDIR(gcj_mlc.c)
+AC_CONFIG_MACRO_DIR([m4])
+AC_CANONICAL_TARGET
+AC_PREREQ(2.61)
+GC_SET_VERSION
+AM_INIT_AUTOMAKE([foreign nostdinc subdir-objects])
+AC_CONFIG_HEADERS([include/config.h])
+AM_MAINTAINER_MODE
+
+AC_SUBST(PACKAGE)
+AC_SUBST(GC_VERSION)
+
+AM_PROG_CC_C_O
+AC_PROG_CXX
+AM_PROG_AS
+AC_PROG_INSTALL
+LT_INIT([disable-static])
+# Only the shared libraries are produced by default, use "--enable-static"
+# option to override it.
+dnl Note: If Autoconf reports that LIBTOOL (or AC_ENABLE_SHARED, or
+dnl AC_PROG_LIBTOOL) is undefined, Libtool installation should be checked.
+
+# Special CFLAGS to use when building
+gc_cflags=""
+
+# Set to "yes" on platforms where mmap should be used instead of sbrk.
+# This will define USE_MMAP.
+gc_use_mmap=""
+
+# We should set -fexceptions if we are using gcc and might be used
+# inside something like gcj.  This is the zeroth approximation:
+if test :"$GCC": = :yes: ; then
+    gc_cflags="${gc_cflags} -fexceptions"
+else
+    case "$host" in
+      hppa*-*-hpux* )
+        if test :$GCC: != :"yes": ; then
+            gc_cflags="${gc_cflags} +ESdbgasm"
+        fi
+        # :TODO: actually we should check using Autoconf if
+        #     the compiler supports this option.
+        ;;
+    esac
+fi
+
+#   target_optspace     --enable-target-optspace ("yes", "no", "")
+case "${target_optspace}:${host}" in
+  yes:*)
+    gc_cflags="${gc_cflags} -Os"
+    ;;
+  :m32r-* | :d10v-* | :d30v-*)
+    gc_cflags="${gc_cflags} -Os"
+    ;;
+  no:* | :*)
+    # Nothing.
+    ;;
+esac
+
+# Set any host dependent compiler flags.
+case "${host}" in
+  mips-tx39-*|mipstx39-unknown-*)
+        gc_cflags="${gc_cflags} -G 0"
+        ;;
+  *)
+        ;;
+esac
+
+AC_MSG_CHECKING([for emscripten])
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#ifdef __EMSCRIPTEN__
+#error "this is emscripten"
+#endif
+]])], [emscripten=no], [emscripten=yes])
+# Note -s ASYNCIFY is required to scan the stack, ASYNCIFY_STACK_SIZE is
+# probably needed for gctest only.
+AS_IF([test "x$emscripten" = "xyes"],
+      [gc_cflags="${gc_cflags} -s ASYNCIFY -s ASYNCIFY_STACK_SIZE=128000"])
+AM_CONDITIONAL(EMSCRIPTEN, test x$emscripten = xyes)
+AC_MSG_RESULT([$emscripten])
+
+GC_CFLAGS=${gc_cflags}
+AC_SUBST(GC_CFLAGS)
+
+dnl Extra user-defined flags to pass both to C and C++ compilers.
+AC_SUBST([CFLAGS_EXTRA])
+
+AC_ARG_ENABLE(threads,
+  [AS_HELP_STRING([--enable-threads=TYPE], [choose threading package])],
+  THREADS=$enableval,
+  [ AC_MSG_CHECKING([for thread model used by GCC])
+    THREADS=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
+    if test -z "$THREADS" -o "x$emscripten" = "xyes"; then
+      THREADS=no
+    fi
+    if test "$THREADS" = "posix"; then
+      case "$host" in
+        *-*-mingw*)
+          # Adjust thread model if cross-compiling for MinGW.
+          THREADS=win32
+          ;;
+      esac
+    fi
+    AC_MSG_RESULT([$THREADS]) ])
+
+AC_ARG_ENABLE(parallel-mark,
+    [AS_HELP_STRING([--disable-parallel-mark],
+        [do not parallelize marking and free list construction])],
+    [case "$THREADS" in
+      no | none | single)
+        if test "${enable_parallel_mark}" != no; then
+          AC_MSG_ERROR([Parallel mark requires --enable-threads=x spec])
+        fi
+        ;;
+     esac]
+)
+
+AC_ARG_ENABLE(thread-local-alloc,
+    [AS_HELP_STRING([--disable-thread-local-alloc],
+        [turn off thread-local allocation optimization])],
+    [case "$THREADS" in
+      no | none | single)
+        if test "${enable_thread_local_alloc}" = yes; then
+          AC_MSG_ERROR(
+                [Thread-local allocation requires --enable-threads=x spec])
+        fi
+        ;;
+     esac])
+
+AC_ARG_ENABLE(threads-discovery,
+    [AS_HELP_STRING([--disable-threads-discovery],
+                    [disable threads discovery in GC])])
+if test "${enable_threads_discovery}" = no; then
+    AC_DEFINE([GC_NO_THREADS_DISCOVERY], 1,
+              [Disable threads discovery in GC.])
+fi
+
+AC_ARG_ENABLE(cplusplus,
+    [AS_HELP_STRING([--enable-cplusplus], [install C++ support])])
+
+dnl Features which may be selected in the following thread-detection switch.
+AH_TEMPLATE([PARALLEL_MARK], [Define to enable parallel marking.])
+AH_TEMPLATE([THREAD_LOCAL_ALLOC],
+            [Define to enable thread-local allocation optimization.])
+AH_TEMPLATE([USE_COMPILER_TLS],
+            [Define to use of compiler-support for thread-local variables.])
+
+dnl Thread selection macros.
+AH_TEMPLATE([GC_THREADS],           [Define to support platform-specific
+                                     threads.])
+AH_TEMPLATE([GC_WIN32_PTHREADS],
+                [Define to support pthreads-win32 or winpthreads.])
+
+dnl System header feature requests.
+AH_TEMPLATE([_POSIX_C_SOURCE], [The POSIX feature macro.])
+AH_TEMPLATE([_PTHREADS], [Indicates the use of pthreads (NetBSD).])
+
+dnl Win32-specific API usage controls.
+AH_TEMPLATE([GC_UNDERSCORE_STDCALL],
+        [Explicitly prefix exported/imported WINAPI symbols with '_'.])
+AH_TEMPLATE([UNICODE],
+        [Use Unicode (W) variant of Win32 API instead of ASCII (A) one.])
+
+dnl GC API symbols export control.
+AH_TEMPLATE([GC_DLL],
+        [Define to build dynamic libraries with only API symbols exposed.])
+
+dnl Check for a flavor of supported inline keyword.
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS $CFLAGS_EXTRA"
+AC_C_INLINE
+CFLAGS="$old_CFLAGS"
+
+THREADDLLIBS=
+need_atomic_ops_asm=false
+use_parallel_mark=no
+use_thread_local_alloc=no
+# Libraries needed to support dynamic loading and/or threads.
+case "$THREADS" in
+ no | none | single)
+    THREADS=none
+    ;;
+ posix | pthreads)
+    THREADS=posix
+    default_threadlibs=false
+    # Common defines for most POSIX platforms.
+    case "$host" in
+      *-*-aix* | *-*-android* | *-*-cygwin* | *-*-darwin* | *-*-dragonfly* | \
+      *-*-freebsd* | *-*-haiku* | *-*-hpux11* | *-*-irix* | \
+      *-*-kfreebsd*-gnu | *-*-gnu* | *-*-*linux* | *-*-msys* | *-*-nacl* | \
+      *-*-netbsd* | *-*-openbsd* | *-*-osf* | *-*-solaris*)
+        AC_DEFINE(GC_THREADS)
+        AC_DEFINE([_REENTRANT], [1],
+                  [Required define if using POSIX threads.])
+        use_parallel_mark=$enable_parallel_mark
+        use_thread_local_alloc=$enable_thread_local_alloc
+        default_threadlibs=true
+        AC_MSG_WARN("Explicit GC_INIT() calls may be required.")
+        ;;
+    esac
+    AC_CHECK_LIB(pthread, pthread_self, THREADDLLIBS="-lpthread",,)
+    case "$host" in
+      *-*-hpux11*)
+        AC_MSG_WARN("Only HP/UX 11 POSIX threads are supported.")
+        AC_DEFINE(_POSIX_C_SOURCE,199506L)
+        THREADDLLIBS="-lpthread -lrt"
+        # HPUX needs REENTRANT for the _r calls.
+        ;;
+      *-*-openbsd*)
+        AM_CFLAGS="$AM_CFLAGS -pthread"
+        THREADDLLIBS=-pthread
+        ;;
+      *-*-freebsd*)
+        AM_CFLAGS="$AM_CFLAGS -pthread"
+        ;;
+      *-*-kfreebsd*-gnu)
+        AM_CFLAGS="$AM_CFLAGS -pthread"
+        THREADDLLIBS=-pthread
+        ;;
+      *-*-gnu*) # E.g. linux but excluding kfreebsd.
+        # The default THREADDLLIBS.
+        ;;
+      *-*-netbsd*)
+        AC_MSG_WARN("Only on NetBSD 2.0 or later.")
+        AC_DEFINE(_PTHREADS)
+        THREADDLLIBS="-lpthread -lrt"
+        ;;
+      *-*-solaris*)
+        THREADDLLIBS="-lpthread -lrt"
+        ;;
+      *-*-cygwin* | *-*-msys*)
+        # Cygwin doesn't have a real libpthread, so Libtool can't link
+        # against it.
+        THREADDLLIBS=""
+        win32_threads=true
+        ;;
+      *-*-mingw*)
+        AC_DEFINE(GC_WIN32_PTHREADS)
+        # Using pthreads-win32 (or other non-Cygwin pthreads) library.
+        THREADDLLIBS="-lpthread"
+        use_parallel_mark=$enable_parallel_mark
+        use_thread_local_alloc=$enable_thread_local_alloc
+        win32_threads=true
+        ;;
+      *-*-darwin*)
+        darwin_threads=true
+        ;;
+      *-*-osf*)
+        AM_CFLAGS="$AM_CFLAGS -pthread"
+        THREADDLLIBS="-lpthread -lrt"
+        ;;
+      *)
+        AS_IF([test x$default_threadlibs != xtrue],
+              [ AC_MSG_ERROR(
+                    [Pthreads not supported by the GC on this platform]) ])
+        # The default THREADDLLIBS.
+        ;;
+    esac
+    case "$host" in
+      sparc*-*-solaris*)
+        if test "$GCC" != yes; then
+          need_atomic_ops_asm=true
+        fi
+        ;;
+    esac
+    ;;
+ mcf | win32)
+    AC_DEFINE(GC_THREADS)
+    use_parallel_mark=$enable_parallel_mark
+    if test "${enable_parallel_mark}" != no \
+            -o "${enable_shared}" != yes -o "${enable_static}" != no; then
+      # Imply THREAD_LOCAL_ALLOC unless GC_DLL.
+      use_thread_local_alloc=$enable_thread_local_alloc
+    fi
+    if test "${enable_win32_dllmain}" = yes; then
+      AC_DEFINE(GC_INSIDE_DLL, 1,
+                [Enable Win32 DllMain-based approach of threads registering.])
+    fi
+    win32_threads=true
+    AC_DEFINE([EMPTY_GETENV_RESULTS], [1],
+              [Wine getenv may not return NULL for missing entry.])
+    ;;
+ dgux386)
+    AC_DEFINE(GC_THREADS)
+    # Use pthread GCC switch
+    THREADDLLIBS=-pthread
+    use_parallel_mark=$enable_parallel_mark
+    use_thread_local_alloc=$enable_thread_local_alloc
+    AC_MSG_WARN("Explicit GC_INIT() calls may be required.")
+    AM_CFLAGS="-pthread $AM_CFLAGS"
+    ;;
+ aix)
+    THREADS=posix
+    THREADDLLIBS=-lpthread
+    AC_DEFINE(GC_THREADS)
+    AC_DEFINE(_REENTRANT)
+    use_parallel_mark=$enable_parallel_mark
+    use_thread_local_alloc=$enable_thread_local_alloc
+    ;;
+ rtems)
+    THREADS=posix
+    AC_DEFINE(GC_THREADS)
+    use_parallel_mark=$enable_parallel_mark
+    use_thread_local_alloc=$enable_thread_local_alloc
+    ;;
+ decosf1 | irix | mach | os2 | solaris | dce | vxworks)
+    AC_MSG_ERROR(thread package $THREADS not yet supported)
+    ;;
+ *)
+    AC_MSG_ERROR($THREADS is an unknown thread package)
+    ;;
+esac
+AC_SUBST(THREADDLLIBS)
+AM_CONDITIONAL(THREADS, test x$THREADS != xnone)
+AM_CONDITIONAL(PTHREADS, test x$THREADS = xposix)
+AM_CONDITIONAL(DARWIN_THREADS, test x$darwin_threads = xtrue)
+AM_CONDITIONAL(WIN32_THREADS, test x$win32_threads = xtrue)
+
+compiler_suncc=no
+pthread_start_standalone=no
+case "$host" in
+  *-*-*linux*)
+      # Turn on the workaround described in pthread_start.c.
+      AS_IF([test "$THREADS" = posix], [pthread_start_standalone=yes])
+      ;;
+  powerpc-*-darwin*)
+      powerpc_darwin=true
+      ;;
+  *-*-solaris*)
+      if test "$GCC" != yes; then
+        # Solaris SunCC
+        compiler_suncc=yes
+        CFLAGS="-O $CFLAGS"
+      fi
+      ;;
+  *-*-wince*)
+      if test "$enable_gc_debug" != "no"; then
+        AC_DEFINE([GC_READ_ENV_FILE], 1,
+                  [Read environment variables from the GC 'env' file.])
+      fi
+      ;;
+esac
+AM_CONDITIONAL(PTHREAD_START_STANDALONE,
+               test x$pthread_start_standalone = xyes)
+
+if test "$GCC" = yes; then
+  # Output all warnings.
+  AC_MSG_CHECKING([whether compiler supports -Wextra])
+  old_CFLAGS="$CFLAGS"
+  CFLAGS="-Wextra $CFLAGS"
+  AC_TRY_COMPILE([],[], [ac_cv_cc_wextra=yes], [ac_cv_cc_wextra=no])
+  CFLAGS="$old_CFLAGS"
+  AC_MSG_RESULT($ac_cv_cc_wextra)
+  AS_IF([test "$ac_cv_cc_wextra" = yes], [WEXTRA="-Wextra"], [WEXTRA="-W"])
+  AC_MSG_CHECKING([whether compiler supports -Wpedantic])
+  CFLAGS="-Wpedantic -Wno-long-long $CFLAGS"
+  AC_TRY_COMPILE([],[
+    extern int quiet;
+  ], [ac_cv_cc_pedantic=yes], [ac_cv_cc_pedantic=no])
+  CFLAGS="$old_CFLAGS"
+  AC_MSG_RESULT($ac_cv_cc_pedantic)
+  WPEDANTIC=
+  AS_IF([test "$ac_cv_cc_pedantic" = yes],
+        [WPEDANTIC="-Wpedantic -Wno-long-long"])
+  CFLAGS="-Wall $WEXTRA $WPEDANTIC $CFLAGS"
+  CXXFLAGS="-Wall $WEXTRA $WPEDANTIC $CXXFLAGS"
+fi
+
+AC_MSG_CHECKING(for xlc)
+AC_TRY_COMPILE([],[
+ #ifndef __xlC__
+ # error
+ #endif
+], [compiler_xlc=yes], [compiler_xlc=no])
+AC_MSG_RESULT($compiler_xlc)
+if test $compiler_xlc = yes -a "$powerpc_darwin" = true; then
+  # the darwin stack-frame-walking code is completely broken on xlc
+  AC_DEFINE([DARWIN_DONT_PARSE_STACK], 1, [See doc/README.macros.])
+fi
+
+# XLC neither requires nor tolerates the unnecessary assembler goop.
+# Similar for the Sun C compiler.
+AM_CONDITIONAL([ASM_WITH_CPP_UNSUPPORTED],
+    [test $compiler_xlc = yes -o $compiler_suncc = yes])
+
+if test "$GCC" = yes; then
+  # Disable aliasing optimization unless forced to.
+  AC_MSG_CHECKING([whether compiler supports -fno-strict-aliasing])
+  ac_cv_fno_strict_aliasing=no
+  for cflag in $CFLAGS; do
+    case "$cflag" in
+      -fstrict-aliasing)
+        # Opposite option already present
+        ac_cv_fno_strict_aliasing=skipped
+        break
+        ;;
+    esac
+  done
+  if test "$ac_cv_fno_strict_aliasing" != skipped; then
+    old_CFLAGS="$CFLAGS"
+    CFLAGS="$CFLAGS -fno-strict-aliasing"
+    AC_TRY_COMPILE([],[], [ac_cv_fno_strict_aliasing=yes], [])
+    CFLAGS="$old_CFLAGS"
+    AS_IF([test "$ac_cv_fno_strict_aliasing" = yes],
+          [CFLAGS="$CFLAGS -fno-strict-aliasing"], [])
+  fi
+  AC_MSG_RESULT($ac_cv_fno_strict_aliasing)
+fi
+
+# Check for getcontext (uClibc can be configured without it, for example)
+AC_CHECK_FUNC([getcontext], [],
+    [ AC_DEFINE([NO_GETCONTEXT], [1], [Missing getcontext function.]) ])
+
+# Check whether dl_iterate_phdr exists (as a strong symbol).
+AC_CHECK_FUNCS([dl_iterate_phdr])
+
+case "$host" in
+# While IRIX 6 has libdl for the O32 and N32 ABIs, it's missing for N64
+# and unnecessary everywhere.
+  mips-sgi-irix6*) ;;
+# We never want libdl on darwin. It is a fake libdl that just ends up making
+# dyld calls anyway.  The same applies to Cygwin.
+  *-*-cygwin* | *-*-darwin* | *-*-msys*)
+    ;;
+  *)
+    AC_CHECK_LIB(dl, dlopen, THREADDLLIBS="$THREADDLLIBS -ldl")
+    ;;
+esac
+
+case "$host" in
+  *-*-hpux*)
+    avoid_cpp_lib=yes;;
+  *)
+    avoid_cpp_lib=no;
+    ;;
+esac
+AM_CONDITIONAL(AVOID_CPP_LIB,test $avoid_cpp_lib = yes)
+
+# Check for various headers.
+AC_CHECK_HEADER([execinfo.h], [],
+    [ AC_DEFINE([GC_MISSING_EXECINFO_H], [1], [Missing execinfo.h header.]) ])
+
+# extra LD Flags which are required for targets
+case "${host}" in
+  *-*-darwin*)
+    extra_ldflags_libgc=-Wl,-single_module
+    ;;
+esac
+AC_SUBST(extra_ldflags_libgc)
+
+AC_SUBST(EXTRA_TEST_LIBS)
+
+target_all=libgc.la
+AC_SUBST(target_all)
+
+dnl If the target is an eCos system, use the appropriate eCos
+dnl I/O routines.
+dnl FIXME: this should not be a local option but a global target
+dnl system; at present there is no eCos target.
+TARGET_ECOS="no"
+AC_ARG_WITH(ecos,
+[  --with-ecos             enable runtime eCos target support],
+TARGET_ECOS="$with_ecos"
+)
+
+addobjs=
+addlibs=
+CXXLIBS=
+
+case "$TARGET_ECOS" in
+   no)
+      ;;
+   *)
+      AC_DEFINE([ECOS], 1, [Define to enable eCos target support.])
+      AM_CPPFLAGS="-I${TARGET_ECOS}/include $AM_CPPFLAGS"
+      addobjs="$addobjs ecos.lo"
+      ;;
+esac
+
+AM_CONDITIONAL(CPLUSPLUS, test "${enable_cplusplus}" = yes)
+
+AC_ARG_ENABLE(throw-bad-alloc-library,
+    [AS_HELP_STRING([--disable-throw-bad-alloc-library],
+                    [do not build C++ gctba library])])
+AM_CONDITIONAL(GC_TBA_LIBRARY,
+               test "${enable_cplusplus}" = yes \
+                    -a "${enable_throw_bad_alloc_library}" != no)
+
+if test "$GCC" = yes; then
+  if test "${enable_cplusplus}" = yes; then
+    case "$host" in
+      *-*-cygwin* | *-*-mingw* | *-*-msys*)
+        AC_MSG_CHECKING([whether libsupc++ required])
+        SUPC="`$CXX -print-file-name=libsupc++.a 2>/dev/null`"
+        if test -n "$SUPC" -a "$SUPC" != "libsupc++.a"; then
+          AC_MSG_RESULT(yes)
+          CXXLIBS="-lsupc++"
+        else
+          AC_MSG_RESULT(no)
+        fi
+        ;;
+    esac
+  fi
+fi
+
+AC_SUBST(CXX)
+AC_SUBST(AM_CFLAGS)
+AC_SUBST(AM_CPPFLAGS)
+AC_SUBST(CXXLIBS)
+
+# Configuration of shared libraries
+#
+AC_MSG_CHECKING(whether to build shared libraries)
+AC_ENABLE_SHARED
+
+case "$host" in
+ alpha-*-openbsd*)
+     enable_shared=no
+     ;;
+ *)
+     ;;
+esac
+
+AC_MSG_RESULT($enable_shared)
+
+# Compile with GC_DLL defined unless building static libraries.
+if test "${enable_shared}" != no -a "${enable_static}" != yes; then
+    AC_DEFINE(GC_DLL)
+    if test "$GCC" = yes; then
+      # Pass -fvisibility=hidden option if supported
+      AC_MSG_CHECKING([whether compiler supports -fvisibility])
+      old_CFLAGS="$CFLAGS"
+      CFLAGS="-Werror -fvisibility=hidden $CFLAGS"
+      AC_TRY_COMPILE([],[], [ac_cv_fvisibility_hidden=yes],
+                     [ac_cv_fvisibility_hidden=no])
+      CFLAGS="$old_CFLAGS"
+      AS_IF([test "$ac_cv_fvisibility_hidden" = yes],
+            [CFLAGS="-DGC_VISIBILITY_HIDDEN_SET -fvisibility=hidden $CFLAGS"],
+            [CFLAGS="-DGC_NO_VISIBILITY $CFLAGS"])
+      AC_MSG_RESULT($ac_cv_fvisibility_hidden)
+    fi
+else
+
+  case "$host" in
+    *-*-cygwin* | *-*-mingw* | *-*-msys*)
+      # Do not require the clients to link with "user32" system library.
+      AC_DEFINE([DONT_USE_USER32_DLL], 1,
+                [Do not use user32.dll import library (Win32).])
+      # Use inline version of GC new and delete operators in test_cpp
+      # otherwise the system ones might be used instead because of arbitrary
+      # ordering of object files when linking.
+      CXXFLAGS="$CXXFLAGS -DGC_NOT_DLL"
+      ;;
+  esac
+fi
+
+# Configuration of machine-dependent code
+#
+AC_MSG_CHECKING(which machine-dependent code should be used)
+machdep=
+case "$host" in
+ alpha-*-openbsd*)
+    if test x"${ac_cv_lib_dl_dlopen}" != xyes ; then
+       AC_MSG_WARN(
+         "OpenBSD/Alpha without dlopen(). Shared library support is disabled.")
+    fi
+    ;;
+ i?86-*-solaris2.[[89]])
+    # PROC_VDB appears to work in 2.8 and 2.9 but not in 2.10+ (for now).
+    AC_DEFINE([SOLARIS25_PROC_VDB_BUG_FIXED], 1,
+              [See the comment in gcconfig.h.])
+    ;;
+ sparc-*-netbsd*)
+    machdep="sparc_netbsd_mach_dep.lo"
+    ;;
+ sparc*-*-linux* | sparc*-*-openbsd* | sparc64-*-freebsd* | sparc64-*-netbsd*)
+    machdep="sparc_mach_dep.lo"
+    ;;
+ sparc-sun-solaris2.3)
+    machdep="sparc_mach_dep.lo"
+    AC_DEFINE(SUNOS53_SHARED_LIB, 1,
+              [Define to work around a Solaris 5.3 bug (see dyn_load.c).])
+    ;;
+ sparc*-sun-solaris2*)
+    machdep="sparc_mach_dep.lo"
+    ;;
+ ia64-*-*)
+    machdep="ia64_save_regs_in_stack.lo"
+    ;;
+esac
+AC_MSG_RESULT($machdep)
+addobjs="$addobjs $machdep"
+AC_SUBST(addobjs)
+AC_SUBST(addlibs)
+
+AC_PROG_LIBTOOL
+
+dnl We use these options to decide which functions to include.
+AC_ARG_WITH(target-subdir,
+[  --with-target-subdir=SUBDIR
+                          configuring with a cross compiler])
+AC_ARG_WITH(cross-host,
+[  --with-cross-host=HOST  configuring with a cross compiler])
+
+dnl automake wants to see AC_EXEEXT.  But we don't need it.  And having
+dnl it is actually a problem, because the compiler we're passed can't
+dnl necessarily do a full link.  So we fool automake here.
+if false; then
+  dnl autoconf 2.50 runs AC_EXEEXT by default, and the macro expands
+  dnl to nothing, so nothing would remain between `then' and `fi' if it
+  dnl were not for the `:' below.
+  :
+  AC_EXEEXT
+fi
+
+dnl The collector might not properly work on IBM AIX when
+dnl built with gcc and -O.  So we remove -O in the appropriate case.
+AC_MSG_CHECKING(whether AIX gcc optimization fix is necessary)
+case "$host" in
+ *aix*)
+    if test "$GCC" = yes; then
+       AC_MSG_RESULT(yes)
+       new_CFLAGS=
+       for i in $CFLAGS; do
+          case "$i" in
+           -O*)
+              ;;
+           *)
+              new_CFLAGS="$new_CFLAGS $i"
+              ;;
+          esac
+       done
+       CFLAGS="$new_CFLAGS"
+    else
+       AC_MSG_RESULT(no)
+    fi
+    ;;
+ *) AC_MSG_RESULT(no) ;;
+esac
+
+dnl Include defines that have become de facto standard.
+dnl ALL_INTERIOR_POINTERS and NO_EXECUTE_PERMISSION can be overridden
+dnl in the startup code.
+AC_DEFINE([NO_EXECUTE_PERMISSION], [1],
+          [Define to make the collector not allocate executable memory
+           by default.])
+AC_DEFINE([ALL_INTERIOR_POINTERS], [1],
+          [Define to recognise all pointers to the interior of objects.])
+
+
+dnl Interface Selection
+dnl -------------------
+dnl
+dnl By default, make the library as general as possible.
+AC_ARG_ENABLE(gcj-support,
+    [AS_HELP_STRING([--disable-gcj-support], [disable support for gcj])])
+if test x"$enable_gcj_support" != xno; then
+    AC_DEFINE(GC_GCJ_SUPPORT, 1, [Define to include support for gcj.])
+    case "$host" in
+      *-*-kfreebsd*-gnu)
+        # FIXME: For a reason, gctest hangs up on kFreeBSD if both of
+        # THREAD_LOCAL_ALLOC and GC_ENABLE_SUSPEND_THREAD are defined.
+        if test "${enable_thread_local_alloc}" = no; then
+          AC_DEFINE(GC_ENABLE_SUSPEND_THREAD)
+        fi
+        ;;
+      *)
+        AC_DEFINE([GC_ENABLE_SUSPEND_THREAD], 1,
+              [Define to turn on GC_suspend_thread support.])
+        ;;
+    esac
+fi
+AM_CONDITIONAL(ENABLE_GCJ_SUPPORT, [test x"enable_gcj_support" != xno])
+
+dnl Interaction with other programs that might use signals.
+AC_ARG_ENABLE(sigrt-signals,
+    [AS_HELP_STRING([--enable-sigrt-signals],
+        [force GC to use SIGRTMIN-based signals for thread suspend/resume])])
+if test x"${enable_sigrt_signals}" = xyes; then
+    AC_DEFINE([GC_USESIGRT_SIGNALS], 1,
+              [Force the GC to use signals based on SIGRTMIN+k.])
+fi
+
+
+dnl Debugging
+dnl ---------
+
+AH_TEMPLATE([GC_HAVE_BUILTIN_BACKTRACE],
+            [Define if backtrace information is supported.])
+AH_TEMPLATE([MAKE_BACK_GRAPH], [See doc/README.macros.])
+AH_TEMPLATE([SAVE_CALL_COUNT],
+            [The number of caller frames saved when allocating with the
+             debugging API.])
+UNWINDLIBS=
+AC_ARG_ENABLE(gc-debug,
+              [AS_HELP_STRING([--enable-gc-debug],
+                    [include full support for pointer backtracing etc.])],
+[ if test "$enable_gc_debug" = "yes"; then
+    AC_MSG_WARN("Should define GC_DEBUG and use debug alloc in clients.")
+    AC_DEFINE([KEEP_BACK_PTRS], 1,
+              [Define to save back-pointers in debugging headers.])
+    keep_back_ptrs=true
+    AC_DEFINE([DBG_HDRS_ALL], 1,
+              [Define to force debug headers on all objects.])
+    AH_TEMPLATE([SHORT_DBG_HDRS],
+                [Shorten the headers to minimize object size at the expense
+                 of checking for writes past the end (see doc/README.macros).])
+
+    case $host in
+      ia64-*-linux* )
+        AC_DEFINE(MAKE_BACK_GRAPH)
+        AC_DEFINE(SAVE_CALL_COUNT, 8)
+        AC_CHECK_LIB(unwind, backtrace, [
+          AC_DEFINE(GC_HAVE_BUILTIN_BACKTRACE)
+          UNWINDLIBS=-lunwind
+          AC_MSG_WARN("Client code may need to link against libunwind.")
+        ])
+      ;;
+      x86-*-linux* | i586-*-linux* | i686-*-linux* | x86_64-*-linux* )
+        AC_DEFINE(MAKE_BACK_GRAPH)
+        AC_MSG_WARN("Client must not use -fomit-frame-pointer.")
+        AC_DEFINE(SAVE_CALL_COUNT, 8)
+      ;;
+      i[3456]86-*-dgux*)
+        AC_DEFINE(MAKE_BACK_GRAPH)
+      ;;
+    esac ]
+  fi)
+AM_CONDITIONAL([MAKE_BACK_GRAPH], [test x"$enable_gc_debug" = xyes])
+AM_CONDITIONAL([KEEP_BACK_PTRS], [test x"$keep_back_ptrs" = xtrue])
+
+# Check whether a compiler warning of unsafe __builtin_return_address(1)
+# could be suppressed by -Wno-frame-address option.
+# __builtin_return_address(1) is used by libgc for debugging purposes only.
+AC_MSG_CHECKING([whether -Wno-frame-address works])
+use_wno_error_frame_address=no
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -Werror -Wno-frame-address $CFLAGS_EXTRA"
+AC_TRY_COMPILE([], [{
+    if (!__builtin_return_address(1)) return 1;
+}], [ use_wno_error_frame_address=yes ])
+CFLAGS="$old_CFLAGS"
+AC_MSG_RESULT($use_wno_error_frame_address)
+if test x"$use_wno_error_frame_address" = xyes; then
+  CFLAGS="$CFLAGS -Wno-frame-address"
+fi
+
+# Check for dladdr (used for debugging).
+AC_MSG_CHECKING(for dladdr)
+have_dladdr=no
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS $CFLAGS_EXTRA"
+AC_TRY_COMPILE([
+#define _GNU_SOURCE 1
+#include <dlfcn.h>], [{
+    Dl_info info;
+    (void)dladdr("", &info);
+}], [ have_dladdr=yes ])
+CFLAGS="$old_CFLAGS"
+AC_MSG_RESULT($have_dladdr)
+if test x"$have_dladdr" = xyes; then
+  AC_DEFINE([HAVE_DLADDR], 1, [Define to use 'dladdr' function.])
+fi
+
+# sigsetjmp could be a macro (thus AC_CHECK_FUNCS cannot be used).
+AC_MSG_CHECKING(for sigsetjmp)
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS $CFLAGS_EXTRA"
+AC_TRY_LINK([#include <setjmp.h>],
+            [sigjmp_buf t; sigsetjmp(t, 0)],
+  [AC_MSG_RESULT(yes)],
+  [AC_MSG_RESULT(no)
+   AC_DEFINE([GC_NO_SIGSETJMP], [1], [Missing sigsetjmp function.])])
+CFLAGS="$old_CFLAGS"
+
+# pthread_setname_np, if available, may have 1, 2 or 3 arguments.
+AS_IF([test "$THREADS" = posix],
+  [AC_MSG_CHECKING(for pthread_setname_np)
+   old_CFLAGS="$CFLAGS"
+   CFLAGS="$CFLAGS $CFLAGS_EXTRA -Werror"
+   AC_TRY_COMPILE([#include <pthread.h>],
+                  [pthread_setname_np("thread-name")],
+     [AC_MSG_RESULT([yes (w/o tid)])
+      AC_DEFINE([HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID], [1],
+                [Define to use 'pthread_setname_np(const char*)' function.])],
+     [AC_TRY_COMPILE([#include <pthread.h>],
+                     [pthread_setname_np(pthread_self(), "thread-name-%u", 0)],
+       [AC_MSG_RESULT([yes (with tid and arg)])
+        AC_DEFINE([HAVE_PTHREAD_SETNAME_NP_WITH_TID_AND_ARG], [1],
+         [Define to use 'pthread_setname_np(pthread_t, const char*, void *)'
+          function.])],
+       [AC_TRY_COMPILE([
+#ifdef __CYGWIN__
+#define _GNU_SOURCE 1
+#elif defined(__linux__) || defined(__GLIBC__) || defined(__GNU__)
+#define _GNU_SOURCE 1
+#endif
+#include <pthread.h>],
+         [pthread_setname_np(pthread_self(), "thread-name")],
+         [AC_MSG_RESULT([yes (with tid)])
+          AC_DEFINE([HAVE_PTHREAD_SETNAME_NP_WITH_TID], [1],
+                    [Define to use 'pthread_setname_np(pthread_t, const char*)'
+                     function.])],
+         [AC_MSG_RESULT(no)])])])
+   CFLAGS="$old_CFLAGS"])
+
+# Check for AViiON Machines running DGUX
+ac_is_dgux=no
+AC_CHECK_HEADER(sys/dg_sys_info.h,
+[ac_is_dgux=yes;])
+
+dnl :GOTCHA: we do not check anything but sys/dg_sys_info.h
+if test $ac_is_dgux = yes; then
+    dgux_spec_opts="-DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
+    CFLAGS="$dgux_spec_opts $CFLAGS"
+    CXXFLAGS="$dgux_spec_opts $CXXFLAGS"
+    if test "$enable_gc_debug" = "yes"; then
+      CFLAGS="-g -mstandard $CFLAGS"
+      CXXFLAGS="-g -mstandard $CXXFLAGS"
+    fi
+    AC_SUBST(CFLAGS)
+    AC_SUBST(CXXFLAGS)
+fi
+
+AC_ARG_ENABLE(java-finalization,
+    [AS_HELP_STRING([--disable-java-finalization],
+                    [disable support for java finalization])])
+if test x"$enable_java_finalization" != xno; then
+    AC_DEFINE([JAVA_FINALIZATION], 1, [See doc/README.macros.])
+fi
+
+AC_ARG_ENABLE(atomic-uncollectable,
+    [AS_HELP_STRING([--disable-atomic-uncollectible],
+                    [disable support for atomic uncollectible allocation])])
+if test x"$enable_atomic_uncollectible" != x"no"; then
+    AC_DEFINE([GC_ATOMIC_UNCOLLECTABLE], 1,
+        [Define to enable atomic uncollectible allocation.])
+fi
+
+AC_ARG_ENABLE(redirect-malloc,
+    [AS_HELP_STRING([--enable-redirect-malloc],
+                    [redirect malloc and friends to GC routines])])
+
+if test "${enable_redirect_malloc}" = yes; then
+    if test "${enable_gc_debug}" = yes; then
+        AC_DEFINE([REDIRECT_MALLOC], GC_debug_malloc_replacement,
+                  [If defined, redirect malloc to this function.])
+        AC_DEFINE([REDIRECT_REALLOC], GC_debug_realloc_replacement,
+                  [If defined, redirect GC_realloc to this function.])
+        AC_DEFINE([REDIRECT_FREE], GC_debug_free,
+                  [If defined, redirect free to this function.])
+    else
+        AC_DEFINE(REDIRECT_MALLOC, GC_malloc)
+    fi
+    AC_DEFINE([GC_USE_DLOPEN_WRAP], 1, [See doc/README.macros.])
+fi
+
+AC_ARG_ENABLE(disclaim,
+    [AS_HELP_STRING([--disable-disclaim],
+        [disable alternative (more efficient) finalization interface])])
+if test x"$enable_disclaim" != xno; then
+    AC_DEFINE(ENABLE_DISCLAIM, 1,
+        [Define to enable alternative finalization interface.])
+fi
+AM_CONDITIONAL(ENABLE_DISCLAIM,
+    [test x"$enable_disclaim" != xno])
+
+AC_ARG_ENABLE(large-config,
+    [AS_HELP_STRING([--enable-large-config],
+        [optimize for large (> 100 MB) heap or root set])])
+if test "${enable_large_config}" = yes; then
+    AC_DEFINE(LARGE_CONFIG, 1,
+              [Define to optimize for large heaps or root sets.])
+fi
+
+dnl This is something of a hack.  When cross-compiling we turn off
+dnl some functionality.  We also enable the "small" configuration.
+dnl These is only correct when targeting an embedded system.  FIXME.
+if test -n "${with_cross_host}"; then
+   AC_DEFINE([NO_CLOCK], 1, [Define to not use system clock (cross compiling).])
+   AC_DEFINE([SMALL_CONFIG], 1,
+             [Define to tune the collector for small heap sizes.])
+fi
+
+if test "$enable_gc_debug" = "no"; then
+   AC_DEFINE([NO_DEBUGGING], 1,
+             [Disable debugging, like GC_dump and its callees.])
+fi
+
+AC_SUBST(UNWINDLIBS)
+
+AC_ARG_ENABLE(gc-assertions,
+    [AS_HELP_STRING([--enable-gc-assertions],
+        [collector-internal assertion checking])])
+if test "${enable_gc_assertions}" = yes; then
+    AC_DEFINE([GC_ASSERTIONS], 1,
+              [Define to enable internal debug assertions.])
+fi
+
+AC_ARG_ENABLE(mmap,
+    [AS_HELP_STRING([--enable-mmap],
+                    [use mmap instead of sbrk to expand the heap])],
+    gc_use_mmap=$enableval)
+
+AC_ARG_ENABLE(munmap,
+    [AS_HELP_STRING([--enable-munmap=N],
+                    [return page to the OS if empty for N collections
+                     (default: 6)])],
+    MUNMAP_THRESHOLD=$enableval)
+if test x$enable_munmap != xno; then
+    AC_DEFINE([USE_MMAP], 1,
+              [Define to use mmap instead of sbrk to expand the heap.])
+    AH_TEMPLATE([USE_WINALLOC],
+                  [Define to use Win32 VirtualAlloc (instead of sbrk or
+                   mmap) to expand the heap.])
+    AC_DEFINE([USE_MUNMAP], 1,
+              [Define to return memory to OS with munmap calls
+               (see doc/README.macros).])
+    if test x$MUNMAP_THRESHOLD = x -o x$MUNMAP_THRESHOLD = xyes; then
+      MUNMAP_THRESHOLD=6
+    fi
+    AC_DEFINE_UNQUOTED([MUNMAP_THRESHOLD], [${MUNMAP_THRESHOLD}],
+        [Number of GC cycles to wait before unmapping an unused block.])
+else
+    if test "${gc_use_mmap}" = "yes"; then
+      AC_DEFINE([USE_MMAP], 1,
+                [Define to use mmap instead of sbrk to expand the heap.])
+    fi
+fi
+
+AC_ARG_ENABLE(dynamic-loading,
+    [AS_HELP_STRING([--disable-dynamic-loading],
+                    [build the collector with disabled tracing
+                     of dynamic library data roots])])
+if test "${enable_dynamic_loading}" = "no"; then
+  AC_DEFINE([IGNORE_DYNAMIC_LOADING], 1,
+            [Do not define DYNAMIC_LOADING even if supported (i.e., build the
+             collector with disabled tracing of dynamic library data roots).])
+fi
+
+AC_ARG_ENABLE(register-main-static-data,
+    [AS_HELP_STRING([--disable-register-main-static-data],
+                    [skip the initial guess of data root sets])])
+if test "${enable_register_main_static_data}" = "no"; then
+    AC_DEFINE([GC_DONT_REGISTER_MAIN_STATIC_DATA], 1,
+              [Skip the initial guess of data root sets.])
+fi
+
+AC_ARG_ENABLE(checksums,
+    [AS_HELP_STRING([--enable-checksums],
+                    [report on erroneously cleared dirty bits at
+                     substantial performance cost; use only for
+                     debugging of the incremental collector])])
+if test x$enable_checksums = xyes; then
+    if test x$enable_munmap != xno -o x$THREADS != xnone; then
+        AC_MSG_ERROR([CHECKSUMS not compatible with USE_MUNMAP or threads])
+    fi
+    AC_DEFINE([CHECKSUMS], 1,
+              [Erroneously cleared dirty bits checking.  Use only for
+               debugging of the incremental collector.])
+fi
+AM_CONDITIONAL([CHECKSUMS], test x$enable_checksums = xyes)
+
+AM_CONDITIONAL(USE_LIBDIR, test -z "$with_cross_host")
+
+AC_ARG_ENABLE(werror,
+    [AS_HELP_STRING([--enable-werror], [pass -Werror to the C compiler])],
+    werror_flag=$enableval, werror_flag=no)
+if test x$werror_flag = xyes; then
+    WERROR_CFLAGS="-Werror"
+    case "$host" in
+      # _dyld_bind_fully_image_containing_address is deprecated in OS X 10.5+
+      *-*-darwin*)
+        WERROR_CFLAGS="$WERROR_CFLAGS -Wno-deprecated-declarations"
+        ;;
+    esac
+fi
+AC_SUBST([WERROR_CFLAGS])
+
+AC_ARG_ENABLE(single-obj-compilation,
+    [AS_HELP_STRING([--enable-single-obj-compilation],
+                    [compile all libgc source files into single .o
+                     (default: yes if static libraries are disabled)])],
+    [], [ AS_IF([test x"$enable_static" = xno],
+                [enable_single_obj_compilation=yes]) ])
+AM_CONDITIONAL([SINGLE_GC_OBJ],
+               [test x"$enable_single_obj_compilation" = xyes])
+
+AC_ARG_ENABLE(gcov,
+    [AS_HELP_STRING([--enable-gcov], [turn on code coverage analysis])])
+if test "$enable_gcov" = "yes"; then
+  CFLAGS="-D NTHREADS=20 $CFLAGS --coverage"
+  if test "${enable_shared}" = no; then
+    # FIXME: As of g++-4.8.4/x86_64, in case of shared library build, test_cpp
+    # linkage fails with "hidden symbol atexit is referenced by DSO" message.
+    CXXFLAGS="$CXXFLAGS --coverage"
+  fi
+  # Turn off optimization to get accurate line numbers.
+  CFLAGS=`echo "$CFLAGS" | sed -e 's/-O\(1\|2\|3\|4\|s\|fast\)\?//g'`
+  CXXFLAGS=`echo "$CXXFLAGS" | sed -e 's/-O\(1\|2\|3\|4\|s\|fast\)\?//g'`
+fi
+
+AC_ARG_ENABLE(docs,
+        [AS_HELP_STRING([--disable-docs],
+                        [do not build and install documentation])])
+AM_CONDITIONAL(ENABLE_DOCS, test x$enable_docs != xno)
+
+AM_CONDITIONAL(ENABLE_SHARED, test x$enable_shared = xyes)
+
+# Atomic Ops
+# ----------
+
+# Do we want to use an external libatomic_ops?  By default use it if it's
+# found.
+AC_ARG_WITH([libatomic-ops],
+    [AS_HELP_STRING([--with-libatomic-ops[=yes|no|check|none]],
+                    [Use an external libatomic_ops? (default: check;
+                     none: use compiler intrinsics or no thread support)])],
+    [], [ AS_IF([test x"$THREADS" != xnone],
+                [with_libatomic_ops=check], [with_libatomic_ops=none]) ])
+
+# Check whether compiler atomic intrinsics can be used.
+if test x"$with_libatomic_ops" = xcheck; then
+  AC_MSG_CHECKING(for compiler intrinsics support)
+  old_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS $CFLAGS_EXTRA -DGC_BUILTIN_ATOMIC"
+  CFLAGS="$CFLAGS -I${srcdir}/include -I${srcdir}/tests"
+  AC_TRY_RUN([#include "test_atomic_ops.c"],
+    [AC_MSG_RESULT(yes)
+     with_libatomic_ops=none],
+    [AC_MSG_RESULT(no)], [AC_MSG_RESULT(skipped because cross-compiling)])
+  CFLAGS="$old_CFLAGS"
+fi
+
+# Check for an external libatomic_ops if the above answer is "yes" or "check".
+# If not found, fail on "yes", and convert "check" to "no".
+# First, check that libatomic_ops usage is not disabled explicitly.
+missing_libatomic_ops=false
+AS_IF([test x"$with_libatomic_ops" != xno -a x"$with_libatomic_ops" != xnone],
+  [ missing_libatomic_ops=true ])
+
+dnl To avoid "syntax error near unexpected token ATOMIC_OPS" configure error
+dnl observed by some clients, the following 3 code lines are commented out:
+dnl
+dnl AS_IF([test x$missing_libatomic_ops = xtrue],
+dnl  [ PKG_CHECK_MODULES([ATOMIC_OPS], [atomic_ops],
+dnl    [ missing_libatomic_ops=false ], [ [] ]) ])
+
+dnl Retry with AC_CHECK_HEADER if PKG_CHECK_MODULES failed.
+AS_IF([test x$missing_libatomic_ops = xtrue],
+      [ AC_CHECK_HEADER([atomic_ops.h], [missing_libatomic_ops=false]) ])
+AS_IF([test x$missing_libatomic_ops = xtrue],
+      [ AS_IF([test x"$with_libatomic_ops" != xcheck],
+              [ AC_MSG_ERROR([An external libatomic_ops was not found]) ])
+        with_libatomic_ops=no ])
+
+# If we have neither an external or an internal version, offer a useful hint
+# and exit.
+AS_IF([test x"$with_libatomic_ops" = xno \
+            -a ! -e "$srcdir/libatomic_ops/src/atomic_ops.h"],
+  [ AC_MSG_ERROR([libatomic_ops is required.  You can either install it on
+                  your system, or fetch and unpack a recent version into the
+                  source directory and link or rename it to libatomic_ops.]) ])
+
+# Finally, emit the definitions for bundled or external AO.
+AC_MSG_CHECKING([which libatomic_ops to use])
+AS_IF([test x"$with_libatomic_ops" != xno],
+  [ AS_IF([test x"$with_libatomic_ops" != xnone -a x"$THREADS" != xnone],
+          [ AC_MSG_RESULT([external])
+            ATOMIC_OPS_LIBS="-latomic_ops"
+            AC_SUBST([ATOMIC_OPS_LIBS]) ],
+          [ AC_MSG_RESULT([none])
+            AS_IF([test x"$THREADS" != xnone],
+                  [ AC_DEFINE([GC_BUILTIN_ATOMIC], [1],
+                              [Use GCC atomic intrinsics instead of
+                               libatomic_ops primitives.]) ]) ])
+    AO_TRYLINK_CFLAGS="" ],
+  [ AC_MSG_RESULT([internal])
+    AO_TRYLINK_CFLAGS="-I${srcdir}/libatomic_ops/src"
+    ATOMIC_OPS_CFLAGS='-I$(top_builddir)/libatomic_ops/src -I$(top_srcdir)/libatomic_ops/src'
+    ATOMIC_OPS_LIBS=""
+    AC_SUBST([ATOMIC_OPS_CFLAGS])
+    AC_CONFIG_SUBDIRS([libatomic_ops])
+  ])
+AM_CONDITIONAL([USE_INTERNAL_LIBATOMIC_OPS],
+    [test x$with_libatomic_ops = xno -a x"$THREADS" != xnone])
+AM_CONDITIONAL([NEED_ATOMIC_OPS_ASM],
+    [test x$with_libatomic_ops = xno -a x$need_atomic_ops_asm = xtrue])
+
+# Check whether particular AO primitives are emulated with locks.
+# The check below is based on the fact that linking with the libatomic_ops
+# binary file is not needed in case of absence of the emulation (except for
+# Solaris SPARC).
+AS_IF([test x$with_libatomic_ops != xnone -a x$need_atomic_ops_asm != xtrue],
+    [ old_CFLAGS="$CFLAGS"
+      CFLAGS="$CFLAGS $AO_TRYLINK_CFLAGS $CFLAGS_EXTRA"
+      AC_MSG_CHECKING([for lock-free AO_or primitive])
+      AC_TRY_LINK([#include "atomic_ops.h"],
+                  [AO_t x=0;AO_or(&x,1)],
+        [ AC_MSG_RESULT(yes)
+          AC_DEFINE([HAVE_LOCKFREE_AO_OR], [1],
+            [libatomic_ops AO_or primitive implementation is lock-free.]) ],
+        [ AC_MSG_RESULT(no) ])
+      AC_MSG_CHECKING([for lock-free AO load/store, test-and-set primitives])
+      AC_TRY_LINK([#include "atomic_ops.h"],
+ [AO_t x=0;unsigned char c=0;AO_TS_t z=AO_TS_INITIALIZER;
+  (void)AO_test_and_set_acquire(&z);AO_CLEAR(&z);AO_compiler_barrier();
+  AO_store(&x,AO_load(&x)+1);AO_char_store(&c,AO_char_load(&c)+1);
+  AO_store_release(&x,AO_load_acquire(&x)+1)],
+        [ AC_MSG_RESULT(yes) ],
+        [ AC_MSG_RESULT(no)
+          use_thread_local_alloc=no
+          AC_DEFINE([BASE_ATOMIC_OPS_EMULATED], [1],
+                    [AO load, store and/or test-and-set primitives are
+                     implemented in libatomic_ops using locks.]) ])
+      AS_IF([test x$use_parallel_mark != xno],
+        [ AC_MSG_CHECKING(
+                [for lock-free compare-and-swap and fetch-and-add primitives])
+          AC_TRY_LINK(
+ [#define AO_REQUIRE_CAS
+  #include "atomic_ops.h"],
+ [AO_t x=0;(void)AO_fetch_and_add(&x,1);(void)AO_compare_and_swap(&x,1,2)],
+                    [ AC_MSG_RESULT(yes) ],
+                    [ AC_MSG_RESULT(no)
+                      use_parallel_mark=no ]) ])
+      CFLAGS="$old_CFLAGS" ])
+
+AS_IF([test x$use_parallel_mark != xno],
+      [ AC_DEFINE(PARALLEL_MARK) ])
+AS_IF([test x$use_thread_local_alloc != xno],
+      [ AC_DEFINE(THREAD_LOCAL_ALLOC) ])
+AM_CONDITIONAL(THREAD_LOCAL_ALLOC, test x$use_thread_local_alloc != xno)
+
+AC_ARG_ENABLE(handle-fork,
+    [AS_HELP_STRING([--enable-handle-fork[=yes|no|auto|manual]],
+                    [attempt to ensure a usable collector after fork()
+                     in multi-threaded programs (default: auto;
+                     manual: GC_atfork_prepare/parent/child should be
+                     called by the client)])])
+if test "${enable_handle_fork}" = yes; then
+    AC_DEFINE(HANDLE_FORK, 1,
+              [Define to install pthread_atfork() handlers by default.])
+elif test "${enable_handle_fork}" = no; then
+    AC_DEFINE(NO_HANDLE_FORK, 1,
+              [Prohibit installation of pthread_atfork() handlers.])
+elif test "${enable_handle_fork}" != manual -a x$THREADS = xposix; then
+    # If the option is omitted, pthread_atfork handlers are installed
+    # by default for the targets where pthread_atfork is known to work.
+    case "$host" in
+      *-*-darwin*)
+        # The incremental mode conflicts with fork handling on Darwin.
+        ;;
+      *-*-aix* | *-*-android* | *-*-cygwin* | *-*-freebsd* | *-*-haiku* | \
+      *-*-hpux11* | *-*-irix* | *-*-kfreebsd*-gnu | \
+      *-*-*linux* | *-*-netbsd* | *-*-openbsd* | *-*-osf* | *-*-solaris*)
+        AC_DEFINE(HANDLE_FORK)
+        ;;
+    esac
+fi
+
+dnl Produce the Files
+dnl -----------------
+
+AC_CONFIG_FILES([Makefile bdw-gc.pc])
+
+AC_CONFIG_COMMANDS([default],,
+  [ srcdir="${srcdir}"
+    host=${host}
+    CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+    CC="${CC}"
+    DEFS="$DEFS" ])
+
+AC_OUTPUT

+ 40 - 0
blitz.mod/bdwgc/cord/cord.am

@@ -0,0 +1,40 @@
+## This file is processed with automake.
+
+# Info (current:revision:age) for the Libtool versioning system.
+# These numbers should be updated at most once just before the release,
+# and, optionally, at most once during the development (after the release).
+LIBCORD_VER_INFO = 5:0:4
+
+lib_LTLIBRARIES += libcord.la
+
+libcord_la_LIBADD = libgc.la
+libcord_la_LDFLAGS = -version-info $(LIBCORD_VER_INFO) -no-undefined
+libcord_la_CPPFLAGS = $(AM_CPPFLAGS)
+
+libcord_la_SOURCES = \
+        cord/cordbscs.c \
+        cord/cordprnt.c \
+        cord/cordxtra.c
+
+TESTS += cordtest$(EXEEXT)
+check_PROGRAMS += cordtest
+cordtest_SOURCES = cord/tests/cordtest.c
+cordtest_LDADD = $(top_builddir)/libcord.la
+
+## In case of static libraries build, libgc.a is already referenced in
+## dependency_libs attribute of libcord.la file.
+if ENABLE_SHARED
+cordtest_LDADD += $(top_builddir)/libgc.la
+endif
+
+EXTRA_DIST += \
+        cord/tests/de.c \
+        cord/tests/de_cmds.h \
+        cord/tests/de_win.c \
+        cord/tests/de_win.h \
+        cord/tests/de_win.rc
+
+pkginclude_HEADERS += \
+        include/gc/cord.h \
+        include/gc/cord_pos.h \
+        include/gc/ec.h

+ 943 - 0
blitz.mod/bdwgc/cord/cordbscs.c

@@ -0,0 +1,943 @@
+/*
+ * Copyright (c) 1993-1994 by Xerox Corporation.  All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#ifndef CORD_BUILD
+# define CORD_BUILD
+#endif
+
+# include <stdlib.h>
+# include <stdio.h>
+# include <string.h>
+
+#include "gc.h"
+#include "gc/cord.h"
+
+/* An implementation of the cord primitives.  These are the only        */
+/* Functions that understand the representation.  We perform only       */
+/* minimal checks on arguments to these functions.  Out of bounds       */
+/* arguments to the iteration functions may result in client functions  */
+/* invoked on garbage data.  In most cases, client functions should be  */
+/* programmed defensively enough that this does not result in memory    */
+/* smashes.                                                             */
+
+typedef void (* oom_fn)(void);
+
+oom_fn CORD_oom_fn = (oom_fn) 0;
+
+# define OUT_OF_MEMORY {  if (CORD_oom_fn != (oom_fn) 0) (*CORD_oom_fn)(); \
+                          ABORT("Out of memory"); }
+# define ABORT(msg) { fprintf(stderr, "%s\n", msg); abort(); }
+
+typedef unsigned long word;
+
+    struct Concatenation {
+        char null;
+        char header;
+        char depth;     /* concatenation nesting depth. */
+        unsigned char left_len;
+                        /* Length of left child if it is sufficiently   */
+                        /* short; 0 otherwise.                          */
+#           define MAX_LEFT_LEN 255
+        word len;
+        CORD left;      /* length(left) > 0     */
+        CORD right;     /* length(right) > 0    */
+    };
+
+    struct Function {
+        char null;
+        char header;
+        char depth;     /* always 0     */
+        char left_len;  /* always 0     */
+        word len;
+        CORD_fn fn;
+        void * client_data;
+    };
+
+    struct Generic {
+        char null;
+        char header;
+        char depth;
+        char left_len;
+        word len;
+    };
+
+typedef union {
+    struct Concatenation concatenation;
+    struct Function function;
+    struct Generic generic;
+    char string[1];
+} CordRep;
+
+# define CONCAT_HDR 1
+
+# define FN_HDR 4
+# define SUBSTR_HDR 6
+        /* Substring nodes are a special case of function nodes.        */
+        /* The client_data field is known to point to a substr_args     */
+        /* structure, and the function is either CORD_apply_access_fn   */
+        /* or CORD_index_access_fn.                                     */
+
+/* The following may be applied only to function and concatenation nodes: */
+#define IS_CONCATENATION(s)  (((CordRep *)s)->generic.header == CONCAT_HDR)
+
+#define IS_FUNCTION(s)  ((((CordRep *)s)->generic.header & FN_HDR) != 0)
+
+#define IS_SUBSTR(s) (((CordRep *)s)->generic.header == SUBSTR_HDR)
+
+#define LEN(s) (((CordRep *)s) -> generic.len)
+#define DEPTH(s) (((CordRep *)s) -> generic.depth)
+#define GEN_LEN(s) (CORD_IS_STRING(s) ? strlen(s) : LEN(s))
+
+#define LEFT_LEN(c) ((c) -> left_len != 0? \
+                                (c) -> left_len \
+                                : (CORD_IS_STRING((c) -> left) ? \
+                                        (c) -> len - GEN_LEN((c) -> right) \
+                                        : LEN((c) -> left)))
+
+#define SHORT_LIMIT (sizeof(CordRep) - 1)
+        /* Cords shorter than this are C strings */
+
+
+/* Dump the internal representation of x to stdout, with initial        */
+/* indentation level n.                                                 */
+void CORD_dump_inner(CORD x, unsigned n)
+{
+    size_t i;
+
+    for (i = 0; i < (size_t)n; i++) {
+        fputs("  ", stdout);
+    }
+    if (x == 0) {
+        fputs("NIL\n", stdout);
+    } else if (CORD_IS_STRING(x)) {
+        for (i = 0; i <= SHORT_LIMIT; i++) {
+            if (x[i] == '\0') break;
+            putchar(x[i]);
+        }
+        if (x[i] != '\0') fputs("...", stdout);
+        putchar('\n');
+    } else if (IS_CONCATENATION(x)) {
+        struct Concatenation * conc = &(((CordRep *)x) -> concatenation);
+
+        printf("Concatenation: %p (len: %d, depth: %d)\n",
+               (void *)x, (int)(conc -> len), (int)(conc -> depth));
+        CORD_dump_inner(conc -> left, n+1);
+        CORD_dump_inner(conc -> right, n+1);
+    } else /* function */ {
+        struct Function * func = &(((CordRep *)x) -> function);
+
+        if (IS_SUBSTR(x)) printf("(Substring) ");
+        printf("Function: %p (len: %d): ", (void *)x, (int)(func -> len));
+        for (i = 0; i < 20 && i < func -> len; i++) {
+            putchar((*(func -> fn))(i, func -> client_data));
+        }
+        if (i < func -> len) fputs("...", stdout);
+        putchar('\n');
+    }
+}
+
+/* Dump the internal representation of x to stdout      */
+void CORD_dump(CORD x)
+{
+    CORD_dump_inner(x, 0);
+    fflush(stdout);
+}
+
+CORD CORD_cat_char_star(CORD x, const char * y, size_t leny)
+{
+    size_t result_len;
+    size_t lenx;
+    int depth;
+
+    if (x == CORD_EMPTY) return(y);
+    if (leny == 0) return(x);
+    if (CORD_IS_STRING(x)) {
+        lenx = strlen(x);
+        result_len = lenx + leny;
+        if (result_len <= SHORT_LIMIT) {
+            char * result = (char *)GC_MALLOC_ATOMIC(result_len + 1);
+
+            if (result == 0) OUT_OF_MEMORY;
+#           ifdef LINT2
+                memcpy(result, x, lenx + 1);
+#           else
+                memcpy(result, x, lenx);
+                                /* No need to copy the terminating zero */
+                                /* as result[lenx] is written below.    */
+#           endif
+            memcpy(result + lenx, y, leny);
+            result[result_len] = '\0';
+            return((CORD) result);
+        } else {
+            depth = 1;
+        }
+    } else {
+        CORD right;
+        CORD left;
+        char * new_right;
+
+        lenx = LEN(x);
+
+        if (leny <= SHORT_LIMIT/2
+            && IS_CONCATENATION(x)
+            && CORD_IS_STRING(right = ((CordRep *)x) -> concatenation.right)) {
+            size_t right_len;
+
+            /* Merge y into right part of x. */
+            if (!CORD_IS_STRING(left = ((CordRep *)x) -> concatenation.left)) {
+                right_len = lenx - LEN(left);
+            } else if (((CordRep *)x) -> concatenation.left_len != 0) {
+                right_len = lenx - ((CordRep *)x) -> concatenation.left_len;
+            } else {
+                right_len = strlen(right);
+            }
+            result_len = right_len + leny;  /* length of new_right */
+            if (result_len <= SHORT_LIMIT) {
+                new_right = (char *)GC_MALLOC_ATOMIC(result_len + 1);
+                if (new_right == 0) OUT_OF_MEMORY;
+                memcpy(new_right, right, right_len);
+                memcpy(new_right + right_len, y, leny);
+                new_right[result_len] = '\0';
+                y = new_right;
+                leny = result_len;
+                x = left;
+                lenx -= right_len;
+                /* Now fall through to concatenate the two pieces: */
+            }
+            if (CORD_IS_STRING(x)) {
+                depth = 1;
+            } else {
+                depth = DEPTH(x) + 1;
+            }
+        } else {
+            depth = DEPTH(x) + 1;
+        }
+        result_len = lenx + leny;
+    }
+    {
+      /* The general case; lenx, result_len is known: */
+        struct Concatenation * result = GC_NEW(struct Concatenation);
+
+        if (NULL == result) OUT_OF_MEMORY;
+        result->header = CONCAT_HDR;
+        result->depth = (char)depth;
+        if (lenx <= MAX_LEFT_LEN)
+            result->left_len = (unsigned char)lenx;
+        result->len = (word)result_len;
+        result->left = x;
+        GC_PTR_STORE_AND_DIRTY((void *)&result->right, y);
+        GC_reachable_here(x);
+        if (depth >= MAX_DEPTH) {
+            return(CORD_balance((CORD)result));
+        } else {
+            return((CORD) result);
+        }
+    }
+}
+
+
+CORD CORD_cat(CORD x, CORD y)
+{
+    size_t result_len;
+    int depth;
+    size_t lenx;
+
+    if (x == CORD_EMPTY) return(y);
+    if (y == CORD_EMPTY) return(x);
+    if (CORD_IS_STRING(y)) {
+        return(CORD_cat_char_star(x, y, strlen(y)));
+    } else if (CORD_IS_STRING(x)) {
+        lenx = strlen(x);
+        depth = DEPTH(y) + 1;
+    } else {
+        int depthy = DEPTH(y);
+
+        lenx = LEN(x);
+        depth = DEPTH(x) + 1;
+        if (depthy >= depth) depth = depthy + 1;
+    }
+    result_len = lenx + LEN(y);
+    {
+        struct Concatenation * result = GC_NEW(struct Concatenation);
+
+        if (NULL == result) OUT_OF_MEMORY;
+        result->header = CONCAT_HDR;
+        result->depth = (char)depth;
+        if (lenx <= MAX_LEFT_LEN)
+            result->left_len = (unsigned char)lenx;
+        result->len = (word)result_len;
+        result->left = x;
+        GC_PTR_STORE_AND_DIRTY((void *)&result->right, y);
+        GC_reachable_here(x);
+        if (depth >= MAX_DEPTH) {
+            return(CORD_balance((CORD)result));
+        } else {
+            return((CORD) result);
+        }
+    }
+}
+
+
+static CordRep *CORD_from_fn_inner(CORD_fn fn, void * client_data, size_t len)
+{
+    if (len == 0) return(0);
+    if (len <= SHORT_LIMIT) {
+        char * result;
+        size_t i;
+        char buf[SHORT_LIMIT+1];
+
+        for (i = 0; i < len; i++) {
+            char c = (*fn)(i, client_data);
+
+            if (c == '\0') goto gen_case;
+            buf[i] = c;
+        }
+
+        result = (char *)GC_MALLOC_ATOMIC(len + 1);
+        if (result == 0) OUT_OF_MEMORY;
+        memcpy(result, buf, len);
+        result[len] = '\0';
+        return (CordRep *)result;
+    }
+  gen_case:
+    {
+        struct Function * result = GC_NEW(struct Function);
+
+        if (NULL == result) OUT_OF_MEMORY;
+        result->header = FN_HDR;
+        /* depth is already 0 */
+        result->len = (word)len;
+        result->fn = fn;
+        GC_PTR_STORE_AND_DIRTY(&result->client_data, client_data);
+        return (CordRep *)result;
+    }
+}
+
+CORD CORD_from_fn(CORD_fn fn, void * client_data, size_t len)
+{
+    return (/* const */ CORD) CORD_from_fn_inner(fn, client_data, len);
+}
+
+size_t CORD_len(CORD x)
+{
+    if (x == 0) {
+        return(0);
+    } else {
+        return(GEN_LEN(x));
+    }
+}
+
+struct substr_args {
+    CordRep * sa_cord;
+    size_t sa_index;
+};
+
+char CORD_index_access_fn(size_t i, void * client_data)
+{
+    struct substr_args *descr = (struct substr_args *)client_data;
+
+    return(((char *)(descr->sa_cord))[i + descr->sa_index]);
+}
+
+char CORD_apply_access_fn(size_t i, void * client_data)
+{
+    struct substr_args *descr = (struct substr_args *)client_data;
+    struct Function * fn_cord = &(descr->sa_cord->function);
+
+    return((*(fn_cord->fn))(i + descr->sa_index, fn_cord->client_data));
+}
+
+/* A version of CORD_substr that simply returns a function node, thus   */
+/* postponing its work. The fourth argument is a function that may      */
+/* be used for efficient access to the ith character.                   */
+/* Assumes i >= 0 and i + n < length(x).                                */
+CORD CORD_substr_closure(CORD x, size_t i, size_t n, CORD_fn f)
+{
+    struct substr_args * sa = GC_NEW(struct substr_args);
+    CordRep * result;
+
+    if (sa == 0) OUT_OF_MEMORY;
+    sa->sa_index = i;
+    GC_PTR_STORE_AND_DIRTY(&sa->sa_cord, x);
+    result = CORD_from_fn_inner(f, (void *)sa, n);
+    if ((CORD)result != CORD_EMPTY && 0 == result -> function.null)
+        result -> function.header = SUBSTR_HDR;
+    return (CORD)result;
+}
+
+# define SUBSTR_LIMIT (10 * SHORT_LIMIT)
+        /* Substrings of function nodes and flat strings shorter than   */
+        /* this are flat strings.  Othewise we use a functional         */
+        /* representation, which is significantly slower to access.     */
+
+/* A version of CORD_substr that assumes i >= 0, n > 0, and i + n < length(x).*/
+CORD CORD_substr_checked(CORD x, size_t i, size_t n)
+{
+    if (CORD_IS_STRING(x)) {
+        if (n > SUBSTR_LIMIT) {
+            return(CORD_substr_closure(x, i, n, CORD_index_access_fn));
+        } else {
+            char * result = (char *)GC_MALLOC_ATOMIC(n + 1);
+
+            if (result == 0) OUT_OF_MEMORY;
+            strncpy(result, x+i, n);
+            result[n] = '\0';
+            return(result);
+        }
+    } else if (IS_CONCATENATION(x)) {
+        struct Concatenation * conc = &(((CordRep *)x) -> concatenation);
+        size_t left_len = LEFT_LEN(conc);
+        size_t right_len = conc -> len - left_len;
+
+        if (i >= left_len) {
+            if (n == right_len) return(conc -> right);
+            return(CORD_substr_checked(conc -> right, i - left_len, n));
+        } else if (i+n <= left_len) {
+            if (n == left_len) return(conc -> left);
+            return(CORD_substr_checked(conc -> left, i, n));
+        } else {
+            /* Need at least one character from each side. */
+            CORD left_part;
+            CORD right_part;
+            size_t left_part_len = left_len - i;
+
+            if (i == 0) {
+                left_part = conc -> left;
+            } else {
+                left_part = CORD_substr_checked(conc -> left, i, left_part_len);
+            }
+            if (i + n == right_len + left_len) {
+                 right_part = conc -> right;
+            } else {
+                 right_part = CORD_substr_checked(conc -> right, 0,
+                                                  n - left_part_len);
+            }
+            return(CORD_cat(left_part, right_part));
+        }
+    } else /* function */ {
+        if (n > SUBSTR_LIMIT) {
+            if (IS_SUBSTR(x)) {
+                /* Avoid nesting substring nodes.       */
+                struct Function * f = &(((CordRep *)x) -> function);
+                struct substr_args *descr =
+                                (struct substr_args *)(f -> client_data);
+
+                return(CORD_substr_closure((CORD)descr->sa_cord,
+                                           i + descr->sa_index,
+                                           n, f -> fn));
+            } else {
+                return(CORD_substr_closure(x, i, n, CORD_apply_access_fn));
+            }
+        } else {
+            char * result;
+            struct Function * f = &(((CordRep *)x) -> function);
+            char buf[SUBSTR_LIMIT+1];
+            char * p = buf;
+            size_t j;
+            size_t lim = i + n;
+
+            for (j = i; j < lim; j++) {
+                char c = (*(f -> fn))(j, f -> client_data);
+
+                if (c == '\0') {
+                    return(CORD_substr_closure(x, i, n, CORD_apply_access_fn));
+                }
+                *p++ = c;
+            }
+            result = (char *)GC_MALLOC_ATOMIC(n + 1);
+            if (result == 0) OUT_OF_MEMORY;
+            memcpy(result, buf, n);
+            result[n] = '\0';
+            return(result);
+        }
+    }
+}
+
+CORD CORD_substr(CORD x, size_t i, size_t n)
+{
+    size_t len = CORD_len(x);
+
+    if (i >= len || n == 0) return(0);
+    if (i + n > len) n = len - i;
+    return(CORD_substr_checked(x, i, n));
+}
+
+/* See cord.h for definition.  We assume i is in range. */
+int CORD_iter5(CORD x, size_t i, CORD_iter_fn f1,
+                         CORD_batched_iter_fn f2, void * client_data)
+{
+    if (x == 0) return(0);
+    if (CORD_IS_STRING(x)) {
+        const char *p = x+i;
+
+        if (*p == '\0') ABORT("2nd arg to CORD_iter5 too big");
+        if (f2 != CORD_NO_FN) {
+            return((*f2)(p, client_data));
+        } else {
+            while (*p) {
+                if ((*f1)(*p, client_data)) return(1);
+                p++;
+            }
+            return(0);
+        }
+    } else if (IS_CONCATENATION(x)) {
+        struct Concatenation * conc = &(((CordRep *)x) -> concatenation);
+
+        if (i > 0) {
+            size_t left_len = LEFT_LEN(conc);
+
+            if (i >= left_len) {
+                return(CORD_iter5(conc -> right, i - left_len, f1, f2,
+                                  client_data));
+            }
+        }
+        if (CORD_iter5(conc -> left, i, f1, f2, client_data)) {
+            return(1);
+        }
+        return(CORD_iter5(conc -> right, 0, f1, f2, client_data));
+    } else /* function */ {
+        struct Function * f = &(((CordRep *)x) -> function);
+        size_t j;
+        size_t lim = f -> len;
+
+        for (j = i; j < lim; j++) {
+            if ((*f1)((*(f -> fn))(j, f -> client_data), client_data)) {
+                return(1);
+            }
+        }
+        return(0);
+    }
+}
+
+#undef CORD_iter
+int CORD_iter(CORD x, CORD_iter_fn f1, void * client_data)
+{
+    return(CORD_iter5(x, 0, f1, CORD_NO_FN, client_data));
+}
+
+int CORD_riter4(CORD x, size_t i, CORD_iter_fn f1, void * client_data)
+{
+    if (x == 0) return(0);
+    if (CORD_IS_STRING(x)) {
+        const char *p = x + i;
+
+        for(;;) {
+            char c = *p;
+
+            if (c == '\0') ABORT("2nd arg to CORD_riter4 too big");
+            if ((*f1)(c, client_data)) return(1);
+            if (p == x) break;
+            p--;
+        }
+        return(0);
+    } else if (IS_CONCATENATION(x)) {
+        struct Concatenation * conc = &(((CordRep *)x) -> concatenation);
+        CORD left_part = conc -> left;
+        size_t left_len = LEFT_LEN(conc);
+
+        if (i >= left_len) {
+            if (CORD_riter4(conc -> right, i - left_len, f1, client_data)) {
+                return(1);
+            }
+            return(CORD_riter4(left_part, left_len - 1, f1, client_data));
+        } else {
+            return(CORD_riter4(left_part, i, f1, client_data));
+        }
+    } else /* function */ {
+        struct Function * f = &(((CordRep *)x) -> function);
+        size_t j;
+
+        for (j = i; ; j--) {
+            if ((*f1)((*(f -> fn))(j, f -> client_data), client_data)) {
+                return(1);
+            }
+            if (j == 0) return(0);
+        }
+    }
+}
+
+int CORD_riter(CORD x, CORD_iter_fn f1, void * client_data)
+{
+    size_t len = CORD_len(x);
+    if (len == 0) return(0);
+    return(CORD_riter4(x, len - 1, f1, client_data));
+}
+
+/*
+ * The following functions are concerned with balancing cords.
+ * Strategy:
+ * Scan the cord from left to right, keeping the cord scanned so far
+ * as a forest of balanced trees of exponentially decreasing length.
+ * When a new subtree needs to be added to the forest, we concatenate all
+ * shorter ones to the new tree in the appropriate order, and then insert
+ * the result into the forest.
+ * Crucial invariants:
+ * 1. The concatenation of the forest (in decreasing order) with the
+ *     unscanned part of the rope is equal to the rope being balanced.
+ * 2. All trees in the forest are balanced.
+ * 3. forest[i] has depth at most i.
+ */
+
+typedef struct {
+    CORD c;
+    size_t len;         /* Actual length of c   */
+} ForestElement;
+
+static size_t min_len [ MAX_DEPTH ];
+
+static int min_len_init = 0;
+
+int CORD_max_len;
+
+typedef ForestElement Forest [ MAX_DEPTH ];
+                        /* forest[i].len >= fib(i+1)            */
+                        /* The string is the concatenation      */
+                        /* of the forest in order of DECREASING */
+                        /* indices.                             */
+
+void CORD_init_min_len(void)
+{
+    int i;
+    size_t last, previous;
+
+    min_len[0] = previous = 1;
+    min_len[1] = last = 2;
+    for (i = 2; i < MAX_DEPTH; i++) {
+        size_t current = last + previous;
+
+        if (current < last) /* overflow */ current = last;
+        min_len[i] = current;
+        previous = last;
+        last = current;
+    }
+    CORD_max_len = (int)last - 1;
+    min_len_init = 1;
+}
+
+
+void CORD_init_forest(ForestElement * forest, size_t max_len)
+{
+    int i;
+
+    for (i = 0; i < MAX_DEPTH; i++) {
+        forest[i].c = 0;
+        if (min_len[i] > max_len) return;
+    }
+    ABORT("Cord too long");
+}
+
+/* Add a leaf to the appropriate level in the forest, cleaning          */
+/* out lower levels as necessary.                                       */
+/* Also works if x is a balanced tree of concatenations; however        */
+/* in this case an extra concatenation node may be inserted above x;    */
+/* This node should not be counted in the statement of the invariants.  */
+void CORD_add_forest(ForestElement * forest, CORD x, size_t len)
+{
+    int i = 0;
+    CORD sum = CORD_EMPTY;
+    size_t sum_len = 0;
+
+    while (len > min_len[i + 1]) {
+        if (forest[i].c != 0) {
+            sum = CORD_cat(forest[i].c, sum);
+            sum_len += forest[i].len;
+            forest[i].c = 0;
+        }
+        i++;
+    }
+    /* Sum has depth at most 1 greter than what would be required       */
+    /* for balance.                                                     */
+    sum = CORD_cat(sum, x);
+    sum_len += len;
+    /* If x was a leaf, then sum is now balanced.  To see this          */
+    /* consider the two cases in which forest[i-1] either is or is      */
+    /* not empty.                                                       */
+    while (sum_len >= min_len[i]) {
+        if (forest[i].c != 0) {
+            sum = CORD_cat(forest[i].c, sum);
+            sum_len += forest[i].len;
+            /* This is again balanced, since sum was balanced, and has  */
+            /* allowable depth that differs from i by at most 1.        */
+            forest[i].c = 0;
+        }
+        i++;
+    }
+    i--;
+    forest[i].c = sum;
+    forest[i].len = sum_len;
+}
+
+CORD CORD_concat_forest(ForestElement * forest, size_t expected_len)
+{
+    int i = 0;
+    CORD sum = 0;
+    size_t sum_len = 0;
+
+    while (sum_len != expected_len) {
+        if (forest[i].c != 0) {
+            sum = CORD_cat(forest[i].c, sum);
+            sum_len += forest[i].len;
+        }
+        i++;
+    }
+    return(sum);
+}
+
+/* Insert the frontier of x into forest.  Balanced subtrees are */
+/* treated as leaves.  This potentially adds one to the depth   */
+/* of the final tree.                                           */
+void CORD_balance_insert(CORD x, size_t len, ForestElement * forest)
+{
+    int depth;
+
+    if (CORD_IS_STRING(x)) {
+        CORD_add_forest(forest, x, len);
+    } else if (IS_CONCATENATION(x)
+               && ((depth = DEPTH(x)) >= MAX_DEPTH
+                   || len < min_len[depth])) {
+        struct Concatenation * conc = &(((CordRep *)x) -> concatenation);
+        size_t left_len = LEFT_LEN(conc);
+
+        CORD_balance_insert(conc -> left, left_len, forest);
+        CORD_balance_insert(conc -> right, len - left_len, forest);
+    } else /* function or balanced */ {
+        CORD_add_forest(forest, x, len);
+    }
+}
+
+
+CORD CORD_balance(CORD x)
+{
+    Forest forest;
+    size_t len;
+
+    if (x == 0) return(0);
+    if (CORD_IS_STRING(x)) return(x);
+    if (!min_len_init) CORD_init_min_len();
+    len = LEN(x);
+    CORD_init_forest(forest, len);
+    CORD_balance_insert(x, len, forest);
+    return(CORD_concat_forest(forest, len));
+}
+
+
+/* Position primitives  */
+
+/* Private routines to deal with the hard cases only: */
+
+/* P contains a prefix of the  path to cur_pos. Extend it to a full     */
+/* path and set up leaf info.                                           */
+/* Return 0 if past the end of cord, 1 o.w.                             */
+void CORD__extend_path(CORD_pos p)
+{
+     struct CORD_pe * current_pe = &(p[0].path[p[0].path_len]);
+     CORD top = current_pe -> pe_cord;
+     size_t pos = p[0].cur_pos;
+     size_t top_pos = current_pe -> pe_start_pos;
+     size_t top_len = GEN_LEN(top);
+
+     /* Fill in the rest of the path. */
+       while(!CORD_IS_STRING(top) && IS_CONCATENATION(top)) {
+         struct Concatenation * conc = &(((CordRep *)top) -> concatenation);
+         size_t left_len;
+
+         left_len = LEFT_LEN(conc);
+         current_pe++;
+         if (pos >= top_pos + left_len) {
+             current_pe -> pe_cord = top = conc -> right;
+             current_pe -> pe_start_pos = top_pos = top_pos + left_len;
+             top_len -= left_len;
+         } else {
+             current_pe -> pe_cord = top = conc -> left;
+             current_pe -> pe_start_pos = top_pos;
+             top_len = left_len;
+         }
+         p[0].path_len++;
+       }
+     /* Fill in leaf description for fast access. */
+       if (CORD_IS_STRING(top)) {
+         p[0].cur_leaf = top;
+         p[0].cur_start = top_pos;
+         p[0].cur_end = top_pos + top_len;
+       } else {
+         p[0].cur_end = 0;
+       }
+       if (pos >= top_pos + top_len) p[0].path_len = CORD_POS_INVALID;
+}
+
+char CORD__pos_fetch(CORD_pos p)
+{
+    /* Leaf is a function node */
+    struct CORD_pe * pe;
+    CORD leaf;
+    struct Function * f;
+
+    if (!CORD_pos_valid(p))
+        ABORT("CORD_pos_fetch: invalid argument");
+    pe = &p[0].path[p[0].path_len];
+    leaf = pe -> pe_cord;
+    if (!IS_FUNCTION(leaf))
+        ABORT("CORD_pos_fetch: bad leaf");
+    f = &((CordRep *)leaf)->function;
+    return ((*(f -> fn))(p[0].cur_pos - pe -> pe_start_pos, f -> client_data));
+}
+
+void CORD__next(CORD_pos p)
+{
+    size_t cur_pos = p[0].cur_pos + 1;
+    struct CORD_pe * current_pe;
+    CORD leaf;
+
+    if (!CORD_pos_valid(p))
+        ABORT("CORD_next: invalid argument");
+    current_pe = &p[0].path[p[0].path_len];
+    leaf = current_pe -> pe_cord;
+
+    /* Leaf is not a string or we're at end of leaf */
+    p[0].cur_pos = cur_pos;
+    if (!CORD_IS_STRING(leaf)) {
+        /* Function leaf        */
+        struct Function * f = &(((CordRep *)leaf) -> function);
+        size_t start_pos = current_pe -> pe_start_pos;
+        size_t end_pos = start_pos + f -> len;
+
+        if (cur_pos < end_pos) {
+          /* Fill cache and return. */
+            size_t i;
+            size_t limit = cur_pos + FUNCTION_BUF_SZ;
+            CORD_fn fn = f -> fn;
+            void * client_data = f -> client_data;
+
+            if (limit > end_pos) {
+                limit = end_pos;
+            }
+            for (i = cur_pos; i < limit; i++) {
+                p[0].function_buf[i - cur_pos] =
+                        (*fn)(i - start_pos, client_data);
+            }
+            p[0].cur_start = cur_pos;
+            p[0].cur_leaf = p[0].function_buf;
+            p[0].cur_end = limit;
+            return;
+        }
+    }
+    /* End of leaf      */
+    /* Pop the stack until we find two concatenation nodes with the     */
+    /* same start position: this implies we were in left part.          */
+    {
+        while (p[0].path_len > 0
+               && current_pe[0].pe_start_pos != current_pe[-1].pe_start_pos) {
+            p[0].path_len--;
+            current_pe--;
+        }
+        if (p[0].path_len == 0) {
+            p[0].path_len = CORD_POS_INVALID;
+            return;
+        }
+    }
+    p[0].path_len--;
+    CORD__extend_path(p);
+}
+
+void CORD__prev(CORD_pos p)
+{
+    struct CORD_pe * pe = &(p[0].path[p[0].path_len]);
+
+    if (p[0].cur_pos == 0) {
+        p[0].path_len = CORD_POS_INVALID;
+        return;
+    }
+    p[0].cur_pos--;
+    if (p[0].cur_pos >= pe -> pe_start_pos) return;
+
+    /* Beginning of leaf        */
+
+    /* Pop the stack until we find two concatenation nodes with the     */
+    /* different start position: this implies we were in right part.    */
+    {
+        struct CORD_pe * current_pe = &((p)[0].path[(p)[0].path_len]);
+
+        while (p[0].path_len > 0
+               && current_pe[0].pe_start_pos == current_pe[-1].pe_start_pos) {
+            p[0].path_len--;
+            current_pe--;
+        }
+    }
+    p[0].path_len--;
+    CORD__extend_path(p);
+}
+
+#undef CORD_pos_fetch
+#undef CORD_next
+#undef CORD_prev
+#undef CORD_pos_to_index
+#undef CORD_pos_to_cord
+#undef CORD_pos_valid
+
+char CORD_pos_fetch(CORD_pos p)
+{
+    if (p[0].cur_end != 0) {
+        return(p[0].cur_leaf[p[0].cur_pos - p[0].cur_start]);
+    } else {
+        return(CORD__pos_fetch(p));
+    }
+}
+
+void CORD_next(CORD_pos p)
+{
+    if (p[0].cur_pos + 1 < p[0].cur_end) {
+        p[0].cur_pos++;
+    } else {
+        CORD__next(p);
+    }
+}
+
+void CORD_prev(CORD_pos p)
+{
+    if (p[0].cur_end != 0 && p[0].cur_pos > p[0].cur_start) {
+        p[0].cur_pos--;
+    } else {
+        CORD__prev(p);
+    }
+}
+
+size_t CORD_pos_to_index(CORD_pos p)
+{
+    return(p[0].cur_pos);
+}
+
+CORD CORD_pos_to_cord(CORD_pos p)
+{
+    return(p[0].path[0].pe_cord);
+}
+
+int CORD_pos_valid(CORD_pos p)
+{
+    return(p[0].path_len != CORD_POS_INVALID);
+}
+
+void CORD_set_pos(CORD_pos p, CORD x, size_t i)
+{
+    if (x == CORD_EMPTY) {
+        p[0].path_len = CORD_POS_INVALID;
+        return;
+    }
+    p[0].path[0].pe_cord = x;
+    p[0].path[0].pe_start_pos = 0;
+    p[0].path_len = 0;
+    p[0].cur_pos = i;
+    CORD__extend_path(p);
+}

+ 446 - 0
blitz.mod/bdwgc/cord/cordprnt.c

@@ -0,0 +1,446 @@
+/*
+ * Copyright (c) 1993-1994 by Xerox Corporation.  All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/* An sprintf implementation that understands cords.  This is probably  */
+/* not terribly portable.  It assumes an ANSI stdarg.h.  It further     */
+/* assumes that I can make copies of va_list variables, and read        */
+/* arguments repeatedly by applying va_arg to the copies.  This         */
+/* could be avoided at some performance cost.                           */
+/* We also assume that unsigned and signed integers of various kinds    */
+/* have the same sizes, and can be cast back and forth.                 */
+/* We assume that void * and char * have the same size.                 */
+/* All this cruft is needed because we want to rely on the underlying   */
+/* sprintf implementation whenever possible.                            */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#ifndef CORD_BUILD
+# define CORD_BUILD
+#endif
+
+#include "gc/cord.h"
+#include "gc/ec.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "gc.h"
+
+#define CONV_SPEC_LEN 50        /* Maximum length of a single   */
+                                /* conversion specification.    */
+#define CONV_RESULT_LEN 50      /* Maximum length of any        */
+                                /* conversion with default      */
+                                /* width and prec.              */
+#if defined(CPPCHECK)
+# define MACRO_BLKSTMT_BEGIN {
+# define MACRO_BLKSTMT_END   }
+#else
+# define MACRO_BLKSTMT_BEGIN do {
+# define MACRO_BLKSTMT_END   } while (0)
+#endif
+
+#define OUT_OF_MEMORY MACRO_BLKSTMT_BEGIN \
+                        if (CORD_oom_fn != 0) (*CORD_oom_fn)(); \
+                        fprintf(stderr, "Out of memory\n"); \
+                        abort(); \
+                      MACRO_BLKSTMT_END
+
+static int ec_len(CORD_ec x)
+{
+    return (int)(CORD_len(x[0].ec_cord) + (x[0].ec_bufptr - x[0].ec_buf));
+}
+
+/* Possible nonumeric precision values. */
+# define NONE -1
+# define VARIABLE -2
+/* Copy the conversion specification from CORD_pos into the buffer buf  */
+/* Return negative on error.                                            */
+/* Source initially points one past the leading %.                      */
+/* It is left pointing at the conversion type.                          */
+/* Assign field width and precision to *width and *prec.                */
+/* If width or prec is *, VARIABLE is assigned.                         */
+/* Set *left to 1 if left adjustment flag is present.                   */
+/* Set *long_arg to 1 if long flag ('l' or 'L') is present, or to       */
+/* -1 if 'h' is present.                                                */
+static int extract_conv_spec(CORD_pos source, char *buf,
+                             int * width, int *prec, int *left, int * long_arg)
+{
+    int result = 0;
+    int current_number = 0;
+    int saw_period = 0;
+    int saw_number = 0;
+    int chars_so_far = 0;
+    char current;
+
+    *width = NONE;
+    buf[chars_so_far++] = '%';
+    while(CORD_pos_valid(source)) {
+        if (chars_so_far >= CONV_SPEC_LEN) return(-1);
+        current = CORD_pos_fetch(source);
+        buf[chars_so_far++] = current;
+        switch(current) {
+          case '*':
+            saw_number = 1;
+            current_number = VARIABLE;
+            break;
+          case '0':
+            if (!saw_number) {
+                /* Zero fill flag; ignore */
+                break;
+            }
+            current_number *= 10;
+            break;
+          case '1':
+          case '2':
+          case '3':
+          case '4':
+          case '5':
+          case '6':
+          case '7':
+          case '8':
+          case '9':
+            saw_number = 1;
+            current_number *= 10;
+            current_number += current - '0';
+            break;
+          case '.':
+            saw_period = 1;
+            if(saw_number) {
+                *width = current_number;
+                saw_number = 0;
+            }
+            current_number = 0;
+            break;
+          case 'l':
+          case 'L':
+            *long_arg = 1;
+            current_number = 0;
+            break;
+          case 'h':
+            *long_arg = -1;
+            current_number = 0;
+            break;
+          case ' ':
+          case '+':
+          case '#':
+            current_number = 0;
+            break;
+          case '-':
+            *left = 1;
+            current_number = 0;
+            break;
+          case 'd':
+          case 'i':
+          case 'o':
+          case 'u':
+          case 'x':
+          case 'X':
+          case 'f':
+          case 'e':
+          case 'E':
+          case 'g':
+          case 'G':
+          case 'c':
+          case 'C':
+          case 's':
+          case 'S':
+          case 'p':
+          case 'n':
+          case 'r':
+            goto done;
+          default:
+            return(-1);
+        }
+        CORD_next(source);
+    }
+    return(-1);
+  done:
+    if (saw_number) {
+        if (saw_period) {
+            *prec = current_number;
+        } else {
+            *prec = NONE;
+            *width = current_number;
+        }
+    } else {
+        *prec = NONE;
+    }
+    buf[chars_so_far] = '\0';
+    return(result);
+}
+
+#if defined(__DJGPP__) || defined(__STRICT_ANSI__)
+  /* vsnprintf is missing in DJGPP (v2.0.3) */
+# define GC_VSNPRINTF(buf, bufsz, format, args) vsprintf(buf, format, args)
+#elif defined(_MSC_VER)
+# if defined(_WIN32_WCE)
+    /* _vsnprintf is deprecated in WinCE */
+#   define GC_VSNPRINTF StringCchVPrintfA
+# else
+#   define GC_VSNPRINTF _vsnprintf
+# endif
+#else
+# define GC_VSNPRINTF vsnprintf
+#endif
+
+int CORD_vsprintf(CORD * out, CORD format, va_list args)
+{
+    CORD_ec result;
+    int count;
+    char current;
+    CORD_pos pos;
+    char conv_spec[CONV_SPEC_LEN + 1];
+
+    CORD_ec_init(result);
+    for (CORD_set_pos(pos, format, 0); CORD_pos_valid(pos); CORD_next(pos)) {
+        current = CORD_pos_fetch(pos);
+        if (current == '%') {
+            CORD_next(pos);
+            if (!CORD_pos_valid(pos)) return(-1);
+            current = CORD_pos_fetch(pos);
+            if (current == '%') {
+                CORD_ec_append(result, current);
+            } else {
+                int width, prec;
+                int left_adj = 0;
+                int long_arg = 0;
+                CORD arg;
+                size_t len;
+
+                if (extract_conv_spec(pos, conv_spec,
+                                      &width, &prec,
+                                      &left_adj, &long_arg) < 0) {
+                    return(-1);
+                }
+                current = CORD_pos_fetch(pos);
+                switch(current) {
+                    case 'n':
+                        /* Assign length to next arg */
+                        if (long_arg == 0) {
+                            int * pos_ptr;
+                            pos_ptr = va_arg(args, int *);
+                            *pos_ptr = ec_len(result);
+                        } else if (long_arg > 0) {
+                            long * pos_ptr;
+                            pos_ptr = va_arg(args, long *);
+                            *pos_ptr = ec_len(result);
+                        } else {
+                            short * pos_ptr;
+                            pos_ptr = va_arg(args, short *);
+                            *pos_ptr = (short)ec_len(result);
+                        }
+                        goto done;
+                    case 'r':
+                        /* Append cord and any padding  */
+                        if (width == VARIABLE) width = va_arg(args, int);
+                        if (prec == VARIABLE) prec = va_arg(args, int);
+                        arg = va_arg(args, CORD);
+                        len = CORD_len(arg);
+                        if (prec != NONE && len > (unsigned)prec) {
+                          if (prec < 0) return(-1);
+                          arg = CORD_substr(arg, 0, (unsigned)prec);
+                          len = (unsigned)prec;
+                        }
+                        if (width != NONE && len < (unsigned)width) {
+                          char * blanks = (char *)GC_MALLOC_ATOMIC(
+                                                (unsigned)width - len + 1);
+
+                          if (NULL == blanks) OUT_OF_MEMORY;
+                          memset(blanks, ' ', (unsigned)width - len);
+                          blanks[(unsigned)width - len] = '\0';
+                          if (left_adj) {
+                            arg = CORD_cat(arg, blanks);
+                          } else {
+                            arg = CORD_cat(blanks, arg);
+                          }
+                        }
+                        CORD_ec_append_cord(result, arg);
+                        goto done;
+                    case 'c':
+                        if (width == NONE && prec == NONE) {
+                            char c;
+
+                            c = (char)va_arg(args, int);
+                            CORD_ec_append(result, c);
+                            goto done;
+                        }
+                        break;
+                    case 's':
+                        if (width == NONE && prec == NONE) {
+                            char * str = va_arg(args, char *);
+                            char c;
+
+                            while ((c = *str++) != '\0') {
+                                CORD_ec_append(result, c);
+                            }
+                            goto done;
+                        }
+                        break;
+                    default:
+                        break;
+                }
+                /* Use standard sprintf to perform conversion */
+                {
+                    char * buf;
+                    va_list vsprintf_args;
+                    int max_size = 0;
+                    int res = 0;
+
+#                   if defined(CPPCHECK)
+                      va_copy(vsprintf_args, args);
+#                   elif defined(__va_copy)
+                      __va_copy(vsprintf_args, args);
+#                   elif defined(__GNUC__) && !defined(__DJGPP__) \
+                         && !defined(__EMX__) /* and probably in other cases */
+                      va_copy(vsprintf_args, args);
+#                   else
+                      vsprintf_args = args;
+#                   endif
+                    if (width == VARIABLE) width = va_arg(args, int);
+                    if (prec == VARIABLE) prec = va_arg(args, int);
+                    if (width != NONE) max_size = width;
+                    if (prec != NONE && prec > max_size) max_size = prec;
+                    max_size += CONV_RESULT_LEN;
+                    if (max_size >= CORD_BUFSZ) {
+                        buf = (char *)GC_MALLOC_ATOMIC((unsigned)max_size + 1);
+                        if (NULL == buf) OUT_OF_MEMORY;
+                    } else {
+                        if (CORD_BUFSZ - (result[0].ec_bufptr-result[0].ec_buf)
+                            < max_size) {
+                            CORD_ec_flush_buf(result);
+                        }
+                        buf = result[0].ec_bufptr;
+                    }
+                    switch(current) {
+                        case 'd':
+                        case 'i':
+                        case 'o':
+                        case 'u':
+                        case 'x':
+                        case 'X':
+                        case 'c':
+                            if (long_arg <= 0) {
+                              (void) va_arg(args, int);
+                            } else /* long_arg > 0 */ {
+                              (void) va_arg(args, long);
+                            }
+                            break;
+                        case 's':
+                        case 'p':
+                            (void) va_arg(args, char *);
+                            break;
+                        case 'f':
+                        case 'e':
+                        case 'E':
+                        case 'g':
+                        case 'G':
+                            (void) va_arg(args, double);
+                            break;
+                        default:
+                            res = -1;
+                    }
+                    if (0 == res)
+                      res = GC_VSNPRINTF(buf, max_size + 1, conv_spec,
+                                         vsprintf_args);
+#                   if defined(CPPCHECK) || defined(__va_copy) \
+                       || (defined(__GNUC__) && !defined(__DJGPP__) \
+                           && !defined(__EMX__))
+                      va_end(vsprintf_args);
+#                   endif
+                    len = (unsigned)res;
+                    if ((char *)(GC_word)res == buf) {
+                        /* old style vsprintf */
+                        len = strlen(buf);
+                    } else if (res < 0) {
+                        return(-1);
+                    }
+                    if (buf != result[0].ec_bufptr) {
+                        char c;
+
+                        while ((c = *buf++) != '\0') {
+                            CORD_ec_append(result, c);
+                        }
+                    } else {
+                        result[0].ec_bufptr = buf + len;
+                    }
+                }
+              done:;
+            }
+        } else {
+            CORD_ec_append(result, current);
+        }
+    }
+    count = ec_len(result);
+    *out = CORD_balance(CORD_ec_to_cord(result));
+    return(count);
+}
+
+int CORD_sprintf(CORD * out, CORD format, ...)
+{
+    va_list args;
+    int result;
+
+    va_start(args, format);
+    result = CORD_vsprintf(out, format, args);
+    va_end(args);
+    return(result);
+}
+
+int CORD_fprintf(FILE * f, CORD format, ...)
+{
+    va_list args;
+    int result;
+    CORD out = CORD_EMPTY; /* initialized to prevent compiler warning */
+
+    va_start(args, format);
+    result = CORD_vsprintf(&out, format, args);
+    va_end(args);
+    if (result > 0) CORD_put(out, f);
+    return(result);
+}
+
+int CORD_vfprintf(FILE * f, CORD format, va_list args)
+{
+    int result;
+    CORD out = CORD_EMPTY;
+
+    result = CORD_vsprintf(&out, format, args);
+    if (result > 0) CORD_put(out, f);
+    return(result);
+}
+
+int CORD_printf(CORD format, ...)
+{
+    va_list args;
+    int result;
+    CORD out = CORD_EMPTY;
+
+    va_start(args, format);
+    result = CORD_vsprintf(&out, format, args);
+    va_end(args);
+    if (result > 0) CORD_put(out, stdout);
+    return(result);
+}
+
+int CORD_vprintf(CORD format, va_list args)
+{
+    int result;
+    CORD out = CORD_EMPTY;
+
+    result = CORD_vsprintf(&out, format, args);
+    if (result > 0) CORD_put(out, stdout);
+    return(result);
+}

+ 639 - 0
blitz.mod/bdwgc/cord/cordxtra.c

@@ -0,0 +1,639 @@
+/*
+ * Copyright (c) 1993-1994 by Xerox Corporation.  All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/*
+ * These are functions on cords that do not need to understand their
+ * implementation.  They serve also serve as example client code for
+ * cord_basics.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#ifndef CORD_BUILD
+# define CORD_BUILD
+#endif
+
+# include <stdio.h>
+# include <string.h>
+# include <stdlib.h>
+# include <stdarg.h>
+
+#include "gc/cord.h"
+#include "gc/ec.h"
+
+# define I_HIDE_POINTERS    /* So we get access to allocation lock. */
+                /* We use this for lazy file reading,   */
+                /* so that we remain independent        */
+                /* of the threads primitives.           */
+# include "gc.h"
+
+/* For now we assume that pointer reads and writes are atomic,  */
+/* i.e. another thread always sees the state before or after    */
+/* a write.  This might be false on a Motorola M68K with        */
+/* pointers that are not 32-bit aligned.  But there probably    */
+/* aren't too many threads packages running on those.           */
+# define ATOMIC_WRITE(x,y) (x) = (y)
+# define ATOMIC_READ(x) (*(x))
+
+/* The standard says these are in stdio.h, but they aren't always: */
+# ifndef SEEK_SET
+#   define SEEK_SET 0
+# endif
+# ifndef SEEK_END
+#   define SEEK_END 2
+# endif
+
+# define BUFSZ 2048     /* Size of stack allocated buffers when */
+                        /* we want large buffers.               */
+
+typedef void (* oom_fn)(void);
+
+# define OUT_OF_MEMORY { if (CORD_oom_fn != (oom_fn) 0) (*CORD_oom_fn)(); \
+                         ABORT("Out of memory"); }
+# define ABORT(msg) { fprintf(stderr, "%s\n", msg); abort(); }
+
+#if GC_GNUC_PREREQ(3, 4)
+# define CORD_ATTR_UNUSED __attribute__((__unused__))
+#else
+# define CORD_ATTR_UNUSED /* empty */
+#endif
+
+CORD CORD_cat_char(CORD x, char c)
+{
+    char * string;
+
+    if (c == '\0') return(CORD_cat(x, CORD_nul(1)));
+    string = (char *)GC_MALLOC_ATOMIC(2);
+    if (string == 0) OUT_OF_MEMORY;
+    string[0] = c;
+    string[1] = '\0';
+    return(CORD_cat_char_star(x, string, 1));
+}
+
+CORD CORD_catn(int nargs, ...)
+{
+    CORD result = CORD_EMPTY;
+    va_list args;
+    int i;
+
+    va_start(args, nargs);
+    for (i = 0; i < nargs; i++) {
+        CORD next = va_arg(args, CORD);
+        result = CORD_cat(result, next);
+    }
+    va_end(args);
+    return(result);
+}
+
+typedef struct {
+    size_t len;
+    size_t count;
+    char * buf;
+} CORD_fill_data;
+
+int CORD_fill_proc(char c, void * client_data)
+{
+    CORD_fill_data * d = (CORD_fill_data *)client_data;
+    size_t count = d -> count;
+
+    (d -> buf)[count] = c;
+    d -> count = ++count;
+    if (count >= d -> len) {
+        return(1);
+    } else {
+        return(0);
+    }
+}
+
+int CORD_batched_fill_proc(const char * s, void * client_data)
+{
+    CORD_fill_data * d = (CORD_fill_data *)client_data;
+    size_t count = d -> count;
+    size_t max = d -> len;
+    char * buf = d -> buf;
+    const char * t = s;
+
+    while((buf[count] = *t++) != '\0') {
+        count++;
+        if (count >= max) {
+            d -> count = count;
+            return(1);
+        }
+    }
+    d -> count = count;
+    return(0);
+}
+
+/* Fill buf with len characters starting at i.  */
+/* Assumes len characters are available in buf. */
+/* Return 1 if buf is filled fully (and len is  */
+/* non-zero), 0 otherwise.                      */
+int CORD_fill_buf(CORD x, size_t i, size_t len, char * buf)
+{
+    CORD_fill_data fd;
+
+    fd.len = len;
+    fd.buf = buf;
+    fd.count = 0;
+    return CORD_iter5(x, i, CORD_fill_proc, CORD_batched_fill_proc, &fd);
+}
+
+int CORD_cmp(CORD x, CORD y)
+{
+    CORD_pos xpos;
+    CORD_pos ypos;
+
+    if (y == CORD_EMPTY) return(x != CORD_EMPTY);
+    if (x == CORD_EMPTY) return(-1);
+    if (CORD_IS_STRING(y) && CORD_IS_STRING(x)) return(strcmp(x,y));
+    CORD_set_pos(xpos, x, 0);
+    CORD_set_pos(ypos, y, 0);
+    for(;;) {
+        size_t avail, yavail;
+
+        if (!CORD_pos_valid(xpos)) {
+            if (CORD_pos_valid(ypos)) {
+                return(-1);
+            } else {
+                return(0);
+            }
+        }
+        if (!CORD_pos_valid(ypos)) {
+            return(1);
+        }
+        avail = CORD_pos_chars_left(xpos);
+        if (avail == 0
+            || (yavail = CORD_pos_chars_left(ypos)) == 0) {
+            char xcurrent = CORD_pos_fetch(xpos);
+            char ycurrent = CORD_pos_fetch(ypos);
+            if (xcurrent != ycurrent) return(xcurrent - ycurrent);
+            CORD_next(xpos);
+            CORD_next(ypos);
+        } else {
+            /* process as many characters as we can */
+            int result;
+
+            if (avail > yavail) avail = yavail;
+            result = strncmp(CORD_pos_cur_char_addr(xpos),
+                         CORD_pos_cur_char_addr(ypos), avail);
+            if (result != 0) return(result);
+            CORD_pos_advance(xpos, avail);
+            CORD_pos_advance(ypos, avail);
+        }
+    }
+}
+
+int CORD_ncmp(CORD x, size_t x_start, CORD y, size_t y_start, size_t len)
+{
+    CORD_pos xpos;
+    CORD_pos ypos;
+    size_t count;
+
+    CORD_set_pos(xpos, x, x_start);
+    CORD_set_pos(ypos, y, y_start);
+    for(count = 0; count < len;) {
+        long avail, yavail;
+
+        if (!CORD_pos_valid(xpos)) {
+            if (CORD_pos_valid(ypos)) {
+                return(-1);
+            } else {
+                return(0);
+            }
+        }
+        if (!CORD_pos_valid(ypos)) {
+            return(1);
+        }
+        if ((avail = CORD_pos_chars_left(xpos)) <= 0
+            || (yavail = CORD_pos_chars_left(ypos)) <= 0) {
+            char xcurrent = CORD_pos_fetch(xpos);
+            char ycurrent = CORD_pos_fetch(ypos);
+
+            if (xcurrent != ycurrent) return(xcurrent - ycurrent);
+            CORD_next(xpos);
+            CORD_next(ypos);
+            count++;
+        } else {
+            /* process as many characters as we can */
+            int result;
+
+            if (avail > yavail) avail = yavail;
+            count += avail;
+            if (count > len)
+                avail -= (long)(count - len);
+            result = strncmp(CORD_pos_cur_char_addr(xpos),
+                         CORD_pos_cur_char_addr(ypos), (size_t)avail);
+            if (result != 0) return(result);
+            CORD_pos_advance(xpos, (size_t)avail);
+            CORD_pos_advance(ypos, (size_t)avail);
+        }
+    }
+    return(0);
+}
+
+char * CORD_to_char_star(CORD x)
+{
+    size_t len = CORD_len(x);
+    char * result = (char *)GC_MALLOC_ATOMIC(len + 1);
+
+    if (result == 0) OUT_OF_MEMORY;
+    if (len > 0 && CORD_fill_buf(x, 0, len, result) != 1)
+      ABORT("CORD_fill_buf malfunction");
+    result[len] = '\0';
+    return(result);
+}
+
+CORD CORD_from_char_star(const char *s)
+{
+    char * result;
+    size_t len = strlen(s);
+
+    if (0 == len) return(CORD_EMPTY);
+    result = (char *)GC_MALLOC_ATOMIC(len + 1);
+    if (result == 0) OUT_OF_MEMORY;
+    memcpy(result, s, len+1);
+    return(result);
+}
+
+const char * CORD_to_const_char_star(CORD x)
+{
+    if (x == 0) return("");
+    if (CORD_IS_STRING(x)) return((const char *)x);
+    return(CORD_to_char_star(x));
+}
+
+char CORD_fetch(CORD x, size_t i)
+{
+    CORD_pos xpos;
+
+    CORD_set_pos(xpos, x, i);
+    if (!CORD_pos_valid(xpos)) ABORT("bad index?");
+    return(CORD_pos_fetch(xpos));
+}
+
+
+int CORD_put_proc(char c, void * client_data)
+{
+    FILE * f = (FILE *)client_data;
+
+    return(putc(c, f) == EOF);
+}
+
+int CORD_batched_put_proc(const char * s, void * client_data)
+{
+    FILE * f = (FILE *)client_data;
+
+    return(fputs(s, f) == EOF);
+}
+
+
+int CORD_put(CORD x, FILE * f)
+{
+    if (CORD_iter5(x, 0, CORD_put_proc, CORD_batched_put_proc, f)) {
+        return(EOF);
+    } else {
+        return(1);
+    }
+}
+
+typedef struct {
+    size_t pos;     /* Current position in the cord */
+    char target;    /* Character we're looking for  */
+} chr_data;
+
+int CORD_chr_proc(char c, void * client_data)
+{
+    chr_data * d = (chr_data *)client_data;
+
+    if (c == d -> target) return(1);
+    (d -> pos) ++;
+    return(0);
+}
+
+int CORD_rchr_proc(char c, void * client_data)
+{
+    chr_data * d = (chr_data *)client_data;
+
+    if (c == d -> target) return(1);
+    (d -> pos) --;
+    return(0);
+}
+
+int CORD_batched_chr_proc(const char *s, void * client_data)
+{
+    chr_data * d = (chr_data *)client_data;
+    const char * occ = strchr(s, d -> target);
+
+    if (NULL == occ) {
+        d -> pos += strlen(s);
+        return(0);
+    } else {
+        d -> pos += occ - s;
+        return(1);
+    }
+}
+
+size_t CORD_chr(CORD x, size_t i, int c)
+{
+    chr_data d;
+
+    d.pos = i;
+    d.target = (char)c;
+    if (CORD_iter5(x, i, CORD_chr_proc, CORD_batched_chr_proc, &d)) {
+        return(d.pos);
+    } else {
+        return(CORD_NOT_FOUND);
+    }
+}
+
+size_t CORD_rchr(CORD x, size_t i, int c)
+{
+    chr_data d;
+
+    d.pos = i;
+    d.target = (char)c;
+    if (CORD_riter4(x, i, CORD_rchr_proc, &d)) {
+        return(d.pos);
+    } else {
+        return(CORD_NOT_FOUND);
+    }
+}
+
+/* Find the first occurrence of s in x at position start or later.      */
+/* This uses an asymptotically poor algorithm, which should typically   */
+/* perform acceptably.  We compare the first few characters directly,   */
+/* and call CORD_ncmp whenever there is a partial match.                */
+/* This has the advantage that we allocate very little, or not at all.  */
+/* It's very fast if there are few close misses.                        */
+size_t CORD_str(CORD x, size_t start, CORD s)
+{
+    CORD_pos xpos;
+    size_t xlen = CORD_len(x);
+    size_t slen;
+    size_t start_len;
+    const char * s_start;
+    unsigned long s_buf = 0;    /* The first few characters of s        */
+    unsigned long x_buf = 0;    /* Start of candidate substring.        */
+                    /* Initialized only to make compilers   */
+                    /* happy.                               */
+    unsigned long mask = 0;
+    size_t i;
+    size_t match_pos;
+
+    if (s == CORD_EMPTY) return(start);
+    if (CORD_IS_STRING(s)) {
+        s_start = s;
+        slen = strlen(s);
+    } else {
+        s_start = CORD_to_char_star(CORD_substr(s, 0, sizeof(unsigned long)));
+        slen = CORD_len(s);
+    }
+    if (xlen < start || xlen - start < slen) return(CORD_NOT_FOUND);
+    start_len = slen;
+    if (start_len > sizeof(unsigned long)) start_len = sizeof(unsigned long);
+    CORD_set_pos(xpos, x, start);
+    for (i = 0; i < start_len; i++) {
+        mask <<= 8;
+        mask |= 0xff;
+        s_buf <<= 8;
+        s_buf |= (unsigned char)s_start[i];
+        x_buf <<= 8;
+        x_buf |= (unsigned char)CORD_pos_fetch(xpos);
+        CORD_next(xpos);
+    }
+    for (match_pos = start; ; match_pos++) {
+        if ((x_buf & mask) == s_buf) {
+            if (slen == start_len ||
+                CORD_ncmp(x, match_pos + start_len,
+                      s, start_len, slen - start_len) == 0) {
+                return(match_pos);
+            }
+        }
+    if ( match_pos == xlen - slen ) {
+        return(CORD_NOT_FOUND);
+    }
+        x_buf <<= 8;
+        x_buf |= (unsigned char)CORD_pos_fetch(xpos);
+        CORD_next(xpos);
+    }
+}
+
+void CORD_ec_flush_buf(CORD_ec x)
+{
+    size_t len = x[0].ec_bufptr - x[0].ec_buf;
+    char * s;
+
+    if (len == 0) return;
+    s = (char *)GC_MALLOC_ATOMIC(len + 1);
+    if (NULL == s) OUT_OF_MEMORY;
+    memcpy(s, x[0].ec_buf, len);
+    s[len] = '\0';
+    x[0].ec_cord = CORD_cat_char_star(x[0].ec_cord, s, len);
+    x[0].ec_bufptr = x[0].ec_buf;
+}
+
+void CORD_ec_append_cord(CORD_ec x, CORD s)
+{
+    CORD_ec_flush_buf(x);
+    x[0].ec_cord = CORD_cat(x[0].ec_cord, s);
+}
+
+char CORD_nul_func(size_t i CORD_ATTR_UNUSED, void * client_data)
+{
+    return (char)(GC_word)client_data;
+}
+
+CORD CORD_chars(char c, size_t i)
+{
+    return CORD_from_fn(CORD_nul_func, (void *)(GC_word)(unsigned char)c, i);
+}
+
+CORD CORD_from_file_eager(FILE * f)
+{
+    CORD_ec ecord;
+
+    CORD_ec_init(ecord);
+    for(;;) {
+        int c = getc(f);
+
+        if (c == 0) {
+          /* Append the right number of NULs                            */
+          /* Note that any string of NULs is represented in 4 words,    */
+          /* independent of its length.                                 */
+            size_t count = 1;
+
+            CORD_ec_flush_buf(ecord);
+            while ((c = getc(f)) == 0) count++;
+            ecord[0].ec_cord = CORD_cat(ecord[0].ec_cord, CORD_nul(count));
+        }
+        if (c == EOF) break;
+        CORD_ec_append(ecord, (char)c);
+    }
+    (void) fclose(f);
+    return(CORD_balance(CORD_ec_to_cord(ecord)));
+}
+
+/* The state maintained for a lazily read file consists primarily       */
+/* of a large direct-mapped cache of previously read values.            */
+/* We could rely more on stdio buffering.  That would have 2            */
+/* disadvantages:                                                       */
+/*  1) Empirically, not all fseek implementations preserve the          */
+/*     buffer whenever they could.                                      */
+/*  2) It would fail if 2 different sections of a long cord             */
+/*     were being read alternately.                                     */
+/* We do use the stdio buffer for read ahead.                           */
+/* To guarantee thread safety in the presence of atomic pointer         */
+/* writes, cache lines are always replaced, and never modified in       */
+/* place.                                                               */
+
+# define LOG_CACHE_SZ 14
+# define CACHE_SZ (1 << LOG_CACHE_SZ)
+# define LOG_LINE_SZ 9
+# define LINE_SZ (1 << LOG_LINE_SZ)
+
+typedef struct {
+    size_t tag;
+    char data[LINE_SZ];
+        /* data[i%LINE_SZ] = ith char in file if tag = i/LINE_SZ    */
+} cache_line;
+
+typedef struct {
+    FILE * lf_file;
+    size_t lf_current;  /* Current file pointer value */
+    cache_line * volatile lf_cache[CACHE_SZ/LINE_SZ];
+} lf_state;
+
+# define MOD_CACHE_SZ(n) ((n) & (CACHE_SZ - 1))
+# define DIV_CACHE_SZ(n) ((n) >> LOG_CACHE_SZ)
+# define MOD_LINE_SZ(n) ((n) & (LINE_SZ - 1))
+# define DIV_LINE_SZ(n) ((n) >> LOG_LINE_SZ)
+# define LINE_START(n) ((n) & ~(LINE_SZ - 1))
+
+typedef struct {
+    lf_state * state;
+    size_t file_pos;    /* Position of needed character. */
+    cache_line * new_cache;
+} refill_data;
+
+/* Executed with allocation lock. */
+static void * GC_CALLBACK refill_cache(void * client_data)
+{
+    lf_state * state = ((refill_data *)client_data) -> state;
+    size_t file_pos = ((refill_data *)client_data) -> file_pos;
+    FILE *f = state -> lf_file;
+    size_t line_start = LINE_START(file_pos);
+    size_t line_no = DIV_LINE_SZ(MOD_CACHE_SZ(file_pos));
+    cache_line * new_cache = ((refill_data *)client_data) -> new_cache;
+
+    if (line_start != state -> lf_current
+        && fseek(f, (long)line_start, SEEK_SET) != 0) {
+            ABORT("fseek failed");
+    }
+    if (fread(new_cache -> data, sizeof(char), LINE_SZ, f)
+        <= file_pos - line_start) {
+        ABORT("fread failed");
+    }
+    new_cache -> tag = DIV_LINE_SZ(file_pos);
+    /* Store barrier goes here. */
+    ATOMIC_WRITE(state -> lf_cache[line_no], new_cache);
+    GC_END_STUBBORN_CHANGE((/* no volatile */ void *)(state -> lf_cache
+                                                      + line_no));
+    state -> lf_current = line_start + LINE_SZ;
+    return (void *)((GC_word)new_cache->data[MOD_LINE_SZ(file_pos)]);
+}
+
+char CORD_lf_func(size_t i, void * client_data)
+{
+    lf_state * state = (lf_state *)client_data;
+    cache_line * volatile * cl_addr =
+                        &(state -> lf_cache[DIV_LINE_SZ(MOD_CACHE_SZ(i))]);
+    cache_line * cl = (cache_line *)ATOMIC_READ(cl_addr);
+
+    if (cl == 0 || cl -> tag != DIV_LINE_SZ(i)) {
+        /* Cache miss */
+        refill_data rd;
+
+        rd.state = state;
+        rd.file_pos =  i;
+        rd.new_cache = GC_NEW_ATOMIC(cache_line);
+        if (rd.new_cache == 0) OUT_OF_MEMORY;
+        return (char)((GC_word)GC_call_with_alloc_lock(refill_cache, &rd));
+    }
+    return(cl -> data[MOD_LINE_SZ(i)]);
+}
+
+void CORD_lf_close_proc(void * obj, void * client_data CORD_ATTR_UNUSED)
+{
+    if (fclose(((lf_state *)obj) -> lf_file) != 0) {
+        ABORT("CORD_lf_close_proc: fclose failed");
+    }
+}
+
+CORD CORD_from_file_lazy_inner(FILE * f, size_t len)
+{
+    lf_state * state = GC_NEW(lf_state);
+    int i;
+
+    if (state == 0) OUT_OF_MEMORY;
+    if (len != 0) {
+        /* Dummy read to force buffer allocation.       */
+        /* This greatly increases the probability       */
+        /* of avoiding deadlock if buffer allocation    */
+        /* is redirected to GC_malloc and the           */
+        /* world is multi-threaded.                     */
+        char buf[1];
+
+        if (fread(buf, 1, 1, f) > 1
+            || fseek(f, 0l, SEEK_SET) != 0) {
+            ABORT("Bad f argument or I/O failure");
+        }
+    }
+    state -> lf_file = f;
+    for (i = 0; i < CACHE_SZ/LINE_SZ; i++) {
+        state -> lf_cache[i] = 0;
+    }
+    state -> lf_current = 0;
+    GC_REGISTER_FINALIZER(state, CORD_lf_close_proc, 0, 0, 0);
+    return(CORD_from_fn(CORD_lf_func, state, len));
+}
+
+CORD CORD_from_file_lazy(FILE * f)
+{
+    long len;
+
+    if (fseek(f, 0l, SEEK_END) != 0
+        || (len = ftell(f)) < 0
+        || fseek(f, 0l, SEEK_SET) != 0) {
+        ABORT("Bad f argument or I/O failure");
+    }
+    return(CORD_from_file_lazy_inner(f, (size_t)len));
+}
+
+# define LAZY_THRESHOLD (128*1024 + 1)
+
+CORD CORD_from_file(FILE * f)
+{
+    long len;
+
+    if (fseek(f, 0l, SEEK_END) != 0
+        || (len = ftell(f)) < 0
+        || fseek(f, 0l, SEEK_SET) != 0) {
+        ABORT("Bad f argument or I/O failure");
+    }
+    if (len < LAZY_THRESHOLD) {
+        return(CORD_from_file_eager(f));
+    } else {
+        return(CORD_from_file_lazy_inner(f, (size_t)len));
+    }
+}

+ 325 - 0
blitz.mod/bdwgc/cord/tests/cordtest.c

@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 1993-1994 by Xerox Corporation.  All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+# include <stdarg.h>
+# include <string.h>
+# include <stdio.h>
+# include <stdlib.h>
+
+#include "gc.h"    /* For GC_INIT() only */
+#include "gc/cord.h"
+
+/* This is a very incomplete test of the cord package.  It knows about  */
+/* a few internals of the package (e.g. when C strings are returned)    */
+/* that real clients shouldn't rely on.                                 */
+
+# define ABORT(string) \
+    { fprintf(stderr, "FAILED: %s\n", string); abort(); }
+
+#if defined(CPPCHECK)
+# undef CORD_iter
+# undef CORD_next
+# undef CORD_pos_fetch
+# undef CORD_pos_to_cord
+# undef CORD_pos_to_index
+# undef CORD_pos_valid
+# undef CORD_prev
+#endif
+
+int count;
+
+int test_fn(char c, void * client_data)
+{
+    if (client_data != (void *)(GC_word)13)
+        ABORT("bad client data");
+    if (count < 64*1024+1) {
+        if ((count & 1) == 0) {
+            if (c != 'b') ABORT("bad char");
+        } else {
+            if (c != 'a') ABORT("bad char");
+        }
+        count++;
+        return(0);
+    } else {
+        if (c != 'c') ABORT("bad char");
+        count++;
+        return(1);
+    }
+}
+
+char id_cord_fn(size_t i, void * client_data)
+{
+    if (client_data != 0) ABORT("id_cord_fn: bad client data");
+    return((char)i);
+}
+
+void test_basics(void)
+{
+    CORD x = CORD_from_char_star("ab");
+    size_t i;
+    CORD y;
+    CORD_pos p;
+
+    x = CORD_cat(x,x);
+    if (x == CORD_EMPTY) ABORT("CORD_cat(x,x) returned empty cord");
+    if (!CORD_IS_STRING(x)) ABORT("short cord should usually be a string");
+    if (strcmp(x, "abab") != 0) ABORT("bad CORD_cat result");
+
+    for (i = 1; i < 16; i++) {
+        x = CORD_cat(x,x);
+    }
+    x = CORD_cat(x,"c");
+    if (CORD_len(x) != 128*1024+1) ABORT("bad length");
+
+    count = 0;
+    if (CORD_iter5(x, 64*1024-1, test_fn, CORD_NO_FN,
+                   (void *)(GC_word)13) == 0) {
+        ABORT("CORD_iter5 failed");
+    }
+    if (count != 64*1024 + 2) ABORT("CORD_iter5 failed");
+
+    count = 0;
+    CORD_set_pos(p, x, 64*1024-1);
+    while(CORD_pos_valid(p)) {
+        (void)test_fn(CORD_pos_fetch(p), (void *)(GC_word)13);
+    CORD_next(p);
+    }
+    if (count != 64*1024 + 2) ABORT("Position based iteration failed");
+
+    y = CORD_substr(x, 1023, 5);
+    if (!y) ABORT("CORD_substr returned NULL");
+    if (!CORD_IS_STRING(y)) ABORT("short cord should usually be a string");
+    if (strcmp(y, "babab") != 0) ABORT("bad CORD_substr result");
+
+    y = CORD_substr(x, 1024, 8);
+    if (!y) ABORT("CORD_substr returned NULL");
+    if (!CORD_IS_STRING(y)) ABORT("short cord should usually be a string");
+    if (strcmp(y, "abababab") != 0) ABORT("bad CORD_substr result");
+
+    y = CORD_substr(x, 128*1024-1, 8);
+    if (!y) ABORT("CORD_substr returned NULL");
+    if (!CORD_IS_STRING(y)) ABORT("short cord should usually be a string");
+    if (strcmp(y, "bc") != 0) ABORT("bad CORD_substr result");
+
+    x = CORD_balance(x);
+    if (CORD_len(x) != 128*1024+1) ABORT("bad length");
+
+    count = 0;
+    if (CORD_iter5(x, 64*1024-1, test_fn, CORD_NO_FN,
+                   (void *)(GC_word)13) == 0) {
+        ABORT("CORD_iter5 failed");
+    }
+    if (count != 64*1024 + 2) ABORT("CORD_iter5 failed");
+
+    y = CORD_substr(x, 1023, 5);
+    if (!y) ABORT("CORD_substr returned NULL");
+    if (!CORD_IS_STRING(y)) ABORT("short cord should usually be a string");
+    if (strcmp(y, "babab") != 0) ABORT("bad CORD_substr result");
+    y = CORD_from_fn(id_cord_fn, 0, 13);
+    i = 0;
+    CORD_set_pos(p, y, i);
+    while(CORD_pos_valid(p)) {
+        char c = CORD_pos_fetch(p);
+
+        if ((size_t)(unsigned char)c != i)
+            ABORT("Traversal of function node failed");
+        CORD_next(p);
+        i++;
+    }
+    if (i != 13) ABORT("Bad apparent length for function node");
+#   if defined(CPPCHECK)
+        /* TODO: Actually test these functions. */
+        CORD_prev(p);
+        (void)CORD_pos_to_cord(p);
+        (void)CORD_pos_to_index(p);
+        (void)CORD_iter(CORD_EMPTY, test_fn, NULL);
+        (void)CORD_riter(CORD_EMPTY, test_fn, NULL);
+        CORD_dump(y);
+#   endif
+}
+
+void test_extras(void)
+{
+#   define FNAME1 "cordtst1.tmp" /* short name (8+3) for portability */
+#   define FNAME2 "cordtst2.tmp"
+    int i;
+    CORD y = "abcdefghijklmnopqrstuvwxyz0123456789";
+    CORD x = "{}";
+    CORD u, w, z;
+    FILE *f;
+    FILE *f1a, *f1b, *f2;
+
+    w = CORD_cat(CORD_cat(y,y),y);
+    z = CORD_catn(3,y,y,y);
+    if (CORD_cmp(w,z) != 0) ABORT("CORD_catn comparison wrong");
+    for (i = 1; i < 100; i++) {
+        x = CORD_cat(x, y);
+    }
+    z = CORD_balance(x);
+    if (CORD_cmp(x,z) != 0) ABORT("balanced string comparison wrong");
+    if (CORD_cmp(x,CORD_cat(z, CORD_nul(13))) >= 0) ABORT("comparison 2");
+    if (CORD_cmp(CORD_cat(x, CORD_nul(13)), z) <= 0) ABORT("comparison 3");
+    if (CORD_cmp(x,CORD_cat(z, "13")) >= 0) ABORT("comparison 4");
+    if ((f = fopen(FNAME1, "w")) == 0) ABORT("open failed");
+    if (CORD_put(z,f) == EOF) ABORT("CORD_put failed");
+    if (fclose(f) == EOF) ABORT("fclose failed");
+    f1a = fopen(FNAME1, "rb");
+    if (!f1a) ABORT("Unable to open " FNAME1);
+    w = CORD_from_file(f1a);
+    if (CORD_len(w) != CORD_len(z)) ABORT("file length wrong");
+    if (CORD_cmp(w,z) != 0) ABORT("file comparison wrong");
+    if (CORD_cmp(CORD_substr(w, 50*36+2, 36), y) != 0)
+        ABORT("file substr wrong");
+    f1b = fopen(FNAME1, "rb");
+    if (!f1b) ABORT("2nd open failed: " FNAME1);
+    z = CORD_from_file_lazy(f1b);
+    if (CORD_cmp(w,z) != 0) ABORT("File conversions differ");
+    if (CORD_chr(w, 0, '9') != 37) ABORT("CORD_chr failed 1");
+    if (CORD_chr(w, 3, 'a') != 38) ABORT("CORD_chr failed 2");
+    if (CORD_rchr(w, CORD_len(w) - 1, '}') != 1) ABORT("CORD_rchr failed");
+    x = y;
+    for (i = 1; i < 14; i++) {
+        x = CORD_cat(x,x);
+    }
+    if ((f = fopen(FNAME2, "w")) == 0) ABORT("2nd open failed");
+#   ifdef __DJGPP__
+      /* FIXME: DJGPP workaround.  Why does this help? */
+      if (fflush(f) != 0) ABORT("fflush failed");
+#   endif
+    if (CORD_put(x,f) == EOF) ABORT("CORD_put failed");
+    if (fclose(f) == EOF) ABORT("fclose failed");
+    f2 = fopen(FNAME2, "rb");
+    if (!f2) ABORT("Unable to open " FNAME2);
+    w = CORD_from_file(f2);
+    if (CORD_len(w) != CORD_len(x)) ABORT("file length wrong");
+    if (CORD_cmp(w,x) != 0) ABORT("file comparison wrong");
+    if (CORD_cmp(CORD_substr(w, 1000*36, 36), y) != 0)
+        ABORT("file substr wrong");
+    if (strcmp(CORD_to_char_star(CORD_substr(w, 1000*36, 36)), y) != 0)
+        ABORT("char * file substr wrong");
+    u = CORD_substr(w, 1000*36, 2);
+    if (!u) ABORT("CORD_substr returned NULL");
+    if (strcmp(u, "ab") != 0)
+        ABORT("short file substr wrong");
+    if (CORD_str(x,1,"9a") != 35) ABORT("CORD_str failed 1");
+    if (CORD_str(x,0,"9abcdefghijk") != 35) ABORT("CORD_str failed 2");
+    if (CORD_str(x,0,"9abcdefghijx") != CORD_NOT_FOUND)
+        ABORT("CORD_str failed 3");
+    if (CORD_str(x,0,"9>") != CORD_NOT_FOUND) ABORT("CORD_str failed 4");
+    /* Note: f1a, f1b, f2 handles are closed lazily by CORD library.    */
+    /* TODO: Propose and use CORD_fclose. */
+    *(CORD volatile *)&w = CORD_EMPTY;
+    *(CORD volatile *)&z = CORD_EMPTY;
+    GC_gcollect();
+    GC_invoke_finalizers();
+            /* Of course, this does not guarantee the files are closed. */
+    if (remove(FNAME1) != 0) {
+        /* On some systems, e.g. OS2, this may fail if f1 is still open. */
+        /* But we cannot call fclose as it might lead to double close.   */
+        fprintf(stderr, "WARNING: remove failed: " FNAME1 "\n");
+    }
+    if (remove(FNAME2) != 0) {
+        fprintf(stderr, "WARNING: remove failed: " FNAME2 "\n");
+    }
+}
+
+int wrap_vprintf(CORD format, ...)
+{
+    va_list args;
+    int result;
+
+    va_start(args, format);
+    result = CORD_vprintf(format, args);
+    va_end(args);
+    return result;
+}
+
+int wrap_vfprintf(FILE * f, CORD format, ...)
+{
+    va_list args;
+    int result;
+
+    va_start(args, format);
+    result = CORD_vfprintf(f, format, args);
+    va_end(args);
+    return result;
+}
+
+#if defined(__DJGPP__) || defined(__STRICT_ANSI__)
+  /* snprintf is missing in DJGPP (v2.0.3) */
+#else
+# if defined(_MSC_VER)
+#   if defined(_WIN32_WCE)
+      /* _snprintf is deprecated in WinCE */
+#     define GC_SNPRINTF StringCchPrintfA
+#   else
+#     define GC_SNPRINTF _snprintf
+#   endif
+# else
+#   define GC_SNPRINTF snprintf
+# endif
+#endif
+
+void test_printf(void)
+{
+    CORD result;
+    char result2[200];
+    long l = -1;
+    short s = (short)-1;
+    CORD x;
+
+    if (CORD_sprintf(&result, "%7.2f%ln", 3.14159F, &l) != 7)
+        ABORT("CORD_sprintf failed 1");
+    if (CORD_cmp(result, "   3.14") != 0)ABORT("CORD_sprintf goofed 1");
+    if (l != 7) ABORT("CORD_sprintf goofed 2");
+    if (CORD_sprintf(&result, "%-7.2s%hn%c%s", "abcd", &s, 'x', "yz") != 10)
+        ABORT("CORD_sprintf failed 2");
+    if (CORD_cmp(result, "ab     xyz") != 0)ABORT("CORD_sprintf goofed 3");
+    if (s != 7) ABORT("CORD_sprintf goofed 4");
+    x = "abcdefghij";
+    x = CORD_cat(x,x);
+    x = CORD_cat(x,x);
+    x = CORD_cat(x,x);
+    if (CORD_sprintf(&result, "->%-120.78r!\n", x) != 124)
+        ABORT("CORD_sprintf failed 3");
+#   ifdef GC_SNPRINTF
+        (void)GC_SNPRINTF(result2, sizeof(result2), "->%-120.78s!\n",
+                          CORD_to_char_star(x));
+#   else
+        (void)sprintf(result2, "->%-120.78s!\n", CORD_to_char_star(x));
+#   endif
+    result2[sizeof(result2) - 1] = '\0';
+    if (CORD_cmp(result, result2) != 0)ABORT("CORD_sprintf goofed 5");
+    /* TODO: Better test CORD_[v][f]printf.     */
+    (void)CORD_printf(CORD_EMPTY);
+    (void)wrap_vfprintf(stdout, CORD_EMPTY);
+    (void)wrap_vprintf(CORD_EMPTY);
+}
+
+int main(void)
+{
+#   ifdef THINK_C
+        printf("cordtest:\n");
+#   endif
+    GC_INIT();
+#   ifndef NO_INCREMENTAL
+      GC_enable_incremental();
+#   endif
+    if (GC_get_find_leak())
+        printf("This test program is not designed for leak detection mode\n");
+    test_basics();
+    test_extras();
+    test_printf();
+    CORD_fprintf(stdout, "SUCCEEDED\n");
+    return(0);
+}

+ 641 - 0
blitz.mod/bdwgc/cord/tests/de.c

@@ -0,0 +1,641 @@
+/*
+ * Copyright (c) 1993-1994 by Xerox Corporation.  All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/*
+ * A really simple-minded text editor based on cords.
+ * Things it does right:
+ *      No size bounds.
+ *      Unbounded undo.
+ *      Shouldn't crash no matter what file you invoke it on (e.g. /vmunix)
+ *              (Make sure /vmunix is not writable before you try this.)
+ *      Scrolls horizontally.
+ * Things it does wrong:
+ *      It doesn't handle tabs reasonably (use "expand" first).
+ *      The command set is MUCH too small.
+ *      The redisplay algorithm doesn't let curses do the scrolling.
+ *      The rule for moving the window over the file is suboptimal.
+ */
+
+#include <stdio.h>
+#include <stdlib.h> /* for exit() */
+
+#include "gc.h"
+#include "gc/cord.h"
+
+#ifdef THINK_C
+#define MACINTOSH
+#endif
+#include <ctype.h>
+
+#if (defined(__BORLANDC__) || defined(__CYGWIN__) || defined(__MINGW32__) \
+     || defined(__NT__) || defined(_WIN32)) && !defined(WIN32)
+    /* If this is DOS or win16, we'll fail anyway.      */
+    /* Might as well assume win32.                      */
+#   define WIN32
+#endif
+
+#if defined(WIN32)
+#  ifndef WIN32_LEAN_AND_MEAN
+#    define WIN32_LEAN_AND_MEAN 1
+#  endif
+#  define NOSERVICE
+#  include <windows.h>
+#  include "de_win.h"
+#elif defined(MACINTOSH)
+#       include <console.h>
+/* curses emulation. */
+#       define initscr()
+#       define endwin()
+#       define nonl()
+#       define noecho() csetmode(C_NOECHO, stdout)
+#       define cbreak() csetmode(C_CBREAK, stdout)
+#       define refresh()
+#       define addch(c) putchar(c)
+#       define standout() cinverse(1, stdout)
+#       define standend() cinverse(0, stdout)
+#       define move(line,col) cgotoxy(col + 1, line + 1, stdout)
+#       define clrtoeol() ccleol(stdout)
+#       define de_error(s) { fprintf(stderr, s); getchar(); }
+#       define LINES 25
+#       define COLS 80
+#else
+#  include <curses.h>
+#  include <unistd.h> /* for sleep() */
+#  define de_error(s) { fprintf(stderr, s); sleep(2); }
+#endif
+#include "de_cmds.h"
+
+#if defined(CPPCHECK)
+# define MACRO_BLKSTMT_BEGIN {
+# define MACRO_BLKSTMT_END   }
+#else
+# define MACRO_BLKSTMT_BEGIN do {
+# define MACRO_BLKSTMT_END   } while (0)
+#endif
+
+#define OUT_OF_MEMORY MACRO_BLKSTMT_BEGIN \
+                        fprintf(stderr, "Out of memory\n"); \
+                        exit(3); \
+                      MACRO_BLKSTMT_END
+
+/* List of line number to position mappings, in descending order. */
+/* There may be holes.                                            */
+typedef struct LineMapRep {
+    int line;
+    size_t pos;
+    struct LineMapRep * previous;
+} * line_map;
+
+/* List of file versions, one per edit operation */
+typedef struct HistoryRep {
+    CORD file_contents;
+    struct HistoryRep * previous;
+    line_map map;       /* Invalid for first record "now" */
+} * history;
+
+history now = 0;
+CORD current;           /* == now -> file_contents.     */
+size_t current_len;     /* Current file length.         */
+line_map current_map = 0;       /* Current line no. to pos. map  */
+size_t current_map_size = 0;    /* Number of current_map entries.       */
+                                /* Not always accurate, but reset       */
+                                /* by prune_map.                        */
+# define MAX_MAP_SIZE 3000
+
+/* Current display position */
+int dis_line = 0;
+int dis_col = 0;
+
+# define ALL -1
+# define NONE - 2
+int need_redisplay = 0; /* Line that needs to be redisplayed.   */
+
+
+/* Current cursor position. Always within file. */
+int line = 0;
+int col = 0;
+size_t file_pos = 0;    /* Character position corresponding to cursor.  */
+
+/* Invalidate line map for lines > i */
+void invalidate_map(int i)
+{
+    while(current_map -> line > i) {
+        current_map = current_map -> previous;
+        current_map_size--;
+    }
+}
+
+/* Reduce the number of map entries to save space for huge files. */
+/* This also affects maps in histories.                           */
+void prune_map(void)
+{
+    line_map map = current_map;
+    int start_line = map -> line;
+
+    current_map_size = 0;
+    do {
+        current_map_size++;
+        if (map -> line < start_line - LINES && map -> previous != 0) {
+            line_map pred = map -> previous -> previous;
+
+            GC_PTR_STORE_AND_DIRTY(&map->previous, pred);
+        }
+        map = map -> previous;
+    } while (map != 0);
+}
+
+/* Add mapping entry */
+void add_map(int line_arg, size_t pos)
+{
+    line_map new_map = GC_NEW(struct LineMapRep);
+    line_map cur_map;
+
+    if (NULL == new_map) OUT_OF_MEMORY;
+    if (current_map_size >= MAX_MAP_SIZE) prune_map();
+    new_map -> line = line_arg;
+    new_map -> pos = pos;
+    cur_map = current_map;
+    GC_PTR_STORE_AND_DIRTY(&new_map->previous, cur_map);
+    current_map = new_map;
+    current_map_size++;
+}
+
+
+
+/* Return position of column *c of ith line in   */
+/* current file. Adjust *c to be within the line.*/
+/* A 0 pointer is taken as 0 column.             */
+/* Returns CORD_NOT_FOUND if i is too big.       */
+/* Assumes i > dis_line.                         */
+size_t line_pos(int i, int *c)
+{
+    int j;
+    size_t cur;
+    line_map map = current_map;
+
+    while (map -> line > i) map = map -> previous;
+    if (map -> line < i - 2) /* rebuild */ invalidate_map(i);
+    for (j = map -> line, cur = map -> pos; j < i;) {
+        cur = CORD_chr(current, cur, '\n');
+        if (cur == current_len-1) return(CORD_NOT_FOUND);
+        cur++;
+        if (++j > current_map -> line) add_map(j, cur);
+    }
+    if (c != 0) {
+        size_t next = CORD_chr(current, cur, '\n');
+
+        if (next == CORD_NOT_FOUND) next = current_len - 1;
+        if (next < cur + *c) {
+            *c = (int)(next - cur);
+        }
+        cur += *c;
+    }
+    return(cur);
+}
+
+void add_hist(CORD s)
+{
+    history new_file = GC_NEW(struct HistoryRep);
+
+    if (NULL == new_file) OUT_OF_MEMORY;
+    new_file -> file_contents = current = s;
+    current_len = CORD_len(s);
+    new_file -> previous = now;
+    GC_END_STUBBORN_CHANGE(new_file);
+    if (now != NULL) {
+        now -> map = current_map;
+        GC_END_STUBBORN_CHANGE(now);
+    }
+    now = new_file;
+}
+
+void del_hist(void)
+{
+    now = now -> previous;
+    current = now -> file_contents;
+    current_map = now -> map;
+    current_len = CORD_len(current);
+}
+
+/* Current screen_contents; a dynamically allocated array of CORDs      */
+CORD * screen = 0;
+int screen_size = 0;
+
+# ifndef WIN32
+/* Replace a line in the curses stdscr. All control characters are      */
+/* displayed as upper case characters in standout mode.  This isn't     */
+/* terribly appropriate for tabs.                                                                       */
+void replace_line(int i, CORD s)
+{
+    CORD_pos p;
+#   if !defined(MACINTOSH)
+        size_t len = CORD_len(s);
+#   endif
+
+    if (screen == 0 || LINES > screen_size) {
+        screen_size = LINES;
+        screen = (CORD *)GC_MALLOC(screen_size * sizeof(CORD));
+        if (NULL == screen) OUT_OF_MEMORY;
+    }
+#   if !defined(MACINTOSH)
+        /* A gross workaround for an apparent curses bug: */
+        if (i == LINES-1 && len == (unsigned)COLS) {
+            s = CORD_substr(s, 0, len - 1);
+        }
+#   endif
+    if (CORD_cmp(screen[i], s) != 0) {
+        move(i, 0); clrtoeol(); move(i,0);
+
+        CORD_FOR (p, s) {
+            int c = CORD_pos_fetch(p) & 0x7f;
+
+            if (iscntrl(c)) {
+                standout(); addch(c + 0x40); standend();
+            } else {
+                addch(c);
+            }
+        }
+        GC_PTR_STORE_AND_DIRTY(screen + i, s);
+    }
+}
+#else
+# define replace_line(i,s) invalidate_line(i)
+#endif
+
+/* Return up to COLS characters of the line of s starting at pos,       */
+/* returning only characters after the given column.                    */
+CORD retrieve_line(CORD s, size_t pos, unsigned column)
+{
+    CORD candidate = CORD_substr(s, pos, column + COLS);
+                        /* avoids scanning very long lines      */
+    size_t eol = CORD_chr(candidate, 0, '\n');
+    int len;
+
+    if (eol == CORD_NOT_FOUND) eol = CORD_len(candidate);
+    len = (int)eol - (int)column;
+    if (len < 0) len = 0;
+    return(CORD_substr(s, pos + column, len));
+}
+
+# ifdef WIN32
+#   define refresh();
+
+    CORD retrieve_screen_line(int i)
+    {
+        size_t pos;
+
+        invalidate_map(dis_line + LINES);       /* Prune search */
+        pos = line_pos(dis_line + i, 0);
+        if (pos == CORD_NOT_FOUND) return(CORD_EMPTY);
+        return(retrieve_line(current, pos, dis_col));
+    }
+# endif
+
+/* Display the visible section of the current file       */
+void redisplay(void)
+{
+    int i;
+
+    invalidate_map(dis_line + LINES);   /* Prune search */
+    for (i = 0; i < LINES; i++) {
+        if (need_redisplay == ALL || need_redisplay == i) {
+            size_t pos = line_pos(dis_line + i, 0);
+
+            if (pos == CORD_NOT_FOUND) break;
+            replace_line(i, retrieve_line(current, pos, dis_col));
+            if (need_redisplay == i) goto done;
+        }
+    }
+    for (; i < LINES; i++) replace_line(i, CORD_EMPTY);
+done:
+    refresh();
+    need_redisplay = NONE;
+}
+
+int dis_granularity;
+
+/* Update dis_line, dis_col, and dis_pos to make cursor visible.        */
+/* Assumes line, col, dis_line, dis_pos are in bounds.                  */
+void normalize_display(void)
+{
+    int old_line = dis_line;
+    int old_col = dis_col;
+
+    dis_granularity = 1;
+    if (LINES > 15 && COLS > 15) dis_granularity = 2;
+    while (dis_line > line) dis_line -= dis_granularity;
+    while (dis_col > col) dis_col -= dis_granularity;
+    while (line >= dis_line + LINES) dis_line += dis_granularity;
+    while (col >= dis_col + COLS) dis_col += dis_granularity;
+    if (old_line != dis_line || old_col != dis_col) {
+        need_redisplay = ALL;
+    }
+}
+
+# if defined(WIN32)
+# elif defined(MACINTOSH)
+#               define move_cursor(x,y) cgotoxy(x + 1, y + 1, stdout)
+# else
+#               define move_cursor(x,y) move(y,x)
+# endif
+
+/* Adjust display so that cursor is visible; move cursor into position  */
+/* Update screen if necessary.                                          */
+void fix_cursor(void)
+{
+    normalize_display();
+    if (need_redisplay != NONE) redisplay();
+    move_cursor(col - dis_col, line - dis_line);
+    refresh();
+#   ifndef WIN32
+      fflush(stdout);
+#   endif
+}
+
+/* Make sure line, col, and dis_pos are somewhere inside file.  */
+/* Recompute file_pos.  Assumes dis_pos is accurate or past eof */
+void fix_pos(void)
+{
+    int my_col = col;
+
+    if ((size_t)line > current_len)
+        line = (int)current_len;
+    file_pos = line_pos(line, &my_col);
+    if (file_pos == CORD_NOT_FOUND) {
+        for (line = current_map -> line, file_pos = current_map -> pos;
+             file_pos < current_len;
+             line++, file_pos = CORD_chr(current, file_pos, '\n') + 1);
+        line--;
+        file_pos = line_pos(line, &col);
+    } else {
+        col = my_col;
+    }
+}
+
+#if defined(WIN32)
+#  define beep() Beep(1000 /* Hz */, 300 /* ms */)
+#elif defined(MACINTOSH)
+#  define beep() SysBeep(1)
+#else
+/*
+ * beep() is part of some curses packages and not others.
+ * We try to match the type of the builtin one, if any.
+ */
+  int beep(void)
+  {
+    putc('\007', stderr);
+    return(0);
+  }
+#endif /* !WIN32 && !MACINTOSH */
+
+#   define NO_PREFIX -1
+#   define BARE_PREFIX -2
+int repeat_count = NO_PREFIX;   /* Current command prefix. */
+
+int locate_mode = 0;                    /* Currently between 2 ^Ls      */
+CORD locate_string = CORD_EMPTY;        /* Current search string.       */
+
+char * arg_file_name;
+
+#ifdef WIN32
+/* Change the current position to whatever is currently displayed at    */
+/* the given SCREEN coordinates.                                        */
+void set_position(int c, int l)
+{
+    line = l + dis_line;
+    col = c + dis_col;
+    fix_pos();
+    move_cursor(col - dis_col, line - dis_line);
+}
+#endif /* WIN32 */
+
+/* Perform the command associated with character c.  C may be an        */
+/* integer > 256 denoting a windows command, one of the above control   */
+/* characters, or another ASCII character to be used as either a        */
+/* character to be inserted, a repeat count, or a search string,        */
+/* depending on the current state.                                      */
+void do_command(int c)
+{
+    int i;
+    int need_fix_pos;
+    FILE * out;
+
+    if ( c == '\r') c = '\n';
+    if (locate_mode) {
+        size_t new_pos;
+
+        if (c == LOCATE) {
+              locate_mode = 0;
+              locate_string = CORD_EMPTY;
+              return;
+        }
+        locate_string = CORD_cat_char(locate_string, (char)c);
+        new_pos = CORD_str(current, file_pos - CORD_len(locate_string) + 1,
+                           locate_string);
+        if (new_pos != CORD_NOT_FOUND) {
+            need_redisplay = ALL;
+            new_pos += CORD_len(locate_string);
+            for (;;) {
+                file_pos = line_pos(line + 1, 0);
+                if (file_pos > new_pos) break;
+                line++;
+            }
+            col = (int)(new_pos - line_pos(line, 0));
+            file_pos = new_pos;
+            fix_cursor();
+        } else {
+            locate_string = CORD_substr(locate_string, 0,
+                                        CORD_len(locate_string) - 1);
+            beep();
+        }
+        return;
+    }
+    if (c == REPEAT) {
+        repeat_count = BARE_PREFIX; return;
+    } else if (c < 0x100 && isdigit(c)){
+        if (repeat_count == BARE_PREFIX) {
+          repeat_count = c - '0'; return;
+        } else if (repeat_count != NO_PREFIX) {
+          repeat_count = 10 * repeat_count + c - '0'; return;
+        }
+    }
+    if (repeat_count == NO_PREFIX) repeat_count = 1;
+    if (repeat_count == BARE_PREFIX && (c == UP || c == DOWN)) {
+        repeat_count = LINES - dis_granularity;
+    }
+    if (repeat_count == BARE_PREFIX) repeat_count = 8;
+    need_fix_pos = 0;
+    for (i = 0; i < repeat_count; i++) {
+        switch(c) {
+          case LOCATE:
+            locate_mode = 1;
+            break;
+          case TOP:
+            line = col = 0;
+            file_pos = 0;
+            break;
+          case UP:
+            if (line != 0) {
+                line--;
+                need_fix_pos = 1;
+            }
+            break;
+          case DOWN:
+            line++;
+            need_fix_pos = 1;
+            break;
+          case LEFT:
+            if (col != 0) {
+                col--; file_pos--;
+            }
+            break;
+          case RIGHT:
+            if (CORD_fetch(current, file_pos) == '\n') break;
+            col++; file_pos++;
+            break;
+          case UNDO:
+            del_hist();
+            need_redisplay = ALL; need_fix_pos = 1;
+            break;
+          case BS:
+            if (col == 0) {
+                beep();
+                break;
+            }
+            col--; file_pos--;
+            /* FALLTHRU */
+          case DEL:
+            if (file_pos == current_len-1) break;
+                /* Can't delete trailing newline */
+            if (CORD_fetch(current, file_pos) == '\n') {
+                need_redisplay = ALL; need_fix_pos = 1;
+            } else {
+                need_redisplay = line - dis_line;
+            }
+            add_hist(CORD_cat(
+                        CORD_substr(current, 0, file_pos),
+                        CORD_substr(current, file_pos+1, current_len)));
+            invalidate_map(line);
+            break;
+          case WRITE:
+            {
+                CORD name = CORD_cat(CORD_from_char_star(arg_file_name),
+                                     ".new");
+
+                if ((out = fopen(CORD_to_const_char_star(name), "wb")) == NULL
+                    || CORD_put(current, out) == EOF) {
+                    de_error("Write failed\n");
+                    need_redisplay = ALL;
+                } else {
+                    fclose(out);
+                }
+            }
+            break;
+          default:
+            {
+                CORD left_part = CORD_substr(current, 0, file_pos);
+                CORD right_part = CORD_substr(current, file_pos, current_len);
+
+                add_hist(CORD_cat(CORD_cat_char(left_part, (char)c),
+                                  right_part));
+                invalidate_map(line);
+                if (c == '\n') {
+                    col = 0; line++; file_pos++;
+                    need_redisplay = ALL;
+                } else {
+                    col++; file_pos++;
+                    need_redisplay = line - dis_line;
+                }
+                break;
+            }
+        }
+    }
+    if (need_fix_pos) fix_pos();
+    fix_cursor();
+    repeat_count = NO_PREFIX;
+}
+
+/* OS independent initialization */
+
+void generic_init(void)
+{
+    FILE * f;
+    CORD initial;
+
+    if ((f = fopen(arg_file_name, "rb")) == NULL) {
+        initial = "\n";
+    } else {
+        size_t len;
+
+        initial = CORD_from_file(f);
+        len = CORD_len(initial);
+        if (0 == len || CORD_fetch(initial, len - 1) != '\n') {
+            initial = CORD_cat(initial, "\n");
+        }
+    }
+    add_map(0,0);
+    add_hist(initial);
+    now -> map = current_map;
+    now -> previous = now;  /* Can't back up further: beginning of the world */
+    GC_END_STUBBORN_CHANGE(now);
+    need_redisplay = ALL;
+    fix_cursor();
+}
+
+#ifndef WIN32
+
+int main(int argc, char **argv)
+{
+    int c;
+    void *buf;
+
+#   if defined(MACINTOSH)
+        console_options.title = "\pDumb Editor";
+        cshow(stdout);
+        argc = ccommand(&argv);
+#   endif
+    GC_set_find_leak(0); /* app is not for testing leak detection mode */
+    GC_INIT();
+#   ifndef NO_INCREMENTAL
+      GC_enable_incremental();
+#   endif
+
+    if (argc != 2) {
+        fprintf(stderr, "Usage: %s file\n", argv[0]);
+        fprintf(stderr, "Cursor keys: ^B(left) ^F(right) ^P(up) ^N(down)\n");
+        fprintf(stderr, "Undo: ^U    Write to <file>.new: ^W");
+        fprintf(stderr, "Quit:^D     Repeat count: ^R[n]\n");
+        fprintf(stderr, "Top: ^T     Locate (search, find): ^L text ^L\n");
+        exit(1);
+    }
+    arg_file_name = argv[1];
+    buf = GC_MALLOC_ATOMIC(8192);
+    if (NULL == buf) OUT_OF_MEMORY;
+    setvbuf(stdout, (char *)buf, _IOFBF, 8192);
+    initscr();
+    noecho(); nonl(); cbreak();
+    generic_init();
+    while ((c = getchar()) != QUIT) {
+        if (c == EOF) break;
+        do_command(c);
+    }
+    move(LINES-1, 0);
+    clrtoeol();
+    refresh();
+    nl();
+    echo();
+    endwin();
+    return 0;
+}
+
+#endif  /* !WIN32 */

+ 31 - 0
blitz.mod/bdwgc/cord/tests/de_cmds.h

@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+#ifndef DE_CMDS_H
+
+# define DE_CMDS_H
+
+# define UP     16      /* ^P */
+# define DOWN   14      /* ^N */
+# define LEFT   2       /* ^B */
+# define RIGHT  6       /* ^F */
+# define DEL    127     /* ^? */
+# define BS     8       /* ^H */
+# define UNDO   21      /* ^U */
+# define WRITE  23      /* ^W */
+# define QUIT   4       /* ^D */
+# define REPEAT 18      /* ^R */
+# define LOCATE 12      /* ^L */
+# define TOP    20      /* ^T */
+
+#endif

+ 387 - 0
blitz.mod/bdwgc/cord/tests/de_win.c

@@ -0,0 +1,387 @@
+/*
+ * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/*
+ * The MS Windows specific part of de.
+ * This started as the generic Windows application template
+ * but significant parts didn't survive to the final version.
+ *
+ * This was written by a nonexpert windows programmer.
+ */
+#if defined(__BORLANDC__) || defined(__CYGWIN__) || defined(__MINGW32__) \
+    || defined(__NT__) || defined(_WIN32) || defined(WIN32)
+
+#ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN 1
+#endif
+#define NOSERVICE
+#include <windows.h>
+
+#include "gc.h"
+#include "gc/cord.h"
+#include "de_cmds.h"
+#include "de_win.h"
+
+int LINES = 0;
+int COLS = 0;
+
+#define szAppName TEXT("DE")
+
+HWND        hwnd;
+
+void de_error(const char *s)
+{
+    (void)MessageBoxA(hwnd, s, "Demonstration Editor",
+                      MB_ICONINFORMATION | MB_OK);
+    InvalidateRect(hwnd, NULL, TRUE);
+}
+
+int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
+                      LPSTR command_line, int nCmdShow)
+{
+   MSG         msg;
+   WNDCLASS    wndclass;
+   HACCEL      hAccel;
+
+   GC_set_find_leak(0);
+   GC_INIT();
+#  ifndef NO_INCREMENTAL
+     GC_enable_incremental();
+#  endif
+#  if defined(CPPCHECK)
+     GC_noop1((GC_word)&WinMain);
+#  endif
+
+   if (!hPrevInstance)
+   {
+      wndclass.style          = CS_HREDRAW | CS_VREDRAW;
+      wndclass.lpfnWndProc    = WndProc;
+      wndclass.cbClsExtra     = 0;
+      wndclass.cbWndExtra     = DLGWINDOWEXTRA;
+      wndclass.hInstance      = hInstance;
+      wndclass.hIcon          = LoadIcon (hInstance, szAppName);
+      wndclass.hCursor        = LoadCursor (NULL, IDC_ARROW);
+      wndclass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);
+      wndclass.lpszMenuName   = TEXT("DE");
+      wndclass.lpszClassName  = szAppName;
+
+      if (RegisterClass (&wndclass) == 0) {
+          de_error("RegisterClass error");
+          return(0);
+      }
+   }
+
+   /* Empirically, the command line does not include the command name ...
+   if (command_line != 0) {
+       while (isspace(*command_line)) command_line++;
+       while (*command_line != 0 && !isspace(*command_line)) command_line++;
+       while (isspace(*command_line)) command_line++;
+   } */
+
+   if (command_line == 0 || *command_line == 0) {
+        de_error("File name argument required");
+        return( 0 );
+   } else {
+        char *p = command_line;
+
+        while (*p != 0 && !isspace(*(unsigned char *)p))
+            p++;
+        arg_file_name = CORD_to_char_star(
+                            CORD_substr(command_line, 0, p - command_line));
+   }
+
+   hwnd = CreateWindow (szAppName,
+                        TEXT("Demonstration Editor"),
+                        WS_OVERLAPPEDWINDOW | WS_CAPTION, /* Window style */
+                        CW_USEDEFAULT, 0, /* default pos. */
+                        CW_USEDEFAULT, 0, /* default width, height */
+                        NULL,   /* No parent */
+                        NULL,   /* Window class menu */
+                        hInstance, NULL);
+   if (hwnd == NULL) {
+        de_error("CreateWindow error");
+        return(0);
+   }
+
+   ShowWindow (hwnd, nCmdShow);
+
+   hAccel = LoadAccelerators( hInstance, szAppName );
+
+   while (GetMessage (&msg, NULL, 0, 0))
+   {
+      if( !TranslateAccelerator( hwnd, hAccel, &msg ) )
+      {
+         TranslateMessage (&msg);
+         DispatchMessage (&msg);
+      }
+   }
+   return (int)msg.wParam;
+}
+
+/* Return the argument with all control characters replaced by blanks.  */
+char * plain_chars(char * text, size_t len)
+{
+    char * result = (char *)GC_MALLOC_ATOMIC(len + 1);
+    size_t i;
+
+    if (NULL == result) return NULL;
+    for (i = 0; i < len; i++) {
+       if (iscntrl(((unsigned char *)text)[i])) {
+           result[i] = ' ';
+       } else {
+           result[i] = text[i];
+       }
+    }
+    result[len] = '\0';
+    return(result);
+}
+
+/* Return the argument with all non-control-characters replaced by      */
+/* blank, and all control characters c replaced by c + 64.              */
+char * control_chars(char * text, size_t len)
+{
+    char * result = (char *)GC_MALLOC_ATOMIC(len + 1);
+    size_t i;
+
+    if (NULL == result) return NULL;
+    for (i = 0; i < len; i++) {
+       if (iscntrl(((unsigned char *)text)[i])) {
+           result[i] = (char)(text[i] + 0x40);
+       } else {
+           result[i] = ' ';
+       }
+    }
+    result[len] = '\0';
+    return(result);
+}
+
+int char_width;
+int char_height;
+
+void get_line_rect(int line_arg, int win_width, RECT * rectp)
+{
+    rectp -> top = line_arg * (LONG)char_height;
+    rectp -> bottom = rectp->top + char_height;
+    rectp -> left = 0;
+    rectp -> right = win_width;
+}
+
+int caret_visible = 0;  /* Caret is currently visible.  */
+
+int screen_was_painted = 0;/* Screen has been painted at least once.    */
+
+void update_cursor(void);
+
+INT_PTR CALLBACK AboutBoxCallback( HWND hDlg, UINT message,
+                           WPARAM wParam, LPARAM lParam )
+{
+   (void)lParam;
+   switch( message )
+   {
+      case WM_INITDIALOG:
+           SetFocus( GetDlgItem( hDlg, IDOK ) );
+           break;
+
+      case WM_COMMAND:
+           switch( wParam )
+           {
+              case IDOK:
+                   EndDialog( hDlg, TRUE );
+                   break;
+           }
+           break;
+
+      case WM_CLOSE:
+           EndDialog( hDlg, TRUE );
+           return TRUE;
+
+   }
+   return FALSE;
+}
+
+LRESULT CALLBACK WndProc (HWND hwnd_arg, UINT message,
+                          WPARAM wParam, LPARAM lParam)
+{
+   static HINSTANCE hInstance;
+   HDC dc;
+   PAINTSTRUCT ps;
+   RECT client_area;
+   RECT this_line;
+   RECT dummy;
+   TEXTMETRIC tm;
+   int i;
+   int id;
+
+   switch (message)
+   {
+      case WM_CREATE:
+           hInstance = ( (LPCREATESTRUCT) lParam)->hInstance;
+           dc = GetDC(hwnd_arg);
+           SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT));
+           GetTextMetrics(dc, &tm);
+           ReleaseDC(hwnd_arg, dc);
+           char_width = tm.tmAveCharWidth;
+           char_height = tm.tmHeight + tm.tmExternalLeading;
+           GetClientRect(hwnd_arg, &client_area);
+           COLS = (client_area.right - client_area.left)/char_width;
+           LINES = (client_area.bottom - client_area.top)/char_height;
+           generic_init();
+           return(0);
+
+      case WM_CHAR:
+           if (wParam == QUIT) {
+               SendMessage(hwnd_arg, WM_CLOSE, 0, 0L);
+           } else {
+               do_command((int)wParam);
+           }
+           return(0);
+
+      case WM_SETFOCUS:
+           CreateCaret(hwnd_arg, NULL, char_width, char_height);
+           ShowCaret(hwnd_arg);
+           caret_visible = 1;
+           update_cursor();
+           return(0);
+
+      case WM_KILLFOCUS:
+           HideCaret(hwnd_arg);
+           DestroyCaret();
+           caret_visible = 0;
+           return(0);
+
+      case WM_LBUTTONUP:
+           {
+               unsigned xpos = LOWORD(lParam);  /* From left    */
+               unsigned ypos = HIWORD(lParam);  /* from top */
+
+               set_position(xpos / (unsigned)char_width,
+                            ypos / (unsigned)char_height);
+               return(0);
+           }
+
+      case WM_COMMAND:
+           id = LOWORD(wParam);
+           if (id & EDIT_CMD_FLAG) {
+               if (id & REPEAT_FLAG) do_command(REPEAT);
+               do_command(CHAR_CMD(id));
+               return( 0 );
+           } else {
+             switch(id) {
+               case IDM_FILEEXIT:
+                  SendMessage(hwnd_arg, WM_CLOSE, 0, 0L);
+                  return( 0 );
+
+               case IDM_HELPABOUT:
+                  if( DialogBox( hInstance, TEXT("ABOUTBOX"),
+                                 hwnd_arg, AboutBoxCallback ) )
+                     InvalidateRect(hwnd_arg, NULL, TRUE);
+                  return( 0 );
+               case IDM_HELPCONTENTS:
+                  de_error(
+                       "Cursor keys: ^B(left) ^F(right) ^P(up) ^N(down)\n"
+                       "Undo: ^U    Write: ^W   Quit:^D  Repeat count: ^R[n]\n"
+                       "Top: ^T   Locate (search, find): ^L text ^L\n");
+                  return( 0 );
+             }
+           }
+           break;
+
+      case WM_CLOSE:
+           DestroyWindow(hwnd_arg);
+           return 0;
+
+      case WM_DESTROY:
+           PostQuitMessage (0);
+           GC_win32_free_heap();
+           return 0;
+
+      case WM_PAINT:
+           dc = BeginPaint(hwnd_arg, &ps);
+           GetClientRect(hwnd_arg, &client_area);
+           COLS = (client_area.right - client_area.left)/char_width;
+           LINES = (client_area.bottom - client_area.top)/char_height;
+           SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT));
+           for (i = 0; i < LINES; i++) {
+               get_line_rect(i, client_area.right, &this_line);
+               if (IntersectRect(&dummy, &this_line, &ps.rcPaint)) {
+                   CORD raw_line = retrieve_screen_line(i);
+                   size_t len = CORD_len(raw_line);
+                   char * text = CORD_to_char_star(raw_line);
+                                /* May contain embedded NULLs   */
+                   char * plain = plain_chars(text, len);
+                   char * blanks = CORD_to_char_star(CORD_chars(' ',
+                                                                COLS - len));
+                   char * control = control_chars(text, len);
+                   if (NULL == plain || NULL == control)
+                       de_error("Out of memory!");
+
+#                  define RED RGB(255,0,0)
+
+                   SetBkMode(dc, OPAQUE);
+                   SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT));
+
+                   if (plain != NULL)
+                       TextOutA(dc, this_line.left, this_line.top,
+                                plain, (int)len);
+                   TextOutA(dc, this_line.left + (int)len * char_width,
+                            this_line.top,
+                            blanks, (int)(COLS - len));
+                   SetBkMode(dc, TRANSPARENT);
+                   SetTextColor(dc, RED);
+                   if (control != NULL)
+                       TextOutA(dc, this_line.left, this_line.top,
+                                control, (int)strlen(control));
+               }
+           }
+           EndPaint(hwnd_arg, &ps);
+           screen_was_painted = 1;
+           return 0;
+   }
+   return DefWindowProc(hwnd_arg, message, wParam, lParam);
+}
+
+int last_col;
+int last_line;
+
+void move_cursor(int c, int l)
+{
+    last_col = c;
+    last_line = l;
+
+    if (caret_visible) update_cursor();
+}
+
+void update_cursor(void)
+{
+    SetCaretPos(last_col * char_width, last_line * char_height);
+    ShowCaret(hwnd);
+}
+
+void invalidate_line(int i)
+{
+    RECT line_r;
+
+    if (!screen_was_painted) return;
+        /* Invalidating a rectangle before painting seems result in a   */
+        /* major performance problem.                                   */
+    get_line_rect(i, COLS*char_width, &line_r);
+    InvalidateRect(hwnd, &line_r, FALSE);
+}
+
+#else
+
+  extern int GC_quiet;
+        /* ANSI C doesn't allow translation units to be empty.  */
+        /* So we guarantee this one is nonempty.                */
+
+#endif /* !WIN32 */

+ 97 - 0
blitz.mod/bdwgc/cord/tests/de_win.h

@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/* cord.h, de_cmds.h, and windows.h should be included before this. */
+
+# define OTHER_FLAG     0x100
+# define EDIT_CMD_FLAG  0x200
+# define REPEAT_FLAG    0x400
+
+# define CHAR_CMD(i) ((i) & 0xff)
+
+/* MENU: DE */
+#define IDM_FILESAVE            (EDIT_CMD_FLAG + WRITE)
+#define IDM_FILEEXIT            (OTHER_FLAG + 1)
+#define IDM_HELPABOUT           (OTHER_FLAG + 2)
+#define IDM_HELPCONTENTS        (OTHER_FLAG + 3)
+
+#define IDM_EDITPDOWN           (REPEAT_FLAG + EDIT_CMD_FLAG + DOWN)
+#define IDM_EDITPUP             (REPEAT_FLAG + EDIT_CMD_FLAG + UP)
+#define IDM_EDITUNDO            (EDIT_CMD_FLAG + UNDO)
+#define IDM_EDITLOCATE          (EDIT_CMD_FLAG + LOCATE)
+#define IDM_EDITDOWN            (EDIT_CMD_FLAG + DOWN)
+#define IDM_EDITUP              (EDIT_CMD_FLAG + UP)
+#define IDM_EDITLEFT            (EDIT_CMD_FLAG + LEFT)
+#define IDM_EDITRIGHT           (EDIT_CMD_FLAG + RIGHT)
+#define IDM_EDITBS              (EDIT_CMD_FLAG + BS)
+#define IDM_EDITDEL             (EDIT_CMD_FLAG + DEL)
+#define IDM_EDITREPEAT          (EDIT_CMD_FLAG + REPEAT)
+#define IDM_EDITTOP             (EDIT_CMD_FLAG + TOP)
+
+
+
+
+/* Windows UI stuff     */
+
+LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
+                          WPARAM wParam, LPARAM lParam);
+
+/* Screen dimensions.  Maintained by de_win.c.  */
+extern int LINES;
+extern int COLS;
+
+/* File being edited.   */
+extern char * arg_file_name;
+
+/* Current display position in file.  Maintained by de.c        */
+extern int dis_line;
+extern int dis_col;
+
+/* Current cursor position in file.                             */
+extern int line;
+extern int col;
+
+/*
+ *  Calls from de_win.c to de.c
+ */
+
+CORD retrieve_screen_line(int i);
+                        /* Get the contents of i'th screen line.        */
+                        /* Relies on COLS.                              */
+
+void set_position(int x, int y);
+                        /* Set column, row.  Upper left of window = (0,0). */
+
+void do_command(int);
+                        /* Execute an editor command.                   */
+                        /* Agument is a command character or one        */
+                        /* of the IDM_ commands.                        */
+
+void generic_init(void);
+                        /* OS independent initialization */
+
+
+/*
+ * Calls from de.c to de_win.c
+ */
+
+void move_cursor(int column, int line);
+                        /* Physically move the cursor on the display,   */
+                        /* so that it appears at                        */
+                        /* (column, line).                              */
+
+void invalidate_line(int line);
+                        /* Invalidate line i on the screen.     */
+
+void de_error(const char *s);
+                        /* Display error message.       */

+ 70 - 0
blitz.mod/bdwgc/cord/tests/de_win.rc

@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+#include "windows.h"
+#include "de_cmds.h"
+#include "de_win.h"
+
+ABOUTBOX DIALOG 19, 21, 163, 47
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "About Demonstration Text Editor"
+BEGIN
+    LTEXT "Demonstration Text Editor", -1, 44, 8, 118, 8, WS_CHILD | WS_VISIBLE | WS_GROUP
+    PUSHBUTTON "OK", IDOK, 118, 27, 24, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+END
+
+DE MENU
+BEGIN
+    POPUP "&File"
+    BEGIN
+        MENUITEM "&Save\t^W", IDM_FILESAVE
+        MENUITEM "E&xit\t^D", IDM_FILEEXIT
+    END
+
+    POPUP "&Edit"
+    BEGIN
+        MENUITEM "Page &Down\t^R^N", IDM_EDITPDOWN
+        MENUITEM "Page &Up\t^R^P", IDM_EDITPUP
+        MENUITEM "U&ndo\t^U", IDM_EDITUNDO
+        MENUITEM "&Locate\t^L ... ^L", IDM_EDITLOCATE
+        MENUITEM "D&own\t^N", IDM_EDITDOWN
+        MENUITEM "U&p\t^P", IDM_EDITUP
+        MENUITEM "Le&ft\t^B", IDM_EDITLEFT
+        MENUITEM "&Right\t^F", IDM_EDITRIGHT
+        MENUITEM "Delete &Backward\tBS", IDM_EDITBS
+        MENUITEM "Delete F&orward\tDEL", IDM_EDITDEL
+        MENUITEM "&Top\t^T", IDM_EDITTOP
+    END
+
+    POPUP "&Help"
+    BEGIN
+        MENUITEM "&Contents", IDM_HELPCONTENTS
+        MENUITEM "&About...", IDM_HELPABOUT
+    END
+
+    MENUITEM "Page_&Down", IDM_EDITPDOWN
+    MENUITEM "Page_&Up", IDM_EDITPUP
+END
+
+DE ACCELERATORS
+BEGIN
+    "^R", IDM_EDITREPEAT
+    "^N", IDM_EDITDOWN
+    "^P", IDM_EDITUP
+    "^L", IDM_EDITLOCATE
+    "^B", IDM_EDITLEFT
+    "^F", IDM_EDITRIGHT
+    "^T", IDM_EDITTOP
+    VK_DELETE, IDM_EDITDEL, VIRTKEY
+    VK_BACK, IDM_EDITBS, VIRTKEY
+END

+ 12 - 9
blitz.mod/bdwgc/darwin_stop_world.c

@@ -81,7 +81,7 @@ GC_INNER ptr_t GC_FindTopOfStack(unsigned long stack_start)
   }
 
 # ifdef DEBUG_THREADS_EXTRA
-    GC_log_printf("FindTopOfStack start at sp = %p\n", (void *)frame);
+    GC_log_printf("FindTopOfStack start at sp= %p\n", (void *)frame);
 # endif
   while (frame->savedSP != 0) {
     /* if there are no more stack frames, stop */
@@ -95,7 +95,7 @@ GC_INNER ptr_t GC_FindTopOfStack(unsigned long stack_start)
       break; /* if the next LR is bogus, stop */
   }
 # ifdef DEBUG_THREADS_EXTRA
-    GC_log_printf("FindTopOfStack finish at sp = %p\n", (void *)frame);
+    GC_log_printf("FindTopOfStack finish at sp= %p\n", (void *)frame);
 # endif
   return (ptr_t)frame;
 }
@@ -199,13 +199,15 @@ STATIC ptr_t GC_stack_range_for(ptr_t *phi, thread_act_t thread, GC_thread p,
     /* else */ {
       mach_msg_type_number_t thread_state_count = GC_MACH_THREAD_STATE_COUNT;
 
-      /* Get the thread state (registers, etc) */
-      kern_result = thread_get_state(thread, GC_MACH_THREAD_STATE,
-                                     (natural_t *)&state,
-                                     &thread_state_count);
+      /* Get the thread state (registers, etc.) */
+      do {
+        kern_result = thread_get_state(thread, GC_MACH_THREAD_STATE,
+                                       (natural_t *)&state,
+                                       &thread_state_count);
+      } while (kern_result == KERN_ABORTED);
     }
 #   ifdef DEBUG_THREADS
-      GC_log_printf("thread_get_state returns value = %d\n", kern_result);
+      GC_log_printf("thread_get_state returns %d\n", kern_result);
 #   endif
     if (kern_result != KERN_SUCCESS)
       ABORT("thread_get_state failed");
@@ -235,7 +237,7 @@ STATIC ptr_t GC_stack_range_for(ptr_t *phi, thread_act_t thread, GC_thread p,
       GC_push_one(state.THREAD_FLD(rdi));
       GC_push_one(state.THREAD_FLD(rsi));
       GC_push_one(state.THREAD_FLD(rbp));
-      /* GC_push_one(state.THREAD_FLD(rsp)); */
+      /* rsp is skipped.        */
       GC_push_one(state.THREAD_FLD(r8));
       GC_push_one(state.THREAD_FLD(r9));
       GC_push_one(state.THREAD_FLD(r10));
@@ -251,6 +253,7 @@ STATIC ptr_t GC_stack_range_for(ptr_t *phi, thread_act_t thread, GC_thread p,
         *phi = GC_FindTopOfStack(state.THREAD_FLD(r1));
 #     endif
       GC_push_one(state.THREAD_FLD(r0));
+      /* r1 is skipped. */
       GC_push_one(state.THREAD_FLD(r2));
       GC_push_one(state.THREAD_FLD(r3));
       GC_push_one(state.THREAD_FLD(r4));
@@ -338,7 +341,7 @@ STATIC ptr_t GC_stack_range_for(ptr_t *phi, thread_act_t thread, GC_thread p,
     *paltstack_lo = NULL;
   }
 # ifdef DEBUG_THREADS
-    GC_log_printf("Darwin: Stack for thread %p = [%p,%p)\n",
+    GC_log_printf("Darwin: Stack for thread %p is [%p,%p)\n",
                   (void *)(word)thread, (void *)lo, (void *)(*phi));
 # endif
   return lo;

+ 6 - 6
blitz.mod/bdwgc/dbg_mlc.c

@@ -3,7 +3,7 @@
  * Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved.
  * Copyright (c) 1997 by Silicon Graphics.  All rights reserved.
  * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
- * Copyright (C) 2007 Free Software Foundation, Inc
+ * Copyright (c) 2007 Free Software Foundation, Inc.
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
@@ -414,14 +414,14 @@ STATIC void GC_print_obj(ptr_t p)
     }
 
     if (NULL != kind_str) {
-        GC_err_printf("%p (%s:%d," IF_NOT_SHORTDBG_HDRS(" sz=%lu,") " %s)\n",
+        GC_err_printf("%p (%s:%d," IF_NOT_SHORTDBG_HDRS(" sz= %lu,") " %s)\n",
                       (void *)((ptr_t)ohdr + sizeof(oh)),
                       ohdr->oh_string, GET_OH_LINENUM(ohdr) /*, */
                       COMMA_IFNOT_SHORTDBG_HDRS((unsigned long)ohdr->oh_sz),
                       kind_str);
     } else {
-        GC_err_printf("%p (%s:%d," IF_NOT_SHORTDBG_HDRS(" sz=%lu,")
-                      " kind=%d descr=0x%lx)\n",
+        GC_err_printf("%p (%s:%d," IF_NOT_SHORTDBG_HDRS(" sz= %lu,")
+                      " kind= %d, descr= 0x%lx)\n",
                       (void *)((ptr_t)ohdr + sizeof(oh)),
                       ohdr->oh_string, GET_OH_LINENUM(ohdr) /*, */
                       COMMA_IFNOT_SHORTDBG_HDRS((unsigned long)ohdr->oh_sz),
@@ -456,11 +456,11 @@ STATIC void GC_debug_print_heap_obj_proc(ptr_t p)
     if ((word)clobbered_addr <= (word)(&ohdr->oh_sz)
         || ohdr -> oh_string == 0) {
         GC_err_printf(
-                "%s %p in or near object at %p(<smashed>, appr. sz = %lu)\n",
+                "%s %p in or near object at %p(<smashed>, appr. sz= %lu)\n",
                 msg, (void *)clobbered_addr, p,
                 (unsigned long)(GC_size((ptr_t)ohdr) - DEBUG_BYTES));
     } else {
-        GC_err_printf("%s %p in or near object at %p (%s:%d, sz=%lu)\n",
+        GC_err_printf("%s %p in or near object at %p (%s:%d, sz= %lu)\n",
                 msg, (void *)clobbered_addr, p,
                 (word)(ohdr -> oh_string) < HBLKSIZE ? "(smashed string)" :
                 ohdr -> oh_string[0] == '\0' ? "EMPTY(smashed?)" :

+ 102 - 0
blitz.mod/bdwgc/digimars.mak

@@ -0,0 +1,102 @@
+# Makefile to build Hans Boehm garbage collector using the Digital Mars
+# compiler from www.digitalmars.com
+# Written by Walter Bright
+
+DEFINES=-D_WINDOWS -DGC_DLL -DGC_THREADS -DGC_DISCOVER_TASK_THREADS -DALL_INTERIOR_POINTERS -DENABLE_DISCLAIM -DGC_ATOMIC_UNCOLLECTABLE -DGC_GCJ_SUPPORT -DJAVA_FINALIZATION -DNO_EXECUTE_PERMISSION -DUSE_MUNMAP
+CFLAGS=-Iinclude -Ilibatomic_ops\src $(DEFINES) -wx -g
+LFLAGS=/ma/implib/co
+CC=sc
+
+.c.obj:
+	$(CC) -c $(CFLAGS) $*
+
+.cpp.obj:
+	$(CC) -c $(CFLAGS) -Aa $*
+
+OBJS=	\
+	allchblk.obj\
+	alloc.obj\
+	blacklst.obj\
+	checksums.obj\
+	dbg_mlc.obj\
+	fnlz_mlc.obj\
+	dyn_load.obj\
+	finalize.obj\
+	gc_badalc.obj\
+	gc_cpp.obj\
+	gcj_mlc.obj\
+	headers.obj\
+	mach_dep.obj\
+	malloc.obj\
+	mallocx.obj\
+	mark.obj\
+	mark_rts.obj\
+	misc.obj\
+	new_hblk.obj\
+	obj_map.obj\
+	os_dep.obj\
+	ptr_chck.obj\
+	reclaim.obj\
+	typd_mlc.obj\
+	win32_threads.obj
+
+targets: gc.dll gc.lib
+
+check: gctest.exe test_cpp.exe
+	gctest.exe
+	test_cpp.exe
+
+gc.lib: gc.dll
+
+gc.dll: $(OBJS) gc.def digimars.mak
+	$(CC) -ogc.dll $(OBJS) -L$(LFLAGS) gc.def kernel32.lib user32.lib
+
+gc.def: digimars.mak
+	echo LIBRARY GC >gc.def
+	echo DESCRIPTION "Boehm-Demers-Weiser Garbage Collector" >>gc.def
+	echo EXETYPE NT	>>gc.def
+	echo EXPORTS >>gc.def
+	echo GC_is_visible_print_proc >>gc.def
+	echo GC_is_valid_displacement_print_proc >>gc.def
+
+clean:
+	del *.log gc.def gc.dll gc.lib gc.map gctest.map test_cpp.map
+	del tests\test.obj gctest.exe tests\test_cpp.obj test_cpp.exe
+	del $(OBJS)
+
+gctest.exe: gc.lib tests\test.obj
+	$(CC) -ogctest.exe tests\test.obj gc.lib
+
+tests\test.obj: tests\test.c
+	$(CC) -c $(CFLAGS) tests\test.c -otests\test.obj
+
+test_cpp.exe: gc.lib tests\test_cpp.obj
+	$(CC) -otest_cpp.exe tests\test_cpp.obj gc.lib
+
+tests\test_cpp.obj: tests\test_cpp.cc
+	$(CC) -c $(CFLAGS) -cpp tests\test_cpp.cc -otests\test_cpp.obj
+
+allchblk.obj: allchblk.c
+alloc.obj: alloc.c
+blacklst.obj: blacklst.c
+checksums.obj: checksums.c
+dbg_mlc.obj: dbg_mlc.c
+dyn_load.obj: dyn_load.c
+finalize.obj: finalize.c
+fnlz_mlc.obj: fnlz_mlc.c
+gc_badalc.obj: gc_badalc.cc gc_badalc.cpp
+gc_cpp.obj: gc_cpp.cc gc_cpp.cpp
+headers.obj: headers.c
+mach_dep.obj: mach_dep.c
+malloc.obj: malloc.c
+mallocx.obj: mallocx.c
+mark.obj: mark.c
+mark_rts.obj: mark_rts.c
+misc.obj: misc.c
+new_hblk.obj: new_hblk.c
+obj_map.obj: obj_map.c
+os_dep.obj: os_dep.c
+ptr_chck.obj: ptr_chck.c
+reclaim.obj: reclaim.c
+typd_mlc.obj: typd_mlc.c
+win32_threads.obj: win32_threads.c

+ 39 - 0
blitz.mod/bdwgc/doc/README.DGUX386

@@ -0,0 +1,39 @@
+    Garbage Collector (parallel version) for x86 DG/UX Release R4.20MU07
+
+
+     *READ* the file README.md first.
+
+     You need the GCC-3.0.3 rev (DG/UX) compiler to build this tree.
+     This compiler has the new "dgux386" threads package implemented.
+     It also supports the switch "-pthread" needed to link correctly
+     the DG/UX's -lrte -lthread with -lgcc and the system's -lc.
+     Finally, we support parallel mark for the SMP DG/UX machines.
+     To build the garbage collector do:
+
+      ./configure
+      make
+      make gctest
+
+     Before you run "gctest" you need to set your LD_LIBRARY_PATH
+     correctly so that "gctest" can find the shared library libgc.
+     Alternatively you can do a configuration
+
+      ./configure --disable-shared
+
+     to build only the static version of libgc.
+
+     To enable debugging messages please do:
+     1) Add the "--enable-gc-debug" flag during configuration.
+     2) Pass "CFLAGS=-DDEBUG_THREADS" to "make".
+
+     In a machine with 4 CPUs (my own machine), parallel mark makes
+     a BIG difference.
+
+     Takis Psarogiannakopoulos
+
+Note (HB):
+     The integration of this patch is currently not complete.
+     The following patches against 6.1alpha3 where hard to move
+     to alpha4, and are not integrated.  There may also be minor
+     problems with stylistic corrections made by me.
+[The diff for ltconfig and ltmain.sh was removed from this file on 2011-08-22]

+ 332 - 0
blitz.mod/bdwgc/doc/README.Mac

@@ -0,0 +1,332 @@
+The contents of this file are old and pertain to pre-MacOSX versions.
+You probably really wanted README.darwin.
+
+---------------------------------------------
+
+Patrick Beard's Notes for building GC with CodeWarrior Pro 2:
+----------------------------------------------------------------------------
+The current build environment for the collector is CodeWarrior Pro 2.
+Projects for CodeWarrior Pro 2 (and for quite a few older versions)
+are distributed in the file Mac_projects.sit.hqx. The project file
+:Mac_projects:gc.prj builds static library versions of the collector.
+:Mac_projects:gctest.prj builds the GC test suite.
+
+Configuring the collector is still done by editing the file
+:extra:Mac_files:MacOS_config.h.
+
+Lars Farm's suggestions on building the collector:
+----------------------------------------------------------------------------
+Garbage Collection on MacOS - a manual 'MakeFile'
+-------------------------------------------------
+
+Project files and IDE's are great on the Macintosh, but they do have
+problems when used as distribution media. This note tries to provide
+porting instructions in pure TEXT form to avoid those problems. A manual
+'makefile' if you like.
+
+    Codewarrior:    CWPro1
+    date:           18 July 1997
+
+The notes may or may not apply to earlier or later versions of the CWPro.
+
+This is just to record my experiences. These notes do not mean I now
+provide a supported port of the GC to MacOS. It works for me. If it works
+for you, great. If it doesn't, sorry, try again...;-) Still, if you find
+errors, please let me know.
+
+
+Porting to MacOS is a bit more complex than it first seems. Which MacOS?
+68K/PowerPC? Which compiler? Each supports both 68K and PowerPC and offer a
+large number of (unique to each environment) compiler settings. Each
+combination of compiler/68K/PPC/settings require a unique combination of
+standard libraries. And the IDE's does not select them for you. They don't
+even check that the library is built with compatible setting and this is
+the major source of problems when porting the GC (and otherwise too).
+
+You will have to make choices when you configure the GC. I've made some
+choices here, but there are other combinations of settings and #defines
+that work too.
+
+As for target settings the major obstacles may be:
+- 68K Processor: check "4-byte Ints".
+- PPC Processor: uncheck "Store Static Data in TOC".
+
+What you need to do:
+1) Build the GC as a library
+2) Test that the library works with 'test.c'.
+3) Test that the C++ interface 'gc_cpp.cc/h' works with 'test_cpp.cc'.
+
+== 1. The Libraries ==
+
+I made one project with four targets (68K/PPC tempmem or appheap). One target
+will suffice if you're able to decide which one you want. I wasn't...
+
+Codewarrior allows a large number of compiler/linker settings. I used these:
+
+Settings shared by all targets:
+------------------------------
+o Access Paths:
+  - User Paths:   the GC folder
+  - System Paths: {Compiler}:Metrowerks Standard Library:
+                  {Compiler}:MacOS Support:Headers:
+                  {Compiler}:MacOS Support:MacHeaders:
+o C/C++ language:
+  - inlining: normal
+  - direct to SOM: off
+  - enable/check: exceptions, RTTI, bool (and if you like pool strings)
+
+PowerPC target settings
+-----------------------
+o Target Settings:
+  - name of target
+  - MacOS PPC Linker
+o PPC Target
+  - name of library
+o C/C++ language
+  - prefix file as described below
+o PPC Processor
+  - Struct Alignment: PowerPC
+  - uncheck "Store Static Data in TOC" -- important!
+    I don't think the others matter, I use full optimization and it is OK
+o PPC Linker
+  - Factory Settings (SYM file with full paths, faster linking, dead-strip
+    static init, Main: __start)
+
+
+68K target settings
+-------------------
+o Target Settings:
+  - name of target
+  - MacOS 68K Linker
+o 68K Target
+  - name of library
+  - A5 relative data
+o C/C++ language
+  - prefix file as described below
+o 68K Processor
+  - Code model: smart
+  - Struct alignment: 68K
+  - FP: SANE
+  - enable 4-Byte Ints -- important!
+    I don't think the others matter. I selected...
+  - enable: 68020
+  - enable: global register allocation
+o IR Optimizer
+  - enable: Optimize Space, Optimize Speed
+    I suppose the others would work too, but haven't tried...
+o 68K Linker
+  - Factory Settings (New Style MacsBug, SYM file with full paths,
+    A6 Frames, fast link, Merge compiler glue into segment 1,
+    dead-strip static init)
+
+Prefix Files to configure the GC sources
+----------------------------------------
+The Codewarrior equivalent of command-line compilers -DNAME=X is to use
+prefix-files. A TEXT file that is automatically #included before the first byte
+of every source file. I used these:
+
+---- ( cut here ) ----  gc_prefix_tempmem.h     -- 68K and PPC -----
+    #include "gc_prefix_common.h"
+    #undef USE_TEMPORARY_MEMORY
+    #define USE_TEMPORARY_MEMORY
+---- ( cut here ) ----  gc_prefix_appmem.h      -- 68K and PPC -----
+    #include "gc_prefix_common.h"
+    #undef USE_TEMPORARY_MEMORY
+//  #define USE_TEMPORARY_MEMORY
+
+---- ( cut here ) ----  gc_prefix_common.h      --------------------
+// gc_prefix_common.h
+// ------------------
+// Codewarrior prefix file to configure the GC libraries
+//
+//   prefix files are the Codewarrior equivalent of the
+//   command line option -Dname=x frequently seen in makefiles
+
+#if !__MWERKS__
+  #error only tried this with Codewarrior
+#endif
+
+#if macintosh
+  #define MSL_USE_PRECOMPILED_HEADERS 0
+  #include <ansi_prefix.mac.h>
+
+  //  See list of #defines to configure the library in: 'MakeFile'
+  //  see also README
+
+  #define ALL_INTERIOR_POINTERS // follows interior pointers.
+//#define DONT_ADD_BYTE_AT_END  // disables the padding if defined.
+//#define SMALL_CONFIG          // whether to use a smaller heap.
+  #define GC_ATOMIC_UNCOLLECTABLE // GC_malloc_atomic_uncollectable()
+
+  // define either or none as per personal preference
+  //   used in malloc.c
+  #define REDIRECT_MALLOC GC_malloc
+//#define REDIRECT_MALLOC GC_malloc_uncollectable
+  // if REDIRECT_MALLOC is #defined make sure that the GC library
+  // is listed before the ANSI/ISO libs in the Codewarrior
+  // 'Link order' panel
+//#define IGNORE_FREE
+
+  // mac specific configs
+//#define USE_TEMPORARY_MEMORY    // use Macintosh temporary memory.
+//#define SHARED_LIBRARY_BUILD    // build for use in a shared library.
+
+#else
+  // could build Win32 here too, or in the future
+  // Rhapsody PPC-mach, Rhapsody PPC-MacOS,
+  // Rhapsody Intel-mach, Rhapsody Intel-Win32,...
+  // ... ugh this will get messy ...
+#endif
+
+// make sure ints are at least 32-bit
+// ( could be set to 16-bit by compiler settings (68K) )
+
+struct gc_private_assert_intsize_{ char x[ sizeof(int)>=4 ? 1 : 0 ]; };
+
+#if __powerc
+  #if __option(toc_data)
+    #error turn off "store static data in TOC" when using GC
+    //     ... or find a way to add TOC to the root set...(?)
+  #endif
+#endif
+---- ( cut here ) ----  end of gc_prefix_common.h  -----------------
+
+Files to build the GC libraries:
+--------------------------------
+    allchblk.c
+    alloc.c
+    blacklst.c
+    checksums.c
+    dbg_mlc.c
+    finalize.c
+    fnlz_mlc.c
+    headers.c
+    mach_dep.c
+    extra/MacOS.c -- contains MacOS code
+    malloc.c
+    mallocx.c
+    mark.c
+    mark_rts.c
+    misc.c
+    new_hblk.c
+    obj_map.c
+    os_dep.c   -- contains MacOS code
+    ptr_chck.c
+    reclaim.c
+    typd_mlc.c
+    gc_badalc.cc
+    gc_cpp.cc
+
+== 2. Test that the library works with 'test.c' ==
+
+The test app is just an ordinary ANSI-C console app. Make sure settings
+match the library you're testing.
+
+Files
+-----
+    test.c
+    the GC library to test        -- link order before ANSI libs
+    suitable Mac+ANSI libraries
+
+prefix:
+------
+---- ( cut here ) ----  gc_prefix_testlib.h     -- all libs -----
+#define MSL_USE_PRECOMPILED_HEADERS 0
+#include <ansi_prefix.mac.h>
+#undef NDEBUG
+
+#define ALL_INTERIOR_POINTERS   /* for GC_priv.h */
+---- ( cut here ) ----
+
+== 3. Test that the C++ interface 'gc_cpp.cc/h' works with 'test_cpp.cc' ==
+
+The test app is just an ordinary ANSI-C console app. Make sure settings match
+the library you're testing.
+
+Files
+-----
+    test_cpp.cc
+    the GC library to test        -- link order before ANSI libs
+    suitable Mac+ANSI libraries
+
+prefix:
+------
+same as for test.c
+
+For convenience I used one test-project with several targets so that all
+test apps are build at once. Two for each library to test: test.c and
+gc_app.cc. When I was satisfied that the libraries were OK. I put the
+libraries + gc.h + the c++ interface-file in a folder that I then put into
+the MSL hierarchy so that I don't have to alter access-paths in projects
+that use the GC.
+
+After that, just add the proper GC library to your project and the GC is in
+action! malloc will call GC_malloc and free GC_free, new/delete too. You
+don't have to call free or delete. You may have to be a bit cautious about
+delete if you're freeing other resources than RAM. See gc_cpp.h. You can
+also keep coding as always with delete/free. That works too. If you want,
+include "gc.h" and tweak its use a bit.
+
+== Symantec SPM ==
+
+It has been a while since I tried the GC in SPM, but I think that the above
+instructions should be sufficient to guide you through in SPM too. SPM
+needs to know where the global data is. Use the files 'datastart.c' and
+'dataend.c'. Put 'datastart.c' at the top of your project and 'dataend.c'
+at the bottom  of your project so that all data is surrounded. This is not
+needed in Codewarrior because it provides intrinsic variables
+__datastart__, __data_end__ that wraps all globals.
+
+
+   It worked for me, hope it works for you.
+
+   Lars Farm
+----------------------------------------------------------------------------
+
+
+Patrick Beard's instructions (may be dated):
+
+The collector should run under Symantec C++/THINK C v7.0.4, and
+Metrowerks C/C++ v4.5 both 68K and PowerPC. Project files are provided
+to build and test the collector under both development systems.
+
+Configuration
+-------------
+
+To configure the collector, under both development systems, a prefix file
+is used to set preprocessor directives. This file is called "MacOS_config.h".
+
+Testing
+-------
+
+To test the collector (always a good idea), build one of the gctest projects,
+gctest. (Symantec C++/THINK C), mw/gctest.68K, or mw/gctest.PPC.  The
+test will ask you how many times to run; 1 should be sufficient.
+
+Building
+--------
+
+For your convenience project files for the major Macintosh development
+systems are provided.
+
+For Symantec C++/THINK C, you must build the two projects gclib-1 and
+gclib-2. It has to be split up because the collector has more than 32 KB
+of static data and no library can have more than this in the Symantec
+environment. (Future versions will probably fix this.)
+
+For Metrowerks C/C++ 4.5 you build gc.68K/PPC and the result will
+be a library called gc.68K.lib/gc.PPC.lib.
+
+Using
+-----
+
+Under Symantec C++/THINK C, you can just add the gclib-1 and gclib-2
+projects to your own project. Under Metrowerks, you add gc.68K.lib or
+gc.PPC.lib and two additional files. You add the files called datastart.c
+and dataend.c to your project, bracketing all files that use the collector.
+See mw/gctest for an example.
+
+Include the projects/libraries you built above into your own project,
+#include "gc.h", and call GC_malloc. You don't have to call GC_free.
+
+Patrick C. Beard

+ 6 - 0
blitz.mod/bdwgc/doc/README.OS2

@@ -0,0 +1,6 @@
+The code assumes static linking, and a single thread.  The editor de has
+not been ported.  The cord test program has.  The supplied OS2_MAKEFILE
+assumes the IBM C Set/2 environment, but the code shouldn't.
+
+Since we haven't figured out how to do partial linking or to build static
+libraries, clients currently need to link against a long list of executables.

+ 9 - 0
blitz.mod/bdwgc/doc/README.aix

@@ -0,0 +1,9 @@
+We have so far failed to find a good way to determine the stack base.
+It is highly recommended that GC_stackbottom be set explicitly on program
+startup.  The supplied value sometimes causes failure under AIX 4.1, though
+it appears to work under 3.X.  HEURISTIC2 seems to work under 4.1, but
+involves a substantial performance penalty, and will fail if there is
+no limit on stack size.
+
+There is no thread support.  (I assume recent versions of AIX provide
+pthreads?  I no longer have access to a machine ...)

+ 284 - 0
blitz.mod/bdwgc/doc/README.amiga

@@ -0,0 +1,284 @@
+            Kjetil S. Matheussen's notes (28-11-2000)
+
+Compiles under SAS/C again. Should also still compile under other
+Amiga compilers without big changes. I haven't checked if it still
+works under gcc, because I don't have gcc for Amiga. But I have
+updated 'Makefile', and hope it compiles fine.
+
+
+WHATS NEW:
+
+1.
+   Made a pretty big effort in preventing GC allocating-functions from
+   returning chip-mem.
+
+   The lower part of the new file AmigaOS.c does this in various ways, mainly by
+   wrapping GC_malloc, GC_malloc_atomic, GC_malloc_uncollectable,
+   GC_malloc_atomic_uncollectable, GC_malloc_ignore_off_page
+   and GC_malloc_atomic_ignore_off_page. GC_realloc is also wrapped, but
+   doesn't do the same effort in preventing to return chip-mem.
+   Other allocating-functions (e.g., GC_*_typed) can probably be
+   used without any problems, but beware that the warn hook will not be called.
+   In case of problems, don't define GC_AMIGA_FASTALLOC.
+
+   Programs using more time actually using the memory allocated
+   (instead of just allocate and free rapidly) have
+   the most to earn on this, but even gctest now normally runs twice
+   as fast and uses less memory, on my poor 8 MB machine.
+
+   The changes have only effect when there is no more
+   fast-mem left. But with the way GC works, it
+   could happen quite often. Beware that an atexit handler had to be added,
+   so using the abort() function will make a big memory-loss.
+   If you absolutely must call abort() instead of exit(), try calling
+   the GC_amiga_free_all_mem function before abort().
+
+   New Amiga-specific compilation flags:
+
+   GC_AMIGA_FASTALLOC - By NOT defining this option, GC will work like before,
+                        it will not try to force fast-mem out of the OS, and
+                        it will use normal calloc for allocation, and the rest
+                        of the following flags will have no effect.
+
+   GC_AMIGA_ONLYFAST - Makes GC never to return chip-mem. GC_AMIGA_RETRY have
+                       no effect if this flag is set.
+
+   GC_AMIGA_GC - If gc returns NULL, do a GC_gcollect, and try again. This
+                 usually is a success with the standard GC configuration.
+                 It is also the most important flag to set to prevent
+                 GC from returning chip-mem. Beware that it slows down a lot
+                 when a program is rapidly allocating/deallocating when
+                 there's either very little fast-memory left or very little
+                 chip-memory left. Its not a very common situation, but gctest
+                 sometimes (very rare) use many minutes because of this.
+
+   GC_AMIGA_RETRY - If gc succeed allocating memory, but it is chip-mem,
+                    try again and see if it is fast-mem. Most of the time,
+                    it will actually return fast-mem for the second try.
+                    I have set max number of retries to 9 or size/5000. You
+                    can change this if you like. (see GC_amiga_rec_alloc())
+
+   GC_AMIGA_PRINTSTATS - Gather some statistics during the execution of a
+                         program, and prints out the info when the atexit-handler
+                         is called.
+
+   My recommendation is to set all this flags, except GC_AMIGA_PRINTSTATS and
+   GC_AMIGA_ONLYFAST.
+
+   If your program demands high response-time, you should
+   not define GC_AMIGA_GC, and possible also define GC_AMIGA_ONLYFAST.
+   GC_AMIGA_RETRY does not seem to slow down much.
+
+   Also, when compiling up programs, and GC_AMIGA_FASTALLOC was not defined when
+   compiling gc, you can define GC_AMIGA_MAKINGLIB to avoid having these allocation-
+   functions wrapped. (see gc.h)
+
+   Note that GC_realloc must not be called before any of
+   the other above mentioned allocating-functions have been called. (shouldn't be
+   any programs doing so either, I hope).
+
+   Another note. The allocation-function is wrapped when defining
+   GC_AMIGA_FASTALLOC by letting the function go thru the new
+   GC_amiga_allocwrapper_do function-pointer (see gc.h). Means that
+   sending function-pointers, such as GC_malloc, GC_malloc_atomic, etc.,
+   for later to be called, e.g., like this, (*GC_malloc_function_pointer)(size),
+   will not wrap the function. This is normally not a big problem, unless
+   all allocation function is called like this, which will cause the
+   atexit un-allocating function never to be called. Then you either
+   have to manually add the atexit handler, or call the allocation-
+   functions function-pointer functions like this;
+   (*GC_amiga_allocwrapper_do)(size,GC_malloc_function_pointer).
+   There are probably better ways this problem could be handled, unfortunately,
+   I didn't find any without rewriting or replacing a lot of the GC-code, which
+   I really didn't want to. (Making new GC_malloc_* functions, and just
+   defining, e.g., GC_malloc as GC_amiga_malloc should work too).
+
+
+   New Amiga-specific function:
+
+     void GC_amiga_set_toany(void (*func)(void));
+
+   'func' is a function that will be called right before gc has to change
+   allocation-method from MEMF_FAST to MEMF_ANY. I.e., when it is likely
+   it will return chip-mem.
+
+
+2. A few small compiler-specific additions to make it compile with SAS/C again.
+
+3. Updated and rewritten the SMakefile.amiga, so that it works again and that
+   the "unnecessary" 'SCOPTIONS' files could be removed. Also included
+   the cord-smakefile stuff in the main smakefile, so that the cord smakefile
+   could be removed too. By typing "smake -f SMakefile.amiga", both gc.lib and
+   cord.lib will be made.
+
+
+
+STILL MISSING:
+
+Programs can not be started from workbench, at least not for SAS/C. (Martin
+Tauchmanns note about that it now works with workbench is definitely wrong
+when concerning SAS/C).  An iconx-script solves this problem.
+
+
+BEWARE!
+
+-To run gctest, set the stack to around 200000 bytes first.
+-SAS/C-specific: cord will crash if you compile gc.lib with
+ either parm=reg or parm=both. (missing legal prototypes for
+ function-pointers someplace is the reason I guess.).
+
+
+tested with software: Radium, http://www.stud.ifi.uio.no/~ksvalast/radium/
+tested with hardware: MC68060
+
+
+                           Martin Tauchmann's notes             (1-Apr-99)
+
+Works now, also with the GNU-C compiler V2.7.2.1. <ftp://ftp.unina.it/pub/amiga/geekgadgets/amiga/m68k/snapshots/971125/amiga-bin/>
+Modify the `Makefile`
+CC=cc $(ABI_FLAG)
+to
+CC=gcc $(ABI_FLAG)
+
+TECHNICAL NOTES
+
+- `GC_get_stack_base()`, `GC_register_data_segments()` works now with every
+   C compiler; also Workbench.
+
+- Removed AMIGA_SKIP_SEG, but the Code-Segment must not be scanned by GC.
+
+
+PROBLEMS
+- When the Linker, does`t merge all Code-Segments to an single one. LD of GCC
+  do it always.
+
+- With ixemul.library V47.3, when an GC program launched from another program
+  (example: `Make` or `if_mach M68K AMIGA gctest`), `GC_register_data_segments()`
+  found the Segment-List of the caller program.
+  Can be fixed, if the run-time initialization code (for C programs, usually *crt0*)
+  support `__data` and `__bss`.
+
+- PowerPC Amiga currently not supported.
+
+- Dynamic libraries (dyn_load.c) not supported.
+
+
+TESTED WITH SOFTWARE
+
+`Optimized Oberon 2 C` (oo2c) <http://cognac.informatik.uni-kl.de/download/index.html>
+
+
+TESTED WITH HARDWARE
+
+MC68030
+
+
+                           Michel Schinz's notes
+
+WHO DID WHAT
+
+The original Amiga port was made by Jesper Peterson. I (Michel Schinz)
+modified it slightly to reflect the changes made in the new official
+distributions, and to take advantage of the new SAS/C 6.x features. I also
+created a makefile to compile the "cord" package (see the cord
+subdirectory).
+
+TECHNICAL NOTES
+
+In addition to Jesper's notes, I have the following to say:
+
+- gctest checks to see if the code segment is added to the root set or not,
+  and complains if it is. The only problem is that, as far as I know, it is
+  impossible to know which segments are code segments and which are data
+  segments (there are indeed solutions to this problem, like scanning the
+  program on disk or patch the LoadSeg functions, but they are rather
+  complicated). The solution I have chosen (see os_dep.c) is to test whether
+  the program counter is in the segment we are about to add to the root set,
+  and if it is, to skip the segment. The problems are that this solution is
+  rather awkward and that it works only for one code segment. This means that
+  if your program has more than one code segment, all of them but one will be
+  added to the root set. This isn't a big problem in fact, since the
+  collector will continue to work correctly, but it may be slower.
+
+  Anyway, the code which decides whether to skip a segment or not can be
+  removed simply by not defining AMIGA_SKIP_SEG. But notice that if you do
+  so, gctest will complain (it will say that "GC_is_visible produced wrong
+  failure indication"). However, it may be useful if you happen to have
+  pointers stored in a code segment (you really shouldn't).
+
+  If anyone has a good solution to the problem of finding, when a program
+  is loaded in memory, whether a segment is a code or a data segment,
+  please let me know.
+
+
+                          Jesper Peterson's notes
+
+ADDITIONAL NOTES FOR AMIGA PORT
+
+These notes assume some familiarity with Amiga internals.
+
+WHY I PORTED TO THE AMIGA
+
+The sole reason why I made this port was as a first step in getting
+the Sather(*) language on the Amiga. A port of this language will
+be done as soon as the Sather 1.0 sources are made available to me.
+Given this motivation, the garbage collection (GC) port is rather
+minimal.
+
+(*) For information on Sather read the comp.lang.sather newsgroup.
+
+LIMITATIONS
+
+This port assumes that the startup code linked with target programs
+is that supplied with SAS/C versions 6.0 or later. This allows
+assumptions to be made about where to find the stack base pointer
+and data segments when programs are run from WorkBench, as opposed
+to running from the CLI. The compiler dependent code is all in the
+GC_get_stack_base() and GC_register_data_segments() functions, but
+may spread as I add Amiga specific features.
+
+Given that SAS/C was assumed, the port is set up to be built with
+"smake" using the "SMakefile". Compiler options in "SCoptions" can
+be set with "scopts" program. Both "smake" and "scopts" are part of
+the SAS/C commercial development system.
+
+In keeping with the porting philosophy outlined above, this port
+will not behave well with Amiga specific code. Especially not inter-
+process communications via messages, and setting up public structures like
+Intuition objects or anything else in the system lists. For the
+time being the use of this library is limited to single threaded
+ANSI/POSIX compliant or near-compliant code. (i.e., stick to stdio
+for now). Given this limitation there is currently no mechanism for
+allocating "CHIP" or "PUBLIC" memory under the garbage collector.
+I'll add this after giving it considerable thought. The major
+problem is the entire physical address space may have to me scanned,
+since there is no telling who we may have passed memory to.
+
+If you allocate your own stack in client code, you will have to
+assign the pointer plus stack size to GC_stackbottom.
+
+The initial stack size of the target program can be compiled in by
+setting the __stack symbol (see SAS documentation). It can be over-
+ridden from the CLI by running the AmigaDOS "stack" program, or from
+the WorkBench by setting the stack size in the tool types window.
+
+SAS/C COMPILER OPTIONS (SCoptions)
+
+You may wish to check the "CPU" code option is appropriate for your
+intended target system.
+
+Under no circumstances set the "StackExtend" code option in either
+compiling the library or *ANY* client code.
+
+All benign compiler warnings have been suppressed. These mainly
+involve lack of prototypes in the code, and dead assignments
+detected by the optimizer.
+
+THE GOOD NEWS
+
+The library as it stands is compatible with the GigaMem commercial
+virtual memory software, and probably similar PD software.
+
+The performance of "gctest" on an Amiga 2630 (68030 @ 25 MHz)
+compares favorably with an HP9000 with similar architecture (a 325
+with a 68030 I think).

+ 62 - 0
blitz.mod/bdwgc/doc/README.arm.cross

@@ -0,0 +1,62 @@
+From: Margaret Fleck
+
+Here's the key details of what worked for me, in case anyone else needs them.
+There may well be better ways to do some of this, but ....
+   -- Margaret
+
+
+The badge4 has a StrongArm-1110 processor and a StrongArm-1111 coprocessor.
+
+Assume that the garbage collector distribution is unpacked into /home/arm/gc,
+which is visible to both the ARM machine and a linux desktop (e.g. via NFS mounting).
+
+Assume that you have a file /home/arm/config.site with contents something like the
+example attached below.  Notice that our local ARM toolchain lives in
+/skiff/local.
+
+Go to /home/arm/gc directory.  Do
+  CONFIG_SITE=/home/arm/config.site ./configure --target=arm-linux
+--prefix=/home/arm/gc
+
+On your desktop, do:
+   make
+   make install
+The main garbage collector library should now be in ../gc/lib/libgc.so.
+
+To test the garbage collector, first do the following on your desktop
+   make gctest
+   ./gctest
+Then do the following on the ARM machine
+   cd .libs
+   ./lt-gctest
+
+Do not try to do "make check" (the usual way of running the test
+program).  This does not work and seems to erase some of the important
+files.
+
+The gctest program claims to have succeeded.  Haven't run any further tests
+with it, though I'll be doing so in the near future.
+
+-------------------------------
+# config.site for configure
+
+HOSTCC=gcc
+
+# Names of the cross-compilers
+CC=/skiff/local/bin/arm-linux-gcc
+CXX=/skiff/local/bin/arm-linux-gcc
+
+# The cross compiler specific options
+CFLAGS="-O2 -fno-exceptions"
+CXXFLAGS="-O2 -fno-exceptions"
+CPPFLAGS="-O2 -fno-exceptions"
+LDFLAGS=""
+
+# Some other programs
+AR=/skiff/local/bin/arm-linux-ar
+RANLIB=/skiff/local/bin/arm-linux-ranlib
+NM=/skiff/local/bin/arm-linux-nm
+ac_cv_path_NM=/skiff/local/bin/arm-linux-nm
+ac_cv_func_setpgrp_void=yes
+x_includes=/skiff/local/arm-linux/include/X11
+x_libraries=/skiff/local/arm-linux/lib/X11

+ 59 - 0
blitz.mod/bdwgc/doc/README.autoconf

@@ -0,0 +1,59 @@
+We support GNU-style builds based on automake, autoconf and libtool.
+This is based almost entirely on Tom Tromey's work with gcj.
+
+To build and install libraries use
+
+configure; make; make install
+
+The advantages of this process are:
+
+1) It should eventually do a better job of automatically determining the
+right compiler to use, etc.  It probably already does in some cases.
+
+2) It tries to automatically set a good set of default GC parameters for
+the platform (e.g. thread support).  It provides an easier way to configure
+some of the others.
+
+3) It integrates better with other projects using a GNU-style build process.
+
+4) It builds both dynamic and static libraries.
+
+The known disadvantages are:
+
+1) The build scripts are much more complex and harder to debug (though largely
+standard).  I don't understand them all, and there's probably lots of redundant
+stuff.
+
+2) It probably doesn't work on all Un*x-like platforms yet.  It probably will
+never work on the rest.
+
+3) The scripts are not yet complete.  Some of the standard GNU targets don't
+yet work.  (Corrections/additions are very welcome.)
+
+The distribution should contain all files needed to run "configure" and "make",
+as well as the sources needed to regenerate the derived files.  (If I missed
+some, please let me know.)
+
+Note that the distribution comes without "Makefile" which is generated by
+"configure".  The distribution also contains "Makefile.direct" which is not
+always equivalent to the generated one.
+
+Important options to configure:
+
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [/usr/local]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [same as prefix]
+  --enable-threads=TYPE   choose threading package
+  --disable-parallel-mark do not parallelize marking and free list
+                          construction
+  --enable-gc-debug       include full support for pointer back-tracing, etc.
+
+
+Unless --prefix is set (or --exec-prefix or one of the more obscure options),
+"make install" will install libgc.a and libgc.so in /usr/local/lib and
+/usr/local/bin, respectively, which would typically require the "make install"
+to be run as root.
+
+It is not recommended to turn off parallel marking for multiprocessors unless
+a poor support of the feature on the platform.

+ 62 - 0
blitz.mod/bdwgc/doc/README.cmake

@@ -0,0 +1,62 @@
+
+CMAKE
+-----
+
+Unix and Win32 binaries (both 32- and 64-bit) can be built using CMake.
+CMake is an open-source tool like automake - it generates makefiles.
+
+CMake v3.14.5 is able to generate:
+  Borland Makefiles
+  MSYS Makefiles
+  MinGW Makefiles
+  NMake Makefiles
+  Unix Makefiles
+  Visual Studio 16 2019
+  Visual Studio 15 2017
+  Visual Studio 14 2015
+  Visual Studio 12 2013
+  Visual Studio 11 2012
+  Visual Studio 10 2010
+  Visual Studio 9 2008
+  Watcom WMake
+
+
+BUILD PROCESS
+-------------
+
+ . install cmake (cmake.org)
+ . add directory containing cmake.exe to %PATH%
+ . run cmake from the gc root directory, passing the target with -G:
+   e.g.,
+      > cmake -G "Visual Studio 9 2008" .
+   use the gc.sln file generated by cmake to build gc
+ . specify -Denable_cplusplus=ON option to build gccpp (GC C++ support)
+ . specify -Dbuild_tests=ON option to the tests (and run them by "ctest -V")
+ . you can also run cmake from a build directory to build outside of
+   the source tree. Just specify the path to the source tree:
+   e.g.,
+      > mkdir out
+      > cd out
+      > cmake -G "Visual Studio 9 2008" ..
+      > cmake --build . --config Release
+      > ctest --build-config Release -V
+
+
+INPUT
+-----
+
+The main input to cmake is CMakeLists.txt file in the GC root directory.  For
+help, go to cmake.org.
+
+
+HOW TO IMPORT BDWGC
+-------------------
+
+Another project could add bdwgc as one of its dependencies with something like
+this in their CMakeLists.txt:
+
+find_package(BDWgc 8.2.0 REQUIRED)
+add_executable(Foo foo.c)
+target_link_libraries(Foo BDWgc::gc)
+
+Other exported libraries are: cord, gccpp, gctba.

+ 40 - 0
blitz.mod/bdwgc/doc/README.cords

@@ -0,0 +1,40 @@
+
+This is a string packages that uses a tree-based representation.
+See cord.h for a description of the functions provided.  Ec.h describes
+"extensible cords", which are essentially output streams that write
+to a cord.  These allow for efficient construction of cords without
+requiring a bound on the size of a cord.
+
+The cord library is built by default in case of the GNU autoconf-based build
+and the CMake-based one (unless "-Dbuild_cord=OFF" option is given to cmake).
+If you wish to build the library with the stand-alone Makefile.direct, type
+"make -f Makefile.direct cords".
+
+More details on the data structure can be found in:
+
+Boehm, Atkinson, and Plass, "Ropes: An Alternative to Strings",
+Software Practice and Experience 25, 12, December 1995, pp. 1315-1330.
+
+A fundamentally similar "rope" data structure is also part of SGI's standard
+template library implementation, and its descendants, which include the
+GNU C++ library.  That uses reference counting by default.
+There is a short description of that data structure at
+http://www.sgi.com/tech/stl/ropeimpl.html .
+
+All of these are descendants of the "ropes" in Xerox Cedar.
+
+cord/tests/de.c is a very dumb text editor that illustrates the use of cords.
+It maintains a list of file versions.  Each version is simply a
+cord representing the file contents.  Nonetheless, standard
+editing operations are efficient, even on very large files.
+(Its 3 line "user manual" can be obtained by invoking it without
+arguments.  Note that ^R^N and ^R^P move the cursor by
+almost a screen.  It does not understand tabs, which will show
+up as highlighted "I"s.  Use the UNIX "expand" program first.)
+To build the editor, type "make de" in the gc directory.
+
+Note that CORD_printf and friends use C functions with variable numbers
+of arguments in non-standard-conforming ways.  This code is known to
+break on some platforms, notably PowerPC.  It should be possible to
+build the remainder of the library (everything but cordprnt.c) on
+any platform that supports the collector.

+ 81 - 0
blitz.mod/bdwgc/doc/README.darwin

@@ -0,0 +1,81 @@
+Darwin/MacOSX Support - December 16, 2003
+
+== Build Notes ==
+
+Building can be done with autoconf as normal. If you want to build
+a Universal library using autoconf, you need to disable dependency
+tracking and specify your desired architectures in CFLAGS:
+
+CFLAGS="-arch ppc -arch i386 -arch x86_64" ./configure --disable-dependency-tracking
+
+
+== Important Usage Notes ==
+
+GC_INIT() MUST be called before calling any other GC functions. This
+is necessary to properly register segments in dynamic libraries. This
+call is required even if you code does not use dynamic libraries as the
+dyld code handles registering all data segments.
+
+When your use of the garbage collector is confined to dylibs and you
+cannot call GC_INIT() before your libraries' static initializers have
+run and perhaps called GC_malloc(), create an initialization routine
+for each library to call GC_INIT(), e.g.:
+
+#include "gc.h"
+extern "C" void my_library_init() { GC_INIT(); }
+
+Compile this code into a my_library_init.o, and link it into your
+dylib. When you link the dylib, pass the -init argument with
+_my_library_init (e.g. gcc -dynamiclib -o my_library.dylib a.o b.o c.o
+my_library_init.o -init _my_library_init). This causes
+my_library_init() to be called before any static initializers, and
+will initialize the garbage collector properly.
+
+Note: It doesn't hurt to call GC_INIT() more than once, so it's best,
+if you have an application or set of libraries that all use the
+garbage collector, to create an initialization routine for each of
+them that calls GC_INIT(). Better safe than sorry.
+
+Thread-local GC allocation will not work with threads that are not
+created using the GC-provided override of pthread_create(). Threads
+created without the GC-provided pthread_create() do not have the
+necessary data structures in the GC to store this data.
+
+
+== Implementation Information ==
+
+Darwin/MacOSX support is nearly complete. Thread support is reliable on
+Darwin 6.x (MacOSX 10.2) and there have been reports of success on older
+Darwin versions (MacOSX 10.1). Shared library support had also been
+added and the gc can be run from a shared library.
+
+Thread support is implemented in terms of mach thread_suspend and
+thread_resume calls. These provide a very clean interface to thread
+suspension. This implementation doesn't rely on pthread_kill so the
+code works on Darwin < 6.0 (MacOSX 10.1). All the code to stop and
+start the world is located in darwin_stop_world.c.
+
+Since not all uses of the GC enable clients to override pthread_create()
+before threads have been created, the code for stopping the world has
+been rewritten to look for threads using Mach kernel calls. Each
+thread identified in this way is suspended and resumed as above. In
+addition, since Mach kernel threads do not contain pointers to their
+stacks, a stack-walking function has been written to find the stack
+limits. Given an initial stack pointer (for the current thread, a
+pointer to a stack-allocated local variable will do; for a non-active
+thread, we grab the value of register 1 (on PowerPC)), it
+will walk the PPC Mach-O-ABI compliant stack chain until it reaches the
+top of the stack. This appears to work correctly for GCC-compiled C,
+C++, Objective-C, and Objective-C++ code, as well as for Java
+programs that use JNI. If you run code that does not follow the stack
+layout or stack pointer conventions laid out in the PPC Mach-O ABI,
+then this will likely crash the garbage collector.
+
+Mach has a very clean interface to exception handing. So, the current
+implementation of the incremental collection uses Mach's exception handling.
+
+Much thanks goes to Andrew Stone, Dietmar Planitzer, Andrew Begel,
+Jeff Sturm, and Jesse Rosenstock for all their work on the
+Darwin/OS X port.
+
+-Brian Alliet

+ 15 - 0
blitz.mod/bdwgc/doc/README.emscripten

@@ -0,0 +1,15 @@
+
+The build system (at least autotools-based) should detect and configure
+emscripten correctly.
+
+As of now, gctest almost passes, except for the tests that involve a_get().
+
+No thread support for now. No idea how to stop other threads (perhaps we need
+support from JS side).
+
+How to build:
+
+    # source EMSDK first
+    emconfigure ./configure
+    emmake make gctest.html
+    # point your browser at .libs/gctest.html

+ 185 - 0
blitz.mod/bdwgc/doc/README.environment

@@ -0,0 +1,185 @@
+The garbage collector looks at a number of environment variables which are,
+then, used to affect its operation.
+
+GC_INITIAL_HEAP_SIZE=<bytes> -  Initial heap size in bytes.  May speed up
+                                process start-up.  Optionally, may be
+                                specified with a multiplier ('k', 'M' or 'G')
+                                suffix.
+
+GC_MAXIMUM_HEAP_SIZE=<bytes> - Maximum collected heap size.  Allows
+                               a multiplier suffix.
+
+GC_LOOP_ON_ABORT - Causes the collector abort routine to enter a tight loop.
+                   This may make it easier to debug, such a process, especially
+                   for multi-threaded platforms that don't produce usable core
+                   files, or if a core file would be too large.  On some
+                   platforms, this also causes SIGSEGV to be caught and
+                   result in an infinite loop in a handler, allowing
+                   similar debugging techniques.
+
+GC_PRINT_STATS - Turn on GC logging.  Not functional with SMALL_CONFIG.
+
+GC_LOG_FILE - The name of the log file.  Stderr by default.  Not functional
+              with SMALL_CONFIG.
+
+GC_ONLY_LOG_TO_FILE - Turns off redirection of GC stdout and stderr to the log
+                      file specified by GC_LOG_FILE.  Has no effect unless
+                      GC_LOG_FILE is set.  Not functional with SMALL_CONFIG.
+
+GC_PRINT_VERBOSE_STATS - Turn on even more logging.  Not functional with
+                         SMALL_CONFIG.
+
+GC_DUMP_REGULARLY - Generate a GC debugging dump GC_dump() on startup
+                    and during every collection.  Very verbose.  Useful
+                    if you have a bug to report, but please include only the
+                    last complete dump.
+
+GC_COLLECT_AT_MALLOC=<n> - Override the default value specified by
+                           GC_COLLECT_AT_MALLOC macro.  Has no effect unless
+                           GC is built with GC_COLLECT_AT_MALLOC defined.
+
+GC_BACKTRACES=<n> - Generate n random back-traces (for heap profiling) after
+                    each GC.  Collector must have been built with
+                    KEEP_BACK_PTRS.  This won't generate useful output unless
+                    most objects in the heap were allocated through debug
+                    allocators.  This is intended to be only a statistical
+                    sample;  individual traces may be erroneous due to
+                    concurrent heap mutation.
+
+GC_PRINT_ADDRESS_MAP - Linux only.  Dump /proc/self/maps, i.e. various address
+                       maps for the process, to stderr on every GC.  Useful for
+                       mapping root addresses to source for deciphering leak
+                       reports.
+
+GC_NPROCS=<n> - Linux w/threads only.  Explicitly sets the number of processors
+                that the GC should expect to use.  Note that setting this to 1
+                when multiple processors are available will preserve
+                correctness, but may lead to really horrible performance,
+                since the lock implementation will immediately yield without
+                first spinning.
+
+GC_MARKERS=<n> - Only if compiled with PARALLEL_MARK.  Set the number
+                of marker threads.  This is normally set to the number of
+                processors.  It is safer to adjust GC_MARKERS than GC_NPROCS,
+                since GC_MARKERS has no impact on the lock implementation.
+
+GC_NO_BLACKLIST_WARNING - Prevents the collector from issuing
+                warnings about allocations of very large blocks.
+                Deprecated.  Use GC_LARGE_ALLOC_WARN_INTERVAL instead.
+
+GC_LARGE_ALLOC_WARN_INTERVAL=<n> - Print every nth warning about very large
+                block allocations, starting with the nth one.  Small values
+                of n are generally benign, in that a bounded number of
+                such warnings generally indicate at most a bounded leak.
+                For best results it should be set at 1 during testing.
+                Default is 5.  Very large numbers effectively disable the
+                warning.
+
+GC_IGNORE_GCJ_INFO - Ignore the type descriptors implicitly supplied by
+                     GC_gcj_malloc and friends.  This is useful for debugging
+                     descriptor generation problems, and possibly for
+                     temporarily working around such problems.  It forces a
+                     fully conservative scan of all heap objects except
+                     those known to be pointer-free, and may thus have other
+                     adverse effects.
+
+GC_PRINT_BACK_HEIGHT - Print max length of chain through unreachable objects
+                     ending in a reachable one.  If this number remains
+                     bounded, then the program is "GC robust".  This ensures
+                     that a fixed number of misidentified pointers can only
+                     result in a bounded space leak.  This currently only
+                     works if debugging allocation is used throughout.
+                     It increases GC space and time requirements appreciably.
+                     This feature is still somewhat experimental, and requires
+                     that the collector have been built with MAKE_BACK_GRAPH
+                     defined.  For details, see Boehm, "Bounding Space Usage
+                     of Conservative Garbage Collectors", POPL 2001
+                     (http://www.hpl.hp.com/techreports/2001/HPL-2001-251.html).
+
+GC_RETRY_SIGNALS -   Try to compensate for lost
+                     thread suspend and restart signals (Pthreads only).
+                     On by default for OSF1 (Tru64) or if the library is
+                     sanitized, off otherwise.  Since we've previously seen
+                     similar issues on some other operating systems, it
+                     was turned into a runtime flag to enable last-minute
+                     work-arounds.  "0" value means "do not retry signals".
+
+GC_USE_GETWRITEWATCH=<n> - Only if MPROTECT_VDB and (GWW_VDB or SOFT_VDB) are
+                     both defined (Win32 and Linux only).  Explicitly specify
+                     which strategy of keeping track of dirtied pages should
+                     be used.  If n=0, then fall back to protecting pages and
+                     catching memory faults strategy), else the collector
+                     tries to use GetWriteWatch-based strategy (GWW_VDB) or
+                     soft-dirty bits strategy (SOFT_VDB) first if available.
+
+GC_DISABLE_INCREMENTAL - Ignore runtime requests to enable incremental GC.
+                     Useful for debugging.
+
+The following turn on runtime flags that are also program settable.  Checked
+only during initialization.  We expect that they will usually be set through
+other means, but this may help with debugging and testing:
+
+GC_ENABLE_INCREMENTAL - Turn on incremental collection at startup.  Note that,
+                     depending on platform and collector configuration, this
+                     may involve write protecting pieces of the heap to
+                     track modifications.  These pieces may include
+                     pointer-free objects or not.  Although this is intended
+                     to be transparent, it may cause unintended system call
+                     failures.  Use with caution.
+
+GC_PAUSE_TIME_TARGET - Set the desired garbage collector pause time in
+                     milliseconds (ms).  This only has an effect if incremental
+                     collection is enabled.  If a collection requires
+                     appreciably more time than this, the client will be
+                     restarted, and the collector will need to do additional
+                     work to compensate.  The special value "999999" indicates
+                     that pause time is unlimited, and the incremental
+                     collector will behave completely like a simple
+                     generational collector.  Any value, except for the given
+                     special one, disables parallel marker (almost fully) for
+                     now.
+
+GC_FULL_FREQUENCY - Set the desired number of partial collections between full
+                    collections.  Matters only if GC_incremental is set.
+                    Not functional with SMALL_CONFIG.
+
+GC_FREE_SPACE_DIVISOR - Set GC_free_space_divisor to the indicated value.
+                      Setting it to larger values decreases space consumption
+                      and increases GC frequency.
+
+GC_UNMAP_THRESHOLD - Set the desired memory blocks unmapping threshold (the
+                   number of sequential garbage collections for which
+                   a candidate block for unmapping should remain free).  The
+                   special value "0" completely disables unmapping.
+
+GC_FORCE_UNMAP_ON_GCOLLECT - Turn "unmap as much as possible on explicit GC"
+                mode on (overrides the default value).  Has no effect on
+                implicitly-initiated garbage collections.  Has no effect if
+                memory unmapping is disabled (or not compiled in) or if the
+                unmapping threshold is 1.
+
+GC_FIND_LEAK - Turns on GC_find_leak and thus leak detection.  Forces a
+               collection at program termination to detect leaks that would
+               otherwise occur after the last GC.
+
+GC_FINDLEAK_DELAY_FREE - Turns on deferred freeing of objects in the
+                       leak-finding mode (see the corresponding macro
+                       description for more information).
+
+GC_ABORT_ON_LEAK - Causes the application to be terminated once leaked or
+                   smashed objects are found.
+
+GC_ALL_INTERIOR_POINTERS - Turns on GC_all_interior_pointers and thus interior
+                           pointer recognition.
+
+GC_DONT_GC - Turns off garbage collection.  Use cautiously.
+
+GC_USE_ENTIRE_HEAP - Set desired GC_use_entire_heap value at start-up.  See
+                     the similar macro description in README.macros.
+
+GC_TRACE=addr - Intended for collector debugging.  Requires that the collector
+                have been built with ENABLE_TRACE defined.  Causes the debugger
+                to log information about the tracing of address ranges
+                containing addr.  Typically addr is the address that contains
+                a pointer to an object that mysteriously failed to get marked.
+                Addr must be specified as a hexadecimal integer.

+ 81 - 0
blitz.mod/bdwgc/doc/README.ews4800

@@ -0,0 +1,81 @@
+GC on EWS4800
+-------------
+
+1. About EWS4800
+
+ EWS4800 is a 32/64-bit workstation.
+
+     Vendor: NEC Corporation
+     OS: UX/4800 R9.* - R13.* (SystemV R4.2)
+     CPU: R4000, R4400, R10000 (MIPS)
+
+2. Compiler
+
+ 32-bit:
+   Use ANSI C compiler.
+     CC = /usr/abiccs/bin/cc
+
+ 64-bit:
+   Use the 64-bit ANSI C compiler.
+     CC = /usr/ccs64/bin/cc
+     AR = /usr/ccs64/bin/ar
+
+3. ELF file format
+   *** Caution: The following information is empirical. ***
+
+ 32-bit:
+   ELF file has a unique format. (See a.out(4) and end(3C).)
+
+     &_start
+        :      text segment
+     &etext
+     DATASTART
+        :      data segment (initialized)
+     &edata
+     DATASTART2
+        :      data segment (uninitialized)
+     &end
+
+   Here, DATASTART and DATASTART2 are macros of GC, and are defined as
+   the following equations. (See include/private/gcconfig.h.)
+   The algorithm for DATASTART is similar with the function
+   GC_SysVGetDataStart() in os_dep.c.
+
+     DATASTART  = ((&etext + 0x3ffff) & ~0x3ffff) + (&etext & 0xffff)
+
+    Dynamically linked:
+     DATASTART2 = (&_gp + 0x8000 + 0x3ffff) & ~0x3ffff
+
+    Statically linked:
+     DATASTART2 = &edata
+
+   GC has to check addresses both between DATASTART and &edata, and
+   between DATASTART2 and &end. If a program accesses between &etext
+   and DATASTART, or between &edata and DATASTART2, the segmentation
+   error occurs and the program stops.
+
+   If a program is statically linked, there is not a gap between
+   &edata and DATASTART2. The global symbol &_DYNAMIC_LINKING is used
+   for the detection.
+
+ 64-bit:
+   ELF file has a simple format. (See end(3C).)
+
+     _ftext
+        :      text segment
+     _etext
+     _fdata = DATASTART
+        :      data segment (initialized)
+     _edata
+     _fbss
+        :      data segment (uninitialized)
+     _end = DATAEND
+
+--
+Hironori SAKAMOTO
+
+
+When using the new "configure; make" build process, please
+run configure with the --disable-shared option.  "Make check" does not
+yet pass with dynamic libraries.  The reasons for that are not yet
+understood.  (HB, paraphrasing message from Hironori SAKAMOTO.)

+ 18 - 0
blitz.mod/bdwgc/doc/README.hp

@@ -0,0 +1,18 @@
+Dynamic loading support requires that executables be linked with -ldld.
+The alternative is to build the collector without defining DYNAMIC_LOADING
+in gcconfig.h and ensuring that all garbage collectible objects are
+accessible without considering statically allocated variables in dynamic
+libraries.
+
+The collector should compile with either plain cc or cc -Ae.  Cc -Aa
+fails to define _HPUX_SOURCE and thus will not configure the collector
+correctly.
+
+Incremental collection support was added recently, and should now work.
+
+In spite of past claims, pthread support under HP/UX 11 should now work.
+Define GC_THREADS macro for the build.  Incremental collection still does not
+work in combination with it.
+
+The stack finding code can be confused by putenv calls before collector
+initialization.  Call GC_malloc() or GC_INIT() before any putenv() calls.

+ 127 - 0
blitz.mod/bdwgc/doc/README.linux

@@ -0,0 +1,127 @@
+See README.alpha for Linux on DEC AXP info.
+
+This file applies mostly to Linux/Intel IA-32.  Ports to Linux on an M68K,
+IA-64, SPARC, MIPS, Alpha and PowerPC are integrated too.  They should behave
+similarly, except that the PowerPC port lacks incremental GC support, and
+it is unknown to what extent the Linux threads code is functional.
+See below for M68K specific notes.
+
+Incremental GC is generally supported.
+
+Dynamic libraries are supported on an ELF system.
+
+The collector appears to work reliably with Linux threads, but beware
+of older versions of glibc and gdb.
+
+The garbage collector uses SIGPWR and SIGXCPU if it is used with
+Linux threads.  These should not be touched by the client program.
+
+To use threads, you need to abide by the following requirements:
+
+1) You need to use LinuxThreads or NPTL (which are included in libc6).
+
+   The collector relies on some implementation details of the LinuxThreads
+   package.  This code may not work on other
+   pthread implementations (in particular it will *not* work with
+   MIT pthreads).
+
+2) You must compile the collector with "-DGC_THREADS -D_REENTRANT" specified
+   in the Makefile.direct file.
+
+3a) Every file that makes thread calls should define GC_THREADS, and then
+   include gc.h.  The latter redefines some of the pthread primitives as
+   macros which also provide the collector with information it requires.
+
+3b) A new alternative to (3a) is to build the collector and compile GC clients
+   with -DGC_USE_LD_WRAP, and to link the final program with
+
+   (for ld) --wrap dlopen --wrap pthread_create \
+            --wrap pthread_join --wrap pthread_detach \
+            --wrap pthread_sigmask --wrap pthread_exit --wrap pthread_cancel
+
+   (for gcc) -Wl,--wrap -Wl,dlopen -Wl,--wrap -Wl,pthread_create \
+             -Wl,--wrap -Wl,pthread_join -Wl,--wrap -Wl,pthread_detach \
+             -Wl,--wrap -Wl,pthread_sigmask -Wl,--wrap -Wl,pthread_exit \
+             -Wl,--wrap -Wl,pthread_cancel
+
+   In any case, _REENTRANT should be defined during compilation.
+
+4) Dlopen() disables collection during its execution.  (It can't run
+   concurrently with the collector, since the collector looks at its
+   data structures.  It can't acquire the allocator lock, since arbitrary
+   user startup code may run as part of dlopen().)  Under unusual
+   conditions, this may cause unexpected heap growth.
+
+5) The combination of GC_THREADS, REDIRECT_MALLOC, and incremental
+   collection is probably not fully reliable, though it now seems to work
+   in simple cases.
+
+6) Thread local storage may not be viewed as part of the root set by the
+   collector.  This probably depends on the linuxthreads version.  For the
+   time being, any collectible memory referenced by thread local storage
+   should also be referenced from elsewhere, or be allocated as uncollectible.
+   (This is really a bug that should be fixed somehow.  Actually, the
+   collector probably gets things right, on Linux at least, if there are not
+   too many tls locations and if dlopen is not used.)
+
+
+M68K LINUX:
+(From Richard Zidlicky)
+The bad news is that it can crash every linux-m68k kernel on a 68040,
+so an additional test is needed somewhere on startup. I have meanwhile
+patches to correct the problem in 68040 buserror handler but it is not
+yet in any standard kernel.
+
+Here is a simple test program to detect whether the kernel has the
+problem. It could be run as a separate check in configure or tested
+upon startup. If it fails (return !0) than mprotect can't be used
+on that system.
+
+/*
+ * test for bug that may crash 68040 based Linux
+ */
+
+#include <sys/mman.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+char *membase;
+int pagesize=4096;
+int pageshift=12;
+int x_taken=0;
+
+int sighandler(int sig)
+{
+   mprotect(membase,pagesize,PROT_READ|PROT_WRITE);
+   x_taken=1;
+}
+
+main()
+{
+  long l;
+
+   signal(SIGSEGV,sighandler);
+   l=(long)mmap(NULL,pagesize,PROT_READ,MAP_PRIVATE | MAP_ANON,-1,0);
+  if (l==-1)
+     {
+       perror("mmap/malloc");
+       abort();
+     }
+  membase=(char*)l;
+    *(long*)(membase+sizeof(long))=123456789;
+  if (*(long*)(membase+sizeof(long)) != 123456789 )
+    {
+      fprintf(stderr,"writeback failed !\n");
+      exit(1);
+    }
+  if (!x_taken)
+    {
+      fprintf(stderr,"exception not taken !\n");
+      exit(1);
+    }
+  fprintf(stderr,"vmtest Ok\n");
+  exit(0);
+}

+ 605 - 0
blitz.mod/bdwgc/doc/README.macros

@@ -0,0 +1,605 @@
+The collector uses a large amount of conditional compilation in order to
+deal with platform dependencies.  This violates a number of known coding
+standards.  On the other hand, it seems to be the only practical way to
+support this many platforms without excessive code duplication.
+
+A few guidelines have mostly been followed in order to keep this manageable:
+
+1) #if and #ifdef directives are properly indented whenever easily possible.
+All known C compilers allow whitespace between the "#" and the "if" to make
+this possible.  ANSI C also allows white space before the "#", though we
+avoid that.  It has the known disadvantages that it differs from the normal
+GNU conventions, and that it makes patches larger than otherwise necessary.
+In my opinion, it's still well worth it, for the same reason that we indent
+ordinary "if" statements.
+
+2) Whenever possible, tests are performed on the macros defined in gcconfig.h
+instead of directly testing platform-specific predefined macros.  This makes
+it relatively easy to adapt to new compilers with a different set of
+predefined macros.  Currently these macros generally identify platforms
+instead of features.  In many cases, this is a mistake.
+
+Many of the tested configuration macros are at least somewhat defined in
+either include/private/gcconfig.h or in Makefile.direct.  Here is an attempt
+at documenting these macros:  (Thanks to Walter Bright for suggesting
+this.)
+
+MACRO           EXPLANATION
+-----           -----------
+
+GC_DEBUG        Tested by gc.h.  Causes all-upper-case macros to
+                expand to calls to debug versions of collector routines.
+
+GC_NAMESPACE    Tested by gc_cpp.h. Causes gc_cpp symbols to be defined
+                in "boehmgc" namespace.
+
+GC_DEBUG_REPLACEMENT    Tested by gc.h. Causes GC_MALLOC/REALLOC() to be
+                defined as GC_debug_malloc/realloc_replacement().
+
+GC_NO_THREAD_REDIRECTS  Tested by gc.h.  Prevents redirection of thread
+                creation routines etc. to GC_ versions.  Requires the
+                programmer to explicitly handle thread registration.
+
+GC_NO_THREAD_DECLS      Tested by gc.h.  MS Windows only.  Do not declare
+                Windows thread creation routines and do not include windows.h.
+
+GC_DONT_INCLUDE_WINDOWS_H   Tested by gc.h.  MS Windows only.  Do not include
+                windows.h from gc.h (but Windows-specific thread creation
+                routines are declared).
+
+GC_UNDERSCORE_STDCALL   Tested by gc.h.  Explicitly prefix exported/imported
+                WINAPI (__stdcall) symbols with '_' (underscore).  Could be
+                used with MinGW (for x86) compiler (in conjunction with
+                GC_DLL) to follow MS conventions for __stdcall symbols naming.
+
+_ENABLE_ARRAYNEW
+                #define'd by the Digital Mars C++ compiler when
+                operator new[] and delete[] are separately
+                overloadable. Used in gc_cpp.h.
+
+GC_NO_INLINE_STD_NEW    Tested by gc_cpp.cc and gc_cpp.h.  MS Windows only.
+                Define the system-wide new and delete operators in gccpp.dll
+                instead of providing an inline version of the operators.
+
+_DLL            Tested by gc_config_macros.h. Defined by Visual C++ if runtime
+                dynamic libraries are in use.  Used (only if none of GC_DLL,
+                GC_NOT_DLL, __GNUC__ are defined) to test whether
+                __declspec(dllimport) needs to be added to declarations
+                to support the case in which the collector is in a DLL.
+
+GC_DLL          Defined by user if dynamic libraries are being built
+                or used.  Also set by gc.h if _DLL is defined (except for
+                mingw) while GC_NOT_DLL and __GNUC__ are both undefined.
+                This is the macro that is tested internally to determine
+                whether the GC is in its own dynamic library.  May need
+                to be set by clients before including gc.h.  Note that
+                inside the GC implementation it indicates that the
+                collector is in its own dynamic library, should export
+                its symbols, etc.  But in clients it indicates that the
+                GC resides in a different DLL, its entry points should
+                be referenced accordingly, and precautions may need to
+                be taken to properly deal with statically allocated
+                variables in the main program.  Used for MS Windows.
+                Also used by GCC v4+ (only when the dynamic shared library
+                is being built) to hide internally used symbols.
+
+GC_NOT_DLL      User-settable macro that overrides _DLL, e.g. if runtime
+                dynamic libraries are used, but the collector is in a static
+                library.  Tested by gc_config_macros.h.
+
+GC_MARKERS=<n>  Set the desired number of marker threads.  If not defined or
+                defined to zero, then the collector decides based on the
+                number of CPU cores.  Only if compiled with PARALLEL_MARK.
+
+
+These define arguments influence the collector configuration:
+
+GC_REQUIRE_WCSDUP       Force GC to export GC_wcsdup() (the Unicode version
+  of GC_strdup); could be useful in the leak-finding mode.  Clients should
+  define it before including gc.h if the function is needed.
+
+FIND_LEAK       Causes GC_find_leak to be initially set.  This causes the
+  collector to assume that all inaccessible objects should have been
+  explicitly deallocated, and reports exceptions.  Finalization and the test
+  program are not usable in this mode.
+
+GC_FINDLEAK_DELAY_FREE  Turns on deferred freeing of objects in the
+  leak-finding mode letting the collector to detect alter-object-after-free
+  errors as well as detect leaked objects sooner (instead of only when program
+  terminates).  Has no effect if SHORT_DBG_HDRS.
+
+GC_ABORT_ON_LEAK        Causes the application to be terminated once leaked or
+  smashed (corrupted on use-after-free) objects are found (after printing the
+  information about that objects).
+
+SUNOS5SIGS      Solaris-like signal handling.  This is probably misnamed,
+  since it really doesn't guarantee much more than POSIX.  Currently set only
+  for Solaris2.X, HPUX, and DRSNX.  Should probably be set for some other
+  platforms.
+
+PCR     Set if the collector is being built as part of the Xerox Portable
+  Common Runtime.
+
+GC_THREADS      Should set the appropriate one of the below macros,
+  except GC_WIN32_PTHREADS, which must be set explicitly.  Tested by gc.h.
+  IMPORTANT: GC_THREADS macro (or the relevant platform-specific deprecated
+  one) must normally also be defined by the client before including gc.h.
+  This redefines thread primitives to invoke the GC_ wrappers instead.
+  Alternatively, linker-based symbol interception can be used on a few
+  platforms.
+
+GC_SOLARIS_THREADS      Enables support for Solaris pthreads.
+  Must also define _REENTRANT.  Deprecated, use GC_THREADS instead.
+
+GC_IRIX_THREADS         Enables support for Irix pthreads.  See README.sgi.
+  Deprecated, use GC_THREADS instead.
+
+GC_HPUX_THREADS         Enables support for HP/UX 11 pthreads.
+  Also requires _REENTRANT or _POSIX_C_SOURCE=199506L. See README.hp.
+  Deprecated, use GC_THREADS instead.
+
+GC_LINUX_THREADS        Enables support for Xavier Leroy's Linux threads
+  or NPTL threads.  See README.linux.  _REENTRANT may also be required.
+  Deprecated, use GC_THREADS instead.
+
+GC_OSF1_THREADS         Enables support for Tru64 pthreads.  Deprecated, use
+  GC_THREADS instead.
+
+GC_FREEBSD_THREADS      Enables support for FreeBSD pthreads.  Appeared to run
+  into some underlying thread problems.  Deprecated, use GC_THREADS instead.
+
+GC_NETBSD_THREADS       Enables support for NetBSD pthreads.  Deprecated, use
+  GC_THREADS instead.
+
+GC_OPENBSD_THREADS      Enables support for OpenBSD pthreads.  Deprecated,
+  use GC_THREADS instead.
+
+GC_DARWIN_THREADS       Enables support for Mac OS X pthreads.  Deprecated,
+  use GC_THREADS instead.
+
+GC_AIX_THREADS  Enables support for IBM AIX threads.  Deprecated, use
+  GC_THREADS instead.
+
+GC_DGUX386_THREADS      Enables support for DB/UX on I386 threads.
+  See README.DGUX386.  (Probably has not been tested recently.)  Deprecated,
+  use GC_THREADS instead.
+
+GC_WIN32_THREADS        Enables support for Win32 threads.  Deprecated,
+  use GC_THREADS instead.
+
+GC_WIN32_PTHREADS       Enables support for pthreads-win32 (or other
+  non-Cygwin pthreads library for Windows).  This cannot be enabled
+  automatically by GC_THREADS, which would assume Win32 native threads.
+
+PTW32_STATIC_LIB        Causes the static version of the Mingw pthreads
+  library to be used.  Requires GC_WIN32_PTHREADS.
+
+GC_PTHREADS_PARAMARK    Causes pthread-based parallel mark implementation
+  to be used even if GC_WIN32_PTHREADS is undefined.  (Useful for WinCE.)
+
+ALL_INTERIOR_POINTERS   Allows all pointers to the interior of objects to be
+  recognized.  (See gc_priv.h for consequences.)  Alternatively,
+  GC_all_interior_pointers can be set at process initialization time.
+
+SMALL_CONFIG    Tries to tune the collector for small heap sizes,
+  usually causing it to use less space in such situations.  Incremental
+  collection no longer works in this case.  Also, removes some
+  statistic-printing code.  Turns off some optimization algorithms (like data
+  prefetching in the mark routine).
+
+NO_CLOCK        Do not use system clock.  Disables some statistic printing.
+
+GC_DISABLE_INCREMENTAL  Turn off the incremental collection support.
+
+NO_INCREMENTAL  Causes the GC test programs to not invoke the incremental mode
+  of the collector.  This has no impact on the generated library, only on the
+  test programs.  (This is often useful for debugging failures unrelated to
+  incremental GC.)
+
+LARGE_CONFIG    Tunes the collector for unusually large heaps.
+  Necessary for heaps larger than about 4 GiB on most (64-bit) machines.
+  Recommended for heaps larger than about 500 MiB.  Not recommended for
+  embedded systems.  Could be used in conjunction with SMALL_CONFIG to
+  generate smaller code (by disabling incremental collection support,
+  statistic printing and some optimization algorithms).
+
+DONT_ADD_BYTE_AT_END    Meaningful only with ALL_INTERIOR_POINTERS or
+  GC_all_interior_pointers = 1.  Normally ALL_INTERIOR_POINTERS
+  causes all objects to be padded so that pointers just past the end of
+  an object can be recognized.  This can be expensive.  (The padding
+  is normally more than one byte due to alignment constraints.)
+  DONT_ADD_BYTE_AT_END disables the padding.
+
+NO_EXECUTE_PERMISSION   May cause some or all of the heap to not
+  have execute permission, i.e. it may be impossible to execute
+  code from the heap.  Affects the incremental collector and memory unmapping.
+  It may greatly improve the performance, since this may avoid some expensive
+  cache synchronization.  Portable clients should call
+  GC_set_pages_executable(1) at the process initialization time if the
+  execute permission is required.
+
+GC_NO_OPERATOR_NEW_ARRAY        Declares that the C++ compiler does not
+  support the new syntax "operator new[]" for allocating and deleting arrays.
+  See gc_cpp.h for details.  No effect on the C part of the collector.
+  This is defined implicitly in a few environments.  Must also be defined
+  by clients that use gc_cpp.h.
+
+REDIRECT_MALLOC=<X>     Causes malloc to be defined as alias for X.
+  Unless the following macros are defined, realloc is also redirected
+  to GC_realloc, and free is redirected to GC_free.
+  Calloc and str[n]dup are redefined in terms of the new malloc.  X should
+  be either GC_malloc or GC_malloc_uncollectable, or
+  GC_debug_malloc_replacement.  (The latter invokes GC_debug_malloc
+  with dummy source location information, but still results in
+  properly remembered call stacks on Linux/X86 and Solaris/SPARC.
+  It requires that the following two macros also be used.)
+  The former is occasionally useful for working around leaks in code
+  you don't want to (or can't) look at.  It may not work for
+  existing code, but it often does.  Neither works on all platforms,
+  since some ports use malloc or calloc to obtain system memory.
+  (Probably works for UNIX, and Win32.)  If you build with DBG_HDRS_ALL,
+  you should only use GC_debug_malloc_replacement as a malloc
+  replacement.
+
+REDIRECT_REALLOC=<X>    Causes GC_realloc to be redirected to X.
+  The canonical use is REDIRECT_REALLOC=GC_debug_realloc_replacement,
+  together with REDIRECT_MALLOC=GC_debug_malloc_replacement to
+  generate leak reports with call stacks for both malloc and realloc.
+  This also requires REDIRECT_FREE.
+
+REDIRECT_FREE=<X>       Causes free to be redirected to X.  The canonical use
+  is REDIRECT_FREE=GC_debug_free.
+
+IGNORE_FREE     Turns calls to free into a no-op.  Only useful with
+  REDIRECT_MALLOC.
+
+NO_DEBUGGING    Removes GC_dump and the debugging routines it calls.
+  Reduces code size slightly at the expense of debuggability.
+
+GC_DUMP_REGULARLY       Generate regular debugging dumps.
+
+DEBUG_THREADS   Turn on printing additional thread-support debugging
+  information.
+
+GC_COLLECT_AT_MALLOC=<n>        Force garbage collection at every
+  GC_malloc_* call with the size greater than the specified value.
+  (Might be useful for application debugging or in find-leak mode.)
+
+JAVA_FINALIZATION       Makes it somewhat safer to finalize objects out of
+  order by specifying a nonstandard finalization mark procedure (see
+  finalize.c).  Objects reachable from finalizable objects will be marked
+  in a separate post-pass, and hence their memory won't be reclaimed.
+  Not recommended unless you are implementing a language that specifies
+  these semantics.  Actually, the macro determines only the initial value
+  of GC_java_finalization variable.
+
+FINALIZE_ON_DEMAND      Causes finalizers to be run only in response
+  to explicit GC_invoke_finalizers() calls.  Actually, the macro only
+  determines the initial value of GC_finalize_on_demand.
+
+GC_NO_FINALIZATION      Exclude finalization support (for smaller code size).
+
+GC_TOGGLE_REFS_NOT_NEEDED       Exclude toggle-refs support.
+
+GC_ATOMIC_UNCOLLECTABLE Includes code for GC_malloc_atomic_uncollectable.
+  This is useful if either the vendor malloc implementation is poor,
+  or if REDIRECT_MALLOC is used.
+
+MARK_BIT_PER_GRANULE    Requests that a mark bit (or often byte)
+  be allocated for each allocation granule, as opposed to each object.
+  This often improves speed, possibly at some cost in space and/or
+  cache footprint.  Normally it is best to let this decision be
+  made automatically depending on platform.
+
+MARK_BIT_PER_OBJ        Requests that a mark bit be allocated for each
+  object instead of allocation granule.  The opposite of
+  MARK_BIT_PER_GRANULE.
+
+HBLKSIZE=<ddd>  Explicitly sets the heap block size (where ddd is a power of
+  2 between 512 and 16384).  Each heap block is devoted to a single size and
+  kind of object.  For the incremental collector it makes sense to match
+  the most likely page size.  Otherwise large values result in more
+  fragmentation, but generally better performance for large heaps.
+
+USE_MMAP        Use MMAP instead of sbrk to get new memory.
+  Works for Linux, FreeBSD, Cygwin, Solaris and Irix.
+
+USE_MUNMAP      Causes memory to be returned to the OS under the right
+  circumstances.  Works under some Unix, Linux and Windows versions.
+  Requires USE_MMAP except for Windows.
+
+USE_WINALLOC (Cygwin only)   Use Win32 VirtualAlloc (instead of sbrk or mmap)
+  to get new memory.  Useful if memory unmapping (USE_MUNMAP) is enabled.
+
+MUNMAP_THRESHOLD=<value>        Set the desired memory blocks unmapping
+  threshold (the number of sequential garbage collections for which
+  a candidate block for unmapping should remain free).
+
+GC_FORCE_UNMAP_ON_GCOLLECT      Set "unmap as much as possible on explicit GC"
+  mode on by default.  The mode could be changed at run-time.  Has no effect
+  unless unmapping is turned on.  Has no effect on implicitly-initiated
+  garbage collections.
+
+PRINT_BLACK_LIST        Whenever a black list entry is added, i.e. whenever
+  the garbage collector detects a value that looks almost, but not quite,
+  like a pointer, print both the address containing the value, and the
+  value of the near-bogus-pointer.  Can be used to identify regions of
+  memory that are likely to contribute misidentified pointers.
+
+KEEP_BACK_PTRS  Add code to save back pointers in debugging headers
+  for objects allocated with the debugging allocator.  If all objects
+  through GC_MALLOC with GC_DEBUG defined, this allows the client
+  to determine how particular or randomly chosen objects are reachable
+  for debugging/profiling purposes.  The gc_backptr.h interface is
+  implemented only if this is defined.
+
+GC_ASSERTIONS   Enable some internal GC assertion checking.  It is intended
+  primarily for debugging of the garbage collector itself, but could also
+  help to identify cases of incorrect GC usage by a client.
+
+DBG_HDRS_ALL    Make sure that all objects have debug headers.  Increases
+  the reliability (from 99.9999% to 100% mod. bugs) of some of the debugging
+  code (especially KEEP_BACK_PTRS).  Makes SHORT_DBG_HDRS possible.
+  Assumes that all client allocation is done through debugging allocators.
+
+SHORT_DBG_HDRS  Assume that all objects have debug headers.  Shorten
+  the headers to minimize object size, at the expense of checking for
+  writes past the end of an object.  This is intended for environments
+  in which most client code is written in a "safe" language, such as
+  Scheme or Java.  Assumes that all client allocation is done using
+  the GC_debug_ functions, or through the macros that expand to these,
+  or by redirecting malloc to GC_debug_malloc_replacement.
+  (Also eliminates the field for the requested object size.)
+  Occasionally could be useful for debugging of client code.  Slows down the
+  collector somewhat, but not drastically.
+
+SAVE_CALL_COUNT=<n>     Set the number of call frames saved with objects
+  allocated through the debugging interface.  Affects the amount of
+  information generated in leak reports.  Only matters on platforms
+  on which we can quickly generate call stacks, currently Linux/X86,
+  Linux/SPARC, Solaris/SPARC, and platforms that provide execinfo.h.
+  Default is zero.  On X86, client code should NOT be compiled with
+  -fomit-frame-pointer.
+
+SAVE_CALL_NARGS=<n>     Set the number of functions arguments to be saved
+  with each call frame.  Default is zero.  Ignored if we don't know how to
+  retrieve arguments on the platform.
+
+CHECKSUMS       Reports on erroneously clear dirty bits (at a substantial
+  performance cost).  Use only for debugging of the incremental collector.
+  Not compatible with USE_MUNMAP or threads.
+
+GC_GCJ_SUPPORT  Includes support for gcj (and possibly other systems
+  that include a pointer to a type descriptor in each allocated object).
+
+USE_I686_PREFETCH       Causes the collector to issue Pentium III style
+  prefetch instructions.  No effect except on Linux/X86 platforms.
+  Empirically the code appears to still run correctly on Pentium II
+  processors, though with no performance benefit.  May not run on other
+  X86 processors probably.  In some cases this improves performance by 15%
+  or so.
+
+USE_3DNOW_PREFETCH      Causes the collector to issue AMD 3DNow style
+  prefetch instructions.  Same restrictions as USE_I686_PREFETCH.
+  Minimally tested.  Didn't appear to be an obvious win on a K6-2/500.
+
+USE_PPC_PREFETCH        Causes the collector to issue PowerPC style
+  prefetch instructions.  No effect except on PowerPC OS X platforms.
+  Performance impact untested.
+
+GC_USE_LD_WRAP  In combination with the old flags listed in README.linux
+  causes the collector some system and pthread calls in a more transparent
+  fashion than the usual macro-based approach.  Requires GNU ld, and
+  currently probably works only with Linux.
+
+GC_USE_DLOPEN_WRAP      Causes the collector to redefine malloc and
+  intercepted pthread routines with their real names, and causes it to use
+  dlopen and dlsym to refer to the original versions.  This makes it possible
+  to build an LD_PRELOADable malloc replacement library.
+
+THREAD_LOCAL_ALLOC      Defines GC_malloc(), GC_malloc_atomic() and
+  GC_gcj_malloc() to use a per-thread set of free-lists. These then allocate
+  in a way that usually does not involve acquisition of a global lock.
+  Recommended for multiprocessors.
+
+USE_COMPILER_TLS        Causes thread local allocation to use
+  the compiler-supported "__thread" thread-local variables.  This is the
+  default in HP/UX.  It may help performance on recent Linux installations.
+  (It failed for me on RedHat 8, but appears to work on RedHat 9.)
+
+GC_ATTR_TLS_FAST        Use specific attributes for GC_thread_key like
+  __attribute__((tls_model("local-exec"))).
+
+PARALLEL_MARK   Allows the marker to run in multiple threads.  Recommended
+  for multiprocessors.
+
+GC_BUILTIN_ATOMIC       Use GCC atomic intrinsics instead of libatomic_ops
+  primitives.
+
+GC_ALWAYS_MULTITHREADED     Force multi-threaded mode at GC initialization.
+  (Turns GC_allow_register_threads into a no-op routine.)
+
+GC_ENABLE_SUSPEND_THREAD (Linux only)   Turn on thread suspend/resume API
+support.
+
+GC_WINMAIN_REDIRECT (Win32 only)        Redirect (rename) an application
+  WinMain to GC_WinMain; implement the "real" WinMain which starts a new
+  thread to call GC_WinMain after initializing the GC.  Useful for WinCE.
+  Incompatible with GC_DLL.
+
+GC_REGISTER_MEM_PRIVATE (Win32 only)    Force to register MEM_PRIVATE R/W
+  sections as data roots.  Might be needed for some WinCE 6.0+ custom builds.
+  (May result in numerous "Data Abort" messages logged to WinCE debugging
+  console.)  Incompatible with GCC toolchains for WinCE.
+
+NO_GETENV       Prevents the collector from looking at environment variables.
+  These may otherwise alter its configuration, or turn off GC altogether.
+  I don't know of a reason to disable this, except possibly if the resulting
+  process runs as a privileged user.  (This is on by default for WinCE.)
+
+EMPTY_GETENV_RESULTS    Define to workaround a reputed Wine bug in getenv
+  (getenv() may return an empty string instead of NULL for a missing entry).
+
+GC_READ_ENV_FILE (Win32 only)   Read environment variables from the GC "env"
+  file (named as the program name plus ".gc.env" extension).  Useful for WinCE
+  targets (which have no getenv()).  In the file, every variable is specified
+  in a separate line and the format is as "<name>=<value>" (without spaces).
+  A comment line may start with any character except for the Latin letters,
+  the digits and the underscore ('_').  The file encoding is Latin-1.
+
+USE_GLOBAL_ALLOC (Win32 only)   Use GlobalAlloc() instead of VirtualAlloc()
+  to allocate the heap.  May be needed to work around a Windows NT/2000 issue.
+  Incompatible with USE_MUNMAP.  See README.win32 for details.
+
+MAKE_BACK_GRAPH         Enable GC_PRINT_BACK_HEIGHT environment variable.
+  See README.environment for details.  Experimental.  Limited platform
+  support.  Implies DBG_HDRS_ALL.  All allocation should be done using
+  the debug interface.
+
+GC_PRINT_BACK_HEIGHT    Permanently turn on back-height printing mode
+  (useful when NO_GETENV).  See the similar environment variable description
+  in README.environment.  Requires MAKE_BACK_GRAPH defined.
+
+HANDLE_FORK (Unix and Cygwin only)      Attempt by default to make GC_malloc()
+  work in a child process fork()'ed from a multi-threaded parent.  Not fully
+  POSIX-compliant and could be disabled at runtime (before GC_INIT).
+
+TEST_WITH_SYSTEM_MALLOC         Causes gctest to allocate (and leak) large
+  chunks of memory with the standard system malloc.  This will cause the root
+  set and collected heap to grow significantly if malloc'ed memory is somehow
+  getting traced by the collector.  This has no impact on the generated
+  library; it only affects the test.
+
+POINTER_MASK=<0x...>    Causes candidate pointers to be AND'ed with the given
+  mask before being considered.  If either this or the following macro is
+  defined, it will be assumed that all pointers stored in the heap need to be
+  processed this way.  Stack and register pointers will be considered both
+  with and without processing.  These macros are normally needed only to
+  support systems that use high-order pointer tags.  EXPERIMENTAL.
+
+POINTER_SHIFT=<n>       Causes the collector to left shift candidate pointers
+  by the indicated amount before trying to interpret them.  Applied after
+  POINTER_MASK. EXPERIMENTAL.  See also the preceding macro.
+
+ENABLE_TRACE    Enables the GC_TRACE=addr environment setting to do its job.
+  By default this is not supported in order to keep the marker as fast as
+  possible.
+
+DARWIN_DONT_PARSE_STACK         Causes the Darwin port to discover thread
+  stack bounds in the same way as other pthread ports, without trying to
+  walk the frames on the stack.  This is recommended only as a fall-back for
+  applications that don't support proper stack unwinding.
+
+GC_NO_THREADS_DISCOVERY (Darwin and Win32+DLL only)     Exclude DllMain-based
+  (on Windows) and task-threads-based (on Darwin) thread registration support.
+
+GC_INSIDE_DLL (Win32 only)      Enable DllMain-based approach of threads
+  registering even in case GC_DLL is not defined.
+
+GC_DISCOVER_TASK_THREADS (Darwin and Win32+DLL only)    Compile the collector
+  with the implicitly turned on task-threads-based (on Darwin) or
+  DllMain-based (on Windows) approach of threads registering.  Only for
+  compatibility and for the case when it is not possible to call
+  GC_use_threads_discovery() early (before other GC calls).
+
+USE_PROC_FOR_LIBRARIES  Causes the Linux collector to treat writable
+  memory mappings (as reported by /proc) as roots, if it doesn't have
+  other information about them.  It no longer traverses dynamic loader
+  data structures to find dynamic library static data.  This may be
+  required for applications that store pointers in mmapped segments without
+  informing the collector.  But it typically performs poorly, especially
+  since it will scan inactive but cached NPTL thread stacks completely.
+
+IGNORE_DYNAMIC_LOADING  Don't define DYNAMIC_LOADING even if supported by the
+  platform (that is, build the collector with disabled tracing of dynamic
+  library data roots).
+
+NO_PROC_STAT    Causes the collector to avoid relying on Linux
+  "/proc/self/stat".
+
+NO_GETCONTEXT   Causes the collector to not assume the existence of the
+  getcontext() function on linux-like platforms.  This currently happens
+  implicitly on Darwin, Hurd, or ARM or MIPS hardware.  It is explicitly
+  needed for some old versions of FreeBSD.
+
+STATIC=static   Causes various GC_ symbols that could logically be declared
+  static to be declared (this is the default if NO_DEBUGGING is specified).
+  Reduces the number of visible symbols (letting the optimizer do its work
+  better), which is probably cleaner, but may make some kinds of debugging
+  and profiling harder.
+
+GC_DLL  Build dynamic-link library (or dynamic shared object).  For Unix this
+  causes the exported symbols to have 'default' visibility (ignored unless
+  GCC v4+) and the internal ones to have 'hidden' visibility.
+
+NO_MSGBOX_ON_ERROR (Win32 only)         Do not show Windows message box with
+  "OK" button on a GC fatal error.  Otherwise the client application is
+  terminated only once the user clicks "OK" button.  Useful for non-GUI (or
+  non-interactive) applications.
+
+DONT_USE_USER32_DLL (Win32 only)        Don't use "user32" DLL import library
+  (containing MessageBox() entry); useful for a static GC library.
+
+GC_PREFER_MPROTECT_VDB  Choose MPROTECT_VDB manually in case of multiple
+  virtual dirty bit strategies are implemented (at present useful on Win32,
+  Solaris and Linux to force MPROTECT_VDB strategy instead of the default
+  GWW_VDB, PROC_VDB or SOFT_VDB ones, respectively).
+
+GC_IGNORE_GCJ_INFO      Disable GCJ-style type information (useful for
+  debugging on WinCE).
+
+GC_PRINT_VERBOSE_STATS  Permanently turn on verbose logging (useful for
+  debugging and profiling on WinCE).
+
+GC_ONLY_LOG_TO_FILE     Don't redirect GC stdout and stderr to the log file
+  specified by GC_LOG_FILE environment variable.  Has effect only when the
+  variable is set (to anything other than "0").
+
+GC_ANDROID_LOG (Android only)   Output error/debug information to Android log.
+
+CONSOLE_LOG (Win32 only)        Output error/debug information to stdout and
+  stderr.
+
+GC_DONT_EXPAND  Don't expand the heap unless explicitly requested or forced to.
+
+GC_USE_ENTIRE_HEAP      Causes the non-incremental collector to use the
+  entire heap before collecting.  This sometimes results in more large block
+  fragmentation, since very large blocks will tend to get broken up during
+  each GC cycle.  It is likely to result in a larger working set, but lower
+  collection frequencies, and hence fewer instructions executed in the
+  collector.  This macro controls only the default GC_use_entire_heap value.
+
+GC_INITIAL_HEAP_SIZE=<value>    Set the desired default initial heap size
+  in bytes.
+
+GC_FREE_SPACE_DIVISOR=<value>   Set alternate default GC_free_space_divisor
+  value.
+
+GC_ALLOCD_BYTES_PER_FINALIZER=<value>   Set alternate default value of
+  GC_allocd_bytes_per_finalizer.
+
+GC_TIME_LIMIT=<milliseconds>    Set alternate default GC_time_limit value
+  (setting this to GC_TIME_UNLIMITED will essentially disable incremental
+  collection while leaving generational collection enabled).
+
+GC_FULL_FREQ=<value>    Set alternate default number of partial collections
+  between full collections (matters only if incremental collection is on).
+
+NO_CANCEL_SAFE (Posix platforms with threads only)      Don't bother trying
+  to make the collector safe for thread cancellation; cancellation is not
+  used.  (Note that if cancellation is used anyway, threads may end up
+  getting canceled in unexpected places.)  Even without this option,
+  PTHREAD_CANCEL_ASYNCHRONOUS is never safe with the collector.  (We could
+  argue about its safety without the collector.)
+
+UNICODE (Win32 only)    Use the Unicode variant ('W') of the Win32 API instead
+  of ANSI/ASCII one ('A').  Useful for WinCE.
+
+HOST_ANDROID (or __ANDROID__)   Compile for Android NDK platform.
+
+SN_TARGET_PS3           Compile for Sony PS/3.
+
+USE_GET_STACKBASE_FOR_MAIN (Linux only)  Use pthread_attr_getstack() instead
+  of __libc_stack_end (or instead of any hard-coded value) for getting the
+  primordial thread stack bottom (useful if the client modifies the program's
+  address space).

+ 39 - 0
blitz.mod/bdwgc/doc/README.sgi

@@ -0,0 +1,39 @@
+Performance of the incremental collector can be greatly enhanced with
+-DNO_EXECUTE_PERMISSION.
+
+The collector should run with all of the -32, -n32 and -64 ABIs.  Remember to
+define the AS macro in the Makefile.direct to be "as -64", or "as -n32".
+
+If you use -DREDIRECT_MALLOC=GC_malloc with C++ code, your code should make
+at least one explicit call to malloc instead of new to ensure that the proper
+version of malloc is linked in.
+
+Sproc threads are not supported.
+
+Pthreads support is provided.  This requires that:
+
+1) You compile the collector with -DGC_THREADS specified in Makefile.direct.
+
+2) You have the latest pthreads patches installed.
+
+(Though the collector makes only documented pthread calls,
+it relies on signal/threads interactions working just right in ways
+that are not required by the standard.  It is unlikely that this code
+will run on other pthreads platforms.  But please tell me if it does.)
+
+3) Every file that makes thread calls should define GC_THREADS and then
+include gc.h.  Gc.h redefines some of the pthread primitives as macros which
+also provide the collector with information it requires.
+
+4) pthread_cond_wait and pthread_cond_timedwait should be prepared for
+premature wakeups.  (I believe the pthreads and related standards require this
+anyway.  Irix pthreads often terminate a wait if a signal arrives.
+The garbage collector uses signals to stop threads.)
+
+5) It is expensive to stop a thread waiting in IO at the time the request is
+initiated.  Applications with many such threads may not exhibit acceptable
+performance with the collector.  (Increasing the heap size may help.)
+
+6) The collector should not be compiled with -DREDIRECT_MALLOC.  This
+confuses some library calls made by the pthreads implementation, which
+expect the standard malloc.

+ 68 - 0
blitz.mod/bdwgc/doc/README.solaris2

@@ -0,0 +1,68 @@
+The collector supports both incremental collection and threads under
+Solaris 2.  The incremental collector normally retrieves page dirty information
+through the appropriate /proc calls.  But it can also be configured
+(by defining MPROTECT_VDB instead of PROC_VDB in gcconfig.h) to use mprotect
+and signals.  This may result in shorter pause times, but it is no longer
+safe to issue arbitrary system calls that write to the heap.
+
+Under other UNIX versions,
+the collector normally obtains memory through sbrk.  There is some reason
+to expect that this is not safe if the client program also calls the system
+malloc, or especially realloc.  The sbrk man page strongly suggests this is
+not safe: "Many library routines use malloc() internally, so use brk()
+and sbrk() only when you know that malloc() definitely will not be used by
+any library routine."  This doesn't make a lot of sense to me, since there
+seems to be no documentation as to which routines can transitively call malloc.
+Nonetheless, under Solaris2, the collector now allocates
+memory using mmap by default.  (It defines USE_MMAP in gcconfig.h.)
+You may want to reverse this decisions if you use -DREDIRECT_MALLOC=...
+
+Note:
+Before you run "make check", you need to set your LD_LIBRARY_PATH correctly
+(e.g., to "/usr/local/lib") so that tests can find the shared library
+libgcc_s.so.1.  Alternatively, you can configure with --disable-shared.
+
+SOLARIS THREADS:
+
+Unless --disable-threads option is given, threads support is on by default in
+configure.  This causes the collector to be compiled with -D GC_THREADS
+ensuring thread safety.  This assumes use of the pthread_ interface; old-style
+Solaris threads are no longer supported.  Thread-local allocation is on by
+default.  Parallel marking is on by default (it could be disabled manually
+by configure --disable-parallel-mark option).
+
+It is also essential that gc.h be included in files that call pthread_create,
+pthread_join, pthread_detach, or dlopen.  gc.h macro defines these to also do
+GC bookkeeping, etc.  gc.h must be included with GC_THREADS macro defined
+first, otherwise these replacements are not visible.  A collector built in
+this way may only be used by programs that are linked with the threads library.
+
+Unless USE_PROC_FOR_LIBRARIES is defined, dlopen disables collection
+temporarily.  In some unlikely cases, this can result in unpleasant heap
+growth.  But it seems better than the race/deadlock issues we had before.
+
+If threads are used on an X86 processor with malloc redirected to
+GC_malloc, it is necessary to call GC_INIT explicitly before forking the
+first thread.  (This avoids a deadlock arising from calling GC_thr_init
+with the allocation lock held.)
+
+There could be an issue when using gc_cpp.h in conjunction with Solaris
+threads and Sun's C++ runtime.  Apparently the overloaded new operator
+may be invoked by some iostream initialization code before threads are
+correctly initialized.  This may cause a SIGSEGV during initialization
+of the garbage collector.  Currently the only known workaround is to not
+invoke the garbage collector from a user defined global operator new, or to
+have it invoke the garbage-collector's allocators only after main has started.
+(Note that the latter requires a moderately expensive test in operator
+delete.)
+
+I encountered "symbol <unknown>: offset .... is non-aligned" errors.  These
+appear to be traceable to the use of the GNU assembler with the Sun linker.
+The former appears to generate a relocation not understood by the latter.
+The fix appears to be to use a consistent toolchain.  (As a non-Solaris-expert
+my solution involved hacking the libtool script, but I'm sure you can
+do something less ugly.)
+
+Hans-J. Boehm
+(The above contains my personal opinions, which are probably not shared
+by anyone else.)

+ 11 - 0
blitz.mod/bdwgc/doc/README.symbian

@@ -0,0 +1,11 @@
+Instructions for Symbian:
+1. Build: use libgc.mmp
+2. Limitations
+2.1. No multi-threaded support yet
+2.2. Be careful with limitation that emulator introduces: Static roots are not
+dynamically accessible (there are Symbian APIs for this purpose but are just
+stubs, returning irrelevant values).
+Consequently, on emulator, you can only use dlls or exe, and retrieve static
+roots by calling global_init_static_root per dll (or exe).
+On target, only libs are supported, because static roots are retrieved by
+linker flags, by calling global_init_static_root in main exe.

+ 2 - 0
blitz.mod/bdwgc/doc/README.uts

@@ -0,0 +1,2 @@
+Alistair Crooks supplied the port.  He used Lexa C version 2.1.3 with
+-Xa to compile.

+ 215 - 0
blitz.mod/bdwgc/doc/README.win32

@@ -0,0 +1,215 @@
+The collector has at various times been compiled under Windows 95 and later,
+NT, and XP, with the original Microsoft SDK, with Visual C++ 2.0, 4.0, and 6,
+with the GNU win32 tools, with Borland C++ Builder, with Watcom C, with EMX,
+and with the Digital Mars compiler (DMC).
+
+For historical reasons,
+the collector test program "gctest" is linked as a GUI application,
+but does not open any windows.  Its output normally appears in the file
+"gctest.gc.log".  It may be started from the file manager.  The hour glass
+cursor may appear as long as it's running.  If it is started from the
+command line, it will usually run in the background.  Wait a few
+minutes (a few seconds on a modern machine) before you check the output.
+You should see either a failure indication or a "Collector appears to work"
+message.
+
+A toy editor (de.exe) based on cords (heavyweight
+strings represented as trees) has been ported and is included.
+It runs fine under either win32 or win32S.  It serves as an example
+of a true Windows application, except that it was written by a
+nonexpert Windows programmer.  (There are some peculiarities
+in the way files are displayed.  The <cr> is displayed explicitly
+for standard DOS text files.  As in the UNIX version, control
+characters are displayed explicitly, but in this case as red text.
+This may be suboptimal for some tastes and/or sets of default
+window colors.)
+
+In general -DREDIRECT_MALLOC is unlikely to work unless the
+application is completely statically linked.
+
+The collector normally allocates memory from the OS with VirtualAlloc.
+This appears to cause problems under Windows NT and Windows 2000 (but
+not Windows 95/98) if the memory is later passed to CreateDIBitmap.
+To work around this problem, build the collector with -DUSE_GLOBAL_ALLOC.
+This is currently incompatible with -DUSE_MUNMAP.  (Thanks to Jonathan
+Clark for tracking this down.  There's some chance this may be fixed
+since we now separate heap sections with an unused page.)
+
+[Threads and incremental collection are discussed near the end, below.]
+
+Microsoft Tools
+---------------
+
+For Microsoft development tools, type
+"nmake -f NT_MAKEFILE cpu=i386 disable_threads=1 enable_static=1 nodebug=1"
+to build the release variant of the collector as a static library without
+threads support.
+
+In order to use the gc_cpp.h C++ interface, all client code should include
+gc_cpp.h.
+
+[See above for gctest.]
+
+If you would prefer a VC++ .NET project file, ask Hans Boehm.  One has
+been contributed, but it seems to contain some absolute paths etc., so
+it can presumably only be a starting point, and is not in the standard
+distribution.  It is unclear (to me, Hans Boehm) whether it is feasible to
+change that.
+
+Clients may need to define GC_NOT_DLL before including gc.h, if the
+collector was built as a static library.
+
+GNU Tools
+---------
+
+The collector should be buildable under Cygwin with the
+"./configure; make check" machinery.
+
+MinGW builds (including for x86_64) are available both directly (on a Windows
+host) and via cross-compilation, e.g.
+"./configure --host=i686-pc-mingw32; make check"
+
+By default, configure instructs make to build the collector as a DLL (shared
+library), adding -D GC_DLL to CFLAGS.
+
+Parallel marker is enabled by default; it could be disabled by
+"--disable-parallel-mark" option.
+
+Memory unmapping could be turned off by "--disable-munmap" option.
+
+Borland Tools
+-------------
+
+For Borland tools, use `cmake -G "Borland Makefiles"`.  Note that
+Borland's compiler defaults to 1 byte alignment in structures (-a1),
+whereas Visual C++ appears to default to 8 byte alignment (/Zp8).
+The garbage collector in its default configuration EXPECTS AT
+LEAST 4 BYTE ALIGNMENT.  Thus the BORLAND DEFAULT MUST
+BE OVERRIDDEN.  (In my opinion, it should usually be anyway.
+I expect that -a1 introduces major performance penalties on a
+486 or Pentium.)  Note that this changes structure layouts.  (As a last
+resort, gcconfig.h can be changed to allow 1 byte alignment.  But
+this has significant negative performance implications.)
+
+Digital Mars compiler
+---------------------
+
+Same as MS Visual C++ but might require
+-DAO_OLD_STYLE_INTERLOCKED_COMPARE_EXCHANGE option to compile with the
+parallel marker enabled.
+
+Watcom compiler
+---------------
+
+Ivan V. Demakov's README for the Watcom port:
+
+The collector has been tested with Watcom C 10.6, 11.0 and OpenWatcom 2.0.
+It runs under win32, win32s, and even under msdos with dos4gw
+dos-extender. It should also run under OS/2, though this isn't
+tested. Under win32 the collector can be built either as dll
+or as static library.
+
+Note that all compilations were done under Windows 95 or NT.
+For unknown reason compiling under Windows 3.11 for NT (one
+attempt has been made) leads to broken executables.
+
+Incremental collection is supported (except for MSDOS and OS/2).
+
+Before compiling you may need to edit WCC_MAKEFILE to set target
+platform, library type (dynamic or static), calling conventions, and
+optimization options.
+
+To compile the collector use the command:
+    wmake -f WCC_MAKEFILE
+
+All programs using gc should be compiled with 4-byte alignment.
+For further explanations on this see comments about Borland.
+
+If the gc is compiled as dll, the macro "GC_DLL" should be defined before
+including "gc.h" (for example, with -DGC_DLL compiler option). It's
+important, otherwise resulting programs will not run.
+
+The alternate way to compile the collector is to use cmake build system:
+    cmake -G "Watcom WMake" .
+    cmake --build .
+
+Special note for OpenWatcom users: the C (unlike the C++) compiler (of the
+latest stable release, not sure for older ones) doesn't force pointer global
+variables (i.e. not struct fields, not sure for locals) to be aligned unless
+optimizing for speed (e.g., "-ot" option is set); the "-zp" option (or align
+pragma) only controls alignment for structs; I don't know whether it's a bug or
+a feature (see an old report of same kind -
+http://bugzilla.openwatcom.org/show_bug.cgi?id=664), so You are warned.
+
+Incremental Collection
+----------------------
+
+There is some support for incremental collection.  By default, the
+collector chooses between explicit page protection, and GetWriteWatch-based
+write tracking automatically, depending on the platform.
+
+The former is slow and interacts poorly with a debugger.
+Pages are protected.  Protection faults are caught by a handler
+installed at the bottom of the handler
+stack.  Whenever possible, I recommend adding a call to
+GC_enable_incremental at the last possible moment, after most
+debugging is complete.  No system
+calls are wrapped by the collector itself.  It may be necessary
+to wrap ReadFile calls that use a buffer in the heap, so that the
+call does not encounter a protection fault while it's running.
+(As usual, none of this is an issue unless GC_enable_incremental
+is called.)
+
+Note that incremental collection is disabled with -DSMALL_CONFIG.
+
+Threads
+-------
+
+The collector by default handles threads similarly to other platforms.
+James Clark's code which tracks threads attached to the collector DLL still
+exists, but requires that both
+- the collector is built in a DLL with GC_DLL defined, and
+- GC_use_threads_discovery() is called before GC initialization, which
+  in turn must happen before creating additional threads.
+We generally recommend avoiding this if possible, since it seems to
+be less than 100% reliable.
+
+To build the collector as a dynamic library which handles threads similarly
+to other platforms, type "nmake -f NT_MAKEFILE".  If automatic tracking of
+threads attached to the collector DLL (i.e. support of both kinds of thread
+tracking) is needed then delete "-DTHREAD_LOCAL_ALLOC" from NT_MAKEFILE
+manually before the build.
+
+The incremental collection is supported only if it is enabled before any
+additional threads are created.
+
+Threads are also supported in static library builds with Microsoft tools
+(e.g., NT_MAKEFILE), as well as with the CMake and GNU tools.  The collector
+must be built with GC_THREADS defined (this is the default in NT_MAKEFILE,
+CMakeLists.txt and configure).
+
+For the normal, non-dll-based thread tracking to work properly,
+threads should be created with GC_CreateThread or GC_beginthreadex,
+and exit normally, or call GC_endthreadex or GC_ExitThread.  (For Cygwin, the
+standard pthread_create/exit calls could be used instead.)  As in the pthread
+case, including gc.h will redefine CreateThread, _beginthreadex,
+_endthreadex, and ExitThread to call the GC_ versions instead.
+
+Note that, as usual, GC_CreateThread tends to introduce resource leaks (in the
+C runtime) that are avoided by GC_beginthreadex.  There is currently no
+equivalent of _beginthread, and it should not be used.
+
+GC_INIT should be called from the main thread before other GC calls.
+
+We strongly advise against using the TerminateThread() win32 API call,
+especially with the garbage collector.  Any use is likely to provoke a
+crash in the GC, since it makes it impossible for the collector to
+correctly track threads.
+
+To build the collector for MinGW pthreads-win32 (or other non-Cygwin pthreads
+implementation for Windows), use Makefile.direct and explicitly set
+GC_WIN32_PTHREADS (or pass --enable-threads=pthreads to configure).
+Use -DPTW32_STATIC_LIB for the static threads library.
+
+The alternate (better) way to build the library is to use CMake script;
+please see README.cmake for the details.

+ 27 - 0
blitz.mod/bdwgc/doc/README.win64

@@ -0,0 +1,27 @@
+64-bit Windows on AMD64/Intel EM64T is supported.  A collector can be built
+with Microsoft Visual C++ 2005 or with mingw-w64 gcc.
+
+NT_MAKEFILE has been used in this environment.  Type
+"nmake -f NT_MAKEFILE cpu=AMD64 nodebug=1" in a Visual C++ command line
+window to build the release variant of the dynamic library with threads
+support.
+To verify that the collector is at least somewhat functional,
+type "nmake -f NT_MAKEFILE cpu=AMD64 check" to build and run the usual test
+programs.  This should create gctest.gc.log after a few seconds.
+
+Test_cpp.exe might not run correctly in case of dynamic GC linking.  (It seems
+that we're getting wrong instances of operator new/delete in some cases.)
+
+This process is completely analogous to NT_MAKEFILE usage
+for the 32-bit library version.
+
+A similar procedure using NT_MAKEFILE is applicable to build the static
+library - just pass "enable_static=1" as an extra argument to nmake.
+If needed, it is also possible to build the library without threads
+support - this could be done by passing "disable_threads=1" argument to nmake.
+
+Note that some warnings have been explicitly turned off in the makefile.
+
+VC++ note: to suppress warnings -D_CRT_SECURE_NO_DEPRECATE is used.
+
+gcc note: -fno-strict-aliasing should be used if optimizing.

+ 273 - 0
blitz.mod/bdwgc/doc/debugging.md

@@ -0,0 +1,273 @@
+# Debugging Garbage Collector Related Problems
+
+This page contains some hints on debugging issues specific to the
+Boehm-Demers-Weiser conservative garbage collector. It applies both
+to debugging issues in client code that manifest themselves as collector
+misbehavior, and to debugging the collector itself.
+
+If you suspect a bug in the collector itself, it is strongly recommended that
+you try the latest collector release before proceeding.
+
+## Bus Errors and Segmentation Violations
+
+If the fault occurred in `GC_find_limit`, or with incremental collection
+enabled, this is probably normal. The collector installs handlers to take care
+of these. You will not see these unless you are using a debugger. Your
+debugger _should_ allow you to continue. It's often preferable to tell the
+debugger to ignore SIGBUS and SIGSEGV ("handle SIGSEGV SIGBUS nostop noprint"
+in gdb, "ignore SIGSEGV SIGBUS" in most versions of dbx) and set a breakpoint
+in `abort`. The collector will call abort if the signal had another cause, and
+there was not other handler previously installed.
+
+We recommend debugging without incremental collection if possible. (This
+applies directly to UNIX systems. Debugging with incremental collection under
+win32 is worse. See README.win32.)
+
+If the application generates an unhandled SIGSEGV or equivalent, it may often
+be easiest to set the environment variable `GC_LOOP_ON_ABORT`. On many
+platforms, this will cause the collector to loop in a handler when the SIGSEGV
+is encountered (or when the collector aborts for some other reason), and
+a debugger can then be attached to the looping process. This sidesteps common
+operating system problems related to incomplete core files for multi-threaded
+applications, etc.
+
+## Other Signals
+
+On most platforms, the multi-threaded version of the collector needs one or
+two other signals for internal use by the collector in stopping threads. It is
+normally wise to tell the debugger to ignore these. On Linux, the collector
+currently uses SIGPWR and SIGXCPU by default.
+
+## Warning Messages About Needing to Allocate Blacklisted Blocks
+
+The garbage collector generates warning messages of the form:
+
+
+    Repeated allocation of very large block ...
+    May lead to memory leak and poor performance
+
+
+when it needs to allocate a block at a location that it knows to be referenced
+by a false pointer. These false pointers can be either permanent (e.g.
+a static integer variable that never changes) or temporary. In the latter
+case, the warning is largely spurious, and the block will eventually
+be reclaimed normally. In the former case, the program will still run
+correctly, but the block will never be reclaimed. Unless the block is intended
+to be permanent, the warning indicates a memory leak.
+
+  1. Ignore these warnings while you are using GC_DEBUG. Some of the routines
+  mentioned below don't have debugging equivalents. (Alternatively, write the
+  missing routines and send them to me.)
+  2. Replace allocator calls that request large blocks with calls to
+  `GC_malloc_ignore_off_page` or `GC_malloc_atomic_ignore_off_page`. You may
+  want to set a breakpoint in `GC_default_warn_proc` to help you identify such
+  calls. Make sure that a pointer to somewhere near the beginning of the
+  resulting block is maintained in a (preferably volatile) variable as long
+  as the block is needed.
+  3. If the large blocks are allocated with realloc, we suggest instead
+  allocating them with something like the following. Note that the realloc
+  size increment should be fairly large (e.g. a factor of 3/2) for this to
+  exhibit reasonable performance. But we all know we should do that anyway.
+
+
+        void * big_realloc(void *p, size_t new_size) {
+            size_t old_size = GC_size(p);
+            void * result;
+            if (new_size <= 10000) return(GC_realloc(p, new_size));
+            if (new_size <= old_size) return(p);
+            result = GC_malloc_ignore_off_page(new_size);
+            if (result == 0) return(0);
+            memcpy(result,p,old_size);
+            GC_free(p);
+            return(result);
+        }
+
+
+  4. In the unlikely case that even relatively small object (<20 KB)
+  allocations are triggering these warnings, then your address space contains
+  lots of "bogus pointers", i.e. values that appear to be pointers but aren't.
+  Usually this can be solved by using `GC_malloc_atomic` or the routines
+  in `gc_typed.h` to allocate large pointer-free regions of bitmaps, etc.
+  Sometimes the problem can be solved with trivial changes of encoding
+  in certain values. It is possible, to identify the source of the bogus
+  pointers by building the collector with `-DPRINT_BLACK_LIST`, which will
+  cause it to print the "bogus pointers", along with their location.
+  5. If you get only a fixed number of these warnings, you are probably only
+  introducing a bounded leak by ignoring them. If the data structures being
+  allocated are intended to be permanent, then it is also safe to ignore them.
+  The warnings can be turned off by calling `GC_set_warn_proc` with
+  a procedure that ignores these warnings (e.g. by doing absolutely nothing).
+
+## The Collector References a Bad Address in GC_malloc
+
+This typically happens while the collector is trying to remove an entry from
+its free list, and the free list pointer is bad because the free list link
+in the last allocated object was bad.
+
+With >99% probability, you wrote past the end of an allocated object. Try
+setting `GC_DEBUG` before including `gc.h` and allocating with `GC_MALLOC`.
+This will try to detect such overwrite errors.
+
+## Unexpectedly Large Heap
+
+Unexpected heap growth can be due to one of the following:
+
+  1. Data structures that are being unintentionally retained. This is commonly
+  caused by data structures that are no longer being used, but were not
+  cleared, or by caches growing without bounds.
+  2. Pointer misidentification. The garbage collector is interpreting integers
+  or other data as pointers and retaining the "referenced" objects. A common
+  symptom is that GC_dump() shows much of the heap as black-listed.
+  3. Heap fragmentation. This should never result in unbounded growth, but
+  it may account for larger heaps. This is most commonly caused by allocation
+  of large objects.
+  4. Per object overhead. This is usually a relatively minor effect, but
+  it may be worth considering. If the collector recognizes interior pointers,
+  object sizes are increased, so that one-past-the-end pointers are correctly
+  recognized. The collector can be configured not to do this
+  (`-DDONT_ADD_BYTE_AT_END`).
+
+The collector rounds up object sizes so the result fits well into the chunk
+size (`HBLKSIZE`, normally 4 KB on 32-bit machines, 8 KB on 64-bit ones) used
+by the collector. Thus it may be worth avoiding objects of size 2K + 1 bytes
+(or exactly 2 KB if a byte is being added at the end.)  The last two cases can
+often be identified by looking at the output of a call to `GC_dump`. Among
+other things, it will print the list of free heap blocks, and a very brief
+description of all chunks in the heap, the object sizes they correspond to,
+and how many live objects were found in the chunk at the last collection.
+
+Growing data structures can usually be identified by:
+
+  1. Building the collector with `-DKEEP_BACK_PTRS`,
+  2. Preferably using debugging allocation (defining `GC_DEBUG` before
+  including `gc.h` and allocating with `GC_MALLOC`), so that objects will
+  be identified by their allocation site,
+  3. Running the application long enough so that most of the heap is composed
+  of "leaked" memory, and
+  4. Then calling `GC_generate_random_backtrace` from `gc_backptr.h` a few
+  times to determine why some randomly sampled objects in the heap are being
+  retained.
+
+The same technique can often be used to identify problems with false pointers,
+by noting whether the reference chains printed
+by `GC_generate_random_backtrace` involve any misidentified pointers.
+An alternate technique is to build the collector with `-DPRINT_BLACK_LIST`
+which will cause it to report values that are almost, but not quite, look like
+heap pointers. It is very likely that actual false pointers will come from
+similar sources.
+
+In the unlikely case that false pointers are an issue, it can usually
+be resolved using one or more of the following techniques:
+
+  1. Use `GC_malloc_atomic` for objects containing no pointers. This is
+  especially important for large arrays containing compressed data,
+  pseudo-random numbers, and the like. It is also likely to improve GC
+  performance, perhaps drastically so if the application is paging.
+  2. If you allocate large objects containing only one or two pointers at the
+  beginning, either try the typed allocation primitives in `gc_typed.h`,
+  or separate out the pointer-free component.
+  3. Consider using `GC_malloc_ignore_off_page` to allocate large objects.
+  (See `gc.h` and above for details. Large means more than 100 KB in most
+  environments.)
+  4. If your heap size is larger than 100 MB or so, build the collector with
+  `-DLARGE_CONFIG`. This allows the collector to keep more precise black-list
+  information.
+  5. If you are using heaps close to, or larger than, a gigabyte on a 32-bit
+  machine, you may want to consider moving to a platform with 64-bit pointers.
+  This is very likely to resolve any false pointer issues.
+
+## Prematurely Reclaimed Objects
+
+The usual symptom of this is a segmentation fault, or an obviously overwritten
+value in a heap object. This should, of course, be impossible. In practice,
+it may happen for reasons like the following:
+
+  1. The collector did not intercept the creation of threads correctly
+  in a multi-threaded application, e.g. because the client called
+  `pthread_create` without including `gc.h`, which redefines it.
+  2. The last pointer to an object in the garbage collected heap was stored
+  somewhere were the collector could not see it, e.g. in an object allocated
+  with system `malloc`, in certain types of `mmap`ed files, or in some data
+  structure visible only to the OS. (On some platforms, thread-local storage
+  is one of these.)
+  3. The last pointer to an object was somehow disguised, e.g. by XORing
+  it with another pointer.
+  4. Incorrect use of `GC_malloc_atomic` or typed allocation.
+  5. An incorrect `GC_free` call.
+  6. The client program overwrote an internal garbage collector data
+  structure.
+  7. A garbage collector bug.
+  8. (Empirically less likely than any of the above.) A compiler optimization
+  that disguised the last pointer.
+
+The following relatively simple techniques should be tried first to narrow
+down the problem:
+
+  1. If you are using the incremental collector try turning it off for
+  debugging.
+  2. If you are using shared libraries, try linking statically. If that works,
+  ensure that DYNAMIC_LOADING is defined on your platform.
+  3. Try to reproduce the problem with fully debuggable unoptimized code. This
+  will eliminate the last possibility, as well as making debugging easier.
+  4. Try replacing any suspect typed allocation and `GC_malloc_atomic` calls
+  with calls to `GC_malloc`.
+  5. Try removing any `GC_free` calls (e.g. with a suitable `#define`).
+  6. Rebuild the collector with `-DGC_ASSERTIONS`.
+  7. If the following works on your platform (i.e. if gctest still works if
+  you do this), try building the collector with
+  `-DREDIRECT_MALLOC=GC_malloc_uncollectable`. This will cause the collector
+  to scan memory allocated with malloc.
+
+If all else fails, you will have to attack this with a debugger. The suggested
+steps are:
+
+  1. Call `GC_dump` from the debugger around the time of the failure. Verify
+  that the collectors idea of the root set (i.e. static data regions which
+  it should scan for pointers) looks plausible. If not, i.e. if it does not
+  include some static variables, report this as a collector bug. Be sure
+  to describe your platform precisely, since this sort of problem is nearly
+  always very platform dependent.
+  2. Especially if the failure is not deterministic, try to isolate
+  it to a relatively small test case.
+  3. Set a break point in `GC_finish_collection`. This is a good point
+  to examine what has been marked, i.e. found reachable, by the collector.
+  4. If the failure is deterministic, run the process up to the last
+  collection before the failure. Note that the variable `GC_gc_no` counts
+  collections and can be used to set a conditional breakpoint in the right
+  one. It is incremented just before the call to `GC_finish_collection`.
+  If object `p` was prematurely recycled, it may be helpful to look
+  at `*GC_find_header(p)` at the failure point. The `hb_last_reclaimed` field
+  will identify the collection number during which its block was last swept.
+  5. Verify that the offending object still has its correct contents at this
+  point. Then call `GC_is_marked(p)` from the debugger to verify that the
+  object has not been marked, and is about to be reclaimed. Note that
+  `GC_is_marked(p)` expects the real address of an object (the address of the
+  debug header if there is one), and thus it may be more appropriate to call
+  `GC_is_marked(GC_base(p))` instead.
+  6. Determine a path from a root, i.e. static variable, stack, or register
+  variable, to the reclaimed object. Call `GC_is_marked(q)` for each object
+  `q` along the path, trying to locate the first unmarked object, say `r`.
+  7. If `r` is pointed to by a static root, verify that the location pointing
+  to it is part of the root set printed by `GC_dump`. If it is on the stack
+  in the main (or only) thread, verify that `GC_stackbottom` is set correctly
+  to the base of the stack. If it is in another thread stack, check the
+  collector's thread data structure (`GC_thread[]` on several platforms)
+  to make sure that stack bounds are set correctly.
+  8. If `r` is pointed to by heap object `s`, check that the collector's
+  layout description for `s` is such that the pointer field will be scanned.
+  Call `*GC_find_header(s)` to look at the descriptor for the heap chunk.
+  The `hb_descr` field specifies the layout of objects in that chunk.
+  See `gc_mark.h` for the meaning of the descriptor. (If its low order 2 bits
+  are zero, then it is just the length of the object prefix to be scanned.
+  This form is always used for objects allocated with `GC_malloc` or
+  `GC_malloc_atomic`.)
+  9. If the failure is not deterministic, you may still be able to apply some
+  of the above technique at the point of failure. But remember that objects
+  allocated since the last collection will not have been marked, even if the
+  collector is functioning properly. On some platforms, the collector can
+  be configured to save call chains in objects for debugging. Enabling this
+  feature will also cause it to save the call stack at the point of the last
+  GC in `GC_arrays._last_stack`.
+  10. When looking at GC internal data structures remember that a number
+  of `GC_xxx` variables are really macro defined to `GC_arrays._xxx`, so that
+  the collector can avoid scanning them.

+ 158 - 0
blitz.mod/bdwgc/doc/finalization.md

@@ -0,0 +1,158 @@
+# Finalization
+
+Many garbage collectors provide a facility for executing user code just before
+an object is collected. This can be used to reclaim any system resources
+or non-garbage-collected memory associated with the object. Experience has
+shown that this can be a useful facility. It is indispensable in cases
+in which system resources are embedded in complex data structures (e.g. file
+descriptors in the `cord.h`).
+
+Our collector provides the necessary functionality through
+`GC_register_finalizer` in `include/gc.h`, or by inheriting from `gc_cleanup`
+in `include/gc_cpp.h`).
+
+However, finalization should not be used in the same way as C++ destructors.
+In well-written programs there will typically be very few uses
+of finalization. (Garbage collected programs that interact with explicitly
+memory-managed libraries may be an exception.)
+
+In general the following guidelines should be followed:
+
+  * Actions that must be executed promptly do not belong in finalizers. They
+  should be handled by explicit calls in the code (or C++ destructors if you
+  prefer). If you expect the action to occur at a specific point, this
+  is probably not hard.
+  * Finalizers are intended for resource reclamation.
+  * Scarce system resources should be managed explicitly whenever convenient.
+  Use finalizers only as a backup mechanism for the cases that would be hard
+  to handle explicitly.
+  * If scarce resources are managed with finalization, the allocation routine
+  for that resource (e.g. open for file handles) should force a garbage
+  collection (two if that does not suffice) if it finds itself short of the
+  resource.
+  * If extremely scarce resources are managed by finalization (e.g. file
+  descriptors on systems which have a limit of 20 open files), it may
+  be necessary to introduce a descriptor caching scheme to hide the resource
+  limit. (E.g., the program would keep real file descriptors for the 20 most
+  recently used logically open files. Any other needed files would be closed
+  after saving their state. They would then be reopened on demand.
+  Finalization would logically close the file, closing the real descriptor
+  only if it happened to be cached.) Note that most modern systems allow
+  thousands of open files, and this is typically not an issue.
+  * Finalization code may be run anyplace an allocation or other call to the
+  collector takes place. In multi-threaded programs, finalizers have to obey
+  the normal locking conventions to ensure safety. Code run directly from
+  finalizers should not acquire locks that may be held during allocation.
+  This restriction can be easily circumvented by calling
+  `GC_set_finalize_on_demand(1)` at program start and creating a separate
+  thread dedicated to periodic invocation of `GC_invoke_finalizers()`.
+
+In single-threaded code, it is also often easiest to have finalizers queued
+and, then to have them explicitly executed by `GC_invoke_finalizers()`.
+
+## Topologically ordered finalization
+
+Our _conservative garbage collector_ supports a form of finalization (with
+`GC_register_finalizer`) in which objects are finalized in topological order.
+If _A_ points to _B_ and both are registered for finalization, it is
+guaranteed the _A_ will be finalized first. This usually guarantees that
+finalization procedures see only unfinalized objects.
+
+This decision is often questioned, particularly since it has an obvious
+disadvantage. The current implementation finalizes long chains of finalizable
+objects one per collection. This is hard to avoid, since the first finalizer
+invoked may store a pointer to the rest of the chain in a global variable,
+making it accessible again. Or it may mutate the rest of the chain.
+
+Cycles involving one or more finalizable objects are never finalized.
+
+## Why topological ordering?
+
+It is important to keep in mind that the choice of finalization ordering
+matters only in relatively rare cases. In spite of the fact that it has
+received a lot of discussion, it is not one of the more important decisions
+in designing a system. Many, especially smaller, applications will never
+notice the difference. Nonetheless, we believe that topologically ordered
+finalization is the right choice.
+
+To understand the justification, observe that if _A_'s finalization procedure
+does not refer to _B_, we could fairly easily have avoided the dependency.
+We could have split _A_ into _A'_ and _A''_ such that any references to _A_
+become references to _A'_, _A'_ points to _A''_ but not vice-versa, only
+fields needed for finalization are stored in _A''_, and _A''_ is enabled for
+finalization. (`GC_register_disappearing_link` provides an alternative
+mechanism that does not require breaking up objects.)
+
+Thus assume that _A_ actually does need access to _B_ during finalization.
+To make things concrete, assume that _B_ is finalizable because it holds
+a pointer to a C object, which must be explicitly deallocated. (This is likely
+to be one of the most common uses of finalization.) If _B_ happens to be
+finalized first, _A_ will see a dangling pointer during its finalization. But
+a principal goal of garbage collection was to avoid dangling pointers.
+
+Note that the client program could enforce topological ordering even if the
+system did not. A pointer to _B_ could be stored in some globally visible
+place, where it is cleared only by _A_'s finalizer. But this puts the burden
+to ensure safety back on the programmer.
+
+With topologically ordered finalization, the programmer can fail to split
+an object, thus leaving an accidental cycle. This results in a leak, which
+is arguably less dangerous than a dangling pointer. More importantly, it is
+_much_ easier to diagnose, since the garbage collector would have to go out of
+its way not to notice finalization cycles. It can trivially report them.
+
+Furthermore unordered finalization does not really solve the problem
+of cycles. Consider the above case in which _A_'s finalization procedure
+depends on _B_, and thus a pointer to _B_ is stored in a global data
+structure, to be cleared by _A_'s finalizer. If there is an accidental pointer
+from _B_ back to _A_, and thus a cycle, neither _B_ nor _A_ will become
+unreachable. The leak is there, just as in the topologically ordered case, but
+it is hidden from easy diagnosis.
+
+A number of alternative finalization orderings have been proposed, e.g. based
+on statically assigned priorities. In our opinion, these are much more likely
+to require complex programming discipline to use in a large modular system.
+(Some of them, e.g. Guardians proposed by Dybvig, Bruggeman, and Eby, do avoid
+some problems which arise in combination with certain other collection
+algorithms.)
+
+Fundamentally, a garbage collector assumes that objects reachable via pointer
+chains may be accessed, and thus should be preserved. Topologically ordered
+finalization simply extends this to object finalization; an finalizable object
+reachable from another finalizer via a pointer chain is presumed to be
+accessible by the finalizer, and thus should not be finalized.
+
+## Programming with topological finalization
+
+Experience with Cedar has shown that cycles or long chains of finalizable
+objects are typically not a problem. Finalizable objects are typically rare.
+There are several ways to reduce spurious dependencies between finalizable
+objects. Splitting objects as discussed above is one technique. The collector
+also provides `GC_register_disappearing_link`, which explicitly nils a pointer
+before determining finalization ordering.
+
+Some so-called "operating systems" fail to clean up some resources associated
+with a process. These resources must be deallocated at all cost before process
+exit whether or not they are still referenced. Probably the best way to deal
+with those is by not relying exclusively on finalization. They should
+be registered in a table of weak pointers (implemented as disguised pointers
+cleared by the finalization procedure that deallocates the resource). If any
+references are still left at process exit, they can be explicitly deallocated
+then.
+
+## Getting around topological finalization ordering
+
+There are certain situations in which cycles between finalizable objects are
+genuinely unavoidable. Most notably, C++ compilers introduce self-cycles
+to represent inheritance. `GC_register_finalizer_ignore_self` tells the
+finalization part of the collector to ignore self cycles. This is used by the
+C++ interface.
+
+Finalize.c actually contains an intentionally undocumented mechanism for
+registering a finalizable object with user-defined dependencies. The problem
+is that this dependency information is also used for memory reclamation, not
+just finalization ordering. Thus misuse can result in dangling pointers even
+if finalization does not create any. The risk of dangling pointers can be
+eliminated by building the collector with `-DJAVA_FINALIZATION`. This forces
+objects reachable from finalizers to be marked, even though this dependency
+is not considered for finalization ordering.

+ 546 - 0
blitz.mod/bdwgc/doc/gcdescr.md

@@ -0,0 +1,546 @@
+# Conservative GC Algorithmic Overview
+
+This is a description of the algorithms and data structures used in our
+conservative garbage collector. I expect the level of detail to increase with
+time. For a survey of GC algorithms, e.g. see Paul Wilson's
+["Uniprocessor Garbage Collection Techniques"](ftp://ftp.cs.utexas.edu/pub/garbage/gcsurvey.ps)
+excellent paper. For an overview of the collector interface, see
+[here](gcinterface.md).
+
+This description is targeted primarily at someone trying to understand the
+source code. It specifically refers to variable and function names. It may
+also be useful for understanding the algorithms at a higher level.
+
+The description here assumes that the collector is used in default mode.
+In particular, we assume that it used as a garbage collector, and not just
+a leak detector. We initially assume that it is used in stop-the-world,
+non-incremental mode, though the presence of the incremental collector will
+be apparent in the design. We assume the default finalization model, but the
+code affected by that is very localized.
+
+Table of Contents
+  * [Introduction](#introduction)
+  * [Allocation](#allocation)
+  * [Mark phase](#mark-phase)
+  * [Sweep phase](#sweep-phase)
+  * [Finalization](#finalization)
+  * [Generational Collection and Dirty Bits](#generational-collection-and-dirty-bits)
+  * [Black-listing](#black-listing)
+  * [Thread support](#thread-support)
+  * [Thread-local allocation](#thread-local-allocation)
+
+## Introduction
+
+The garbage collector uses a modified mark-sweep algorithm. Conceptually
+it operates roughly in four phases, which are performed occasionally as part
+of a memory allocation:
+
+  1. _Preparation phase_
+
+     Each object has an associated mark bit. Clear all mark
+     bits, indicating that all objects are potentially unreachable.
+
+  2. _Mark phase_
+
+     Marks all objects that can be reachable via chains of pointers from
+     variables. Often the collector has no real information about the location
+     of pointer variables in the heap, so it views all static data areas,
+     stacks and registers as potentially containing pointers. Any bit
+     patterns that represent addresses inside heap objects managed by the
+     collector are viewed as pointers. Unless the client program has made heap
+     object layout information available to the collector, any heap objects
+     found to be reachable from variables are again scanned similarly.
+
+  3. _Sweep phase_
+
+     Scans the heap for inaccessible, and hence unmarked,
+     objects, and returns them to an appropriate free list for reuse. This is
+     not really a separate phase; even in non-incremental mode this operation
+     is usually performed on demand during an allocation that discovers an
+     empty free list. Thus the sweep phase is very unlikely to touch a page
+     that would not have been touched shortly thereafter anyway.
+
+  4. _Finalization phase_
+
+     Unreachable objects which had been registered for
+     finalization are enqueued for finalization outside the collector.
+
+The remaining sections describe the memory allocation data structures, and
+then the last 3 collection phases in more detail. We conclude by outlining
+some of the additional features implemented in the collector.
+
+## Allocation
+
+The collector includes its own memory allocator. The allocator obtains memory
+from the system in a platform-dependent way. Under UNIX, it uses either
+`malloc`, `sbrk`, or `mmap`.
+
+Most static data used by the allocator, as well as that needed by the rest
+of the garbage collector is stored inside the `_GC_arrays` structure. This
+allows the garbage collector to easily ignore the collectors own data
+structures when it searches for root pointers. Other allocator and collector
+internal data structures are allocated dynamically with `GC_scratch_alloc`.
+The latter does not allow for deallocation, and is therefore used only for
+permanent data structures.
+
+The allocator returns objects of different _kinds_. Different _kinds_ are
+handled somewhat differently by certain parts of the garbage collector.
+Certain kinds are scanned for pointers, others are not. Some may have
+per-object type descriptors that determine pointer locations. Or a specific
+kind may correspond to one specific object layout. Two built-in kinds are
+uncollectible. In spite of that, it is very likely that most C clients of the
+collector currently use at most two kinds: `NORMAL` and `PTRFREE` objects. The
+[GCJ](https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcj/) runtime also makes heavy
+use of a kind (allocated with `GC_gcj_malloc`) that stores type information
+at a known offset in method tables.
+
+The collector uses a two level allocator. A large block is defined to be one
+larger than half of `HBLKSIZE`, which is a power of 2, typically on the order
+of the page size.
+
+Large block sizes are rounded up to the next multiple of `HBLKSIZE` and then
+allocated by `GC_allochblk`. The collector use an approximate best fit
+algorithm by keeping free lists for several large block sizes. The actual
+implementation of `GC_allochblk` is significantly complicated by black-listing
+issues (see below).
+
+Small blocks are allocated in chunks of size `HBLKSIZE`. Each chunk
+is dedicated to only one object size and kind.
+
+The allocator maintains separate free lists for each size and kind of object.
+Associated with each kind is an array of free list pointers, with entry
+`freelist[i]` pointing to a free list of size 'i' objects. Index `i` is
+expressed in granules, which are the minimum allocatable unit, typically 8 or
+16 bytes. The free lists themselves are linked through the first word in each
+object (see `obj_link` macro).
+
+Once a large block is split for use in smaller objects, it can only be used
+for objects of that size, unless the collector discovers a completely empty
+chunk. Completely empty chunks are restored to the appropriate large block
+free list.
+
+In order to avoid allocating blocks for too many distinct object sizes, the
+collector normally does not directly allocate objects of every possible
+request size. Instead, the request is rounded up to one of a smaller number
+of allocated sizes, for which free lists are maintained. The exact allocated
+sizes are computed on demand, but subject to the constraint that they increase
+roughly in geometric progression. Thus objects requested early in the
+execution are likely to be allocated with exactly the requested size, subject
+to alignment constraints. See `GC_init_size_map` for details.
+
+The actual size rounding operation during small object allocation
+is implemented as a table lookup in `GC_size_map` which maps a requested
+allocation size in bytes to a number of granules.
+
+Both collector initialization and computation of allocated sizes are handled
+carefully so that they do not slow down the small object fast allocation path.
+An attempt to allocate before the collector is initialized, or before the
+appropriate `GC_size_map` entry is computed, will take the same path as an
+allocation attempt with an empty free list. This results in a call to the slow
+path code (`GC_generic_malloc_inner`) which performs the appropriate
+initialization checks.
+
+In non-incremental mode, we make a decision about whether to garbage collect
+whenever an allocation would otherwise have failed with the current heap size.
+If the total amount of allocation since the last collection is less than the
+heap size divided by `GC_free_space_divisor`, we try to expand the heap.
+Otherwise, we initiate a garbage collection. This ensures that the amount
+of garbage collection work per allocated byte remains constant.
+
+The above is in fact an oversimplification of the real heap expansion and GC
+triggering heuristic, which adjusts slightly for root size and certain kinds
+of fragmentation. In particular:
+
+  * Programs with a large root set size and little live heap memory will
+  expand the heap to amortize the cost of scanning the roots.
+  * GC actually collects more frequently in non-incremental mode. The large
+  block allocator usually refuses to split large heap blocks once the garbage
+  collection threshold is reached. This often has the effect of collecting
+  well before the heap fills up, thus reducing fragmentation and working set
+  size at the expense of GC time. (If the collector is configured not to unmap
+  unused pages, GC chooses an intermediate strategy depending on how much
+  large object allocation has taken place in the past.)
+  * In calculating the amount of allocation since the last collection we give
+  partial credit for objects we expect to be explicitly deallocated. Even
+  if all objects are explicitly managed, it is often desirable to collect
+  on rare occasion, since that is our only mechanism for coalescing completely
+  empty chunks.
+
+It has been suggested that this should be adjusted so that we favor expansion
+if the resulting heap still fits into physical memory. In many cases, that
+would no doubt help. But it is tricky to do this in a way that remains robust
+if multiple application are contending for a single pool of physical memory.
+
+## Mark phase
+
+At each collection, the collector marks all objects that are possibly
+reachable from pointer variables. Since it cannot generally tell where pointer
+variables are located, it scans the following _root segments_ for pointers:
+
+  * The registers. Depending on the architecture, this may be done using
+  assembly code, or by calling a `setjmp`-like function which saves register
+  contents on the stack.
+  * The stack(s). In the case of a single-threaded application, on most
+  platforms this is done by scanning the memory between (an approximation of)
+  the current stack pointer and `GC_stackbottom`. (For Intel Itanium, the
+  register stack scanned separately.) The `GC_stackbottom` variable is set in
+  a highly platform-specific way depending on the appropriate configuration
+  information in `gcconfig.h`. Note that the currently active stack needs
+  to be scanned carefully, since callee-save registers of client code may
+  appear inside collector stack frames, which may change during the mark
+  process. This is addressed by scanning some sections of the stack _eagerly_,
+  effectively capturing a snapshot at one point in time.
+  * Static data region(s). In the simplest case, this is the region between
+  `DATASTART` and `DATAEND`, as defined in `gcconfig.h`. However, in most
+  cases, this will also involve static data regions associated with dynamic
+  libraries. These are identified by the mostly platform-specific code
+  in `dyn_load.c`.  The marker maintains an explicit stack of memory regions
+  that are known to be accessible, but that have not yet been searched for
+  contained pointers. Each stack entry contains the starting address of the
+  block to be scanned, as well as a descriptor of the block. If no layout
+  information is available for the block, then the descriptor is simply
+  a length. (For other possibilities, see `gc_mark.h`.)
+
+At the beginning of the mark phase, all root segments (as described above) are
+pushed on the stack by `GC_push_roots`. (Registers and eagerly scanned stack
+sections are processed by pushing the referenced objects instead of the stack
+section itself.) If `ALL_INTERIOR_POINTERS` is not defined, then stack roots
+require special treatment. In this case, the normal marking code ignores
+interior pointers, but `GC_push_all_stack` explicitly checks for interior
+pointers and pushes descriptors for target objects.
+
+The marker is structured to allow incremental marking. Each call
+to `GC_mark_some` performs a small amount of work towards marking the heap.
+It maintains explicit state in the form of `GC_mark_state`, which identifies
+a particular sub-phase. Some other pieces of state, most notably the mark
+stack, identify how much work remains to be done in each sub-phase. The normal
+progression of mark states for a stop-the-world collection is:
+
+  1. `MS_INVALID` indicating that there may be accessible unmarked objects.
+  In this case `GC_objects_are_marked` will simultaneously be false, so the
+  mark state is advanced to
+  2. `MS_PUSH_UNCOLLECTABLE` indicating that it suffices to push uncollectible
+  objects, roots, and then mark everything reachable from them. `GC_scan_ptr`
+  is advanced through the heap until all uncollectible objects are pushed, and
+  objects reachable from them are marked. At that point, the next call
+  to `GC_mark_some` calls `GC_push_roots` to push the roots. It, then,
+  advances the mark state to
+  3. `MS_ROOTS_PUSHED` asserting that once the mark stack is empty, all
+  reachable objects are marked. Once in this state, we work only on emptying
+  the mark stack. Once this is completed, the state changes to
+  4. `MS_NONE` indicating that reachable objects are marked.
+
+The core mark routine `GC_mark_from`, is called repeatedly by several of the
+sub-phases when the mark stack starts to fill up. It is also called repeatedly
+in `MS_ROOTS_PUSHED` state to empty the mark stack. The routine is designed
+to only perform a limited amount of marking at each call, so that it can
+also be used by the incremental collector. It is fairly carefully tuned,
+since it usually consumes a large majority of the garbage collection time.
+
+The fact that it performs only a small amount of work per call also allows
+it to be used as the core routine of the parallel marker. In that case it is
+normally invoked on thread-private mark stacks instead of the global mark
+stack. More details can be found [here](scale.md).
+
+The marker correctly handles mark stack overflows. Whenever the mark stack
+overflows, the mark state is reset to `MS_INVALID`. Since there are already
+marked objects in the heap, this eventually forces a complete scan of the
+heap, searching for pointers, during which any unmarked objects referenced
+by marked objects are again pushed on the mark stack. This process is repeated
+until the mark phase completes without a stack overflow. Each time the stack
+overflows, an attempt is made to grow the mark stack. All pieces of the
+collector that push regions onto the mark stack have to be careful to ensure
+forward progress, even in case of repeated mark stack overflows. Every mark
+attempt results in additional marked objects.
+
+Each mark stack entry is processed by examining all candidate pointers in the
+range described by the entry. If the region has no associated type information
+then this typically requires that each 4-byte aligned quantity (8-byte aligned
+if 64-bit pointers) be considered a candidate pointer.
+
+We determine whether a candidate pointer is actually the address of a heap
+block. This is done in the following steps:
+
+  * The candidate pointer is checked against rough heap bounds. These heap
+  bounds are maintained such that all actual heap objects fall between them.
+  In order to facilitate black-listing (see below) we also include address
+  regions that the heap is likely to expand into. Most non-pointers fail this
+  initial test.
+  * The candidate pointer is divided into two pieces; the most significant
+  bits identify a `HBLKSIZE`-sized page in the address space, and the least
+  significant bits specify an offset within that page. (A hardware page may
+  actually consist of multiple such pages. Normally, HBLKSIZE is usually the
+  page size divided by a small power of two. Alternatively, if the collector
+  is built with `-DLARGE_CONFIG`, such a page may consist of multiple hardware
+  pages.)
+  * The page address part of the candidate pointer is looked up in
+  a [table](tree.md). Each table entry contains either 0, indicating that
+  the page is not part of the garbage collected heap, a small integer _n_,
+  indicating that the page is part of large object, starting at least _n_
+  pages back, or a pointer to a descriptor for the page. In the first case,
+  the candidate pointer is not a true pointer and can be safely ignored.
+  In the last two cases, we can obtain a descriptor for the page containing
+  the beginning of the object.
+  * The starting address of the referenced object is computed. The page
+  descriptor contains the size of the object(s) in that page, the object kind,
+  and the necessary mark bits for those objects. The size information can be
+  used to map the candidate pointer to the object starting address.
+  To accelerate this process, the page header also contains a pointer to
+  a precomputed map of page offsets to displacements from the beginning of an
+  object. The use of this map avoids a potentially slow integer remainder
+  operation in computing the object start address.
+  * The mark bit for the target object is checked and set. If the object was
+  previously unmarked, the object is pushed on the mark stack. The descriptor
+  is read from the page descriptor. (This is computed from information stored
+  in `GC_obj_kinds` when the page is first allocated.)
+
+At the end of the mark phase, mark bits for left-over free lists are cleared,
+in case a free list was accidentally marked due to a stray pointer.
+
+## Sweep phase
+
+At the end of the mark phase, all blocks in the heap are examined. Unmarked
+large objects are immediately returned to the large object free list. Each
+small object page is checked to see if all mark bits are clear. If so, the
+entire page is returned to the large object free list. Small object pages
+containing some reachable object are queued for later sweeping, unless
+we determine that the page contains very little free space, in which case
+it is not examined further.
+
+This initial sweep pass touches only block headers, not the blocks themselves.
+Thus it does not require significant paging, even if large sections of the
+heap are not in physical memory.
+
+Nonempty small object pages are swept when an allocation attempt encounters
+an empty free list for that object size and kind. Pages for the correct size
+and kind are repeatedly swept until at least one empty block is found.
+Sweeping such a page involves scanning the mark bit array in the page header,
+and building a free list linked through the first words in the objects
+themselves. This does involve touching the appropriate data page, but in most
+cases it will be touched only just before it is used for allocation. Hence any
+paging is essentially unavoidable.
+
+Except in the case of pointer-free objects, we maintain the invariant that any
+object in a small object free list is cleared (except possibly for the link
+field). Thus it becomes the burden of the small object sweep routine to clear
+objects. This has the advantage that we can easily recover from accidentally
+marking a free list, though that could also be handled by other means. The
+collector currently spends a fair amount of time clearing objects, and this
+approach should probably be revisited. In most configurations, we use
+specialized sweep routines to handle common small object sizes. Since
+we allocate one mark bit per word, it becomes easier to examine the relevant
+mark bits if the object size divides the word length evenly. We also suitably
+unroll the inner sweep loop in each case. (It is conceivable that
+profile-based procedure cloning in the compiler could make this unnecessary
+and counterproductive. I know of no existing compiler to which this applies.)
+
+The sweeping of small object pages could be avoided completely at the expense
+of examining mark bits directly in the allocator. This would probably be more
+expensive, since each allocation call would have to reload a large amount
+of state (e.g. next object address to be swept, position in mark bit table)
+before it could do its work. The current scheme keeps the allocator simple and
+allows useful optimizations in the sweeper.
+
+## Finalization
+
+Both `GC_register_disappearing_link` and `GC_register_finalizer` add the
+request to a corresponding hash table. The hash table is allocated out of
+collected memory, but the reference to the finalizable object is hidden from
+the collector. Currently finalization requests are processed non-incrementally
+at the end of a mark cycle.
+
+The collector makes an initial pass over the table of finalizable objects,
+pushing the contents of unmarked objects onto the mark stack. After pushing
+each object, the marker is invoked to mark all objects reachable from it. The
+object itself is not explicitly marked. This assures that objects on which
+a finalizer depends are neither collected nor finalized.
+
+If in the process of marking from an object the object itself becomes marked,
+we have uncovered a cycle involving the object. This usually results in
+a warning from the collector. Such objects are not finalized, since it may be
+unsafe to do so. See the more detailed discussion of
+[finalization semantics](finalization.md).
+
+Any objects remaining unmarked at the end of this process are added to a queue
+of objects whose finalizers can be run. Depending on collector configuration,
+finalizers are dequeued and run either implicitly during allocation calls,
+or explicitly in response to a user request. (Note that the former
+is unfortunately both the default and not generally safe. If finalizers
+perform synchronization, it may result in deadlocks. Nontrivial finalizers
+generally need to perform synchronization, and thus require a different
+collector configuration.)
+
+The collector provides a mechanism for replacing the procedure that is used
+to mark through objects. This is used both to provide support for Java-style
+unordered finalization, and to ignore certain kinds of cycles, e.g. those
+arising from C++ implementations of virtual inheritance.
+
+## Generational Collection and Dirty Bits
+
+We basically use the concurrent and generational GC algorithm described in
+["Mostly Parallel Garbage Collection"](http://www.hboehm.info/gc/papers/pldi91.ps.Z),
+by Boehm, Demers, and Shenker.
+
+The most significant modification is that the collector always starts running
+in the allocating thread. There is no separate garbage collector thread. (If
+parallel GC is enabled, helper threads may also be woken up.) If an allocation
+attempt either requests a large object, or encounters an empty small object
+free list, and notices that there is a collection in progress, it immediately
+performs a small amount of marking work as described above.
+
+This change was made both because we wanted to easily accommodate
+single-threaded environments, and because a separate GC thread requires very
+careful control over the scheduler to prevent the mutator from out-running the
+collector, and hence provoking unneeded heap growth.
+
+In incremental mode, the heap is always expanded when we encounter
+insufficient space for an allocation. Garbage collection is triggered whenever
+we notice that more than `GC_heap_size / 2 * GC_free_space_divisor` bytes
+of allocation have taken place. After `GC_full_freq` minor collections a major
+collection is started.
+
+All collections initially run uninterrupted until a predetermined amount
+of time (50 ms by default) has expired. If this allows the collection
+to complete entirely, we can avoid correcting for data structure modifications
+during the collection. If it does not complete, we return control to the
+mutator, and perform small amounts of additional GC work during those later
+allocations that cannot be satisfied from small object free lists. When
+marking completes, the set of modified pages is retrieved, and we mark once
+again from marked objects on those pages, this time with the mutator stopped.
+
+We keep track of modified pages using one of several distinct mechanisms:
+
+  * (`MPROTECT_VDB`) By write-protecting physical pages and catching write
+  faults. This is implemented for many Unix-like systems and for Win32. It is
+  not possible in a few environments.
+  * (`GWW_VDB`) By using the Win32 `GetWriteWatch` function to read dirty
+  bits.
+  * (`PROC_VDB`) By retrieving dirty bit information from /proc. (Currently
+  only Sun's Solaris supports this. Though this is considerably cleaner,
+  performance may actually be better with `mprotect` and signals.)
+  * (`SOFT_VDB`) By retrieving Linux soft-dirty bit information from /proc.
+  * (`PCR_VDB`) By relying on an external dirty bit implementation, in this
+  case the one in Xerox PCR.
+  * Through explicit mutator cooperation. This enabled by
+  `GC_set_manual_vdb_allowed(1)` call, and requires the client code to call
+  `GC_ptr_store_and_dirty` or `GC_end_stubborn_change` (followed by a number
+  of `GC_reachable_here` calls), and is rarely used.
+  * (`DEFAULT_VDB`) By treating all pages as dirty. This is the default
+  if none of the other techniques is known to be usable. (Practical only for
+  testing.)
+
+## Black-listing
+
+The collector implements _black-listing_ of pages, as described in
+["Space Efficient Conservative Collection", PLDI'93](http://dl.acm.org/citation.cfm?doid=155090.155109)
+by Boehm, also available
+[here](https://www.cs.rice.edu/~javaplt/311/Readings/pldi93.pdf).
+
+During the mark phase, the collector tracks _near misses_, i.e. attempts
+to follow a _pointer_ to just outside the garbage-collected heap, or to
+a currently unallocated page inside the heap. Pages that have been the targets
+of such near misses are likely to be the targets of misidentified _pointers_
+in the future. To minimize the future damage caused by such misidentification,
+they will be allocated only to small pointer-free objects.
+
+The collector understands two different kinds of black-listing. A page may be
+black listed for interior pointer references (`GC_add_to_black_list_stack`),
+if it was the target of a near miss from a location that requires interior
+pointer recognition, e.g. the stack, or the heap if `GC_all_interior_pointers`
+is set. In this case, we also avoid allocating large blocks that include this
+page.
+
+If the near miss came from a source that did not require interior pointer
+recognition, it is black-listed with `GC_add_to_black_list_normal`. A page
+black-listed in this way may appear inside a large object, so long as it is
+not the first page of a large object.
+
+The `GC_allochblk` routine respects black-listing when assigning a block to
+a particular object kind and size. It occasionally drops (i.e. allocates and
+forgets) blocks that are completely black-listed in order to avoid excessively
+long large block free lists containing only unusable blocks. This would
+otherwise become an issue if there is low demand for small pointer-free
+objects.
+
+## Thread support
+
+We support several different threading models. Unfortunately Pthreads, the
+only reasonably well standardized thread model, supports too narrow
+an interface for conservative garbage collection. There appears to be no
+completely portable way to allow the collector to coexist with various
+Pthreads implementations. Hence we currently support only the more common
+Pthreads implementations.
+
+In particular, it is very difficult for the collector to stop all other
+threads in the system and examine the register contents. This is currently
+accomplished with very different mechanisms for some Pthreads implementations.
+For Linux/HPUX/OSF1, Solaris and Irix it sends signals to individual Pthreads
+and has them wait in the signal handler.
+
+The Linux and Irix implementations use only documented Pthreads calls, but
+rely on extensions to their semantics. The Linux implementation
+`pthread_stop_world.c` relies on only very mild extensions to the pthreads
+semantics, and already supports a large number of other Unix-like pthreads
+implementations. Our goal is to make this the only pthread support in the
+collector.
+
+All implementations must intercept thread creation and a few other
+thread-specific calls to allow enumeration of threads and location of thread
+stacks. This is current accomplished with `#define`'s in `gc.h` (really
+`gc_pthread_redirects.h`), or optionally by using `ld`'s function call
+wrapping mechanism under Linux.
+
+The collector support several facilities to enhance the processor-scalability
+and thread performance of the collector. These are discussed in more detail
+[here](scale.md). We briefly outline the data approach to thread-local
+allocation in the next section.
+
+## Thread-local allocation
+
+If thread-local allocation is enabled (which is true in the default
+configuration for most supported platforms), the collector keeps separate
+arrays of free lists for each thread.
+
+The free list arrays associated with each thread are only used to satisfy
+requests for objects that are both very small, and belong to one of a small
+number of well-known kinds. These include _normal_, pointer-free, _gcj_ and
+_disclaim_ objects.
+
+Thread-local free list entries contain either a pointer to the first element
+of a free list, or they contain a counter of the number of allocation
+granules, corresponding to objects of this size, allocated so far. Initially
+they contain the value one, i.e. a small counter value.
+
+Thread-local allocation goes directly through the global allocator if the
+object is of a size or kind not covered by the local free lists.
+
+If there is an appropriate local free list, the allocator checks whether
+it contains a sufficiently small counter value. If so, the counter is simply
+incremented by a value, and the global allocator is used. In this way,
+the initial few allocations of a given size bypass the local allocator.
+A thread that only allocates a handful of objects of a given size will not
+build up its own free list for that size. This avoids wasting space for
+unpopular objects sizes or kinds.
+
+Once the counter passes a threshold, `GC_malloc_many` is called to allocate
+roughly `HBLKSIZE` space and put it on the corresponding local free list.
+Further allocations of that size and kind then use this free list, and no
+longer need to acquire the allocation lock. The allocation procedure
+is otherwise similar to the global free lists. The local free lists are also
+linked using the first word in the object. In most cases this means they
+require considerably less time.
+
+Local free lists are treated by most of the rest of the collector as though
+they were in-use reachable data. This requires some care, since pointer-free
+objects are not normally traced, and hence a special tracing procedure
+is required to mark all objects on pointer-free and gcj local free lists.
+
+On thread exit, any remaining thread-local free list entries are transferred
+back to the global free list.
+
+Note that if the collector is configured for thread-local allocation (the
+default for most platforms), `GC_malloc` and friends only use thread-local
+allocation.
+
+For some more details see [here](scale.md), and the technical report entitled
+["Fast Multiprocessor Memory Allocation and Garbage Collection"](http://www.hpl.hp.com/techreports/2000/HPL-2000-165.html).

+ 216 - 0
blitz.mod/bdwgc/doc/gcinterface.md

@@ -0,0 +1,216 @@
+# C/C++ Interface
+
+On many platforms, a single-threaded garbage collector library can be built
+to act as a plug-in `malloc` replacement. (Build it with
+`-DREDIRECT_MALLOC=GC_malloc -DIGNORE_FREE`.) This is often the best way to
+deal with third-party libraries which leak or prematurely free objects.
+`-DREDIRECT_MALLOC=GC_malloc` is intended primarily as an easy way to adapt
+old code, not for new development.
+
+New code should use the interface discussed below.
+
+Code must be linked against the GC library. On most UNIX platforms, depending
+on how the collector is built, this will be `libgc.a` or `libgc.so`.
+
+The following describes the standard C interface to the garbage collector.
+It is not a complete definition of the interface. It describes only the most
+commonly used functionality, approximately in decreasing order of frequency
+of use. This somewhat duplicates the information in `gc.man` file. The full
+interface is described in `gc.h` file.
+
+Clients should include `gc.h` (i.e., not `gc_config_macros.h`,
+`gc_pthread_redirects.h`, `gc_version.h`). In the case of multi-threaded code,
+`gc.h` should be included after the threads header file, and after defining
+`GC_THREADS` macro. The header file `gc.h` must be included in files that use
+either GC or threads primitives, since threads primitives will be redefined
+to cooperate with the GC on many platforms.
+
+Thread users should also be aware that on many platforms objects reachable
+only from thread-local variables may be prematurely reclaimed. Thus objects
+pointed to by thread-local variables should also be pointed to by a globally
+visible data area, e.g. thread's stack. (This behavior is viewed as a bug, but
+as one that is exceedingly hard to fix without some `libc` hooks.)
+
+`void * GC_MALLOC(size_t _bytes_)` - Allocates and clears _bytes_
+of storage. Requires (amortized) time proportional to _bytes_. The resulting
+object will be automatically deallocated when unreferenced. References from
+objects allocated with the system malloc are usually not considered by the
+collector. (See `GC_MALLOC_UNCOLLECTABLE`, however. Building the collector
+with `-DREDIRECT_MALLOC=GC_malloc_uncollectable` is often a way around this.)
+`GC_MALLOC` is a macro which invokes `GC_malloc` by default or, if `GC_DEBUG`
+is defined before `gc.h` is included, a debugging version that checks
+occasionally for overwrite errors, and the like.
+
+`void * GC_MALLOC_ATOMIC(size_t _bytes_)` - Allocates _bytes_
+of storage. Requires (amortized) time proportional to _bytes_. The resulting
+object will be automatically deallocated when unreferenced. The client
+promises that the resulting object will never contain any pointers. The memory
+is not cleared. This is the preferred way to allocate strings, floating point
+arrays, bitmaps, etc. More precise information about pointer locations can be
+communicated to the collector using the interface in `gc_typed.h`.
+
+`void * GC_MALLOC_UNCOLLECTABLE(size_t _bytes_)` - Identical
+to `GC_MALLOC`, except that the resulting object is not automatically
+deallocated. Unlike the system-provided `malloc`, the collector does scan the
+object for pointers to garbage-collectible memory, even if the block itself
+does not appear to be reachable. (Objects allocated in this way are
+effectively treated as roots by the collector.)
+
+`void * GC_REALLOC(void * _old_object_, size_t _new_bytes_)` - Allocates
+a new object of the indicated size and copy the old object's content into the
+new object. The old object is reused in place if convenient. If the original
+object was allocated with `GC_MALLOC_ATOMIC`, the new object is subject to the
+same constraints. If it was allocated as an uncollectible object, then the new
+object is uncollectible, and the old object (if different) is deallocated.
+
+`void GC_FREE(void * _object_)` - Explicitly deallocates an _object_.
+Typically not useful for small collectible objects.
+
+`void * GC_MALLOC_IGNORE_OFF_PAGE(size_t _bytes_)` and
+`void * GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(size_t _bytes_)` - Analogous
+to `GC_MALLOC` and `GC_MALLOC_ATOMIC`, respectively, except that the client
+guarantees that as long as the resulting object is of use, a pointer
+is maintained to someplace inside the first 512 bytes of the object. This
+pointer should be declared volatile to avoid interference from compiler
+optimizations. (Other nonvolatile pointers to the object may exist as well.)
+This is the preferred way to allocate objects that are likely to be
+more than 100 KB in size. It greatly reduces the risk that such objects will
+be accidentally retained when they are no longer needed. Thus space usage may
+be significantly reduced. Another way is `GC_set_all_interior_pointers(0)`
+called at program start (this, however, is generally not suitable for C++ code
+because of multiple inheritance).
+
+`void GC_INIT()` - On some platforms, it is necessary to invoke this _from
+the main executable_, _not from a dynamic library_, before the initial
+invocation of a GC routine. It is recommended that this be done in portable
+code, though we try to ensure that it expands to a no-op on as many platforms
+as possible.
+
+`void GC_gcollect(void)` - Explicitly forces a garbage collection.
+
+`void GC_enable_incremental(void)` - Causes the garbage collector
+to perform a small amount of work every few invocations of `GC_MALLOC` or the
+like, instead of performing an entire collection at once. This is likely
+to increase total running time. It will improve response on a platform that
+has suitable support in the garbage collector (Linux and most Unix versions,
+Win32 if the collector was suitably built). On many platforms this interacts
+poorly with system calls that write to the garbage collected heap.
+
+`void GC_set_warn_proc(GC_warn_proc)` - Replaces the default procedure
+used by the collector to print warnings. The collector may otherwise
+write to `stderr`, most commonly because `GC_malloc` was used in a situation
+in which `GC_malloc_ignore_off_page` would have been more appropriate. See
+`gc.h` for details.
+
+`void GC_REGISTER_FINALIZER(...)` - Registers a function to be called when
+an object becomes inaccessible. This is often useful as a backup method for
+releasing system resources (e.g. closing files) when the object referencing
+them becomes inaccessible. It is not an acceptable method to perform actions
+that must be performed in a timely fashion. See `gc.h` for details of the
+interface. See also [here](finalization.md) for a more detailed discussion
+of the design. Note that an object may become inaccessible before client code
+is done operating on objects referenced by its fields. Suitable
+synchronization is usually required. See
+[here](http://portal.acm.org/citation.cfm?doid=604131.604153) or
+[here](http://www.hpl.hp.com/techreports/2002/HPL-2002-335.html) for details.
+
+If you are concerned with multiprocessor performance and scalability, you
+should consider enabling and using thread local allocation.
+
+If your platform supports it, you should also build the collector with
+parallel marking support (`-DPARALLEL_MARK`); configure has it on by default.
+
+If the collector is used in an environment in which pointer location
+information for heap objects is easily available, this can be passed on to the
+collector using the interfaces in either `gc_typed.h` or `gc_gcj.h`.
+
+The collector distribution also includes a **string package** that takes
+advantage of the collector. For details see `cord.h` file.
+
+## C++ Interface
+
+The C++ interface is implemented as a thin layer on the C interface.
+Unfortunately, this thin layer appears to be very sensitive to variations
+in C++ implementations, particularly since it tries to replace the global
+`::new` operator, something that appears to not be well-standardized. Your
+platform may need minor adjustments in this layer (`gc_badalc.cc`,
+`gc_cpp.cc`, `gc_cpp.h`, and possibly `gc_allocator.h`). Such changes do not
+require understanding of collector internals, though they may require a good
+understanding of your platform. (Patches enhancing portability are welcome.
+But it is easy to break one platform by fixing another.)
+
+Usage of the collector from C++ is also complicated by the fact that there are
+many _standard_ ways to allocate memory in C++. The default `::new` operator,
+default `malloc`, and default STL allocators allocate memory that is not
+garbage collected, and is not normally _traced_ by the collector. This means
+that any pointers in memory allocated by these default allocators will not be
+seen by the collector. Garbage-collectible memory referenced only by pointers
+stored in such default-allocated objects is likely to be reclaimed prematurely
+by the collector.
+
+It is the programmers responsibility to ensure that garbage-collectible memory
+is referenced by pointers stored in one of
+
+  * Program variables
+  * Garbage-collected objects
+  * Uncollected but _traceable_ objects
+
+Traceable objects are not necessarily reclaimed by the collector, but are
+scanned for pointers to collectible objects. They are usually allocated
+by `GC_MALLOC_UNCOLLECTABLE`, as described above, and through some interfaces
+described below.
+
+On most platforms, the collector may not trace correctly from in-flight
+exception objects. Thus objects thrown as exceptions should only point
+to otherwise reachable memory. This is another bug whose proper repair
+requires platform hooks.
+
+The easiest way to ensure that collectible objects are properly referenced
+is to allocate only collectible objects. This requires that every allocation
+go through one of the following interfaces, each one of which replaces
+a standard C++ allocation mechanism. Note that this requires that all STL
+containers be explicitly instantiated with `gc_allocator`.
+
+### STL allocators
+
+Recent versions of the collector include a hopefully standard-conforming
+allocator implementation in `gc_allocator.h`. It defines `traceable_allocator`
+and `gc_allocator` which may be used either directly to allocate memory or to
+instantiate container templates. The former allocates uncollectible but traced
+memory. The latter allocates garbage-collected memory.
+
+These should work with any fully standard-conforming C++ compiler.
+
+### Class inheritance based interface for new-based allocation
+
+Users may include `gc_cpp.h` and then cause members of classes to be allocated
+in garbage collectible memory by having those classes inherit from class `gc`.
+For details see `gc_cpp.h` file.
+
+Linking against `libgccpp` in addition to the `gc` library overrides `::new`
+(and friends) to allocate traceable but uncollectible memory, making
+it safe to refer to collectible objects from the resulting memory.
+
+If the user includes `gc_cpp.h` but `::new` should not be overridden then
+`libgctba` (in addition to the `gc`) library should be linked with to provide
+the definition of `GC_throw_bad_alloc` C++ function used by operator `new` of
+class `gc`. Alternatively, the client may define `GC_NEW_ABORTS_ON_OOM` macro
+before include of `gc_cpp.h` (this instructs `::new` to issue an abort instead
+of throwing an exception), or may define `GC_INCLUDE_NEW` one before include
+of `gc_cpp.h` (however, this might not compile or work as expected on some
+platforms).
+
+## C interface
+
+It is also possible to use the C interface from `gc.h` directly. On platforms
+which use `malloc` to implement `::new`, it should usually be possible to use
+a version of the collector that has been compiled as a `malloc` replacement.
+It is also possible to replace `::new` and other allocation functions
+suitably, as is done by `libgccpp`.
+
+Note that user-implemented small-block allocation often works poorly with
+an underlying garbage-collected large block allocator, since the collector has
+to view all objects accessible from the user's free list as reachable. This
+is likely to cause problems if `GC_MALLOC` is used with something like the
+original HP version of STL. This approach works well with the SGI versions
+of the STL only if the `malloc_alloc` allocator is used.

+ 160 - 0
blitz.mod/bdwgc/doc/leak.md

@@ -0,0 +1,160 @@
+# Using the Garbage Collector as Leak Detector
+
+The garbage collector may be used as a leak detector. In this case, the
+primary function of the collector is to report objects that were allocated
+(typically with `GC_MALLOC`), not deallocated (normally with `GC_FREE`), but
+are no longer accessible. Since the object is no longer accessible, there
+is normally no way to deallocate the object at a later time; thus it can
+safely be assumed that the object has been "leaked".
+
+This is substantially different from counting leak detectors, which simply
+verify that all allocated objects are eventually deallocated.
+A garbage-collector based leak detector can provide somewhat more precise
+information when an object was leaked. More importantly, it does not report
+objects that are never deallocated because they are part of "permanent" data
+structures. Thus it does not require all objects to be deallocated at process
+exit time, a potentially useless activity that often triggers large amounts
+of paging.
+
+The garbage collector provides leak detection support. This includes the
+following features:
+
+  1. Leak detection mode can be initiated at run-time by `GC_set_find_leak(1)`
+  call at program startup instead of building the collector with `FIND_LEAK`
+  macro defined.
+  2. Leaked objects should be reported and then correctly garbage collected.
+
+To use the collector as a leak detector, do the following steps:
+
+  1. Activate the leak detection mode as described above.
+  2. Change the program so that all allocation and deallocation goes through
+  the garbage collector.
+  3. Arrange to call `GC_gcollect` (or `CHECK_LEAKS()`) at appropriate points
+  to check for leaks. (This happens implicitly but probably not with
+  a sufficient frequency for long running programs.)
+
+The second step can usually be accomplished with the
+`-DREDIRECT_MALLOC=GC_malloc` option when the collector is built, or by
+defining `malloc`, `calloc`, `realloc`, `free` (as well as `strdup`,
+`strndup`, `wcsdup`, `memalign`, `posix_memalign`) to call the corresponding
+garbage collector functions. But this, by itself, will not yield very
+informative diagnostics, since the collector does not keep track of the
+information about how objects were allocated. The error reports will include
+only object addresses.
+
+For more precise error reports, as much of the program as possible should use
+the all uppercase variants of these functions, after defining `GC_DEBUG`, and
+then including `gc.h`. In this environment `GC_MALLOC` is a macro which causes
+at least the file name and line number at the allocation point to be saved
+as part of the object. Leak reports will then also include this information.
+
+Many collector features (e.g. finalization and disappearing links) are less
+useful in this context, and are not fully supported. Their use will usually
+generate additional bogus leak reports, since the collector itself drops some
+associated objects.
+
+The same is generally true of thread support. However, the correct leak
+reports should be generated with linuxthreads, at least.
+
+On a few platforms (currently Solaris/SPARC, Irix, and, with
+`-DSAVE_CALL_CHAIN`, Linux/X86), `GC_MALLOC` also causes some more information
+about its call stack to be saved in the object. Such information is reproduced
+in the error reports in very non-symbolic form, but it can be very useful with
+the aid of a debugger.
+
+## An Example
+
+The `leak_detector.h` file is included in the "include" subdirectory of the
+distribution.
+
+Assume the collector has been built with `-DFIND_LEAK` or
+`GC_set_find_leak(1)` exists as the first statement in `main`.
+
+The program to be tested for leaks could look like `tests/leak_test.c` file
+of the distribution.
+
+On an Intel X86 Linux system this produces on the stderr stream:
+
+
+    Found 1 leaked objects:
+    0x806dff0 (tests/leak_test.c:19, sz=4, NORMAL)
+
+
+(On most unmentioned operating systems, the output is similar to this. If the
+collector had been built on Linux/X86 with `-DSAVE_CALL_CHAIN`, the output
+would be closer to the Solaris example. For this to work, the program should
+not be compiled with `-fomit_frame_pointer`.)
+
+On Irix it reports:
+
+
+    Found 1 leaked objects:
+    0x10040fe0 (tests/leak_test.c:19, sz=4, NORMAL)
+            Caller at allocation:
+                    ##PC##= 0x10004910
+
+
+and on Solaris the error report is:
+
+
+    Found 1 leaked objects:
+    0xef621fc8 (tests/leak_test.c:19, sz=4, NORMAL)
+            Call chain at allocation:
+                    args: 4 (0x4), 200656 (0x30FD0)
+                    ##PC##= 0x14ADC
+                    args: 1 (0x1), -268436012 (0xEFFFFDD4)
+                    ##PC##= 0x14A64
+
+
+In the latter two cases some additional information is given about how malloc
+was called when the leaked object was allocated. For Solaris, the first line
+specifies the arguments to `GC_debug_malloc` (the actual allocation routine),
+The second one specifies the program counter inside `main`, the third one
+specifies the arguments to `main`, and, finally, the program counter inside
+the caller to `main` (i.e. in the C startup code). In the Irix case, only the
+address inside the caller to `main` is given.
+
+In many cases, a debugger is needed to interpret the additional information.
+On systems supporting the `adb` debugger, the `tools/callprocs.sh` script can
+be used to replace program counter values with symbolic names. The collector
+tries to generate symbolic names for call stacks if it knows how to do so on
+the platform. This is true on Linux/X86, but not on most other platforms.
+
+## Simplified leak detection under Linux
+
+It should be possible to run the collector in the leak detection mode on
+a program a.out under Linux/X86 as follows:
+
+  1. If possible, ensure that a.out is a single-threaded executable. On some
+  platforms this does not work at all for the multi-threaded programs.
+  2. If possible, ensure that the `addr2line` program is installed
+  in `/usr/bin`. (It comes with most Linux distributions.)
+  3. If possible, compile your program, which we'll call `a.out`, with full
+  debug information. This will improve the quality of the leak reports.
+  With this approach, it is no longer necessary to call `GC_` routines
+  explicitly, though that can also improve the quality of the leak reports.
+  4. Build the collector and install it in directory _foo_ as follows (it may
+  be safe to omit the `--disable-threads` option on Linux, but the combination
+  of thread support and `malloc` replacement is not yet rock solid):
+
+   - `configure --prefix=_foo_ --enable-gc-debug --enable-redirect-malloc --disable-threads`
+   - `make`
+   - `make install`
+
+  5. Set environment variables as follows (the last two are optional, just to
+  confirm the collector is running, and to facilitate debugging from another
+  console window if something goes wrong, respectively):
+
+   - `LD_PRELOAD=_foo_/lib/libgc.so`
+   - `GC_FIND_LEAK`
+   - `GC_PRINT_STATS`
+   - `GC_LOOP_ON_ABORT`
+
+  6. Simply run `a.out` as you normally would. Note that if you run anything
+  else (e.g. your editor) with those environment variables set, it will also
+  be leak tested. This may or may not be useful and/or embarrassing. It can
+  generate mountains of leak reports if the application was not designed
+  to avoid leaks, e.g. because it's always short-lived.
+
+This has not yet been thoroughly tested on large applications, but it's known
+to do the right thing on at least some small ones.

+ 310 - 0
blitz.mod/bdwgc/doc/overview.md

@@ -0,0 +1,310 @@
+[Interface Overview](gcinterface.md) | [Tutorial Slides](http://www.hboehm.info/gc/04tutorial.pdf) | [FAQ](http://www.hboehm.info/gc/faq.html) | [Example](simple_example.md) | [Download](https://github.com/ivmai/bdwgc/wiki/Download) | [License](http://www.hboehm.info/gc/license.txt)
+---|---|---|---|---|---
+
+# A garbage collector for C and C++
+
+  * Platforms
+  * Some collector details
+  * Further reading
+  * Information provided on the BDWGC site
+  * More background information
+  * Contacts and new release announcements
+
+[ This is an updated version of the page formerly at
+`www.hpl.hp.com/personal/Hans_Boehm/gc/`, before that at
+`http://reality.sgi.com/boehm/gc.html` and before that at
+`ftp://ftp.parc.xerox.com/pub/gc/gc.html`. ]
+
+The
+[Boehm](http://www.hboehm.info)-[Demers](http://www.cs.cornell.edu/annual_report/00-01/bios.htm#demers)-[Weiser](http://www.ubiq.com/hypertext/weiser/weiser.html)
+conservative Garbage Collector (**BDWGC**) can be used as a garbage collecting
+replacement for C `malloc` or C++ `new`. It allows you to allocate memory
+basically as you normally would, without explicitly deallocating memory that
+is no longer useful. The collector automatically recycles memory when
+it determines that it can no longer be otherwise accessed. A simple example
+of such a use is given [here](simple_example.md).
+
+The collector is also used by a number of programming language implementations
+that either use C as intermediate code, want to facilitate easier
+interoperation with C libraries, or just prefer the simple collector
+interface. For a more detailed description of the interface, see
+[here](gcinterface.md).
+
+Alternatively, the garbage collector may be used as a [leak detector](leak.md)
+for C or C++ programs, though that is not its primary goal.
+
+Typically several versions are offered for
+[downloading](https://github.com/ivmai/bdwgc/wiki/Download): preview, stable,
+legacy. Usually you should use the one marked as the _latest stable_ release.
+Preview versions may contain additional features, platform support, but are
+likely to be less well tested. The list of changes for each version
+is specified on the [releases](https://github.com/ivmai/bdwgc/releases) page.
+The development version (snapshot) is available in the master branch of
+[bdwgc git](https://github.com/ivmai/bdwgc) repository on GitHub.
+
+The arguments for and against conservative garbage collection in C and C++ are
+briefly discussed [here](http://www.hboehm.info/gc/issues.html). The
+beginnings of a frequently-asked-questions list are
+[here](http://www.hboehm.info/gc/faq.html).
+
+The garbage collector code is copyrighted by
+[Hans-J. Boehm](http://www.hboehm.info), Alan J. Demers,
+[Xerox Corporation](http://www.xerox.com/),
+[Silicon Graphics](http://www.sgi.com/),
+[Hewlett-Packard Company](http://www.hp.com/),
+[Ivan Maidanski](https://github.com/ivmai), and partially by some others.
+It may be used and copied without payment of a fee under minimal restrictions.
+See the LICENSE file in the distribution or the
+[license](http://www.hboehm.info/gc/license.txt) for more details.
+**IT IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED OR IMPLIED.
+ANY USE IS AT YOUR OWN RISK.**
+
+Empirically, this collector works with most unmodified C programs, simply
+by replacing `malloc` and `calloc` with `GC_malloc` calls, replacing `realloc`
+with `GC_realloc` calls, and removing `free` calls. Exceptions are discussed
+[here](http://www.hboehm.info/gc/issues.html).
+
+## Platforms
+
+The collector is not completely portable, but the distribution includes ports
+to most standard PC and UNIX/Linux platforms. The collector should work
+on Linux, Android, BSD variants, OS/2, Windows (Win32 and Win64), MacOS X,
+iOS, HP/UX, Solaris, Tru64, Irix, Symbian and other operating systems. Some
+platforms are more polished (better supported) than others.
+
+Irix pthreads, Linux threads, Windows threads, Solaris threads (pthreads
+only), HP/UX 11 pthreads, Tru64 pthreads, and MacOS X threads are supported.
+
+## Some Collector Details
+
+The collector uses a [mark-sweep](http://www.hboehm.info/gc/complexity.html)
+algorithm. It provides incremental and generational collection under operating
+systems which provide the right kind of virtual memory support. (Currently
+this includes SunOS[45], IRIX, OSF/1, Linux, and Windows, with varying
+restrictions.) It allows [finalization](finalization.md) code to be invoked
+when an object is collected. It can take advantage of type information
+to locate pointers if such information is provided, but it is usually used
+without such information. See the README and `gc.h` files in the distribution
+for more details.
+
+For an overview of the implementation, see [here](gcdescr.md).
+
+The garbage collector distribution includes a C string (`cord.h`) package that
+provides for fast concatenation and substring operations on long strings.
+A simple curses- and win32-based editor that represents the entire file as
+a cord is included as a sample application.
+
+Performance of the non-incremental collector is typically competitive with
+`malloc`/`free` implementations. Both space and time overhead are likely to be
+only slightly higher for programs written for `malloc`/`free` (see Detlefs,
+Dosser and Zorn's
+[Memory Allocation Costs in Large C and C++ Programs](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.30.3073&rep=rep1&type=ps)).
+For programs allocating primarily very small objects, the collector may be
+faster; for programs allocating primarily large objects it will be slower.
+If the collector is used in a multi-threaded environment and configured for
+thread-local allocation, it may in some cases significantly outperform
+`malloc`/`free` allocation in time.
+
+We also expect that in many cases any additional overhead will be more than
+compensated for by e.g. decreased copying if programs are written and tuned
+for garbage collection.
+
+## Further reading
+
+**The beginnings of a frequently asked questions list for this collector are
+[here](http://www.hboehm.info/gc/faq.html).**
+
+**The following provide information on garbage collection in general:**
+
+Paul Wilson's
+[garbage collection ftp archive](ftp://ftp.cs.utexas.edu/pub/garbage)
+and [GC survey](ftp://ftp.cs.utexas.edu/pub/garbage/gcsurvey.ps).
+
+The Ravenbrook
+[Memory Management Reference](http://www.memorymanagement.org/).
+
+David Chase's [GC FAQ](http://www.iecc.com/gclist/GC-faq.html).
+
+Richard Jones'
+[Garbage Collection Page](https://www.cs.kent.ac.uk/people/staff/rej/gc.html)
+and his [book](http://www.cs.kent.ac.uk/people/staff/rej/gcbook/gcbook.html).
+
+**The following papers describe the collector algorithms we use and the
+underlying design decisions at a higher level:**
+
+(Some of the lower level details can be found [here](gcdescr.md).)
+
+The first one is not available electronically due to copyright considerations.
+Most of the others are subject to ACM copyright.
+
+Boehm, H., Dynamic Memory Allocation and Garbage Collection,
+_Computers in Physics 9_, 3, May/June 1995, pp. 297-303. This is directed
+at an otherwise sophisticated audience unfamiliar with memory allocation
+issues. The algorithmic details differ from those in the implementation. There
+is a related letter to the editor and a minor correction in the next issue.
+
+Boehm, H., and [M. Weiser](http://www.ubiq.com/hypertext/weiser/weiser.html),
+[Garbage Collection in an Uncooperative Environment](http://www.hboehm.info/spe_gc_paper/),
+_Software Practice and Experience_, September 1988, pp. 807-820.
+
+Boehm, H., A. Demers, and S. Shenker,
+[Mostly Parallel Garbage Collection](http://www.hboehm.info/gc/papers/pldi91.ps.Z),
+Proceedings of the ACM SIGPLAN '91 Conference on Programming Language Design
+and Implementation, _SIGPLAN Notices 26_, 6 (June 1991), pp. 157-164.
+
+Boehm, H.,
+[Space Efficient Conservative Garbage Collection](http://www.hboehm.info/gc/papers/pldi93.ps.Z),
+Proceedings of the ACM SIGPLAN '93 Conference on Programming Language Design
+and Implementation, _SIGPLAN Notices 28_, 6 (June 1993), pp. 197-206.
+
+Boehm, H., Reducing Garbage Collector Cache Misses,
+_Proceedings of the 2000 International Symposium on Memory Management_.
+[Official version](http://portal.acm.org/citation.cfm?doid=362422.362438).
+[Technical report](http://www.hpl.hp.com/techreports/2000/HPL-2000-99.html)
+version. Describes the prefetch strategy incorporated into the collector for
+some platforms. Explains why the sweep phase of a _mark-sweep_ collector
+should not really be a distinct phase.
+
+M. Serrano, H. Boehm, Understanding Memory Allocation of Scheme Programs,
+_Proceedings of the Fifth ACM SIGPLAN International Conference on Functional
+Programming_, 2000, Montreal, Canada, pp. 245-256.
+[Official version](http://dl.acm.org/citation.cfm?id=351264). Earlier
+[Technical Report](http://www.hpl.hp.com/techreports/2000/HPL-2000-62.html)
+version. Includes some discussion of the collector debugging facilities for
+identifying causes of memory retention.
+
+Boehm, H., Fast Multiprocessor Memory Allocation and Garbage Collection,
+[HP Labs Technical Report HPL 2000-165](http://www.hpl.hp.com/techreports/2000/HPL-2000-165.html).
+Discusses the parallel collection algorithms, and presents some performance
+results.
+
+Boehm, H., Bounding Space Usage of Conservative Garbage Collectors,
+_Proceedings of the 2002 ACM SIGPLAN-SIGACT Symposium on Principles
+of Programming Languages_, Jan. 2002, pp. 93-100.
+[Official version](http://portal.acm.org/citation.cfm?doid=503272.503282).
+[Technical report](http://www.hpl.hp.com/techreports/2001/HPL-2001-251.html)
+version. Includes a discussion of a collector facility to much more reliably
+test for the potential of unbounded heap growth.
+
+**The following papers discuss language and compiler restrictions necessary
+to guaranteed safety of conservative garbage collection:**
+
+We thank John Levine and JCLT for allowing us to make the second paper
+available electronically, and providing PostScript for the final version.
+
+Boehm, H.,
+[Simple Garbage-Collector-Safety](http://www.hboehm.info/gc/papers/pldi96.ps.gz),
+Proceedings of the ACM SIGPLAN '96 Conference on Programming Language Design
+and Implementation.
+
+Boehm, H., and D. Chase,
+[A Proposal for Garbage-Collector-Safe C Compilation](http://www.hboehm.info/gc/papers/boecha.ps.gz),
+_Journal of C Language Translation 4_, 2 (December 1992), pp. 126-141.
+
+**Other related information:**
+
+The Detlefs, Dosser and Zorn's
+[Memory Allocation Costs in Large C and C++ Programs](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.30.3073&rep=rep1&type=ps).
+This is a performance comparison of the Boehm-Demers-Weiser collector
+to `malloc`/`free`, using programs written for `malloc`/`free`.
+
+Joel Bartlett's
+[mostly copying conservative garbage collector for C++](ftp://gatekeeper.dec.com/pub/compaq/WRL/research-reports/WRL-TN-12.ps).
+
+John Ellis and David Detlef's
+[Safe Efficient Garbage Collection for C++](http://dl.acm.org/citation.cfm?id=1267983)
+proposal.
+
+Henry Baker's [paper collection](http://home.pipeline.com/%7Ehbaker1/).
+
+Slides for Hans Boehm's
+[Allocation and GC Myths](http://www.hboehm.info/gc/myths.ps) talk.
+
+## Information provided on the BDWGC site
+
+[Current users](https://github.com/ivmai/bdwgc/wiki/Known-clients) list.
+
+[A simple illustration of how to build and use the collector](simple_example.md).
+
+[Description of alternate interfaces to the garbage collector](gcinterface.md).
+
+[Slides from an ISMM 2004 tutorial about the GC](http://www.hboehm.info/gc/04tutorial.pdf).
+
+[A FAQ (frequently asked questions) list](http://www.hboehm.info/gc/faq.html).
+
+[How to use the garbage collector as a leak detector](leak.md).
+
+[Some hints on debugging garbage collected applications](debugging.md).
+
+[An overview of the implementation of the garbage collector](gcdescr.md).
+
+[The data structure used for fast pointer lookups](tree.md).
+
+[Scalability of the collector to multiprocessors](scale.md).
+
+[Directory](http://www.hboehm.info/gc/gc_source/) containing the distribution
+files of all garbage collector releases. It duplicates
+[Download](https://github.com/ivmai/bdwgc/wiki/Download) page on GitHub.
+
+## More background information
+
+[An attempt to establish a bound on space usage of conservative garbage collectors](http://www.hboehm.info/gc/bounds.html).
+
+[Mark-sweep versus copying garbage collectors and their complexity](http://www.hboehm.info/gc/complexity.html).
+
+[Pros and cons of conservative garbage collectors, in comparison to other collectors](http://www.hboehm.info/gc/conservative.html).
+
+[Issues related to garbage collection vs. manual memory management in C/C++](http://www.hboehm.info/gc/issues.html).
+
+[An example of a case in which garbage collection results in a much faster implementation as a result of reduced synchronization](http://www.hboehm.info/gc/example.html).
+
+[Slide set discussing performance of nonmoving garbage collectors](http://www.hboehm.info/gc/nonmoving/).
+
+[Slide set discussing _Destructors, Finalizers, and Synchronization_, POPL 2003](http://www.hboehm.info/popl03/web/).
+
+[Paper corresponding to above slide set](http://portal.acm.org/citation.cfm?doid=604131.604153)
+([Technical Report](http://www.hpl.hp.com/techreports/2002/HPL-2002-335.html)
+version).
+
+[A Java/Scheme/C/C++ garbage collection benchmark](http://www.hboehm.info/gc/gc_bench/).
+
+[Slides for talk on memory allocation myths](http://www.hboehm.info/gc/myths.ps).
+
+[Slides for OOPSLA 98 garbage collection talk](http://www.hboehm.info/gc/gctalk.ps).
+
+[Related papers](http://www.hboehm.info/gc/papers/).
+
+## Contacts and new release announcements
+
+GitHub and Stack Overflow are the major two places for communication.
+
+Technical questions (how to, how does it work, etc.) should be posted
+to [Stack Overflow](https://stackoverflow.com/questions/tagged/boehm-gc) with
+_boehm-gc_ tag.
+
+To contribute, please rebase your code to the latest
+[master](https://github.com/ivmai/bdwgc/tree/master/) and submit
+a [pull request](https://github.com/ivmai/bdwgc/pulls) to GitHub.
+
+To report a bug, or propose (request) a new feature, create
+a [GitHub issue](https://github.com/ivmai/bdwgc/issues). Please make sure
+it has not been reported yet by someone else.
+
+To receive notifications on every release, please subscribe to
+[Releases RSS feed](https://github.com/ivmai/bdwgc/releases.atom).
+Notifications on all issues and pull requests are available
+by [watching](https://github.com/ivmai/bdwgc/watchers) the project.
+
+Mailing lists ([email protected], [email protected],
+and the former [email protected] and [email protected]) are not
+used at this moment. Their content is available
+in
+[bdwgc-announce](https://github.com/ivmai/bdwgc/files/1037650/bdwgc-announce-mailing-list-archive-2014_02.tar.gz)
+and
+[bdwgc](https://github.com/ivmai/bdwgc/files/1038163/bdwgc-mailing-list-archive-2017_04.tar.gz)
+archive files, respectively. The gc list archive may also be read
+at [Narkive](http://bdwgc.opendylan.narkive.com).
+
+Some prior discussion of the collector has taken place on the gcc java mailing
+list, whose archives appear [here](http://gcc.gnu.org/ml/java/), and also
+on [[email protected]](http://lists.tunes.org/mailman/listinfo/gclist).

+ 263 - 0
blitz.mod/bdwgc/doc/porting.md

@@ -0,0 +1,263 @@
+# Conservative Garbage Collector Porting Directions
+
+The collector is designed to be relatively easy to port, but is not portable
+code per se. The collector inherently has to perform operations, such
+as scanning the stack(s), that are not possible in portable C code.
+
+All of the following assumes that the collector is being ported to
+a byte-addressable 32- or 64-bit machine. Currently all successful ports
+to 64-bit machines involve LP64 and LLP64 targets (notably Win64). You
+are hereby discouraged from attempting a port to non-byte-addressable,
+or 8-bit, or 16-bit machines.
+
+The difficulty of porting the collector varies greatly depending on the needed
+functionality. In the simplest case, only some small additions are needed for
+the `include/private/gcconfig.h` file. This is described in the following
+section. Later sections discuss some of the optional features, which typically
+involve more porting effort.
+
+Note that the collector makes heavy use of `ifdef`s. Unlike some other
+software projects, we have concluded repeatedly that this is preferable
+to system dependent files, with code duplicated between the files. However,
+to keep this manageable, we do strongly believe in indenting `ifdef`s
+correctly (for historical reasons usually without the leading sharp sign).
+(Separate source files are of course fine if they do not result in code
+duplication.)
+
+## Adding Platforms to gcconfig.h
+
+If neither thread support, nor tracing of dynamic library data is required,
+these are often the only changes you will need to make.
+
+The `gcconfig.h` file consists of three sections:
+
+  1. A section that defines GC-internal macros that identify the architecture
+  (e.g. `IA64` or `I386`) and operating system (e.g. `LINUX` or `MSWIN32`).
+  This is usually done by testing predefined macros. By defining our own
+  macros instead of using the predefined ones directly, we can impose a bit
+  more consistency, and somewhat isolate ourselves from compiler differences.
+  It is relatively straightforward to add a new entry here. But please try
+  to be consistent with the existing code. In particular, 64-bit variants
+  of 32-bit architectures general are _not_ treated as a new architecture.
+  Instead we explicitly test for 64-bit-ness in the few places in which
+  it matters. (The notable exception here is `I386` and `X86_64`. This
+  is partially historical, and partially justified by the fact that there are
+  arguably more substantial architecture and ABI differences here than for
+  RISC variants.) On GNU-based systems, `cpp -dM empty_source_file.c` seems
+  to generate a set of predefined macros. On some other systems, the "verbose"
+  compiler option may do so, or the manual page may list them.
+
+  2. A section that defines a small number of platform-specific macros, which
+  are then used directly by the collector. For simple ports, this is where
+  most of the effort is required. We describe the macros below. This section
+  contains a subsection for each architecture (enclosed in a suitable `ifdef`.
+  Each subsection usually contains some architecture-dependent defines,
+  followed by several sets of OS-dependent defines, again enclosed in
+  `ifdef`s.
+
+  3. A section that fills in defaults for some macros left undefined in the
+  preceding section, and defines some other macros that rarely need adjustment
+  for new platforms. You will typically not have to touch these. If you are
+  porting to an OS that was previously completely unsupported, it is likely
+  that you will need to add another clause to the definition of `GET_MEM`.
+
+The following macros must be defined correctly for each architecture and
+operating system:
+
+  * `MACH_TYPE` - Defined to a string that represents the machine
+  architecture. Usually just the macro name used to identify the architecture,
+  but enclosed in quotes.
+  * `OS_TYPE` - Defined to a string that represents the operating system name.
+  Usually just the macro name used to identify the operating system, but
+  enclosed in quotes.
+  * `CPP_WORDSZ` - The word size in bits as a constant suitable for
+  preprocessor tests, i.e. without casts or `sizeof` expressions. Currently
+  always defined as either 64 or 32. For platforms supporting both 32- and
+  64-bit ABIs, this should be conditionally defined depending on the current
+  ABI. There is a default of 32.
+  * `ALIGNMENT` - Defined to be the largest _N_ such that all pointer
+  are guaranteed to be aligned on _N_-byte boundaries. Defining it to be _1_
+  will always work, but perform poorly. For all modern 32-bit platforms, this
+  is 4. For all modern 64-bit platforms, this is 8. Whether or not X86
+  qualifies as a modern architecture here is compiler- and OS-dependent.
+  * `DATASTART` - The beginning of the main data segment. The collector will
+  trace all memory between `DATASTART` and `DATAEND` for root pointers.
+  On some platforms, this can be defined to a constant address, though
+  experience has shown that to be risky. Ideally the linker will define
+  a symbol (e.g. `_data`) whose address is the beginning of the data segment.
+  Sometimes the value can be computed using the `GC_SysVGetDataStart`
+  function. Not used if either the next macro is defined, or if dynamic
+  loading is supported, and the dynamic loading support defines a function
+  `GC_register_main_static_data` which returns false.
+  * `SEARCH_FOR_DATA_START` - If this is defined `DATASTART` will be defined
+  to a dynamically computed value which is obtained by starting with the
+  address of `_end` and walking backwards until non-addressable memory
+  is found. This often works on Posix-like platforms. It makes it harder
+  to debug client programs, since startup involves generating and catching
+  a segmentation fault, which tends to confuse users.
+  * `DATAEND` - Set to the end of the main data segment. Defaults to `_end`,
+  where that is declared as an array. This works in some cases, since the
+  linker introduces a suitable symbol.
+  * `DATASTART2`, `DATAEND2` - Some platforms have two discontiguous main data
+  segments, e.g. for initialized and uninitialized data. If so, these two
+  macros should be defined to the limits of the second main data segment.
+  * `STACK_GROWS_UP` - Should be defined if the stack (or thread stacks) grow
+  towards higher addresses. (This appears to be true only on PA-RISC. If your
+  architecture has more than one stack per thread, and is not supported yet,
+  you will need to do more work. Grep for "IA64" in the source for an
+  example.)
+  * `STACKBOTTOM` - Defined to be the cold end of the stack, which is usually
+  (i.e. when the stacks grow down) the highest address in the stack. It must
+  bound the region of the stack that contains pointers into the GC heap. With
+  thread support, this must be the cold end of the main stack, which typically
+  cannot be found in the same way as the other thread stacks. If this is not
+  defined and none of the following three macros is defined, client code must
+  explicitly set `GC_stackbottom` to an appropriate value before calling
+  `GC_INIT` or any other `GC_` routine.
+  * `LINUX_STACKBOTTOM` - May be defined instead of `STACKBOTTOM`. If defined,
+  then the cold end of the stack will be determined, we usually read it from
+  `/proc`.
+  * `HEURISTIC1` - May be defined instead of `STACKBOTTOM`. `STACK_GRAN`
+  should generally also be redefined. The cold end of the stack is determined
+  by taking an address inside `GC_init`s frame, and rounding it up to the next
+  multiple of `STACK_GRAN`. This works well if the stack bottom is always
+  aligned to a large power of two. (`STACK_GRAN` is predefined to 0x1000000,
+  which is rarely optimal.)
+  * `HEURISTIC2` - May be defined instead of `STACKBOTTOM`. The cold end
+  of the stack is determined by taking an address inside `GC_init`s frame,
+  incrementing it repeatedly in small steps (decrement if `STACK_GROWS_UP`),
+  and reading the value at each location. We remember the value when the first
+  Segmentation violation or Bus error is signaled, round that to the nearest
+  plausible page boundary, and use that as the stack bottom.
+  * `DYNAMIC_LOADING` - Should be defined if `dyn_load.c` has been updated for
+  this platform and tracing of dynamic library roots is supported.
+  * `GWW_VDB`, `MPROTECT_VDB`, `PROC_VDB`, `SOFT_VDB` - May be defined if the
+  corresponding _virtual dirty bit_ implementation in `os_dep.c` is usable on
+  this platform. This allows incremental/generational garbage collection.
+  (`GWW_VDB` uses the Win32 `GetWriteWatch` function to read dirty bits,
+  `MPROTECT_VDB` identifies modified pages by write protecting the heap and
+  catching faults. `PROC_VDB` and `SOFT_VDB` use the /proc pseudo-files to
+  read dirty bits.)
+  * `PREFETCH`, `GC_PREFETCH_FOR_WRITE` - The collector uses `PREFETCH(x)`
+  to preload the cache with the data at _x_ address. This defaults to a no-op.
+  * `CLEAR_DOUBLE` - If `CLEAR_DOUBLE` is defined, then `CLEAR_DOUBLE(x)`
+  is used as a fast way to clear the two words at `GC_malloc`-aligned address
+  _x_. By default, word stores of 0 are used instead.
+  * `HEAP_START` - May be defined as the initial address hint for mmap-based
+  allocation.
+
+## Additional requirements for a basic port
+
+In some cases, you may have to add additional platform-specific code to other
+files. A likely candidate is the implementation
+of `GC_with_callee_saves_pushed` in `mach_dep.c`. This ensure that register
+contents that the collector must trace from are copied to the stack. Typically
+this can be done portably, but on some platforms it may require assembly code,
+or just tweaking of conditional compilation tests.
+
+If your platform supports `getcontext` then defining the macro
+`UNIX_LIKE` for your OS in `gcconfig.h` (if it is not defined there yet)
+is likely to solve the problem. Otherwise, if you are using gcc,
+`_builtin_unwind_init` will be used, and should work fine. If that is not
+applicable either, the implementation will try to use `setjmp`. This will work
+if your `setjmp` implementation saves all possibly pointer-valued registers
+into the buffer, as opposed to trying to unwind the stack at `longjmp` time.
+The `setjmp_test` test tries to determine this, but often does not get it
+right. Registers tracing handled with an assembly code is generally to be
+avoided.
+
+Most commonly `os_dep.c` will not require attention, but see below.
+
+## Thread support
+
+Supporting threads requires that the collector be able to find and suspend all
+threads potentially accessing the garbage-collected heap, and locate any state
+associated with each thread that must be traced.
+
+The functionality needed for thread support is generally implemented in one or
+more files specific to the particular thread interface. For example, somewhat
+portable pthread support is implemented in `pthread_support.c` and
+`pthread_stop_world.c`. The essential functionality consists of:
+
+  * `GC_stop_world` - Stops all threads which may access the garbage collected
+  heap, other than the caller;
+  * `GC_start_world` - Restart other threads;
+  * `GC_push_all_stacks` - Push the contents of all thread stacks (or,
+  at least, of pointer-containing regions in the thread stacks) onto the mark
+  stack.
+
+These very often require that the garbage collector maintain its own data
+structures to track active threads.
+
+In addition, `LOCK` and `UNLOCK` must be implemented in `gc_locks.h`.
+
+The easiest case is probably a new pthreads platform on which threads can be
+stopped with signals. In this case, the changes involve:
+
+  1. Introducing a suitable `GC_xxx_THREADS` macro, which should
+  be automatically defined by `gc_config_macros.h` in the right cases.
+  It should also result in a definition of `GC_PTHREADS`, as for the existing
+  cases.
+  2. Ensuring that the `atomic_ops` package at least minimally
+  supports the platform. If incremental GC is needed, or if pthread locks
+  do not perform adequately as the allocation lock, you will probably need
+  to ensure that a sufficient `atomic_ops` port exists for the platform
+  to provided an atomic test and set operation. The latest GC code can use
+  GCC atomic intrinsics instead of `atomic_ops` package (see
+  `include/private/gc_atomic_ops.h`).
+  3. Making any needed adjustments to `pthread_stop_world.c` and
+  `pthread_support.c`. Ideally none should be needed. In fact, not all of this
+  is as well standardized as one would like, and outright bugs requiring
+  workarounds are common.  Non-preemptive threads packages will probably
+  require further work. Similarly thread-local allocation and parallel marking
+  requires further work in `pthread_support.c`, and may require better
+  `atomic_ops` support for the designed platform.
+
+## Dynamic library support
+
+So long as `DATASTART` and `DATAEND` are defined correctly, the collector will
+trace memory reachable from file scope or `static` variables defined as part
+of the main executable. This is sufficient if either the program is statically
+linked, or if pointers to the garbage-collected heap are never stored
+in non-stack variables defined in dynamic libraries.
+
+If dynamic library data sections must also be traced, then:
+
+  * `DYNAMIC_LOADING` must be defined in the appropriate section of
+  `gcconfig.h`.
+  * An appropriate versions of the functions `GC_register_dynamic_libraries`
+  should be defined in `dyn_load.c`. This function should invoke
+  `GC_cond_add_roots(region_start, region_end, TRUE)` on each dynamic
+  library data section.
+
+Implementations that scan for writable data segments are error prone,
+particularly in the presence of threads. They frequently result in race
+conditions when threads exit and stacks disappear. They may also accidentally
+trace large regions of graphics memory, or mapped files. On at least one
+occasion they have been known to try to trace device memory that could not
+safely be read in the manner the GC wanted to read it.
+
+It is usually safer to walk the dynamic linker data structure, especially
+if the linker exports an interface to do so. But beware of poorly documented
+locking behavior in this case.
+
+## Incremental GC support
+
+For incremental and generational collection to work, `os_dep.c` must contain
+a suitable _virtual dirty bit_ implementation, which allows the collector
+to track which heap pages (assumed to be a multiple of the collector's block
+size) have been written during a certain time interval. The collector provides
+several implementations, which might be adapted. The default (`DEFAULT_VDB`)
+is a placeholder which treats all pages as having been written. This ensures
+correctness, but renders incremental and generational collection essentially
+useless.
+
+## Stack traces for debug support
+
+If stack traces in objects are needed for debug support, `GC_save_callers` and
+`GC_print_callers` must be implemented.
+
+## Disclaimer
+
+This is an initial pass at porting guidelines. Some things have no doubt been
+overlooked.

+ 172 - 0
blitz.mod/bdwgc/doc/scale.md

@@ -0,0 +1,172 @@
+# Garbage collector scalability
+
+If Makefile.direct is used, in its default configuration the
+Boehm-Demers-Weiser garbage collector is not thread-safe. Generally, it can be
+made thread-safe by building the collector with `-DGC_THREADS` compilation
+flag. This has primarily the following effects:
+
+  1. It causes the garbage collector to stop all other threads when it needs
+  to see a consistent memory state. It intercepts thread creation and
+  termination events to maintain a list of client threads to be stopped when
+  needed.
+  2. It causes the collector to acquire a lock around essentially all
+  allocation and garbage collection activity.  Since a single lock is used for
+  all allocation-related activity, only one thread can be allocating
+  or collecting at one point. This inherently limits performance
+  of multi-threaded applications on multiprocessors.
+
+On most platforms, the allocator/collector lock is implemented as a spin lock
+with exponential back-off. Longer wait times are implemented by yielding
+and/or sleeping. If a collection is in progress, the pure spinning stage
+is skipped. This has the uncontested advantage that most uniprocessor lock
+acquisitions are very cheap. It has the disadvantage that the application may
+sleep for small periods of time even when there is work to be done. And
+threads may be unnecessarily woken up for short periods. Nonetheless, this
+scheme empirically outperforms native queue-based mutual exclusion
+implementations in most cases, sometimes drastically so.
+
+## Options for enhanced scalability
+
+The collector uses two facilities to enhance collector scalability on
+multiprocessors. They are intended to be used together. (The following refers
+to Makefile.direct again.)
+
+  * Building the collector with `-DPARALLEL_MARK` allows the collector to run
+  the mark phase in parallel in multiple threads, and thus on multiple
+  processors (or processor cores). The mark phase typically consumes the large
+  majority of the collection time. Thus, this largely parallelizes the garbage
+  collector itself, though not the allocation process. Currently the marking
+  is performed by the thread that triggered the collection, together with
+  _N_ - 1 dedicated threads, where _N_ is the number of processors (cores)
+  detected by the collector. The dedicated marker threads are created at
+  initialization time (and optionally recreated in child processes after
+  forking). Another effect of this flag is to switch to a more
+  concurrent implementation of `GC_malloc_many`, so that free lists can be
+  built and memory can be cleared by more than one thread concurrently.
+  * Building the collector with `-DTHREAD_LOCAL_ALLOC` adds support for
+  thread-local allocation. This causes `GC_malloc` (actually `GC_malloc_kind`)
+  and `GC_gcj_malloc` to be redefined to perform thread-local allocation.
+
+Memory returned from thread-local allocators is completely interchangeable
+with that returned by the standard allocators. It may be used by other
+threads. The only difference is that, if the thread allocates enough memory
+of a certain kind, it will build a thread-local free list for objects of that
+kind, and allocate from that. This greatly reduces locking. The thread-local
+free lists are refilled using `GC_malloc_many`.
+
+An important side effect of this flag is to replace the default
+spin-then-sleep lock to be replaced by a spin-then-queue based implementation.
+This _reduces performance_ for the standard allocation functions, though
+it usually improves performance when thread-local allocation is used heavily,
+and, thus, the number of short-duration lock acquisitions is greatly reduced.
+
+## The Parallel Marking Algorithm
+
+We use an algorithm similar to
+[that developed by Endo, Taura, and Yonezawa](http://www.yl.is.s.u-tokyo.ac.jp/gc/)
+at the University of Tokyo. However, the data structures and implementation
+are different, and represent a smaller change to the original collector
+source, probably at the expense of extreme scalability. Some of the
+refinements they suggest, e.g. splitting large objects, were also incorporated
+into out approach.
+
+The global mark stack is transformed into a global work queue. Unlike the
+usual case, it never shrinks during a mark phase. The mark threads remove
+objects from the queue by copying them to a local mark stack and changing the
+global descriptor to zero, indicating that there is no more work to be done
+for this entry. This removal is done with no synchronization. Thus it is
+possible for more than one worker to remove the same entry, resulting in some
+work duplication.
+
+The global work queue grows only if a marker thread decides to return some
+of its local mark stack to the global one. This is done if the global queue
+appears to be running low, or if the local stack is in danger of overflowing.
+It does require synchronization, but should be relatively rare.
+
+The sequential marking code is reused to process local mark stacks. Hence the
+amount of additional code required for parallel marking is minimal.
+
+It should be possible to use incremental/generational collection in the
+presence of the parallel collector by calling `GC_enable_incremental`, but
+the current implementation does not allow interruption of the parallel marker,
+so the latter is mostly avoided if the client sets the collection time limit.
+
+Gcj-style mark descriptors do not currently mix with the combination of local
+allocation and incremental collection. They should work correctly with one or
+the other, but not both.
+
+The number of marker threads is set on startup to the number of available
+processor cores (or to the value of either `GC_MARKERS` or `GC_NPROCS`
+environment variable, if provided). If only a single processor is detected,
+parallel marking is disabled.
+
+Note that setting `GC_NPROCS` to 1 also causes some lock acquisitions inside
+the collector to immediately yield the processor instead of busy waiting
+first. In the case of a multiprocessor and a client with multiple
+simultaneously runnable threads, this may have disastrous performance
+consequences (e.g. a factor of 10 slowdown).
+
+## Performance
+
+We conducted some simple experiments with a version of
+[our GC benchmark](http://www.hboehm.info/gc/gc_bench/) that was slightly
+modified to run multiple concurrent client threads in the same address space.
+Each client thread does the same work as the original benchmark, but they
+share a heap. This benchmark involves very little work outside of memory
+allocation. This was run with an ancient GC (released in 2000) on a dual
+processor Pentium III/500 machine under Linux 2.2.12.
+
+Running with a thread-unsafe collector, the benchmark ran in 9 seconds. With
+the simple thread-safe collector, built with `-DGC_THREADS`, the execution
+time increased to 10.3 seconds, or 23.5 elapsed seconds with two clients. (The
+times for the `malloc`/`free` version with glibc `malloc` are 10.51 (standard
+library, pthreads not linked), 20.90 (one thread, pthreads linked), and 24.55
+seconds, respectively. The benchmark favors a garbage collector, since most
+objects are small.)
+
+The following table gives execution times for the collector built with
+parallel marking and thread-local allocation support
+(`-DGC_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC`). We tested the client
+using either one or two marker threads, and running one or two client threads.
+Note that the client uses thread local allocation exclusively. With
+`-DTHREAD_LOCAL_ALLOC` the collector switches to a locking strategy that
+is better tuned to less frequent lock acquisition. The standard allocation
+primitives thus perform slightly worse than without `-DTHREAD_LOCAL_ALLOC`,
+and should be avoided in time-critical code.
+
+(The results using `pthread_mutex_lock` directly for allocation locking would
+have been worse still, at least for older versions of linuxthreads. With
+`-DTHREAD_LOCAL_ALLOC`, we first repeatedly try to acquire the lock with
+`pthread_mutex_try_lock`, busy-waiting between attempts. After a fixed number
+of attempts, we use `pthread_mutex_lock`.)
+
+These measurements do not use incremental collection, nor was prefetching
+enabled in the marker. We used the C version of the benchmark. All
+measurements are in elapsed seconds on an unloaded machine.
+
+Number of client threads| 1 marker thread (secs.)| 2 marker threads (secs.)
+---|------|-----
+  1| 10.45| 7.85
+  2| 19.95| 12.3
+
+The execution time for the single threaded case is slightly worse than with
+simple locking. However, even the single-threaded benchmark runs faster than
+even the thread-unsafe version if a second processor is available. The
+execution time for two clients with thread local allocation time is only 1.4
+times the sequential execution time for a single thread in a thread-unsafe
+environment, even though it involves twice the client work. That represents
+close to a factor of 2 improvement over the 2 client case with the old
+collector. The old collector clearly still suffered from some contention
+overhead, in spite of the fact that the locking scheme had been fairly well
+tuned.
+
+Full linear speedup (i.e. the same execution time for 1 client on one
+processor as 2 clients on 2 processors) is probably not achievable on this
+kind of hardware even with such a small number of processors, since the memory
+system is a major constraint for the garbage collector, the processors usually
+share a single memory bus, and thus the aggregate memory bandwidth does not
+increase in proportion to the number of processors (cores).
+
+These results are likely to be very sensitive to both hardware and OS issues.
+Preliminary experiments with an older Pentium Pro machine running an older
+kernel were far less encouraging.

+ 182 - 0
blitz.mod/bdwgc/doc/simple_example.md

@@ -0,0 +1,182 @@
+# Using the Garbage Collector: A simple example
+
+The following consists of step-by-step instructions for building and using the
+collector. We'll assume a Linux/gcc platform and a single-threaded
+application. The green text contains information about other platforms
+or scenarios. It can be skipped, especially on first reading.
+
+## Building the collector
+
+If you have not so yet, unpack the collector and enter the newly created
+directory with:
+
+
+    tar xvfz gc-<version>.tar.gz
+    cd gc-<version>
+
+
+You can configure, build, and install the collector in a private directory,
+say /home/xyz/gc, with the following commands:
+
+
+    ./configure --prefix=/home/xyz/gc --disable-threads
+    make
+    make check
+    make install
+
+
+Here the `make check` command is optional, but highly recommended. It runs
+a basic correctness test which usually takes well under a minute.
+
+### Other platforms
+
+On non-Unix, non-Linux platforms, the collector is usually built by copying
+the appropriate makefile (see the platform-specific README in doc/README.xxx
+in the distribution) to the file "Makefile", and then typing `make` (or
+`nmake` or ...). This builds the library in the source tree. You may want
+to move it and the files in the include directory to a more convenient place.
+
+If you use a makefile that does not require running a configure script, you
+should first look at the makefile, and adjust any options that are documented
+there.
+
+If your platform provides a `make` utility, that is generally preferred
+to platform- and compiler- dependent "project" files. (At least that is the
+strong preference of the would-be maintainer of those project files.)
+
+### Threads
+
+If you do not need thread support, configure the collector with:
+
+
+    --disable-threads
+
+
+Alternatively, if your target is a real old-fashioned uniprocessor (no
+"hyperthreading", etc.), you may just want to turn off parallel marking with
+`--disable-parallel-mark`.
+
+### C++
+
+You will need to include the C++ support, which unfortunately tends to be
+among the least portable parts of the collector, since it seems to rely
+on some corner cases of the language. On Linux, it suffices to add
+`--enable-cplusplus` to the configure options.
+
+## Writing the program
+
+You will need to include "gc.h" at the beginning of every file that allocates
+memory through the garbage collector. Call `GC_MALLOC` wherever you would have
+call `malloc`. This initializes memory to zero like `calloc`; there is no need
+to explicitly clear the result.
+
+If you know that an object will not contain pointers to the garbage-collected
+heap, and you don't need it to be initialized, call `GC_MALLOC_ATOMIC`
+instead.
+
+A function `GC_FREE` is provided but need not be called. For very small
+objects, your program will probably perform better if you do not call it, and
+let the collector do its job.
+
+A `GC_REALLOC` function behaves like the C library `realloc`. It allocates
+uninitialized pointer-free memory if the original object was allocated that
+way.
+
+The following program `loop.c` is a trivial example:
+
+
+    #include "gc.h"
+    #include <assert.h>
+    #include <stdio.h>
+
+    int main(void) {
+        int i;
+
+        GC_INIT();
+        for (i = 0; i < 10000000; ++i) {
+            int **p = (int **) GC_MALLOC(sizeof(int *));
+            int *q = (int *) GC_MALLOC_ATOMIC(sizeof(int));
+            assert(*p == 0);
+            *p = (int *) GC_REALLOC(q, 2 * sizeof(int));
+            if (i % 100000 == 0)
+                printf("Heap size = %lu bytes\n",
+                       (unsigned long)GC_get_heap_size());
+        }
+        return 0;
+    }
+
+
+### Interaction with the system malloc
+
+It is usually best not to mix garbage-collected allocation with the system
+`malloc`-`free`. If you do, you need to be careful not to store pointers
+to the garbage-collected heap in memory allocated with the system `malloc`.
+
+### Other Platforms
+
+On some other platforms it is necessary to call `GC_INIT` from the main
+program, which is presumed to be part of the main executable, not a dynamic
+library. This can never hurt, and is thus generally good practice.
+
+### Threads
+
+For a multi-threaded program, some more rules apply:
+
+  * Files that either allocate through the GC _or make thread-related calls_
+  should first define the macro `GC_THREADS`, and then include `gc.h`. On some
+  platforms this will redefine some threads primitives, e.g. to let the
+  collector keep track of thread creation.
+
+### C++
+
+In the case of C++, you need to be especially careful not to store pointers
+to the garbage-collected heap in areas that are not traced by the collector.
+The collector includes some _alternate interfaces_ to make that easier.
+
+### Debugging
+
+Additional debug checks can be performed by defining `GC_DEBUG` before
+including `gc.h`. Additional options are available if the collector is also
+built with `--enable-gc-debug` and all allocations are performed with
+`GC_DEBUG` defined.
+
+### What if I can't rewrite/recompile my program?
+
+You may be able to build the collector with `--enable-redirect-malloc` and set
+the `LD_PRELOAD` environment variable to point to the resulting library, thus
+replacing the standard `malloc` with its garbage-collected counterpart. This
+is rather platform dependent. See the _GC leak detection documentation_ for
+some more details.
+
+## Compiling and linking
+
+The above application `loop.c` test program can be compiled and linked with:
+
+
+    cc -I/home/xyz/gc/include loop.c /home/xyz/gc/lib/libgc.a -o loop
+
+
+The `-I` option directs the compiler to the right include directory. In this
+case, we list the static library directly on the compile line; the dynamic
+library could have been used instead, provided we arranged for the dynamic
+loader to find it, e.g. by setting `LD_LIBRARY_PATH`.
+
+### Threads
+
+On pthread platforms, you will of course also have to link with `-lpthread`,
+and compile with any thread-safety options required by your compiler. On some
+platforms, you may also need to link with `-ldl` or `-lrt`. Looking
+at `tools/threadlibs.c` should give you the appropriate list if a plain
+`-lpthread` does not work.
+
+## Running the executable
+
+The executable can of course be run normally, e.g. by typing:
+
+
+    ./loop
+
+
+The operation of the collector is affected by a number of environment
+variables. For example, setting `GC_PRINT_STATS` produces some GC statistics
+on stdout. See `README.environment` in the distribution for details.

+ 175 - 0
blitz.mod/bdwgc/doc/tree.md

@@ -0,0 +1,175 @@
+# Two-Level Tree Structure for Fast Pointer Lookup
+
+The Boehm-Demers-Weiser conservative Garbage Collector uses a 2-level tree
+data structure to aid in fast pointer identification. This data structure
+is described in a bit more detail here, since
+
+  1. Variations of the data structure are more generally useful.
+  2. It appears to be hard to understand by reading the code.
+  3. Some other collectors appear to use inferior data structures to solve the
+  same problem.
+  4. It is central to fast collector operation.  A candidate pointer
+  is divided into three sections, the _high_, _middle_, and _low_ bits. The
+  exact division between these three groups of bits is dependent on the
+  detailed collector configuration.
+
+The high and middle bits are used to look up an entry in the table described
+here. The resulting table entry consists of either a block descriptor
+(`struct hblkhdr *` or `hdr *`) identifying the layout of objects in the
+block, or an indication that this address range corresponds to the middle of
+a large block, together with a hint for locating the actual block descriptor.
+Such a hint consist of a displacement that can be subtracted from the middle
+bits of the candidate pointer without leaving the object.
+
+In either case, the block descriptor (`struct hblkhdr`) refers to a table
+of object starting addresses (the `hb_map` field). The starting address table
+is indexed by the low bits if the candidate pointer. The resulting entry
+contains a displacement to the beginning of the object, or an indication that
+this cannot be a valid object pointer. (If all interior pointer are
+recognized, pointers into large objects are handled specially,
+as appropriate.)
+
+## The Tree
+
+The rest of this discussion focuses on the two level data structure used
+to map the high and middle bits to the block descriptor.
+
+The high bits are used as an index into the `GC_top_index` (really
+`GC_arrays._top_index`) array. Each entry points to a `bottom_index` data
+structure. This structure in turn consists mostly of an array `index` indexed
+by the middle bits of the candidate pointer. The `index` array contains the
+actual `hdr` pointers.
+
+Thus a pointer lookup consists primarily of a handful of memory references,
+and can be quite fast:
+
+  1. The appropriate `bottom_index` pointer is looked up in `GC_top_index`,
+  based on the high bits of the candidate pointer.
+  2. The appropriate `hdr` pointer is looked up in the `bottom_index`
+  structure, based on the middle bits.
+  3. The block layout map pointer is retrieved from the `hdr` structure. (This
+  memory reference is necessary since we try to share block layout maps.)
+  4. The displacement to the beginning of the object is retrieved from the
+  above map.
+
+In order to conserve space, not all `GC_top_index` entries in fact point
+to distinct `bottom_index` structures. If no address with the corresponding
+high bits is part of the heap, then the entry points to `GC_all_nils`,
+a single `bottom_index` structure consisting only of `NULL` `hdr` pointers.
+
+`Bottom_index` structures contain slightly more information than just `hdr`
+pointers. The `asc_link` field is used to link all `bottom_index` structures
+in ascending order for fast traversal. This list is pointed to be
+`GC_all_bottom_indices`. It is maintained with the aid of `key` field that
+contains the high bits corresponding to the `bottom_index`.
+
+## 64-bit addresses
+
+In the case of 64-bit addresses, this picture is complicated slightly by the
+fact that one of the index structures would have to be huge to cover the
+entire address space with a two level tree. We deal with this by turning
+`GC_top_index` into a chained hash table, instead of a simple array. This adds
+a `hash_link` field to the `bottom_index` structure.
+
+The _hash function_ consists of dropping the high bits. This is cheap
+to compute, and guarantees that there will be no collisions if the heap
+is contiguous and not excessively large.
+
+## A picture
+
+The following is an _ASCII_ diagram of the data structure used by GC_base. This was
+contributed originally by Dave Barrett.
+
+
+         63                  LOG_TOP_SZ[11]  LOG_BOTTOM_SZ[10]   LOG_HBLKSIZE[13]
+        +------------------+----------------+------------------+------------------+
+      p:|                  |   TL_HASH(hi)  |                  |   HBLKDISPL(p)   |
+        +------------------+----------------+------------------+------------------+
+         \-----------------------HBLKPTR(p)-------------------/
+         \------------hi-------------------/
+                           \______ ________/ \________ _______/ \________ _______/
+                                  V                   V                  V
+                                  |                   |                  |
+                GC_top_index[]    |                   |                  |
+      ---      +--------------+   |                   |                  |
+       ^       |              |   |                   |                  |
+       |       |              |   |                   |                  |
+      TOP_SZ   +--------------+<--+                   |                  |
+     (items)+-<|      []      | *                     |                  |
+       |    |  +--------------+  if 0 < bi< HBLKSIZE  |                  |
+       |    |  |              | then large object     |                  |
+       |    |  |              | starts at the bi'th   |                  |
+       v    |  |              | hblk before p.        |             i    |
+      ---   |  +--------------+                       |          (word-  |
+            v                                         |         aligned) |
+        bi= |GET_BI(p){->hash_link}->key==hi          |                  |
+            v                                         |                  |
+            |   (bottom_index)  \ scratch_alloc'd     |                  |
+            |   ( struct  bi )  / by get_index()      |                  |
+      ---   +->+--------------+                       |                  |
+       ^       |              |                       |                  |
+       |       |              |                       |                  |
+    BOTTOM_SZ  |              |   ha=GET_HDR_ADDR(p)  |                  |
+     (items)   +--------------+<----------------------+          +-------+
+       |   +--<|   index[]    |                                  |
+       |   |   +--------------+                      GC_obj_map: v
+       |   |   |              |              from      / +-+-+-----+-+-+-+-+  ---
+       v   |   |              |       GC_add_map_entry <0| | |     | | | | |   ^
+      ---  |   +--------------+                        \ +-+-+-----+-+-+-+-+   |
+           |   |   asc_link   |                          +-+-+-----+-+-+-+-+ MAXOBJGRANULES
+           |   +--------------+                      +-->| | |  j  | | | | |  +1
+           |   |     key      |                      |   +-+-+-----+-+-+-+-+   |
+           |   +--------------+                      |   +-+-+-----+-+-+-+-+   |
+           |   |  hash_link   |                      |   | | |     | | | | |   v
+           |   +--------------+                      |   +-+-+-----+-+-+-+-+  ---
+           |                                         |   |<----MAP_LEN---->|
+           |                                         |   =HBLKSIZE/GRANULE_BYTES
+     HDR(p)| GC_find_header(p)                       |    (1024 on Alpha)
+           |                           \ from        |    (8/16 bits each)
+           |    (hdr) (struct hblkhdr) / alloc_hdr() |
+           +--->+----------------------+             |
+      GET_HDR(p)| word   hb_sz (words) |             |
+                +----------------------+             |
+                | struct hblk *hb_next |             |
+                +----------------------+             |
+                | word hb_descr        |             |
+                +----------------------+             |
+                | char * hb_map        |>------------+
+                +----------------------+
+                | ushort hb_obj_kind   |
+                +----------------------+
+                |   hb_last_reclaimed  |
+       ---      +----------------------+
+        ^       |                      |
+    MARK_BITS_SZ|       hb_marks[]     |  * if hdr is free, hb_sz is the size of
+      (words)   |                      |  a heap chunk (struct hblk) of at least
+        v       |                      |  MININCR*HBLKSIZE bytes (below),
+       ---      +----------------------+  otherwise, size of each object in chunk.
+
+
+Dynamic data structures above are interleaved throughout the heap in blocks
+of size `MININCR * HBLKSIZE` bytes as done by `gc_scratch_alloc` which cannot
+be freed; free lists are used (e.g. `alloc_hdr`). `hblk`'s below are
+collected.
+
+
+                 (struct hblk)
+      ---    +----------------------+ < HBLKSIZE  ---
+       ^     +-----hb_body----------+ (and WORDSZ) ^         ---   ---
+       |     |                      |   aligned    |          ^     ^
+       |     |                      |              |        hb_sz   |
+       |     |                      |              |       (words)  |
+       |     |      Object 0        |              |          |     |
+       |     |                      |            i |(word-    v     |
+       |     + - - - - - - - - - - -+ ---   (bytes)|aligned) ---    |
+       |     |                      |  ^           |          ^     |
+       |     |                      |  j (words)   |          |     |
+     n *     |      Object 1        |  v           v        hb_sz HBLKSIZE/BYTES_PER_WORD
+    HBLKSIZE |                      |---------------          |   (words)
+    (bytes)  |                      |                         v     |
+       |     + - - - - - - - - - - -+                        ---    |
+       |     |                      | !ALL_INTERIOR_POINTERS  ^     |
+       |     |                      | sets j only for       hb_sz   |
+       |     |      Object N        | valid object offsets.   |     |
+       v     |                      | All objects WORDSZ-     v     v
+      ---    +----------------------+ aligned.               ---   ---

+ 45 - 44
blitz.mod/bdwgc/dyn_load.c

@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
  * Copyright (c) 1997 by Silicon Graphics.  All rights reserved.
+ * Copyright (c) 2009-2021 Ivan Maidanski
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
@@ -26,7 +27,7 @@
  * But then not much of anything is safe in the presence of dlclose.
  */
 
-#if !defined(MACOS) && !defined(SN_TARGET_ORBIS) && !defined(SN_TARGET_PSP2) \
+#if !defined(MACOS) && !defined(GC_NO_TYPES) && !defined(SN_TARGET_PSP2) \
     && !defined(_WIN32_WCE) && !defined(__CC_ARM)
 # include <sys/types.h>
 #endif
@@ -149,8 +150,10 @@ STATIC GC_has_static_roots_func GC_has_static_roots = 0;
 #    elif defined(NETBSD) || defined(OPENBSD)
 #      if ELFSIZE == 32
 #        define ElfW(type) Elf32_##type
-#      else
+#      elif ELFSIZE == 64
 #        define ElfW(type) Elf64_##type
+#      else
+#        error Missing ELFSIZE define
 #      endif
 #    else
 #      if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32
@@ -303,10 +306,9 @@ static void sort_heap_sects(struct HeapSect *base, size_t number_of_elements)
     }
 }
 
-STATIC void GC_register_map_entries(char *maps)
+STATIC void GC_register_map_entries(const char *maps)
 {
-    char *prot;
-    char *buf_ptr = maps;
+    const char *prot;
     ptr_t start, end;
     unsigned int maj_dev;
     ptr_t least_ha, greatest_ha;
@@ -319,10 +321,9 @@ STATIC void GC_register_map_entries(char *maps)
                   + GC_our_memory[GC_n_memory-1].hs_bytes;
 
     for (;;) {
-        buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, &prot,
-                                     &maj_dev, 0);
-        if (NULL == buf_ptr)
-            break;
+        maps = GC_parse_map_entry(maps, &start, &end, &prot, &maj_dev, 0);
+        if (NULL == maps) break;
+
         if (prot[1] == 'w') {
             /* This is a writable mapping.  Add it to           */
             /* the root set unless it is already otherwise      */
@@ -397,11 +398,7 @@ STATIC void GC_register_map_entries(char *maps)
 
 GC_INNER void GC_register_dynamic_libraries(void)
 {
-    char *maps = GC_get_maps();
-
-    if (NULL == maps)
-        ABORT("Failed to read /proc for library registration");
-    GC_register_map_entries(maps);
+    GC_register_map_entries(GC_get_maps());
 }
 
 /* We now take care of the main data segment ourselves: */
@@ -545,11 +542,15 @@ STATIC int GC_register_dynlib_callback(struct dl_phdr_info * info,
             if (load_segs[j].start2 != 0) {
               WARN("More than one GNU_RELRO segment per load one\n",0);
             } else {
-              GC_ASSERT((word)end <= (word)load_segs[j].end);
+              GC_ASSERT((word)end <=
+                            (((word)load_segs[j].end + GC_page_size - 1) &
+                             ~(GC_page_size - 1)));
               /* Remove from the existing load segment */
               load_segs[j].end2 = load_segs[j].end;
               load_segs[j].end = start;
               load_segs[j].start2 = end;
+              /* Note that start2 may be greater than end2 because of   */
+              /* p->p_memsz value multiple of page size.                */
             }
             break;
           }
@@ -835,7 +836,7 @@ GC_INNER void GC_register_dynamic_libraries(void)
     }
     if (ioctl(fd, PIOCNMAP, &needed_sz) < 0) {
         ABORT_ARG2("/proc PIOCNMAP ioctl failed",
-                   ": fd = %d, errno = %d", fd, errno);
+                   ": fd= %d, errno= %d", fd, errno);
     }
     if (needed_sz >= current_sz) {
         GC_scratch_recycle_no_gww(addr_map,
@@ -851,7 +852,7 @@ GC_INNER void GC_register_dynamic_libraries(void)
         ABORT_ARG3("/proc PIOCMAP ioctl failed",
                    ": errcode= %d, needed_sz= %d, addr_map= %p",
                    errno, needed_sz, (void *)addr_map);
-    };
+    }
     if (GC_n_heap_sects > 0) {
         heap_end = GC_heap_sects[GC_n_heap_sects-1].hs_start
                         + GC_heap_sects[GC_n_heap_sects-1].hs_bytes;
@@ -913,6 +914,8 @@ GC_INNER void GC_register_dynamic_libraries(void)
     }
     /* Don't keep cached descriptor, for now.  Some kernels don't like us */
     /* to keep a /proc file descriptor around during kill -9.             */
+    /* Otherwise, it should also require FD_CLOEXEC and proper handling   */
+    /* at fork (i.e. close because of the pid change).                    */
         if (close(fd) < 0) ABORT("Couldn't close /proc file");
         fd = -1;
 }
@@ -974,11 +977,12 @@ GC_INNER void GC_register_dynamic_libraries(void)
 # ifdef DEBUG_VIRTUALQUERY
   void GC_dump_meminfo(MEMORY_BASIC_INFORMATION *buf)
   {
-    GC_printf("BaseAddress = 0x%lx, AllocationBase = 0x%lx,"
-              " RegionSize = 0x%lx(%lu)\n", buf -> BaseAddress,
-              buf -> AllocationBase, buf -> RegionSize, buf -> RegionSize);
-    GC_printf("\tAllocationProtect = 0x%lx, State = 0x%lx, Protect = 0x%lx, "
-              "Type = 0x%lx\n", buf -> AllocationProtect, buf -> State,
+    GC_printf("BaseAddress= 0x%lx, AllocationBase= 0x%lx,"
+              " RegionSize= 0x%lx(%lu)\n",
+              buf -> BaseAddress, buf -> AllocationBase,
+              buf -> RegionSize, buf -> RegionSize);
+    GC_printf("\tAllocationProtect= 0x%lx, State= 0x%lx, Protect= 0x%lx, "
+              "Type= 0x%lx\n", buf -> AllocationProtect, buf -> State,
               buf -> Protect, buf -> Type);
   }
 # endif /* DEBUG_VIRTUALQUERY */
@@ -1107,10 +1111,10 @@ GC_INNER void GC_register_dynamic_libraries(void)
 
 #     ifdef DL_VERBOSE
         GC_log_printf("---Module---\n");
-        GC_log_printf("Module ID\t = %16ld\n", moduleinfo.lmi_modid);
-        GC_log_printf("Count of regions = %16d\n", moduleinfo.lmi_nregion);
-        GC_log_printf("flags for module = %16lx\n", moduleinfo.lmi_flags);
-        GC_log_printf("module pathname\t = \"%s\"\n", moduleinfo.lmi_name);
+        GC_log_printf("Module ID: %ld\n", moduleinfo.lmi_modid);
+        GC_log_printf("Count of regions: %d\n", moduleinfo.lmi_nregion);
+        GC_log_printf("Flags for module: %016lx\n", moduleinfo.lmi_flags);
+        GC_log_printf("Module pathname: \"%s\"\n", moduleinfo.lmi_name);
 #     endif
 
       /* For each region in this module */
@@ -1127,14 +1131,12 @@ GC_INNER void GC_register_dynamic_libraries(void)
 
 #         ifdef DL_VERBOSE
             GC_log_printf("--- Region ---\n");
-            GC_log_printf("Region number\t = %16ld\n",
-                          regioninfo.lri_region_no);
-            GC_log_printf("Protection flags = %016x\n", regioninfo.lri_prot);
-            GC_log_printf("Virtual address\t = %16p\n", regioninfo.lri_vaddr);
-            GC_log_printf("Mapped address\t = %16p\n",
-                          regioninfo.lri_mapaddr);
-            GC_log_printf("Region size\t = %16ld\n", regioninfo.lri_size);
-            GC_log_printf("Region name\t = \"%s\"\n", regioninfo.lri_name);
+            GC_log_printf("Region number: %ld\n", regioninfo.lri_region_no);
+            GC_log_printf("Protection flags: %016x\n", regioninfo.lri_prot);
+            GC_log_printf("Virtual address: %p\n", regioninfo.lri_vaddr);
+            GC_log_printf("Mapped address: %p\n", regioninfo.lri_mapaddr);
+            GC_log_printf("Region size: %ld\n", regioninfo.lri_size);
+            GC_log_printf("Region name: \"%s\"\n", regioninfo.lri_name);
 #         endif
 
           /* register region as a garbage collection root */
@@ -1186,15 +1188,14 @@ GC_INNER void GC_register_dynamic_libraries(void)
 
 #     ifdef DL_VERBOSE
         GC_log_printf("---Shared library---\n");
-        GC_log_printf("\tfilename\t= \"%s\"\n", shl_desc->filename);
-        GC_log_printf("\tindex\t\t= %d\n", index);
-        GC_log_printf("\thandle\t\t= %08x\n",
-                      (unsigned long) shl_desc->handle);
-        GC_log_printf("\ttext seg.start\t= %08x\n", shl_desc->tstart);
-        GC_log_printf("\ttext seg.end\t= %08x\n", shl_desc->tend);
-        GC_log_printf("\tdata seg.start\t= %08x\n", shl_desc->dstart);
-        GC_log_printf("\tdata seg.end\t= %08x\n", shl_desc->dend);
-        GC_log_printf("\tref.count\t= %lu\n", shl_desc->ref_count);
+        GC_log_printf("filename= \"%s\"\n", shl_desc->filename);
+        GC_log_printf("index= %d\n", index);
+        GC_log_printf("handle= %08x\n", (unsigned long) shl_desc->handle);
+        GC_log_printf("text seg.start= %08x\n", shl_desc->tstart);
+        GC_log_printf("text seg.end= %08x\n", shl_desc->tend);
+        GC_log_printf("data seg.start= %08x\n", shl_desc->dstart);
+        GC_log_printf("data seg.end= %08x\n", shl_desc->dend);
+        GC_log_printf("ref.count= %lu\n", shl_desc->ref_count);
 #     endif
 
       /* register shared library's data segment as a garbage collection root */
@@ -1207,7 +1208,7 @@ GC_INNER void GC_register_dynamic_libraries(void)
 #endif /* HPUX */
 
 #ifdef AIX
-# pragma alloca
+# include <alloca.h>
 # include <sys/ldr.h>
 # include <sys/errno.h>
   GC_INNER void GC_register_dynamic_libraries(void)

+ 544 - 0
blitz.mod/bdwgc/extra/AmigaOS.c

@@ -0,0 +1,544 @@
+
+
+/******************************************************************
+
+  AmigaOS-specific routines for GC.
+  This file is normally included from os_dep.c
+
+******************************************************************/
+
+
+#if !defined(GC_AMIGA_DEF) && !defined(GC_AMIGA_SB) && !defined(GC_AMIGA_DS) && !defined(GC_AMIGA_AM)
+# include "private/gc_priv.h"
+# include <stdio.h>
+# include <signal.h>
+# define GC_AMIGA_DEF
+# define GC_AMIGA_SB
+# define GC_AMIGA_DS
+# define GC_AMIGA_AM
+#endif
+
+
+#ifdef GC_AMIGA_DEF
+
+# ifndef __GNUC__
+#   include <exec/exec.h>
+# endif
+# include <proto/exec.h>
+# include <proto/dos.h>
+# include <dos/dosextens.h>
+# include <workbench/startup.h>
+
+#endif
+
+
+
+
+#ifdef GC_AMIGA_SB
+
+/******************************************************************
+   Find the base of the stack.
+******************************************************************/
+
+ptr_t GC_get_main_stack_base(void)
+{
+    struct Process *proc = (struct Process*)SysBase->ThisTask;
+
+    /* Reference: Amiga Guru Book Pages: 42,567,574 */
+    if (proc->pr_Task.tc_Node.ln_Type==NT_PROCESS
+        && proc->pr_CLI != NULL) {
+        /* first ULONG is StackSize */
+        /*longPtr = proc->pr_ReturnAddr;
+        size = longPtr[0];*/
+
+        return (char *)proc->pr_ReturnAddr + sizeof(ULONG);
+    } else {
+        return (char *)proc->pr_Task.tc_SPUpper;
+    }
+}
+
+#endif
+
+
+#ifdef GC_AMIGA_DS
+/******************************************************************
+   Register data segments.
+******************************************************************/
+
+   void GC_register_data_segments(void)
+   {
+     struct Process     *proc;
+     struct CommandLineInterface *cli;
+     BPTR myseglist;
+     ULONG *data;
+
+#    ifdef __GNUC__
+        ULONG dataSegSize;
+        GC_bool found_segment = FALSE;
+        extern char __data_size[];
+
+        dataSegSize=__data_size+8;
+        /* Can`t find the Location of __data_size, because
+           it`s possible that is it, inside the segment. */
+
+#     endif
+
+        proc= (struct Process*)SysBase->ThisTask;
+
+        /* Reference: Amiga Guru Book Pages: 538ff,565,573
+                     and XOper.asm */
+        myseglist = proc->pr_SegList;
+        if (proc->pr_Task.tc_Node.ln_Type==NT_PROCESS) {
+          if (proc->pr_CLI != NULL) {
+            /* ProcLoaded       'Loaded as a command: '*/
+            cli = BADDR(proc->pr_CLI);
+            myseglist = cli->cli_Module;
+          }
+        } else {
+          ABORT("Not a Process.");
+        }
+
+        if (myseglist == NULL) {
+            ABORT("Arrrgh.. can't find segments, aborting");
+        }
+
+        /* xoper hunks Shell Process */
+
+        for (data = (ULONG *)BADDR(myseglist); data != NULL;
+             data = (ULONG *)BADDR(data[0])) {
+          if ((ULONG)GC_register_data_segments < (ULONG)(&data[1])
+              || (ULONG)GC_register_data_segments > (ULONG)(&data[1])
+                                                    + data[-1]) {
+#             ifdef __GNUC__
+                if (dataSegSize == data[-1]) {
+                  found_segment = TRUE;
+                }
+#             endif
+              GC_add_roots_inner((char *)&data[1],
+                                 ((char *)&data[1]) + data[-1], FALSE);
+          }
+        } /* for */
+#       ifdef __GNUC__
+           if (!found_segment) {
+             ABORT("Can`t find correct Segments.\nSolution: Use an newer version of ixemul.library");
+           }
+#       endif
+   }
+
+#endif
+
+
+
+#ifdef GC_AMIGA_AM
+
+#ifndef GC_AMIGA_FASTALLOC
+
+void *GC_amiga_allocwrapper(size_t size,void *(*AllocFunction)(size_t size2)){
+        return (*AllocFunction)(size);
+}
+
+void *(*GC_amiga_allocwrapper_do)(size_t size,void *(*AllocFunction)(size_t size2))
+        =GC_amiga_allocwrapper;
+
+#else
+
+
+
+
+void *GC_amiga_allocwrapper_firsttime(size_t size,void *(*AllocFunction)(size_t size2));
+
+void *(*GC_amiga_allocwrapper_do)(size_t size,void *(*AllocFunction)(size_t size2))
+        =GC_amiga_allocwrapper_firsttime;
+
+
+/******************************************************************
+   Amiga-specific routines to obtain memory, and force GC to give
+   back fast-mem whenever possible.
+        These hacks makes gc-programs go many times faster when
+   the Amiga is low on memory, and are therefore strictly necessary.
+
+   -Kjetil S. Matheussen, 2000.
+******************************************************************/
+
+
+
+/* List-header for all allocated memory. */
+
+struct GC_Amiga_AllocedMemoryHeader{
+        ULONG size;
+        struct GC_Amiga_AllocedMemoryHeader *next;
+};
+struct GC_Amiga_AllocedMemoryHeader *GC_AMIGAMEM=(struct GC_Amiga_AllocedMemoryHeader *)(int)~(NULL);
+
+
+
+/* Type of memory. Once in the execution of a program, this might change to MEMF_ANY|MEMF_CLEAR */
+
+ULONG GC_AMIGA_MEMF = MEMF_FAST | MEMF_CLEAR;
+
+
+/* Prevents GC_amiga_get_mem from allocating memory if this one is TRUE. */
+#ifndef GC_AMIGA_ONLYFAST
+BOOL GC_amiga_dontalloc=FALSE;
+#endif
+
+#ifdef GC_AMIGA_PRINTSTATS
+int succ=0,succ2=0;
+int nsucc=0,nsucc2=0;
+int nullretries=0;
+int numcollects=0;
+int chipa=0;
+int allochip=0;
+int allocfast=0;
+int cur0=0;
+int cur1=0;
+int cur10=0;
+int cur50=0;
+int cur150=0;
+int cur151=0;
+int ncur0=0;
+int ncur1=0;
+int ncur10=0;
+int ncur50=0;
+int ncur150=0;
+int ncur151=0;
+#endif
+
+/* Free everything at program-end. */
+
+void GC_amiga_free_all_mem(void){
+        struct GC_Amiga_AllocedMemoryHeader *gc_am=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(GC_AMIGAMEM));
+
+#ifdef GC_AMIGA_PRINTSTATS
+        printf("\n\n"
+                "%d bytes of chip-mem, and %d bytes of fast-mem where allocated from the OS.\n",
+                allochip,allocfast
+        );
+        printf(
+                "%d bytes of chip-mem were returned from the GC_AMIGA_FASTALLOC supported allocating functions.\n",
+                chipa
+        );
+        printf("\n");
+        printf("GC_gcollect was called %d times to avoid returning NULL or start allocating with the MEMF_ANY flag.\n",numcollects);
+        printf("%d of them was a success. (the others had to use allocation from the OS.)\n",nullretries);
+        printf("\n");
+        printf("Succeeded forcing %d gc-allocations (%d bytes) of chip-mem to be fast-mem.\n",succ,succ2);
+        printf("Failed forcing %d gc-allocations (%d bytes) of chip-mem to be fast-mem.\n",nsucc,nsucc2);
+        printf("\n");
+        printf(
+                "Number of retries before succeeding a chip->fast force:\n"
+                "0: %d, 1: %d, 2-9: %d, 10-49: %d, 50-149: %d, >150: %d\n",
+                cur0,cur1,cur10,cur50,cur150,cur151
+        );
+        printf(
+                "Number of retries before giving up a chip->fast force:\n"
+                "0: %d, 1: %d, 2-9: %d, 10-49: %d, 50-149: %d, >150: %d\n",
+                ncur0,ncur1,ncur10,ncur50,ncur150,ncur151
+        );
+#endif
+
+        while(gc_am!=NULL){
+                struct GC_Amiga_AllocedMemoryHeader *temp = gc_am->next;
+                FreeMem(gc_am,gc_am->size);
+                gc_am=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(temp));
+        }
+}
+
+#ifndef GC_AMIGA_ONLYFAST
+
+/* All memory with address lower than this one is chip-mem. */
+
+char *chipmax;
+
+
+/*
+ * Always set to the last size of memory tried to be allocated.
+ * Needed to ensure allocation when the size is bigger than 100000.
+ *
+ */
+size_t latestsize;
+
+#endif
+
+
+#ifdef GC_AMIGA_FASTALLOC
+
+/*
+ * The actual function that is called with the GET_MEM macro.
+ *
+ */
+
+void *GC_amiga_get_mem(size_t size){
+        struct GC_Amiga_AllocedMemoryHeader *gc_am;
+
+#ifndef GC_AMIGA_ONLYFAST
+        if(GC_amiga_dontalloc==TRUE){
+                return NULL;
+        }
+
+        /* We really don't want to use chip-mem, but if we must, then as little as possible. */
+        if(GC_AMIGA_MEMF==(MEMF_ANY|MEMF_CLEAR) && size>100000 && latestsize<50000) return NULL;
+#endif
+
+        gc_am=AllocMem((ULONG)(size + sizeof(struct GC_Amiga_AllocedMemoryHeader)),GC_AMIGA_MEMF);
+        if(gc_am==NULL) return NULL;
+
+        gc_am->next=GC_AMIGAMEM;
+        gc_am->size=size + sizeof(struct GC_Amiga_AllocedMemoryHeader);
+        GC_AMIGAMEM=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(gc_am));
+
+#ifdef GC_AMIGA_PRINTSTATS
+        if((char *)gc_am<chipmax){
+                allochip+=size;
+        }else{
+                allocfast+=size;
+        }
+#endif
+
+        return gc_am+1;
+
+}
+
+#endif
+
+
+#ifndef GC_AMIGA_ONLYFAST
+
+/* Tries very hard to force GC to find fast-mem to return. Done recursively
+ * to hold the rejected memory-pointers reachable from the collector in an
+ * easy way.
+ *
+ */
+#ifdef GC_AMIGA_RETRY
+void *GC_amiga_rec_alloc(size_t size,void *(*AllocFunction)(size_t size2),const int rec){
+        void *ret;
+
+        ret=(*AllocFunction)(size);
+
+#ifdef GC_AMIGA_PRINTSTATS
+        if((char *)ret>chipmax || ret==NULL){
+                if(ret==NULL){
+                        nsucc++;
+                        nsucc2+=size;
+                        if(rec==0) ncur0++;
+                        if(rec==1) ncur1++;
+                        if(rec>1 && rec<10) ncur10++;
+                        if(rec>=10 && rec<50) ncur50++;
+                        if(rec>=50 && rec<150) ncur150++;
+                        if(rec>=150) ncur151++;
+                }else{
+                        succ++;
+                        succ2+=size;
+                        if(rec==0) cur0++;
+                        if(rec==1) cur1++;
+                        if(rec>1 && rec<10) cur10++;
+                        if(rec>=10 && rec<50) cur50++;
+                        if(rec>=50 && rec<150) cur150++;
+                        if(rec>=150) cur151++;
+                }
+        }
+#endif
+
+        if (((char *)ret)<=chipmax && ret!=NULL && (rec<(size>500000?9:size/5000))){
+                ret=GC_amiga_rec_alloc(size,AllocFunction,rec+1);
+        }
+
+        return ret;
+}
+#endif
+
+
+/* The allocating-functions defined inside the Amiga-blocks in gc.h is called
+ * via these functions.
+ */
+
+
+void *GC_amiga_allocwrapper_any(size_t size,void *(*AllocFunction)(size_t size2)){
+        void *ret;
+
+        GC_amiga_dontalloc=TRUE; /* Pretty tough thing to do, but its indeed necessary. */
+        latestsize=size;
+
+        ret=(*AllocFunction)(size);
+
+        if(((char *)ret) <= chipmax){
+                if(ret==NULL){
+                        /* Give GC access to allocate memory. */
+#ifdef GC_AMIGA_GC
+                        if(!GC_dont_gc){
+                                GC_gcollect();
+#ifdef GC_AMIGA_PRINTSTATS
+                                numcollects++;
+#endif
+                                ret=(*AllocFunction)(size);
+                        }
+                        if(ret==NULL)
+#endif
+                        {
+                                GC_amiga_dontalloc=FALSE;
+                                ret=(*AllocFunction)(size);
+                                if(ret==NULL){
+                                        WARN("Out of Memory!  Returning NIL!\n", 0);
+                                }
+                        }
+#ifdef GC_AMIGA_PRINTSTATS
+                        else{
+                                nullretries++;
+                        }
+                        if(ret!=NULL && (char *)ret<=chipmax) chipa+=size;
+#endif
+                }
+#ifdef GC_AMIGA_RETRY
+                else{
+                        void *ret2;
+                        /* We got chip-mem. Better try again and again and again etc., we might get fast-mem sooner or later... */
+                        /* Using gctest to check the effectiveness of doing this, does seldom give a very good result. */
+                        /* However, real programs doesn't normally rapidly allocate and deallocate. */
+                        if(
+                                AllocFunction!=GC_malloc_uncollectable
+#ifdef GC_ATOMIC_UNCOLLECTABLE
+                                && AllocFunction!=GC_malloc_atomic_uncollectable
+#endif
+                        ){
+                                ret2=GC_amiga_rec_alloc(size,AllocFunction,0);
+                        }else{
+                                ret2=(*AllocFunction)(size);
+#ifdef GC_AMIGA_PRINTSTATS
+                                if((char *)ret2<chipmax || ret2==NULL){
+                                        nsucc++;
+                                        nsucc2+=size;
+                                        ncur0++;
+                                }else{
+                                        succ++;
+                                        succ2+=size;
+                                        cur0++;
+                                }
+#endif
+                        }
+                        if(((char *)ret2)>chipmax){
+                                GC_free(ret);
+                                ret=ret2;
+                        }else{
+                                GC_free(ret2);
+                        }
+                }
+#endif
+        }
+
+#   if defined(CPPCHECK)
+      if (GC_amiga_dontalloc) /* variable is actually used by AllocFunction */
+#   endif
+        GC_amiga_dontalloc=FALSE;
+
+        return ret;
+}
+
+
+
+void (*GC_amiga_toany)(void)=NULL;
+
+void GC_amiga_set_toany(void (*func)(void)){
+        GC_amiga_toany=func;
+}
+
+#endif /* !GC_AMIGA_ONLYFAST */
+
+
+void *GC_amiga_allocwrapper_fast(size_t size,void *(*AllocFunction)(size_t size2)){
+        void *ret;
+
+        ret=(*AllocFunction)(size);
+
+        if(ret==NULL){
+                /* Enable chip-mem allocation. */
+#ifdef GC_AMIGA_GC
+                if(!GC_dont_gc){
+                        GC_gcollect();
+#ifdef GC_AMIGA_PRINTSTATS
+                        numcollects++;
+#endif
+                        ret=(*AllocFunction)(size);
+                }
+                if(ret==NULL)
+#endif
+                {
+#ifndef GC_AMIGA_ONLYFAST
+                        GC_AMIGA_MEMF=MEMF_ANY | MEMF_CLEAR;
+                        if(GC_amiga_toany!=NULL) (*GC_amiga_toany)();
+                        GC_amiga_allocwrapper_do=GC_amiga_allocwrapper_any;
+                        return GC_amiga_allocwrapper_any(size,AllocFunction);
+#endif
+                }
+#ifdef GC_AMIGA_PRINTSTATS
+                else{
+                        nullretries++;
+                }
+#endif
+        }
+
+        return ret;
+}
+
+void *GC_amiga_allocwrapper_firsttime(size_t size,void *(*AllocFunction)(size_t size2)){
+        atexit(&GC_amiga_free_all_mem);
+        chipmax=(char *)SysBase->MaxLocMem; /* For people still having SysBase in chip-mem, this might speed up a bit. */
+        GC_amiga_allocwrapper_do=GC_amiga_allocwrapper_fast;
+        return GC_amiga_allocwrapper_fast(size,AllocFunction);
+}
+
+
+#endif /* GC_AMIGA_FASTALLOC */
+
+
+
+/*
+ * The wrapped realloc function.
+ *
+ */
+void *GC_amiga_realloc(void *old_object,size_t new_size_in_bytes){
+#ifndef GC_AMIGA_FASTALLOC
+        return GC_realloc(old_object,new_size_in_bytes);
+#else
+        void *ret;
+        latestsize=new_size_in_bytes;
+        ret=GC_realloc(old_object,new_size_in_bytes);
+        if(ret==NULL && new_size_in_bytes != 0
+           && GC_AMIGA_MEMF==(MEMF_FAST | MEMF_CLEAR)){
+                /* Out of fast-mem. */
+#ifdef GC_AMIGA_GC
+                if(!GC_dont_gc){
+                        GC_gcollect();
+#ifdef GC_AMIGA_PRINTSTATS
+                        numcollects++;
+#endif
+                        ret=GC_realloc(old_object,new_size_in_bytes);
+                }
+                if(ret==NULL)
+#endif
+                {
+#ifndef GC_AMIGA_ONLYFAST
+                        GC_AMIGA_MEMF=MEMF_ANY | MEMF_CLEAR;
+                        if(GC_amiga_toany!=NULL) (*GC_amiga_toany)();
+                        GC_amiga_allocwrapper_do=GC_amiga_allocwrapper_any;
+                        ret=GC_realloc(old_object,new_size_in_bytes);
+#endif
+                }
+#ifdef GC_AMIGA_PRINTSTATS
+                else{
+                        nullretries++;
+                }
+#endif
+        }
+        if(ret==NULL && new_size_in_bytes != 0){
+                WARN("Out of Memory!  Returning NIL!\n", 0);
+        }
+#ifdef GC_AMIGA_PRINTSTATS
+        if(((char *)ret)<chipmax && ret!=NULL){
+                chipa+=new_size_in_bytes;
+        }
+#endif
+        return ret;
+#endif
+}
+
+#endif /* GC_AMIGA_AM */

+ 169 - 0
blitz.mod/bdwgc/extra/MacOS.c

@@ -0,0 +1,169 @@
+/*
+        MacOS.c
+
+        Some routines for the Macintosh OS port of the Hans-J. Boehm, Alan J. Demers
+        garbage collector.
+
+        <Revision History>
+
+        11/22/94  pcb  StripAddress the temporary memory handle for 24-bit mode.
+        11/30/94  pcb  Tracking all memory usage so we can deallocate it all at once.
+        02/10/96  pcb  Added routine to perform a final collection when
+unloading shared library.
+
+        by Patrick C. Beard.
+ */
+/* Boehm, February 15, 1996 2:55 pm PST */
+
+#include <Resources.h>
+#include <Memory.h>
+#include <LowMem.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define GC_BUILD
+#include "gc.h"
+#include "private/gc_priv.h"
+
+/* use 'CODE' resource 0 to get exact location of the beginning of global space. */
+
+typedef struct {
+        unsigned long aboveA5;
+        unsigned long belowA5;
+        unsigned long JTSize;
+        unsigned long JTOffset;
+} *CodeZeroPtr, **CodeZeroHandle;
+
+void* GC_MacGetDataStart(void)
+{
+        CodeZeroHandle code0 = (CodeZeroHandle)GetResource('CODE', 0);
+        if (code0) {
+                long belowA5Size = (**code0).belowA5;
+                ReleaseResource((Handle)code0);
+                return (LMGetCurrentA5() - belowA5Size);
+        }
+        fprintf(stderr, "Couldn't load the jump table.");
+        exit(-1);
+# if !defined(CPPCHECK)
+        return 0; /* to avoid compiler complain about missing return */
+# endif
+}
+
+#ifdef USE_TEMPORARY_MEMORY
+
+/* track the use of temporary memory so it can be freed all at once. */
+
+typedef struct TemporaryMemoryBlock TemporaryMemoryBlock, **TemporaryMemoryHandle;
+
+struct TemporaryMemoryBlock {
+        TemporaryMemoryHandle nextBlock;
+        char data[];
+};
+
+static TemporaryMemoryHandle theTemporaryMemory = NULL;
+
+void GC_MacFreeTemporaryMemory(void);
+
+Ptr GC_MacTemporaryNewPtr(size_t size, Boolean clearMemory)
+{
+#     if !defined(SHARED_LIBRARY_BUILD)
+        static Boolean firstTime = true;
+#     endif
+        OSErr result;
+        TemporaryMemoryHandle tempMemBlock;
+        Ptr tempPtr = nil;
+
+        tempMemBlock = (TemporaryMemoryHandle)TempNewHandle(size + sizeof(TemporaryMemoryBlock), &result);
+        if (tempMemBlock && result == noErr) {
+                HLockHi((Handle)tempMemBlock);
+                tempPtr = (**tempMemBlock).data;
+                if (clearMemory) memset(tempPtr, 0, size);
+                tempPtr = StripAddress(tempPtr);
+
+                /* keep track of the allocated blocks. */
+                (**tempMemBlock).nextBlock = theTemporaryMemory;
+                theTemporaryMemory = tempMemBlock;
+        }
+
+#     if !defined(SHARED_LIBRARY_BUILD)
+        /* install an exit routine to clean up the memory used at the end. */
+        if (firstTime) {
+                atexit(&GC_MacFreeTemporaryMemory);
+                firstTime = false;
+        }
+#     endif
+
+        return tempPtr;
+}
+
+static void perform_final_collection(void)
+{
+  unsigned i;
+  word last_fo_entries = 0;
+
+  /* adjust the stack bottom, because CFM calls us from another stack
+     location. */
+     GC_stackbottom = (ptr_t)&i;
+
+  /* try to collect and finalize everything in sight */
+    for (i = 0; i < 2 || GC_fo_entries < last_fo_entries; i++) {
+        last_fo_entries = GC_fo_entries;
+        GC_gcollect();
+    }
+}
+
+
+void GC_MacFreeTemporaryMemory(void)
+{
+# if defined(SHARED_LIBRARY_BUILD)
+    /* if possible, collect all memory, and invoke all finalizers. */
+      perform_final_collection();
+# endif
+
+    if (theTemporaryMemory != NULL) {
+#     if !defined(SHARED_LIBRARY_BUILD)
+        long totalMemoryUsed = 0;
+#     endif
+        TemporaryMemoryHandle tempMemBlock = theTemporaryMemory;
+        while (tempMemBlock /* != NULL */) {
+                TemporaryMemoryHandle nextBlock = (**tempMemBlock).nextBlock;
+#             if !defined(SHARED_LIBRARY_BUILD)
+                totalMemoryUsed += GetHandleSize((Handle)tempMemBlock);
+#             endif
+                DisposeHandle((Handle)tempMemBlock);
+                tempMemBlock = nextBlock;
+        }
+        theTemporaryMemory = NULL;
+
+#       if !defined(SHARED_LIBRARY_BUILD)
+          if (GC_print_stats) {
+            fprintf(stdout, "[total memory used:  %ld bytes.]\n",
+                    totalMemoryUsed);
+            fprintf(stdout, "[total collections: %lu]\n",
+                    (unsigned long)GC_gc_no);
+          }
+#       endif
+    }
+}
+
+#endif /* USE_TEMPORARY_MEMORY */
+
+#if __option(far_data)
+
+  void* GC_MacGetDataEnd(void)
+  {
+        CodeZeroHandle code0 = (CodeZeroHandle)GetResource('CODE', 0);
+        if (code0) {
+                long aboveA5Size = (**code0).aboveA5;
+                ReleaseResource((Handle)code0);
+                return (LMGetCurrentA5() + aboveA5Size);
+        }
+        fprintf(stderr, "Couldn't load the jump table.");
+        exit(-1);
+#   if !defined(CPPCHECK)
+        return 0;
+#   endif
+  }
+
+#endif /* __option(far_data) */

+ 27 - 0
blitz.mod/bdwgc/extra/Mac_files/MacOS_config.h

@@ -0,0 +1,27 @@
+/*
+        MacOS_config.h
+
+        Configuration flags for Macintosh development systems.
+
+        <Revision History>
+
+        11/16/95  pcb  Updated compilation flags to reflect latest 4.6 Makefile.
+
+        by Patrick C. Beard.
+ */
+/* Boehm, November 17, 1995 12:10 pm PST */
+
+#ifdef __MWERKS__
+/* for CodeWarrior Pro with Metrowerks Standard Library (MSL). */
+/* #define MSL_USE_PRECOMPILED_HEADERS 0 */
+#include <ansi_prefix.mac.h>
+#endif /* __MWERKS__ */
+
+/* these are defined again in gc_priv.h. */
+#undef TRUE
+#undef FALSE
+
+#define ALL_INTERIOR_POINTERS   /* follows interior pointers. */
+/* #define DONT_ADD_BYTE_AT_END */    /* no padding. */
+/* #define SMALL_CONFIG */           /* whether to use a smaller heap. */
+#define USE_TEMPORARY_MEMORY    /* use Macintosh temporary memory. */

+ 9 - 0
blitz.mod/bdwgc/extra/Mac_files/dataend.c

@@ -0,0 +1,9 @@
+/*
+    dataend.c
+
+    A hack to get the extent of global data for the Macintosh.
+
+    by Patrick C. Beard.
+ */
+
+long __dataend;

+ 9 - 0
blitz.mod/bdwgc/extra/Mac_files/datastart.c

@@ -0,0 +1,9 @@
+/*
+    datastart.c
+
+    A hack to get the extent of global data for the Macintosh.
+
+    by Patrick C. Beard.
+ */
+
+long __datastart;

+ 93 - 0
blitz.mod/bdwgc/extra/gc.c

@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
+ * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.
+ * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.
+ * Copyright (c) 2000-2009 by Hewlett-Packard Development Company.
+ * All rights reserved.
+ * Copyright (c) 2009-2018 Ivan Maidanski
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/* This file could be used for the following purposes:          */
+/* - get the complete GC as a single link object file (module); */
+/* - enable more compiler optimizations.                        */
+
+/* Tip: to get the highest level of compiler optimizations, the typical */
+/* compiler options (GCC) to use are:                                   */
+/* -O3 -fno-strict-aliasing -march=native -Wall -fprofile-generate/use  */
+
+/* Warning: GCC for Linux (for C++ clients only): Use -fexceptions both */
+/* for GC and the client otherwise GC_thread_exit_proc() is not         */
+/* guaranteed to be invoked (see the comments in pthread_start.c).      */
+
+#ifndef __cplusplus
+  /* static is desirable here for more efficient linkage.               */
+  /* TODO: Enable this in case of the compilation as C++ code.          */
+# define GC_INNER STATIC
+# define GC_EXTERN GC_INNER
+                /* STATIC is defined in gcconfig.h. */
+#endif
+
+/* Small files go first... */
+#include "../backgraph.c"
+#include "../blacklst.c"
+#include "../checksums.c"
+#include "../gcj_mlc.c"
+#include "../headers.c"
+#include "../new_hblk.c"
+#include "../obj_map.c"
+#include "../ptr_chck.c"
+
+#include "gc/gc_inline.h"
+#include "../allchblk.c"
+#include "../alloc.c"
+#include "../dbg_mlc.c"
+#include "../finalize.c"
+#include "../fnlz_mlc.c"
+#include "../malloc.c"
+#include "../mallocx.c"
+#include "../mark.c"
+#include "../mark_rts.c"
+#include "../reclaim.c"
+#include "../typd_mlc.c"
+
+#include "../misc.c"
+#include "../os_dep.c"
+#include "../thread_local_alloc.c"
+
+/* Most platform-specific files go here... */
+#include "../darwin_stop_world.c"
+#include "../dyn_load.c"
+#include "../gc_dlopen.c"
+#if !defined(PLATFORM_MACH_DEP)
+# include "../mach_dep.c"
+#endif
+#if !defined(PLATFORM_STOP_WORLD)
+# include "../pthread_stop_world.c"
+#endif
+#include "../pthread_support.c"
+#include "../specific.c"
+#include "../win32_threads.c"
+
+#ifndef GC_PTHREAD_START_STANDALONE
+# include "../pthread_start.c"
+#endif
+
+/* Restore pthread calls redirection (if altered in             */
+/* pthread_stop_world.c, pthread_support.c or win32_threads.c). */
+/* This is only useful if directly included from application    */
+/* (instead of linking gc).                                     */
+#ifndef GC_NO_THREAD_REDIRECTS
+# define GC_PTHREAD_REDIRECTS_ONLY
+# include "gc/gc_pthread_redirects.h"
+#endif
+
+/* The files from "extra" folder are not included. */

+ 392 - 0
blitz.mod/bdwgc/extra/msvc_dbg.c

@@ -0,0 +1,392 @@
+/*
+  Copyright (c) 2004-2005 Andrei Polushin
+
+  Permission is hereby granted, free of charge,  to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction,  including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  THE SOFTWARE.
+*/
+
+#if !defined(_M_ARM) && !defined(_M_ARM64) \
+    && !defined(_M_X64) && defined(_MSC_VER)
+
+/* TODO: arm[64], x86_64 currently miss some machine-dependent code below.  */
+/* See also GC_HAVE_BUILTIN_BACKTRACE in gc_config_macros.h.                */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define GC_BUILD
+#include "gc.h"
+
+#ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN 1
+#endif
+#define NOSERVICE
+#include <windows.h>
+
+#pragma pack(push, 8)
+#include <imagehlp.h>
+#pragma pack(pop)
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/* Compatibility with <execinfo.h> */
+int backtrace(void* addresses[], int count);
+char** backtrace_symbols(void* const addresses[], int count);
+
+#ifdef __cplusplus
+  } /* extern "C" */
+#endif
+
+#pragma comment(lib, "dbghelp.lib")
+#pragma optimize("gy", off)
+
+/* Disable a warning that /GS can not protect parameters and local      */
+/* variables from local buffer overrun because optimizations are off.   */
+#pragma warning(disable:4748)
+
+typedef GC_word word;
+#define GC_ULONG_PTR word
+
+#ifdef _WIN64
+        typedef GC_ULONG_PTR ULONG_ADDR;
+#else
+        typedef ULONG        ULONG_ADDR;
+#endif
+
+#ifndef MAX_SYM_NAME
+#define MAX_SYM_NAME 2000
+#endif
+
+static HANDLE GetSymHandle(void)
+{
+  static HANDLE symHandle = NULL;
+  if (!symHandle) {
+    BOOL bRet = SymInitialize(symHandle = GetCurrentProcess(), NULL, FALSE);
+    if (bRet) {
+      DWORD dwOptions = SymGetOptions();
+      dwOptions &= ~SYMOPT_UNDNAME;
+      dwOptions |= SYMOPT_LOAD_LINES;
+      SymSetOptions(dwOptions);
+    }
+  }
+  return symHandle;
+}
+
+static void* CALLBACK FunctionTableAccess(HANDLE hProcess,
+                                          ULONG_ADDR dwAddrBase)
+{
+  return SymFunctionTableAccess(hProcess, dwAddrBase);
+}
+
+static ULONG_ADDR CALLBACK GetModuleBase(HANDLE hProcess, ULONG_ADDR dwAddress)
+{
+  MEMORY_BASIC_INFORMATION memoryInfo;
+  ULONG_ADDR dwAddrBase = SymGetModuleBase(hProcess, dwAddress);
+  if (dwAddrBase != 0) {
+    return dwAddrBase;
+  }
+  if (VirtualQueryEx(hProcess, (void*)(GC_ULONG_PTR)dwAddress, &memoryInfo,
+                     sizeof(memoryInfo))) {
+    char filePath[_MAX_PATH];
+    char curDir[_MAX_PATH];
+    char exePath[_MAX_PATH];
+    DWORD size = GetModuleFileNameA((HINSTANCE)memoryInfo.AllocationBase,
+                                    filePath, sizeof(filePath));
+
+    /* Save and restore current directory around SymLoadModule, see KB  */
+    /* article Q189780.                                                 */
+    GetCurrentDirectoryA(sizeof(curDir), curDir);
+    GetModuleFileNameA(NULL, exePath, sizeof(exePath));
+#if _MSC_VER > 1200
+    strcat_s(exePath, sizeof(exePath), "\\..");
+#else /* VC6 or earlier */
+    strcat(exePath, "\\..");
+#endif
+    SetCurrentDirectoryA(exePath);
+#ifdef _DEBUG
+    GetCurrentDirectoryA(sizeof(exePath), exePath);
+#endif
+    SymLoadModule(hProcess, NULL, size ? filePath : NULL, NULL,
+                  (ULONG_ADDR)(GC_ULONG_PTR)memoryInfo.AllocationBase, 0);
+    SetCurrentDirectoryA(curDir);
+  }
+  return (ULONG_ADDR)(GC_ULONG_PTR)memoryInfo.AllocationBase;
+}
+
+static ULONG_ADDR CheckAddress(void* address)
+{
+  ULONG_ADDR dwAddress = (ULONG_ADDR)(GC_ULONG_PTR)address;
+  GetModuleBase(GetSymHandle(), dwAddress);
+  return dwAddress;
+}
+
+static size_t GetStackFramesFromContext(HANDLE hProcess, HANDLE hThread,
+                                        CONTEXT* context, size_t skip,
+                                        void* frames[], size_t maxFrames);
+
+static size_t GetStackFrames(size_t skip, void* frames[], size_t maxFrames)
+{
+  HANDLE hProcess = GetSymHandle();
+  HANDLE hThread = GetCurrentThread();
+  CONTEXT context;
+  context.ContextFlags = CONTEXT_FULL;
+  if (!GetThreadContext(hThread, &context)) {
+    return 0;
+  }
+  /* GetThreadContext might return invalid context for the current thread. */
+#if defined(_M_IX86)
+    __asm mov context.Ebp, ebp
+#endif
+  return GetStackFramesFromContext(hProcess, hThread, &context, skip + 1,
+                                   frames, maxFrames);
+}
+
+static size_t GetStackFramesFromContext(HANDLE hProcess, HANDLE hThread,
+                                        CONTEXT* context, size_t skip,
+                                        void* frames[], size_t maxFrames)
+{
+  size_t frameIndex;
+  DWORD machineType;
+  STACKFRAME stackFrame = { 0 };
+  stackFrame.AddrPC.Mode      = AddrModeFlat;
+#if defined(_M_IX86)
+  machineType                 = IMAGE_FILE_MACHINE_I386;
+  stackFrame.AddrPC.Offset    = context->Eip;
+  stackFrame.AddrStack.Mode   = AddrModeFlat;
+  stackFrame.AddrStack.Offset = context->Esp;
+  stackFrame.AddrFrame.Mode   = AddrModeFlat;
+  stackFrame.AddrFrame.Offset = context->Ebp;
+#elif defined(_M_MRX000)
+  machineType                 = IMAGE_FILE_MACHINE_R4000;
+  stackFrame.AddrPC.Offset    = context->Fir;
+#elif defined(_M_ALPHA)
+  machineType                 = IMAGE_FILE_MACHINE_ALPHA;
+  stackFrame.AddrPC.Offset    = (unsigned long)context->Fir;
+#elif defined(_M_PPC)
+  machineType                 = IMAGE_FILE_MACHINE_POWERPC;
+  stackFrame.AddrPC.Offset    = context->Iar;
+#elif defined(_M_IA64)
+  machineType                 = IMAGE_FILE_MACHINE_IA64;
+  stackFrame.AddrPC.Offset    = context->StIIP;
+#elif defined(_M_ALPHA64)
+  machineType                 = IMAGE_FILE_MACHINE_ALPHA64;
+  stackFrame.AddrPC.Offset    = context->Fir;
+#elif !defined(CPPCHECK)
+# error Unknown CPU
+#endif
+  for (frameIndex = 0; frameIndex < maxFrames; ) {
+    BOOL bRet = StackWalk(machineType, hProcess, hThread, &stackFrame,
+                    &context, NULL, FunctionTableAccess, GetModuleBase, NULL);
+    if (!bRet) {
+      break;
+    }
+    if (skip) {
+      skip--;
+    } else {
+      frames[frameIndex++] = (void*)(GC_ULONG_PTR)stackFrame.AddrPC.Offset;
+    }
+  }
+  return frameIndex;
+}
+
+static size_t GetModuleNameFromAddress(void* address, char* moduleName,
+                                       size_t size)
+{
+  const char* sourceName;
+  IMAGEHLP_MODULE moduleInfo = { sizeof(moduleInfo) };
+
+  if (size) *moduleName = 0;
+  if (!SymGetModuleInfo(GetSymHandle(), CheckAddress(address), &moduleInfo)) {
+    return 0;
+  }
+  sourceName = strrchr(moduleInfo.ImageName, '\\');
+  if (sourceName) {
+    sourceName++;
+  } else {
+    sourceName = moduleInfo.ImageName;
+  }
+  if (size) {
+    strncpy(moduleName, sourceName, size)[size - 1] = 0;
+  }
+  return strlen(sourceName);
+}
+
+union sym_namebuf_u {
+  IMAGEHLP_SYMBOL sym;
+  char symNameBuffer[sizeof(IMAGEHLP_SYMBOL) + MAX_SYM_NAME];
+};
+
+static size_t GetSymbolNameFromAddress(void* address, char* symbolName,
+                                       size_t size, size_t* offsetBytes)
+{
+  if (size) *symbolName = 0;
+  if (offsetBytes) *offsetBytes = 0;
+  __try {
+    ULONG_ADDR dwOffset = 0;
+    union sym_namebuf_u u;
+
+    u.sym.SizeOfStruct  = sizeof(u.sym);
+    u.sym.MaxNameLength = sizeof(u.symNameBuffer) - sizeof(u.sym);
+
+    if (!SymGetSymFromAddr(GetSymHandle(), CheckAddress(address), &dwOffset,
+                           &u.sym)) {
+      return 0;
+    } else {
+      const char* sourceName = u.sym.Name;
+      char undName[1024];
+      if (UnDecorateSymbolName(u.sym.Name, undName, sizeof(undName),
+                UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ACCESS_SPECIFIERS)) {
+        sourceName = undName;
+      } else if (SymUnDName(&u.sym, undName, sizeof(undName))) {
+        sourceName = undName;
+      }
+      if (offsetBytes) {
+        *offsetBytes = dwOffset;
+      }
+      if (size) {
+        strncpy(symbolName, sourceName, size)[size - 1] = 0;
+      }
+      return strlen(sourceName);
+    }
+  } __except (EXCEPTION_EXECUTE_HANDLER) {
+    SetLastError(GetExceptionCode());
+  }
+  return 0;
+}
+
+static size_t GetFileLineFromAddress(void* address, char* fileName,
+                                     size_t size, size_t* lineNumber,
+                                     size_t* offsetBytes)
+{
+  char* sourceName;
+  IMAGEHLP_LINE line = { sizeof (line) };
+  GC_ULONG_PTR dwOffset = 0;
+
+  if (size) *fileName = 0;
+  if (lineNumber) *lineNumber = 0;
+  if (offsetBytes) *offsetBytes = 0;
+  if (!SymGetLineFromAddr(GetSymHandle(), CheckAddress(address), &dwOffset,
+                          &line)) {
+    return 0;
+  }
+  if (lineNumber) {
+    *lineNumber = line.LineNumber;
+  }
+  if (offsetBytes) {
+    *offsetBytes = dwOffset;
+  }
+  sourceName = line.FileName;
+  /* TODO: resolve relative filenames, found in "source directories"    */
+  /* registered with MSVC IDE.                                          */
+  if (size) {
+    strncpy(fileName, sourceName, size)[size - 1] = 0;
+  }
+  return strlen(sourceName);
+}
+
+#define GC_SNPRINTF _snprintf
+
+static size_t GetDescriptionFromAddress(void* address, const char* format,
+                                        char* buffer, size_t size)
+{
+  char* const begin = buffer;
+  char* const end = buffer + size;
+  size_t line_number = 0;
+
+  (void)format;
+  if (size) {
+    *buffer = 0;
+  }
+  buffer += GetFileLineFromAddress(address, buffer, size, &line_number, NULL);
+  size = (GC_ULONG_PTR)end < (GC_ULONG_PTR)buffer ? 0 : end - buffer;
+
+  if (line_number) {
+    char str[20];
+
+    (void)GC_SNPRINTF(str, sizeof(str), "(%d) : ", (int)line_number);
+    str[sizeof(str) - 1] = '\0';
+    if (size) {
+      strncpy(buffer, str, size)[size - 1] = 0;
+    }
+    buffer += strlen(str);
+    size = (GC_ULONG_PTR)end < (GC_ULONG_PTR)buffer ? 0 : end - buffer;
+  }
+
+  if (size) {
+    strncpy(buffer, "at ", size)[size - 1] = 0;
+  }
+  buffer += sizeof("at ") - 1;
+  size = (GC_ULONG_PTR)end < (GC_ULONG_PTR)buffer ? 0 : end - buffer;
+
+  buffer += GetSymbolNameFromAddress(address, buffer, size, NULL);
+  size = (GC_ULONG_PTR)end < (GC_ULONG_PTR)buffer ? 0 : end - buffer;
+
+  if (size) {
+    strncpy(buffer, " in ", size)[size - 1] = 0;
+  }
+  buffer += sizeof(" in ") - 1;
+  size = (GC_ULONG_PTR)end < (GC_ULONG_PTR)buffer ? 0 : end - buffer;
+
+  buffer += GetModuleNameFromAddress(address, buffer, size);
+  return buffer - begin;
+}
+
+static size_t GetDescriptionFromStack(void* const frames[], size_t count,
+                                      const char* format, char* description[],
+                                      size_t size)
+{
+  const GC_ULONG_PTR begin = (GC_ULONG_PTR)description;
+  const GC_ULONG_PTR end = begin + size;
+  GC_ULONG_PTR buffer = begin + (count + 1) * sizeof(char*);
+  size_t i;
+
+  for (i = 0; i < count; ++i) {
+    if (description)
+      description[i] = (char*)buffer;
+    buffer += 1 + GetDescriptionFromAddress(frames[i], format, (char*)buffer,
+                                            end < buffer ? 0 : end - buffer);
+  }
+  if (description)
+    description[count] = NULL;
+  return buffer - begin;
+}
+
+/* Compatibility with <execinfo.h> */
+
+int backtrace(void* addresses[], int count)
+{
+  return GetStackFrames(1, addresses, count);
+}
+
+char** backtrace_symbols(void* const addresses[], int count)
+{
+  size_t size = GetDescriptionFromStack(addresses, count, NULL, NULL, 0);
+  char** symbols = (char**)malloc(size);
+  if (symbols != NULL)
+    GetDescriptionFromStack(addresses, count, NULL, symbols, size);
+  return symbols;
+}
+
+#else
+
+  extern int GC_quiet;
+        /* ANSI C does not allow translation units to be empty. */
+
+#endif

+ 181 - 0
blitz.mod/bdwgc/extra/pcr_interface.c

@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+# include "private/gc_priv.h"
+
+# ifdef PCR
+/*
+ * We wrap all of the allocator functions to avoid questions of
+ * compatibility between the prototyped and nonprototyped versions of the f
+ */
+# include "config/PCR_StdTypes.h"
+# include "mm/PCR_MM.h"
+# include <errno.h>
+
+# define MY_MAGIC 17L
+# define MY_DEBUGMAGIC 42L
+
+void * GC_AllocProc(size_t size, PCR_Bool ptrFree, PCR_Bool clear )
+{
+    if (ptrFree) {
+        void * result = (void *)GC_malloc_atomic(size);
+        if (clear && result != 0) BZERO(result, size);
+        return(result);
+    } else {
+        return((void *)GC_malloc(size));
+    }
+}
+
+void * GC_DebugAllocProc(size_t size, PCR_Bool ptrFree, PCR_Bool clear )
+{
+    if (ptrFree) {
+        void * result = (void *)GC_debug_malloc_atomic(size, __FILE__,
+                                                             __LINE__);
+        if (clear && result != 0) BZERO(result, size);
+        return(result);
+    } else {
+        return((void *)GC_debug_malloc(size, __FILE__, __LINE__));
+    }
+}
+
+# define GC_ReallocProc GC_realloc
+void * GC_DebugReallocProc(void * old_object, size_t new_size_in_bytes)
+{
+    return(GC_debug_realloc(old_object, new_size_in_bytes, __FILE__, __LINE__));
+}
+
+# define GC_FreeProc GC_free
+# define GC_DebugFreeProc GC_debug_free
+
+typedef struct {
+  PCR_ERes (*ed_proc)(void *p, size_t size, PCR_Any data);
+  GC_bool ed_pointerfree;
+  PCR_ERes ed_fail_code;
+  PCR_Any ed_client_data;
+} enumerate_data;
+
+void GC_enumerate_block(struct hblk *h, enumerate_data * ed)
+{
+    hdr * hhdr;
+    size_t sz;
+    ptr_t p;
+    ptr_t lim;
+    word descr;
+
+# if !defined(CPPCHECK)
+#   error This code was updated without testing.
+#   error and its precursor was clearly broken.
+# endif
+    hhdr = HDR(h);
+    descr = hhdr -> hb_descr;
+    sz = (size_t)hhdr->hb_sz;
+    if (descr != 0 && ed -> ed_pointerfree
+        || descr == 0 && !(ed -> ed_pointerfree)) return;
+    lim = (ptr_t)(h+1) - sz;
+    p = (ptr_t)h;
+    do {
+        if (PCR_ERes_IsErr(ed -> ed_fail_code)) return;
+        ed -> ed_fail_code =
+            (*(ed -> ed_proc))(p, sz, ed -> ed_client_data);
+        p+= sz;
+    } while ((word)p <= (word)lim);
+}
+
+struct PCR_MM_ProcsRep * GC_old_allocator = 0;
+
+PCR_ERes GC_EnumerateProc(
+    PCR_Bool ptrFree,
+    PCR_ERes (*proc)(void *p, size_t size, PCR_Any data),
+    PCR_Any data
+)
+{
+    enumerate_data ed;
+
+    ed.ed_proc = proc;
+    ed.ed_pointerfree = ptrFree;
+    ed.ed_fail_code = PCR_ERes_okay;
+    ed.ed_client_data = data;
+    GC_apply_to_all_blocks(GC_enumerate_block, &ed);
+    if (ed.ed_fail_code != PCR_ERes_okay) {
+        return(ed.ed_fail_code);
+    } else {
+        /* Also enumerate objects allocated by my predecessors */
+        return((*(GC_old_allocator->mmp_enumerate))(ptrFree, proc, data));
+    }
+}
+
+void GC_DummyFreeProc(void *p) {}
+
+void GC_DummyShutdownProc(void) {}
+
+struct PCR_MM_ProcsRep GC_Rep = {
+        MY_MAGIC,
+        GC_AllocProc,
+        GC_ReallocProc,
+        GC_DummyFreeProc,       /* mmp_free */
+        GC_FreeProc,            /* mmp_unsafeFree */
+        GC_EnumerateProc,
+        GC_DummyShutdownProc    /* mmp_shutdown */
+};
+
+struct PCR_MM_ProcsRep GC_DebugRep = {
+        MY_DEBUGMAGIC,
+        GC_DebugAllocProc,
+        GC_DebugReallocProc,
+        GC_DummyFreeProc,       /* mmp_free */
+        GC_DebugFreeProc,               /* mmp_unsafeFree */
+        GC_EnumerateProc,
+        GC_DummyShutdownProc    /* mmp_shutdown */
+};
+
+GC_bool GC_use_debug = 0;
+
+void GC_pcr_install()
+{
+    PCR_MM_Install((GC_use_debug? &GC_DebugRep : &GC_Rep), &GC_old_allocator);
+}
+
+PCR_ERes
+PCR_GC_Setup(void)
+{
+    return PCR_ERes_okay;
+}
+
+extern GC_bool GC_quiet;
+
+PCR_ERes
+PCR_GC_Run(void)
+{
+
+    if( !PCR_Base_TestPCRArg("-nogc") ) {
+        GC_quiet = ( PCR_Base_TestPCRArg("-gctrace") ? 0 : 1 );
+        GC_use_debug = (GC_bool)PCR_Base_TestPCRArg("-debug_alloc");
+        GC_init();
+        if( !PCR_Base_TestPCRArg("-nogc_incremental") ) {
+            /*
+             * awful hack to test whether VD is implemented ...
+             */
+            if( PCR_VD_Start( 0, NIL, 0) != PCR_ERes_FromErr(ENOSYS) ) {
+                GC_enable_incremental();
+            }
+        }
+    }
+    return PCR_ERes_okay;
+}
+
+void GC_push_thread_structures(void)
+{
+    /* PCR doesn't work unless static roots are pushed.  Can't get here. */
+    ABORT("In GC_push_thread_structures()");
+}
+
+# endif

+ 39 - 0
blitz.mod/bdwgc/extra/real_malloc.c

@@ -0,0 +1,39 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+# ifdef HAVE_CONFIG_H
+#   include "config.h"
+# endif
+
+# ifdef PCR
+/*
+ * This definition should go in its own file that includes no other
+ * header files.  Otherwise, we risk not getting the underlying system
+ * malloc.
+ */
+# define PCR_NO_RENAME
+# include <stdlib.h>
+
+void * real_malloc(size_t size)
+{
+    return(malloc(size));
+}
+
+# else
+
+extern int GC_quiet;
+        /* ANSI C doesn't allow translation units to be empty.  */
+        /* So we guarantee this one is nonempty.                */
+
+#endif /* PCR */

+ 52 - 0
blitz.mod/bdwgc/extra/symbian.cpp

@@ -0,0 +1,52 @@
+
+#include <e32cmn.h>
+#include <e32std.h>
+#include <f32file.h>
+#include <aknutils.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern "C" {
+
+int GC_get_main_symbian_stack_base()
+{
+    TThreadStackInfo aInfo;
+    TInt err = RThread().StackInfo(aInfo);
+    if ( !err )
+        {
+        return aInfo.iBase;
+        }
+    else
+        {
+        return 0;
+        }
+}
+
+char* GC_get_private_path_and_zero_file()
+{
+    // always on c: drive
+    RFs fs;
+    fs.Connect();
+    fs.CreatePrivatePath( EDriveC );
+    TFileName path;
+    fs.PrivatePath( path );
+    fs.Close();
+    _LIT( KCDrive, "c:" );
+    path.Insert( 0, KCDrive );
+
+
+    //convert to char*, assume ascii
+    TBuf8<KMaxFileName> path8;
+    path8.Copy( path );
+    _LIT8( KZero8, "zero" );
+    path8.Append( KZero8 );
+
+    size_t size = path8.Length() + 1;
+    char* copyChar = (char*) malloc( size );
+    if (copyChar)
+        memcpy( copyChar, path8.PtrZ(), size );
+
+    return copyChar; // ownership passed
+}
+
+} /* extern "C" */

+ 10 - 0
blitz.mod/bdwgc/extra/symbian/global_end.cpp

@@ -0,0 +1,10 @@
+// Symbian-specific file.
+
+// INCLUDE FILES
+#include "private/gcconfig.h"
+
+extern "C" {
+
+int winscw_data_end;
+
+} /* extern "C" */

+ 10 - 0
blitz.mod/bdwgc/extra/symbian/global_start.cpp

@@ -0,0 +1,10 @@
+// Symbian-specific file.
+
+// INCLUDE FILES
+#include "private/gcconfig.h"
+
+extern "C" {
+
+int winscw_data_start;
+
+} /* extern "C" */

+ 28 - 0
blitz.mod/bdwgc/extra/symbian/init_global_static_roots.cpp

@@ -0,0 +1,28 @@
+// Symbian-specific file.
+
+// INCLUDE FILES
+#include <e32def.h>
+
+#include "private/gcconfig.h"
+#include "gc.h"
+
+extern "C" {
+
+void GC_init_global_static_roots()
+{
+    ptr_t dataStart = NULL;
+    ptr_t dataEnd = NULL;
+#   if defined (__WINS__)
+        extern int winscw_data_start, winscw_data_end;
+        dataStart = ((ptr_t)&winscw_data_start);
+        dataEnd   = ((ptr_t)&winscw_data_end);
+#   else
+        extern int Image$$RW$$Limit[], Image$$RW$$Base[];
+        dataStart = ((ptr_t)Image$$RW$$Base);
+        dataEnd   = ((ptr_t)Image$$RW$$Limit);
+#   endif
+
+    GC_add_roots(dataStart, dataEnd);
+}
+
+} /* extern "C" */

+ 6 - 21
blitz.mod/bdwgc/finalize.c

@@ -2,7 +2,7 @@
  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
  * Copyright (c) 1991-1996 by Xerox Corporation.  All rights reserved.
  * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.
- * Copyright (C) 2007 Free Software Foundation, Inc
+ * Copyright (c) 2007 Free Software Foundation, Inc.
  * Copyright (c) 2008-2020 Ivan Maidanski
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
@@ -18,7 +18,7 @@
 #include "private/gc_pmark.h"
 
 #ifndef GC_NO_FINALIZATION
-# include "javaxfc.h" /* to get GC_finalize_all() as extern "C" */
+# include "gc/javaxfc.h" /* to get GC_finalize_all() as extern "C" */
 
 /* Type of mark procedure used for marking from finalizable object.     */
 /* This procedure normally does not mark the object, only its           */
@@ -600,29 +600,14 @@ GC_API GC_await_finalize_proc GC_CALL GC_get_await_finalize_proc(void)
 
 /* Possible finalization_marker procedures.  Note that mark stack       */
 /* overflow is handled by the caller, and is not a disaster.            */
+#if defined(_MSC_VER) && defined(I386)
+  GC_ATTR_NOINLINE
+  /* Otherwise some optimizer bug is tickled in VC for X86 (v19, at least). */
+#endif
 STATIC void GC_normal_finalize_mark_proc(ptr_t p)
 {
-# if defined(_MSC_VER) && defined(I386)
-    hdr * hhdr = HDR(p);
-    /* This is a manually inlined variant of GC_push_obj().  Otherwise  */
-    /* some optimizer bug is tickled in VC for X86 (v19, at least).     */
-#   define mark_stack_top GC_mark_stack_top
-    mse * mark_stack_limit = GC_mark_stack + GC_mark_stack_size;
-    word descr = hhdr -> hb_descr;
-
-    if (descr != 0) {
-      mark_stack_top++;
-      if ((word)mark_stack_top >= (word)mark_stack_limit) {
-        mark_stack_top = GC_signal_mark_stack_overflow(mark_stack_top);
-      }
-      mark_stack_top -> mse_start = p;
-      mark_stack_top -> mse_descr.w = descr;
-    }
-#   undef mark_stack_top
-# else
     GC_mark_stack_top = GC_push_obj(p, HDR(p), GC_mark_stack_top,
                                     GC_mark_stack + GC_mark_stack_size);
-# endif
 }
 
 /* This only pays very partial attention to the mark descriptor.        */

+ 2 - 2
blitz.mod/bdwgc/fnlz_mlc.c

@@ -16,8 +16,8 @@
 
 #ifdef ENABLE_DISCLAIM
 
-#include "gc_disclaim.h"
-#include "gc_inline.h" /* for GC_malloc_kind */
+#include "gc/gc_disclaim.h"
+#include "gc/gc_inline.h" /* for GC_malloc_kind */
 #include "private/dbg_mlc.h" /* for oh type */
 
 #if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)

+ 155 - 0
blitz.mod/bdwgc/gc.man

@@ -0,0 +1,155 @@
+.TH BDWGC 3 "26 Mar 2019"
+.SH NAME
+GC_malloc, GC_malloc_atomic, GC_free, GC_realloc, GC_enable_incremental,
+GC_register_finalizer, GC_malloc_ignore_off_page,
+GC_malloc_atomic_ignore_off_page, GC_set_warn_proc \- Garbage collecting
+malloc replacement
+.SH SYNOPSIS
+#include <gc.h>
+.br
+void * GC_malloc(size_t size);
+.br
+void * GC_malloc_atomic(size_t size);
+.br
+void GC_free(void *ptr);
+.br
+void * GC_realloc(void *ptr, size_t size);
+.br
+void GC_enable_incremental(void);
+.br
+void * GC_malloc_ignore_off_page(size_t size);
+.br
+void * GC_malloc_atomic_ignore_off_page(size_t size);
+.br
+void GC_set_warn_proc(void (*proc)(char *, GC_word));
+.br
+.sp
+cc ... -lgc
+.LP
+.SH DESCRIPTION
+.I GC_malloc
+and
+.I GC_free
+are plug-in replacements for standard malloc and free.  However,
+.I
+GC_malloc
+will attempt to reclaim inaccessible space automatically by invoking
+a conservative garbage collector at appropriate points.  The collector
+traverses all data structures accessible by following pointers from the
+machines registers, stack(s), data, and bss segments.  Inaccessible structures
+will be reclaimed.  A machine word is considered to be a valid pointer if
+it is an address inside an object allocated by
+.I
+GC_malloc
+or friends.
+.LP
+In most cases it is preferable to call the macros GC_MALLOC, GC_FREE, etc.
+instead of calling GC_malloc and friends directly.  This allows debugging
+versions of the routines to be substituted by defining GC_DEBUG before
+including gc.h.
+.LP
+See the documentation in the include files gc_cpp.h and gc_allocator.h,
+as well as the gcinterface.md file in the distribution,
+for an alternate, C++ specific interface to the garbage collector.
+Note that C++ programs generally
+need to be careful to ensure that all allocated memory (whether via new,
+malloc, or STL allocators) that may point to garbage collected memory
+is either itself garbage collected, or at least traced by the collector.
+.LP
+Unlike the standard implementations of malloc,
+.I
+GC_malloc
+clears the newly allocated storage.
+.I
+GC_malloc_atomic
+does not.  Furthermore, it informs the collector that the resulting object
+will never contain any pointers, and should therefore not be scanned by the
+collector.
+.LP
+.I
+GC_free
+can be used to deallocate objects, but its use is optional, and generally
+discouraged.
+.I
+GC_realloc
+has the standard realloc semantics.  It preserves pointer-free-ness.
+.I
+GC_register_finalizer
+allows for registration of functions that are invoked when an object becomes
+inaccessible.
+.LP
+The garbage collector tries to avoid allocating memory at locations that
+already appear to be referenced before allocation.  (Such apparent
+``pointers'' are usually large integers and the like that just happen to look
+like an address.)  This may make it hard to allocate very large objects.
+An attempt to do so may generate a warning.
+.LP
+.I
+GC_malloc_ignore_off_page
+and
+.I
+GC_malloc_atomic_ignore_off_page
+inform the collector that the client code will always maintain a pointer to
+near the beginning of the object (within the first 512 bytes), and that
+pointers beyond that can be ignored by the collector.  This makes it much
+easier for the collector to place large objects.  These are recommended for
+large object allocation.  (Objects expected to be > ~100 KB should be
+allocated this way.)
+.LP
+It is also possible to use the collector to find storage leaks in programs
+destined to be run with standard malloc/free.  The collector can be compiled
+for thread-safe operation.  Unlike standard malloc, it is safe to call malloc
+after a previous malloc call was interrupted by a signal, provided the
+original malloc call is not resumed.
+.LP
+The collector may, on rare occasion, produce warning messages.  On UNIX
+machines these appear on stderr.  Warning messages can be filtered,
+redirected, or ignored with
+.I
+GC_set_warn_proc
+This is recommended for production code.  See gc.h for details.
+.LP
+Fully portable code should call
+.I
+GC_INIT
+from the primordial thread of the main program before making any other
+GC calls.  On most platforms this does nothing and the collector is
+initialized on first use.  On a few platforms explicit initialization is
+necessary.  And it can never hurt.
+.LP
+Debugging versions of many of the above routines are provided as macros.
+Their names are identical to the above, but consist of all capital letters.
+If GC_DEBUG is defined before gc.h is included, these routines do additional
+checking, and allow the leak detecting version of the collector to produce
+slightly more useful output.  Without GC_DEBUG defined, they behave exactly
+like the lower-case versions.
+.LP
+On some machines, collection will be performed incrementally after a call to
+.I
+GC_enable_incremental.
+This may temporarily write protect pages in the heap.  See the README file for
+more information on how this interacts with system calls that write to the
+heap.
+.LP
+Other facilities not discussed here include limited facilities to support
+incremental collection on machines without appropriate VM support, provisions
+for providing more explicit object layout information to the garbage
+collector, more direct support for ``weak'' pointers, support for
+``abortable'' garbage collections during idle time, etc.
+.LP
+.SH "SEE ALSO"
+The README and gc.h files in the distribution.  More detailed definitions of
+the functions exported by the collector are given there.  (The above list is
+not complete.)
+.LP
+The web site at http://www.hboehm.info/gc/ (or https://github.com/ivmai/bdwgc/).
+.LP
+Boehm, H., and M. Weiser, "Garbage Collection in an Uncooperative Environment",
+"Software Practice & Experience", September 1988, pp. 807-820.
+.LP
+The malloc(3) man page.
+.LP
+.SH AUTHOR
+Hans-J. Boehm ([email protected]).
+Some of the code was written by others (see the AUTHORS file for the details),
+most notably by Alan Demers, and, recently, Ivan Maidanski.

+ 1 - 1
blitz.mod/bdwgc/gc_dlopen.c

@@ -36,7 +36,7 @@
  *  2) FASTLOCK is not a significant win.
  */
 
-#include "gc_gcj.h"
+#include "gc/gc_gcj.h"
 #include "private/dbg_mlc.h"
 
 int GC_gcj_kind = 0;    /* Object kind for objects with descriptors     */

+ 27 - 19
blitz.mod/bdwgc/headers.c

@@ -109,22 +109,26 @@ GC_INNER ptr_t GC_scratch_alloc(size_t bytes)
 
     bytes = ROUNDUP_GRANULE_SIZE(bytes);
     for (;;) {
-        GC_scratch_free_ptr += bytes;
-        if ((word)GC_scratch_free_ptr <= (word)GC_scratch_end_ptr) {
+        GC_ASSERT((word)GC_scratch_end_ptr >= (word)result);
+        if (bytes <= (word)GC_scratch_end_ptr - (word)result) {
             /* Unallocated space of scratch buffer has enough size. */
+            GC_scratch_free_ptr = result + bytes;
             return result;
         }
 
+        GC_ASSERT(GC_page_size != 0);
         if (bytes >= MINHINCR * HBLKSIZE) {
             bytes_to_get = ROUNDUP_PAGESIZE_IF_MMAP(bytes);
             result = (ptr_t)GET_MEM(bytes_to_get);
-            GC_add_to_our_memory(result, bytes_to_get);
-            /* Undo scratch free area pointer update; get memory directly. */
-            GC_scratch_free_ptr -= bytes;
             if (result != NULL) {
+              GC_add_to_our_memory(result, bytes_to_get);
+              /* No update of scratch free area pointer;        */
+              /* get memory directly.                           */
+#             ifdef USE_SCRATCH_LAST_END_PTR
                 /* Update end point of last obtained area (needed only  */
                 /* by GC_register_dynamic_libraries for some targets).  */
                 GC_scratch_last_end_ptr = result + bytes;
+#             endif
             }
             return result;
         }
@@ -132,20 +136,28 @@ GC_INNER ptr_t GC_scratch_alloc(size_t bytes)
         bytes_to_get = ROUNDUP_PAGESIZE_IF_MMAP(MINHINCR * HBLKSIZE);
                                                 /* round up for safety */
         result = (ptr_t)GET_MEM(bytes_to_get);
-        GC_add_to_our_memory(result, bytes_to_get);
-        if (NULL == result) {
+        if (EXPECT(NULL == result, FALSE)) {
             WARN("Out of memory - trying to allocate requested amount"
                  " (%" WARN_PRIdPTR " bytes)...\n", (word)bytes);
-            GC_scratch_free_ptr -= bytes; /* Undo free area pointer update */
             bytes_to_get = ROUNDUP_PAGESIZE_IF_MMAP(bytes);
             result = (ptr_t)GET_MEM(bytes_to_get);
-            GC_add_to_our_memory(result, bytes_to_get);
+            if (result != NULL) {
+              GC_add_to_our_memory(result, bytes_to_get);
+#             ifdef USE_SCRATCH_LAST_END_PTR
+                GC_scratch_last_end_ptr = result + bytes;
+#             endif
+            }
             return result;
         }
+
+        GC_add_to_our_memory(result, bytes_to_get);
+        /* TODO: some amount of unallocated space may remain unused forever */
         /* Update scratch area pointers and retry.      */
         GC_scratch_free_ptr = result;
         GC_scratch_end_ptr = GC_scratch_free_ptr + bytes_to_get;
-        GC_scratch_last_end_ptr = GC_scratch_end_ptr;
+#       ifdef USE_SCRATCH_LAST_END_PTR
+          GC_scratch_last_end_ptr = GC_scratch_end_ptr;
+#       endif
     }
 }
 
@@ -332,9 +344,7 @@ void GC_apply_to_all_blocks(void (*fn)(struct hblk *h, word client_data),
      }
 }
 
-/* Get the next valid block whose address is at least h */
-/* Return 0 if there is none.                           */
-GC_INNER struct hblk * GC_next_used_block(struct hblk *h)
+GC_INNER struct hblk * GC_next_block(struct hblk *h, GC_bool allow_free)
 {
     REGISTER bottom_index * bi;
     REGISTER word j = ((word)h >> LOG_HBLKSIZE) & (BOTTOM_SZ-1);
@@ -348,14 +358,15 @@ GC_INNER struct hblk * GC_next_used_block(struct hblk *h)
         while (bi != 0 && bi -> key < hi) bi = bi -> asc_link;
         j = 0;
     }
-    while(bi != 0) {
+
+    while (bi != 0) {
         while (j < BOTTOM_SZ) {
             hdr * hhdr = bi -> index[j];
             if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
                 j++;
             } else {
-                if (!HBLK_IS_FREE(hhdr)) {
-                    return((struct hblk *)
+                if (allow_free || !HBLK_IS_FREE(hhdr)) {
+                    return ((struct hblk *)
                               (((bi -> key << LOG_BOTTOM_SZ) + j)
                                << LOG_HBLKSIZE));
                 } else {
@@ -369,9 +380,6 @@ GC_INNER struct hblk * GC_next_used_block(struct hblk *h)
     return(0);
 }
 
-/* Get the last (highest address) block whose address is        */
-/* at most h.  Return 0 if there is none.                       */
-/* Unlike the above, this may return a free block.              */
 GC_INNER struct hblk * GC_prev_block(struct hblk *h)
 {
     bottom_index * bi;

+ 2 - 2151
blitz.mod/bdwgc/include/gc.h

@@ -1,2151 +1,2 @@
-/*
- * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
- * Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved.
- * Copyright 1996-1999 by Silicon Graphics.  All rights reserved.
- * Copyright 1999 by Hewlett-Packard Company.  All rights reserved.
- * Copyright (C) 2007 Free Software Foundation, Inc
- * Copyright (c) 2000-2011 by Hewlett-Packard Development Company.
- * Copyright (c) 2009-2020 Ivan Maidanski
- *
- * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
- * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
- *
- * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
- * Permission to modify the code and to distribute modified code is granted,
- * provided the above notices are retained, and a notice that the code was
- * modified is included with the above copyright notice.
- */
-
-/*
- * Note that this defines a large number of tuning hooks, which can
- * safely be ignored in nearly all cases.  For normal use it suffices
- * to call only GC_MALLOC and perhaps GC_REALLOC.
- * For better performance, also look at GC_MALLOC_ATOMIC, and
- * GC_enable_incremental.  If you need an action to be performed
- * immediately before an object is collected, look at GC_register_finalizer.
- * Everything else is best ignored unless you encounter performance
- * problems.
- */
-
-#ifndef GC_H
-#define GC_H
-
-/* Help debug mixed up preprocessor symbols.    */
-#if (defined(WIN64) && !defined(_WIN64)) && defined(_MSC_VER)
-#pragma message("Warning: Expecting _WIN64 for x64 targets! Notice the leading underscore!")
-#endif
-
-#include "gc_version.h"
-        /* Define version numbers here to allow test on build machine   */
-        /* for cross-builds.  Note that this defines the header         */
-        /* version number, which may or may not match that of the       */
-        /* dynamic library.  GC_get_version() can be used to obtain     */
-        /* the latter.                                                  */
-
-#include "gc_config_macros.h"
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-typedef void * GC_PTR;  /* preserved only for backward compatibility    */
-
-/* Define word and signed_word to be unsigned and signed types of the   */
-/* size as char * or void *.  There seems to be no way to do this       */
-/* even semi-portably.  The following is probably no better/worse       */
-/* than almost anything else.                                           */
-/* The ANSI standard suggests that size_t and ptrdiff_t might be        */
-/* better choices.  But those had incorrect definitions on some older   */
-/* systems.  Notably "typedef int size_t" is WRONG.                     */
-#ifdef _WIN64
-# if defined(__int64) && !defined(CPPCHECK)
-    typedef unsigned __int64 GC_word;
-    typedef __int64 GC_signed_word;
-# else
-    typedef unsigned long long GC_word;
-    typedef long long GC_signed_word;
-# endif
-#else
-  typedef unsigned long GC_word;
-  typedef long GC_signed_word;
-#endif
-
-/* Get the GC library version. The returned value is a constant in the  */
-/* form: ((version_major<<16) | (version_minor<<8) | version_micro).    */
-GC_API unsigned GC_CALL GC_get_version(void);
-
-/* Public read-only variables */
-/* The supplied getter functions are preferred for new code.            */
-
-GC_API GC_ATTR_DEPRECATED GC_word GC_gc_no;
-                        /* Counter incremented per collection.          */
-                        /* Includes empty GCs at startup.               */
-GC_API GC_word GC_CALL GC_get_gc_no(void);
-                        /* GC_get_gc_no() is unsynchronized, so         */
-                        /* it requires GC_call_with_alloc_lock() to     */
-                        /* avoid data races on multiprocessors.         */
-
-#ifdef GC_THREADS
-  GC_API GC_ATTR_DEPRECATED int GC_parallel;
-                        /* GC is parallelized for performance on        */
-                        /* multiprocessors.  Set to a non-zero value    */
-                        /* only implicitly if collector is built with   */
-                        /* PARALLEL_MARK defined, and if either         */
-                        /* GC_MARKERS (or GC_NPROCS) environment        */
-                        /* variable is set to > 1, or multiple cores    */
-                        /* (processors) are available, or the client    */
-                        /* calls GC_set_markers_count() before the GC   */
-                        /* initialization.  The getter does             */
-                        /* not use or need synchronization (i.e.        */
-                        /* acquiring the GC lock).  GC_parallel value   */
-                        /* is equal to the number of marker threads     */
-                        /* minus one (i.e. number of existing parallel  */
-                        /* marker threads excluding the initiating one).*/
-  GC_API int GC_CALL GC_get_parallel(void);
-
-  /* Set the number of marker threads (including the initiating one)    */
-  /* to the desired value at start-up.  Zero value means the collector  */
-  /* is to decide.  Has no effect if called after GC initialization.    */
-  /* If the correct non-zero value is passed, then GC_parallel should   */
-  /* be set to the value minus one.  The function does not use any      */
-  /* synchronization.                                                   */
-  GC_API void GC_CALL GC_set_markers_count(unsigned);
-#endif
-
-
-/* Public R/W variables */
-/* The supplied setter and getter functions are preferred for new code. */
-
-typedef void * (GC_CALLBACK * GC_oom_func)(size_t /* bytes_requested */);
-GC_API GC_ATTR_DEPRECATED GC_oom_func GC_oom_fn;
-                        /* When there is insufficient memory to satisfy */
-                        /* an allocation request, we return             */
-                        /* (*GC_oom_fn)(size).  By default this just    */
-                        /* returns NULL.                                */
-                        /* If it returns, it must return 0 or a valid   */
-                        /* pointer to a previously allocated heap       */
-                        /* object.  GC_oom_fn must not be 0.            */
-                        /* Both the supplied setter and the getter      */
-                        /* acquire the GC lock (to avoid data races).   */
-GC_API void GC_CALL GC_set_oom_fn(GC_oom_func) GC_ATTR_NONNULL(1);
-GC_API GC_oom_func GC_CALL GC_get_oom_fn(void);
-
-typedef void (GC_CALLBACK * GC_on_heap_resize_proc)(GC_word /* new_size */);
-GC_API GC_ATTR_DEPRECATED GC_on_heap_resize_proc GC_on_heap_resize;
-                        /* Invoked when the heap grows or shrinks.      */
-                        /* Called with the world stopped (and the       */
-                        /* allocation lock held).  May be 0.            */
-GC_API void GC_CALL GC_set_on_heap_resize(GC_on_heap_resize_proc);
-GC_API GC_on_heap_resize_proc GC_CALL GC_get_on_heap_resize(void);
-                        /* Both the supplied setter and the getter      */
-                        /* acquire the GC lock (to avoid data races).   */
-
-typedef enum {
-    GC_EVENT_START /* COLLECTION */,
-    GC_EVENT_MARK_START,
-    GC_EVENT_MARK_END,
-    GC_EVENT_RECLAIM_START,
-    GC_EVENT_RECLAIM_END,
-    GC_EVENT_END /* COLLECTION */,
-    GC_EVENT_PRE_STOP_WORLD /* STOPWORLD_BEGIN */,
-    GC_EVENT_POST_STOP_WORLD /* STOPWORLD_END */,
-    GC_EVENT_PRE_START_WORLD /* STARTWORLD_BEGIN */,
-    GC_EVENT_POST_START_WORLD /* STARTWORLD_END */,
-    GC_EVENT_THREAD_SUSPENDED,
-    GC_EVENT_THREAD_UNSUSPENDED
-} GC_EventType;
-
-typedef void (GC_CALLBACK * GC_on_collection_event_proc)(GC_EventType);
-                        /* Invoked to indicate progress through the     */
-                        /* collection process.  Not used for thread     */
-                        /* suspend/resume notifications.  Called with   */
-                        /* the GC lock held (or, even, the world        */
-                        /* stopped).  May be 0 (means no notifier).     */
-GC_API void GC_CALL GC_set_on_collection_event(GC_on_collection_event_proc);
-GC_API GC_on_collection_event_proc GC_CALL GC_get_on_collection_event(void);
-                        /* Both the supplied setter and the getter      */
-                        /* acquire the GC lock (to avoid data races).   */
-
-#if defined(GC_THREADS) || (defined(GC_BUILD) && defined(NN_PLATFORM_CTR))
-  typedef void (GC_CALLBACK * GC_on_thread_event_proc)(GC_EventType,
-                                                void * /* thread_id */);
-                        /* Invoked when a thread is suspended or        */
-                        /* resumed during collection.  Called with the  */
-                        /* GC lock held (and the world stopped          */
-                        /* partially).  May be 0 (means no notifier).   */
-  GC_API void GC_CALL GC_set_on_thread_event(GC_on_thread_event_proc);
-  GC_API GC_on_thread_event_proc GC_CALL GC_get_on_thread_event(void);
-                        /* Both the supplied setter and the getter      */
-                        /* acquire the GC lock (to avoid data races).   */
-#endif
-
-GC_API GC_ATTR_DEPRECATED int GC_find_leak;
-                        /* Set to true to turn on the leak-finding mode */
-                        /* (do not actually garbage collect, but simply */
-                        /* report inaccessible memory that was not      */
-                        /* deallocated with GC_FREE).  Initial value    */
-                        /* is determined by FIND_LEAK macro.            */
-                        /* The value should not typically be modified   */
-                        /* after GC initialization (and, thus, it does  */
-                        /* not use or need synchronization).            */
-GC_API void GC_CALL GC_set_find_leak(int);
-GC_API int GC_CALL GC_get_find_leak(void);
-
-GC_API GC_ATTR_DEPRECATED int GC_all_interior_pointers;
-                        /* Arrange for pointers to object interiors to  */
-                        /* be recognized as valid.  Typically should    */
-                        /* not be changed after GC initialization (in   */
-                        /* case of calling it after the GC is           */
-                        /* initialized, the setter acquires the GC lock */
-                        /* (to avoid data races).  The initial value    */
-                        /* depends on whether the GC is built with      */
-                        /* ALL_INTERIOR_POINTERS macro defined or not.  */
-                        /* Unless DONT_ADD_BYTE_AT_END is defined, this */
-                        /* also affects whether sizes are increased by  */
-                        /* at least a byte to allow "off the end"       */
-                        /* pointer recognition.  Must be only 0 or 1.   */
-GC_API void GC_CALL GC_set_all_interior_pointers(int);
-GC_API int GC_CALL GC_get_all_interior_pointers(void);
-
-GC_API GC_ATTR_DEPRECATED int GC_finalize_on_demand;
-                        /* If nonzero, finalizers will only be run in   */
-                        /* response to an explicit GC_invoke_finalizers */
-                        /* call.  The default is determined by whether  */
-                        /* the FINALIZE_ON_DEMAND macro is defined      */
-                        /* when the collector is built.                 */
-                        /* The setter and getter are unsynchronized.    */
-GC_API void GC_CALL GC_set_finalize_on_demand(int);
-GC_API int GC_CALL GC_get_finalize_on_demand(void);
-
-GC_API GC_ATTR_DEPRECATED int GC_java_finalization;
-                        /* Mark objects reachable from finalizable      */
-                        /* objects in a separate post-pass.  This makes */
-                        /* it a bit safer to use non-topologically-     */
-                        /* ordered finalization.  Default value is      */
-                        /* determined by JAVA_FINALIZATION macro.       */
-                        /* Enables register_finalizer_unreachable to    */
-                        /* work correctly.                              */
-                        /* The setter and getter are unsynchronized.    */
-GC_API void GC_CALL GC_set_java_finalization(int);
-GC_API int GC_CALL GC_get_java_finalization(void);
-
-typedef void (GC_CALLBACK * GC_finalizer_notifier_proc)(void);
-GC_API GC_ATTR_DEPRECATED GC_finalizer_notifier_proc GC_finalizer_notifier;
-                        /* Invoked by the collector when there are      */
-                        /* objects to be finalized.  Invoked at most    */
-                        /* once per GC cycle.  Never invoked unless     */
-                        /* GC_finalize_on_demand is set.                */
-                        /* Typically this will notify a finalization    */
-                        /* thread, which will call GC_invoke_finalizers */
-                        /* in response.  May be 0 (means no notifier).  */
-                        /* Both the supplied setter and the getter      */
-                        /* acquire the GC lock (to avoid data races).   */
-GC_API void GC_CALL GC_set_finalizer_notifier(GC_finalizer_notifier_proc);
-GC_API GC_finalizer_notifier_proc GC_CALL GC_get_finalizer_notifier(void);
-
-GC_API
-# ifndef GC_DONT_GC
-    GC_ATTR_DEPRECATED
-# endif
-  int GC_dont_gc;       /* != 0 ==> Do not collect.  This overrides     */
-                        /* explicit GC_gcollect() calls as well.        */
-                        /* Used as a counter, so that nested enabling   */
-                        /* and disabling work correctly.  Should        */
-                        /* normally be updated with GC_enable() and     */
-                        /* GC_disable() calls.  Direct assignment to    */
-                        /* GC_dont_gc is deprecated.  To check whether  */
-                        /* GC is disabled, GC_is_disabled() is          */
-                        /* preferred for new code.                      */
-
-GC_API GC_ATTR_DEPRECATED int GC_dont_expand;
-                        /* Do not expand the heap unless explicitly     */
-                        /* requested or forced to.  The setter and      */
-                        /* getter are unsynchronized.                   */
-GC_API void GC_CALL GC_set_dont_expand(int);
-GC_API int GC_CALL GC_get_dont_expand(void);
-
-GC_API GC_ATTR_DEPRECATED int GC_use_entire_heap;
-                /* Causes the non-incremental collector to use the      */
-                /* entire heap before collecting.  This sometimes       */
-                /* results in more large block fragmentation, since     */
-                /* very large blocks will tend to get broken up         */
-                /* during each GC cycle.  It is likely to result in a   */
-                /* larger working set, but lower collection             */
-                /* frequencies, and hence fewer instructions executed   */
-                /* in the collector.                                    */
-
-GC_API GC_ATTR_DEPRECATED int GC_full_freq;
-                            /* Number of partial collections between    */
-                            /* full collections.  Matters only if       */
-                            /* GC_is_incremental_mode().                */
-                            /* Full collections are also triggered if   */
-                            /* the collector detects a substantial      */
-                            /* increase in the number of in-use heap    */
-                            /* blocks.  Values in the tens are now      */
-                            /* perfectly reasonable, unlike for         */
-                            /* earlier GC versions.                     */
-                        /* The setter and getter are unsynchronized, so */
-                        /* GC_call_with_alloc_lock() is required to     */
-                        /* avoid data races (if the value is modified   */
-                        /* after the GC is put to multi-threaded mode). */
-GC_API void GC_CALL GC_set_full_freq(int);
-GC_API int GC_CALL GC_get_full_freq(void);
-
-GC_API GC_ATTR_DEPRECATED GC_word GC_non_gc_bytes;
-                        /* Bytes not considered candidates for          */
-                        /* collection.  Used only to control scheduling */
-                        /* of collections.  Updated by                  */
-                        /* GC_malloc_uncollectable and GC_free.         */
-                        /* Wizards only.                                */
-                        /* The setter and getter are unsynchronized, so */
-                        /* GC_call_with_alloc_lock() is required to     */
-                        /* avoid data races (if the value is modified   */
-                        /* after the GC is put to multi-threaded mode). */
-GC_API void GC_CALL GC_set_non_gc_bytes(GC_word);
-GC_API GC_word GC_CALL GC_get_non_gc_bytes(void);
-
-GC_API GC_ATTR_DEPRECATED int GC_no_dls;
-                        /* Don't register dynamic library data segments. */
-                        /* Wizards only.  Should be used only if the     */
-                        /* application explicitly registers all roots.   */
-                        /* (In some environments like Microsoft Windows  */
-                        /* and Apple's Darwin, this may also prevent     */
-                        /* registration of the main data segment as part */
-                        /* of the root set.)                             */
-                        /* The setter and getter are unsynchronized.     */
-GC_API void GC_CALL GC_set_no_dls(int);
-GC_API int GC_CALL GC_get_no_dls(void);
-
-GC_API GC_ATTR_DEPRECATED GC_word GC_free_space_divisor;
-                        /* We try to make sure that we allocate at      */
-                        /* least N/GC_free_space_divisor bytes between  */
-                        /* collections, where N is twice the number     */
-                        /* of traced bytes, plus the number of untraced */
-                        /* bytes (bytes in "atomic" objects), plus      */
-                        /* a rough estimate of the root set size.       */
-                        /* N approximates GC tracing work per GC.       */
-                        /* The initial value is GC_FREE_SPACE_DIVISOR.  */
-                        /* Increasing its value will use less space     */
-                        /* but more collection time.  Decreasing it     */
-                        /* will appreciably decrease collection time    */
-                        /* at the expense of space.                     */
-                        /* The setter and getter are unsynchronized, so */
-                        /* GC_call_with_alloc_lock() is required to     */
-                        /* avoid data races (if the value is modified   */
-                        /* after the GC is put to multi-threaded mode). */
-                        /* In GC v7.1 (and before), the setter returned */
-                        /* the old value.                               */
-GC_API void GC_CALL GC_set_free_space_divisor(GC_word);
-GC_API GC_word GC_CALL GC_get_free_space_divisor(void);
-
-GC_API GC_ATTR_DEPRECATED GC_word GC_max_retries;
-                        /* The maximum number of GCs attempted before   */
-                        /* reporting out of memory after heap           */
-                        /* expansion fails.  Initially 0.               */
-                        /* The setter and getter are unsynchronized, so */
-                        /* GC_call_with_alloc_lock() is required to     */
-                        /* avoid data races (if the value is modified   */
-                        /* after the GC is put to multi-threaded mode). */
-GC_API void GC_CALL GC_set_max_retries(GC_word);
-GC_API GC_word GC_CALL GC_get_max_retries(void);
-
-
-GC_API GC_ATTR_DEPRECATED char *GC_stackbottom;
-                                /* The cold end (bottom) of user stack. */
-                                /* May be set in the client prior to    */
-                                /* calling any GC_ routines.  This      */
-                                /* avoids some overhead, and            */
-                                /* potentially some signals that can    */
-                                /* confuse debuggers.  Otherwise the    */
-                                /* collector attempts to set it         */
-                                /* automatically.                       */
-                                /* For multi-threaded code, this is the */
-                                /* cold end of the stack for the        */
-                                /* primordial thread.  Portable clients */
-                                /* should use GC_get_stack_base(),      */
-                                /* GC_call_with_gc_active() and         */
-                                /* GC_register_my_thread() instead.     */
-
-GC_API GC_ATTR_DEPRECATED int GC_dont_precollect;
-                                /* Do not collect as part of GC         */
-                                /* initialization.  Should be set only  */
-                                /* if the client wants a chance to      */
-                                /* manually initialize the root set     */
-                                /* before the first collection.         */
-                                /* Interferes with blacklisting.        */
-                                /* Wizards only.  The setter and getter */
-                                /* are unsynchronized (and no external  */
-                                /* locking is needed since the value is */
-                                /* accessed at GC initialization only). */
-GC_API void GC_CALL GC_set_dont_precollect(int);
-GC_API int GC_CALL GC_get_dont_precollect(void);
-
-GC_API GC_ATTR_DEPRECATED unsigned long GC_time_limit;
-                               /* If incremental collection is enabled, */
-                               /* we try to terminate collections       */
-                               /* after this many milliseconds (plus    */
-                               /* the amount of nanoseconds as given in */
-                               /* the latest GC_set_time_limit_tv call, */
-                               /* if any).  Not a hard time bound.      */
-                               /* Setting this variable to              */
-                               /* GC_TIME_UNLIMITED will essentially    */
-                               /* disable incremental collection while  */
-                               /* leaving generational collection       */
-                               /* enabled.                              */
-#define GC_TIME_UNLIMITED 999999
-                               /* Setting GC_time_limit to this value   */
-                               /* will disable the "pause time exceeded"*/
-                               /* tests.                                */
-                        /* The setter and getter are unsynchronized, so */
-                        /* GC_call_with_alloc_lock() is required to     */
-                        /* avoid data races (if the value is modified   */
-                        /* after the GC is put to multi-threaded mode). */
-                        /* The setter does not update the value of the  */
-                        /* nanosecond part of the time limit (it is     */
-                        /* zero unless ever set by GC_set_time_limit_tv */
-                        /* call).                                       */
-GC_API void GC_CALL GC_set_time_limit(unsigned long);
-GC_API unsigned long GC_CALL GC_get_time_limit(void);
-
-/* A portable type definition of time with a nanosecond precision.      */
-struct GC_timeval_s {
-  unsigned long tv_ms;  /* time in milliseconds */
-  unsigned long tv_nsec;/* nanoseconds fraction (<1000000) */
-};
-
-/* Public procedures */
-
-/* Set/get the time limit of the incremental collections.  This is      */
-/* similar to GC_set_time_limit and GC_get_time_limit but the time is   */
-/* provided with the nanosecond precision.  The value of tv_nsec part   */
-/* should be less than a million.  If the value of tv_ms part is        */
-/* GC_TIME_UNLIMITED then tv_nsec is ignored.  Initially, the value of  */
-/* tv_nsec part of the time limit is zero.  The functions do not use    */
-/* any synchronization.  Defined only if the library has been compiled  */
-/* without NO_CLOCK.                                                    */
-GC_API void GC_CALL GC_set_time_limit_tv(struct GC_timeval_s);
-GC_API struct GC_timeval_s GC_CALL GC_get_time_limit_tv(void);
-
-/* Set/get the minimum value of the ratio of allocated bytes since GC   */
-/* to the amount of finalizers created since that GC (value >           */
-/* GC_bytes_allocd / (GC_fo_entries - last_fo_entries)) which triggers  */
-/* the collection instead heap expansion.  The value has no effect in   */
-/* the GC incremental mode.  The default value is 10000 unless          */
-/* GC_ALLOCD_BYTES_PER_FINALIZER macro with a custom value is defined   */
-/* to build libgc.  The default value might be not the right choice for */
-/* clients where e.g. most objects have a finalizer.  Zero value        */
-/* effectively disables taking amount of finalizers in the decision     */
-/* whether to collect or not.  The functions do not use any             */
-/* synchronization.                                                     */
-GC_API void GC_CALL GC_set_allocd_bytes_per_finalizer(GC_word);
-GC_API GC_word GC_CALL GC_get_allocd_bytes_per_finalizer(void);
-
-/* Tell the collector to start various performance measurements.        */
-/* Only the total time taken by full collections is calculated, as      */
-/* of now.  And, currently, there is no way to stop the measurements.   */
-/* The function does not use any synchronization.  Defined only if the  */
-/* library has been compiled without NO_CLOCK.                          */
-GC_API void GC_CALL GC_start_performance_measurement(void);
-
-/* Get the total time of all full collections since the start of the    */
-/* performance measurements.  The measurement unit is one millisecond.  */
-/* Note that the returned value wraps around on overflow.               */
-/* The function does not use any synchronization.  Defined only if the  */
-/* library has been compiled without NO_CLOCK.                          */
-GC_API unsigned long GC_CALL GC_get_full_gc_total_time(void);
-
-/* Set whether the GC will allocate executable memory pages or not.     */
-/* A non-zero argument instructs the collector to allocate memory with  */
-/* the executable flag on.  Must be called before the collector is      */
-/* initialized.  May have no effect on some platforms.  The default     */
-/* value is controlled by NO_EXECUTE_PERMISSION macro (if present then  */
-/* the flag is off).  Portable clients should have                      */
-/* GC_set_pages_executable(1) call (before GC_INIT) provided they are   */
-/* going to execute code on any of the GC-allocated memory objects.     */
-GC_API void GC_CALL GC_set_pages_executable(int);
-
-/* Returns non-zero value if the GC is set to the allocate-executable   */
-/* mode.  The mode could be changed by GC_set_pages_executable (before  */
-/* GC_INIT) unless the former has no effect on the platform.  Does not  */
-/* use or need synchronization (i.e. acquiring the allocator lock).     */
-GC_API int GC_CALL GC_get_pages_executable(void);
-
-/* The setter and getter of the minimum value returned by the internal  */
-/* min_bytes_allocd().  The value should not be zero; the default value */
-/* is one.  Not synchronized.                                           */
-GC_API void GC_CALL GC_set_min_bytes_allocd(size_t);
-GC_API size_t GC_CALL GC_get_min_bytes_allocd(void);
-
-/* Set/get the size in pages of units operated by GC_collect_a_little.  */
-/* The value should not be zero.  Not synchronized.                     */
-GC_API void GC_CALL GC_set_rate(int);
-GC_API int GC_CALL GC_get_rate(void);
-
-/* Set/get the maximum number of prior attempts at the world-stop       */
-/* marking.  Not synchronized.                                          */
-GC_API void GC_CALL GC_set_max_prior_attempts(int);
-GC_API int GC_CALL GC_get_max_prior_attempts(void);
-
-/* Overrides the default handle-fork mode.  Non-zero value means GC     */
-/* should install proper pthread_atfork handlers.  Has effect only if   */
-/* called before GC_INIT.  Clients should invoke GC_set_handle_fork     */
-/* with non-zero argument if going to use fork with GC functions called */
-/* in the forked child.  (Note that such client and atfork handlers     */
-/* activities are not fully POSIX-compliant.)  GC_set_handle_fork       */
-/* instructs GC_init to setup GC fork handlers using pthread_atfork,    */
-/* the latter might fail (or, even, absent on some targets) causing     */
-/* abort at GC initialization.  Issues with missing (or failed)         */
-/* pthread_atfork() could be avoided by invocation                      */
-/* of GC_set_handle_fork(-1) at application start-up and surrounding    */
-/* each fork() with the relevant GC_atfork_prepare/parent/child calls.  */
-GC_API void GC_CALL GC_set_handle_fork(int);
-
-/* Routines to handle POSIX fork() manually (no-op if handled           */
-/* automatically).  GC_atfork_prepare should be called immediately      */
-/* before fork(); GC_atfork_parent should be invoked just after fork in */
-/* the branch that corresponds to parent process (i.e., fork result is  */
-/* non-zero); GC_atfork_child is to be called immediately in the child  */
-/* branch (i.e., fork result is 0). Note that GC_atfork_child() call    */
-/* should, of course, precede GC_start_mark_threads call (if any).      */
-GC_API void GC_CALL GC_atfork_prepare(void);
-GC_API void GC_CALL GC_atfork_parent(void);
-GC_API void GC_CALL GC_atfork_child(void);
-
-/* Initialize the collector.  Portable clients should call GC_INIT()    */
-/* from the main program instead.                                       */
-GC_API void GC_CALL GC_init(void);
-
-/* Returns non-zero (TRUE) if and only if the collector is initialized  */
-/* (or, at least, the initialization is in progress).                   */
-GC_API int GC_CALL GC_is_init_called(void);
-
-/* Perform the collector shutdown.  (E.g. dispose critical sections on  */
-/* Win32 target.)  A duplicate invocation is a no-op.  GC_INIT should   */
-/* not be called after the shutdown.  See also GC_win32_free_heap().    */
-GC_API void GC_CALL GC_deinit(void);
-
-/* General purpose allocation routines, with roughly malloc calling     */
-/* conv.  The atomic versions promise that no relevant pointers are     */
-/* contained in the object.  The non-atomic versions guarantee that the */
-/* new object is cleared.  GC_malloc_uncollectable allocates            */
-/* an object that is scanned for pointers to collectible                */
-/* objects, but is not itself collectible.  The object is scanned even  */
-/* if it does not appear to be reachable.  GC_malloc_uncollectable and  */
-/* GC_free called on the resulting object implicitly update             */
-/* GC_non_gc_bytes appropriately.                                       */
-GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
-        GC_malloc(size_t /* size_in_bytes */);
-GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
-        GC_malloc_atomic(size_t /* size_in_bytes */);
-GC_API GC_ATTR_MALLOC char * GC_CALL GC_strdup(const char *);
-GC_API GC_ATTR_MALLOC char * GC_CALL
-        GC_strndup(const char *, size_t) GC_ATTR_NONNULL(1);
-GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
-        GC_malloc_uncollectable(size_t /* size_in_bytes */);
-GC_API GC_ATTR_DEPRECATED void * GC_CALL GC_malloc_stubborn(size_t);
-
-/* GC_memalign() is not well tested.                                    */
-GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(2) void * GC_CALL
-        GC_memalign(size_t /* align */, size_t /* lb */);
-GC_API int GC_CALL GC_posix_memalign(void ** /* memptr */, size_t /* align */,
-                        size_t /* lb */) GC_ATTR_NONNULL(1);
-
-/* Explicitly deallocate an object.  Dangerous if used incorrectly.     */
-/* Requires a pointer to the base of an object.                         */
-/* An object should not be enabled for finalization (and it should not  */
-/* contain registered disappearing links of any kind) when it is        */
-/* explicitly deallocated.                                              */
-/* GC_free(0) is a no-op, as required by ANSI C for free.               */
-GC_API void GC_CALL GC_free(void *);
-
-/* The "stubborn" objects allocation is not supported anymore.  Exists  */
-/* only for the backward compatibility.                                 */
-#define GC_MALLOC_STUBBORN(sz)  GC_MALLOC(sz)
-#define GC_NEW_STUBBORN(t)      GC_NEW(t)
-#define GC_CHANGE_STUBBORN(p)   GC_change_stubborn(p)
-GC_API GC_ATTR_DEPRECATED void GC_CALL GC_change_stubborn(const void *);
-
-/* Inform the collector that the object has been changed.               */
-/* Only non-NULL pointer stores into the object are considered to be    */
-/* changes.  Matters only if the incremental collection is enabled in   */
-/* the manual VDB mode (otherwise the function does nothing).           */
-/* Should be followed typically by GC_reachable_here called for each    */
-/* of the stored pointers.                                              */
-GC_API void GC_CALL GC_end_stubborn_change(const void *) GC_ATTR_NONNULL(1);
-
-/* Return a pointer to the base (lowest address) of an object given     */
-/* a pointer to a location within the object.                           */
-/* I.e., map an interior pointer to the corresponding base pointer.     */
-/* Note that with debugging allocation, this returns a pointer to the   */
-/* actual base of the object, i.e. the debug information, not to        */
-/* the base of the user object.                                         */
-/* Return 0 if displaced_pointer doesn't point to within a valid        */
-/* object.                                                              */
-/* Note that a deallocated object in the garbage collected heap         */
-/* may be considered valid, even if it has been deallocated with        */
-/* GC_free.                                                             */
-GC_API void * GC_CALL GC_base(void * /* displaced_pointer */);
-
-/* Return non-zero (TRUE) if and only if the argument points to         */
-/* somewhere in GC heap.  Primary use is as a fast alternative to       */
-/* GC_base to check whether the pointed object is allocated by GC       */
-/* or not.  It is assumed that the collector is already initialized.    */
-GC_API int GC_CALL GC_is_heap_ptr(const void *);
-
-/* Given a pointer to the base of an object, return its size in bytes.  */
-/* The returned size may be slightly larger than what was originally    */
-/* requested.                                                           */
-GC_API size_t GC_CALL GC_size(const void * /* obj_addr */) GC_ATTR_NONNULL(1);
-
-/* For compatibility with C library.  This is occasionally faster than  */
-/* a malloc followed by a bcopy.  But if you rely on that, either here  */
-/* or with the standard C library, your code is broken.  In my          */
-/* opinion, it shouldn't have been invented, but now we're stuck. -HB   */
-/* The resulting object has the same kind as the original.              */
-/* It is an error to have changes enabled for the original object.      */
-/* It does not change the content of the object from its beginning to   */
-/* the minimum of old size and new_size_in_bytes; the content above in  */
-/* case of object size growth is initialized to zero (not guaranteed    */
-/* for atomic object type).  The function follows ANSI conventions for  */
-/* NULL old_object (i.e., equivalent to GC_malloc regardless of new     */
-/* size).  If new size is zero (and old_object is non-NULL) then the    */
-/* call is equivalent to GC_free (and NULL is returned).  If old_object */
-/* is non-NULL, it must have been returned by an earlier call to        */
-/* GC_malloc* or GC_realloc.  In case of the allocation failure, the    */
-/* memory pointed by old_object is untouched (and not freed).           */
-/* If the returned pointer is not the same as old_object and both of    */
-/* them are non-NULL then old_object is freed.  Returns either NULL (in */
-/* case of the allocation failure or zero new size) or pointer to the   */
-/* allocated memory.                                                    */
-GC_API void * GC_CALL GC_realloc(void * /* old_object */,
-                                 size_t /* new_size_in_bytes */)
-                        /* 'realloc' attr */ GC_ATTR_ALLOC_SIZE(2);
-
-/* Explicitly increase the heap size.   */
-/* Returns 0 on failure, 1 on success.  */
-GC_API int GC_CALL GC_expand_hp(size_t /* number_of_bytes */);
-
-/* Limit the heap size to n bytes.  Useful when you're debugging,       */
-/* especially on systems that don't handle running out of memory well.  */
-/* n == 0 ==> unbounded.  This is the default.  This setter function is */
-/* unsynchronized (so it might require GC_call_with_alloc_lock to avoid */
-/* data races).                                                         */
-GC_API void GC_CALL GC_set_max_heap_size(GC_word /* n */);
-
-/* Inform the collector that a certain section of statically allocated  */
-/* memory contains no pointers to garbage collected memory.  Thus it    */
-/* need not be scanned.  This is sometimes important if the application */
-/* maps large read/write files into the address space, which could be   */
-/* mistaken for dynamic library data segments on some systems.          */
-/* Both section start and end are not needed to be pointer-aligned.     */
-GC_API void GC_CALL GC_exclude_static_roots(void * /* low_address */,
-                                            void * /* high_address_plus_1 */);
-
-/* Clear the number of entries in the exclusion table.  Wizards only.   */
-GC_API void GC_CALL GC_clear_exclusion_table(void);
-
-/* Clear the set of root segments.  Wizards only.                       */
-GC_API void GC_CALL GC_clear_roots(void);
-
-/* Add a root segment.  Wizards only.                                   */
-/* Both segment start and end are not needed to be pointer-aligned.     */
-/* low_address must not be greater than high_address_plus_1.            */
-GC_API void GC_CALL GC_add_roots(void * /* low_address */,
-                                 void * /* high_address_plus_1 */);
-
-/* Remove a root segment.  Wizards only.                                */
-/* May be unimplemented on some platforms.                              */
-GC_API void GC_CALL GC_remove_roots(void * /* low_address */,
-                                    void * /* high_address_plus_1 */);
-
-/* Add a displacement to the set of those considered valid by the       */
-/* collector.  GC_register_displacement(n) means that if p was returned */
-/* by GC_malloc, then (char *)p + n will be considered to be a valid    */
-/* pointer to p.  N must be small and less than the size of p.          */
-/* (All pointers to the interior of objects from the stack are          */
-/* considered valid in any case.  This applies to heap objects and      */
-/* static data.)                                                        */
-/* Preferably, this should be called before any other GC procedures.    */
-/* Calling it later adds to the probability of excess memory            */
-/* retention.                                                           */
-/* This is a no-op if the collector has recognition of                  */
-/* arbitrary interior pointers enabled, which is now the default.       */
-GC_API void GC_CALL GC_register_displacement(size_t /* n */);
-
-/* The following version should be used if any debugging allocation is  */
-/* being done.                                                          */
-GC_API void GC_CALL GC_debug_register_displacement(size_t /* n */);
-
-/* Explicitly trigger a full, world-stop collection.    */
-GC_API void GC_CALL GC_gcollect(void);
-
-/* Same as above but ignores the default stop_func setting and tries to */
-/* unmap as much memory as possible (regardless of the corresponding    */
-/* switch setting).  The recommended usage: on receiving a system       */
-/* low-memory event; before retrying a system call failed because of    */
-/* the system is running out of resources.                              */
-GC_API void GC_CALL GC_gcollect_and_unmap(void);
-
-/* Trigger a full world-stopped collection.  Abort the collection if    */
-/* and when stop_func returns a nonzero value.  Stop_func will be       */
-/* called frequently, and should be reasonably fast.  (stop_func is     */
-/* called with the allocation lock held and the world might be stopped; */
-/* it's not allowed for stop_func to manipulate pointers to the garbage */
-/* collected heap or call most of GC functions.)  This works even       */
-/* if virtual dirty bits, and hence incremental collection is not       */
-/* available for this architecture.  Collections can be aborted faster  */
-/* than normal pause times for incremental collection.  However,        */
-/* aborted collections do no useful work; the next collection needs     */
-/* to start from the beginning.  stop_func must not be 0.               */
-/* GC_try_to_collect() returns 0 if the collection was aborted (or the  */
-/* collections are disabled), 1 if it succeeded.                        */
-typedef int (GC_CALLBACK * GC_stop_func)(void);
-GC_API int GC_CALL GC_try_to_collect(GC_stop_func /* stop_func */)
-                                                        GC_ATTR_NONNULL(1);
-
-/* Set and get the default stop_func.  The default stop_func is used by */
-/* GC_gcollect() and by implicitly trigged collections (except for the  */
-/* case when handling out of memory).  Must not be 0.                   */
-/* Both the setter and getter acquire the GC lock to avoid data races.  */
-GC_API void GC_CALL GC_set_stop_func(GC_stop_func /* stop_func */)
-                                                        GC_ATTR_NONNULL(1);
-GC_API GC_stop_func GC_CALL GC_get_stop_func(void);
-
-/* Return the number of bytes in the heap.  Excludes collector private  */
-/* data structures.  Excludes the unmapped memory (returned to the OS). */
-/* Includes empty blocks and fragmentation loss.  Includes some pages   */
-/* that were allocated but never written.                               */
-/* This is an unsynchronized getter, so it should be called typically   */
-/* with the GC lock held to avoid data races on multiprocessors (the    */
-/* alternative is to use GC_get_heap_usage_safe or GC_get_prof_stats    */
-/* API calls instead).                                                  */
-/* This getter remains lock-free (unsynchronized) for compatibility     */
-/* reason since some existing clients call it from a GC callback        */
-/* holding the allocator lock.  (This API function and the following    */
-/* four ones below were made thread-safe in GC v7.2alpha1 and          */
-/* reverted back in v7.2alpha7 for the reason described.)               */
-GC_API size_t GC_CALL GC_get_heap_size(void);
-
-/* Return a lower bound on the number of free bytes in the heap         */
-/* (excluding the unmapped memory space).  This is an unsynchronized    */
-/* getter (see GC_get_heap_size comment regarding thread-safety).       */
-GC_API size_t GC_CALL GC_get_free_bytes(void);
-
-/* Return the size (in bytes) of the unmapped memory (which is returned */
-/* to the OS but could be remapped back by the collector later unless   */
-/* the OS runs out of system/virtual memory). This is an unsynchronized */
-/* getter (see GC_get_heap_size comment regarding thread-safety).       */
-GC_API size_t GC_CALL GC_get_unmapped_bytes(void);
-
-/* Return the number of bytes allocated since the last collection.      */
-/* This is an unsynchronized getter (see GC_get_heap_size comment       */
-/* regarding thread-safety).                                            */
-GC_API size_t GC_CALL GC_get_bytes_since_gc(void);
-
-/* Return the number of explicitly deallocated bytes of memory since    */
-/* the recent collection.  This is an unsynchronized getter.            */
-GC_API size_t GC_CALL GC_get_expl_freed_bytes_since_gc(void);
-
-/* Return the total number of bytes allocated in this process.          */
-/* Never decreases, except due to wrapping.  This is an unsynchronized  */
-/* getter (see GC_get_heap_size comment regarding thread-safety).       */
-GC_API size_t GC_CALL GC_get_total_bytes(void);
-
-/* Return the heap usage information.  This is a thread-safe (atomic)   */
-/* alternative for the five above getters.   (This function acquires    */
-/* the allocator lock thus preventing data racing and returning the     */
-/* consistent result.)  Passing NULL pointer is allowed for any         */
-/* argument.  Returned (filled in) values are of word type.             */
-GC_API void GC_CALL GC_get_heap_usage_safe(GC_word * /* pheap_size */,
-                                           GC_word * /* pfree_bytes */,
-                                           GC_word * /* punmapped_bytes */,
-                                           GC_word * /* pbytes_since_gc */,
-                                           GC_word * /* ptotal_bytes */);
-
-/* Structure used to query GC statistics (profiling information).       */
-/* More fields could be added in the future.  To preserve compatibility */
-/* new fields should be added only to the end, and no deprecated fields */
-/* should be removed from.                                              */
-struct GC_prof_stats_s {
-  GC_word heapsize_full;
-            /* Heap size in bytes (including the area unmapped to OS).  */
-            /* Same as GC_get_heap_size() + GC_get_unmapped_bytes().    */
-  GC_word free_bytes_full;
-            /* Total bytes contained in free and unmapped blocks.       */
-            /* Same as GC_get_free_bytes() + GC_get_unmapped_bytes().   */
-  GC_word unmapped_bytes;
-            /* Amount of memory unmapped to OS.  Same as the value      */
-            /* returned by GC_get_unmapped_bytes().                     */
-  GC_word bytes_allocd_since_gc;
-            /* Number of bytes allocated since the recent collection.   */
-            /* Same as returned by GC_get_bytes_since_gc().             */
-  GC_word allocd_bytes_before_gc;
-            /* Number of bytes allocated before the recent garbage      */
-            /* collection.  The value may wrap.  Same as the result of  */
-            /* GC_get_total_bytes() - GC_get_bytes_since_gc().          */
-  GC_word non_gc_bytes;
-            /* Number of bytes not considered candidates for garbage    */
-            /* collection.  Same as returned by GC_get_non_gc_bytes().  */
-  GC_word gc_no;
-            /* Garbage collection cycle number.  The value may wrap     */
-            /* (and could be -1).  Same as returned by GC_get_gc_no().  */
-  GC_word markers_m1;
-            /* Number of marker threads (excluding the initiating one). */
-            /* Same as returned by GC_get_parallel (or 0 if the         */
-            /* collector is single-threaded).                           */
-  GC_word bytes_reclaimed_since_gc;
-            /* Approximate number of reclaimed bytes after recent GC.   */
-  GC_word reclaimed_bytes_before_gc;
-            /* Approximate number of bytes reclaimed before the recent  */
-            /* garbage collection.  The value may wrap.                 */
-  GC_word expl_freed_bytes_since_gc;
-            /* Number of bytes freed explicitly since the recent GC.    */
-            /* Same as returned by GC_get_expl_freed_bytes_since_gc().  */
-};
-
-/* Atomically get GC statistics (various global counters).  Clients     */
-/* should pass the size of the buffer (of GC_prof_stats_s type) to fill */
-/* in the values - this is for interoperability between different GC    */
-/* versions, an old client could have fewer fields, and vice versa,     */
-/* client could use newer gc.h (with more entries declared in the       */
-/* structure) than that of the linked libgc binary; in the latter case, */
-/* unsupported (unknown) fields are filled in with -1.  Return the size */
-/* (in bytes) of the filled in part of the structure (excluding all     */
-/* unknown fields, if any).                                             */
-GC_API size_t GC_CALL GC_get_prof_stats(struct GC_prof_stats_s *,
-                                        size_t /* stats_sz */);
-#ifdef GC_THREADS
-  /* Same as above but unsynchronized (i.e., not holding the allocation */
-  /* lock).  Clients should call it using GC_call_with_alloc_lock to    */
-  /* avoid data races on multiprocessors.                               */
-  GC_API size_t GC_CALL GC_get_prof_stats_unsafe(struct GC_prof_stats_s *,
-                                                 size_t /* stats_sz */);
-#endif
-
-/* Get the element value (converted to bytes) at a given index of       */
-/* size_map table which provides requested-to-actual allocation size    */
-/* mapping.  Assumes the collector is initialized.  Returns -1 if the   */
-/* index is out of size_map table bounds. Does not use synchronization, */
-/* thus clients should call it using GC_call_with_alloc_lock typically  */
-/* to avoid data races on multiprocessors.                              */
-GC_API size_t GC_CALL GC_get_size_map_at(int i);
-
-/* Count total memory use in bytes by all allocated blocks.  Acquires   */
-/* the lock.                                                            */
-GC_API size_t GC_CALL GC_get_memory_use(void);
-
-/* Disable garbage collection.  Even GC_gcollect calls will be          */
-/* ineffective.                                                         */
-GC_API void GC_CALL GC_disable(void);
-
-/* Return non-zero (TRUE) if and only if garbage collection is disabled */
-/* (i.e., GC_dont_gc value is non-zero).  Does not acquire the lock.    */
-GC_API int GC_CALL GC_is_disabled(void);
-
-/* Try to re-enable garbage collection.  GC_disable() and GC_enable()   */
-/* calls nest.  Garbage collection is enabled if the number of calls to */
-/* both functions is equal.                                             */
-GC_API void GC_CALL GC_enable(void);
-
-/* Select whether to use the manual VDB mode for the incremental        */
-/* collection.  Has no effect if called after enabling the incremental  */
-/* collection.  The default value is off unless the collector is        */
-/* compiled with MANUAL_VDB defined.  The manual VDB mode should be     */
-/* used only if the client has the appropriate GC_END_STUBBORN_CHANGE   */
-/* and GC_reachable_here (or, alternatively, GC_PTR_STORE_AND_DIRTY)    */
-/* calls (to ensure proper write barriers).  Both the setter and getter */
-/* are not synchronized, and are defined only if the library has been   */
-/* compiled without SMALL_CONFIG.                                       */
-GC_API void GC_CALL GC_set_manual_vdb_allowed(int);
-GC_API int GC_CALL GC_get_manual_vdb_allowed(void);
-
-/* Enable incremental/generational collection.  Not advisable unless    */
-/* dirty bits are available or most heap objects are pointer-free       */
-/* (atomic) or immutable.  Don't use in leak finding mode.  Ignored if  */
-/* GC_dont_gc is non-zero.  Only the generational piece of this is      */
-/* functional if GC_time_limit is set to GC_TIME_UNLIMITED.  Causes     */
-/* thread-local variant of GC_gcj_malloc() to revert to locked          */
-/* allocation.  Must be called before any such GC_gcj_malloc() calls.   */
-/* For best performance, should be called as early as possible.         */
-/* On some platforms, calling it later may have adverse effects.        */
-/* Safe to call before GC_INIT().  Includes a  GC_init() call.          */
-GC_API void GC_CALL GC_enable_incremental(void);
-
-/* Return non-zero (TRUE) if and only if the incremental mode is on.    */
-/* Does not acquire the lock.                                           */
-GC_API int GC_CALL GC_is_incremental_mode(void);
-
-/* Does incremental mode write-protect pages?  Returns zero or  */
-/* more of the following, or'ed together:                       */
-#define GC_PROTECTS_POINTER_HEAP  1 /* May protect non-atomic objects.  */
-#define GC_PROTECTS_PTRFREE_HEAP  2
-#define GC_PROTECTS_STATIC_DATA   4 /* Currently never.                 */
-#define GC_PROTECTS_STACK         8 /* Probably impractical.            */
-
-#define GC_PROTECTS_NONE 0
-/* The collector is assumed to be initialized before this call.         */
-GC_API int GC_CALL GC_incremental_protection_needs(void);
-
-/* Perform some garbage collection work, if appropriate.        */
-/* Return 0 if there is no more work to be done (including the  */
-/* case when garbage collection is not appropriate).            */
-/* Typically performs an amount of work corresponding roughly   */
-/* to marking from one page.  May do more work if further       */
-/* progress requires it, e.g. if incremental collection is      */
-/* disabled.  It is reasonable to call this in a wait loop      */
-/* until it returns 0.                                          */
-GC_API int GC_CALL GC_collect_a_little(void);
-
-/* Allocate an object of size lb bytes.  The client guarantees that     */
-/* as long as the object is live, it will be referenced by a pointer    */
-/* that points to somewhere within the first 256 bytes of the object.   */
-/* (This should normally be declared volatile to prevent the compiler   */
-/* from invalidating this assertion.)  This routine is only useful      */
-/* if a large array is being allocated.  It reduces the chance of       */
-/* accidentally retaining such an array as a result of scanning an      */
-/* integer that happens to be an address inside the array.  (Actually,  */
-/* it reduces the chance of the allocator not finding space for such    */
-/* an array, since it will try hard to avoid introducing such a false   */
-/* reference.)  On a SunOS 4.X or MS Windows system this is recommended */
-/* for arrays likely to be larger than 100 KB or so.  For other systems,*/
-/* or if the collector is not configured to recognize all interior      */
-/* pointers, the threshold is normally much higher.                     */
-GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
-        GC_malloc_ignore_off_page(size_t /* lb */);
-GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
-        GC_malloc_atomic_ignore_off_page(size_t /* lb */);
-
-#ifdef GC_ADD_CALLER
-# define GC_EXTRAS GC_RETURN_ADDR, __FILE__, __LINE__
-# define GC_EXTRA_PARAMS GC_word ra, const char * s, int i
-#else
-# define GC_EXTRAS __FILE__, __LINE__
-# define GC_EXTRA_PARAMS const char * s, int i
-#endif
-
-/* The following is only defined if the library has been suitably       */
-/* compiled:                                                            */
-GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
-        GC_malloc_atomic_uncollectable(size_t /* size_in_bytes */);
-GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
-        GC_debug_malloc_atomic_uncollectable(size_t, GC_EXTRA_PARAMS);
-
-/* Debugging (annotated) allocation.  GC_gcollect will check            */
-/* objects allocated in this way for overwrites, etc.                   */
-GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
-        GC_debug_malloc(size_t /* size_in_bytes */, GC_EXTRA_PARAMS);
-GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
-        GC_debug_malloc_atomic(size_t /* size_in_bytes */, GC_EXTRA_PARAMS);
-GC_API GC_ATTR_MALLOC char * GC_CALL
-        GC_debug_strdup(const char *, GC_EXTRA_PARAMS);
-GC_API GC_ATTR_MALLOC char * GC_CALL
-        GC_debug_strndup(const char *, size_t, GC_EXTRA_PARAMS)
-                                                        GC_ATTR_NONNULL(1);
-GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
-        GC_debug_malloc_uncollectable(size_t /* size_in_bytes */,
-                                      GC_EXTRA_PARAMS);
-GC_API GC_ATTR_DEPRECATED void * GC_CALL
-        GC_debug_malloc_stubborn(size_t /* size_in_bytes */, GC_EXTRA_PARAMS);
-GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
-        GC_debug_malloc_ignore_off_page(size_t /* size_in_bytes */,
-                                        GC_EXTRA_PARAMS);
-GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
-        GC_debug_malloc_atomic_ignore_off_page(size_t /* size_in_bytes */,
-                                        GC_EXTRA_PARAMS);
-GC_API void GC_CALL GC_debug_free(void *);
-GC_API void * GC_CALL GC_debug_realloc(void * /* old_object */,
-                        size_t /* new_size_in_bytes */, GC_EXTRA_PARAMS)
-                        /* 'realloc' attr */ GC_ATTR_ALLOC_SIZE(2);
-GC_API GC_ATTR_DEPRECATED void GC_CALL GC_debug_change_stubborn(const void *);
-GC_API void GC_CALL GC_debug_end_stubborn_change(const void *)
-                                                        GC_ATTR_NONNULL(1);
-
-/* Routines that allocate objects with debug information (like the      */
-/* above), but just fill in dummy file and line number information.     */
-/* Thus they can serve as drop-in malloc/realloc replacements.  This    */
-/* can be useful for two reasons:                                       */
-/* 1) It allows the collector to be built with DBG_HDRS_ALL defined     */
-/*    even if some allocation calls come from 3rd party libraries       */
-/*    that can't be recompiled.                                         */
-/* 2) On some platforms, the file and line information is redundant,    */
-/*    since it can be reconstructed from a stack trace.  On such        */
-/*    platforms it may be more convenient not to recompile, e.g. for    */
-/*    leak detection.  This can be accomplished by instructing the      */
-/*    linker to replace malloc/realloc with these.                      */
-GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
-        GC_debug_malloc_replacement(size_t /* size_in_bytes */);
-GC_API /* 'realloc' attr */ GC_ATTR_ALLOC_SIZE(2) void * GC_CALL
-        GC_debug_realloc_replacement(void * /* object_addr */,
-                                     size_t /* size_in_bytes */);
-
-#ifdef GC_DEBUG_REPLACEMENT
-# define GC_MALLOC(sz) GC_debug_malloc_replacement(sz)
-# define GC_REALLOC(old, sz) GC_debug_realloc_replacement(old, sz)
-#elif defined(GC_DEBUG)
-# define GC_MALLOC(sz) GC_debug_malloc(sz, GC_EXTRAS)
-# define GC_REALLOC(old, sz) GC_debug_realloc(old, sz, GC_EXTRAS)
-#else
-# define GC_MALLOC(sz) GC_malloc(sz)
-# define GC_REALLOC(old, sz) GC_realloc(old, sz)
-#endif /* !GC_DEBUG_REPLACEMENT && !GC_DEBUG */
-
-#ifdef GC_DEBUG
-# define GC_MALLOC_ATOMIC(sz) GC_debug_malloc_atomic(sz, GC_EXTRAS)
-# define GC_STRDUP(s) GC_debug_strdup(s, GC_EXTRAS)
-# define GC_STRNDUP(s, sz) GC_debug_strndup(s, sz, GC_EXTRAS)
-# define GC_MALLOC_ATOMIC_UNCOLLECTABLE(sz) \
-                        GC_debug_malloc_atomic_uncollectable(sz, GC_EXTRAS)
-# define GC_MALLOC_UNCOLLECTABLE(sz) \
-                        GC_debug_malloc_uncollectable(sz, GC_EXTRAS)
-# define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
-                        GC_debug_malloc_ignore_off_page(sz, GC_EXTRAS)
-# define GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(sz) \
-                        GC_debug_malloc_atomic_ignore_off_page(sz, GC_EXTRAS)
-# define GC_FREE(p) GC_debug_free(p)
-# define GC_REGISTER_FINALIZER(p, f, d, of, od) \
-      GC_debug_register_finalizer(p, f, d, of, od)
-# define GC_REGISTER_FINALIZER_IGNORE_SELF(p, f, d, of, od) \
-      GC_debug_register_finalizer_ignore_self(p, f, d, of, od)
-# define GC_REGISTER_FINALIZER_NO_ORDER(p, f, d, of, od) \
-      GC_debug_register_finalizer_no_order(p, f, d, of, od)
-# define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \
-      GC_debug_register_finalizer_unreachable(p, f, d, of, od)
-# define GC_END_STUBBORN_CHANGE(p) GC_debug_end_stubborn_change(p)
-# define GC_PTR_STORE_AND_DIRTY(p, q) GC_debug_ptr_store_and_dirty(p, q)
-# define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \
-      GC_general_register_disappearing_link(link, \
-                                        GC_base((/* no const */ void *)(obj)))
-# define GC_REGISTER_LONG_LINK(link, obj) \
-      GC_register_long_link(link, GC_base((/* no const */ void *)(obj)))
-# define GC_REGISTER_DISPLACEMENT(n) GC_debug_register_displacement(n)
-#else
-# define GC_MALLOC_ATOMIC(sz) GC_malloc_atomic(sz)
-# define GC_STRDUP(s) GC_strdup(s)
-# define GC_STRNDUP(s, sz) GC_strndup(s, sz)
-# define GC_MALLOC_ATOMIC_UNCOLLECTABLE(sz) GC_malloc_atomic_uncollectable(sz)
-# define GC_MALLOC_UNCOLLECTABLE(sz) GC_malloc_uncollectable(sz)
-# define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
-                        GC_malloc_ignore_off_page(sz)
-# define GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(sz) \
-                        GC_malloc_atomic_ignore_off_page(sz)
-# define GC_FREE(p) GC_free(p)
-# define GC_REGISTER_FINALIZER(p, f, d, of, od) \
-      GC_register_finalizer(p, f, d, of, od)
-# define GC_REGISTER_FINALIZER_IGNORE_SELF(p, f, d, of, od) \
-      GC_register_finalizer_ignore_self(p, f, d, of, od)
-# define GC_REGISTER_FINALIZER_NO_ORDER(p, f, d, of, od) \
-      GC_register_finalizer_no_order(p, f, d, of, od)
-# define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \
-      GC_register_finalizer_unreachable(p, f, d, of, od)
-# define GC_END_STUBBORN_CHANGE(p) GC_end_stubborn_change(p)
-# define GC_PTR_STORE_AND_DIRTY(p, q) GC_ptr_store_and_dirty(p, q)
-# define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \
-      GC_general_register_disappearing_link(link, obj)
-# define GC_REGISTER_LONG_LINK(link, obj) \
-      GC_register_long_link(link, obj)
-# define GC_REGISTER_DISPLACEMENT(n) GC_register_displacement(n)
-#endif /* !GC_DEBUG */
-
-/* The following are included because they are often convenient, and    */
-/* reduce the chance for a misspecified size argument.  But calls may   */
-/* expand to something syntactically incorrect if t is a complicated    */
-/* type expression.  Note that, unlike C++ new operator, these ones     */
-/* may return NULL (if out of memory).                                  */
-#define GC_NEW(t)               ((t*)GC_MALLOC(sizeof(t)))
-#define GC_NEW_ATOMIC(t)        ((t*)GC_MALLOC_ATOMIC(sizeof(t)))
-#define GC_NEW_UNCOLLECTABLE(t) ((t*)GC_MALLOC_UNCOLLECTABLE(sizeof(t)))
-
-#ifdef GC_REQUIRE_WCSDUP
-  /* This might be unavailable on some targets (or not needed). */
-  /* wchar_t should be defined in stddef.h */
-  GC_API GC_ATTR_MALLOC wchar_t * GC_CALL
-        GC_wcsdup(const wchar_t *) GC_ATTR_NONNULL(1);
-  GC_API GC_ATTR_MALLOC wchar_t * GC_CALL
-        GC_debug_wcsdup(const wchar_t *, GC_EXTRA_PARAMS) GC_ATTR_NONNULL(1);
-# ifdef GC_DEBUG
-#   define GC_WCSDUP(s) GC_debug_wcsdup(s, GC_EXTRAS)
-# else
-#   define GC_WCSDUP(s) GC_wcsdup(s)
-# endif
-#endif /* GC_REQUIRE_WCSDUP */
-
-/* Finalization.  Some of these primitives are grossly unsafe.          */
-/* The idea is to make them both cheap, and sufficient to build         */
-/* a safer layer, closer to Modula-3, Java, or PCedar finalization.     */
-/* The interface represents my conclusions from a long discussion       */
-/* with Alan Demers, Dan Greene, Carl Hauser, Barry Hayes,              */
-/* Christian Jacobi, and Russ Atkinson.  It's not perfect, and          */
-/* probably nobody else agrees with it.     Hans-J. Boehm  3/13/92      */
-typedef void (GC_CALLBACK * GC_finalization_proc)(void * /* obj */,
-                                                  void * /* client_data */);
-
-GC_API void GC_CALL GC_register_finalizer(void * /* obj */,
-                        GC_finalization_proc /* fn */, void * /* cd */,
-                        GC_finalization_proc * /* ofn */, void ** /* ocd */)
-                                                GC_ATTR_NONNULL(1);
-GC_API void GC_CALL GC_debug_register_finalizer(void * /* obj */,
-                        GC_finalization_proc /* fn */, void * /* cd */,
-                        GC_finalization_proc * /* ofn */, void ** /* ocd */)
-                                                GC_ATTR_NONNULL(1);
-        /* When obj is no longer accessible, invoke             */
-        /* (*fn)(obj, cd).  If a and b are inaccessible, and    */
-        /* a points to b (after disappearing links have been    */
-        /* made to disappear), then only a will be              */
-        /* finalized.  (If this does not create any new         */
-        /* pointers to b, then b will be finalized after the    */
-        /* next collection.)  Any finalizable object that       */
-        /* is reachable from itself by following one or more    */
-        /* pointers will not be finalized (or collected).       */
-        /* Thus cycles involving finalizable objects should     */
-        /* be avoided, or broken by disappearing links.         */
-        /* All but the last finalizer registered for an object  */
-        /* is ignored.                                          */
-        /* No-op in the leak-finding mode.                      */
-        /* Finalization may be removed by passing 0 as fn.      */
-        /* Finalizers are implicitly unregistered when they are */
-        /* enqueued for finalization (i.e. become ready to be   */
-        /* finalized).                                          */
-        /* The old finalizer and client data are stored in      */
-        /* *ofn and *ocd.  (ofn and/or ocd may be NULL.         */
-        /* The allocation lock is held while *ofn and *ocd are  */
-        /* updated.  In case of error (no memory to register    */
-        /* new finalizer), *ofn and *ocd remain unchanged.)     */
-        /* Fn is never invoked on an accessible object,         */
-        /* provided hidden pointers are converted to real       */
-        /* pointers only if the allocation lock is held, and    */
-        /* such conversions are not performed by finalization   */
-        /* routines.                                            */
-        /* If GC_register_finalizer is aborted as a result of   */
-        /* a signal, the object may be left with no             */
-        /* finalization, even if neither the old nor new        */
-        /* finalizer were NULL.                                 */
-        /* Obj should be the starting address of an object      */
-        /* allocated by GC_malloc or friends. Obj may also be   */
-        /* NULL or point to something outside GC heap (in this  */
-        /* case, fn is ignored, *ofn and *ocd are set to NULL). */
-        /* Note that any garbage collectible object referenced  */
-        /* by cd will be considered accessible until the        */
-        /* finalizer is invoked.                                */
-
-/* Another versions of the above follow.  It ignores            */
-/* self-cycles, i.e. pointers from a finalizable object to      */
-/* itself.  There is a stylistic argument that this is wrong,   */
-/* but it's unavoidable for C++, since the compiler may         */
-/* silently introduce these.  It's also benign in that specific */
-/* case.  And it helps if finalizable objects are split to      */
-/* avoid cycles.                                                */
-/* Note that cd will still be viewed as accessible, even if it  */
-/* refers to the object itself.                                 */
-GC_API void GC_CALL GC_register_finalizer_ignore_self(void * /* obj */,
-                        GC_finalization_proc /* fn */, void * /* cd */,
-                        GC_finalization_proc * /* ofn */, void ** /* ocd */)
-                                                GC_ATTR_NONNULL(1);
-GC_API void GC_CALL GC_debug_register_finalizer_ignore_self(void * /* obj */,
-                        GC_finalization_proc /* fn */, void * /* cd */,
-                        GC_finalization_proc * /* ofn */, void ** /* ocd */)
-                                                GC_ATTR_NONNULL(1);
-
-/* Another version of the above.  It ignores all cycles.        */
-/* It should probably only be used by Java implementations.     */
-/* Note that cd will still be viewed as accessible, even if it  */
-/* refers to the object itself.                                 */
-GC_API void GC_CALL GC_register_finalizer_no_order(void * /* obj */,
-                        GC_finalization_proc /* fn */, void * /* cd */,
-                        GC_finalization_proc * /* ofn */, void ** /* ocd */)
-                                                GC_ATTR_NONNULL(1);
-GC_API void GC_CALL GC_debug_register_finalizer_no_order(void * /* obj */,
-                        GC_finalization_proc /* fn */, void * /* cd */,
-                        GC_finalization_proc * /* ofn */, void ** /* ocd */)
-                                                GC_ATTR_NONNULL(1);
-
-/* This is a special finalizer that is useful when an object's  */
-/* finalizer must be run when the object is known to be no      */
-/* longer reachable, not even from other finalizable objects.   */
-/* It behaves like "normal" finalization, except that the       */
-/* finalizer is not run while the object is reachable from      */
-/* other objects specifying unordered finalization.             */
-/* Effectively it allows an object referenced, possibly         */
-/* indirectly, from an unordered finalizable object to override */
-/* the unordered finalization request.                          */
-/* This can be used in combination with finalizer_no_order so   */
-/* as to release resources that must not be released while an   */
-/* object can still be brought back to life by other            */
-/* finalizers.                                                  */
-/* Only works if GC_java_finalization is set.  Probably only    */
-/* of interest when implementing a language that requires       */
-/* unordered finalization (e.g. Java, C#).                      */
-GC_API void GC_CALL GC_register_finalizer_unreachable(void * /* obj */,
-                        GC_finalization_proc /* fn */, void * /* cd */,
-                        GC_finalization_proc * /* ofn */, void ** /* ocd */)
-                                                GC_ATTR_NONNULL(1);
-GC_API void GC_CALL GC_debug_register_finalizer_unreachable(void * /* obj */,
-                        GC_finalization_proc /* fn */, void * /* cd */,
-                        GC_finalization_proc * /* ofn */, void ** /* ocd */)
-                                                GC_ATTR_NONNULL(1);
-
-#define GC_NO_MEMORY 2  /* Failure due to lack of memory.       */
-
-/* The following routine may be used to break cycles between    */
-/* finalizable objects, thus causing cyclic finalizable         */
-/* objects to be finalized in the correct order.  Standard      */
-/* use involves calling GC_register_disappearing_link(&p),      */
-/* where p is a pointer that is not followed by finalization    */
-/* code, and should not be considered in determining            */
-/* finalization order.                                          */
-GC_API int GC_CALL GC_register_disappearing_link(void ** /* link */)
-                                                GC_ATTR_NONNULL(1);
-        /* Link should point to a field of a heap allocated     */
-        /* object obj.  *link will be cleared when obj is       */
-        /* found to be inaccessible.  This happens BEFORE any   */
-        /* finalization code is invoked, and BEFORE any         */
-        /* decisions about finalization order are made.         */
-        /* This is useful in telling the finalizer that         */
-        /* some pointers are not essential for proper           */
-        /* finalization.  This may avoid finalization cycles.   */
-        /* Note that obj may be resurrected by another          */
-        /* finalizer, and thus the clearing of *link may        */
-        /* be visible to non-finalization code.                 */
-        /* There's an argument that an arbitrary action should  */
-        /* be allowed here, instead of just clearing a pointer. */
-        /* But this causes problems if that action alters, or   */
-        /* examines connectivity.  Returns GC_DUPLICATE if link */
-        /* was already registered, GC_SUCCESS if registration   */
-        /* succeeded, GC_NO_MEMORY if it failed for lack of     */
-        /* memory, and GC_oom_fn did not handle the problem.    */
-        /* Only exists for backward compatibility.  See below:  */
-
-GC_API int GC_CALL GC_general_register_disappearing_link(void ** /* link */,
-                                                    const void * /* obj */)
-                        GC_ATTR_NONNULL(1) GC_ATTR_NONNULL(2);
-        /* A slight generalization of the above. *link is       */
-        /* cleared when obj first becomes inaccessible.  This   */
-        /* can be used to implement weak pointers easily and    */
-        /* safely. Typically link will point to a location      */
-        /* holding a disguised pointer to obj.  (A pointer      */
-        /* inside an "atomic" object is effectively disguised.) */
-        /* In this way, weak pointers are broken before any     */
-        /* object reachable from them gets finalized.           */
-        /* Each link may be registered only with one obj value, */
-        /* i.e. all objects but the last one (link registered   */
-        /* with) are ignored.  This was added after a long      */
-        /* email discussion with John Ellis.                    */
-        /* link must be non-NULL (and be properly aligned).     */
-        /* obj must be a pointer to the first word of an object */
-        /* allocated by GC_malloc or friends.   A link          */
-        /* disappears when it is unregistered manually, or when */
-        /* (*link) is cleared, or when the object containing    */
-        /* this link is garbage collected.  It is unsafe to     */
-        /* explicitly deallocate the object containing link.    */
-        /* Explicit deallocation of obj may or may not cause    */
-        /* link to eventually be cleared.                       */
-        /* No-op in the leak-finding mode.                      */
-        /* This function can be used to implement certain types */
-        /* of weak pointers.  Note, however, this generally     */
-        /* requires that the allocation lock is held (see       */
-        /* GC_call_with_alloc_lock() below) when the disguised  */
-        /* pointer is accessed.  Otherwise a strong pointer     */
-        /* could be recreated between the time the collector    */
-        /* decides to reclaim the object and the link is        */
-        /* cleared.  Returns GC_SUCCESS if registration         */
-        /* succeeded (a new link is registered), GC_DUPLICATE   */
-        /* if link was already registered (with some object),   */
-        /* GC_NO_MEMORY if registration failed for lack of      */
-        /* memory (and GC_oom_fn did not handle the problem),   */
-        /* GC_UNIMPLEMENTED if GC_find_leak is true.            */
-
-GC_API int GC_CALL GC_move_disappearing_link(void ** /* link */,
-                                             void ** /* new_link */)
-                        GC_ATTR_NONNULL(2);
-        /* Moves a link previously registered via               */
-        /* GC_general_register_disappearing_link (or            */
-        /* GC_register_disappearing_link).  Does not change the */
-        /* target object of the weak reference.  Does not       */
-        /* change (*new_link) content.  May be called with      */
-        /* new_link equal to link (to check whether link has    */
-        /* been registered).  Returns GC_SUCCESS on success,    */
-        /* GC_DUPLICATE if there is already another             */
-        /* disappearing link at the new location (never         */
-        /* returned if new_link is equal to link), GC_NOT_FOUND */
-        /* if no link is registered at the original location.   */
-
-GC_API int GC_CALL GC_unregister_disappearing_link(void ** /* link */);
-        /* Undoes a registration by either of the above two     */
-        /* routines.  Returns 0 if link was not actually        */
-        /* registered (otherwise returns 1).                    */
-
-GC_API int GC_CALL GC_register_long_link(void ** /* link */,
-                                    const void * /* obj */)
-                        GC_ATTR_NONNULL(1) GC_ATTR_NONNULL(2);
-        /* Similar to GC_general_register_disappearing_link but */
-        /* *link only gets cleared when obj becomes truly       */
-        /* inaccessible.  An object becomes truly inaccessible  */
-        /* when it can no longer be resurrected from its        */
-        /* finalizer (e.g. by assigning itself to a pointer     */
-        /* traceable from root).  This can be used to implement */
-        /* long weak pointers easily and safely.                */
-
-GC_API int GC_CALL GC_move_long_link(void ** /* link */,
-                                     void ** /* new_link */)
-                        GC_ATTR_NONNULL(2);
-        /* Similar to GC_move_disappearing_link but for a link  */
-        /* previously registered via GC_register_long_link.     */
-
-GC_API int GC_CALL GC_unregister_long_link(void ** /* link */);
-        /* Similar to GC_unregister_disappearing_link but for a */
-        /* registration by either of the above two routines.    */
-
-/* Support of toggle-ref style of external memory management    */
-/* without hooking up to the host retain/release machinery.     */
-/* The idea of toggle-ref is that an external reference to      */
-/* an object is kept and it can be either a strong or weak      */
-/* reference; a weak reference is used when the external peer   */
-/* has no interest in the object, and a strong otherwise.       */
-typedef enum {
-   GC_TOGGLE_REF_DROP,
-   GC_TOGGLE_REF_STRONG,
-   GC_TOGGLE_REF_WEAK
-} GC_ToggleRefStatus;
-
-/* The callback is to decide (return) the new state of a given  */
-/* object.  Invoked by the collector for all objects registered */
-/* for toggle-ref processing.  Invoked with the allocation lock */
-/* held (but the "world" is running).                           */
-typedef GC_ToggleRefStatus (GC_CALLBACK *GC_toggleref_func)(void * /* obj */);
-
-/* Set (register) a callback that decides the state of a given  */
-/* object (by, probably, inspecting its native state).          */
-/* The argument may be 0 (means no callback).  Both the setter  */
-/* and the getter acquire the allocation lock (to avoid data    */
-/* races).                                                      */
-GC_API void GC_CALL GC_set_toggleref_func(GC_toggleref_func);
-GC_API GC_toggleref_func GC_CALL GC_get_toggleref_func(void);
-
-/* Register a given object for toggle-ref processing.  It will  */
-/* be stored internally and the toggle-ref callback will be     */
-/* invoked on the object until the callback returns             */
-/* GC_TOGGLE_REF_DROP or the object is collected.  If is_strong */
-/* is true then the object is registered with a strong ref,     */
-/* a weak one otherwise.  Returns GC_SUCCESS if registration    */
-/* succeeded (or no callback registered yet), GC_NO_MEMORY if   */
-/* it failed for lack of memory.                                */
-GC_API int GC_CALL GC_toggleref_add(void * /* obj */, int /* is_strong */)
-                                                GC_ATTR_NONNULL(1);
-
-/* Finalizer callback support.  Invoked by the collector (with  */
-/* the allocation lock held) for each unreachable object        */
-/* enqueued for finalization.                                   */
-typedef void (GC_CALLBACK * GC_await_finalize_proc)(void * /* obj */);
-GC_API void GC_CALL GC_set_await_finalize_proc(GC_await_finalize_proc);
-GC_API GC_await_finalize_proc GC_CALL GC_get_await_finalize_proc(void);
-                        /* Zero means no callback.  The setter  */
-                        /* and getter acquire the lock too.     */
-
-/* Returns !=0 if GC_invoke_finalizers has something to do.     */
-/* Does not use any synchronization.                            */
-GC_API int GC_CALL GC_should_invoke_finalizers(void);
-
-GC_API int GC_CALL GC_invoke_finalizers(void);
-        /* Run finalizers for all objects that are ready to     */
-        /* be finalized.  Return the number of finalizers       */
-        /* that were run.  Normally this is also called         */
-        /* implicitly during some allocations.  If              */
-        /* GC_finalize_on_demand is nonzero, it must be called  */
-        /* explicitly.                                          */
-
-/* Explicitly tell the collector that an object is reachable    */
-/* at a particular program point.  This prevents the argument   */
-/* pointer from being optimized away, even it is otherwise no   */
-/* longer needed.  It should have no visible effect in the      */
-/* absence of finalizers or disappearing links.  But it may be  */
-/* needed to prevent finalizers from running while the          */
-/* associated external resource is still in use.                */
-/* The function is sometimes called keep_alive in other         */
-/* settings.                                                    */
-#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
-# define GC_reachable_here(ptr) \
-                __asm__ __volatile__(" " : : "X"(ptr) : "memory")
-#else
-  GC_API void GC_CALL GC_noop1(GC_word);
-# ifdef LINT2
-#   define GC_reachable_here(ptr) GC_noop1(~(GC_word)(ptr)^(~(GC_word)0))
-                /* The expression matches the one of COVERT_DATAFLOW(). */
-# else
-#   define GC_reachable_here(ptr) GC_noop1((GC_word)(ptr))
-# endif
-#endif
-
-/* GC_set_warn_proc can be used to redirect or filter warning messages. */
-/* p may not be a NULL pointer.  msg is printf format string (arg must  */
-/* match the format).  Both the setter and the getter acquire the GC    */
-/* lock (to avoid data races).  In GC v7.1 (and before), the setter     */
-/* returned the old warn_proc value.                                    */
-typedef void (GC_CALLBACK * GC_warn_proc)(char * /* msg */,
-                                          GC_word /* arg */);
-GC_API void GC_CALL GC_set_warn_proc(GC_warn_proc /* p */) GC_ATTR_NONNULL(1);
-/* GC_get_warn_proc returns the current warn_proc.                      */
-GC_API GC_warn_proc GC_CALL GC_get_warn_proc(void);
-
-/* GC_ignore_warn_proc may be used as an argument for GC_set_warn_proc  */
-/* to suppress all warnings (unless statistics printing is turned on).  */
-GC_API void GC_CALLBACK GC_ignore_warn_proc(char *, GC_word);
-
-/* Change file descriptor of GC log.  Unavailable on some targets.      */
-GC_API void GC_CALL GC_set_log_fd(int);
-
-/* abort_func is invoked on GC fatal aborts (just before OS-dependent   */
-/* abort or exit(1) is called).  Must be non-NULL.  The default one     */
-/* outputs msg to stderr provided msg is non-NULL.  msg is NULL if      */
-/* invoked before exit(1) otherwise msg is non-NULL (i.e., if invoked   */
-/* before abort).  Both the setter and getter acquire the GC lock.      */
-/* Both the setter and getter are defined only if the library has been  */
-/* compiled without SMALL_CONFIG.                                       */
-typedef void (GC_CALLBACK * GC_abort_func)(const char * /* msg */);
-GC_API void GC_CALL GC_set_abort_func(GC_abort_func) GC_ATTR_NONNULL(1);
-GC_API GC_abort_func GC_CALL GC_get_abort_func(void);
-
-/* A portable way to abort the application because of not enough memory.*/
-GC_API void GC_CALL GC_abort_on_oom(void);
-
-/* The following is intended to be used by a higher level       */
-/* (e.g. Java-like) finalization facility.  It is expected      */
-/* that finalization code will arrange for hidden pointers to   */
-/* disappear.  Otherwise objects can be accessed after they     */
-/* have been collected.                                         */
-/* Should not be used in the leak-finding mode.                 */
-/* Note that putting pointers in atomic objects or in           */
-/* non-pointer slots of "typed" objects is equivalent to        */
-/* disguising them in this way, and may have other advantages.  */
-typedef GC_word GC_hidden_pointer;
-#define GC_HIDE_POINTER(p) (~(GC_hidden_pointer)(p))
-/* Converting a hidden pointer to a real pointer requires verifying     */
-/* that the object still exists.  This involves acquiring the           */
-/* allocator lock to avoid a race with the collector.                   */
-#define GC_REVEAL_POINTER(p) ((void *)GC_HIDE_POINTER(p))
-
-#if defined(I_HIDE_POINTERS) || defined(GC_I_HIDE_POINTERS)
-  /* This exists only for compatibility (the GC-prefixed symbols are    */
-  /* preferred for new code).                                           */
-# define HIDE_POINTER(p) GC_HIDE_POINTER(p)
-# define REVEAL_POINTER(p) GC_REVEAL_POINTER(p)
-#endif
-
-/* The routines to acquire/release the allocator lock.                  */
-/* The lock is not reentrant.  GC_alloc_unlock() should not be called   */
-/* unless the lock is acquired by the current thread.                   */
-#ifdef GC_THREADS
-  GC_API void GC_CALL GC_alloc_lock(void);
-  GC_API void GC_CALL GC_alloc_unlock(void);
-#else
-  /* No need for real locking if the client is single-threaded.         */
-# define GC_alloc_lock() (void)0
-# define GC_alloc_unlock() (void)0
-#endif /* !GC_THREADS */
-
-typedef void * (GC_CALLBACK * GC_fn_type)(void * /* client_data */);
-GC_API void * GC_CALL GC_call_with_alloc_lock(GC_fn_type /* fn */,
-                                void * /* client_data */) GC_ATTR_NONNULL(1);
-
-/* These routines are intended to explicitly notify the collector       */
-/* of new threads.  Often this is unnecessary because thread creation   */
-/* is implicitly intercepted by the collector, using header-file        */
-/* defines, or linker-based interception.  In the long run the intent   */
-/* is to always make redundant registration safe.  In the short run,    */
-/* this is being implemented a platform at a time.                      */
-/* The interface is complicated by the fact that we probably will not   */
-/* ever be able to automatically determine the stack bottom for thread  */
-/* stacks on all platforms.                                             */
-
-/* Structure representing the bottom (cold end) of a thread stack.      */
-/* On most platforms this contains just a single address.               */
-struct GC_stack_base {
-  void * mem_base;      /* the bottom of the general-purpose stack */
-# if defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
-    void * reg_base;    /* the bottom of the register stack */
-# endif
-};
-
-typedef void * (GC_CALLBACK * GC_stack_base_func)(
-                struct GC_stack_base * /* sb */, void * /* arg */);
-
-/* Call a function with a stack base structure corresponding to         */
-/* somewhere in the GC_call_with_stack_base frame.  This often can      */
-/* be used to provide a sufficiently accurate stack bottom.  And we     */
-/* implement it everywhere.                                             */
-GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func /* fn */,
-                                        void * /* arg */) GC_ATTR_NONNULL(1);
-
-#define GC_SUCCESS 0
-#define GC_DUPLICATE 1          /* Was already registered.              */
-#define GC_NO_THREADS 2         /* No thread support in GC.             */
-        /* GC_NO_THREADS is not returned by any GC function anymore.    */
-#define GC_UNIMPLEMENTED 3 /* Not yet implemented on this platform.     */
-#define GC_NOT_FOUND 4          /* Requested link not found (returned   */
-                                /* by GC_move_disappearing_link).       */
-
-#if defined(GC_DARWIN_THREADS) || defined(GC_WIN32_THREADS)
-  /* Use implicit thread registration and processing (via Win32 DllMain */
-  /* or Darwin task_threads).  Deprecated.  Must be called before       */
-  /* GC_INIT() and other GC routines.  Should be avoided if             */
-  /* GC_pthread_create, GC_beginthreadex (or GC_CreateThread) could be  */
-  /* called instead.  Disables parallelized GC on Win32.                */
-  GC_API void GC_CALL GC_use_threads_discovery(void);
-#endif
-
-#ifdef GC_THREADS
-  /* Suggest the GC to use the specific signal to suspend threads.      */
-  /* Has no effect after GC_init and on non-POSIX systems.              */
-  GC_API void GC_CALL GC_set_suspend_signal(int);
-
-  /* Suggest the GC to use the specific signal to resume threads.       */
-  /* Has no effect after GC_init and on non-POSIX systems.              */
-  GC_API void GC_CALL GC_set_thr_restart_signal(int);
-
-  /* Return the signal number (constant after initialization) used by   */
-  /* the GC to suspend threads on POSIX systems.  Return -1 otherwise.  */
-  GC_API int GC_CALL GC_get_suspend_signal(void);
-
-  /* Return the signal number (constant after initialization) used by   */
-  /* the garbage collector to restart (resume) threads on POSIX         */
-  /* systems.  Return -1 otherwise.                                     */
-  GC_API int GC_CALL GC_get_thr_restart_signal(void);
-
-  /* Restart marker threads after POSIX fork in child.  Meaningless in  */
-  /* other situations.  Should not be called if fork followed by exec.  */
-  GC_API void GC_CALL GC_start_mark_threads(void);
-
-  /* Explicitly enable GC_register_my_thread() invocation.              */
-  /* Done implicitly if a GC thread-creation function is called (or     */
-  /* implicit thread registration is activated, or the collector is     */
-  /* compiled with GC_ALWAYS_MULTITHREADED defined).  Otherwise, it     */
-  /* must be called from the main (or any previously registered) thread */
-  /* between the collector initialization and the first explicit        */
-  /* registering of a thread (it should be called as late as possible). */
-  GC_API void GC_CALL GC_allow_register_threads(void);
-
-  /* Register the current thread, with the indicated stack bottom, as   */
-  /* a new thread whose stack(s) should be traced by the GC.  If it     */
-  /* is not implicitly called by the GC, this must be called before a   */
-  /* thread can allocate garbage collected memory, or assign pointers   */
-  /* to the garbage collected heap.  Once registered, a thread will be  */
-  /* stopped during garbage collections.                                */
-  /* This call must be previously enabled (see above).                  */
-  /* This should never be called from the main thread, where it is      */
-  /* always done implicitly.  This is normally done implicitly if GC_   */
-  /* functions are called to create the thread, e.g. by including gc.h  */
-  /* (which redefines some system functions) before calling the system  */
-  /* thread creation function.  Nonetheless, thread cleanup routines    */
-  /* (e.g., pthread key destructor) typically require manual thread     */
-  /* registering (and unregistering) if pointers to GC-allocated        */
-  /* objects are manipulated inside.                                    */
-  /* It is also always done implicitly on some platforms if             */
-  /* GC_use_threads_discovery() is called at start-up.  Except for the  */
-  /* latter case, the explicit call is normally required for threads    */
-  /* created by third-party libraries.                                  */
-  /* A manually registered thread requires manual unregistering.        */
-  /* Returns GC_SUCCESS on success, GC_DUPLICATE if already registered. */
-  GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *)
-                                                        GC_ATTR_NONNULL(1);
-
-  /* Return non-zero (TRUE) if and only if the calling thread is        */
-  /* registered with the garbage collector.                             */
-  GC_API int GC_CALL GC_thread_is_registered(void);
-
-  /* Notify the collector about the stack and the alt-stack of the      */
-  /* current thread.  stack_start/size is used to determine the stack   */
-  /* boundaries when a thread is suspended while it is on an alt-stack. */
-  GC_API void GC_CALL GC_register_altstack(void * /* stack_start */,
-                                           GC_word /* stack_size */,
-                                           void * /* altstack_base */,
-                                           GC_word /* altstack_size */);
-
-  /* Unregister the current thread.  Only an explicitly registered      */
-  /* thread (i.e. for which GC_register_my_thread() returns GC_SUCCESS) */
-  /* is allowed (and required) to call this function.  (As a special    */
-  /* exception, it is also allowed to once unregister the main thread.) */
-  /* The thread may no longer allocate garbage collected memory or      */
-  /* manipulate pointers to the garbage collected heap after making     */
-  /* this call.  Specifically, if it wants to return or otherwise       */
-  /* communicate a pointer to the garbage-collected heap to another     */
-  /* thread, it must do this before calling GC_unregister_my_thread,    */
-  /* most probably by saving it in a global data structure.  Must not   */
-  /* be called inside a GC callback function (except for                */
-  /* GC_call_with_stack_base() one).                                    */
-  GC_API int GC_CALL GC_unregister_my_thread(void);
-
-  /* Stop/start the world explicitly.  Not recommended for general use. */
-  GC_API void GC_CALL GC_stop_world_external(void);
-  GC_API void GC_CALL GC_start_world_external(void);
-#endif /* GC_THREADS */
-
-/* Wrapper for functions that are likely to block (or, at least, do not */
-/* allocate garbage collected memory and/or manipulate pointers to the  */
-/* garbage collected heap) for an appreciable length of time.  While fn */
-/* is running, the collector is said to be in the "inactive" state for  */
-/* the current thread (this means that the thread is not suspended and  */
-/* the thread's stack frames "belonging" to the functions in the        */
-/* "inactive" state are not scanned during garbage collections).  It is */
-/* assumed that the collector is already initialized and the current    */
-/* thread is registered.  It is allowed for fn to call                  */
-/* GC_call_with_gc_active() (even recursively), thus temporarily        */
-/* toggling the collector's state back to "active".  The latter         */
-/* technique might be used to make stack scanning more precise (i.e.    */
-/* scan only stack frames of functions that allocate garbage collected  */
-/* memory and/or manipulate pointers to the garbage collected heap).    */
-GC_API void * GC_CALL GC_do_blocking(GC_fn_type /* fn */,
-                                void * /* client_data */) GC_ATTR_NONNULL(1);
-
-/* Call a function switching to the "active" state of the collector for */
-/* the current thread (i.e. the user function is allowed to call any    */
-/* GC function and/or manipulate pointers to the garbage collected      */
-/* heap).  GC_call_with_gc_active() has the functionality opposite to   */
-/* GC_do_blocking() one.  It is assumed that the collector is already   */
-/* initialized and the current thread is registered.  fn may toggle     */
-/* the collector thread's state temporarily to "inactive" one by using  */
-/* GC_do_blocking.  GC_call_with_gc_active() often can be used to       */
-/* provide a sufficiently accurate stack bottom.                        */
-GC_API void * GC_CALL GC_call_with_gc_active(GC_fn_type /* fn */,
-                                void * /* client_data */) GC_ATTR_NONNULL(1);
-
-/* Attempt to fill in the GC_stack_base structure with the stack bottom */
-/* for this thread.  This appears to be required to implement anything  */
-/* like the JNI AttachCurrentThread in an environment in which new      */
-/* threads are not automatically registered with the collector.         */
-/* It is also unfortunately hard to implement well on many platforms.   */
-/* Returns GC_SUCCESS or GC_UNIMPLEMENTED.  This function acquires the  */
-/* GC lock on some platforms.                                           */
-GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *)
-                                                        GC_ATTR_NONNULL(1);
-
-/* Fill in the GC_stack_base structure with the cold end (bottom) of    */
-/* the stack of the current thread (or coroutine).                      */
-/* Unlike GC_get_stack_base, it retrieves the value stored in the       */
-/* collector (which is initially set by the collector upon the thread   */
-/* is started or registered manually but it could be later updated by   */
-/* client using GC_set_stackbottom).  Returns the GC-internal non-NULL  */
-/* handle of the thread which could be passed to GC_set_stackbottom     */
-/* later.  It is assumed that the collector is already initialized and  */
-/* the thread is registered.  Acquires the GC lock to avoid data races. */
-GC_API void * GC_CALL GC_get_my_stackbottom(struct GC_stack_base *)
-                                                        GC_ATTR_NONNULL(1);
-
-/* Set the cool end of the user (coroutine) stack of the specified      */
-/* thread.  The GC thread handle is either the one returned by          */
-/* GC_get_my_stackbottom or NULL (the latter designates the current     */
-/* thread).  The caller should hold the GC lock (e.g. using             */
-/* GC_call_with_alloc_lock).  Also, the function could be used for      */
-/* setting GC_stackbottom value (the bottom of the primordial thread)   */
-/* before the collector is initialized (the GC lock is not needed to be */
-/* acquired in this case).                                              */
-GC_API void GC_CALL GC_set_stackbottom(void * /* gc_thread_handle */,
-                                       const struct GC_stack_base *)
-                                                        GC_ATTR_NONNULL(2);
-
-/* The following routines are primarily intended for use with a         */
-/* preprocessor which inserts calls to check C pointer arithmetic.      */
-/* They indicate failure by invoking the corresponding _print_proc.     */
-
-/* Check that p and q point to the same object.                 */
-/* Fail conspicuously if they don't.                            */
-/* Returns the first argument.                                  */
-/* Succeeds if neither p nor q points to the heap.              */
-/* May succeed if both p and q point to between heap objects.   */
-GC_API void * GC_CALL GC_same_obj(void * /* p */, void * /* q */);
-
-/* Checked pointer pre- and post- increment operations.  Note that      */
-/* the second argument is in units of bytes, not multiples of the       */
-/* object size.  This should either be invoked from a macro, or the     */
-/* call should be automatically generated.                              */
-GC_API void * GC_CALL GC_pre_incr(void **, ptrdiff_t /* how_much */)
-                                                        GC_ATTR_NONNULL(1);
-GC_API void * GC_CALL GC_post_incr(void **, ptrdiff_t /* how_much */)
-                                                        GC_ATTR_NONNULL(1);
-
-/* Check that p is visible                                              */
-/* to the collector as a possibly pointer containing location.          */
-/* If it isn't fail conspicuously.                                      */
-/* Returns the argument in all cases.  May erroneously succeed          */
-/* in hard cases.  (This is intended for debugging use with             */
-/* untyped allocations.  The idea is that it should be possible, though */
-/* slow, to add such a call to all indirect pointer stores.)            */
-/* Currently useless for multi-threaded worlds.                         */
-GC_API void * GC_CALL GC_is_visible(void * /* p */);
-
-/* Check that if p is a pointer to a heap page, then it points to       */
-/* a valid displacement within a heap object.                           */
-/* Fail conspicuously if this property does not hold.                   */
-/* Uninteresting with GC_all_interior_pointers.                         */
-/* Always returns its argument.                                         */
-GC_API void * GC_CALL GC_is_valid_displacement(void * /* p */);
-
-/* Explicitly dump the GC state.  This is most often called from the    */
-/* debugger, or by setting the GC_DUMP_REGULARLY environment variable,  */
-/* but it may be useful to call it from client code during debugging.   */
-/* The current collection number is printed in the header of the dump.  */
-/* Acquires the GC lock to avoid data races.                            */
-/* Defined only if the library has been compiled without NO_DEBUGGING.  */
-GC_API void GC_CALL GC_dump(void);
-
-/* The same as GC_dump but allows to specify the name of dump and does  */
-/* not acquire the lock.  If name is non-NULL, it is printed to help    */
-/* identifying individual dumps.  Otherwise the current collection      */
-/* number is used as the name.                                          */
-/* Defined only if the library has been compiled without NO_DEBUGGING.  */
-GC_API void GC_CALL GC_dump_named(const char * /* name */);
-
-/* Dump information about each block of every GC memory section.        */
-/* Defined only if the library has been compiled without NO_DEBUGGING.  */
-GC_API void GC_CALL GC_dump_regions(void);
-
-/* Dump information about every registered disappearing link and        */
-/* finalizable object.                                                  */
-/* Defined only if the library has been compiled without NO_DEBUGGING.  */
-GC_API void GC_CALL GC_dump_finalization(void);
-
-/* Safer, but slow, pointer addition.  Probably useful mainly with      */
-/* a preprocessor.  Useful only for heap pointers.                      */
-/* Only the macros without trailing digits are meant to be used         */
-/* by clients.  These are designed to model the available C pointer     */
-/* arithmetic expressions.                                              */
-/* Even then, these are probably more useful as                         */
-/* documentation than as part of the API.                               */
-/* Note that GC_PTR_ADD evaluates the first argument more than once.    */
-#if defined(GC_DEBUG) && defined(__GNUC__)
-# define GC_PTR_ADD3(x, n, type_of_result) \
-        ((type_of_result)GC_same_obj((x)+(n), (x)))
-# define GC_PRE_INCR3(x, n, type_of_result) \
-        ((type_of_result)GC_pre_incr((void **)(&(x)), (n)*sizeof(*x)))
-# define GC_POST_INCR3(x, n, type_of_result) \
-        ((type_of_result)GC_post_incr((void **)(&(x)), (n)*sizeof(*x)))
-# define GC_PTR_ADD(x, n) GC_PTR_ADD3(x, n, __typeof__(x))
-# define GC_PRE_INCR(x, n) GC_PRE_INCR3(x, n, __typeof__(x))
-# define GC_POST_INCR(x) GC_POST_INCR3(x, 1, __typeof__(x))
-# define GC_POST_DECR(x) GC_POST_INCR3(x, -1, __typeof__(x))
-#else /* !GC_DEBUG || !__GNUC__ */
-  /* We can't do this right without typeof, which ANSI decided was not    */
-  /* sufficiently useful.  Without it we resort to the non-debug version. */
-  /* TODO: This should eventually support C++0x decltype. */
-# define GC_PTR_ADD(x, n) ((x)+(n))
-# define GC_PRE_INCR(x, n) ((x) += (n))
-# define GC_POST_INCR(x) ((x)++)
-# define GC_POST_DECR(x) ((x)--)
-#endif /* !GC_DEBUG || !__GNUC__ */
-
-/* Safer assignment of a pointer to a non-stack location.       */
-#ifdef GC_DEBUG
-# define GC_PTR_STORE(p, q) \
-        (*(void **)GC_is_visible((void *)(p)) = \
-                    GC_is_valid_displacement((void *)(q)))
-#else
-# define GC_PTR_STORE(p, q) (*(void **)(p) = (void *)(q))
-#endif
-
-/* GC_PTR_STORE_AND_DIRTY(p,q) is equivalent to GC_PTR_STORE(p,q)       */
-/* followed by GC_END_STUBBORN_CHANGE(p) and GC_reachable_here(q)       */
-/* (assuming p and q do not have side effects).                         */
-GC_API void GC_CALL GC_ptr_store_and_dirty(void * /* p */,
-                                           const void * /* q */);
-GC_API void GC_CALL GC_debug_ptr_store_and_dirty(void * /* p */,
-                                                 const void * /* q */);
-
-/* Functions called to report pointer checking errors */
-GC_API void (GC_CALLBACK * GC_same_obj_print_proc)(void * /* p */,
-                                                   void * /* q */);
-GC_API void (GC_CALLBACK * GC_is_valid_displacement_print_proc)(void *);
-GC_API void (GC_CALLBACK * GC_is_visible_print_proc)(void *);
-
-#ifdef GC_PTHREADS
-  /* For pthread support, we generally need to intercept a number of    */
-  /* thread library calls.  We do that here by macro defining them.     */
-# ifdef __cplusplus
-    } /* extern "C" */
-# endif
-# include "gc_pthread_redirects.h"
-# ifdef __cplusplus
-    extern "C" {
-# endif
-#endif
-
-/* This returns a list of objects, linked through their first word.     */
-/* Its use can greatly reduce lock contention problems, since the       */
-/* allocation lock can be acquired and released many fewer times.       */
-GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_many(size_t /* lb */);
-#define GC_NEXT(p) (*(void * *)(p))     /* Retrieve the next element    */
-                                        /* in returned list.            */
-
-/* A filter function to control the scanning of dynamic libraries.      */
-/* If implemented, called by GC before registering a dynamic library    */
-/* (discovered by GC) section as a static data root (called only as     */
-/* a last reason not to register).  The filename of the library, the    */
-/* address and the length of the memory region (section) are passed.    */
-/* This routine should return nonzero if that region should be scanned. */
-/* Always called with the allocation lock held.  Depending on the       */
-/* platform, might be called with the "world" stopped.                  */
-typedef int (GC_CALLBACK * GC_has_static_roots_func)(
-                                        const char * /* dlpi_name */,
-                                        void * /* section_start */,
-                                        size_t /* section_size */);
-
-/* Register a new callback (a user-supplied filter) to control the      */
-/* scanning of dynamic libraries.  Replaces any previously registered   */
-/* callback.  May be 0 (means no filtering).  May be unused on some     */
-/* platforms (if the filtering is unimplemented or inappropriate).      */
-GC_API void GC_CALL GC_register_has_static_roots_callback(
-                                        GC_has_static_roots_func);
-
-#if !defined(CPPCHECK) && !defined(GC_WINDOWS_H_INCLUDED) && defined(WINAPI)
-  /* windows.h is included before gc.h */
-# define GC_WINDOWS_H_INCLUDED
-#endif
-
-#if defined(GC_WIN32_THREADS) \
-    && (!defined(GC_PTHREADS) || defined(GC_BUILD) \
-        || defined(GC_WINDOWS_H_INCLUDED))
-                /* Note: for Cygwin and pthreads-win32, this is skipped */
-                /* unless windows.h is included before gc.h.            */
-
-# if (!defined(GC_NO_THREAD_DECLS) || defined(GC_BUILD)) \
-     && !defined(GC_DONT_INCL_WINDOWS_H)
-
-#   ifdef __cplusplus
-      } /* Including windows.h in an extern "C" context no longer works. */
-#   endif
-
-#   if !defined(_WIN32_WCE) && !defined(__CEGCC__)
-#     include <process.h> /* For _beginthreadex, _endthreadex */
-#   endif
-
-#   if defined(GC_BUILD) || !defined(GC_DONT_INCLUDE_WINDOWS_H)
-#     include <windows.h>
-#     define GC_WINDOWS_H_INCLUDED
-#   endif
-
-#   ifdef __cplusplus
-      extern "C" {
-#   endif
-
-#   ifdef GC_UNDERSCORE_STDCALL
-      /* Explicitly prefix exported/imported WINAPI (__stdcall) symbols */
-      /* with '_' (underscore).  Might be useful if MinGW/x86 is used.  */
-#     define GC_CreateThread _GC_CreateThread
-#     define GC_ExitThread _GC_ExitThread
-#   endif
-
-#   ifndef DECLSPEC_NORETURN
-      /* Typically defined in winnt.h. */
-#     ifdef GC_WINDOWS_H_INCLUDED
-#       define DECLSPEC_NORETURN /* empty */
-#     else
-#       define DECLSPEC_NORETURN __declspec(noreturn)
-#     endif
-#   endif
-
-#   if !defined(_UINTPTR_T) && !defined(_UINTPTR_T_DEFINED) \
-       && !defined(UINTPTR_MAX)
-      typedef GC_word GC_uintptr_t;
-#   else
-      typedef uintptr_t GC_uintptr_t;
-#   endif
-
-#   ifdef _WIN64
-#     define GC_WIN32_SIZE_T GC_uintptr_t
-#   elif defined(GC_WINDOWS_H_INCLUDED)
-#     define GC_WIN32_SIZE_T DWORD
-#   else
-#     define GC_WIN32_SIZE_T unsigned long
-#   endif
-
-#   ifdef GC_INSIDE_DLL
-      /* Export GC DllMain to be invoked from client DllMain.   */
-#     ifdef GC_UNDERSCORE_STDCALL
-#       define GC_DllMain _GC_DllMain
-#     endif
-#     ifdef GC_WINDOWS_H_INCLUDED
-        GC_API BOOL WINAPI GC_DllMain(HINSTANCE /* inst */,
-                                      ULONG /* reason */,
-                                      LPVOID /* reserved */);
-#     else
-        GC_API int __stdcall GC_DllMain(void *, unsigned long, void *);
-#     endif
-#   endif /* GC_INSIDE_DLL */
-
-    /* All threads must be created using GC_CreateThread or             */
-    /* GC_beginthreadex, or must explicitly call GC_register_my_thread  */
-    /* (and call GC_unregister_my_thread before thread termination), so */
-    /* that they will be recorded in the thread table.  For backward    */
-    /* compatibility, it is possible to build the GC with GC_DLL        */
-    /* defined, and to call GC_use_threads_discovery.  This implicitly  */
-    /* registers all created threads, but appears to be less robust.    */
-    /* Currently the collector expects all threads to fall through and  */
-    /* terminate normally, or call GC_endthreadex() or GC_ExitThread,   */
-    /* so that the thread is properly unregistered.                     */
-#   ifdef GC_WINDOWS_H_INCLUDED
-      GC_API HANDLE WINAPI GC_CreateThread(
-                LPSECURITY_ATTRIBUTES /* lpThreadAttributes */,
-                GC_WIN32_SIZE_T /* dwStackSize */,
-                LPTHREAD_START_ROUTINE /* lpStartAddress */,
-                LPVOID /* lpParameter */, DWORD /* dwCreationFlags */,
-                LPDWORD /* lpThreadId */);
-
-      GC_API DECLSPEC_NORETURN void WINAPI GC_ExitThread(
-                                                DWORD /* dwExitCode */);
-#   else
-      struct _SECURITY_ATTRIBUTES;
-      GC_API void *__stdcall GC_CreateThread(struct _SECURITY_ATTRIBUTES *,
-                                GC_WIN32_SIZE_T,
-                                unsigned long (__stdcall *)(void *),
-                                void *, unsigned long, unsigned long *);
-      GC_API DECLSPEC_NORETURN void __stdcall GC_ExitThread(unsigned long);
-#   endif
-
-#   if !defined(_WIN32_WCE) && !defined(__CEGCC__)
-      GC_API GC_uintptr_t GC_CALL GC_beginthreadex(
-                        void * /* security */, unsigned /* stack_size */,
-                        unsigned (__stdcall *)(void *),
-                        void * /* arglist */, unsigned /* initflag */,
-                        unsigned * /* thrdaddr */);
-
-      /* Note: _endthreadex() is not currently marked as no-return in   */
-      /* VC++ and MinGW headers, so we don't mark it neither.           */
-      GC_API void GC_CALL GC_endthreadex(unsigned /* retval */);
-#   endif /* !_WIN32_WCE */
-
-# endif /* !GC_NO_THREAD_DECLS */
-
-# ifdef GC_WINMAIN_REDIRECT
-    /* win32_threads.c implements the real WinMain(), which will start  */
-    /* a new thread to call GC_WinMain() after initializing the garbage */
-    /* collector.                                                       */
-#   define WinMain GC_WinMain
-# endif
-
-  /* For compatibility only. */
-# define GC_use_DllMain GC_use_threads_discovery
-
-# ifndef GC_NO_THREAD_REDIRECTS
-#   define CreateThread GC_CreateThread
-#   define ExitThread GC_ExitThread
-#   undef _beginthreadex
-#   define _beginthreadex GC_beginthreadex
-#   undef _endthreadex
-#   define _endthreadex GC_endthreadex
-/* #define _beginthread { > "Please use _beginthreadex instead of _beginthread" < } */
-# endif /* !GC_NO_THREAD_REDIRECTS */
-
-#endif /* GC_WIN32_THREADS */
-
-/* Public setter and getter for switching "unmap as much as possible"   */
-/* mode on(1) and off(0).  Has no effect unless unmapping is turned on. */
-/* Has no effect on implicitly-initiated garbage collections.  Initial  */
-/* value is controlled by GC_FORCE_UNMAP_ON_GCOLLECT.  The setter and   */
-/* getter are unsynchronized.                                           */
-GC_API void GC_CALL GC_set_force_unmap_on_gcollect(int);
-GC_API int GC_CALL GC_get_force_unmap_on_gcollect(void);
-
-/* Fully portable code should call GC_INIT() from the main program      */
-/* before making any other GC_ calls.  On most platforms this is a      */
-/* no-op and the collector self-initializes.  But a number of           */
-/* platforms make that too hard.                                        */
-/* A GC_INIT call is required if the collector is built with            */
-/* THREAD_LOCAL_ALLOC defined and the initial allocation call is not    */
-/* to GC_malloc() or GC_malloc_atomic().                                */
-
-#if defined(__CYGWIN32__) || defined(__CYGWIN__)
-  /* Similarly gnu-win32 DLLs need explicit initialization from the     */
-  /* main program, as does AIX.                                         */
-# ifdef __x86_64__
-    /* Cygwin/x64 does not add leading underscore to symbols anymore.   */
-    extern int __data_start__[], __data_end__[];
-    extern int __bss_start__[], __bss_end__[];
-#   define GC_DATASTART ((GC_word)__data_start__ < (GC_word)__bss_start__ \
-                         ? (void *)__data_start__ : (void *)__bss_start__)
-#   define GC_DATAEND ((GC_word)__data_end__ > (GC_word)__bss_end__ \
-                       ? (void *)__data_end__ : (void *)__bss_end__)
-# else
-    extern int _data_start__[], _data_end__[], _bss_start__[], _bss_end__[];
-#   define GC_DATASTART ((GC_word)_data_start__ < (GC_word)_bss_start__ \
-                         ? (void *)_data_start__ : (void *)_bss_start__)
-#   define GC_DATAEND ((GC_word)_data_end__ > (GC_word)_bss_end__ \
-                      ? (void *)_data_end__ : (void *)_bss_end__)
-# endif /* !__x86_64__ */
-# define GC_INIT_CONF_ROOTS GC_add_roots(GC_DATASTART, GC_DATAEND); \
-                                 GC_gcollect() /* For blacklisting. */
-        /* Required at least if GC is in a DLL.  And doesn't hurt. */
-#elif defined(_AIX)
-  extern int _data[], _end[];
-# define GC_DATASTART ((void *)_data)
-# define GC_DATAEND ((void *)_end)
-# define GC_INIT_CONF_ROOTS GC_add_roots(GC_DATASTART, GC_DATAEND)
-#elif (defined(HOST_ANDROID) || defined(__ANDROID__)) \
-      && defined(IGNORE_DYNAMIC_LOADING)
-  /* This is ugly but seems the only way to register data roots of the  */
-  /* client shared library if the GC dynamic loading support is off.    */
-# pragma weak __dso_handle
-  extern int __dso_handle[];
-  GC_API void * GC_CALL GC_find_limit(void * /* start */, int /* up */);
-# define GC_INIT_CONF_ROOTS (void)(__dso_handle != 0 \
-                                   ? (GC_add_roots(__dso_handle, \
-                                            GC_find_limit(__dso_handle, \
-                                                          1 /*up*/)), 0) : 0)
-#else
-# define GC_INIT_CONF_ROOTS /* empty */
-#endif
-
-#ifdef GC_DONT_EXPAND
-  /* Set GC_dont_expand to TRUE at start-up */
-# define GC_INIT_CONF_DONT_EXPAND GC_set_dont_expand(1)
-#else
-# define GC_INIT_CONF_DONT_EXPAND /* empty */
-#endif
-
-#ifdef GC_FORCE_UNMAP_ON_GCOLLECT
-  /* Turn on "unmap as much as possible on explicit GC" mode at start-up */
-# define GC_INIT_CONF_FORCE_UNMAP_ON_GCOLLECT \
-                GC_set_force_unmap_on_gcollect(1)
-#else
-# define GC_INIT_CONF_FORCE_UNMAP_ON_GCOLLECT /* empty */
-#endif
-
-#ifdef GC_DONT_GC
-  /* This is for debugging only (useful if environment variables are    */
-  /* unsupported); cannot call GC_disable as goes before GC_init.       */
-# define GC_INIT_CONF_MAX_RETRIES (void)(GC_dont_gc = 1)
-#elif defined(GC_MAX_RETRIES) && !defined(CPPCHECK)
-  /* Set GC_max_retries to the desired value at start-up */
-# define GC_INIT_CONF_MAX_RETRIES GC_set_max_retries(GC_MAX_RETRIES)
-#else
-# define GC_INIT_CONF_MAX_RETRIES /* empty */
-#endif
-
-#if defined(GC_ALLOCD_BYTES_PER_FINALIZER) && !defined(CPPCHECK)
-  /* Set GC_allocd_bytes_per_finalizer to the desired value at start-up. */
-# define GC_INIT_CONF_ALLOCD_BYTES_PER_FINALIZER \
-        GC_set_allocd_bytes_per_finalizer(GC_ALLOCD_BYTES_PER_FINALIZER)
-#else
-# define GC_INIT_CONF_ALLOCD_BYTES_PER_FINALIZER /* empty */
-#endif
-
-#if defined(GC_FREE_SPACE_DIVISOR) && !defined(CPPCHECK)
-  /* Set GC_free_space_divisor to the desired value at start-up */
-# define GC_INIT_CONF_FREE_SPACE_DIVISOR \
-                GC_set_free_space_divisor(GC_FREE_SPACE_DIVISOR)
-#else
-# define GC_INIT_CONF_FREE_SPACE_DIVISOR /* empty */
-#endif
-
-#if defined(GC_FULL_FREQ) && !defined(CPPCHECK)
-  /* Set GC_full_freq to the desired value at start-up */
-# define GC_INIT_CONF_FULL_FREQ GC_set_full_freq(GC_FULL_FREQ)
-#else
-# define GC_INIT_CONF_FULL_FREQ /* empty */
-#endif
-
-#if defined(GC_TIME_LIMIT) && !defined(CPPCHECK)
-  /* Set GC_time_limit (in ms) to the desired value at start-up. */
-# define GC_INIT_CONF_TIME_LIMIT GC_set_time_limit(GC_TIME_LIMIT)
-#else
-# define GC_INIT_CONF_TIME_LIMIT /* empty */
-#endif
-
-#if defined(GC_MARKERS) && defined(GC_THREADS) && !defined(CPPCHECK)
-  /* Set the number of marker threads (including the initiating */
-  /* one) to the desired value at start-up.                     */
-# define GC_INIT_CONF_MARKERS GC_set_markers_count(GC_MARKERS)
-#else
-# define GC_INIT_CONF_MARKERS /* empty */
-#endif
-
-#if defined(GC_SIG_SUSPEND) && defined(GC_THREADS) && !defined(CPPCHECK)
-# define GC_INIT_CONF_SUSPEND_SIGNAL GC_set_suspend_signal(GC_SIG_SUSPEND)
-#else
-# define GC_INIT_CONF_SUSPEND_SIGNAL /* empty */
-#endif
-
-#if defined(GC_SIG_THR_RESTART) && defined(GC_THREADS) && !defined(CPPCHECK)
-# define GC_INIT_CONF_THR_RESTART_SIGNAL \
-                GC_set_thr_restart_signal(GC_SIG_THR_RESTART)
-#else
-# define GC_INIT_CONF_THR_RESTART_SIGNAL /* empty */
-#endif
-
-#if defined(GC_MAXIMUM_HEAP_SIZE) && !defined(CPPCHECK)
-  /* Limit the heap size to the desired value (useful for debugging).   */
-  /* The limit could be overridden either at the program start-up by    */
-  /* the similar environment variable or anytime later by the           */
-  /* corresponding API function call.                                   */
-# define GC_INIT_CONF_MAXIMUM_HEAP_SIZE \
-                GC_set_max_heap_size(GC_MAXIMUM_HEAP_SIZE)
-#else
-# define GC_INIT_CONF_MAXIMUM_HEAP_SIZE /* empty */
-#endif
-
-#ifdef GC_IGNORE_WARN
-  /* Turn off all warnings at start-up (after GC initialization) */
-# define GC_INIT_CONF_IGNORE_WARN GC_set_warn_proc(GC_ignore_warn_proc)
-#else
-# define GC_INIT_CONF_IGNORE_WARN /* empty */
-#endif
-
-#if defined(GC_INITIAL_HEAP_SIZE) && !defined(CPPCHECK)
-  /* Set heap size to the desired value at start-up */
-# define GC_INIT_CONF_INITIAL_HEAP_SIZE \
-                { size_t heap_size = GC_get_heap_size(); \
-                  if (heap_size < (GC_INITIAL_HEAP_SIZE)) \
-                    (void)GC_expand_hp((GC_INITIAL_HEAP_SIZE) - heap_size); }
-#else
-# define GC_INIT_CONF_INITIAL_HEAP_SIZE /* empty */
-#endif
-
-/* Portable clients should call this at the program start-up.  More     */
-/* over, some platforms require this call to be done strictly from the  */
-/* primordial thread.  Multiple invocations are harmless.               */
-#define GC_INIT() { GC_INIT_CONF_DONT_EXPAND; /* pre-init */ \
-                    GC_INIT_CONF_FORCE_UNMAP_ON_GCOLLECT; \
-                    GC_INIT_CONF_MAX_RETRIES; \
-                    GC_INIT_CONF_ALLOCD_BYTES_PER_FINALIZER; \
-                    GC_INIT_CONF_FREE_SPACE_DIVISOR; \
-                    GC_INIT_CONF_FULL_FREQ; \
-                    GC_INIT_CONF_TIME_LIMIT; \
-                    GC_INIT_CONF_MARKERS; \
-                    GC_INIT_CONF_SUSPEND_SIGNAL; \
-                    GC_INIT_CONF_THR_RESTART_SIGNAL; \
-                    GC_INIT_CONF_MAXIMUM_HEAP_SIZE; \
-                    GC_init(); /* real GC initialization */ \
-                    GC_INIT_CONF_ROOTS; /* post-init */ \
-                    GC_INIT_CONF_IGNORE_WARN; \
-                    GC_INIT_CONF_INITIAL_HEAP_SIZE; }
-
-/* win32S may not free all resources on process exit.                   */
-/* This explicitly deallocates the heap.  Defined only for Windows.     */
-GC_API void GC_CALL GC_win32_free_heap(void);
-
-#if defined(__SYMBIAN32__)
-  void GC_init_global_static_roots(void);
-#endif
-
-#if defined(_AMIGA) && !defined(GC_AMIGA_MAKINGLIB)
-  /* Allocation really goes through GC_amiga_allocwrapper_do.   */
-  void *GC_amiga_realloc(void *, size_t);
-# define GC_realloc(a,b) GC_amiga_realloc(a,b)
-  void GC_amiga_set_toany(void (*)(void));
-  extern int GC_amiga_free_space_divisor_inc;
-  extern void *(*GC_amiga_allocwrapper_do)(size_t, void *(GC_CALL *)(size_t));
-# define GC_malloc(a) \
-        (*GC_amiga_allocwrapper_do)(a,GC_malloc)
-# define GC_malloc_atomic(a) \
-        (*GC_amiga_allocwrapper_do)(a,GC_malloc_atomic)
-# define GC_malloc_uncollectable(a) \
-        (*GC_amiga_allocwrapper_do)(a,GC_malloc_uncollectable)
-# define GC_malloc_atomic_uncollectable(a) \
-        (*GC_amiga_allocwrapper_do)(a,GC_malloc_atomic_uncollectable)
-# define GC_malloc_ignore_off_page(a) \
-        (*GC_amiga_allocwrapper_do)(a,GC_malloc_ignore_off_page)
-# define GC_malloc_atomic_ignore_off_page(a) \
-        (*GC_amiga_allocwrapper_do)(a,GC_malloc_atomic_ignore_off_page)
-#endif /* _AMIGA && !GC_AMIGA_MAKINGLIB */
-
-#ifdef __cplusplus
-  } /* extern "C" */
-#endif
-
-#endif /* GC_H */
+/* This file is installed for backward compatibility. */
+#include "gc/gc.h"

+ 0 - 0
blitz.mod/bdwgc/include/cord.h → blitz.mod/bdwgc/include/gc/cord.h


+ 0 - 0
blitz.mod/bdwgc/include/cord_pos.h → blitz.mod/bdwgc/include/gc/cord_pos.h


+ 0 - 0
blitz.mod/bdwgc/include/ec.h → blitz.mod/bdwgc/include/gc/ec.h


+ 2172 - 0
blitz.mod/bdwgc/include/gc/gc.h

@@ -0,0 +1,2172 @@
+/*
+ * Copyright (c) 1988-1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved.
+ * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.
+ * Copyright (c) 1999 by Hewlett-Packard Company.  All rights reserved.
+ * Copyright (c) 2007 Free Software Foundation, Inc.
+ * Copyright (c) 2000-2011 by Hewlett-Packard Development Company.
+ * Copyright (c) 2009-2020 Ivan Maidanski
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/*
+ * Note that this defines a large number of tuning hooks, which can
+ * safely be ignored in nearly all cases.  For normal use it suffices
+ * to call only GC_MALLOC and perhaps GC_REALLOC.
+ * For better performance, also look at GC_MALLOC_ATOMIC, and
+ * GC_enable_incremental.  If you need an action to be performed
+ * immediately before an object is collected, look at GC_register_finalizer.
+ * Everything else is best ignored unless you encounter performance
+ * problems.
+ */
+
+#ifndef GC_H
+#define GC_H
+
+/* Help debug mixed up preprocessor symbols.    */
+#if (defined(WIN64) && !defined(_WIN64)) && defined(_MSC_VER)
+#pragma message("Warning: Expecting _WIN64 for x64 targets! Notice the leading underscore!")
+#endif
+
+#include "gc_version.h"
+        /* Define version numbers here to allow test on build machine   */
+        /* for cross-builds.  Note that this defines the header         */
+        /* version number, which may or may not match that of the       */
+        /* dynamic library.  GC_get_version() can be used to obtain     */
+        /* the latter.                                                  */
+
+#include "gc_config_macros.h"
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+typedef void * GC_PTR;  /* preserved only for backward compatibility    */
+
+/* Define word and signed_word to be unsigned and signed types of the   */
+/* size as char * or void *.  There seems to be no way to do this       */
+/* even semi-portably.  The following is probably no better/worse       */
+/* than almost anything else.                                           */
+/* The ANSI standard suggests that size_t and ptrdiff_t might be        */
+/* better choices.  But those had incorrect definitions on some older   */
+/* systems.  Notably "typedef int size_t" is WRONG.                     */
+#ifdef _WIN64
+# if defined(__int64) && !defined(CPPCHECK)
+    typedef unsigned __int64 GC_word;
+    typedef __int64 GC_signed_word;
+# else
+    typedef unsigned long long GC_word;
+    typedef long long GC_signed_word;
+# endif
+#else
+  typedef unsigned long GC_word;
+  typedef long GC_signed_word;
+#endif
+
+/* Get the GC library version. The returned value is a constant in the  */
+/* form: ((version_major<<16) | (version_minor<<8) | version_micro).    */
+GC_API unsigned GC_CALL GC_get_version(void);
+
+/* Public read-only variables */
+/* The supplied getter functions are preferred for new code.            */
+
+GC_API GC_ATTR_DEPRECATED GC_word GC_gc_no;
+                        /* Counter incremented per collection.          */
+                        /* Includes empty GCs at startup.               */
+GC_API GC_word GC_CALL GC_get_gc_no(void);
+                        /* GC_get_gc_no() is unsynchronized, so         */
+                        /* it requires GC_call_with_alloc_lock() to     */
+                        /* avoid data races on multiprocessors.         */
+
+#ifdef GC_THREADS
+  GC_API GC_ATTR_DEPRECATED int GC_parallel;
+                        /* GC is parallelized for performance on        */
+                        /* multiprocessors.  Set to a non-zero value    */
+                        /* only implicitly if collector is built with   */
+                        /* PARALLEL_MARK defined, and if either         */
+                        /* GC_MARKERS (or GC_NPROCS) environment        */
+                        /* variable is set to > 1, or multiple cores    */
+                        /* (processors) are available, or the client    */
+                        /* calls GC_set_markers_count() before the GC   */
+                        /* initialization.  The getter does             */
+                        /* not use or need synchronization (i.e.        */
+                        /* acquiring the GC lock).  GC_parallel value   */
+                        /* is equal to the number of marker threads     */
+                        /* minus one (i.e. number of existing parallel  */
+                        /* marker threads excluding the initiating one).*/
+  GC_API int GC_CALL GC_get_parallel(void);
+
+  /* Set the number of marker threads (including the initiating one)    */
+  /* to the desired value at start-up.  Zero value means the collector  */
+  /* is to decide.  Has no effect if called after GC initialization.    */
+  /* If the correct non-zero value is passed, then GC_parallel should   */
+  /* be set to the value minus one.  The function does not use any      */
+  /* synchronization.                                                   */
+  GC_API void GC_CALL GC_set_markers_count(unsigned);
+#endif
+
+
+/* Public R/W variables */
+/* The supplied setter and getter functions are preferred for new code. */
+
+typedef void * (GC_CALLBACK * GC_oom_func)(size_t /* bytes_requested */);
+GC_API GC_ATTR_DEPRECATED GC_oom_func GC_oom_fn;
+                        /* When there is insufficient memory to satisfy */
+                        /* an allocation request, we return             */
+                        /* (*GC_oom_fn)(size).  By default this just    */
+                        /* returns NULL.                                */
+                        /* If it returns, it must return 0 or a valid   */
+                        /* pointer to a previously allocated heap       */
+                        /* object.  GC_oom_fn must not be 0.            */
+                        /* Both the supplied setter and the getter      */
+                        /* acquire the GC lock (to avoid data races).   */
+GC_API void GC_CALL GC_set_oom_fn(GC_oom_func) GC_ATTR_NONNULL(1);
+GC_API GC_oom_func GC_CALL GC_get_oom_fn(void);
+
+typedef void (GC_CALLBACK * GC_on_heap_resize_proc)(GC_word /* new_size */);
+GC_API GC_ATTR_DEPRECATED GC_on_heap_resize_proc GC_on_heap_resize;
+                        /* Invoked when the heap grows or shrinks.      */
+                        /* Called with the world stopped (and the       */
+                        /* allocation lock held).  May be 0.            */
+GC_API void GC_CALL GC_set_on_heap_resize(GC_on_heap_resize_proc);
+GC_API GC_on_heap_resize_proc GC_CALL GC_get_on_heap_resize(void);
+                        /* Both the supplied setter and the getter      */
+                        /* acquire the GC lock (to avoid data races).   */
+
+typedef enum {
+    GC_EVENT_START /* COLLECTION */,
+    GC_EVENT_MARK_START,
+    GC_EVENT_MARK_END,
+    GC_EVENT_RECLAIM_START,
+    GC_EVENT_RECLAIM_END,
+    GC_EVENT_END /* COLLECTION */,
+    GC_EVENT_PRE_STOP_WORLD /* STOPWORLD_BEGIN */,
+    GC_EVENT_POST_STOP_WORLD /* STOPWORLD_END */,
+    GC_EVENT_PRE_START_WORLD /* STARTWORLD_BEGIN */,
+    GC_EVENT_POST_START_WORLD /* STARTWORLD_END */,
+    GC_EVENT_THREAD_SUSPENDED,
+    GC_EVENT_THREAD_UNSUSPENDED
+} GC_EventType;
+
+typedef void (GC_CALLBACK * GC_on_collection_event_proc)(GC_EventType);
+                        /* Invoked to indicate progress through the     */
+                        /* collection process.  Not used for thread     */
+                        /* suspend/resume notifications.  Called with   */
+                        /* the GC lock held (or, even, the world        */
+                        /* stopped).  May be 0 (means no notifier).     */
+GC_API void GC_CALL GC_set_on_collection_event(GC_on_collection_event_proc);
+GC_API GC_on_collection_event_proc GC_CALL GC_get_on_collection_event(void);
+                        /* Both the supplied setter and the getter      */
+                        /* acquire the GC lock (to avoid data races).   */
+
+#if defined(GC_THREADS) || (defined(GC_BUILD) && defined(NN_PLATFORM_CTR))
+  typedef void (GC_CALLBACK * GC_on_thread_event_proc)(GC_EventType,
+                                                void * /* thread_id */);
+                        /* Invoked when a thread is suspended or        */
+                        /* resumed during collection.  Called with the  */
+                        /* GC lock held (and the world stopped          */
+                        /* partially).  May be 0 (means no notifier).   */
+  GC_API void GC_CALL GC_set_on_thread_event(GC_on_thread_event_proc);
+  GC_API GC_on_thread_event_proc GC_CALL GC_get_on_thread_event(void);
+                        /* Both the supplied setter and the getter      */
+                        /* acquire the GC lock (to avoid data races).   */
+#endif
+
+GC_API GC_ATTR_DEPRECATED int GC_find_leak;
+                        /* Set to true to turn on the leak-finding mode */
+                        /* (do not actually garbage collect, but simply */
+                        /* report inaccessible memory that was not      */
+                        /* deallocated with GC_FREE).  Initial value    */
+                        /* is determined by FIND_LEAK macro.            */
+                        /* The value should not typically be modified   */
+                        /* after GC initialization (and, thus, it does  */
+                        /* not use or need synchronization).            */
+GC_API void GC_CALL GC_set_find_leak(int);
+GC_API int GC_CALL GC_get_find_leak(void);
+
+GC_API GC_ATTR_DEPRECATED int GC_all_interior_pointers;
+                        /* Arrange for pointers to object interiors to  */
+                        /* be recognized as valid.  Typically should    */
+                        /* not be changed after GC initialization (in   */
+                        /* case of calling it after the GC is           */
+                        /* initialized, the setter acquires the GC lock */
+                        /* (to avoid data races).  The initial value    */
+                        /* depends on whether the GC is built with      */
+                        /* ALL_INTERIOR_POINTERS macro defined or not.  */
+                        /* Unless DONT_ADD_BYTE_AT_END is defined, this */
+                        /* also affects whether sizes are increased by  */
+                        /* at least a byte to allow "off the end"       */
+                        /* pointer recognition.  Must be only 0 or 1.   */
+GC_API void GC_CALL GC_set_all_interior_pointers(int);
+GC_API int GC_CALL GC_get_all_interior_pointers(void);
+
+GC_API GC_ATTR_DEPRECATED int GC_finalize_on_demand;
+                        /* If nonzero, finalizers will only be run in   */
+                        /* response to an explicit GC_invoke_finalizers */
+                        /* call.  The default is determined by whether  */
+                        /* the FINALIZE_ON_DEMAND macro is defined      */
+                        /* when the collector is built.                 */
+                        /* The setter and getter are unsynchronized.    */
+GC_API void GC_CALL GC_set_finalize_on_demand(int);
+GC_API int GC_CALL GC_get_finalize_on_demand(void);
+
+GC_API GC_ATTR_DEPRECATED int GC_java_finalization;
+                        /* Mark objects reachable from finalizable      */
+                        /* objects in a separate post-pass.  This makes */
+                        /* it a bit safer to use non-topologically-     */
+                        /* ordered finalization.  Default value is      */
+                        /* determined by JAVA_FINALIZATION macro.       */
+                        /* Enables register_finalizer_unreachable to    */
+                        /* work correctly.                              */
+                        /* The setter and getter are unsynchronized.    */
+GC_API void GC_CALL GC_set_java_finalization(int);
+GC_API int GC_CALL GC_get_java_finalization(void);
+
+typedef void (GC_CALLBACK * GC_finalizer_notifier_proc)(void);
+GC_API GC_ATTR_DEPRECATED GC_finalizer_notifier_proc GC_finalizer_notifier;
+                        /* Invoked by the collector when there are      */
+                        /* objects to be finalized.  Invoked at most    */
+                        /* once per GC cycle.  Never invoked unless     */
+                        /* GC_finalize_on_demand is set.                */
+                        /* Typically this will notify a finalization    */
+                        /* thread, which will call GC_invoke_finalizers */
+                        /* in response.  May be 0 (means no notifier).  */
+                        /* Both the supplied setter and the getter      */
+                        /* acquire the GC lock (to avoid data races).   */
+GC_API void GC_CALL GC_set_finalizer_notifier(GC_finalizer_notifier_proc);
+GC_API GC_finalizer_notifier_proc GC_CALL GC_get_finalizer_notifier(void);
+
+GC_API
+# ifndef GC_DONT_GC
+    GC_ATTR_DEPRECATED
+# endif
+  int GC_dont_gc;       /* != 0 ==> Do not collect.  This overrides     */
+                        /* explicit GC_gcollect() calls as well.        */
+                        /* Used as a counter, so that nested enabling   */
+                        /* and disabling work correctly.  Should        */
+                        /* normally be updated with GC_enable() and     */
+                        /* GC_disable() calls.  Direct assignment to    */
+                        /* GC_dont_gc is deprecated.  To check whether  */
+                        /* GC is disabled, GC_is_disabled() is          */
+                        /* preferred for new code.                      */
+
+GC_API GC_ATTR_DEPRECATED int GC_dont_expand;
+                        /* Do not expand the heap unless explicitly     */
+                        /* requested or forced to.  The setter and      */
+                        /* getter are unsynchronized.                   */
+GC_API void GC_CALL GC_set_dont_expand(int);
+GC_API int GC_CALL GC_get_dont_expand(void);
+
+GC_API GC_ATTR_DEPRECATED int GC_use_entire_heap;
+                /* Causes the non-incremental collector to use the      */
+                /* entire heap before collecting.  This sometimes       */
+                /* results in more large block fragmentation, since     */
+                /* very large blocks will tend to get broken up         */
+                /* during each GC cycle.  It is likely to result in a   */
+                /* larger working set, but lower collection             */
+                /* frequencies, and hence fewer instructions executed   */
+                /* in the collector.                                    */
+
+GC_API GC_ATTR_DEPRECATED int GC_full_freq;
+                            /* Number of partial collections between    */
+                            /* full collections.  Matters only if       */
+                            /* GC_is_incremental_mode().                */
+                            /* Full collections are also triggered if   */
+                            /* the collector detects a substantial      */
+                            /* increase in the number of in-use heap    */
+                            /* blocks.  Values in the tens are now      */
+                            /* perfectly reasonable, unlike for         */
+                            /* earlier GC versions.                     */
+                        /* The setter and getter are unsynchronized, so */
+                        /* GC_call_with_alloc_lock() is required to     */
+                        /* avoid data races (if the value is modified   */
+                        /* after the GC is put to multi-threaded mode). */
+GC_API void GC_CALL GC_set_full_freq(int);
+GC_API int GC_CALL GC_get_full_freq(void);
+
+GC_API GC_ATTR_DEPRECATED GC_word GC_non_gc_bytes;
+                        /* Bytes not considered candidates for          */
+                        /* collection.  Used only to control scheduling */
+                        /* of collections.  Updated by                  */
+                        /* GC_malloc_uncollectable and GC_free.         */
+                        /* Wizards only.                                */
+                        /* The setter and getter are unsynchronized, so */
+                        /* GC_call_with_alloc_lock() is required to     */
+                        /* avoid data races (if the value is modified   */
+                        /* after the GC is put to multi-threaded mode). */
+GC_API void GC_CALL GC_set_non_gc_bytes(GC_word);
+GC_API GC_word GC_CALL GC_get_non_gc_bytes(void);
+
+GC_API GC_ATTR_DEPRECATED int GC_no_dls;
+                        /* Don't register dynamic library data segments. */
+                        /* Wizards only.  Should be used only if the     */
+                        /* application explicitly registers all roots.   */
+                        /* (In some environments like Microsoft Windows  */
+                        /* and Apple's Darwin, this may also prevent     */
+                        /* registration of the main data segment as part */
+                        /* of the root set.)                             */
+                        /* The setter and getter are unsynchronized.     */
+GC_API void GC_CALL GC_set_no_dls(int);
+GC_API int GC_CALL GC_get_no_dls(void);
+
+GC_API GC_ATTR_DEPRECATED GC_word GC_free_space_divisor;
+                        /* We try to make sure that we allocate at      */
+                        /* least N/GC_free_space_divisor bytes between  */
+                        /* collections, where N is twice the number     */
+                        /* of traced bytes, plus the number of untraced */
+                        /* bytes (bytes in "atomic" objects), plus      */
+                        /* a rough estimate of the root set size.       */
+                        /* N approximates GC tracing work per GC.       */
+                        /* The initial value is GC_FREE_SPACE_DIVISOR.  */
+                        /* Increasing its value will use less space     */
+                        /* but more collection time.  Decreasing it     */
+                        /* will appreciably decrease collection time    */
+                        /* at the expense of space.                     */
+                        /* The setter and getter are unsynchronized, so */
+                        /* GC_call_with_alloc_lock() is required to     */
+                        /* avoid data races (if the value is modified   */
+                        /* after the GC is put to multi-threaded mode). */
+                        /* In GC v7.1 (and before), the setter returned */
+                        /* the old value.                               */
+GC_API void GC_CALL GC_set_free_space_divisor(GC_word);
+GC_API GC_word GC_CALL GC_get_free_space_divisor(void);
+
+GC_API GC_ATTR_DEPRECATED GC_word GC_max_retries;
+                        /* The maximum number of GCs attempted before   */
+                        /* reporting out of memory after heap           */
+                        /* expansion fails.  Initially 0.               */
+                        /* The setter and getter are unsynchronized, so */
+                        /* GC_call_with_alloc_lock() is required to     */
+                        /* avoid data races (if the value is modified   */
+                        /* after the GC is put to multi-threaded mode). */
+GC_API void GC_CALL GC_set_max_retries(GC_word);
+GC_API GC_word GC_CALL GC_get_max_retries(void);
+
+
+GC_API GC_ATTR_DEPRECATED char *GC_stackbottom;
+                                /* The cold end (bottom) of user stack. */
+                                /* May be set in the client prior to    */
+                                /* calling any GC_ routines.  This      */
+                                /* avoids some overhead, and            */
+                                /* potentially some signals that can    */
+                                /* confuse debuggers.  Otherwise the    */
+                                /* collector attempts to set it         */
+                                /* automatically.                       */
+                                /* For multi-threaded code, this is the */
+                                /* cold end of the stack for the        */
+                                /* primordial thread.  Portable clients */
+                                /* should use GC_get_stack_base(),      */
+                                /* GC_call_with_gc_active() and         */
+                                /* GC_register_my_thread() instead.     */
+
+GC_API GC_ATTR_DEPRECATED int GC_dont_precollect;
+                                /* Do not collect as part of GC         */
+                                /* initialization.  Should be set only  */
+                                /* if the client wants a chance to      */
+                                /* manually initialize the root set     */
+                                /* before the first collection.         */
+                                /* Interferes with blacklisting.        */
+                                /* Wizards only.  The setter and getter */
+                                /* are unsynchronized (and no external  */
+                                /* locking is needed since the value is */
+                                /* accessed at GC initialization only). */
+GC_API void GC_CALL GC_set_dont_precollect(int);
+GC_API int GC_CALL GC_get_dont_precollect(void);
+
+GC_API GC_ATTR_DEPRECATED unsigned long GC_time_limit;
+                               /* If incremental collection is enabled, */
+                               /* we try to terminate collections       */
+                               /* after this many milliseconds (plus    */
+                               /* the amount of nanoseconds as given in */
+                               /* the latest GC_set_time_limit_tv call, */
+                               /* if any).  Not a hard time bound.      */
+                               /* Setting this variable to              */
+                               /* GC_TIME_UNLIMITED will essentially    */
+                               /* disable incremental collection while  */
+                               /* leaving generational collection       */
+                               /* enabled.                              */
+#define GC_TIME_UNLIMITED 999999
+                               /* Setting GC_time_limit to this value   */
+                               /* will disable the "pause time exceeded"*/
+                               /* tests.                                */
+                        /* The setter and getter are unsynchronized, so */
+                        /* GC_call_with_alloc_lock() is required to     */
+                        /* avoid data races (if the value is modified   */
+                        /* after the GC is put to multi-threaded mode). */
+                        /* The setter does not update the value of the  */
+                        /* nanosecond part of the time limit (it is     */
+                        /* zero unless ever set by GC_set_time_limit_tv */
+                        /* call).                                       */
+GC_API void GC_CALL GC_set_time_limit(unsigned long);
+GC_API unsigned long GC_CALL GC_get_time_limit(void);
+
+/* A portable type definition of time with a nanosecond precision.      */
+struct GC_timeval_s {
+  unsigned long tv_ms;  /* time in milliseconds */
+  unsigned long tv_nsec;/* nanoseconds fraction (<1000000) */
+};
+
+/* Public procedures */
+
+/* Set/get the time limit of the incremental collections.  This is      */
+/* similar to GC_set_time_limit and GC_get_time_limit but the time is   */
+/* provided with the nanosecond precision.  The value of tv_nsec part   */
+/* should be less than a million.  If the value of tv_ms part is        */
+/* GC_TIME_UNLIMITED then tv_nsec is ignored.  Initially, the value of  */
+/* tv_nsec part of the time limit is zero.  The functions do not use    */
+/* any synchronization.  Defined only if the library has been compiled  */
+/* without NO_CLOCK.                                                    */
+GC_API void GC_CALL GC_set_time_limit_tv(struct GC_timeval_s);
+GC_API struct GC_timeval_s GC_CALL GC_get_time_limit_tv(void);
+
+/* Set/get the minimum value of the ratio of allocated bytes since GC   */
+/* to the amount of finalizers created since that GC (value >           */
+/* GC_bytes_allocd / (GC_fo_entries - last_fo_entries)) which triggers  */
+/* the collection instead heap expansion.  The value has no effect in   */
+/* the GC incremental mode.  The default value is 10000 unless          */
+/* GC_ALLOCD_BYTES_PER_FINALIZER macro with a custom value is defined   */
+/* to build libgc.  The default value might be not the right choice for */
+/* clients where e.g. most objects have a finalizer.  Zero value        */
+/* effectively disables taking amount of finalizers in the decision     */
+/* whether to collect or not.  The functions do not use any             */
+/* synchronization.                                                     */
+GC_API void GC_CALL GC_set_allocd_bytes_per_finalizer(GC_word);
+GC_API GC_word GC_CALL GC_get_allocd_bytes_per_finalizer(void);
+
+/* Tell the collector to start various performance measurements.        */
+/* Only the total time taken by full collections is calculated, as      */
+/* of now.  And, currently, there is no way to stop the measurements.   */
+/* The function does not use any synchronization.  Defined only if the  */
+/* library has been compiled without NO_CLOCK.                          */
+GC_API void GC_CALL GC_start_performance_measurement(void);
+
+/* Get the total time of all full collections since the start of the    */
+/* performance measurements.  The measurement unit is one millisecond.  */
+/* Note that the returned value wraps around on overflow.               */
+/* The function does not use any synchronization.  Defined only if the  */
+/* library has been compiled without NO_CLOCK.                          */
+GC_API unsigned long GC_CALL GC_get_full_gc_total_time(void);
+
+/* Set whether the GC will allocate executable memory pages or not.     */
+/* A non-zero argument instructs the collector to allocate memory with  */
+/* the executable flag on.  Must be called before the collector is      */
+/* initialized.  May have no effect on some platforms.  The default     */
+/* value is controlled by NO_EXECUTE_PERMISSION macro (if present then  */
+/* the flag is off).  Portable clients should have                      */
+/* GC_set_pages_executable(1) call (before GC_INIT) provided they are   */
+/* going to execute code on any of the GC-allocated memory objects.     */
+GC_API void GC_CALL GC_set_pages_executable(int);
+
+/* Returns non-zero value if the GC is set to the allocate-executable   */
+/* mode.  The mode could be changed by GC_set_pages_executable (before  */
+/* GC_INIT) unless the former has no effect on the platform.  Does not  */
+/* use or need synchronization (i.e. acquiring the allocator lock).     */
+GC_API int GC_CALL GC_get_pages_executable(void);
+
+/* The setter and getter of the minimum value returned by the internal  */
+/* min_bytes_allocd().  The value should not be zero; the default value */
+/* is one.  Not synchronized.                                           */
+GC_API void GC_CALL GC_set_min_bytes_allocd(size_t);
+GC_API size_t GC_CALL GC_get_min_bytes_allocd(void);
+
+/* Set/get the size in pages of units operated by GC_collect_a_little.  */
+/* The value should not be zero.  Not synchronized.                     */
+GC_API void GC_CALL GC_set_rate(int);
+GC_API int GC_CALL GC_get_rate(void);
+
+/* Set/get the maximum number of prior attempts at the world-stop       */
+/* marking.  Not synchronized.                                          */
+GC_API void GC_CALL GC_set_max_prior_attempts(int);
+GC_API int GC_CALL GC_get_max_prior_attempts(void);
+
+/* Control whether to disable algorithm deciding if a collection should */
+/* be started when we allocated enough to amortize GC.  Both the setter */
+/* and the getter acquire the GC lock (to avoid data races).            */
+GC_API void GC_CALL GC_set_disable_automatic_collection(int);
+GC_API int GC_CALL GC_get_disable_automatic_collection(void);
+
+/* Overrides the default handle-fork mode.  Non-zero value means GC     */
+/* should install proper pthread_atfork handlers.  Has effect only if   */
+/* called before GC_INIT.  Clients should invoke GC_set_handle_fork     */
+/* with non-zero argument if going to use fork with GC functions called */
+/* in the forked child.  (Note that such client and atfork handlers     */
+/* activities are not fully POSIX-compliant.)  GC_set_handle_fork       */
+/* instructs GC_init to setup GC fork handlers using pthread_atfork,    */
+/* the latter might fail (or, even, absent on some targets) causing     */
+/* abort at GC initialization.  Issues with missing (or failed)         */
+/* pthread_atfork() could be avoided by invocation                      */
+/* of GC_set_handle_fork(-1) at application start-up and surrounding    */
+/* each fork() with the relevant GC_atfork_prepare/parent/child calls.  */
+GC_API void GC_CALL GC_set_handle_fork(int);
+
+/* Routines to handle POSIX fork() manually (no-op if handled           */
+/* automatically).  GC_atfork_prepare should be called immediately      */
+/* before fork(); GC_atfork_parent should be invoked just after fork in */
+/* the branch that corresponds to parent process (i.e., fork result is  */
+/* non-zero); GC_atfork_child is to be called immediately in the child  */
+/* branch (i.e., fork result is 0). Note that GC_atfork_child() call    */
+/* should, of course, precede GC_start_mark_threads call (if any).      */
+GC_API void GC_CALL GC_atfork_prepare(void);
+GC_API void GC_CALL GC_atfork_parent(void);
+GC_API void GC_CALL GC_atfork_child(void);
+
+/* Initialize the collector.  Portable clients should call GC_INIT()    */
+/* from the main program instead.                                       */
+GC_API void GC_CALL GC_init(void);
+
+/* Returns non-zero (TRUE) if and only if the collector is initialized  */
+/* (or, at least, the initialization is in progress).                   */
+GC_API int GC_CALL GC_is_init_called(void);
+
+/* Perform the collector shutdown.  (E.g. dispose critical sections on  */
+/* Win32 target.)  A duplicate invocation is a no-op.  GC_INIT should   */
+/* not be called after the shutdown.  See also GC_win32_free_heap().    */
+GC_API void GC_CALL GC_deinit(void);
+
+/* General purpose allocation routines, with roughly malloc calling     */
+/* conv.  The atomic versions promise that no relevant pointers are     */
+/* contained in the object.  The non-atomic versions guarantee that the */
+/* new object is cleared.  GC_malloc_uncollectable allocates            */
+/* an object that is scanned for pointers to collectible                */
+/* objects, but is not itself collectible.  The object is scanned even  */
+/* if it does not appear to be reachable.  GC_malloc_uncollectable and  */
+/* GC_free called on the resulting object implicitly update             */
+/* GC_non_gc_bytes appropriately.                                       */
+GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
+        GC_malloc(size_t /* size_in_bytes */);
+GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
+        GC_malloc_atomic(size_t /* size_in_bytes */);
+GC_API GC_ATTR_MALLOC char * GC_CALL GC_strdup(const char *);
+GC_API GC_ATTR_MALLOC char * GC_CALL
+        GC_strndup(const char *, size_t) GC_ATTR_NONNULL(1);
+GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
+        GC_malloc_uncollectable(size_t /* size_in_bytes */);
+GC_API GC_ATTR_DEPRECATED void * GC_CALL GC_malloc_stubborn(size_t);
+
+/* GC_memalign() is not well tested.                                    */
+GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(2) void * GC_CALL
+        GC_memalign(size_t /* align */, size_t /* lb */);
+GC_API int GC_CALL GC_posix_memalign(void ** /* memptr */, size_t /* align */,
+                        size_t /* lb */) GC_ATTR_NONNULL(1);
+
+/* Explicitly deallocate an object.  Dangerous if used incorrectly.     */
+/* Requires a pointer to the base of an object.                         */
+/* An object should not be enabled for finalization (and it should not  */
+/* contain registered disappearing links of any kind) when it is        */
+/* explicitly deallocated.                                              */
+/* GC_free(0) is a no-op, as required by ANSI C for free.               */
+GC_API void GC_CALL GC_free(void *);
+
+/* The "stubborn" objects allocation is not supported anymore.  Exists  */
+/* only for the backward compatibility.                                 */
+#define GC_MALLOC_STUBBORN(sz)  GC_MALLOC(sz)
+#define GC_NEW_STUBBORN(t)      GC_NEW(t)
+#define GC_CHANGE_STUBBORN(p)   GC_change_stubborn(p)
+GC_API GC_ATTR_DEPRECATED void GC_CALL GC_change_stubborn(const void *);
+
+/* Inform the collector that the object has been changed.               */
+/* Only non-NULL pointer stores into the object are considered to be    */
+/* changes.  Matters only if the incremental collection is enabled in   */
+/* the manual VDB mode (otherwise the function does nothing).           */
+/* Should be followed typically by GC_reachable_here called for each    */
+/* of the stored pointers.                                              */
+GC_API void GC_CALL GC_end_stubborn_change(const void *) GC_ATTR_NONNULL(1);
+
+/* Return a pointer to the base (lowest address) of an object given     */
+/* a pointer to a location within the object.                           */
+/* I.e., map an interior pointer to the corresponding base pointer.     */
+/* Note that with debugging allocation, this returns a pointer to the   */
+/* actual base of the object, i.e. the debug information, not to        */
+/* the base of the user object.                                         */
+/* Return 0 if displaced_pointer doesn't point to within a valid        */
+/* object.                                                              */
+/* Note that a deallocated object in the garbage collected heap         */
+/* may be considered valid, even if it has been deallocated with        */
+/* GC_free.                                                             */
+GC_API void * GC_CALL GC_base(void * /* displaced_pointer */);
+
+/* Return non-zero (TRUE) if and only if the argument points to         */
+/* somewhere in GC heap.  Primary use is as a fast alternative to       */
+/* GC_base to check whether the pointed object is allocated by GC       */
+/* or not.  It is assumed that the collector is already initialized.    */
+GC_API int GC_CALL GC_is_heap_ptr(const void *);
+
+/* Given a pointer to the base of an object, return its size in bytes.  */
+/* The returned size may be slightly larger than what was originally    */
+/* requested.                                                           */
+GC_API size_t GC_CALL GC_size(const void * /* obj_addr */) GC_ATTR_NONNULL(1);
+
+/* For compatibility with C library.  This is occasionally faster than  */
+/* a malloc followed by a bcopy.  But if you rely on that, either here  */
+/* or with the standard C library, your code is broken.  In my          */
+/* opinion, it shouldn't have been invented, but now we're stuck. -HB   */
+/* The resulting object has the same kind as the original.              */
+/* It is an error to have changes enabled for the original object.      */
+/* It does not change the content of the object from its beginning to   */
+/* the minimum of old size and new_size_in_bytes; the content above in  */
+/* case of object size growth is initialized to zero (not guaranteed    */
+/* for atomic object type).  The function follows ANSI conventions for  */
+/* NULL old_object (i.e., equivalent to GC_malloc regardless of new     */
+/* size).  If new size is zero (and old_object is non-NULL) then the    */
+/* call is equivalent to GC_free (and NULL is returned).  If old_object */
+/* is non-NULL, it must have been returned by an earlier call to        */
+/* GC_malloc* or GC_realloc.  In case of the allocation failure, the    */
+/* memory pointed by old_object is untouched (and not freed).           */
+/* If the returned pointer is not the same as old_object and both of    */
+/* them are non-NULL then old_object is freed.  Returns either NULL (in */
+/* case of the allocation failure or zero new size) or pointer to the   */
+/* allocated memory.                                                    */
+GC_API void * GC_CALL GC_realloc(void * /* old_object */,
+                                 size_t /* new_size_in_bytes */)
+                        /* 'realloc' attr */ GC_ATTR_ALLOC_SIZE(2);
+
+/* Explicitly increase the heap size.   */
+/* Returns 0 on failure, 1 on success.  */
+GC_API int GC_CALL GC_expand_hp(size_t /* number_of_bytes */);
+
+/* Limit the heap size to n bytes.  Useful when you're debugging,       */
+/* especially on systems that don't handle running out of memory well.  */
+/* n == 0 ==> unbounded.  This is the default.  This setter function is */
+/* unsynchronized (so it might require GC_call_with_alloc_lock to avoid */
+/* data races).                                                         */
+GC_API void GC_CALL GC_set_max_heap_size(GC_word /* n */);
+
+/* Inform the collector that a certain section of statically allocated  */
+/* memory contains no pointers to garbage collected memory.  Thus it    */
+/* need not be scanned.  This is sometimes important if the application */
+/* maps large read/write files into the address space, which could be   */
+/* mistaken for dynamic library data segments on some systems.          */
+/* Both section start and end are not needed to be pointer-aligned.     */
+GC_API void GC_CALL GC_exclude_static_roots(void * /* low_address */,
+                                            void * /* high_address_plus_1 */);
+
+/* Clear the number of entries in the exclusion table.  Wizards only.   */
+GC_API void GC_CALL GC_clear_exclusion_table(void);
+
+/* Clear the set of root segments.  Wizards only.                       */
+GC_API void GC_CALL GC_clear_roots(void);
+
+/* Add a root segment.  Wizards only.                                   */
+/* Both segment start and end are not needed to be pointer-aligned.     */
+/* low_address must not be greater than high_address_plus_1.            */
+GC_API void GC_CALL GC_add_roots(void * /* low_address */,
+                                 void * /* high_address_plus_1 */);
+
+/* Remove a root segment.  Wizards only.                                */
+/* May be unimplemented on some platforms.                              */
+GC_API void GC_CALL GC_remove_roots(void * /* low_address */,
+                                    void * /* high_address_plus_1 */);
+
+/* Add a displacement to the set of those considered valid by the       */
+/* collector.  GC_register_displacement(n) means that if p was returned */
+/* by GC_malloc, then (char *)p + n will be considered to be a valid    */
+/* pointer to p.  N must be small and less than the size of p.          */
+/* (All pointers to the interior of objects from the stack are          */
+/* considered valid in any case.  This applies to heap objects and      */
+/* static data.)                                                        */
+/* Preferably, this should be called before any other GC procedures.    */
+/* Calling it later adds to the probability of excess memory            */
+/* retention.                                                           */
+/* This is a no-op if the collector has recognition of                  */
+/* arbitrary interior pointers enabled, which is now the default.       */
+GC_API void GC_CALL GC_register_displacement(size_t /* n */);
+
+/* The following version should be used if any debugging allocation is  */
+/* being done.                                                          */
+GC_API void GC_CALL GC_debug_register_displacement(size_t /* n */);
+
+/* Explicitly trigger a full, world-stop collection.    */
+GC_API void GC_CALL GC_gcollect(void);
+
+/* Same as above but ignores the default stop_func setting and tries to */
+/* unmap as much memory as possible (regardless of the corresponding    */
+/* switch setting).  The recommended usage: on receiving a system       */
+/* low-memory event; before retrying a system call failed because of    */
+/* the system is running out of resources.                              */
+GC_API void GC_CALL GC_gcollect_and_unmap(void);
+
+/* Trigger a full world-stopped collection.  Abort the collection if    */
+/* and when stop_func returns a nonzero value.  Stop_func will be       */
+/* called frequently, and should be reasonably fast.  (stop_func is     */
+/* called with the allocation lock held and the world might be stopped; */
+/* it's not allowed for stop_func to manipulate pointers to the garbage */
+/* collected heap or call most of GC functions.)  This works even       */
+/* if virtual dirty bits, and hence incremental collection is not       */
+/* available for this architecture.  Collections can be aborted faster  */
+/* than normal pause times for incremental collection.  However,        */
+/* aborted collections do no useful work; the next collection needs     */
+/* to start from the beginning.  stop_func must not be 0.               */
+/* GC_try_to_collect() returns 0 if the collection was aborted (or the  */
+/* collections are disabled), 1 if it succeeded.                        */
+typedef int (GC_CALLBACK * GC_stop_func)(void);
+GC_API int GC_CALL GC_try_to_collect(GC_stop_func /* stop_func */)
+                                                        GC_ATTR_NONNULL(1);
+
+/* Set and get the default stop_func.  The default stop_func is used by */
+/* GC_gcollect() and by implicitly trigged collections (except for the  */
+/* case when handling out of memory).  Must not be 0.                   */
+/* Both the setter and getter acquire the GC lock to avoid data races.  */
+GC_API void GC_CALL GC_set_stop_func(GC_stop_func /* stop_func */)
+                                                        GC_ATTR_NONNULL(1);
+GC_API GC_stop_func GC_CALL GC_get_stop_func(void);
+
+/* Return the number of bytes in the heap.  Excludes collector private  */
+/* data structures.  Excludes the unmapped memory (returned to the OS). */
+/* Includes empty blocks and fragmentation loss.  Includes some pages   */
+/* that were allocated but never written.                               */
+/* This is an unsynchronized getter, so it should be called typically   */
+/* with the GC lock held to avoid data races on multiprocessors (the    */
+/* alternative is to use GC_get_heap_usage_safe or GC_get_prof_stats    */
+/* API calls instead).                                                  */
+/* This getter remains lock-free (unsynchronized) for compatibility     */
+/* reason since some existing clients call it from a GC callback        */
+/* holding the allocator lock.  (This API function and the following    */
+/* four ones below were made thread-safe in GC v7.2alpha1 and           */
+/* reverted back in v7.2alpha7 for the reason described.)               */
+GC_API size_t GC_CALL GC_get_heap_size(void);
+
+/* Return a lower bound on the number of free bytes in the heap         */
+/* (excluding the unmapped memory space).  This is an unsynchronized    */
+/* getter (see GC_get_heap_size comment regarding thread-safety).       */
+GC_API size_t GC_CALL GC_get_free_bytes(void);
+
+/* Return the size (in bytes) of the unmapped memory (which is returned */
+/* to the OS but could be remapped back by the collector later unless   */
+/* the OS runs out of system/virtual memory). This is an unsynchronized */
+/* getter (see GC_get_heap_size comment regarding thread-safety).       */
+GC_API size_t GC_CALL GC_get_unmapped_bytes(void);
+
+/* Return the number of bytes allocated since the last collection.      */
+/* This is an unsynchronized getter (see GC_get_heap_size comment       */
+/* regarding thread-safety).                                            */
+GC_API size_t GC_CALL GC_get_bytes_since_gc(void);
+
+/* Return the number of explicitly deallocated bytes of memory since    */
+/* the recent collection.  This is an unsynchronized getter.            */
+GC_API size_t GC_CALL GC_get_expl_freed_bytes_since_gc(void);
+
+/* Return the total number of bytes allocated in this process.          */
+/* Never decreases, except due to wrapping.  This is an unsynchronized  */
+/* getter (see GC_get_heap_size comment regarding thread-safety).       */
+GC_API size_t GC_CALL GC_get_total_bytes(void);
+
+/* Return the total number of bytes obtained from OS.  Includes the     */
+/* unmapped memory.  Never decreases.  It is an unsynchronized getter.  */
+GC_API size_t GC_CALL GC_get_obtained_from_os_bytes(void);
+
+/* Return the heap usage information.  This is a thread-safe (atomic)   */
+/* alternative for the five above getters.   (This function acquires    */
+/* the allocator lock thus preventing data racing and returning the     */
+/* consistent result.)  Passing NULL pointer is allowed for any         */
+/* argument.  Returned (filled in) values are of word type.             */
+GC_API void GC_CALL GC_get_heap_usage_safe(GC_word * /* pheap_size */,
+                                           GC_word * /* pfree_bytes */,
+                                           GC_word * /* punmapped_bytes */,
+                                           GC_word * /* pbytes_since_gc */,
+                                           GC_word * /* ptotal_bytes */);
+
+/* Structure used to query GC statistics (profiling information).       */
+/* More fields could be added in the future.  To preserve compatibility */
+/* new fields should be added only to the end, and no deprecated fields */
+/* should be removed from.                                              */
+struct GC_prof_stats_s {
+  GC_word heapsize_full;
+            /* Heap size in bytes (including the area unmapped to OS).  */
+            /* Same as GC_get_heap_size() + GC_get_unmapped_bytes().    */
+  GC_word free_bytes_full;
+            /* Total bytes contained in free and unmapped blocks.       */
+            /* Same as GC_get_free_bytes() + GC_get_unmapped_bytes().   */
+  GC_word unmapped_bytes;
+            /* Amount of memory unmapped to OS.  Same as the value      */
+            /* returned by GC_get_unmapped_bytes().                     */
+  GC_word bytes_allocd_since_gc;
+            /* Number of bytes allocated since the recent collection.   */
+            /* Same as returned by GC_get_bytes_since_gc().             */
+  GC_word allocd_bytes_before_gc;
+            /* Number of bytes allocated before the recent garbage      */
+            /* collection.  The value may wrap.  Same as the result of  */
+            /* GC_get_total_bytes() - GC_get_bytes_since_gc().          */
+  GC_word non_gc_bytes;
+            /* Number of bytes not considered candidates for garbage    */
+            /* collection.  Same as returned by GC_get_non_gc_bytes().  */
+  GC_word gc_no;
+            /* Garbage collection cycle number.  The value may wrap     */
+            /* (and could be -1).  Same as returned by GC_get_gc_no().  */
+  GC_word markers_m1;
+            /* Number of marker threads (excluding the initiating one). */
+            /* Same as returned by GC_get_parallel (or 0 if the         */
+            /* collector is single-threaded).                           */
+  GC_word bytes_reclaimed_since_gc;
+            /* Approximate number of reclaimed bytes after recent GC.   */
+  GC_word reclaimed_bytes_before_gc;
+            /* Approximate number of bytes reclaimed before the recent  */
+            /* garbage collection.  The value may wrap.                 */
+  GC_word expl_freed_bytes_since_gc;
+            /* Number of bytes freed explicitly since the recent GC.    */
+            /* Same as returned by GC_get_expl_freed_bytes_since_gc().  */
+  GC_word obtained_from_os_bytes;
+            /* Total amount of memory obtained from OS, in bytes.       */
+};
+
+/* Atomically get GC statistics (various global counters).  Clients     */
+/* should pass the size of the buffer (of GC_prof_stats_s type) to fill */
+/* in the values - this is for interoperability between different GC    */
+/* versions, an old client could have fewer fields, and vice versa,     */
+/* client could use newer gc.h (with more entries declared in the       */
+/* structure) than that of the linked libgc binary; in the latter case, */
+/* unsupported (unknown) fields are filled in with -1.  Return the size */
+/* (in bytes) of the filled in part of the structure (excluding all     */
+/* unknown fields, if any).                                             */
+GC_API size_t GC_CALL GC_get_prof_stats(struct GC_prof_stats_s *,
+                                        size_t /* stats_sz */);
+#ifdef GC_THREADS
+  /* Same as above but unsynchronized (i.e., not holding the allocation */
+  /* lock).  Clients should call it using GC_call_with_alloc_lock to    */
+  /* avoid data races on multiprocessors.                               */
+  GC_API size_t GC_CALL GC_get_prof_stats_unsafe(struct GC_prof_stats_s *,
+                                                 size_t /* stats_sz */);
+#endif
+
+/* Get the element value (converted to bytes) at a given index of       */
+/* size_map table which provides requested-to-actual allocation size    */
+/* mapping.  Assumes the collector is initialized.  Returns -1 if the   */
+/* index is out of size_map table bounds. Does not use synchronization, */
+/* thus clients should call it using GC_call_with_alloc_lock typically  */
+/* to avoid data races on multiprocessors.                              */
+GC_API size_t GC_CALL GC_get_size_map_at(int i);
+
+/* Count total memory use in bytes by all allocated blocks.  Acquires   */
+/* the lock.                                                            */
+GC_API size_t GC_CALL GC_get_memory_use(void);
+
+/* Disable garbage collection.  Even GC_gcollect calls will be          */
+/* ineffective.                                                         */
+GC_API void GC_CALL GC_disable(void);
+
+/* Return non-zero (TRUE) if and only if garbage collection is disabled */
+/* (i.e., GC_dont_gc value is non-zero).  Does not acquire the lock.    */
+GC_API int GC_CALL GC_is_disabled(void);
+
+/* Try to re-enable garbage collection.  GC_disable() and GC_enable()   */
+/* calls nest.  Garbage collection is enabled if the number of calls to */
+/* both functions is equal.                                             */
+GC_API void GC_CALL GC_enable(void);
+
+/* Select whether to use the manual VDB mode for the incremental        */
+/* collection.  Has no effect if called after enabling the incremental  */
+/* collection.  The default value is off unless the collector is        */
+/* compiled with MANUAL_VDB defined.  The manual VDB mode should be     */
+/* used only if the client has the appropriate GC_END_STUBBORN_CHANGE   */
+/* and GC_reachable_here (or, alternatively, GC_PTR_STORE_AND_DIRTY)    */
+/* calls (to ensure proper write barriers).  Both the setter and getter */
+/* are not synchronized, and are defined only if the library has been   */
+/* compiled without SMALL_CONFIG.                                       */
+GC_API void GC_CALL GC_set_manual_vdb_allowed(int);
+GC_API int GC_CALL GC_get_manual_vdb_allowed(void);
+
+/* Enable incremental/generational collection.  Not advisable unless    */
+/* dirty bits are available or most heap objects are pointer-free       */
+/* (atomic) or immutable.  Don't use in leak finding mode.  Ignored if  */
+/* GC_dont_gc is non-zero.  Only the generational piece of this is      */
+/* functional if GC_time_limit is set to GC_TIME_UNLIMITED.  Causes     */
+/* thread-local variant of GC_gcj_malloc() to revert to locked          */
+/* allocation.  Must be called before any such GC_gcj_malloc() calls.   */
+/* For best performance, should be called as early as possible.         */
+/* On some platforms, calling it later may have adverse effects.        */
+/* Safe to call before GC_INIT().  Includes a  GC_init() call.          */
+GC_API void GC_CALL GC_enable_incremental(void);
+
+/* Return non-zero (TRUE) if and only if the incremental mode is on.    */
+/* Does not acquire the lock.                                           */
+GC_API int GC_CALL GC_is_incremental_mode(void);
+
+#define GC_PROTECTS_POINTER_HEAP  1 /* May protect non-atomic objects.  */
+#define GC_PROTECTS_PTRFREE_HEAP  2
+#define GC_PROTECTS_STATIC_DATA   4 /* Currently never.                 */
+#define GC_PROTECTS_STACK         8 /* Probably impractical.            */
+
+#define GC_PROTECTS_NONE 0
+
+/* Does incremental mode write-protect pages?  Returns zero or  */
+/* more of the above GC_PROTECTS_*, or'ed together.             */
+/* The collector is assumed to be initialized before this call. */
+/* The result is not affected by GC_set_manual_vdb_allowed().   */
+/* Call of GC_enable_incremental() may change the result to     */
+/* GC_PROTECTS_NONE if some implementation is chosen at runtime */
+/* not needing to write-protect the pages.                      */
+GC_API int GC_CALL GC_incremental_protection_needs(void);
+
+/* Force start of incremental collection.  Acquires the GC lock.        */
+/* No-op unless GC incremental mode is on.                              */
+GC_API void GC_CALL GC_start_incremental_collection(void);
+
+/* Perform some garbage collection work, if appropriate.        */
+/* Return 0 if there is no more work to be done (including the  */
+/* case when garbage collection is not appropriate).            */
+/* Typically performs an amount of work corresponding roughly   */
+/* to marking from one page.  May do more work if further       */
+/* progress requires it, e.g. if incremental collection is      */
+/* disabled.  It is reasonable to call this in a wait loop      */
+/* until it returns 0.                                          */
+GC_API int GC_CALL GC_collect_a_little(void);
+
+/* Allocate an object of size lb bytes.  The client guarantees that     */
+/* as long as the object is live, it will be referenced by a pointer    */
+/* that points to somewhere within the first 256 bytes of the object.   */
+/* (This should normally be declared volatile to prevent the compiler   */
+/* from invalidating this assertion.)  This routine is only useful      */
+/* if a large array is being allocated.  It reduces the chance of       */
+/* accidentally retaining such an array as a result of scanning an      */
+/* integer that happens to be an address inside the array.  (Actually,  */
+/* it reduces the chance of the allocator not finding space for such    */
+/* an array, since it will try hard to avoid introducing such a false   */
+/* reference.)  On a SunOS 4.X or MS Windows system this is recommended */
+/* for arrays likely to be larger than 100 KB or so.  For other systems,*/
+/* or if the collector is not configured to recognize all interior      */
+/* pointers, the threshold is normally much higher.                     */
+GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
+        GC_malloc_ignore_off_page(size_t /* lb */);
+GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
+        GC_malloc_atomic_ignore_off_page(size_t /* lb */);
+
+#ifdef GC_ADD_CALLER
+# define GC_EXTRAS GC_RETURN_ADDR, __FILE__, __LINE__
+# define GC_EXTRA_PARAMS GC_word ra, const char * s, int i
+#else
+# define GC_EXTRAS __FILE__, __LINE__
+# define GC_EXTRA_PARAMS const char * s, int i
+#endif
+
+/* The following is only defined if the library has been suitably       */
+/* compiled:                                                            */
+GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
+        GC_malloc_atomic_uncollectable(size_t /* size_in_bytes */);
+GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
+        GC_debug_malloc_atomic_uncollectable(size_t, GC_EXTRA_PARAMS);
+
+/* Debugging (annotated) allocation.  GC_gcollect will check            */
+/* objects allocated in this way for overwrites, etc.                   */
+GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
+        GC_debug_malloc(size_t /* size_in_bytes */, GC_EXTRA_PARAMS);
+GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
+        GC_debug_malloc_atomic(size_t /* size_in_bytes */, GC_EXTRA_PARAMS);
+GC_API GC_ATTR_MALLOC char * GC_CALL
+        GC_debug_strdup(const char *, GC_EXTRA_PARAMS);
+GC_API GC_ATTR_MALLOC char * GC_CALL
+        GC_debug_strndup(const char *, size_t, GC_EXTRA_PARAMS)
+                                                        GC_ATTR_NONNULL(1);
+GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
+        GC_debug_malloc_uncollectable(size_t /* size_in_bytes */,
+                                      GC_EXTRA_PARAMS);
+GC_API GC_ATTR_DEPRECATED void * GC_CALL
+        GC_debug_malloc_stubborn(size_t /* size_in_bytes */, GC_EXTRA_PARAMS);
+GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
+        GC_debug_malloc_ignore_off_page(size_t /* size_in_bytes */,
+                                        GC_EXTRA_PARAMS);
+GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
+        GC_debug_malloc_atomic_ignore_off_page(size_t /* size_in_bytes */,
+                                        GC_EXTRA_PARAMS);
+GC_API void GC_CALL GC_debug_free(void *);
+GC_API void * GC_CALL GC_debug_realloc(void * /* old_object */,
+                        size_t /* new_size_in_bytes */, GC_EXTRA_PARAMS)
+                        /* 'realloc' attr */ GC_ATTR_ALLOC_SIZE(2);
+GC_API GC_ATTR_DEPRECATED void GC_CALL GC_debug_change_stubborn(const void *);
+GC_API void GC_CALL GC_debug_end_stubborn_change(const void *)
+                                                        GC_ATTR_NONNULL(1);
+
+/* Routines that allocate objects with debug information (like the      */
+/* above), but just fill in dummy file and line number information.     */
+/* Thus they can serve as drop-in malloc/realloc replacements.  This    */
+/* can be useful for two reasons:                                       */
+/* 1) It allows the collector to be built with DBG_HDRS_ALL defined     */
+/*    even if some allocation calls come from 3rd party libraries       */
+/*    that can't be recompiled.                                         */
+/* 2) On some platforms, the file and line information is redundant,    */
+/*    since it can be reconstructed from a stack trace.  On such        */
+/*    platforms it may be more convenient not to recompile, e.g. for    */
+/*    leak detection.  This can be accomplished by instructing the      */
+/*    linker to replace malloc/realloc with these.                      */
+GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
+        GC_debug_malloc_replacement(size_t /* size_in_bytes */);
+GC_API /* 'realloc' attr */ GC_ATTR_ALLOC_SIZE(2) void * GC_CALL
+        GC_debug_realloc_replacement(void * /* object_addr */,
+                                     size_t /* size_in_bytes */);
+
+#ifdef GC_DEBUG_REPLACEMENT
+# define GC_MALLOC(sz) GC_debug_malloc_replacement(sz)
+# define GC_REALLOC(old, sz) GC_debug_realloc_replacement(old, sz)
+#elif defined(GC_DEBUG)
+# define GC_MALLOC(sz) GC_debug_malloc(sz, GC_EXTRAS)
+# define GC_REALLOC(old, sz) GC_debug_realloc(old, sz, GC_EXTRAS)
+#else
+# define GC_MALLOC(sz) GC_malloc(sz)
+# define GC_REALLOC(old, sz) GC_realloc(old, sz)
+#endif /* !GC_DEBUG_REPLACEMENT && !GC_DEBUG */
+
+#ifdef GC_DEBUG
+# define GC_MALLOC_ATOMIC(sz) GC_debug_malloc_atomic(sz, GC_EXTRAS)
+# define GC_STRDUP(s) GC_debug_strdup(s, GC_EXTRAS)
+# define GC_STRNDUP(s, sz) GC_debug_strndup(s, sz, GC_EXTRAS)
+# define GC_MALLOC_ATOMIC_UNCOLLECTABLE(sz) \
+                        GC_debug_malloc_atomic_uncollectable(sz, GC_EXTRAS)
+# define GC_MALLOC_UNCOLLECTABLE(sz) \
+                        GC_debug_malloc_uncollectable(sz, GC_EXTRAS)
+# define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
+                        GC_debug_malloc_ignore_off_page(sz, GC_EXTRAS)
+# define GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(sz) \
+                        GC_debug_malloc_atomic_ignore_off_page(sz, GC_EXTRAS)
+# define GC_FREE(p) GC_debug_free(p)
+# define GC_REGISTER_FINALIZER(p, f, d, of, od) \
+      GC_debug_register_finalizer(p, f, d, of, od)
+# define GC_REGISTER_FINALIZER_IGNORE_SELF(p, f, d, of, od) \
+      GC_debug_register_finalizer_ignore_self(p, f, d, of, od)
+# define GC_REGISTER_FINALIZER_NO_ORDER(p, f, d, of, od) \
+      GC_debug_register_finalizer_no_order(p, f, d, of, od)
+# define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \
+      GC_debug_register_finalizer_unreachable(p, f, d, of, od)
+# define GC_END_STUBBORN_CHANGE(p) GC_debug_end_stubborn_change(p)
+# define GC_PTR_STORE_AND_DIRTY(p, q) GC_debug_ptr_store_and_dirty(p, q)
+# define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \
+      GC_general_register_disappearing_link(link, \
+                                        GC_base((/* no const */ void *)(obj)))
+# define GC_REGISTER_LONG_LINK(link, obj) \
+      GC_register_long_link(link, GC_base((/* no const */ void *)(obj)))
+# define GC_REGISTER_DISPLACEMENT(n) GC_debug_register_displacement(n)
+#else
+# define GC_MALLOC_ATOMIC(sz) GC_malloc_atomic(sz)
+# define GC_STRDUP(s) GC_strdup(s)
+# define GC_STRNDUP(s, sz) GC_strndup(s, sz)
+# define GC_MALLOC_ATOMIC_UNCOLLECTABLE(sz) GC_malloc_atomic_uncollectable(sz)
+# define GC_MALLOC_UNCOLLECTABLE(sz) GC_malloc_uncollectable(sz)
+# define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
+                        GC_malloc_ignore_off_page(sz)
+# define GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(sz) \
+                        GC_malloc_atomic_ignore_off_page(sz)
+# define GC_FREE(p) GC_free(p)
+# define GC_REGISTER_FINALIZER(p, f, d, of, od) \
+      GC_register_finalizer(p, f, d, of, od)
+# define GC_REGISTER_FINALIZER_IGNORE_SELF(p, f, d, of, od) \
+      GC_register_finalizer_ignore_self(p, f, d, of, od)
+# define GC_REGISTER_FINALIZER_NO_ORDER(p, f, d, of, od) \
+      GC_register_finalizer_no_order(p, f, d, of, od)
+# define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \
+      GC_register_finalizer_unreachable(p, f, d, of, od)
+# define GC_END_STUBBORN_CHANGE(p) GC_end_stubborn_change(p)
+# define GC_PTR_STORE_AND_DIRTY(p, q) GC_ptr_store_and_dirty(p, q)
+# define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \
+      GC_general_register_disappearing_link(link, obj)
+# define GC_REGISTER_LONG_LINK(link, obj) \
+      GC_register_long_link(link, obj)
+# define GC_REGISTER_DISPLACEMENT(n) GC_register_displacement(n)
+#endif /* !GC_DEBUG */
+
+/* The following are included because they are often convenient, and    */
+/* reduce the chance for a misspecified size argument.  But calls may   */
+/* expand to something syntactically incorrect if t is a complicated    */
+/* type expression.  Note that, unlike C++ new operator, these ones     */
+/* may return NULL (if out of memory).                                  */
+#define GC_NEW(t)               ((t*)GC_MALLOC(sizeof(t)))
+#define GC_NEW_ATOMIC(t)        ((t*)GC_MALLOC_ATOMIC(sizeof(t)))
+#define GC_NEW_UNCOLLECTABLE(t) ((t*)GC_MALLOC_UNCOLLECTABLE(sizeof(t)))
+
+#ifdef GC_REQUIRE_WCSDUP
+  /* This might be unavailable on some targets (or not needed). */
+  /* wchar_t should be defined in stddef.h */
+  GC_API GC_ATTR_MALLOC wchar_t * GC_CALL
+        GC_wcsdup(const wchar_t *) GC_ATTR_NONNULL(1);
+  GC_API GC_ATTR_MALLOC wchar_t * GC_CALL
+        GC_debug_wcsdup(const wchar_t *, GC_EXTRA_PARAMS) GC_ATTR_NONNULL(1);
+# ifdef GC_DEBUG
+#   define GC_WCSDUP(s) GC_debug_wcsdup(s, GC_EXTRAS)
+# else
+#   define GC_WCSDUP(s) GC_wcsdup(s)
+# endif
+#endif /* GC_REQUIRE_WCSDUP */
+
+/* Finalization.  Some of these primitives are grossly unsafe.          */
+/* The idea is to make them both cheap, and sufficient to build         */
+/* a safer layer, closer to Modula-3, Java, or PCedar finalization.     */
+/* The interface represents my conclusions from a long discussion       */
+/* with Alan Demers, Dan Greene, Carl Hauser, Barry Hayes,              */
+/* Christian Jacobi, and Russ Atkinson.  It's not perfect, and          */
+/* probably nobody else agrees with it.     Hans-J. Boehm  3/13/92      */
+typedef void (GC_CALLBACK * GC_finalization_proc)(void * /* obj */,
+                                                  void * /* client_data */);
+
+GC_API void GC_CALL GC_register_finalizer(void * /* obj */,
+                        GC_finalization_proc /* fn */, void * /* cd */,
+                        GC_finalization_proc * /* ofn */, void ** /* ocd */)
+                                                GC_ATTR_NONNULL(1);
+GC_API void GC_CALL GC_debug_register_finalizer(void * /* obj */,
+                        GC_finalization_proc /* fn */, void * /* cd */,
+                        GC_finalization_proc * /* ofn */, void ** /* ocd */)
+                                                GC_ATTR_NONNULL(1);
+        /* When obj is no longer accessible, invoke             */
+        /* (*fn)(obj, cd).  If a and b are inaccessible, and    */
+        /* a points to b (after disappearing links have been    */
+        /* made to disappear), then only a will be              */
+        /* finalized.  (If this does not create any new         */
+        /* pointers to b, then b will be finalized after the    */
+        /* next collection.)  Any finalizable object that       */
+        /* is reachable from itself by following one or more    */
+        /* pointers will not be finalized (or collected).       */
+        /* Thus cycles involving finalizable objects should     */
+        /* be avoided, or broken by disappearing links.         */
+        /* All but the last finalizer registered for an object  */
+        /* is ignored.                                          */
+        /* No-op in the leak-finding mode.                      */
+        /* Finalization may be removed by passing 0 as fn.      */
+        /* Finalizers are implicitly unregistered when they are */
+        /* enqueued for finalization (i.e. become ready to be   */
+        /* finalized).                                          */
+        /* The old finalizer and client data are stored in      */
+        /* *ofn and *ocd.  (ofn and/or ocd may be NULL.         */
+        /* The allocation lock is held while *ofn and *ocd are  */
+        /* updated.  In case of error (no memory to register    */
+        /* new finalizer), *ofn and *ocd remain unchanged.)     */
+        /* Fn is never invoked on an accessible object,         */
+        /* provided hidden pointers are converted to real       */
+        /* pointers only if the allocation lock is held, and    */
+        /* such conversions are not performed by finalization   */
+        /* routines.                                            */
+        /* If GC_register_finalizer is aborted as a result of   */
+        /* a signal, the object may be left with no             */
+        /* finalization, even if neither the old nor new        */
+        /* finalizer were NULL.                                 */
+        /* Obj should be the starting address of an object      */
+        /* allocated by GC_malloc or friends. Obj may also be   */
+        /* NULL or point to something outside GC heap (in this  */
+        /* case, fn is ignored, *ofn and *ocd are set to NULL). */
+        /* Note that any garbage collectible object referenced  */
+        /* by cd will be considered accessible until the        */
+        /* finalizer is invoked.                                */
+
+/* Another versions of the above follow.  It ignores            */
+/* self-cycles, i.e. pointers from a finalizable object to      */
+/* itself.  There is a stylistic argument that this is wrong,   */
+/* but it's unavoidable for C++, since the compiler may         */
+/* silently introduce these.  It's also benign in that specific */
+/* case.  And it helps if finalizable objects are split to      */
+/* avoid cycles.                                                */
+/* Note that cd will still be viewed as accessible, even if it  */
+/* refers to the object itself.                                 */
+GC_API void GC_CALL GC_register_finalizer_ignore_self(void * /* obj */,
+                        GC_finalization_proc /* fn */, void * /* cd */,
+                        GC_finalization_proc * /* ofn */, void ** /* ocd */)
+                                                GC_ATTR_NONNULL(1);
+GC_API void GC_CALL GC_debug_register_finalizer_ignore_self(void * /* obj */,
+                        GC_finalization_proc /* fn */, void * /* cd */,
+                        GC_finalization_proc * /* ofn */, void ** /* ocd */)
+                                                GC_ATTR_NONNULL(1);
+
+/* Another version of the above.  It ignores all cycles.        */
+/* It should probably only be used by Java implementations.     */
+/* Note that cd will still be viewed as accessible, even if it  */
+/* refers to the object itself.                                 */
+GC_API void GC_CALL GC_register_finalizer_no_order(void * /* obj */,
+                        GC_finalization_proc /* fn */, void * /* cd */,
+                        GC_finalization_proc * /* ofn */, void ** /* ocd */)
+                                                GC_ATTR_NONNULL(1);
+GC_API void GC_CALL GC_debug_register_finalizer_no_order(void * /* obj */,
+                        GC_finalization_proc /* fn */, void * /* cd */,
+                        GC_finalization_proc * /* ofn */, void ** /* ocd */)
+                                                GC_ATTR_NONNULL(1);
+
+/* This is a special finalizer that is useful when an object's  */
+/* finalizer must be run when the object is known to be no      */
+/* longer reachable, not even from other finalizable objects.   */
+/* It behaves like "normal" finalization, except that the       */
+/* finalizer is not run while the object is reachable from      */
+/* other objects specifying unordered finalization.             */
+/* Effectively it allows an object referenced, possibly         */
+/* indirectly, from an unordered finalizable object to override */
+/* the unordered finalization request.                          */
+/* This can be used in combination with finalizer_no_order so   */
+/* as to release resources that must not be released while an   */
+/* object can still be brought back to life by other            */
+/* finalizers.                                                  */
+/* Only works if GC_java_finalization is set.  Probably only    */
+/* of interest when implementing a language that requires       */
+/* unordered finalization (e.g. Java, C#).                      */
+GC_API void GC_CALL GC_register_finalizer_unreachable(void * /* obj */,
+                        GC_finalization_proc /* fn */, void * /* cd */,
+                        GC_finalization_proc * /* ofn */, void ** /* ocd */)
+                                                GC_ATTR_NONNULL(1);
+GC_API void GC_CALL GC_debug_register_finalizer_unreachable(void * /* obj */,
+                        GC_finalization_proc /* fn */, void * /* cd */,
+                        GC_finalization_proc * /* ofn */, void ** /* ocd */)
+                                                GC_ATTR_NONNULL(1);
+
+#define GC_NO_MEMORY 2  /* Failure due to lack of memory.       */
+
+/* The following routine may be used to break cycles between    */
+/* finalizable objects, thus causing cyclic finalizable         */
+/* objects to be finalized in the correct order.  Standard      */
+/* use involves calling GC_register_disappearing_link(&p),      */
+/* where p is a pointer that is not followed by finalization    */
+/* code, and should not be considered in determining            */
+/* finalization order.                                          */
+GC_API int GC_CALL GC_register_disappearing_link(void ** /* link */)
+                                                GC_ATTR_NONNULL(1);
+        /* Link should point to a field of a heap allocated     */
+        /* object obj.  *link will be cleared when obj is       */
+        /* found to be inaccessible.  This happens BEFORE any   */
+        /* finalization code is invoked, and BEFORE any         */
+        /* decisions about finalization order are made.         */
+        /* This is useful in telling the finalizer that         */
+        /* some pointers are not essential for proper           */
+        /* finalization.  This may avoid finalization cycles.   */
+        /* Note that obj may be resurrected by another          */
+        /* finalizer, and thus the clearing of *link may        */
+        /* be visible to non-finalization code.                 */
+        /* There's an argument that an arbitrary action should  */
+        /* be allowed here, instead of just clearing a pointer. */
+        /* But this causes problems if that action alters, or   */
+        /* examines connectivity.  Returns GC_DUPLICATE if link */
+        /* was already registered, GC_SUCCESS if registration   */
+        /* succeeded, GC_NO_MEMORY if it failed for lack of     */
+        /* memory, and GC_oom_fn did not handle the problem.    */
+        /* Only exists for backward compatibility.  See below:  */
+
+GC_API int GC_CALL GC_general_register_disappearing_link(void ** /* link */,
+                                                    const void * /* obj */)
+                        GC_ATTR_NONNULL(1) GC_ATTR_NONNULL(2);
+        /* A slight generalization of the above. *link is       */
+        /* cleared when obj first becomes inaccessible.  This   */
+        /* can be used to implement weak pointers easily and    */
+        /* safely. Typically link will point to a location      */
+        /* holding a disguised pointer to obj.  (A pointer      */
+        /* inside an "atomic" object is effectively disguised.) */
+        /* In this way, weak pointers are broken before any     */
+        /* object reachable from them gets finalized.           */
+        /* Each link may be registered only with one obj value, */
+        /* i.e. all objects but the last one (link registered   */
+        /* with) are ignored.  This was added after a long      */
+        /* email discussion with John Ellis.                    */
+        /* link must be non-NULL (and be properly aligned).     */
+        /* obj must be a pointer to the first word of an object */
+        /* allocated by GC_malloc or friends.   A link          */
+        /* disappears when it is unregistered manually, or when */
+        /* (*link) is cleared, or when the object containing    */
+        /* this link is garbage collected.  It is unsafe to     */
+        /* explicitly deallocate the object containing link.    */
+        /* Explicit deallocation of obj may or may not cause    */
+        /* link to eventually be cleared.                       */
+        /* No-op in the leak-finding mode.                      */
+        /* This function can be used to implement certain types */
+        /* of weak pointers.  Note, however, this generally     */
+        /* requires that the allocation lock is held (see       */
+        /* GC_call_with_alloc_lock() below) when the disguised  */
+        /* pointer is accessed.  Otherwise a strong pointer     */
+        /* could be recreated between the time the collector    */
+        /* decides to reclaim the object and the link is        */
+        /* cleared.  Returns GC_SUCCESS if registration         */
+        /* succeeded (a new link is registered), GC_DUPLICATE   */
+        /* if link was already registered (with some object),   */
+        /* GC_NO_MEMORY if registration failed for lack of      */
+        /* memory (and GC_oom_fn did not handle the problem),   */
+        /* GC_UNIMPLEMENTED if GC_find_leak is true.            */
+
+GC_API int GC_CALL GC_move_disappearing_link(void ** /* link */,
+                                             void ** /* new_link */)
+                        GC_ATTR_NONNULL(2);
+        /* Moves a link previously registered via               */
+        /* GC_general_register_disappearing_link (or            */
+        /* GC_register_disappearing_link).  Does not change the */
+        /* target object of the weak reference.  Does not       */
+        /* change (*new_link) content.  May be called with      */
+        /* new_link equal to link (to check whether link has    */
+        /* been registered).  Returns GC_SUCCESS on success,    */
+        /* GC_DUPLICATE if there is already another             */
+        /* disappearing link at the new location (never         */
+        /* returned if new_link is equal to link), GC_NOT_FOUND */
+        /* if no link is registered at the original location.   */
+
+GC_API int GC_CALL GC_unregister_disappearing_link(void ** /* link */);
+        /* Undoes a registration by either of the above two     */
+        /* routines.  Returns 0 if link was not actually        */
+        /* registered (otherwise returns 1).                    */
+
+GC_API int GC_CALL GC_register_long_link(void ** /* link */,
+                                    const void * /* obj */)
+                        GC_ATTR_NONNULL(1) GC_ATTR_NONNULL(2);
+        /* Similar to GC_general_register_disappearing_link but */
+        /* *link only gets cleared when obj becomes truly       */
+        /* inaccessible.  An object becomes truly inaccessible  */
+        /* when it can no longer be resurrected from its        */
+        /* finalizer (e.g. by assigning itself to a pointer     */
+        /* traceable from root).  This can be used to implement */
+        /* long weak pointers easily and safely.                */
+
+GC_API int GC_CALL GC_move_long_link(void ** /* link */,
+                                     void ** /* new_link */)
+                        GC_ATTR_NONNULL(2);
+        /* Similar to GC_move_disappearing_link but for a link  */
+        /* previously registered via GC_register_long_link.     */
+
+GC_API int GC_CALL GC_unregister_long_link(void ** /* link */);
+        /* Similar to GC_unregister_disappearing_link but for a */
+        /* registration by either of the above two routines.    */
+
+/* Support of toggle-ref style of external memory management    */
+/* without hooking up to the host retain/release machinery.     */
+/* The idea of toggle-ref is that an external reference to      */
+/* an object is kept and it can be either a strong or weak      */
+/* reference; a weak reference is used when the external peer   */
+/* has no interest in the object, and a strong otherwise.       */
+typedef enum {
+   GC_TOGGLE_REF_DROP,
+   GC_TOGGLE_REF_STRONG,
+   GC_TOGGLE_REF_WEAK
+} GC_ToggleRefStatus;
+
+/* The callback is to decide (return) the new state of a given  */
+/* object.  Invoked by the collector for all objects registered */
+/* for toggle-ref processing.  Invoked with the allocation lock */
+/* held (but the "world" is running).                           */
+typedef GC_ToggleRefStatus (GC_CALLBACK *GC_toggleref_func)(void * /* obj */);
+
+/* Set (register) a callback that decides the state of a given  */
+/* object (by, probably, inspecting its native state).          */
+/* The argument may be 0 (means no callback).  Both the setter  */
+/* and the getter acquire the allocation lock (to avoid data    */
+/* races).                                                      */
+GC_API void GC_CALL GC_set_toggleref_func(GC_toggleref_func);
+GC_API GC_toggleref_func GC_CALL GC_get_toggleref_func(void);
+
+/* Register a given object for toggle-ref processing.  It will  */
+/* be stored internally and the toggle-ref callback will be     */
+/* invoked on the object until the callback returns             */
+/* GC_TOGGLE_REF_DROP or the object is collected.  If is_strong */
+/* is true then the object is registered with a strong ref,     */
+/* a weak one otherwise.  Returns GC_SUCCESS if registration    */
+/* succeeded (or no callback registered yet), GC_NO_MEMORY if   */
+/* it failed for lack of memory.                                */
+GC_API int GC_CALL GC_toggleref_add(void * /* obj */, int /* is_strong */)
+                                                GC_ATTR_NONNULL(1);
+
+/* Finalizer callback support.  Invoked by the collector (with  */
+/* the allocation lock held) for each unreachable object        */
+/* enqueued for finalization.                                   */
+typedef void (GC_CALLBACK * GC_await_finalize_proc)(void * /* obj */);
+GC_API void GC_CALL GC_set_await_finalize_proc(GC_await_finalize_proc);
+GC_API GC_await_finalize_proc GC_CALL GC_get_await_finalize_proc(void);
+                        /* Zero means no callback.  The setter  */
+                        /* and getter acquire the lock too.     */
+
+/* Returns !=0 if GC_invoke_finalizers has something to do.     */
+/* Does not use any synchronization.                            */
+GC_API int GC_CALL GC_should_invoke_finalizers(void);
+
+GC_API int GC_CALL GC_invoke_finalizers(void);
+        /* Run finalizers for all objects that are ready to     */
+        /* be finalized.  Return the number of finalizers       */
+        /* that were run.  Normally this is also called         */
+        /* implicitly during some allocations.  If              */
+        /* GC_finalize_on_demand is nonzero, it must be called  */
+        /* explicitly.                                          */
+
+/* Explicitly tell the collector that an object is reachable    */
+/* at a particular program point.  This prevents the argument   */
+/* pointer from being optimized away, even it is otherwise no   */
+/* longer needed.  It should have no visible effect in the      */
+/* absence of finalizers or disappearing links.  But it may be  */
+/* needed to prevent finalizers from running while the          */
+/* associated external resource is still in use.                */
+/* The function is sometimes called keep_alive in other         */
+/* settings.                                                    */
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+# define GC_reachable_here(ptr) \
+                __asm__ __volatile__(" " : : "X"(ptr) : "memory")
+#else
+  GC_API void GC_CALL GC_noop1(GC_word);
+# ifdef LINT2
+#   define GC_reachable_here(ptr) GC_noop1(~(GC_word)(ptr)^(~(GC_word)0))
+                /* The expression matches the one of COVERT_DATAFLOW(). */
+# else
+#   define GC_reachable_here(ptr) GC_noop1((GC_word)(ptr))
+# endif
+#endif
+
+/* GC_set_warn_proc can be used to redirect or filter warning messages. */
+/* p may not be a NULL pointer.  msg is printf format string (arg must  */
+/* match the format).  Both the setter and the getter acquire the GC    */
+/* lock (to avoid data races).  In GC v7.1 (and before), the setter     */
+/* returned the old warn_proc value.                                    */
+typedef void (GC_CALLBACK * GC_warn_proc)(char * /* msg */,
+                                          GC_word /* arg */);
+GC_API void GC_CALL GC_set_warn_proc(GC_warn_proc /* p */) GC_ATTR_NONNULL(1);
+/* GC_get_warn_proc returns the current warn_proc.                      */
+GC_API GC_warn_proc GC_CALL GC_get_warn_proc(void);
+
+/* GC_ignore_warn_proc may be used as an argument for GC_set_warn_proc  */
+/* to suppress all warnings (unless statistics printing is turned on).  */
+GC_API void GC_CALLBACK GC_ignore_warn_proc(char *, GC_word);
+
+/* Change file descriptor of GC log.  Unavailable on some targets.      */
+GC_API void GC_CALL GC_set_log_fd(int);
+
+/* abort_func is invoked on GC fatal aborts (just before OS-dependent   */
+/* abort or exit(1) is called).  Must be non-NULL.  The default one     */
+/* outputs msg to stderr provided msg is non-NULL.  msg is NULL if      */
+/* invoked before exit(1) otherwise msg is non-NULL (i.e., if invoked   */
+/* before abort).  Both the setter and getter acquire the GC lock.      */
+/* Both the setter and getter are defined only if the library has been  */
+/* compiled without SMALL_CONFIG.                                       */
+typedef void (GC_CALLBACK * GC_abort_func)(const char * /* msg */);
+GC_API void GC_CALL GC_set_abort_func(GC_abort_func) GC_ATTR_NONNULL(1);
+GC_API GC_abort_func GC_CALL GC_get_abort_func(void);
+
+/* A portable way to abort the application because of not enough memory.*/
+GC_API void GC_CALL GC_abort_on_oom(void);
+
+/* The following is intended to be used by a higher level       */
+/* (e.g. Java-like) finalization facility.  It is expected      */
+/* that finalization code will arrange for hidden pointers to   */
+/* disappear.  Otherwise objects can be accessed after they     */
+/* have been collected.                                         */
+/* Should not be used in the leak-finding mode.                 */
+/* Note that putting pointers in atomic objects or in           */
+/* non-pointer slots of "typed" objects is equivalent to        */
+/* disguising them in this way, and may have other advantages.  */
+typedef GC_word GC_hidden_pointer;
+#define GC_HIDE_POINTER(p) (~(GC_hidden_pointer)(p))
+/* Converting a hidden pointer to a real pointer requires verifying     */
+/* that the object still exists.  This involves acquiring the           */
+/* allocator lock to avoid a race with the collector.                   */
+#define GC_REVEAL_POINTER(p) ((void *)GC_HIDE_POINTER(p))
+
+#if defined(I_HIDE_POINTERS) || defined(GC_I_HIDE_POINTERS)
+  /* This exists only for compatibility (the GC-prefixed symbols are    */
+  /* preferred for new code).                                           */
+# define HIDE_POINTER(p) GC_HIDE_POINTER(p)
+# define REVEAL_POINTER(p) GC_REVEAL_POINTER(p)
+#endif
+
+/* The routines to acquire/release the allocator lock.                  */
+/* The lock is not reentrant.  GC_alloc_unlock() should not be called   */
+/* unless the lock is acquired by the current thread.                   */
+#ifdef GC_THREADS
+  GC_API void GC_CALL GC_alloc_lock(void);
+  GC_API void GC_CALL GC_alloc_unlock(void);
+#else
+  /* No need for real locking if the client is single-threaded.         */
+# define GC_alloc_lock() (void)0
+# define GC_alloc_unlock() (void)0
+#endif /* !GC_THREADS */
+
+typedef void * (GC_CALLBACK * GC_fn_type)(void * /* client_data */);
+GC_API void * GC_CALL GC_call_with_alloc_lock(GC_fn_type /* fn */,
+                                void * /* client_data */) GC_ATTR_NONNULL(1);
+
+/* These routines are intended to explicitly notify the collector       */
+/* of new threads.  Often this is unnecessary because thread creation   */
+/* is implicitly intercepted by the collector, using header-file        */
+/* defines, or linker-based interception.  In the long run the intent   */
+/* is to always make redundant registration safe.  In the short run,    */
+/* this is being implemented a platform at a time.                      */
+/* The interface is complicated by the fact that we probably will not   */
+/* ever be able to automatically determine the stack bottom for thread  */
+/* stacks on all platforms.                                             */
+
+/* Structure representing the bottom (cold end) of a thread stack.      */
+/* On most platforms this contains just a single address.               */
+struct GC_stack_base {
+  void * mem_base;      /* the bottom of the general-purpose stack */
+# if defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
+    void * reg_base;    /* the bottom of the register stack */
+# endif
+};
+
+typedef void * (GC_CALLBACK * GC_stack_base_func)(
+                struct GC_stack_base * /* sb */, void * /* arg */);
+
+/* Call a function with a stack base structure corresponding to         */
+/* somewhere in the GC_call_with_stack_base frame.  This often can      */
+/* be used to provide a sufficiently accurate stack bottom.  And we     */
+/* implement it everywhere.                                             */
+GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func /* fn */,
+                                        void * /* arg */) GC_ATTR_NONNULL(1);
+
+#define GC_SUCCESS 0
+#define GC_DUPLICATE 1          /* Was already registered.              */
+#define GC_NO_THREADS 2         /* No thread support in GC.             */
+        /* GC_NO_THREADS is not returned by any GC function anymore.    */
+#define GC_UNIMPLEMENTED 3 /* Not yet implemented on this platform.     */
+#define GC_NOT_FOUND 4          /* Requested link not found (returned   */
+                                /* by GC_move_disappearing_link).       */
+
+#if defined(GC_DARWIN_THREADS) || defined(GC_WIN32_THREADS)
+  /* Use implicit thread registration and processing (via Win32 DllMain */
+  /* or Darwin task_threads).  Deprecated.  Must be called before       */
+  /* GC_INIT() and other GC routines.  Should be avoided if             */
+  /* GC_pthread_create, GC_beginthreadex (or GC_CreateThread) could be  */
+  /* called instead.  Disables parallelized GC on Win32.                */
+  GC_API void GC_CALL GC_use_threads_discovery(void);
+#endif
+
+#ifdef GC_THREADS
+  /* Suggest the GC to use the specific signal to suspend threads.      */
+  /* Has no effect after GC_init and on non-POSIX systems.              */
+  GC_API void GC_CALL GC_set_suspend_signal(int);
+
+  /* Suggest the GC to use the specific signal to resume threads.       */
+  /* Has no effect after GC_init and on non-POSIX systems.              */
+  GC_API void GC_CALL GC_set_thr_restart_signal(int);
+
+  /* Return the signal number (constant after initialization) used by   */
+  /* the GC to suspend threads on POSIX systems.  Return -1 otherwise.  */
+  GC_API int GC_CALL GC_get_suspend_signal(void);
+
+  /* Return the signal number (constant after initialization) used by   */
+  /* the garbage collector to restart (resume) threads on POSIX         */
+  /* systems.  Return -1 otherwise.                                     */
+  GC_API int GC_CALL GC_get_thr_restart_signal(void);
+
+  /* Restart marker threads after POSIX fork in child.  Meaningless in  */
+  /* other situations.  Should not be called if fork followed by exec.  */
+  GC_API void GC_CALL GC_start_mark_threads(void);
+
+  /* Explicitly enable GC_register_my_thread() invocation.              */
+  /* Done implicitly if a GC thread-creation function is called (or     */
+  /* implicit thread registration is activated, or the collector is     */
+  /* compiled with GC_ALWAYS_MULTITHREADED defined).  Otherwise, it     */
+  /* must be called from the main (or any previously registered) thread */
+  /* between the collector initialization and the first explicit        */
+  /* registering of a thread (it should be called as late as possible). */
+  GC_API void GC_CALL GC_allow_register_threads(void);
+
+  /* Register the current thread, with the indicated stack bottom, as   */
+  /* a new thread whose stack(s) should be traced by the GC.  If it     */
+  /* is not implicitly called by the GC, this must be called before a   */
+  /* thread can allocate garbage collected memory, or assign pointers   */
+  /* to the garbage collected heap.  Once registered, a thread will be  */
+  /* stopped during garbage collections.                                */
+  /* This call must be previously enabled (see above).                  */
+  /* This should never be called from the main thread, where it is      */
+  /* always done implicitly.  This is normally done implicitly if GC_   */
+  /* functions are called to create the thread, e.g. by including gc.h  */
+  /* (which redefines some system functions) before calling the system  */
+  /* thread creation function.  Nonetheless, thread cleanup routines    */
+  /* (e.g., pthread key destructor) typically require manual thread     */
+  /* registering (and unregistering) if pointers to GC-allocated        */
+  /* objects are manipulated inside.                                    */
+  /* It is also always done implicitly on some platforms if             */
+  /* GC_use_threads_discovery() is called at start-up.  Except for the  */
+  /* latter case, the explicit call is normally required for threads    */
+  /* created by third-party libraries.                                  */
+  /* A manually registered thread requires manual unregistering.        */
+  /* Returns GC_SUCCESS on success, GC_DUPLICATE if already registered. */
+  GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *)
+                                                        GC_ATTR_NONNULL(1);
+
+  /* Return non-zero (TRUE) if and only if the calling thread is        */
+  /* registered with the garbage collector.                             */
+  GC_API int GC_CALL GC_thread_is_registered(void);
+
+  /* Notify the collector about the stack and the alt-stack of the      */
+  /* current thread.  stack_start/size is used to determine the stack   */
+  /* boundaries when a thread is suspended while it is on an alt-stack. */
+  GC_API void GC_CALL GC_register_altstack(void * /* stack_start */,
+                                           GC_word /* stack_size */,
+                                           void * /* altstack_base */,
+                                           GC_word /* altstack_size */);
+
+  /* Unregister the current thread.  Only an explicitly registered      */
+  /* thread (i.e. for which GC_register_my_thread() returns GC_SUCCESS) */
+  /* is allowed (and required) to call this function.  (As a special    */
+  /* exception, it is also allowed to once unregister the main thread.) */
+  /* The thread may no longer allocate garbage collected memory or      */
+  /* manipulate pointers to the garbage collected heap after making     */
+  /* this call.  Specifically, if it wants to return or otherwise       */
+  /* communicate a pointer to the garbage-collected heap to another     */
+  /* thread, it must do this before calling GC_unregister_my_thread,    */
+  /* most probably by saving it in a global data structure.  Must not   */
+  /* be called inside a GC callback function (except for                */
+  /* GC_call_with_stack_base() one).                                    */
+  GC_API int GC_CALL GC_unregister_my_thread(void);
+
+  /* Stop/start the world explicitly.  Not recommended for general use. */
+  GC_API void GC_CALL GC_stop_world_external(void);
+  GC_API void GC_CALL GC_start_world_external(void);
+#endif /* GC_THREADS */
+
+/* Wrapper for functions that are likely to block (or, at least, do not */
+/* allocate garbage collected memory and/or manipulate pointers to the  */
+/* garbage collected heap) for an appreciable length of time.  While fn */
+/* is running, the collector is said to be in the "inactive" state for  */
+/* the current thread (this means that the thread is not suspended and  */
+/* the thread's stack frames "belonging" to the functions in the        */
+/* "inactive" state are not scanned during garbage collections).  It is */
+/* assumed that the collector is already initialized and the current    */
+/* thread is registered.  It is allowed for fn to call                  */
+/* GC_call_with_gc_active() (even recursively), thus temporarily        */
+/* toggling the collector's state back to "active".  The latter         */
+/* technique might be used to make stack scanning more precise (i.e.    */
+/* scan only stack frames of functions that allocate garbage collected  */
+/* memory and/or manipulate pointers to the garbage collected heap).    */
+GC_API void * GC_CALL GC_do_blocking(GC_fn_type /* fn */,
+                                void * /* client_data */) GC_ATTR_NONNULL(1);
+
+/* Call a function switching to the "active" state of the collector for */
+/* the current thread (i.e. the user function is allowed to call any    */
+/* GC function and/or manipulate pointers to the garbage collected      */
+/* heap).  GC_call_with_gc_active() has the functionality opposite to   */
+/* GC_do_blocking() one.  It is assumed that the collector is already   */
+/* initialized and the current thread is registered.  fn may toggle     */
+/* the collector thread's state temporarily to "inactive" one by using  */
+/* GC_do_blocking.  GC_call_with_gc_active() often can be used to       */
+/* provide a sufficiently accurate stack bottom.                        */
+GC_API void * GC_CALL GC_call_with_gc_active(GC_fn_type /* fn */,
+                                void * /* client_data */) GC_ATTR_NONNULL(1);
+
+/* Attempt to fill in the GC_stack_base structure with the stack bottom */
+/* for this thread.  This appears to be required to implement anything  */
+/* like the JNI AttachCurrentThread in an environment in which new      */
+/* threads are not automatically registered with the collector.         */
+/* It is also unfortunately hard to implement well on many platforms.   */
+/* Returns GC_SUCCESS or GC_UNIMPLEMENTED.  This function acquires the  */
+/* GC lock on some platforms.                                           */
+GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *)
+                                                        GC_ATTR_NONNULL(1);
+
+/* Fill in the GC_stack_base structure with the cold end (bottom) of    */
+/* the stack of the current thread (or coroutine).                      */
+/* Unlike GC_get_stack_base, it retrieves the value stored in the       */
+/* collector (which is initially set by the collector upon the thread   */
+/* is started or registered manually but it could be later updated by   */
+/* client using GC_set_stackbottom).  Returns the GC-internal non-NULL  */
+/* handle of the thread which could be passed to GC_set_stackbottom     */
+/* later.  It is assumed that the collector is already initialized and  */
+/* the thread is registered.  Acquires the GC lock to avoid data races. */
+GC_API void * GC_CALL GC_get_my_stackbottom(struct GC_stack_base *)
+                                                        GC_ATTR_NONNULL(1);
+
+/* Set the cool end of the user (coroutine) stack of the specified      */
+/* thread.  The GC thread handle is either the one returned by          */
+/* GC_get_my_stackbottom or NULL (the latter designates the current     */
+/* thread).  The caller should hold the GC lock (e.g. using             */
+/* GC_call_with_alloc_lock).  Also, the function could be used for      */
+/* setting GC_stackbottom value (the bottom of the primordial thread)   */
+/* before the collector is initialized (the GC lock is not needed to be */
+/* acquired in this case).                                              */
+GC_API void GC_CALL GC_set_stackbottom(void * /* gc_thread_handle */,
+                                       const struct GC_stack_base *)
+                                                        GC_ATTR_NONNULL(2);
+
+/* The following routines are primarily intended for use with a         */
+/* preprocessor which inserts calls to check C pointer arithmetic.      */
+/* They indicate failure by invoking the corresponding _print_proc.     */
+
+/* Check that p and q point to the same object.                 */
+/* Fail conspicuously if they don't.                            */
+/* Returns the first argument.                                  */
+/* Succeeds if neither p nor q points to the heap.              */
+/* May succeed if both p and q point to between heap objects.   */
+GC_API void * GC_CALL GC_same_obj(void * /* p */, void * /* q */);
+
+/* Checked pointer pre- and post- increment operations.  Note that      */
+/* the second argument is in units of bytes, not multiples of the       */
+/* object size.  This should either be invoked from a macro, or the     */
+/* call should be automatically generated.                              */
+GC_API void * GC_CALL GC_pre_incr(void **, ptrdiff_t /* how_much */)
+                                                        GC_ATTR_NONNULL(1);
+GC_API void * GC_CALL GC_post_incr(void **, ptrdiff_t /* how_much */)
+                                                        GC_ATTR_NONNULL(1);
+
+/* Check that p is visible                                              */
+/* to the collector as a possibly pointer containing location.          */
+/* If it isn't fail conspicuously.                                      */
+/* Returns the argument in all cases.  May erroneously succeed          */
+/* in hard cases.  (This is intended for debugging use with             */
+/* untyped allocations.  The idea is that it should be possible, though */
+/* slow, to add such a call to all indirect pointer stores.)            */
+/* Currently useless for multi-threaded worlds.                         */
+GC_API void * GC_CALL GC_is_visible(void * /* p */);
+
+/* Check that if p is a pointer to a heap page, then it points to       */
+/* a valid displacement within a heap object.                           */
+/* Fail conspicuously if this property does not hold.                   */
+/* Uninteresting with GC_all_interior_pointers.                         */
+/* Always returns its argument.                                         */
+GC_API void * GC_CALL GC_is_valid_displacement(void * /* p */);
+
+/* Explicitly dump the GC state.  This is most often called from the    */
+/* debugger, or by setting the GC_DUMP_REGULARLY environment variable,  */
+/* but it may be useful to call it from client code during debugging.   */
+/* The current collection number is printed in the header of the dump.  */
+/* Acquires the GC lock to avoid data races.                            */
+/* Defined only if the library has been compiled without NO_DEBUGGING.  */
+GC_API void GC_CALL GC_dump(void);
+
+/* The same as GC_dump but allows to specify the name of dump and does  */
+/* not acquire the lock.  If name is non-NULL, it is printed to help    */
+/* identifying individual dumps.  Otherwise the current collection      */
+/* number is used as the name.                                          */
+/* Defined only if the library has been compiled without NO_DEBUGGING.  */
+GC_API void GC_CALL GC_dump_named(const char * /* name */);
+
+/* Dump information about each block of every GC memory section.        */
+/* Defined only if the library has been compiled without NO_DEBUGGING.  */
+GC_API void GC_CALL GC_dump_regions(void);
+
+/* Dump information about every registered disappearing link and        */
+/* finalizable object.                                                  */
+/* Defined only if the library has been compiled without NO_DEBUGGING.  */
+GC_API void GC_CALL GC_dump_finalization(void);
+
+/* Safer, but slow, pointer addition.  Probably useful mainly with      */
+/* a preprocessor.  Useful only for heap pointers.                      */
+/* Only the macros without trailing digits are meant to be used         */
+/* by clients.  These are designed to model the available C pointer     */
+/* arithmetic expressions.                                              */
+/* Even then, these are probably more useful as                         */
+/* documentation than as part of the API.                               */
+/* Note that GC_PTR_ADD evaluates the first argument more than once.    */
+#if defined(GC_DEBUG) && defined(__GNUC__)
+# define GC_PTR_ADD3(x, n, type_of_result) \
+        ((type_of_result)GC_same_obj((x)+(n), (x)))
+# define GC_PRE_INCR3(x, n, type_of_result) \
+        ((type_of_result)GC_pre_incr((void **)(&(x)), (n)*sizeof(*x)))
+# define GC_POST_INCR3(x, n, type_of_result) \
+        ((type_of_result)GC_post_incr((void **)(&(x)), (n)*sizeof(*x)))
+# define GC_PTR_ADD(x, n) GC_PTR_ADD3(x, n, __typeof__(x))
+# define GC_PRE_INCR(x, n) GC_PRE_INCR3(x, n, __typeof__(x))
+# define GC_POST_INCR(x) GC_POST_INCR3(x, 1, __typeof__(x))
+# define GC_POST_DECR(x) GC_POST_INCR3(x, -1, __typeof__(x))
+#else /* !GC_DEBUG || !__GNUC__ */
+  /* We can't do this right without typeof, which ANSI decided was not    */
+  /* sufficiently useful.  Without it we resort to the non-debug version. */
+  /* TODO: This should eventually support C++0x decltype. */
+# define GC_PTR_ADD(x, n) ((x)+(n))
+# define GC_PRE_INCR(x, n) ((x) += (n))
+# define GC_POST_INCR(x) ((x)++)
+# define GC_POST_DECR(x) ((x)--)
+#endif /* !GC_DEBUG || !__GNUC__ */
+
+/* Safer assignment of a pointer to a non-stack location.       */
+#ifdef GC_DEBUG
+# define GC_PTR_STORE(p, q) \
+        (*(void **)GC_is_visible((void *)(p)) = \
+                    GC_is_valid_displacement((void *)(q)))
+#else
+# define GC_PTR_STORE(p, q) (*(void **)(p) = (void *)(q))
+#endif
+
+/* GC_PTR_STORE_AND_DIRTY(p,q) is equivalent to GC_PTR_STORE(p,q)       */
+/* followed by GC_END_STUBBORN_CHANGE(p) and GC_reachable_here(q)       */
+/* (assuming p and q do not have side effects).                         */
+GC_API void GC_CALL GC_ptr_store_and_dirty(void * /* p */,
+                                           const void * /* q */);
+GC_API void GC_CALL GC_debug_ptr_store_and_dirty(void * /* p */,
+                                                 const void * /* q */);
+
+/* Functions called to report pointer checking errors */
+GC_API void (GC_CALLBACK * GC_same_obj_print_proc)(void * /* p */,
+                                                   void * /* q */);
+GC_API void (GC_CALLBACK * GC_is_valid_displacement_print_proc)(void *);
+GC_API void (GC_CALLBACK * GC_is_visible_print_proc)(void *);
+
+#ifdef GC_PTHREADS
+  /* For pthread support, we generally need to intercept a number of    */
+  /* thread library calls.  We do that here by macro defining them.     */
+# ifdef __cplusplus
+    } /* extern "C" */
+# endif
+# include "gc_pthread_redirects.h"
+# ifdef __cplusplus
+    extern "C" {
+# endif
+#endif
+
+/* This returns a list of objects, linked through their first word.     */
+/* Its use can greatly reduce lock contention problems, since the       */
+/* allocation lock can be acquired and released many fewer times.       */
+GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_many(size_t /* lb */);
+#define GC_NEXT(p) (*(void * *)(p))     /* Retrieve the next element    */
+                                        /* in returned list.            */
+
+/* A filter function to control the scanning of dynamic libraries.      */
+/* If implemented, called by GC before registering a dynamic library    */
+/* (discovered by GC) section as a static data root (called only as     */
+/* a last reason not to register).  The filename of the library, the    */
+/* address and the length of the memory region (section) are passed.    */
+/* This routine should return nonzero if that region should be scanned. */
+/* Always called with the allocation lock held.  Depending on the       */
+/* platform, might be called with the "world" stopped.                  */
+typedef int (GC_CALLBACK * GC_has_static_roots_func)(
+                                        const char * /* dlpi_name */,
+                                        void * /* section_start */,
+                                        size_t /* section_size */);
+
+/* Register a new callback (a user-supplied filter) to control the      */
+/* scanning of dynamic libraries.  Replaces any previously registered   */
+/* callback.  May be 0 (means no filtering).  May be unused on some     */
+/* platforms (if the filtering is unimplemented or inappropriate).      */
+GC_API void GC_CALL GC_register_has_static_roots_callback(
+                                        GC_has_static_roots_func);
+
+#if !defined(CPPCHECK) && !defined(GC_WINDOWS_H_INCLUDED) && defined(WINAPI)
+  /* windows.h is included before gc.h */
+# define GC_WINDOWS_H_INCLUDED
+#endif
+
+#if defined(GC_WIN32_THREADS) \
+    && (!defined(GC_PTHREADS) || defined(GC_BUILD) \
+        || defined(GC_WINDOWS_H_INCLUDED))
+                /* Note: for Cygwin and pthreads-win32, this is skipped */
+                /* unless windows.h is included before gc.h.            */
+
+# if (!defined(GC_NO_THREAD_DECLS) || defined(GC_BUILD)) \
+     && !defined(GC_DONT_INCL_WINDOWS_H)
+
+#   ifdef __cplusplus
+      } /* Including windows.h in an extern "C" context no longer works. */
+#   endif
+
+#   if !defined(_WIN32_WCE) && !defined(__CEGCC__)
+#     include <process.h> /* For _beginthreadex, _endthreadex */
+#   endif
+
+#   if defined(GC_BUILD) || !defined(GC_DONT_INCLUDE_WINDOWS_H)
+#     include <windows.h>
+#     define GC_WINDOWS_H_INCLUDED
+#   endif
+
+#   ifdef __cplusplus
+      extern "C" {
+#   endif
+
+#   ifdef GC_UNDERSCORE_STDCALL
+      /* Explicitly prefix exported/imported WINAPI (__stdcall) symbols */
+      /* with '_' (underscore).  Might be useful if MinGW/x86 is used.  */
+#     define GC_CreateThread _GC_CreateThread
+#     define GC_ExitThread _GC_ExitThread
+#   endif
+
+#   ifndef DECLSPEC_NORETURN
+      /* Typically defined in winnt.h. */
+#     ifdef GC_WINDOWS_H_INCLUDED
+#       define DECLSPEC_NORETURN /* empty */
+#     else
+#       define DECLSPEC_NORETURN __declspec(noreturn)
+#     endif
+#   endif
+
+#   if !defined(_UINTPTR_T) && !defined(_UINTPTR_T_DEFINED) \
+       && !defined(UINTPTR_MAX)
+      typedef GC_word GC_uintptr_t;
+#   else
+      typedef uintptr_t GC_uintptr_t;
+#   endif
+
+#   ifdef _WIN64
+#     define GC_WIN32_SIZE_T GC_uintptr_t
+#   elif defined(GC_WINDOWS_H_INCLUDED)
+#     define GC_WIN32_SIZE_T DWORD
+#   else
+#     define GC_WIN32_SIZE_T unsigned long
+#   endif
+
+#   ifdef GC_INSIDE_DLL
+      /* Export GC DllMain to be invoked from client DllMain.   */
+#     ifdef GC_UNDERSCORE_STDCALL
+#       define GC_DllMain _GC_DllMain
+#     endif
+#     ifdef GC_WINDOWS_H_INCLUDED
+        GC_API BOOL WINAPI GC_DllMain(HINSTANCE /* inst */,
+                                      ULONG /* reason */,
+                                      LPVOID /* reserved */);
+#     else
+        GC_API int __stdcall GC_DllMain(void *, unsigned long, void *);
+#     endif
+#   endif /* GC_INSIDE_DLL */
+
+    /* All threads must be created using GC_CreateThread or             */
+    /* GC_beginthreadex, or must explicitly call GC_register_my_thread  */
+    /* (and call GC_unregister_my_thread before thread termination), so */
+    /* that they will be recorded in the thread table.  For backward    */
+    /* compatibility, it is possible to build the GC with GC_DLL        */
+    /* defined, and to call GC_use_threads_discovery.  This implicitly  */
+    /* registers all created threads, but appears to be less robust.    */
+    /* Currently the collector expects all threads to fall through and  */
+    /* terminate normally, or call GC_endthreadex() or GC_ExitThread,   */
+    /* so that the thread is properly unregistered.                     */
+#   ifdef GC_WINDOWS_H_INCLUDED
+      GC_API HANDLE WINAPI GC_CreateThread(
+                LPSECURITY_ATTRIBUTES /* lpThreadAttributes */,
+                GC_WIN32_SIZE_T /* dwStackSize */,
+                LPTHREAD_START_ROUTINE /* lpStartAddress */,
+                LPVOID /* lpParameter */, DWORD /* dwCreationFlags */,
+                LPDWORD /* lpThreadId */);
+
+      GC_API DECLSPEC_NORETURN void WINAPI GC_ExitThread(
+                                                DWORD /* dwExitCode */);
+#   else
+      struct _SECURITY_ATTRIBUTES;
+      GC_API void *__stdcall GC_CreateThread(struct _SECURITY_ATTRIBUTES *,
+                                GC_WIN32_SIZE_T,
+                                unsigned long (__stdcall *)(void *),
+                                void *, unsigned long, unsigned long *);
+      GC_API DECLSPEC_NORETURN void __stdcall GC_ExitThread(unsigned long);
+#   endif
+
+#   if !defined(_WIN32_WCE) && !defined(__CEGCC__)
+      GC_API GC_uintptr_t GC_CALL GC_beginthreadex(
+                        void * /* security */, unsigned /* stack_size */,
+                        unsigned (__stdcall *)(void *),
+                        void * /* arglist */, unsigned /* initflag */,
+                        unsigned * /* thrdaddr */);
+
+      /* Note: _endthreadex() is not currently marked as no-return in   */
+      /* VC++ and MinGW headers, so we don't mark it neither.           */
+      GC_API void GC_CALL GC_endthreadex(unsigned /* retval */);
+#   endif /* !_WIN32_WCE */
+
+# endif /* !GC_NO_THREAD_DECLS */
+
+# ifdef GC_WINMAIN_REDIRECT
+    /* win32_threads.c implements the real WinMain(), which will start  */
+    /* a new thread to call GC_WinMain() after initializing the garbage */
+    /* collector.                                                       */
+#   define WinMain GC_WinMain
+# endif
+
+  /* For compatibility only. */
+# define GC_use_DllMain GC_use_threads_discovery
+
+# ifndef GC_NO_THREAD_REDIRECTS
+#   define CreateThread GC_CreateThread
+#   define ExitThread GC_ExitThread
+#   undef _beginthreadex
+#   define _beginthreadex GC_beginthreadex
+#   undef _endthreadex
+#   define _endthreadex GC_endthreadex
+/* #define _beginthread { > "Please use _beginthreadex instead of _beginthread" < } */
+# endif /* !GC_NO_THREAD_REDIRECTS */
+
+#endif /* GC_WIN32_THREADS */
+
+/* Public setter and getter for switching "unmap as much as possible"   */
+/* mode on(1) and off(0).  Has no effect unless unmapping is turned on. */
+/* Has no effect on implicitly-initiated garbage collections.  Initial  */
+/* value is controlled by GC_FORCE_UNMAP_ON_GCOLLECT.  The setter and   */
+/* getter are unsynchronized.                                           */
+GC_API void GC_CALL GC_set_force_unmap_on_gcollect(int);
+GC_API int GC_CALL GC_get_force_unmap_on_gcollect(void);
+
+/* Fully portable code should call GC_INIT() from the main program      */
+/* before making any other GC_ calls.  On most platforms this is a      */
+/* no-op and the collector self-initializes.  But a number of           */
+/* platforms make that too hard.                                        */
+/* A GC_INIT call is required if the collector is built with            */
+/* THREAD_LOCAL_ALLOC defined and the initial allocation call is not    */
+/* to GC_malloc() or GC_malloc_atomic().                                */
+
+#if defined(__CYGWIN32__) || defined(__CYGWIN__)
+  /* Similarly gnu-win32 DLLs need explicit initialization from the     */
+  /* main program, as does AIX.                                         */
+# ifdef __x86_64__
+    /* Cygwin/x64 does not add leading underscore to symbols anymore.   */
+    extern int __data_start__[], __data_end__[];
+    extern int __bss_start__[], __bss_end__[];
+#   define GC_DATASTART ((GC_word)__data_start__ < (GC_word)__bss_start__ \
+                         ? (void *)__data_start__ : (void *)__bss_start__)
+#   define GC_DATAEND ((GC_word)__data_end__ > (GC_word)__bss_end__ \
+                       ? (void *)__data_end__ : (void *)__bss_end__)
+# else
+    extern int _data_start__[], _data_end__[], _bss_start__[], _bss_end__[];
+#   define GC_DATASTART ((GC_word)_data_start__ < (GC_word)_bss_start__ \
+                         ? (void *)_data_start__ : (void *)_bss_start__)
+#   define GC_DATAEND ((GC_word)_data_end__ > (GC_word)_bss_end__ \
+                      ? (void *)_data_end__ : (void *)_bss_end__)
+# endif /* !__x86_64__ */
+# define GC_INIT_CONF_ROOTS GC_add_roots(GC_DATASTART, GC_DATAEND); \
+                                 GC_gcollect() /* For blacklisting. */
+        /* Required at least if GC is in a DLL.  And doesn't hurt. */
+#elif defined(_AIX)
+  extern int _data[], _end[];
+# define GC_DATASTART ((void *)_data)
+# define GC_DATAEND ((void *)_end)
+# define GC_INIT_CONF_ROOTS GC_add_roots(GC_DATASTART, GC_DATAEND)
+#elif (defined(HOST_ANDROID) || defined(__ANDROID__)) \
+      && defined(IGNORE_DYNAMIC_LOADING)
+  /* This is ugly but seems the only way to register data roots of the  */
+  /* client shared library if the GC dynamic loading support is off.    */
+# pragma weak __dso_handle
+  extern int __dso_handle[];
+  GC_API void * GC_CALL GC_find_limit(void * /* start */, int /* up */);
+# define GC_INIT_CONF_ROOTS (void)(__dso_handle != 0 \
+                                   ? (GC_add_roots(__dso_handle, \
+                                            GC_find_limit(__dso_handle, \
+                                                          1 /*up*/)), 0) : 0)
+#else
+# define GC_INIT_CONF_ROOTS /* empty */
+#endif
+
+#ifdef GC_DONT_EXPAND
+  /* Set GC_dont_expand to TRUE at start-up */
+# define GC_INIT_CONF_DONT_EXPAND GC_set_dont_expand(1)
+#else
+# define GC_INIT_CONF_DONT_EXPAND /* empty */
+#endif
+
+#ifdef GC_FORCE_UNMAP_ON_GCOLLECT
+  /* Turn on "unmap as much as possible on explicit GC" mode at start-up */
+# define GC_INIT_CONF_FORCE_UNMAP_ON_GCOLLECT \
+                GC_set_force_unmap_on_gcollect(1)
+#else
+# define GC_INIT_CONF_FORCE_UNMAP_ON_GCOLLECT /* empty */
+#endif
+
+#ifdef GC_DONT_GC
+  /* This is for debugging only (useful if environment variables are    */
+  /* unsupported); cannot call GC_disable as goes before GC_init.       */
+# define GC_INIT_CONF_MAX_RETRIES (void)(GC_dont_gc = 1)
+#elif defined(GC_MAX_RETRIES) && !defined(CPPCHECK)
+  /* Set GC_max_retries to the desired value at start-up */
+# define GC_INIT_CONF_MAX_RETRIES GC_set_max_retries(GC_MAX_RETRIES)
+#else
+# define GC_INIT_CONF_MAX_RETRIES /* empty */
+#endif
+
+#if defined(GC_ALLOCD_BYTES_PER_FINALIZER) && !defined(CPPCHECK)
+  /* Set GC_allocd_bytes_per_finalizer to the desired value at start-up. */
+# define GC_INIT_CONF_ALLOCD_BYTES_PER_FINALIZER \
+        GC_set_allocd_bytes_per_finalizer(GC_ALLOCD_BYTES_PER_FINALIZER)
+#else
+# define GC_INIT_CONF_ALLOCD_BYTES_PER_FINALIZER /* empty */
+#endif
+
+#if defined(GC_FREE_SPACE_DIVISOR) && !defined(CPPCHECK)
+  /* Set GC_free_space_divisor to the desired value at start-up */
+# define GC_INIT_CONF_FREE_SPACE_DIVISOR \
+                GC_set_free_space_divisor(GC_FREE_SPACE_DIVISOR)
+#else
+# define GC_INIT_CONF_FREE_SPACE_DIVISOR /* empty */
+#endif
+
+#if defined(GC_FULL_FREQ) && !defined(CPPCHECK)
+  /* Set GC_full_freq to the desired value at start-up */
+# define GC_INIT_CONF_FULL_FREQ GC_set_full_freq(GC_FULL_FREQ)
+#else
+# define GC_INIT_CONF_FULL_FREQ /* empty */
+#endif
+
+#if defined(GC_TIME_LIMIT) && !defined(CPPCHECK)
+  /* Set GC_time_limit (in ms) to the desired value at start-up. */
+# define GC_INIT_CONF_TIME_LIMIT GC_set_time_limit(GC_TIME_LIMIT)
+#else
+# define GC_INIT_CONF_TIME_LIMIT /* empty */
+#endif
+
+#if defined(GC_MARKERS) && defined(GC_THREADS) && !defined(CPPCHECK)
+  /* Set the number of marker threads (including the initiating */
+  /* one) to the desired value at start-up.                     */
+# define GC_INIT_CONF_MARKERS GC_set_markers_count(GC_MARKERS)
+#else
+# define GC_INIT_CONF_MARKERS /* empty */
+#endif
+
+#if defined(GC_SIG_SUSPEND) && defined(GC_THREADS) && !defined(CPPCHECK)
+# define GC_INIT_CONF_SUSPEND_SIGNAL GC_set_suspend_signal(GC_SIG_SUSPEND)
+#else
+# define GC_INIT_CONF_SUSPEND_SIGNAL /* empty */
+#endif
+
+#if defined(GC_SIG_THR_RESTART) && defined(GC_THREADS) && !defined(CPPCHECK)
+# define GC_INIT_CONF_THR_RESTART_SIGNAL \
+                GC_set_thr_restart_signal(GC_SIG_THR_RESTART)
+#else
+# define GC_INIT_CONF_THR_RESTART_SIGNAL /* empty */
+#endif
+
+#if defined(GC_MAXIMUM_HEAP_SIZE) && !defined(CPPCHECK)
+  /* Limit the heap size to the desired value (useful for debugging).   */
+  /* The limit could be overridden either at the program start-up by    */
+  /* the similar environment variable or anytime later by the           */
+  /* corresponding API function call.                                   */
+# define GC_INIT_CONF_MAXIMUM_HEAP_SIZE \
+                GC_set_max_heap_size(GC_MAXIMUM_HEAP_SIZE)
+#else
+# define GC_INIT_CONF_MAXIMUM_HEAP_SIZE /* empty */
+#endif
+
+#ifdef GC_IGNORE_WARN
+  /* Turn off all warnings at start-up (after GC initialization) */
+# define GC_INIT_CONF_IGNORE_WARN GC_set_warn_proc(GC_ignore_warn_proc)
+#else
+# define GC_INIT_CONF_IGNORE_WARN /* empty */
+#endif
+
+#if defined(GC_INITIAL_HEAP_SIZE) && !defined(CPPCHECK)
+  /* Set heap size to the desired value at start-up */
+# define GC_INIT_CONF_INITIAL_HEAP_SIZE \
+                { size_t heap_size = GC_get_heap_size(); \
+                  if (heap_size < (GC_INITIAL_HEAP_SIZE)) \
+                    (void)GC_expand_hp((GC_INITIAL_HEAP_SIZE) - heap_size); }
+#else
+# define GC_INIT_CONF_INITIAL_HEAP_SIZE /* empty */
+#endif
+
+/* Portable clients should call this at the program start-up.  More     */
+/* over, some platforms require this call to be done strictly from the  */
+/* primordial thread.  Multiple invocations are harmless.               */
+#define GC_INIT() { GC_INIT_CONF_DONT_EXPAND; /* pre-init */ \
+                    GC_INIT_CONF_FORCE_UNMAP_ON_GCOLLECT; \
+                    GC_INIT_CONF_MAX_RETRIES; \
+                    GC_INIT_CONF_ALLOCD_BYTES_PER_FINALIZER; \
+                    GC_INIT_CONF_FREE_SPACE_DIVISOR; \
+                    GC_INIT_CONF_FULL_FREQ; \
+                    GC_INIT_CONF_TIME_LIMIT; \
+                    GC_INIT_CONF_MARKERS; \
+                    GC_INIT_CONF_SUSPEND_SIGNAL; \
+                    GC_INIT_CONF_THR_RESTART_SIGNAL; \
+                    GC_INIT_CONF_MAXIMUM_HEAP_SIZE; \
+                    GC_init(); /* real GC initialization */ \
+                    GC_INIT_CONF_ROOTS; /* post-init */ \
+                    GC_INIT_CONF_IGNORE_WARN; \
+                    GC_INIT_CONF_INITIAL_HEAP_SIZE; }
+
+/* win32S may not free all resources on process exit.                   */
+/* This explicitly deallocates the heap.  Defined only for Windows.     */
+GC_API void GC_CALL GC_win32_free_heap(void);
+
+#if defined(__SYMBIAN32__)
+  void GC_init_global_static_roots(void);
+#endif
+
+#if defined(_AMIGA) && !defined(GC_AMIGA_MAKINGLIB)
+  /* Allocation really goes through GC_amiga_allocwrapper_do.   */
+  void *GC_amiga_realloc(void *, size_t);
+# define GC_realloc(a,b) GC_amiga_realloc(a,b)
+  void GC_amiga_set_toany(void (*)(void));
+  extern int GC_amiga_free_space_divisor_inc;
+  extern void *(*GC_amiga_allocwrapper_do)(size_t, void *(GC_CALL *)(size_t));
+# define GC_malloc(a) \
+        (*GC_amiga_allocwrapper_do)(a,GC_malloc)
+# define GC_malloc_atomic(a) \
+        (*GC_amiga_allocwrapper_do)(a,GC_malloc_atomic)
+# define GC_malloc_uncollectable(a) \
+        (*GC_amiga_allocwrapper_do)(a,GC_malloc_uncollectable)
+# define GC_malloc_atomic_uncollectable(a) \
+        (*GC_amiga_allocwrapper_do)(a,GC_malloc_atomic_uncollectable)
+# define GC_malloc_ignore_off_page(a) \
+        (*GC_amiga_allocwrapper_do)(a,GC_malloc_ignore_off_page)
+# define GC_malloc_atomic_ignore_off_page(a) \
+        (*GC_amiga_allocwrapper_do)(a,GC_malloc_atomic_ignore_off_page)
+#endif /* _AMIGA && !GC_AMIGA_MAKINGLIB */
+
+#ifdef __cplusplus
+  } /* extern "C" */
+#endif
+
+#endif /* GC_H */

+ 0 - 0
blitz.mod/bdwgc/include/gc_allocator.h → blitz.mod/bdwgc/include/gc/gc_allocator.h


+ 0 - 0
blitz.mod/bdwgc/include/gc_backptr.h → blitz.mod/bdwgc/include/gc/gc_backptr.h


+ 458 - 0
blitz.mod/bdwgc/include/gc/gc_config_macros.h

@@ -0,0 +1,458 @@
+/*
+ * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
+ * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.
+ * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.
+ * Copyright (c) 2000-2009 by Hewlett-Packard Development Company.
+ * All rights reserved.
+ * Copyright (c) 2008-2020 Ivan Maidanski
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/* This should never be included directly; it is included only from gc.h. */
+/* We separate it only to make gc.h more suitable as documentation.       */
+#if defined(GC_H)
+
+/* Convenient internal macro to test version of GCC.    */
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+# define GC_GNUC_PREREQ(major, minor) \
+            ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((major) << 16) + (minor))
+#else
+# define GC_GNUC_PREREQ(major, minor) 0 /* FALSE */
+#endif
+
+/* Some tests for old macros.  These violate our namespace rules and    */
+/* will disappear shortly.  Use the GC_ names.                          */
+#if defined(SOLARIS_THREADS) || defined(_SOLARIS_THREADS) \
+    || defined(_SOLARIS_PTHREADS) || defined(GC_SOLARIS_PTHREADS)
+  /* We no longer support old style Solaris threads.            */
+  /* GC_SOLARIS_THREADS now means pthreads.                     */
+# ifndef GC_SOLARIS_THREADS
+#   define GC_SOLARIS_THREADS
+# endif
+#endif
+#if defined(IRIX_THREADS)
+# define GC_IRIX_THREADS
+#endif
+#if defined(DGUX_THREADS) && !defined(GC_DGUX386_THREADS)
+# define GC_DGUX386_THREADS
+#endif
+#if defined(AIX_THREADS)
+# define GC_AIX_THREADS
+#endif
+#if defined(HPUX_THREADS)
+# define GC_HPUX_THREADS
+#endif
+#if defined(OSF1_THREADS)
+# define GC_OSF1_THREADS
+#endif
+#if defined(LINUX_THREADS)
+# define GC_LINUX_THREADS
+#endif
+#if defined(WIN32_THREADS)
+# define GC_WIN32_THREADS
+#endif
+#if defined(RTEMS_THREADS)
+# define GC_RTEMS_PTHREADS
+#endif
+#if defined(USE_LD_WRAP)
+# define GC_USE_LD_WRAP
+#endif
+
+#if defined(GC_WIN32_PTHREADS) && !defined(GC_WIN32_THREADS)
+  /* Using pthreads-win32 library (or other Win32 implementation).  */
+# define GC_WIN32_THREADS
+#endif
+
+#if defined(GC_AIX_THREADS) || defined(GC_DARWIN_THREADS) \
+    || defined(GC_DGUX386_THREADS) || defined(GC_FREEBSD_THREADS) \
+    || defined(GC_HPUX_THREADS) \
+    || defined(GC_IRIX_THREADS) || defined(GC_LINUX_THREADS) \
+    || defined(GC_NETBSD_THREADS) || defined(GC_OPENBSD_THREADS) \
+    || defined(GC_OSF1_THREADS) || defined(GC_SOLARIS_THREADS) \
+    || defined(GC_WIN32_THREADS) || defined(GC_RTEMS_PTHREADS)
+# ifndef GC_THREADS
+#   define GC_THREADS
+# endif
+#elif defined(GC_THREADS)
+# if defined(__linux__)
+#   define GC_LINUX_THREADS
+# elif defined(__OpenBSD__)
+#   define GC_OPENBSD_THREADS
+# elif defined(_PA_RISC1_1) || defined(_PA_RISC2_0) || defined(hppa) \
+       || defined(__HPPA) || (defined(__ia64) && defined(_HPUX_SOURCE))
+#   define GC_HPUX_THREADS
+# elif defined(__HAIKU__)
+#   define GC_HAIKU_THREADS
+# elif (defined(__DragonFly__) || defined(__FreeBSD_kernel__) \
+        || defined(__FreeBSD__)) && !defined(GC_NO_FREEBSD)
+#   define GC_FREEBSD_THREADS
+# elif defined(__NetBSD__)
+#   define GC_NETBSD_THREADS
+# elif defined(__alpha) || defined(__alpha__) /* && !Linux && !xBSD */
+#   define GC_OSF1_THREADS
+# elif (defined(mips) || defined(__mips) || defined(_mips)) \
+        && !(defined(nec_ews) || defined(_nec_ews) \
+             || defined(ultrix) || defined(__ultrix))
+#   define GC_IRIX_THREADS
+# elif defined(__sparc) /* && !Linux */ \
+       || ((defined(sun) || defined(__sun)) \
+           && (defined(i386) || defined(__i386__) \
+               || defined(__amd64) || defined(__amd64__)))
+#   define GC_SOLARIS_THREADS
+# elif defined(__APPLE__) && defined(__MACH__)
+#   define GC_DARWIN_THREADS
+# endif
+# if defined(DGUX) && (defined(i386) || defined(__i386__))
+#   define GC_DGUX386_THREADS
+# endif
+# if defined(_AIX)
+#   define GC_AIX_THREADS
+# endif
+# if (defined(_WIN32) || defined(_MSC_VER) || defined(__BORLANDC__) \
+      || defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__CEGCC__) \
+      || defined(_WIN32_WCE) || defined(__MINGW32__)) \
+     && !defined(GC_WIN32_THREADS)
+    /* Either posix or native Win32 threads. */
+#   define GC_WIN32_THREADS
+# endif
+# if defined(__rtems__) && (defined(i386) || defined(__i386__))
+#   define GC_RTEMS_PTHREADS
+# endif
+#endif /* GC_THREADS */
+
+#undef GC_PTHREADS
+#if (!defined(GC_WIN32_THREADS) || defined(GC_WIN32_PTHREADS) \
+     || defined(__CYGWIN32__) || defined(__CYGWIN__)) && defined(GC_THREADS) \
+    && !defined(NN_PLATFORM_CTR) && !defined(NN_BUILD_TARGET_PLATFORM_NX)
+  /* Posix threads. */
+# define GC_PTHREADS
+#endif
+
+#if !defined(_PTHREADS) && defined(GC_NETBSD_THREADS)
+# define _PTHREADS
+#endif
+
+#if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE)
+# define _POSIX4A_DRAFT10_SOURCE 1
+#endif
+
+#if !defined(_REENTRANT) && defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS)
+  /* Better late than never.  This fails if system headers that depend  */
+  /* on this were previously included.                                  */
+# define _REENTRANT 1
+#endif
+
+#define __GC
+#if !defined(_WIN32_WCE) || defined(__GNUC__)
+# include <stddef.h>
+# if defined(__MINGW32__) && !defined(_WIN32_WCE)
+#   include <stdint.h>
+    /* We mention uintptr_t.                                            */
+    /* Perhaps this should be included in pure msft environments        */
+    /* as well?                                                         */
+# endif
+#else /* _WIN32_WCE */
+  /* Yet more kludges for WinCE.        */
+# include <stdlib.h> /* size_t is defined here */
+# ifndef _PTRDIFF_T_DEFINED
+    /* ptrdiff_t is not defined */
+#   define _PTRDIFF_T_DEFINED
+    typedef long ptrdiff_t;
+# endif
+#endif /* _WIN32_WCE */
+
+#if !defined(GC_NOT_DLL) && !defined(GC_DLL) \
+    && ((defined(_DLL) && !defined(__GNUC__)) \
+        || (defined(DLL_EXPORT) && defined(GC_BUILD)))
+# define GC_DLL
+#endif
+
+#if defined(GC_DLL) && !defined(GC_API)
+
+# if defined(__CEGCC__)
+#   if defined(GC_BUILD)
+#     define GC_API __declspec(dllexport)
+#   else
+#     define GC_API __declspec(dllimport)
+#   endif
+
+# elif defined(__MINGW32__)
+#   if defined(__cplusplus) && defined(GC_BUILD)
+#     define GC_API extern __declspec(dllexport)
+#   elif defined(GC_BUILD) || defined(__MINGW32_DELAY_LOAD__)
+#     define GC_API __declspec(dllexport)
+#   else
+#     define GC_API extern __declspec(dllimport)
+#   endif
+
+# elif defined(_MSC_VER) || defined(__DMC__) || defined(__BORLANDC__) \
+        || defined(__CYGWIN__)
+#   ifdef GC_BUILD
+#     define GC_API extern __declspec(dllexport)
+#   else
+#     define GC_API __declspec(dllimport)
+#   endif
+
+# elif defined(__WATCOMC__)
+#   ifdef GC_BUILD
+#     define GC_API extern __declspec(dllexport)
+#   else
+#     define GC_API extern __declspec(dllimport)
+#   endif
+
+# elif defined(__SYMBIAN32__)
+#   ifdef GC_BUILD
+#     define GC_API extern EXPORT_C
+#   else
+#     define GC_API extern IMPORT_C
+#   endif
+
+# elif defined(__GNUC__)
+    /* Only matters if used in conjunction with -fvisibility=hidden option. */
+#   if defined(GC_BUILD) && !defined(GC_NO_VISIBILITY) \
+            && (GC_GNUC_PREREQ(4, 0) || defined(GC_VISIBILITY_HIDDEN_SET))
+#     define GC_API extern __attribute__((__visibility__("default")))
+#   endif
+# endif
+#endif /* GC_DLL */
+
+#ifndef GC_API
+# define GC_API extern
+#endif
+
+#ifndef GC_CALL
+# define GC_CALL
+#endif
+
+#ifndef GC_CALLBACK
+# define GC_CALLBACK GC_CALL
+#endif
+
+#ifndef GC_ATTR_MALLOC
+  /* 'malloc' attribute should be used for all malloc-like functions    */
+  /* (to tell the compiler that a function may be treated as if any     */
+  /* non-NULL pointer it returns cannot alias any other pointer valid   */
+  /* when the function returns).  If the client code violates this rule */
+  /* by using custom GC_oom_func then define GC_OOM_FUNC_RETURNS_ALIAS. */
+# ifdef GC_OOM_FUNC_RETURNS_ALIAS
+#   define GC_ATTR_MALLOC /* empty */
+# elif GC_GNUC_PREREQ(3, 1)
+#   define GC_ATTR_MALLOC __attribute__((__malloc__))
+# elif defined(_MSC_VER) && (_MSC_VER >= 1900) && !defined(__EDG__)
+#   define GC_ATTR_MALLOC \
+                __declspec(allocator) __declspec(noalias) __declspec(restrict)
+# elif defined(_MSC_VER) && _MSC_VER >= 1400
+#   define GC_ATTR_MALLOC __declspec(noalias) __declspec(restrict)
+# else
+#   define GC_ATTR_MALLOC
+# endif
+#endif
+
+#ifndef GC_ATTR_ALLOC_SIZE
+  /* 'alloc_size' attribute improves __builtin_object_size correctness. */
+# undef GC_ATTR_CALLOC_SIZE
+# ifdef __clang__
+#   if __has_attribute(__alloc_size__)
+#     define GC_ATTR_ALLOC_SIZE(argnum) __attribute__((__alloc_size__(argnum)))
+#     define GC_ATTR_CALLOC_SIZE(n, s) __attribute__((__alloc_size__(n, s)))
+#   else
+#     define GC_ATTR_ALLOC_SIZE(argnum) /* empty */
+#   endif
+# elif GC_GNUC_PREREQ(4, 3) && !defined(__ICC)
+#   define GC_ATTR_ALLOC_SIZE(argnum) __attribute__((__alloc_size__(argnum)))
+#   define GC_ATTR_CALLOC_SIZE(n, s) __attribute__((__alloc_size__(n, s)))
+# else
+#   define GC_ATTR_ALLOC_SIZE(argnum) /* empty */
+# endif
+#endif
+
+#ifndef GC_ATTR_CALLOC_SIZE
+# define GC_ATTR_CALLOC_SIZE(n, s) /* empty */
+#endif
+
+#ifndef GC_ATTR_NONNULL
+# if GC_GNUC_PREREQ(4, 0)
+#   define GC_ATTR_NONNULL(argnum) __attribute__((__nonnull__(argnum)))
+# else
+#   define GC_ATTR_NONNULL(argnum) /* empty */
+# endif
+#endif
+
+#ifndef GC_ATTR_CONST
+# if GC_GNUC_PREREQ(4, 0)
+#   define GC_ATTR_CONST __attribute__((__const__))
+# else
+#   define GC_ATTR_CONST /* empty */
+# endif
+#endif
+
+#ifndef GC_ATTR_DEPRECATED
+# ifdef GC_BUILD
+#   undef GC_ATTR_DEPRECATED
+#   define GC_ATTR_DEPRECATED /* empty */
+# elif GC_GNUC_PREREQ(4, 0)
+#   define GC_ATTR_DEPRECATED __attribute__((__deprecated__))
+# elif defined(_MSC_VER) && _MSC_VER >= 1200
+#   define GC_ATTR_DEPRECATED __declspec(deprecated)
+# else
+#   define GC_ATTR_DEPRECATED /* empty */
+# endif
+#endif
+
+#if defined(__sgi) && !defined(__GNUC__) && _COMPILER_VERSION >= 720
+# define GC_ADD_CALLER
+# define GC_RETURN_ADDR (GC_word)__return_address
+#endif
+
+#if defined(__linux__) || defined(__GLIBC__)
+# if !defined(__native_client__)
+#   include <features.h>
+# endif
+# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \
+        && !defined(__ia64__) \
+        && !defined(GC_MISSING_EXECINFO_H) \
+        && !defined(GC_HAVE_BUILTIN_BACKTRACE)
+#   define GC_HAVE_BUILTIN_BACKTRACE
+# endif
+# if defined(__i386__) || defined(__amd64__) || defined(__x86_64__)
+#   define GC_CAN_SAVE_CALL_STACKS
+# endif
+#endif /* GLIBC */
+
+#if defined(_MSC_VER) && _MSC_VER >= 1200 /* version 12.0+ (MSVC 6.0+) */ \
+        && !defined(_M_ARM) && !defined(_M_ARM64) \
+        && !defined(_AMD64_) && !defined(_M_X64) && !defined(_WIN32_WCE) \
+        && !defined(GC_HAVE_NO_BUILTIN_BACKTRACE) \
+        && !defined(GC_HAVE_BUILTIN_BACKTRACE)
+# define GC_HAVE_BUILTIN_BACKTRACE
+#endif
+
+#if defined(GC_HAVE_BUILTIN_BACKTRACE) && !defined(GC_CAN_SAVE_CALL_STACKS)
+# define GC_CAN_SAVE_CALL_STACKS
+#endif
+
+#if defined(__sparc__)
+# define GC_CAN_SAVE_CALL_STACKS
+#endif
+
+/* If we're on a platform on which we can't save call stacks, but       */
+/* gcc is normally used, we go ahead and define GC_ADD_CALLER.          */
+/* We make this decision independent of whether gcc is actually being   */
+/* used, in order to keep the interface consistent, and allow mixing    */
+/* of compilers.                                                        */
+/* This may also be desirable if it is possible but expensive to        */
+/* retrieve the call chain.                                             */
+#if (defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__) \
+     || defined(__FreeBSD_kernel__) || defined(__HAIKU__) \
+     || defined(__NetBSD__) || defined(__OpenBSD__) \
+     || defined(HOST_ANDROID) || defined(__ANDROID__)) \
+    && !defined(GC_CAN_SAVE_CALL_STACKS)
+# define GC_ADD_CALLER
+# if GC_GNUC_PREREQ(2, 95)
+    /* gcc knows how to retrieve return address, but we don't know      */
+    /* how to generate call stacks.                                     */
+#   define GC_RETURN_ADDR (GC_word)__builtin_return_address(0)
+#   if GC_GNUC_PREREQ(4, 0) && (defined(__i386__) || defined(__amd64__) \
+                        || defined(__x86_64__) /* and probably others... */) \
+       && !defined(GC_NO_RETURN_ADDR_PARENT)
+#     define GC_HAVE_RETURN_ADDR_PARENT
+#     define GC_RETURN_ADDR_PARENT \
+        (GC_word)__builtin_extract_return_addr(__builtin_return_address(1))
+            /* Note: a compiler might complain that calling                 */
+            /* __builtin_return_address with a nonzero argument is unsafe.  */
+#   endif
+# else
+    /* Just pass 0 for gcc compatibility.       */
+#   define GC_RETURN_ADDR 0
+# endif
+#endif /* !GC_CAN_SAVE_CALL_STACKS */
+
+#ifdef GC_PTHREADS
+
+# if (defined(GC_DARWIN_THREADS) || defined(GC_WIN32_PTHREADS) \
+      || defined(__native_client__) || defined(GC_RTEMS_PTHREADS)) \
+      && !defined(GC_NO_DLOPEN)
+    /* Either there is no dlopen() or we do not need to intercept it.   */
+#   define GC_NO_DLOPEN
+# endif
+
+# if (defined(GC_DARWIN_THREADS) || defined(GC_WIN32_PTHREADS) \
+      || defined(GC_OPENBSD_THREADS) || defined(__native_client__)) \
+     && !defined(GC_NO_PTHREAD_SIGMASK)
+    /* Either there is no pthread_sigmask() or no need to intercept it. */
+#   define GC_NO_PTHREAD_SIGMASK
+# endif
+
+# if defined(__native_client__)
+    /* At present, NaCl pthread_create() prototype does not have        */
+    /* "const" for its "attr" argument; also, NaCl pthread_exit() one   */
+    /* does not have "noreturn" attribute.                              */
+#   ifndef GC_PTHREAD_CREATE_CONST
+#     define GC_PTHREAD_CREATE_CONST /* empty */
+#   endif
+#   ifndef GC_HAVE_PTHREAD_EXIT
+#     define GC_HAVE_PTHREAD_EXIT
+#     define GC_PTHREAD_EXIT_ATTRIBUTE /* empty */
+#   endif
+# endif
+
+# if !defined(GC_HAVE_PTHREAD_EXIT) \
+     && !defined(HOST_ANDROID) && !defined(__ANDROID__) \
+     && (defined(GC_LINUX_THREADS) || defined(GC_SOLARIS_THREADS))
+#   define GC_HAVE_PTHREAD_EXIT
+    /* Intercept pthread_exit on Linux and Solaris.     */
+#   if GC_GNUC_PREREQ(2, 7)
+#     define GC_PTHREAD_EXIT_ATTRIBUTE __attribute__((__noreturn__))
+#   elif defined(__NORETURN) /* used in Solaris */
+#     define GC_PTHREAD_EXIT_ATTRIBUTE __NORETURN
+#   else
+#     define GC_PTHREAD_EXIT_ATTRIBUTE /* empty */
+#   endif
+# endif
+
+# if (!defined(GC_HAVE_PTHREAD_EXIT) || defined(__native_client__)) \
+     && !defined(GC_NO_PTHREAD_CANCEL)
+    /* Either there is no pthread_cancel() or no need to intercept it.  */
+#   define GC_NO_PTHREAD_CANCEL
+# endif
+
+#endif /* GC_PTHREADS */
+
+#ifdef __cplusplus
+
+#ifndef GC_ATTR_EXPLICIT
+# if __cplusplus >= 201103L && !defined(__clang__) || _MSVC_LANG >= 201103L \
+     || defined(CPPCHECK)
+#   define GC_ATTR_EXPLICIT explicit
+# else
+#   define GC_ATTR_EXPLICIT /* empty */
+# endif
+#endif
+
+#ifndef GC_NOEXCEPT
+# if defined(__DMC__) || (defined(__BORLANDC__) \
+        && (defined(_RWSTD_NO_EXCEPTIONS) || defined(_RWSTD_NO_EX_SPEC))) \
+     || (defined(_MSC_VER) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS) \
+     || (defined(__WATCOMC__) && !defined(_CPPUNWIND))
+#   define GC_NOEXCEPT /* empty */
+#   ifndef GC_NEW_ABORTS_ON_OOM
+#     define GC_NEW_ABORTS_ON_OOM
+#   endif
+# elif __cplusplus >= 201103L || _MSVC_LANG >= 201103L
+#   define GC_NOEXCEPT noexcept
+# else
+#   define GC_NOEXCEPT throw()
+# endif
+#endif
+
+#endif /* __cplusplus */
+
+#endif

+ 568 - 0
blitz.mod/bdwgc/include/gc/gc_cpp.h

@@ -0,0 +1,568 @@
+/*
+ * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program for any
+ * purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is
+ * granted, provided the above notices are retained, and a notice that
+ * the code was modified is included with the above copyright notice.
+ */
+
+#ifndef GC_CPP_H
+#define GC_CPP_H
+
+/****************************************************************************
+C++ Interface to the Boehm Collector
+
+    John R. Ellis and Jesse Hull
+
+This interface provides access to the Boehm collector.  It provides
+basic facilities similar to those described in "Safe, Efficient
+Garbage Collection for C++", by John R. Ellis and David L. Detlefs
+(ftp://ftp.parc.xerox.com/pub/ellis/gc).
+
+All heap-allocated objects are either "collectible" or
+"uncollectible".  Programs must explicitly delete uncollectible
+objects, whereas the garbage collector will automatically delete
+collectible objects when it discovers them to be inaccessible.
+Collectible objects may freely point at uncollectible objects and vice
+versa.
+
+Objects allocated with the built-in "::operator new" are uncollectible.
+
+Objects derived from class "gc" are collectible.  For example:
+
+    class A: public gc {...};
+    A* a = new A;       // a is collectible.
+
+Collectible instances of non-class types can be allocated using the GC
+(or UseGC) placement:
+
+    typedef int A[ 10 ];
+    A* a = new (GC) A;
+
+Uncollectible instances of classes derived from "gc" can be allocated
+using the NoGC placement:
+
+    class A: public gc {...};
+    A* a = new (NoGC) A;   // a is uncollectible.
+
+The new(PointerFreeGC) syntax allows the allocation of collectible
+objects that are not scanned by the collector.  This useful if you
+are allocating compressed data, bitmaps, or network packets.  (In
+the latter case, it may remove danger of unfriendly network packets
+intentionally containing values that cause spurious memory retention.)
+
+Both uncollectible and collectible objects can be explicitly deleted
+with "delete", which invokes an object's destructors and frees its
+storage immediately.
+
+A collectible object may have a clean-up function, which will be
+invoked when the collector discovers the object to be inaccessible.
+An object derived from "gc_cleanup" or containing a member derived
+from "gc_cleanup" has a default clean-up function that invokes the
+object's destructors.  Explicit clean-up functions may be specified as
+an additional placement argument:
+
+    A* a = ::new (GC, MyCleanup) A;
+
+An object is considered "accessible" by the collector if it can be
+reached by a path of pointers from static variables, automatic
+variables of active functions, or from some object with clean-up
+enabled; pointers from an object to itself are ignored.
+
+Thus, if objects A and B both have clean-up functions, and A points at
+B, B is considered accessible.  After A's clean-up is invoked and its
+storage released, B will then become inaccessible and will have its
+clean-up invoked.  If A points at B and B points to A, forming a
+cycle, then that's considered a storage leak, and neither will be
+collectible.  See the interface gc.h for low-level facilities for
+handling such cycles of objects with clean-up.
+
+The collector cannot guarantee that it will find all inaccessible
+objects.  In practice, it finds almost all of them.
+
+
+Cautions:
+
+1. Be sure the collector has been augmented with "make c++" or
+"--enable-cplusplus".
+
+2.  If your compiler supports the new "operator new[]" syntax, then
+add -DGC_OPERATOR_NEW_ARRAY to the Makefile.
+
+If your compiler doesn't support "operator new[]", beware that an
+array of type T, where T is derived from "gc", may or may not be
+allocated as a collectible object (it depends on the compiler).  Use
+the explicit GC placement to make the array collectible.  For example:
+
+    class A: public gc {...};
+    A* a1 = new A[ 10 ];        // collectible or uncollectible?
+    A* a2 = new (GC) A[ 10 ];   // collectible.
+
+3. The destructors of collectible arrays of objects derived from
+"gc_cleanup" will not be invoked properly.  For example:
+
+    class A: public gc_cleanup {...};
+    A* a = new (GC) A[ 10 ];    // destructors not invoked correctly
+
+Typically, only the destructor for the first element of the array will
+be invoked when the array is garbage-collected.  To get all the
+destructors of any array executed, you must supply an explicit
+clean-up function:
+
+    A* a = new (GC, MyCleanUp) A[ 10 ];
+
+(Implementing clean-up of arrays correctly, portably, and in a way
+that preserves the correct exception semantics requires a language
+extension, e.g. the "gc" keyword.)
+
+4. Compiler bugs (now hopefully history):
+
+* Solaris 2's CC (SC3.0) doesn't implement t->~T() correctly, so the
+destructors of classes derived from gc_cleanup won't be invoked.
+You'll have to explicitly register a clean-up function with
+new-placement syntax.
+
+* Evidently cfront 3.0 does not allow destructors to be explicitly
+invoked using the ANSI-conforming syntax t->~T().  If you're using
+cfront 3.0, you'll have to comment out the class gc_cleanup, which
+uses explicit invocation.
+
+5. GC name conflicts:
+
+Many other systems seem to use the identifier "GC" as an abbreviation
+for "Graphics Context".  Thus, GC placement has been replaced
+by UseGC.  GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined.
+
+****************************************************************************/
+
+#include "gc.h"
+
+#ifdef GC_NAMESPACE
+# define GC_NS_QUALIFY(T) boehmgc::T
+#else
+# define GC_NS_QUALIFY(T) T
+#endif
+
+#ifndef THINK_CPLUS
+# define GC_cdecl GC_CALLBACK
+#else
+# define GC_cdecl _cdecl
+#endif
+
+#if !defined(GC_NO_OPERATOR_NEW_ARRAY) \
+    && !defined(_ENABLE_ARRAYNEW) /* Digimars */ \
+    && (defined(__BORLANDC__) && (__BORLANDC__ < 0x450) \
+        || (defined(__GNUC__) && !GC_GNUC_PREREQ(2, 6)) \
+        || (defined(_MSC_VER) && _MSC_VER <= 1020) \
+        || (defined(__WATCOMC__) && __WATCOMC__ < 1050))
+# define GC_NO_OPERATOR_NEW_ARRAY
+#endif
+
+#if !defined(GC_NO_OPERATOR_NEW_ARRAY) && !defined(GC_OPERATOR_NEW_ARRAY)
+# define GC_OPERATOR_NEW_ARRAY
+#endif
+
+#if (!defined(__BORLANDC__) || __BORLANDC__ > 0x0620) \
+    && ! defined (__sgi) && ! defined(__WATCOMC__) \
+    && (!defined(_MSC_VER) || _MSC_VER > 1020)
+# define GC_PLACEMENT_DELETE
+#endif
+
+#if defined(GC_NEW_ABORTS_ON_OOM) || defined(_LIBCPP_NO_EXCEPTIONS)
+# define GC_OP_NEW_OOM_CHECK(obj) \
+                do { if (!(obj)) GC_abort_on_oom(); } while (0)
+#elif defined(GC_INCLUDE_NEW)
+# include <new> // for bad_alloc
+# define GC_OP_NEW_OOM_CHECK(obj) if (obj) {} else throw std::bad_alloc()
+#else
+  // "new" header is not included, so bad_alloc cannot be thrown directly.
+  GC_API void GC_CALL GC_throw_bad_alloc();
+# define GC_OP_NEW_OOM_CHECK(obj) if (obj) {} else GC_throw_bad_alloc()
+#endif // !GC_NEW_ABORTS_ON_OOM && !GC_INCLUDE_NEW
+
+#ifdef GC_NAMESPACE
+namespace boehmgc
+{
+#endif
+
+enum GCPlacement
+{
+  UseGC,
+# ifndef GC_NAME_CONFLICT
+    GC = UseGC,
+# endif
+  NoGC,
+  PointerFreeGC
+# ifdef GC_ATOMIC_UNCOLLECTABLE
+    , PointerFreeNoGC
+# endif
+};
+
+/**
+ * Instances of classes derived from "gc" will be allocated in the collected
+ * heap by default, unless an explicit NoGC placement is specified.
+ */
+class gc
+{
+public:
+  inline void* operator new(size_t size);
+  inline void* operator new(size_t size, GCPlacement gcp);
+  inline void* operator new(size_t size, void* p) GC_NOEXCEPT;
+    // Must be redefined here, since the other overloadings hide
+    // the global definition.
+  inline void operator delete(void* obj) GC_NOEXCEPT;
+
+# ifdef GC_PLACEMENT_DELETE
+    inline void operator delete(void*, GCPlacement) GC_NOEXCEPT;
+      // Called if construction fails.
+    inline void operator delete(void*, void*) GC_NOEXCEPT;
+# endif // GC_PLACEMENT_DELETE
+
+# ifdef GC_OPERATOR_NEW_ARRAY
+    inline void* operator new[](size_t size);
+    inline void* operator new[](size_t size, GCPlacement gcp);
+    inline void* operator new[](size_t size, void* p) GC_NOEXCEPT;
+    inline void operator delete[](void* obj) GC_NOEXCEPT;
+#   ifdef GC_PLACEMENT_DELETE
+      inline void operator delete[](void*, GCPlacement) GC_NOEXCEPT;
+      inline void operator delete[](void*, void*) GC_NOEXCEPT;
+#   endif
+# endif // GC_OPERATOR_NEW_ARRAY
+};
+
+/**
+ * Instances of classes derived from "gc_cleanup" will be allocated
+ * in the collected heap by default.  When the collector discovers
+ * an inaccessible object derived from "gc_cleanup" or containing
+ * a member derived from "gc_cleanup", its destructors will be invoked.
+ */
+class gc_cleanup: virtual public gc
+{
+public:
+  inline gc_cleanup();
+  inline virtual ~gc_cleanup();
+
+private:
+  inline static void GC_cdecl cleanup(void* obj, void* clientData);
+};
+
+extern "C" {
+  typedef void (GC_CALLBACK * GCCleanUpFunc)(void* obj, void* clientData);
+}
+
+#ifdef GC_NAMESPACE
+}
+#endif
+
+#ifdef _MSC_VER
+  // Disable warning that "no matching operator delete found; memory will
+  // not be freed if initialization throws an exception"
+# pragma warning(disable:4291)
+  // TODO: "non-member operator new or delete may not be declared inline"
+  // warning is disabled for now.
+# pragma warning(disable:4595)
+#endif
+
+inline void* operator new(size_t size, GC_NS_QUALIFY(GCPlacement) gcp,
+                          GC_NS_QUALIFY(GCCleanUpFunc) /* cleanup */ = 0,
+                          void* /* clientData */ = 0);
+    // Allocates a collectible or uncollectible object, according to the
+    // value of "gcp".
+    //
+    // For collectible objects, if "cleanup" is non-null, then when the
+    // allocated object "obj" becomes inaccessible, the collector will
+    // invoke the function "cleanup(obj, clientData)" but will not
+    // invoke the object's destructors.  It is an error to explicitly
+    // delete an object allocated with a non-null "cleanup".
+    //
+    // It is an error to specify a non-null "cleanup" with NoGC or for
+    // classes derived from "gc_cleanup" or containing members derived
+    // from "gc_cleanup".
+
+#ifdef GC_PLACEMENT_DELETE
+  inline void operator delete(void*, GC_NS_QUALIFY(GCPlacement),
+                              GC_NS_QUALIFY(GCCleanUpFunc),
+                              void*) GC_NOEXCEPT;
+#endif
+
+#ifndef GC_NO_INLINE_STD_NEW
+
+#if defined(_MSC_VER) || defined(__DMC__) \
+    || ((defined(__BORLANDC__) || defined(__CYGWIN__) \
+         || defined(__CYGWIN32__) || defined(__MINGW32__) \
+         || defined(__WATCOMC__)) \
+        && !defined(GC_BUILD) && !defined(GC_NOT_DLL))
+  // Inlining done to avoid mix up of new and delete operators by VC++ 9 (due
+  // to arbitrary ordering during linking).
+
+# ifdef GC_OPERATOR_NEW_ARRAY
+    inline void* operator new[](size_t size)
+    {
+      void* obj = GC_MALLOC_UNCOLLECTABLE(size);
+      GC_OP_NEW_OOM_CHECK(obj);
+      return obj;
+    }
+
+    inline void operator delete[](void* obj) GC_NOEXCEPT
+    {
+      GC_FREE(obj);
+    }
+# endif
+
+  inline void* operator new(size_t size)
+  {
+    void* obj = GC_MALLOC_UNCOLLECTABLE(size);
+    GC_OP_NEW_OOM_CHECK(obj);
+    return obj;
+  }
+
+  inline void operator delete(void* obj) GC_NOEXCEPT
+  {
+    GC_FREE(obj);
+  }
+
+# if __cplusplus >= 201402L || _MSVC_LANG >= 201402L // C++14
+    inline void operator delete(void* obj, size_t size) GC_NOEXCEPT {
+      (void)size; // size is ignored
+      GC_FREE(obj);
+    }
+
+#   if defined(GC_OPERATOR_NEW_ARRAY)
+      inline void operator delete[](void* obj, size_t size) GC_NOEXCEPT {
+        (void)size;
+        GC_FREE(obj);
+      }
+#   endif
+# endif // C++14
+#endif
+
+#ifdef _MSC_VER
+
+  // This new operator is used by VC++ in case of Debug builds:
+# ifdef GC_DEBUG
+    inline void* operator new(size_t size, int /* nBlockUse */,
+                              const char* szFileName, int nLine)
+    {
+      void* obj = GC_debug_malloc_uncollectable(size, szFileName, nLine);
+      GC_OP_NEW_OOM_CHECK(obj);
+      return obj;
+    }
+# else
+    inline void* operator new(size_t size, int /* nBlockUse */,
+                              const char* /* szFileName */, int /* nLine */)
+    {
+      void* obj = GC_malloc_uncollectable(size);
+      GC_OP_NEW_OOM_CHECK(obj);
+      return obj;
+    }
+# endif /* !GC_DEBUG */
+
+# ifdef GC_OPERATOR_NEW_ARRAY
+    // This new operator is used by VC++ 7+ in Debug builds:
+    inline void* operator new[](size_t size, int nBlockUse,
+                                const char* szFileName, int nLine)
+    {
+      return operator new(size, nBlockUse, szFileName, nLine);
+    }
+# endif
+
+#endif // _MSC_VER
+
+#elif defined(_MSC_VER)
+  // The following ensures that the system default operator new[] does not
+  // get undefined, which is what seems to happen on VC++ 6 for some reason
+  // if we define a multi-argument operator new[].
+  // There seems to be no way to redirect new in this environment without
+  // including this everywhere.
+# ifdef GC_OPERATOR_NEW_ARRAY
+    void *operator new[](size_t size);
+    void operator delete[](void* obj);
+# endif
+
+  void* operator new(size_t size);
+  void operator delete(void* obj);
+
+  void* operator new(size_t size, int /* nBlockUse */,
+                     const char * szFileName, int nLine);
+#endif // GC_NO_INLINE_STD_NEW && _MSC_VER
+
+#ifdef GC_OPERATOR_NEW_ARRAY
+  // The operator new for arrays, identical to the above.
+  inline void* operator new[](size_t size, GC_NS_QUALIFY(GCPlacement) gcp,
+                              GC_NS_QUALIFY(GCCleanUpFunc) /* cleanup */ = 0,
+                              void* /* clientData */ = 0);
+#endif // GC_OPERATOR_NEW_ARRAY
+
+/* Inline implementation */
+
+#ifdef GC_NAMESPACE
+namespace boehmgc
+{
+#endif
+
+inline void* gc::operator new(size_t size)
+{
+  void* obj = GC_MALLOC(size);
+  GC_OP_NEW_OOM_CHECK(obj);
+  return obj;
+}
+
+inline void* gc::operator new(size_t size, GCPlacement gcp)
+{
+  void* obj;
+  switch (gcp) {
+  case UseGC:
+    obj = GC_MALLOC(size);
+    break;
+  case PointerFreeGC:
+    obj = GC_MALLOC_ATOMIC(size);
+    break;
+# ifdef GC_ATOMIC_UNCOLLECTABLE
+    case PointerFreeNoGC:
+      obj = GC_MALLOC_ATOMIC_UNCOLLECTABLE(size);
+      break;
+# endif
+  case NoGC:
+  default:
+    obj = GC_MALLOC_UNCOLLECTABLE(size);
+  }
+  GC_OP_NEW_OOM_CHECK(obj);
+  return obj;
+}
+
+inline void* gc::operator new(size_t /* size */, void* p) GC_NOEXCEPT
+{
+  return p;
+}
+
+inline void gc::operator delete(void* obj) GC_NOEXCEPT
+{
+  GC_FREE(obj);
+}
+
+#ifdef GC_PLACEMENT_DELETE
+  inline void gc::operator delete(void*, void*) GC_NOEXCEPT {}
+
+  inline void gc::operator delete(void* p, GCPlacement /* gcp */) GC_NOEXCEPT
+  {
+    GC_FREE(p);
+  }
+#endif // GC_PLACEMENT_DELETE
+
+#ifdef GC_OPERATOR_NEW_ARRAY
+  inline void* gc::operator new[](size_t size)
+  {
+    return gc::operator new(size);
+  }
+
+  inline void* gc::operator new[](size_t size, GCPlacement gcp)
+  {
+    return gc::operator new(size, gcp);
+  }
+
+  inline void* gc::operator new[](size_t /* size */, void* p) GC_NOEXCEPT
+  {
+    return p;
+  }
+
+  inline void gc::operator delete[](void* obj) GC_NOEXCEPT
+  {
+    gc::operator delete(obj);
+  }
+
+# ifdef GC_PLACEMENT_DELETE
+    inline void gc::operator delete[](void*, void*) GC_NOEXCEPT {}
+
+    inline void gc::operator delete[](void* p,
+                                      GCPlacement /* gcp */) GC_NOEXCEPT
+    {
+      gc::operator delete(p);
+    }
+# endif
+#endif // GC_OPERATOR_NEW_ARRAY
+
+inline gc_cleanup::~gc_cleanup()
+{
+  void* base = GC_base(this);
+  if (0 == base) return; // Non-heap object.
+  GC_register_finalizer_ignore_self(base, 0, 0, 0, 0);
+}
+
+inline void GC_CALLBACK gc_cleanup::cleanup(void* obj, void* displ)
+{
+  ((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup();
+}
+
+inline gc_cleanup::gc_cleanup()
+{
+  GC_finalization_proc oldProc;
+  void* oldData;
+  void* this_ptr = (void*)this;
+  void* base = GC_base(this_ptr);
+  if (base != 0) {
+    // Don't call the debug version, since this is a real base address.
+    GC_register_finalizer_ignore_self(base, (GC_finalization_proc) cleanup,
+                                      (void*)((char*)this_ptr - (char*)base),
+                                      &oldProc, &oldData);
+    if (oldProc != 0) {
+      GC_register_finalizer_ignore_self(base, oldProc, oldData, 0, 0);
+    }
+  }
+}
+
+#ifdef GC_NAMESPACE
+}
+#endif
+
+inline void* operator new(size_t size, GC_NS_QUALIFY(GCPlacement) gcp,
+                          GC_NS_QUALIFY(GCCleanUpFunc) cleanup,
+                          void* clientData)
+{
+  void* obj;
+  switch (gcp) {
+  case GC_NS_QUALIFY(UseGC):
+    obj = GC_MALLOC(size);
+    if (cleanup != 0 && obj != 0) {
+      GC_REGISTER_FINALIZER_IGNORE_SELF(obj, cleanup, clientData, 0, 0);
+    }
+    break;
+  case GC_NS_QUALIFY(PointerFreeGC):
+    obj = GC_MALLOC_ATOMIC(size);
+    break;
+# ifdef GC_ATOMIC_UNCOLLECTABLE
+    case GC_NS_QUALIFY(PointerFreeNoGC):
+      obj = GC_MALLOC_ATOMIC_UNCOLLECTABLE(size);
+      break;
+# endif
+  case GC_NS_QUALIFY(NoGC):
+  default:
+    obj = GC_MALLOC_UNCOLLECTABLE(size);
+  }
+  GC_OP_NEW_OOM_CHECK(obj);
+  return obj;
+}
+
+#ifdef GC_PLACEMENT_DELETE
+  inline void operator delete(void* p, GC_NS_QUALIFY(GCPlacement) /* gcp */,
+                              GC_NS_QUALIFY(GCCleanUpFunc) /* cleanup */,
+                              void* /* clientData */) GC_NOEXCEPT
+  {
+    GC_FREE(p);
+  }
+#endif // GC_PLACEMENT_DELETE
+
+#ifdef GC_OPERATOR_NEW_ARRAY
+  inline void* operator new[](size_t size, GC_NS_QUALIFY(GCPlacement) gcp,
+                              GC_NS_QUALIFY(GCCleanUpFunc) cleanup,
+                              void* clientData)
+  {
+    return ::operator new(size, gcp, cleanup, clientData);
+  }
+#endif // GC_OPERATOR_NEW_ARRAY
+
+#endif /* GC_CPP_H */

+ 0 - 0
blitz.mod/bdwgc/include/gc_disclaim.h → blitz.mod/bdwgc/include/gc/gc_disclaim.h


+ 0 - 0
blitz.mod/bdwgc/include/gc_gcj.h → blitz.mod/bdwgc/include/gc/gc_gcj.h


+ 0 - 0
blitz.mod/bdwgc/include/gc_inline.h → blitz.mod/bdwgc/include/gc/gc_inline.h


+ 0 - 0
blitz.mod/bdwgc/include/gc_mark.h → blitz.mod/bdwgc/include/gc/gc_mark.h


+ 0 - 0
blitz.mod/bdwgc/include/gc_pthread_redirects.h → blitz.mod/bdwgc/include/gc/gc_pthread_redirects.h


Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor