sleepyhead111 commited on
Commit
2aec307
·
verified ·
1 Parent(s): 095d273

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. mosesdecoder/doc/PhraseDictionaryBitextSampling.howto +4 -0
  2. mosesdecoder/jam-files/boost-build/build/alias.jam +73 -0
  3. mosesdecoder/jam-files/boost-build/build/build-request.jam +322 -0
  4. mosesdecoder/jam-files/boost-build/build/configure.jam +237 -0
  5. mosesdecoder/jam-files/boost-build/build/feature.jam +1335 -0
  6. mosesdecoder/jam-files/boost-build/build/generators.jam +1380 -0
  7. mosesdecoder/jam-files/boost-build/build/modifiers.jam +232 -0
  8. mosesdecoder/jam-files/boost-build/build/property.jam +788 -0
  9. mosesdecoder/jam-files/boost-build/build/scanner.jam +153 -0
  10. mosesdecoder/jam-files/boost-build/build/toolset.jam +575 -0
  11. mosesdecoder/jam-files/boost-build/build/type.jam +425 -0
  12. mosesdecoder/jam-files/engine/boehm_gc/NT_X64_STATIC_THREADS_MAKEFILE +74 -0
  13. mosesdecoder/jam-files/engine/boehm_gc/SMakefile.amiga +177 -0
  14. mosesdecoder/jam-files/engine/boehm_gc/alpha_mach_dep.S +86 -0
  15. mosesdecoder/jam-files/engine/boehm_gc/backgraph.c +469 -0
  16. mosesdecoder/jam-files/engine/boehm_gc/bdw-gc.pc +10 -0
  17. mosesdecoder/jam-files/engine/boehm_gc/callprocs +4 -0
  18. mosesdecoder/jam-files/engine/boehm_gc/compile +142 -0
  19. mosesdecoder/jam-files/engine/boehm_gc/configure +0 -0
  20. mosesdecoder/jam-files/engine/boehm_gc/doc/README +548 -0
  21. mosesdecoder/jam-files/engine/boehm_gc/doc/README.amiga +322 -0
  22. mosesdecoder/jam-files/engine/boehm_gc/doc/README.changes +0 -0
  23. mosesdecoder/jam-files/engine/boehm_gc/doc/README.ews4800 +81 -0
  24. mosesdecoder/jam-files/engine/boehm_gc/doc/README.macros +82 -0
  25. mosesdecoder/jam-files/engine/boehm_gc/doc/README.rs6000 +9 -0
  26. mosesdecoder/jam-files/engine/boehm_gc/doc/doc.am +55 -0
  27. mosesdecoder/jam-files/engine/boehm_gc/doc/gcdescr.html +621 -0
  28. mosesdecoder/jam-files/engine/boehm_gc/doc/scale.html +210 -0
  29. mosesdecoder/jam-files/engine/boehm_gc/doc/simple_example.html +202 -0
  30. mosesdecoder/jam-files/engine/boehm_gc/finalize.c +869 -0
  31. mosesdecoder/jam-files/engine/boehm_gc/gc.mak +2220 -0
  32. mosesdecoder/jam-files/engine/boehm_gc/gc_cpp.cpp +2 -0
  33. mosesdecoder/jam-files/engine/boehm_gc/hpux_test_and_clear.s +21 -0
  34. mosesdecoder/jam-files/engine/boehm_gc/mips_ultrix_mach_dep.s +26 -0
  35. mosesdecoder/jam-files/engine/boehm_gc/misc.c +1177 -0
  36. mosesdecoder/jam-files/engine/boehm_gc/os_dep.c +0 -0
  37. mosesdecoder/jam-files/engine/boehm_gc/pcr_interface.c +179 -0
  38. mosesdecoder/jam-files/engine/boehm_gc/pthread_support.c +1495 -0
  39. mosesdecoder/jam-files/engine/boehm_gc/reclaim.c +608 -0
  40. mosesdecoder/jam-files/engine/boehm_gc/sparc_netbsd_mach_dep.s +34 -0
  41. mosesdecoder/jam-files/engine/boehm_gc/version.h +30 -0
  42. mosesdecoder/lm/common/compare.hh +174 -0
  43. mosesdecoder/lm/common/model_buffer.cc +91 -0
  44. mosesdecoder/lm/common/model_buffer.hh +63 -0
  45. mosesdecoder/lm/common/ngram_stream.hh +65 -0
  46. mosesdecoder/lm/common/print.hh +58 -0
  47. mosesdecoder/lm/common/size_option.cc +24 -0
  48. mosesdecoder/lm/common/size_option.hh +11 -0
  49. mosesdecoder/lm/common/special.hh +27 -0
  50. mosesdecoder/lm/config.cc +30 -0
mosesdecoder/doc/PhraseDictionaryBitextSampling.howto ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ The documentation for memory-mapped, dynamic suffix arrays has moved to
2
+ http://www.statmt.org/moses/?n=Moses.AdvancedFeatures#ntoc40
3
+
4
+ Search for PhraseDictionaryBitextSampling.
mosesdecoder/jam-files/boost-build/build/alias.jam ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2003, 2004, 2006 Vladimir Prus
2
+ # Distributed under the Boost Software License, Version 1.0.
3
+ # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
4
+
5
+ # This module defines the 'alias' rule and the associated target class.
6
+ #
7
+ # Alias is just a main target which returns its source targets without any
8
+ # processing. For example:
9
+ #
10
+ # alias bin : hello test_hello ;
11
+ # alias lib : helpers xml_parser ;
12
+ #
13
+ # Another important use of 'alias' is to conveniently group source files:
14
+ #
15
+ # alias platform-src : win.cpp : <os>NT ;
16
+ # alias platform-src : linux.cpp : <os>LINUX ;
17
+ # exe main : main.cpp platform-src ;
18
+ #
19
+ # Lastly, it is possible to create a local alias for some target, with different
20
+ # properties:
21
+ #
22
+ # alias big_lib : : @/external_project/big_lib/<link>static ;
23
+ #
24
+
25
+ import "class" : new ;
26
+ import project ;
27
+ import property-set ;
28
+ import targets ;
29
+
30
+
31
+ class alias-target-class : basic-target
32
+ {
33
+ rule __init__ ( name : project : sources * : requirements *
34
+ : default-build * : usage-requirements * )
35
+ {
36
+ basic-target.__init__ $(name) : $(project) : $(sources) :
37
+ $(requirements) : $(default-build) : $(usage-requirements) ;
38
+ }
39
+
40
+ rule construct ( name : source-targets * : property-set )
41
+ {
42
+ return [ property-set.empty ] $(source-targets) ;
43
+ }
44
+
45
+ rule compute-usage-requirements ( subvariant )
46
+ {
47
+ local base = [ basic-target.compute-usage-requirements $(subvariant) ] ;
48
+ return [ $(base).add [ $(subvariant).sources-usage-requirements ] ] ;
49
+ }
50
+ }
51
+
52
+
53
+ # Declares the 'alias' target. It will process its sources virtual-targets by
54
+ # returning them unaltered as its own constructed virtual-targets.
55
+ #
56
+ rule alias ( name : sources * : requirements * : default-build * :
57
+ usage-requirements * )
58
+ {
59
+ local project = [ project.current ] ;
60
+
61
+ targets.main-target-alternative
62
+ [ new alias-target-class $(name) : $(project)
63
+ : [ targets.main-target-sources $(sources) : $(name) : no-renaming ]
64
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
65
+ : [ targets.main-target-default-build $(default-build) : $(project)
66
+ ]
67
+ : [ targets.main-target-usage-requirements $(usage-requirements) :
68
+ $(project) ]
69
+ ] ;
70
+ }
71
+
72
+
73
+ IMPORT $(__name__) : alias : : alias ;
mosesdecoder/jam-files/boost-build/build/build-request.jam ADDED
@@ -0,0 +1,322 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2002 Dave Abrahams
2
+ # Distributed under the Boost Software License, Version 1.0.
3
+ # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
4
+
5
+ import "class" : new ;
6
+ import sequence ;
7
+ import set ;
8
+ import regex ;
9
+ import feature ;
10
+ import property ;
11
+ import container ;
12
+ import string ;
13
+
14
+
15
+ # Transform property-set by applying f to each component property.
16
+ #
17
+ local rule apply-to-property-set ( f property-set )
18
+ {
19
+ local properties = [ feature.split $(property-set) ] ;
20
+ return [ string.join [ $(f) $(properties) ] : / ] ;
21
+ }
22
+
23
+
24
+ # Expand the given build request by combining all property-sets which do not
25
+ # specify conflicting non-free features. Expects all the project files to
26
+ # already be loaded.
27
+ #
28
+ rule expand-no-defaults ( property-sets * )
29
+ {
30
+ # First make all features and subfeatures explicit.
31
+ local expanded-property-sets = [ sequence.transform apply-to-property-set
32
+ feature.expand-subfeatures : $(property-sets) ] ;
33
+
34
+ # Now combine all of the expanded property-sets
35
+ local product = [ x-product $(expanded-property-sets) : $(feature-space) ] ;
36
+
37
+ return $(product) ;
38
+ }
39
+
40
+
41
+ # Implementation of x-product, below. Expects all the project files to already
42
+ # be loaded.
43
+ #
44
+ local rule x-product-aux ( property-sets + )
45
+ {
46
+ local result ;
47
+ local p = [ feature.split $(property-sets[1]) ] ;
48
+ local f = [ set.difference $(p:G) : [ feature.free-features ] ] ;
49
+ local seen ;
50
+ # No conflict with things used at a higher level?
51
+ if ! [ set.intersection $(f) : $(x-product-used) ]
52
+ {
53
+ local x-product-seen ;
54
+ {
55
+ # Do not mix in any conflicting features.
56
+ local x-product-used = $(x-product-used) $(f) ;
57
+
58
+ if $(property-sets[2])
59
+ {
60
+ local rest = [ x-product-aux $(property-sets[2-]) : $(feature-space) ] ;
61
+ result = $(property-sets[1])/$(rest) ;
62
+ }
63
+
64
+ result ?= $(property-sets[1]) ;
65
+ }
66
+
67
+ # If we did not encounter a conflicting feature lower down, do not
68
+ # recurse again.
69
+ if ! [ set.intersection $(f) : $(x-product-seen) ]
70
+ {
71
+ property-sets = ;
72
+ }
73
+
74
+ seen = $(x-product-seen) ;
75
+ }
76
+
77
+ if $(property-sets[2])
78
+ {
79
+ result += [ x-product-aux $(property-sets[2-]) : $(feature-space) ] ;
80
+ }
81
+
82
+ # Note that we have seen these features so that higher levels will recurse
83
+ # again without them set.
84
+ x-product-seen += $(f) $(seen) ;
85
+ return $(result) ;
86
+ }
87
+
88
+
89
+ # Return the cross-product of all elements of property-sets, less any that would
90
+ # contain conflicting values for single-valued features. Expects all the project
91
+ # files to already be loaded.
92
+ #
93
+ local rule x-product ( property-sets * )
94
+ {
95
+ if $(property-sets).non-empty
96
+ {
97
+ # Prepare some "scoped globals" that can be used by the implementation
98
+ # function, x-product-aux.
99
+ local x-product-seen x-product-used ;
100
+ return [ x-product-aux $(property-sets) : $(feature-space) ] ;
101
+ }
102
+ # Otherwise return empty.
103
+ }
104
+
105
+
106
+ # Returns true if either 'v' or the part of 'v' before the first '-' symbol is
107
+ # an implicit value. Expects all the project files to already be loaded.
108
+ #
109
+ local rule looks-like-implicit-value ( v )
110
+ {
111
+ if [ feature.is-implicit-value $(v) ]
112
+ {
113
+ return true ;
114
+ }
115
+ else
116
+ {
117
+ local split = [ regex.split $(v) - ] ;
118
+ if [ feature.is-implicit-value $(split[1]) ]
119
+ {
120
+ return true ;
121
+ }
122
+ }
123
+ }
124
+
125
+
126
+ # Takes the command line tokens (such as taken from the ARGV rule) and
127
+ # constructs a build request from them. Returns a vector of two vectors (where
128
+ # "vector" means container.jam's "vector"). First is the set of targets
129
+ # specified in the command line, and second is the set of requested build
130
+ # properties. Expects all the project files to already be loaded.
131
+ #
132
+ rule from-command-line ( command-line * )
133
+ {
134
+ local targets ;
135
+ local properties ;
136
+
137
+ command-line = $(command-line[2-]) ;
138
+ local skip-next = ;
139
+ for local e in $(command-line)
140
+ {
141
+ if $(skip-next)
142
+ {
143
+ skip-next = ;
144
+ }
145
+ else if ! [ MATCH "^(-).*" : $(e) ]
146
+ {
147
+ # Build request spec either has "=" in it or completely consists of
148
+ # implicit feature values.
149
+ local fs = feature-space ;
150
+ if [ MATCH "(.*=.*)" : $(e) ]
151
+ || [ looks-like-implicit-value $(e:D=) : $(feature-space) ]
152
+ {
153
+ properties += [ convert-command-line-element $(e) :
154
+ $(feature-space) ] ;
155
+ }
156
+ else
157
+ {
158
+ targets += $(e) ;
159
+ }
160
+ }
161
+ else if [ MATCH "^(-[-ldjfsto])$" : $(e) ]
162
+ {
163
+ skip-next = true ;
164
+ }
165
+ }
166
+ return [ new vector
167
+ [ new vector $(targets) ]
168
+ [ new vector $(properties) ] ] ;
169
+ }
170
+
171
+
172
+ # Converts one element of command line build request specification into internal
173
+ # form. Expects all the project files to already be loaded.
174
+ #
175
+ local rule convert-command-line-element ( e )
176
+ {
177
+ local result ;
178
+ local parts = [ regex.split $(e) "/" ] ;
179
+ while $(parts)
180
+ {
181
+ local p = $(parts[1]) ;
182
+ local m = [ MATCH "([^=]*)=(.*)" : $(p) ] ;
183
+ local lresult ;
184
+ local feature ;
185
+ local values ;
186
+ if $(m)
187
+ {
188
+ feature = $(m[1]) ;
189
+ values = [ regex.split $(m[2]) "," ] ;
190
+ lresult = <$(feature)>$(values) ;
191
+ }
192
+ else
193
+ {
194
+ lresult = [ regex.split $(p) "," ] ;
195
+ }
196
+
197
+ if $(feature) && free in [ feature.attributes $(feature) ]
198
+ {
199
+ # If we have free feature, then the value is everything
200
+ # until the end of the command line token. Slashes in
201
+ # the following string are not taked to mean separation
202
+ # of properties. Commas are also not interpreted specially.
203
+ values = $(values:J=,) ;
204
+ values = $(values) $(parts[2-]) ;
205
+ values = $(values:J=/) ;
206
+ lresult = <$(feature)>$(values) ;
207
+ parts = ;
208
+ }
209
+
210
+ if ! [ MATCH (.*-.*) : $(p) ]
211
+ {
212
+ # property.validate cannot handle subfeatures, so we avoid the check
213
+ # here.
214
+ for local p in $(lresult)
215
+ {
216
+ property.validate $(p) : $(feature-space) ;
217
+ }
218
+ }
219
+
220
+ if ! $(result)
221
+ {
222
+ result = $(lresult) ;
223
+ }
224
+ else
225
+ {
226
+ result = $(result)/$(lresult) ;
227
+ }
228
+
229
+ parts = $(parts[2-]) ;
230
+ }
231
+
232
+ return $(result) ;
233
+ }
234
+
235
+
236
+ rule __test__ ( )
237
+ {
238
+ import assert ;
239
+ import feature ;
240
+
241
+ feature.prepare-test build-request-test-temp ;
242
+
243
+ import build-request ;
244
+ import build-request : expand-no-defaults : build-request.expand-no-defaults ;
245
+ import errors : try catch ;
246
+ import feature : feature subfeature ;
247
+
248
+ feature toolset : gcc msvc borland : implicit ;
249
+ subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4
250
+ 3.0 3.0.1 3.0.2 : optional ;
251
+
252
+ feature variant : debug release : implicit composite ;
253
+ feature inlining : on off ;
254
+ feature "include" : : free ;
255
+
256
+ feature stdlib : native stlport : implicit ;
257
+
258
+ feature runtime-link : dynamic static : symmetric ;
259
+
260
+ # Empty build requests should expand to empty.
261
+ assert.result
262
+ : build-request.expand-no-defaults ;
263
+
264
+ assert.result
265
+ <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug
266
+ <toolset>msvc/<stdlib>stlport/<variant>debug
267
+ <toolset>msvc/<variant>debug
268
+ : build-request.expand-no-defaults gcc-3.0.1/stlport msvc/stlport msvc debug ;
269
+
270
+ assert.result
271
+ <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug
272
+ <toolset>msvc/<variant>debug
273
+ <variant>debug/<toolset>msvc/<stdlib>stlport
274
+ : build-request.expand-no-defaults gcc-3.0.1/stlport msvc debug msvc/stlport ;
275
+
276
+ assert.result
277
+ <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug/<inlining>off
278
+ <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>release/<inlining>off
279
+ : build-request.expand-no-defaults gcc-3.0.1/stlport debug release <inlining>off ;
280
+
281
+ assert.result
282
+ <include>a/b/c/<toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug/<include>x/y/z
283
+ <include>a/b/c/<toolset>msvc/<stdlib>stlport/<variant>debug/<include>x/y/z
284
+ <include>a/b/c/<toolset>msvc/<variant>debug/<include>x/y/z
285
+ : build-request.expand-no-defaults <include>a/b/c gcc-3.0.1/stlport msvc/stlport msvc debug <include>x/y/z ;
286
+
287
+ local r ;
288
+
289
+ r = [ build-request.from-command-line bjam debug runtime-link=dynamic ] ;
290
+ assert.equal [ $(r).get-at 1 ] : ;
291
+ assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic ;
292
+
293
+ try ;
294
+ {
295
+ build-request.from-command-line bjam gcc/debug runtime-link=dynamic/static ;
296
+ }
297
+ catch \"static\" is not a value of an implicit feature ;
298
+
299
+ r = [ build-request.from-command-line bjam -d2 --debug debug target runtime-link=dynamic ] ;
300
+ assert.equal [ $(r).get-at 1 ] : target ;
301
+ assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic ;
302
+
303
+ r = [ build-request.from-command-line bjam debug runtime-link=dynamic,static ] ;
304
+ assert.equal [ $(r).get-at 1 ] : ;
305
+ assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic <runtime-link>static ;
306
+
307
+ r = [ build-request.from-command-line bjam debug gcc/runtime-link=dynamic,static ] ;
308
+ assert.equal [ $(r).get-at 1 ] : ;
309
+ assert.equal [ $(r).get-at 2 ] : debug gcc/<runtime-link>dynamic
310
+ gcc/<runtime-link>static ;
311
+
312
+ r = [ build-request.from-command-line bjam msvc gcc,borland/runtime-link=static ] ;
313
+ assert.equal [ $(r).get-at 1 ] : ;
314
+ assert.equal [ $(r).get-at 2 ] : msvc gcc/<runtime-link>static
315
+ borland/<runtime-link>static ;
316
+
317
+ r = [ build-request.from-command-line bjam gcc-3.0 ] ;
318
+ assert.equal [ $(r).get-at 1 ] : ;
319
+ assert.equal [ $(r).get-at 2 ] : gcc-3.0 ;
320
+
321
+ feature.finish-test build-request-test-temp ;
322
+ }
mosesdecoder/jam-files/boost-build/build/configure.jam ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2010 Vladimir Prus.
2
+ #
3
+ # Use, modification and distribution is subject to the Boost Software
4
+ # License Version 1.0. (See accompanying file LICENSE_1_0.txt or
5
+ # http://www.boost.org/LICENSE_1_0.txt)
6
+
7
+ # This module defines function to help with two main tasks:
8
+ #
9
+ # - Discovering build-time configuration for the purposes of adjusting
10
+ # build process.
11
+ # - Reporting what is built, and how it is configured.
12
+
13
+ import targets ;
14
+ import errors ;
15
+ import targets ;
16
+ import sequence ;
17
+ import property ;
18
+ import property-set ;
19
+ import "class" : new ;
20
+ import common ;
21
+ import path ;
22
+
23
+ rule log-summary ( )
24
+ {
25
+
26
+ }
27
+
28
+ .width = 30 ;
29
+
30
+ rule set-width ( width )
31
+ {
32
+ .width = $(width) ;
33
+ }
34
+
35
+ # Declare that the components specified by the parameter exist.
36
+ rule register-components ( components * )
37
+ {
38
+ .components += $(components) ;
39
+ }
40
+
41
+ # Declare that the components specified by the parameters will
42
+ # be build.
43
+ rule components-building ( components * )
44
+ {
45
+ .built-components += $(components) ;
46
+ }
47
+
48
+ # Report something about component configuration that the
49
+ # user should better know.
50
+ rule log-component-configuration ( component : message )
51
+ {
52
+ # FIXME: implement per-property-set logs
53
+ .component-logs.$(component) += $(message) ;
54
+ }
55
+
56
+
57
+
58
+ rule log-check-result ( result )
59
+ {
60
+ if ! $(.announced-checks)
61
+ {
62
+ ECHO "Performing configuration checks\n" ;
63
+ .announced-checks = 1 ;
64
+ }
65
+
66
+ ECHO $(result) ;
67
+ #.check-results += $(result) ;
68
+ }
69
+
70
+ rule log-library-search-result ( library : result )
71
+ {
72
+ local x = [ PAD " - $(library) : $(result)" : $(.width) ] ;
73
+ log-check-result "$(x)" ;
74
+ }
75
+
76
+ rule print-component-configuration ( )
77
+ {
78
+ local c = [ sequence.unique $(.components) ] ;
79
+
80
+ ECHO "\nComponent configuration:\n" ;
81
+ for c in $(.components)
82
+ {
83
+ local s ;
84
+ if $(c) in $(.built-components)
85
+ {
86
+ s = "building" ;
87
+ }
88
+ else
89
+ {
90
+ s = "not building" ;
91
+ }
92
+ ECHO [ PAD " - $(c)" : $(.width) ] ": $(s)" ;
93
+ for local m in $(.component-logs.$(c))
94
+ {
95
+ ECHO " -" $(m) ;
96
+ }
97
+ }
98
+ ECHO ;
99
+ }
100
+
101
+ rule print-configure-checks-summary ( )
102
+ {
103
+ # FIXME: the problem with that approach is tha
104
+ # the user sees checks summary when all checks are
105
+ # done, and has no progress reporting while the
106
+ # checks are being executed.
107
+ if $(.check-results)
108
+ {
109
+ ECHO "Configuration checks summary\n" ;
110
+
111
+ for local r in $(.check-results)
112
+ {
113
+ ECHO $(r) ;
114
+ }
115
+ ECHO ;
116
+ }
117
+ }
118
+
119
+ # Attempt to build a metatarget named by 'metatarget-reference'
120
+ # in context of 'project' with properties 'ps'.
121
+ # Returns non-empty value if build is OK.
122
+ rule builds-raw ( metatarget-reference : project : ps : what : retry ? )
123
+ {
124
+ local result ;
125
+
126
+ if ! $(retry) && ! $(.$(what)-tested.$(ps))
127
+ {
128
+ .$(what)-tested.$(ps) = true ;
129
+
130
+ local targets = [ targets.generate-from-reference
131
+ $(metatarget-reference) : $(project) : $(ps) ] ;
132
+
133
+ local jam-targets ;
134
+ for local t in $(targets[2-])
135
+ {
136
+ jam-targets += [ $(t).actualize ] ;
137
+ }
138
+
139
+ if ! UPDATE_NOW in [ RULENAMES ]
140
+ {
141
+ # Cannot determine. Assume existance.
142
+ }
143
+ else
144
+ {
145
+ local x = [ PAD " - $(what)" : $(.width) ] ;
146
+ if [ UPDATE_NOW $(jam-targets) :
147
+ $(.log-fd) : ignore-minus-n : ignore-minus-q ]
148
+ {
149
+ .$(what)-supported.$(ps) = yes ;
150
+ result = true ;
151
+ log-check-result "$(x) : yes" ;
152
+ }
153
+ else
154
+ {
155
+ log-check-result "$(x) : no" ;
156
+ }
157
+ }
158
+ return $(result) ;
159
+ }
160
+ else
161
+ {
162
+ return $(.$(what)-supported.$(ps)) ;
163
+ }
164
+ }
165
+
166
+ rule builds ( metatarget-reference : properties * : what ? : retry ? )
167
+ {
168
+ what ?= "$(metatarget-reference) builds" ;
169
+
170
+ # FIXME: this should not be hardcoded. Other checks might
171
+ # want to consider different set of features as relevant.
172
+ local toolset = [ property.select <toolset> : $(properties) ] ;
173
+ local toolset-version-property = "<toolset-$(toolset:G=):version>" ;
174
+ local relevant = [ property.select <target-os> <toolset> $(toolset-version-property)
175
+ <address-model> <architecture>
176
+ : $(properties) ] ;
177
+ local ps = [ property-set.create $(relevant) ] ;
178
+ local t = [ targets.current ] ;
179
+ local p = [ $(t).project ] ;
180
+
181
+ return [ builds-raw $(metatarget-reference) : $(p) : $(ps) : $(what) : $(retry) ] ;
182
+ }
183
+
184
+
185
+ # Called by Boost.Build startup code to specify name of a file
186
+ # that will receive results of configure checks. This
187
+ # should never be called by users.
188
+ rule set-log-file ( log-file )
189
+ {
190
+ path.makedirs [ path.parent $(log-file) ] ;
191
+
192
+ .log-fd = [ FILE_OPEN $(log-file) : "w" ] ;
193
+ }
194
+
195
+ # Frontend rules
196
+
197
+ class check-target-builds-worker
198
+ {
199
+ import configure ;
200
+ import property-set ;
201
+ import targets ;
202
+ import property ;
203
+
204
+ rule __init__ ( target message ? : true-properties * : false-properties * )
205
+ {
206
+ self.target = $(target) ;
207
+ self.message = $(message) ;
208
+ self.true-properties = $(true-properties) ;
209
+ self.false-properties = $(false-properties) ;
210
+ }
211
+
212
+ rule check ( properties * )
213
+ {
214
+ local choosen ;
215
+ if [ configure.builds $(self.target) : $(properties) : $(self.message) ]
216
+ {
217
+ choosen = $(self.true-properties) ;
218
+ }
219
+ else
220
+ {
221
+ choosen = $(self.false-properties) ;
222
+ }
223
+ return [ property.evaluate-conditionals-in-context $(choosen) : $(properties) ] ;
224
+ }
225
+ }
226
+
227
+
228
+ rule check-target-builds ( target message ? : true-properties * : false-properties * )
229
+ {
230
+ local instance = [ new check-target-builds-worker $(target) $(message) : $(true-properties)
231
+ : $(false-properties) ] ;
232
+ return <conditional>@$(instance).check ;
233
+ }
234
+
235
+ IMPORT $(__name__) : check-target-builds : : check-target-builds ;
236
+
237
+
mosesdecoder/jam-files/boost-build/build/feature.jam ADDED
@@ -0,0 +1,1335 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2001, 2002, 2003 Dave Abrahams
2
+ # Copyright 2002, 2006 Rene Rivera
3
+ # Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
4
+ # Distributed under the Boost Software License, Version 1.0.
5
+ # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
6
+
7
+ import assert : * ;
8
+ import "class" : * ;
9
+ import errors : lol->list ;
10
+ import indirect ;
11
+ import modules ;
12
+ import regex ;
13
+ import sequence ;
14
+ import set ;
15
+ import utility ;
16
+
17
+
18
+ local rule setup ( )
19
+ {
20
+ .all-attributes =
21
+ implicit
22
+ composite
23
+ optional
24
+ symmetric
25
+ free
26
+ incidental
27
+ path
28
+ dependency
29
+ propagated
30
+ link-incompatible
31
+ subfeature
32
+ order-sensitive
33
+ ;
34
+
35
+ .all-features = ;
36
+ .all-subfeatures = ;
37
+ .all-top-features = ; # non-subfeatures
38
+ .all-implicit-values = ;
39
+ }
40
+ setup ;
41
+
42
+
43
+ # Prepare a fresh space to test in by moving all global variable settings into
44
+ # the given temporary module and erasing them here.
45
+ #
46
+ rule prepare-test ( temp-module )
47
+ {
48
+ DELETE_MODULE $(temp-module) ;
49
+
50
+ # Transfer globals to temp-module.
51
+ for local v in [ VARNAMES feature ]
52
+ {
53
+ if [ MATCH (\\.) : $(v) ]
54
+ {
55
+ modules.poke $(temp-module) : $(v) : $($(v)) ;
56
+ $(v) = ;
57
+ }
58
+ }
59
+ setup ;
60
+ }
61
+
62
+
63
+ # Clear out all global variables and recover all variables from the given
64
+ # temporary module.
65
+ #
66
+ rule finish-test ( temp-module )
67
+ {
68
+ # Clear globals.
69
+ for local v in [ VARNAMES feature ]
70
+ {
71
+ if [ MATCH (\\.) : $(v) ]
72
+ {
73
+ $(v) = ;
74
+ }
75
+ }
76
+
77
+ for local v in [ VARNAMES $(temp-module) ]
78
+ {
79
+ $(v) = [ modules.peek $(temp-module) : $(v) ] ;
80
+ }
81
+ DELETE_MODULE $(temp-module) ;
82
+ }
83
+
84
+
85
+ # Transform features by bracketing any elements which are not already bracketed
86
+ # by "<>".
87
+ #
88
+ local rule grist ( features * )
89
+ {
90
+ local empty = "" ;
91
+ return $(empty:G=$(features)) ;
92
+ }
93
+
94
+
95
+ # Declare a new feature with the given name, values, and attributes.
96
+ #
97
+ rule feature (
98
+ name # Feature name.
99
+ : values * # Allowable values - may be extended later using feature.extend.
100
+ : attributes * # Feature attributes (e.g. implicit, free, propagated...).
101
+ )
102
+ {
103
+ name = [ grist $(name) ] ;
104
+
105
+ local error ;
106
+
107
+ # Check for any unknown attributes.
108
+ if ! ( $(attributes) in $(.all-attributes) )
109
+ {
110
+ error = unknown attributes:
111
+ [ set.difference $(attributes) : $(.all-attributes) ] ;
112
+ }
113
+ else if $(name) in $(.all-features)
114
+ {
115
+ error = feature already defined: ;
116
+ }
117
+ else if implicit in $(attributes) && free in $(attributes)
118
+ {
119
+ error = free features cannot also be implicit ;
120
+ }
121
+ else if free in $(attributes) && propagated in $(attributes)
122
+ {
123
+ error = free features cannot be propagated ;
124
+ }
125
+ else
126
+ {
127
+ local m = [ MATCH (.*=.*) : $(values) ] ;
128
+ if $(m[1])
129
+ {
130
+ error = "feature value may not contain '='" ;
131
+ }
132
+ }
133
+
134
+ if $(error)
135
+ {
136
+ errors.error $(error)
137
+ : "in" feature declaration:
138
+ : feature [ lol->list $(1) : $(2) : $(3) ] ;
139
+ }
140
+
141
+ $(name).values ?= ;
142
+ $(name).attributes = $(attributes) ;
143
+ $(name).subfeatures ?= ;
144
+ $(attributes).features += $(name) ;
145
+
146
+ .all-features += $(name) ;
147
+ if subfeature in $(attributes)
148
+ {
149
+ .all-subfeatures += $(name) ;
150
+ }
151
+ else
152
+ {
153
+ .all-top-features += $(name) ;
154
+ }
155
+ extend $(name) : $(values) ;
156
+ }
157
+
158
+
159
+ # Sets the default value of the given feature, overriding any previous default.
160
+ #
161
+ rule set-default ( feature : value )
162
+ {
163
+ local f = [ grist $(feature) ] ;
164
+ local a = $($(f).attributes) ;
165
+ local bad-attribute = ;
166
+ if free in $(a)
167
+ {
168
+ bad-attribute = free ;
169
+ }
170
+ else if optional in $(a)
171
+ {
172
+ bad-attribute = optional ;
173
+ }
174
+ if $(bad-attribute)
175
+ {
176
+ errors.error "$(bad-attribute) property $(f) cannot have a default." ;
177
+ }
178
+ if ! $(value) in $($(f).values)
179
+ {
180
+ errors.error "The specified default value, '$(value)' is invalid"
181
+ : "allowed values are: " $($(f).values) ;
182
+ }
183
+ $(f).default = $(value) ;
184
+ }
185
+
186
+
187
+ # Returns the default property values for the given features.
188
+ #
189
+ rule defaults ( features * )
190
+ {
191
+ local result ;
192
+ for local f in $(features)
193
+ {
194
+ local gf = $(:E=:G=$(f)) ;
195
+ local a = $($(gf).attributes) ;
196
+ if ( free in $(a) ) || ( optional in $(a) )
197
+ {
198
+ }
199
+ else
200
+ {
201
+ result += $(gf)$($(gf).default) ;
202
+ }
203
+ }
204
+ return $(result) ;
205
+ }
206
+
207
+
208
+ # Returns true iff all 'names' elements are valid features.
209
+ #
210
+ rule valid ( names + )
211
+ {
212
+ if $(names) in $(.all-features)
213
+ {
214
+ return true ;
215
+ }
216
+ }
217
+
218
+
219
+ # Returns the attibutes of the given feature.
220
+ #
221
+ rule attributes ( feature )
222
+ {
223
+ return $($(:E=:G=$(feature)).attributes) ;
224
+ }
225
+
226
+
227
+ # Returns the values of the given feature.
228
+ #
229
+ rule values ( feature )
230
+ {
231
+ return $($(:E=:G=$(feature)).values) ;
232
+ }
233
+
234
+
235
+ # Returns true iff 'value-string' is a value-string of an implicit feature.
236
+ #
237
+ rule is-implicit-value ( value-string )
238
+ {
239
+ local v = [ regex.split $(value-string) - ] ;
240
+ local failed ;
241
+ if ! $(v[1]) in $(.all-implicit-values)
242
+ {
243
+ failed = true ;
244
+ }
245
+ else
246
+ {
247
+ local feature = $($(v[1]).implicit-feature) ;
248
+ for local subvalue in $(v[2-])
249
+ {
250
+ if ! [ find-implied-subfeature $(feature) $(subvalue) : $(v[1]) ]
251
+ {
252
+ failed = true ;
253
+ }
254
+ }
255
+ }
256
+
257
+ if ! $(failed)
258
+ {
259
+ return true ;
260
+ }
261
+ }
262
+
263
+
264
+ # Returns the implicit feature associated with the given implicit value.
265
+ #
266
+ rule implied-feature ( implicit-value )
267
+ {
268
+ local components = [ regex.split $(implicit-value) "-" ] ;
269
+
270
+ local feature = $($(components[1]).implicit-feature) ;
271
+ if ! $(feature)
272
+ {
273
+ errors.error \"$(implicit-value)\" is not a value of an implicit feature ;
274
+ feature = "" ; # Keep testing happy; it expects a result.
275
+ }
276
+ return $(feature) ;
277
+ }
278
+
279
+
280
+ local rule find-implied-subfeature ( feature subvalue : value-string ? )
281
+ {
282
+ # Feature should be of the form <feature-name>.
283
+ if $(feature) != $(feature:G)
284
+ {
285
+ errors.error invalid feature $(feature) ;
286
+ }
287
+
288
+ return $($(feature)$(value-string:E="")<>$(subvalue).subfeature) ;
289
+ }
290
+
291
+
292
+ # Given a feature and a value of one of its subfeatures, find the name of the
293
+ # subfeature. If value-string is supplied, looks for implied subfeatures that
294
+ # are specific to that value of feature
295
+ #
296
+ rule implied-subfeature (
297
+ feature # The main feature name.
298
+ subvalue # The value of one of its subfeatures.
299
+ : value-string ? # The value of the main feature.
300
+ )
301
+ {
302
+ local subfeature = [ find-implied-subfeature $(feature) $(subvalue)
303
+ : $(value-string) ] ;
304
+ if ! $(subfeature)
305
+ {
306
+ value-string ?= "" ;
307
+ errors.error \"$(subvalue)\" is not a known subfeature value of
308
+ $(feature)$(value-string) ;
309
+ }
310
+ return $(subfeature) ;
311
+ }
312
+
313
+
314
+ # Generate an error if the feature is unknown.
315
+ #
316
+ local rule validate-feature ( feature )
317
+ {
318
+ if ! $(feature) in $(.all-features)
319
+ {
320
+ errors.error unknown feature \"$(feature)\" ;
321
+ }
322
+ }
323
+
324
+
325
+ # Given a feature and its value or just a value corresponding to an implicit
326
+ # feature, returns a property set consisting of all component subfeatures and
327
+ # their values. For example all the following calls:
328
+ #
329
+ # expand-subfeatures-aux <toolset>gcc-2.95.2-linux-x86
330
+ # expand-subfeatures-aux gcc-2.95.2-linux-x86
331
+ #
332
+ # return:
333
+ #
334
+ # <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86
335
+ #
336
+ local rule expand-subfeatures-aux (
337
+ feature ? # Feature name or empty if value corresponds to an
338
+ # implicit property.
339
+ : value # Feature value.
340
+ : dont-validate ? # If set, no value string validation will be done.
341
+ )
342
+ {
343
+ if $(feature)
344
+ {
345
+ feature = $(feature) ;
346
+ }
347
+
348
+ if ! $(feature)
349
+ {
350
+ feature = [ implied-feature $(value) ] ;
351
+ }
352
+ else
353
+ {
354
+ validate-feature $(feature) ;
355
+ }
356
+ if ! $(dont-validate)
357
+ {
358
+ validate-value-string $(feature) $(value) ;
359
+ }
360
+
361
+ local components = [ regex.split $(value) "-" ] ;
362
+
363
+ # Get the top-level feature's value.
364
+ local value = $(components[1]:G=) ;
365
+
366
+ local result = $(components[1]:G=$(feature)) ;
367
+
368
+ local subvalues = $(components[2-]) ;
369
+ while $(subvalues)
370
+ {
371
+ local subvalue = $(subvalues[1]) ; # Pop the head off of subvalues.
372
+ subvalues = $(subvalues[2-]) ;
373
+
374
+ local subfeature = [ find-implied-subfeature $(feature) $(subvalue) :
375
+ $(value) ] ;
376
+
377
+ # If no subfeature was found reconstitute the value string and use that.
378
+ if ! $(subfeature)
379
+ {
380
+ result = $(components:J=-) ;
381
+ result = $(result:G=$(feature)) ;
382
+ subvalues = ; # Stop looping.
383
+ }
384
+ else
385
+ {
386
+ local f = [ MATCH ^<(.*)>$ : $(feature) ] ;
387
+ result += $(subvalue:G=$(f)-$(subfeature)) ;
388
+ }
389
+ }
390
+
391
+ return $(result) ;
392
+ }
393
+
394
+
395
+ # Make all elements of properties corresponding to implicit features explicit,
396
+ # and express all subfeature values as separate properties in their own right.
397
+ # For example, all of the following properties
398
+ #
399
+ # gcc-2.95.2-linux-x86
400
+ # <toolset>gcc-2.95.2-linux-x86
401
+ #
402
+ # might expand to
403
+ #
404
+ # <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86
405
+ #
406
+ rule expand-subfeatures (
407
+ properties * # Property set with elements of the form
408
+ # <feature>value-string or just value-string in the case
409
+ # of implicit features.
410
+ : dont-validate ?
411
+ )
412
+ {
413
+ local result ;
414
+ for local p in $(properties)
415
+ {
416
+ # Don't expand subfeatures in subfeatures
417
+ if ! [ MATCH "(:)" : $(p:G) ]
418
+ {
419
+ result += [ expand-subfeatures-aux $(p:G) : $(p:G=) : $(dont-validate) ] ;
420
+ }
421
+ else
422
+ {
423
+ result += $(p) ;
424
+ }
425
+ }
426
+ return $(result) ;
427
+ }
428
+
429
+
430
+ # Helper for extend, below. Handles the feature case.
431
+ #
432
+ local rule extend-feature ( feature : values * )
433
+ {
434
+ feature = [ grist $(feature) ] ;
435
+ validate-feature $(feature) ;
436
+ if implicit in $($(feature).attributes)
437
+ {
438
+ for local v in $(values)
439
+ {
440
+ if $($(v).implicit-feature)
441
+ {
442
+ errors.error $(v) is already associated with the \"$($(v).implicit-feature)\" feature ;
443
+ }
444
+ $(v).implicit-feature = $(feature) ;
445
+ }
446
+
447
+ .all-implicit-values += $(values) ;
448
+ }
449
+ if ! $($(feature).values)
450
+ {
451
+ # This is the first value specified for this feature so make it be the
452
+ # default.
453
+ $(feature).default = $(values[1]) ;
454
+ }
455
+ $(feature).values += $(values) ;
456
+ }
457
+
458
+
459
+ # Checks that value-string is a valid value-string for the given feature.
460
+ #
461
+ rule validate-value-string ( feature value-string )
462
+ {
463
+ if ! (
464
+ free in $($(feature).attributes)
465
+ || ( $(value-string) in $(feature).values )
466
+ )
467
+ {
468
+ local values = $(value-string) ;
469
+
470
+ if $($(feature).subfeatures)
471
+ {
472
+ if ! ( $(value-string) in $($(feature).values) )
473
+ && ! ( $(value-string) in $($(feature).subfeatures) )
474
+ {
475
+ values = [ regex.split $(value-string) - ] ;
476
+ }
477
+ }
478
+
479
+ if ! ( $(values[1]) in $($(feature).values) ) &&
480
+
481
+ # An empty value is allowed for optional features.
482
+ ( $(values[1]) || ! ( optional in $($(feature).attributes) ) )
483
+ {
484
+ errors.error \"$(values[1])\" is not a known value of feature $(feature)
485
+ : legal values: \"$($(feature).values)\" ;
486
+ }
487
+
488
+ for local v in $(values[2-])
489
+ {
490
+ # This will validate any subfeature values in value-string.
491
+ implied-subfeature $(feature) $(v) : $(values[1]) ;
492
+ }
493
+ }
494
+ }
495
+
496
+
497
+ # A helper that computes:
498
+ # * name(s) of module-local variable(s) used to record the correspondence
499
+ # between subvalue(s) and a subfeature
500
+ # * value of that variable when such a subfeature/subvalue has been defined and
501
+ # returns a list consisting of the latter followed by the former.
502
+ #
503
+ local rule subvalue-var (
504
+ feature # Main feature name.
505
+ value-string ? # If supplied, specifies a specific value of the main
506
+ # feature for which the subfeature values are valid.
507
+ : subfeature # Subfeature name.
508
+ : subvalues * # Subfeature values.
509
+ )
510
+ {
511
+ feature = [ grist $(feature) ] ;
512
+ validate-feature $(feature) ;
513
+ if $(value-string)
514
+ {
515
+ validate-value-string $(feature) $(value-string) ;
516
+ }
517
+
518
+ local subfeature-name = [ get-subfeature-name $(subfeature) $(value-string) ] ;
519
+
520
+ return $(subfeature-name)
521
+ $(feature)$(value-string:E="")<>$(subvalues).subfeature ;
522
+ }
523
+
524
+
525
+ # Extends the given subfeature with the subvalues. If the optional value-string
526
+ # is provided, the subvalues are only valid for the given value of the feature.
527
+ # Thus, you could say that <target-platform>mingw is specific to
528
+ # <toolset>gcc-2.95.2 as follows:
529
+ #
530
+ # extend-subfeature toolset gcc-2.95.2 : target-platform : mingw ;
531
+ #
532
+ rule extend-subfeature (
533
+ feature # The feature whose subfeature is being extended.
534
+
535
+ value-string ? # If supplied, specifies a specific value of the main
536
+ # feature for which the new subfeature values are valid.
537
+
538
+ : subfeature # Subfeature name.
539
+ : subvalues * # Additional subfeature values.
540
+ )
541
+ {
542
+ local subfeature-vars = [ subvalue-var $(feature) $(value-string)
543
+ : $(subfeature) : $(subvalues) ] ;
544
+
545
+ local f = [ utility.ungrist [ grist $(feature) ] ] ;
546
+ extend $(f)-$(subfeature-vars[1]) : $(subvalues) ;
547
+
548
+ # Provide a way to get from the given feature or property and subfeature
549
+ # value to the subfeature name.
550
+ $(subfeature-vars[2-]) = $(subfeature-vars[1]) ;
551
+ }
552
+
553
+
554
+ # Returns true iff the subvalues are valid for the feature. When the optional
555
+ # value-string is provided, returns true iff the subvalues are valid for the
556
+ # given value of the feature.
557
+ #
558
+ rule is-subvalue ( feature : value-string ? : subfeature : subvalue )
559
+ {
560
+ local subfeature-vars = [ subvalue-var $(feature) $(value-string)
561
+ : $(subfeature) : $(subvalue) ] ;
562
+
563
+ if $($(subfeature-vars[2])) = $(subfeature-vars[1])
564
+ {
565
+ return true ;
566
+ }
567
+ }
568
+
569
+
570
+ # Can be called three ways:
571
+ #
572
+ # 1. extend feature : values *
573
+ # 2. extend <feature> subfeature : values *
574
+ # 3. extend <feature>value-string subfeature : values *
575
+ #
576
+ # * Form 1 adds the given values to the given feature.
577
+ # * Forms 2 and 3 add subfeature values to the given feature.
578
+ # * Form 3 adds the subfeature values as specific to the given property
579
+ # value-string.
580
+ #
581
+ rule extend ( feature-or-property subfeature ? : values * )
582
+ {
583
+ local feature ; # If a property was specified this is its feature.
584
+ local value-string ; # E.g., the gcc-2.95-2 part of <toolset>gcc-2.95.2.
585
+
586
+ # If a property was specified.
587
+ if $(feature-or-property:G) && $(feature-or-property:G=)
588
+ {
589
+ # Extract the feature and value-string, if any.
590
+ feature = $(feature-or-property:G) ;
591
+ value-string = $(feature-or-property:G=) ;
592
+ }
593
+ else
594
+ {
595
+ feature = [ grist $(feature-or-property) ] ;
596
+ }
597
+
598
+ # Dispatch to the appropriate handler.
599
+ if $(subfeature)
600
+ {
601
+ extend-subfeature $(feature) $(value-string) : $(subfeature)
602
+ : $(values) ;
603
+ }
604
+ else
605
+ {
606
+ # If no subfeature was specified, we do not expect to see a
607
+ # value-string.
608
+ if $(value-string)
609
+ {
610
+ errors.error can only specify a property as the first argument when
611
+ extending a subfeature
612
+ : usage:
613
+ : " extend" feature ":" values...
614
+ : " | extend" <feature>value-string subfeature ":" values...
615
+ ;
616
+ }
617
+
618
+ extend-feature $(feature) : $(values) ;
619
+ }
620
+ }
621
+
622
+
623
+ local rule get-subfeature-name ( subfeature value-string ? )
624
+ {
625
+ local prefix = $(value-string): ;
626
+ return $(prefix:E="")$(subfeature) ;
627
+ }
628
+
629
+
630
+ # Declares a subfeature.
631
+ #
632
+ rule subfeature (
633
+ feature # Root feature that is not a subfeature.
634
+ value-string ? # A value-string specifying which feature or subfeature
635
+ # values this subfeature is specific to, if any.
636
+ : subfeature # The name of the subfeature being declared.
637
+ : subvalues * # The allowed values of this subfeature.
638
+ : attributes * # The attributes of the subfeature.
639
+ )
640
+ {
641
+ feature = [ grist $(feature) ] ;
642
+ validate-feature $(feature) ;
643
+
644
+ # Add grist to the subfeature name if a value-string was supplied.
645
+ local subfeature-name = [ get-subfeature-name $(subfeature) $(value-string) ] ;
646
+
647
+ if $(subfeature-name) in $($(feature).subfeatures)
648
+ {
649
+ errors.error \"$(subfeature)\" already declared as a subfeature of \"$(feature)\"
650
+ "specific to "$(value-string) ;
651
+ }
652
+ $(feature).subfeatures += $(subfeature-name) ;
653
+
654
+ # First declare the subfeature as a feature in its own right.
655
+ local f = [ utility.ungrist $(feature) ] ;
656
+ feature $(f)-$(subfeature-name) : $(subvalues) : $(attributes) subfeature ;
657
+
658
+ # Now make sure the subfeature values are known.
659
+ extend-subfeature $(feature) $(value-string) : $(subfeature) : $(subvalues) ;
660
+ }
661
+
662
+
663
+ # Set components of the given composite property.
664
+ #
665
+ rule compose ( composite-property : component-properties * )
666
+ {
667
+ local feature = $(composite-property:G) ;
668
+ if ! ( composite in [ attributes $(feature) ] )
669
+ {
670
+ errors.error "$(feature)" is not a composite feature ;
671
+ }
672
+
673
+ $(composite-property).components ?= ;
674
+ if $($(composite-property).components)
675
+ {
676
+ errors.error components of "$(composite-property)" already set:
677
+ $($(composite-property).components) ;
678
+ }
679
+
680
+ if $(composite-property) in $(component-properties)
681
+ {
682
+ errors.error composite property "$(composite-property)" cannot have itself as a component ;
683
+ }
684
+ $(composite-property).components = $(component-properties) ;
685
+ }
686
+
687
+
688
+ local rule expand-composite ( property )
689
+ {
690
+ return $(property)
691
+ [ sequence.transform expand-composite : $($(property).components) ] ;
692
+ }
693
+
694
+
695
+ # Return all values of the given feature specified by the given property set.
696
+ #
697
+ rule get-values ( feature : properties * )
698
+ {
699
+ local result ;
700
+
701
+ feature = $(:E=:G=$(feature)) ; # Add <> if necessary.
702
+ for local p in $(properties)
703
+ {
704
+ if $(p:G) = $(feature)
705
+ {
706
+ # Use MATCH instead of :G= to get the value, in order to preserve
707
+ # the value intact instead of having bjam treat it as a decomposable
708
+ # path.
709
+ result += [ MATCH ">(.*)" : $(p) ] ;
710
+ }
711
+ }
712
+ return $(result) ;
713
+ }
714
+
715
+
716
+ rule free-features ( )
717
+ {
718
+ return $(free.features) ;
719
+ }
720
+
721
+
722
+ # Expand all composite properties in the set so that all components are
723
+ # explicitly expressed.
724
+ #
725
+ rule expand-composites ( properties * )
726
+ {
727
+ local explicit-features = $(properties:G) ;
728
+ local result ;
729
+
730
+ # Now expand composite features.
731
+ for local p in $(properties)
732
+ {
733
+ local expanded = [ expand-composite $(p) ] ;
734
+
735
+ for local x in $(expanded)
736
+ {
737
+ if ! $(x) in $(result)
738
+ {
739
+ local f = $(x:G) ;
740
+
741
+ if $(f) in $(free.features)
742
+ {
743
+ result += $(x) ;
744
+ }
745
+ else if ! $(x) in $(properties) # x is the result of expansion
746
+ {
747
+ if ! $(f) in $(explicit-features) # not explicitly-specified
748
+ {
749
+ if $(f) in $(result:G)
750
+ {
751
+ errors.error expansions of composite features result
752
+ in conflicting values for $(f)
753
+ : values: [ get-values $(f) : $(result) ] $(x:G=)
754
+ : one contributing composite property was $(p) ;
755
+ }
756
+ else
757
+ {
758
+ result += $(x) ;
759
+ }
760
+ }
761
+ }
762
+ else if $(f) in $(result:G)
763
+ {
764
+ errors.error explicitly-specified values of non-free feature
765
+ $(f) conflict :
766
+ "existing values:" [ get-values $(f) : $(properties) ] :
767
+ "value from expanding " $(p) ":" $(x:G=) ;
768
+ }
769
+ else
770
+ {
771
+ result += $(x) ;
772
+ }
773
+ }
774
+ }
775
+ }
776
+ return $(result) ;
777
+ }
778
+
779
+
780
+ # Return true iff f is an ordinary subfeature of the parent-property's feature,
781
+ # or if f is a subfeature of the parent-property's feature specific to the
782
+ # parent-property's value.
783
+ #
784
+ local rule is-subfeature-of ( parent-property f )
785
+ {
786
+ if subfeature in $($(f).attributes)
787
+ {
788
+ local specific-subfeature = [ MATCH <(.*):(.*)> : $(f) ] ;
789
+ if $(specific-subfeature)
790
+ {
791
+ # The feature has the form <topfeature-topvalue:subfeature>, e.g.
792
+ # <toolset-msvc:version>.
793
+ local feature-value = [ split-top-feature $(specific-subfeature[1])
794
+ ] ;
795
+ if <$(feature-value[1])>$(feature-value[2]) = $(parent-property)
796
+ {
797
+ return true ;
798
+ }
799
+ }
800
+ else
801
+ {
802
+ # The feature has the form <topfeature-subfeature>, e.g.
803
+ # <toolset-version>
804
+ local top-sub = [ split-top-feature [ utility.ungrist $(f) ] ] ;
805
+ if $(top-sub[2]) && <$(top-sub[1])> = $(parent-property:G)
806
+ {
807
+ return true ;
808
+ }
809
+ }
810
+ }
811
+ }
812
+
813
+
814
+ # As for is-subfeature-of but for subproperties.
815
+ #
816
+ local rule is-subproperty-of ( parent-property p )
817
+ {
818
+ return [ is-subfeature-of $(parent-property) $(p:G) ] ;
819
+ }
820
+
821
+
822
+ # Given a property, return the subset of features consisting of all ordinary
823
+ # subfeatures of the property's feature, and all specific subfeatures of the
824
+ # property's feature which are conditional on the property's value.
825
+ #
826
+ local rule select-subfeatures ( parent-property : features * )
827
+ {
828
+ return [ sequence.filter is-subfeature-of $(parent-property) : $(features) ] ;
829
+ }
830
+
831
+
832
+ # As for select-subfeatures but for subproperties.
833
+ #
834
+ local rule select-subproperties ( parent-property : properties * )
835
+ {
836
+ return [ sequence.filter is-subproperty-of $(parent-property) : $(properties) ] ;
837
+ }
838
+
839
+
840
+ # Given a property set which may consist of composite and implicit properties
841
+ # and combined subfeature values, returns an expanded, normalized property set
842
+ # with all implicit features expressed explicitly, all subfeature values
843
+ # individually expressed, and all components of composite properties expanded.
844
+ # Non-free features directly expressed in the input properties cause any values
845
+ # of those features due to composite feature expansion to be dropped. If two
846
+ # values of a given non-free feature are directly expressed in the input, an
847
+ # error is issued.
848
+ #
849
+ rule expand ( properties * )
850
+ {
851
+ local expanded = [ expand-subfeatures $(properties) ] ;
852
+ return [ expand-composites $(expanded) ] ;
853
+ }
854
+
855
+
856
+ # Helper rule for minimize. Returns true iff property's feature is present in
857
+ # the contents of the variable named by feature-set-var.
858
+ #
859
+ local rule in-features ( feature-set-var property )
860
+ {
861
+ if $(property:G) in $($(feature-set-var))
862
+ {
863
+ return true ;
864
+ }
865
+ }
866
+
867
+
868
+ # Helper rule for minimize. Returns the list with the same properties, but with
869
+ # all subfeatures moved to the end of the list.
870
+ #
871
+ local rule move-subfeatures-to-the-end ( properties * )
872
+ {
873
+ local x1 ;
874
+ local x2 ;
875
+ for local p in $(properties)
876
+ {
877
+ if subfeature in $($(p:G).attributes)
878
+ {
879
+ x2 += $(p) ;
880
+ }
881
+ else
882
+ {
883
+ x1 += $(p) ;
884
+ }
885
+ }
886
+ return $(x1) $(x2) ;
887
+ }
888
+
889
+
890
+ # Given an expanded property set, eliminate all redundancy: properties that are
891
+ # elements of other (composite) properties in the set will be eliminated.
892
+ # Non-symmetric properties equal to default values will be eliminated unless
893
+ # they override a value from some composite property. Implicit properties will
894
+ # be expressed without feature grist, and sub-property values will be expressed
895
+ # as elements joined to the corresponding main property.
896
+ #
897
+ rule minimize ( properties * )
898
+ {
899
+ # Precondition checking
900
+ local implicits = [ set.intersection $(p:G=) : $(p:G) ] ;
901
+ if $(implicits)
902
+ {
903
+ errors.error minimize requires an expanded property set, but
904
+ \"$(implicits[1])\" appears to be the value of an un-expanded
905
+ implicit feature ;
906
+ }
907
+
908
+ # Remove properties implied by composite features.
909
+ local components = $($(properties).components) ;
910
+ local x = [ set.difference $(properties) : $(components) ] ;
911
+
912
+ # Handle subfeatures and implicit features.
913
+ x = [ move-subfeatures-to-the-end $(x) ] ;
914
+ local result ;
915
+ while $(x)
916
+ {
917
+ local p fullp = $(x[1]) ;
918
+ local f = $(p:G) ;
919
+ local v = $(p:G=) ;
920
+
921
+ # Eliminate features in implicit properties.
922
+ if implicit in [ attributes $(f) ]
923
+ {
924
+ p = $(v) ;
925
+ }
926
+
927
+ # Locate all subproperties of $(x[1]) in the property set.
928
+ local subproperties = [ select-subproperties $(fullp) : $(x) ] ;
929
+ if $(subproperties)
930
+ {
931
+ # Reconstitute the joined property name.
932
+ local sorted = [ sequence.insertion-sort $(subproperties) ] ;
933
+ result += $(p)-$(sorted:G="":J=-) ;
934
+
935
+ x = [ set.difference $(x[2-]) : $(subproperties) ] ;
936
+ }
937
+ else
938
+ {
939
+ # Eliminate properties whose value is equal to feature's default,
940
+ # which are not symmetric and which do not contradict values implied
941
+ # by composite properties.
942
+
943
+ # Since all component properties of composites in the set have been
944
+ # eliminated, any remaining property whose feature is the same as a
945
+ # component of a composite in the set must have a non-redundant
946
+ # value.
947
+ if $(fullp) != [ defaults $(f) ]
948
+ || symmetric in [ attributes $(f) ]
949
+ || $(fullp:G) in $(components:G)
950
+ {
951
+ result += $(p) ;
952
+ }
953
+
954
+ x = $(x[2-]) ;
955
+ }
956
+ }
957
+ return $(result) ;
958
+ }
959
+
960
+
961
+ # Combine all subproperties into their parent properties
962
+ #
963
+ # Requires: for every subproperty, there is a parent property. All features are
964
+ # explicitly expressed.
965
+ #
966
+ # This rule probably should not be needed, but build-request.expand-no-defaults
967
+ # is being abused for unintended purposes and it needs help.
968
+ #
969
+ rule compress-subproperties ( properties * )
970
+ {
971
+ local all-subs ;
972
+ local matched-subs ;
973
+ local result ;
974
+
975
+ for local p in $(properties)
976
+ {
977
+ if ! $(p:G)
978
+ {
979
+ # Expecting fully-gristed properties.
980
+ assert.variable-not-empty p:G ;
981
+ }
982
+
983
+ if ! subfeature in $($(p:G).attributes)
984
+ {
985
+ local subs = [ sequence.insertion-sort
986
+ [ sequence.filter is-subproperty-of $(p) : $(properties) ] ] ;
987
+
988
+ matched-subs += $(subs) ;
989
+
990
+ local subvalues = -$(subs:G=:J=-) ;
991
+ subvalues ?= "" ;
992
+ result += $(p)$(subvalues) ;
993
+ }
994
+ else
995
+ {
996
+ all-subs += $(p) ;
997
+ }
998
+ }
999
+ assert.result true : set.equal $(all-subs) : $(matched-subs) ;
1000
+ return $(result) ;
1001
+ }
1002
+
1003
+
1004
+ # Given an ungristed string, finds the longest prefix which is a top-level
1005
+ # feature name followed by a dash, and return a pair consisting of the parts
1006
+ # before and after that dash. More interesting than a simple split because
1007
+ # feature names may contain dashes.
1008
+ #
1009
+ local rule split-top-feature ( feature-plus )
1010
+ {
1011
+ local e = [ regex.split $(feature-plus) - ] ;
1012
+ local f = $(e[1]) ;
1013
+ local v ;
1014
+ while $(e)
1015
+ {
1016
+ if <$(f)> in $(.all-top-features)
1017
+ {
1018
+ v = $(f) $(e[2-]:J=-) ;
1019
+ }
1020
+ e = $(e[2-]) ;
1021
+ f = $(f)-$(e[1]) ;
1022
+ }
1023
+ return $(v) ;
1024
+ }
1025
+
1026
+
1027
+ # Given a set of properties, add default values for features not represented in
1028
+ # the set.
1029
+ #
1030
+ # Note: if there's an ordinary feature F1 and a composite feature F2 which
1031
+ # includes some value for F1 and both feature have default values then the
1032
+ # default value of F1 will be added (as opposed to the value in F2). This might
1033
+ # not be the right idea, e.g. consider:
1034
+ #
1035
+ # feature variant : debug ... ;
1036
+ # <variant>debug : .... <runtime-debugging>on
1037
+ # feature <runtime-debugging> : off on ;
1038
+ #
1039
+ # Here, when adding default for an empty property set, we'll get
1040
+ #
1041
+ # <variant>debug <runtime_debugging>off
1042
+ #
1043
+ # and that's kind of strange.
1044
+ #
1045
+ rule add-defaults ( properties * )
1046
+ {
1047
+ for local v in $(properties:G=)
1048
+ {
1049
+ if $(v) in $(properties)
1050
+ {
1051
+ errors.error add-defaults requires explicitly specified features,
1052
+ but \"$(v)\" appears to be the value of an un-expanded implicit
1053
+ feature ;
1054
+ }
1055
+ }
1056
+ # We don't add default for elements with ":" inside. This catches:
1057
+ # 1. Conditional properties --- we don't want <variant>debug:<define>DEBUG
1058
+ # to be takes as specified value for <variant>
1059
+ # 2. Free properties with ":" in values. We don't care, since free
1060
+ # properties don't have defaults.
1061
+ local xproperties = [ MATCH "^([^:]+)$" : $(properties) ] ;
1062
+ local missing-top = [ set.difference $(.all-top-features) : $(xproperties:G) ] ;
1063
+ local more = [ defaults $(missing-top) ] ;
1064
+ properties += $(more) ;
1065
+ xproperties += $(more) ;
1066
+
1067
+ # Add defaults for subfeatures of features which are present.
1068
+ for local p in $(xproperties)
1069
+ {
1070
+ local s = $($(p:G).subfeatures) ;
1071
+ local f = [ utility.ungrist $(p:G) ] ;
1072
+ local missing-subs = [ set.difference <$(f)-$(s)> : $(properties:G) ] ;
1073
+ properties += [ defaults [ select-subfeatures $(p) : $(missing-subs) ] ] ;
1074
+ }
1075
+
1076
+ return $(properties) ;
1077
+ }
1078
+
1079
+
1080
+ # Given a property-set of the form
1081
+ # v1/v2/...vN-1/<fN>vN/<fN+1>vN+1/...<fM>vM
1082
+ #
1083
+ # Returns
1084
+ # v1 v2 ... vN-1 <fN>vN <fN+1>vN+1 ... <fM>vM
1085
+ #
1086
+ # Note that vN...vM may contain slashes. This needs to be resilient to the
1087
+ # substitution of backslashes for slashes, since Jam, unbidden, sometimes swaps
1088
+ # slash direction on NT.
1089
+ #
1090
+ rule split ( property-set )
1091
+ {
1092
+ local pieces = [ regex.split $(property-set) [\\/] ] ;
1093
+ local result ;
1094
+
1095
+ for local x in $(pieces)
1096
+ {
1097
+ if ( ! $(x:G) ) && $(result[-1]:G)
1098
+ {
1099
+ result = $(result[1--2]) $(result[-1])/$(x) ;
1100
+ }
1101
+ else
1102
+ {
1103
+ result += $(x) ;
1104
+ }
1105
+ }
1106
+
1107
+ return $(result) ;
1108
+ }
1109
+
1110
+
1111
+ # Tests of module feature.
1112
+ #
1113
+ rule __test__ ( )
1114
+ {
1115
+ # Use a fresh copy of the feature module.
1116
+ prepare-test feature-test-temp ;
1117
+
1118
+ import assert ;
1119
+ import errors : try catch ;
1120
+
1121
+ # These are local rules and so must be explicitly reimported into the
1122
+ # testing module.
1123
+ import feature : extend-feature validate-feature select-subfeatures ;
1124
+
1125
+ feature toolset : gcc : implicit ;
1126
+ feature define : : free ;
1127
+ feature runtime-link : dynamic static : symmetric ;
1128
+ feature optimization : on off ;
1129
+ feature variant : debug release profile : implicit composite symmetric ;
1130
+ feature stdlib : native stlport ;
1131
+ feature magic : : free ;
1132
+
1133
+ compose <variant>debug : <define>_DEBUG <optimization>off ;
1134
+ compose <variant>release : <define>NDEBUG <optimization>on ;
1135
+
1136
+ assert.result dynamic static : values <runtime-link> ;
1137
+ assert.result dynamic static : values runtime-link ;
1138
+
1139
+ try ;
1140
+ {
1141
+ compose <variant>profile : <variant>profile ;
1142
+ }
1143
+ catch composite property <variant>profile cannot have itself as a component ;
1144
+
1145
+ extend-feature toolset : msvc metrowerks ;
1146
+ subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4 3.0 3.0.1 3.0.2 ;
1147
+
1148
+ assert.true is-subvalue toolset : gcc : version : 2.95.3 ;
1149
+ assert.false is-subvalue toolset : gcc : version : 1.1 ;
1150
+
1151
+ assert.false is-subvalue toolset : msvc : version : 2.95.3 ;
1152
+ assert.false is-subvalue toolset : : version : yabba ;
1153
+
1154
+ feature yabba ;
1155
+ subfeature yabba : version : dabba ;
1156
+ assert.true is-subvalue yabba : : version : dabba ;
1157
+
1158
+ subfeature toolset gcc : platform : linux cygwin : optional ;
1159
+
1160
+ assert.result <toolset-gcc:version>
1161
+ : select-subfeatures <toolset>gcc
1162
+ : <toolset-gcc:version>
1163
+ <toolset-msvc:version>
1164
+ <toolset-version>
1165
+ <stdlib> ;
1166
+
1167
+ subfeature stdlib : version : 3 4 : optional ;
1168
+
1169
+ assert.result <stdlib-version>
1170
+ : select-subfeatures <stdlib>native
1171
+ : <toolset-gcc:version>
1172
+ <toolset-msvc:version>
1173
+ <toolset-version>
1174
+ <stdlib-version> ;
1175
+
1176
+ assert.result <toolset>gcc <toolset-gcc:version>3.0.1
1177
+ : expand-subfeatures <toolset>gcc-3.0.1 ;
1178
+
1179
+ assert.result <toolset>gcc <toolset-gcc:version>3.0.1 <toolset-gcc:platform>linux
1180
+ : expand-subfeatures <toolset>gcc-3.0.1-linux ;
1181
+
1182
+ assert.result <toolset>gcc <toolset-gcc:version>3.0.1
1183
+ : expand <toolset>gcc <toolset-gcc:version>3.0.1 ;
1184
+
1185
+ assert.result <define>foo=x-y
1186
+ : expand-subfeatures <define>foo=x-y ;
1187
+
1188
+ assert.result <toolset>gcc <toolset-gcc:version>3.0.1
1189
+ : expand-subfeatures gcc-3.0.1 ;
1190
+
1191
+ assert.result a c e
1192
+ : get-values <x> : <x>a <y>b <x>c <y>d <x>e ;
1193
+
1194
+ assert.result <toolset>gcc <toolset-gcc:version>3.0.1
1195
+ <variant>debug <define>_DEBUG <optimization>on
1196
+ : expand gcc-3.0.1 debug <optimization>on ;
1197
+
1198
+ assert.result <variant>debug <define>_DEBUG <optimization>on
1199
+ : expand debug <optimization>on ;
1200
+
1201
+ assert.result <optimization>on <variant>debug <define>_DEBUG
1202
+ : expand <optimization>on debug ;
1203
+
1204
+ assert.result <runtime-link>dynamic <optimization>on
1205
+ : defaults <runtime-link> <define> <optimization> ;
1206
+
1207
+ # Make sure defaults is resilient to missing grist.
1208
+ assert.result <runtime-link>dynamic <optimization>on
1209
+ : defaults runtime-link define optimization ;
1210
+
1211
+ feature dummy : dummy1 dummy2 ;
1212
+ subfeature dummy : subdummy : x y z : optional ;
1213
+
1214
+ feature fu : fu1 fu2 : optional ;
1215
+ subfeature fu : subfu : x y z : optional ;
1216
+ subfeature fu : subfu2 : q r s ;
1217
+
1218
+ assert.result optional : attributes <fu> ;
1219
+ assert.result optional : attributes fu ;
1220
+
1221
+ assert.result <runtime-link>static <define>foobar <optimization>on
1222
+ <toolset>gcc:<define>FOO <toolset>gcc <variant>debug <stdlib>native
1223
+ <dummy>dummy1 <toolset-gcc:version>2.95.2
1224
+ : add-defaults <runtime-link>static <define>foobar <optimization>on
1225
+ <toolset>gcc:<define>FOO ;
1226
+
1227
+ assert.result <runtime-link>static <define>foobar <optimization>on
1228
+ <toolset>gcc:<define>FOO <fu>fu1 <toolset>gcc <variant>debug
1229
+ <stdlib>native <dummy>dummy1 <fu-subfu2>q <toolset-gcc:version>2.95.2
1230
+ : add-defaults <runtime-link>static <define>foobar <optimization>on
1231
+ <toolset>gcc:<define>FOO <fu>fu1 ;
1232
+
1233
+ set-default <runtime-link> : static ;
1234
+ assert.result <runtime-link>static : defaults <runtime-link> ;
1235
+
1236
+ assert.result gcc-3.0.1 debug <optimization>on
1237
+ : minimize [ expand gcc-3.0.1 debug <optimization>on <stdlib>native ] ;
1238
+
1239
+ assert.result gcc-3.0.1 debug <runtime-link>dynamic
1240
+ : minimize
1241
+ [ expand gcc-3.0.1 debug <optimization>off <runtime-link>dynamic ] ;
1242
+
1243
+ assert.result gcc-3.0.1 debug
1244
+ : minimize [ expand gcc-3.0.1 debug <optimization>off ] ;
1245
+
1246
+ assert.result debug <optimization>on
1247
+ : minimize [ expand debug <optimization>on ] ;
1248
+
1249
+ assert.result gcc-3.0
1250
+ : minimize <toolset>gcc <toolset-gcc:version>3.0 ;
1251
+
1252
+ assert.result gcc-3.0
1253
+ : minimize <toolset-gcc:version>3.0 <toolset>gcc ;
1254
+
1255
+ assert.result <x>y/z <a>b/c <d>e/f
1256
+ : split <x>y/z/<a>b/c/<d>e/f ;
1257
+
1258
+ assert.result <x>y/z <a>b/c <d>e/f
1259
+ : split <x>y\\z\\<a>b\\c\\<d>e\\f ;
1260
+
1261
+ assert.result a b c <d>e/f/g <h>i/j/k
1262
+ : split a/b/c/<d>e/f/g/<h>i/j/k ;
1263
+
1264
+ assert.result a b c <d>e/f/g <h>i/j/k
1265
+ : split a\\b\\c\\<d>e\\f\\g\\<h>i\\j\\k ;
1266
+
1267
+ # Test error checking.
1268
+
1269
+ try ;
1270
+ {
1271
+ expand release <optimization>off <optimization>on ;
1272
+ }
1273
+ catch explicitly-specified values of non-free feature <optimization> conflict ;
1274
+
1275
+ try ;
1276
+ {
1277
+ validate-feature <foobar> ;
1278
+ }
1279
+ catch unknown feature ;
1280
+
1281
+ validate-value-string <toolset> gcc ;
1282
+ validate-value-string <toolset> gcc-3.0.1 ;
1283
+
1284
+ try ;
1285
+ {
1286
+ validate-value-string <toolset> digital_mars ;
1287
+ }
1288
+ catch \"digital_mars\" is not a known value of <toolset> ;
1289
+
1290
+ try ;
1291
+ {
1292
+ feature foobar : : baz ;
1293
+ }
1294
+ catch unknown attributes: baz ;
1295
+
1296
+ feature feature1 ;
1297
+ try ;
1298
+ {
1299
+ feature feature1 ;
1300
+ }
1301
+ catch feature already defined: ;
1302
+
1303
+ try ;
1304
+ {
1305
+ feature feature2 : : free implicit ;
1306
+ }
1307
+ catch free features cannot also be implicit ;
1308
+
1309
+ try ;
1310
+ {
1311
+ feature feature3 : : free propagated ;
1312
+ }
1313
+ catch free features cannot be propagated ;
1314
+
1315
+ try ;
1316
+ {
1317
+ implied-feature lackluster ;
1318
+ }
1319
+ catch \"lackluster\" is not a value of an implicit feature ;
1320
+
1321
+ try ;
1322
+ {
1323
+ implied-subfeature <toolset> 3.0.1 ;
1324
+ }
1325
+ catch \"3.0.1\" is not a known subfeature value of <toolset> ;
1326
+
1327
+ try ;
1328
+ {
1329
+ implied-subfeature <toolset> not-a-version : gcc ;
1330
+ }
1331
+ catch \"not-a-version\" is not a known subfeature value of <toolset>gcc ;
1332
+
1333
+ # Leave a clean copy of the features module behind.
1334
+ finish-test feature-test-temp ;
1335
+ }
mosesdecoder/jam-files/boost-build/build/generators.jam ADDED
@@ -0,0 +1,1380 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright Vladimir Prus 2002.
2
+ # Copyright Rene Rivera 2006.
3
+ #
4
+ # Distributed under the Boost Software License, Version 1.0.
5
+ # (See accompanying file LICENSE_1_0.txt or copy at
6
+ # http://www.boost.org/LICENSE_1_0.txt)
7
+
8
+ # Manages 'generators' --- objects which can do transformation between different
9
+ # target types and contain algorithm for finding transformation from sources to
10
+ # targets.
11
+ #
12
+ # The main entry point to this module is generators.construct rule. It is given
13
+ # a list of source targets, desired target type and a set of properties. It
14
+ # starts by selecting 'viable generators', which have any chances of producing
15
+ # the desired target type with the required properties. Generators are ranked
16
+ # and a set of the most specific ones is selected.
17
+ #
18
+ # The most specific generators have their 'run' methods called, with the
19
+ # properties and list of sources. Each one selects a target which can be
20
+ # directly consumed, and tries to convert the remaining ones to the types it can
21
+ # consume. This is done by recursively calling 'construct' with all consumable
22
+ # types.
23
+ #
24
+ # If the generator has collected all the targets it needs, it creates targets
25
+ # corresponding to result, and returns it. When all generators have been run,
26
+ # results of one of them are selected and returned as a result.
27
+ #
28
+ # It is quite possible for 'construct' to return more targets that it was asked
29
+ # for. For example, if it were asked to generate a target of type EXE, but the
30
+ # only found generator produces both EXE and TDS (file with debug) information.
31
+ # The extra target will be returned.
32
+ #
33
+ # Likewise, when generator tries to convert sources to consumable types, it can
34
+ # get more targets that it was asked for. The question is what to do with extra
35
+ # targets. Boost.Build attempts to convert them to requested types, and attempts
36
+ # that as early as possible. Specifically, this is done after invoking each
37
+ # generator. TODO: An example is needed to document the rationale for trying
38
+ # extra target conversion at that point.
39
+ #
40
+ # In order for the system to be able to use a specific generator instance 'when
41
+ # needed', the instance needs to be registered with the system using
42
+ # generators.register() or one of its related rules. Unregistered generators may
43
+ # only be run explicitly and will not be considered by Boost.Build when when
44
+ # converting between given target types.
45
+
46
+ import "class" : new ;
47
+ import errors ;
48
+ import property-set ;
49
+ import sequence ;
50
+ import set ;
51
+ import type ;
52
+ import utility ;
53
+ import virtual-target ;
54
+
55
+
56
+ if "--debug-generators" in [ modules.peek : ARGV ]
57
+ {
58
+ .debug = true ;
59
+ }
60
+
61
+
62
+ # Updated cached viable source target type information as needed after a new
63
+ # target type gets defined. This is needed because if a target type is a viable
64
+ # source target type for some generator then all of the target type's derived
65
+ # target types should automatically be considered as viable source target types
66
+ # for the same generator as well. Does nothing if a non-derived target type is
67
+ # passed to it.
68
+ #
69
+ rule update-cached-information-with-a-new-type ( type )
70
+ {
71
+ local base-type = [ type.base $(type) ] ;
72
+ if $(base-type)
73
+ {
74
+ for local g in $(.vstg-cached-generators)
75
+ {
76
+ if $(base-type) in $(.vstg.$(g))
77
+ {
78
+ .vstg.$(g) += $(type) ;
79
+ }
80
+ }
81
+
82
+ for local t in $(.vst-cached-types)
83
+ {
84
+ if $(base-type) in $(.vst.$(t))
85
+ {
86
+ .vst.$(t) += $(type) ;
87
+ }
88
+ }
89
+ }
90
+ }
91
+
92
+
93
+ # Clears cached viable source target type information except for target types
94
+ # and generators with all source types listed as viable. Should be called when
95
+ # something invalidates those cached values by possibly causing some new source
96
+ # types to become viable.
97
+ #
98
+ local rule invalidate-extendable-viable-source-target-type-cache ( )
99
+ {
100
+ local generators-with-cached-source-types = $(.vstg-cached-generators) ;
101
+ .vstg-cached-generators = ;
102
+ for local g in $(generators-with-cached-source-types)
103
+ {
104
+ if $(.vstg.$(g)) = *
105
+ {
106
+ .vstg-cached-generators += $(g) ;
107
+ }
108
+ else
109
+ {
110
+ .vstg.$(g) = ;
111
+ }
112
+ }
113
+
114
+ local types-with-cached-source-types = $(.vst-cached-types) ;
115
+ .vst-cached-types = ;
116
+ for local t in $(types-with-cached-source-types)
117
+ {
118
+ if $(.vst.$(t)) = *
119
+ {
120
+ .vst-cached-types += $(t) ;
121
+ }
122
+ else
123
+ {
124
+ .vst.$(t) = ;
125
+ }
126
+ }
127
+ }
128
+
129
+
130
+ # Outputs a debug message if generators debugging is on. Each element of
131
+ # 'message' is checked to see if it is a class instance. If so, instead of the
132
+ # value, the result of 'str' call is output.
133
+ #
134
+ local rule generators.dout ( message * )
135
+ {
136
+ if $(.debug)
137
+ {
138
+ ECHO [ sequence.transform utility.str : $(message) ] ;
139
+ }
140
+ }
141
+
142
+
143
+ local rule indent ( )
144
+ {
145
+ return $(.indent:J="") ;
146
+ }
147
+
148
+
149
+ local rule increase-indent ( )
150
+ {
151
+ .indent += " " ;
152
+ }
153
+
154
+
155
+ local rule decrease-indent ( )
156
+ {
157
+ .indent = $(.indent[2-]) ;
158
+ }
159
+
160
+
161
+ # Models a generator.
162
+ #
163
+ class generator
164
+ {
165
+ import generators : indent increase-indent decrease-indent generators.dout ;
166
+ import set ;
167
+ import utility ;
168
+ import feature ;
169
+ import errors ;
170
+ import sequence ;
171
+ import type ;
172
+ import virtual-target ;
173
+ import "class" : new ;
174
+ import property ;
175
+ import path ;
176
+
177
+ EXPORT class@generator : indent increase-indent decrease-indent
178
+ generators.dout ;
179
+
180
+ rule __init__ (
181
+ id # Identifies the generator - should be name
182
+ # of the rule which sets up the build
183
+ # actions.
184
+
185
+ composing ? # Whether generator processes each source
186
+ # target in turn, converting it to required
187
+ # types. Ordinary generators pass all
188
+ # sources together to the recursive
189
+ # generators.construct-types call.
190
+
191
+ : source-types * # Types that this generator can handle. If
192
+ # empty, the generator can consume anything.
193
+
194
+ : target-types-and-names + # Types the generator will create and,
195
+ # optionally, names for created targets.
196
+ # Each element should have the form
197
+ # type["(" name-pattern ")"], for example,
198
+ # obj(%_x). Generated target name will be
199
+ # found by replacing % with the name of
200
+ # source, provided an explicit name was not
201
+ # specified.
202
+
203
+ : requirements *
204
+ )
205
+ {
206
+ self.id = $(id) ;
207
+ self.rule-name = $(id) ;
208
+ self.composing = $(composing) ;
209
+ self.source-types = $(source-types) ;
210
+ self.target-types-and-names = $(target-types-and-names) ;
211
+ self.requirements = $(requirements) ;
212
+
213
+ for local e in $(target-types-and-names)
214
+ {
215
+ # Create three parallel lists: one with the list of target types,
216
+ # and two other with prefixes and postfixes to be added to target
217
+ # name. We use parallel lists for prefix and postfix (as opposed to
218
+ # mapping), because given target type might occur several times, for
219
+ # example "H H(%_symbols)".
220
+ local m = [ MATCH ([^\\(]*)(\\((.*)%(.*)\\))? : $(e) ] ;
221
+ self.target-types += $(m[1]) ;
222
+ self.name-prefix += $(m[3]:E="") ;
223
+ self.name-postfix += $(m[4]:E="") ;
224
+ }
225
+
226
+ # Note that 'transform' here, is the same as 'for_each'.
227
+ sequence.transform type.validate : $(self.source-types) ;
228
+ sequence.transform type.validate : $(self.target-types) ;
229
+ }
230
+
231
+ ################# End of constructor #################
232
+
233
+ rule id ( )
234
+ {
235
+ return $(self.id) ;
236
+ }
237
+
238
+ # Returns the list of target type the generator accepts.
239
+ #
240
+ rule source-types ( )
241
+ {
242
+ return $(self.source-types) ;
243
+ }
244
+
245
+ # Returns the list of target types that this generator produces. It is
246
+ # assumed to be always the same -- i.e. it can not change depending on some
247
+ # provided list of sources.
248
+ #
249
+ rule target-types ( )
250
+ {
251
+ return $(self.target-types) ;
252
+ }
253
+
254
+ # Returns the required properties for this generator. Properties in returned
255
+ # set must be present in build properties if this generator is to be used.
256
+ # If result has grist-only element, that build properties must include some
257
+ # value of that feature.
258
+ #
259
+ # XXX: remove this method?
260
+ #
261
+ rule requirements ( )
262
+ {
263
+ return $(self.requirements) ;
264
+ }
265
+
266
+ rule set-rule-name ( rule-name )
267
+ {
268
+ self.rule-name = $(rule-name) ;
269
+ }
270
+
271
+ rule rule-name ( )
272
+ {
273
+ return $(self.rule-name) ;
274
+ }
275
+
276
+ # Returns a true value if the generator can be run with the specified
277
+ # properties.
278
+ #
279
+ rule match-rank ( property-set-to-match )
280
+ {
281
+ # See if generator requirements are satisfied by 'properties'. Treat a
282
+ # feature name in requirements (i.e. grist-only element), as matching
283
+ # any value of the feature.
284
+ local all-requirements = [ requirements ] ;
285
+
286
+ local property-requirements feature-requirements ;
287
+ for local r in $(all-requirements)
288
+ {
289
+ if $(r:G=)
290
+ {
291
+ property-requirements += $(r) ;
292
+ }
293
+ else
294
+ {
295
+ feature-requirements += $(r) ;
296
+ }
297
+ }
298
+
299
+ local properties-to-match = [ $(property-set-to-match).raw ] ;
300
+ if $(property-requirements) in $(properties-to-match) &&
301
+ $(feature-requirements) in $(properties-to-match:G)
302
+ {
303
+ return true ;
304
+ }
305
+ else
306
+ {
307
+ return ;
308
+ }
309
+ }
310
+
311
+ # Returns another generator which differs from $(self) in
312
+ # - id
313
+ # - value to <toolset> feature in properties
314
+ #
315
+ rule clone ( new-id : new-toolset-properties + )
316
+ {
317
+ local g = [ new $(__class__) $(new-id) $(self.composing) :
318
+ $(self.source-types) : $(self.target-types-and-names) :
319
+ # Note: this does not remove any subfeatures of <toolset> which
320
+ # might cause problems.
321
+ [ property.change $(self.requirements) : <toolset> ]
322
+ $(new-toolset-properties) ] ;
323
+ return $(g) ;
324
+ }
325
+
326
+ # Creates another generator that is the same as $(self), except that if
327
+ # 'base' is in target types of $(self), 'type' will in target types of the
328
+ # new generator.
329
+ #
330
+ rule clone-and-change-target-type ( base : type )
331
+ {
332
+ local target-types ;
333
+ for local t in $(self.target-types-and-names)
334
+ {
335
+ local m = [ MATCH ([^\\(]*)(\\(.*\\))? : $(t) ] ;
336
+ if $(m) = $(base)
337
+ {
338
+ target-types += $(type)$(m[2]:E="") ;
339
+ }
340
+ else
341
+ {
342
+ target-types += $(t) ;
343
+ }
344
+ }
345
+
346
+ local g = [ new $(__class__) $(self.id) $(self.composing) :
347
+ $(self.source-types) : $(target-types) : $(self.requirements) ] ;
348
+ if $(self.rule-name)
349
+ {
350
+ $(g).set-rule-name $(self.rule-name) ;
351
+ }
352
+ return $(g) ;
353
+ }
354
+
355
+ # Tries to invoke this generator on the given sources. Returns a list of
356
+ # generated targets (instances of 'virtual-target') and optionally a set of
357
+ # properties to be added to the usage-requirements for all the generated
358
+ # targets. Returning nothing from run indicates that the generator was
359
+ # unable to create the target.
360
+ #
361
+ rule run
362
+ (
363
+ project # Project for which the targets are generated.
364
+ name ? # Used when determining the 'name' attribute for all
365
+ # generated targets. See the 'generated-targets' method.
366
+ : property-set # Desired properties for generated targets.
367
+ : sources + # Source targets.
368
+ )
369
+ {
370
+ generators.dout [ indent ] " ** generator" $(self.id) ;
371
+ generators.dout [ indent ] " composing:" $(self.composing) ;
372
+
373
+ if ! $(self.composing) && $(sources[2]) && $(self.source-types[2])
374
+ {
375
+ errors.error "Unsupported source/source-type combination" ;
376
+ }
377
+
378
+ # We do not run composing generators if no name is specified. The reason
379
+ # is that composing generator combines several targets, which can have
380
+ # different names, and it cannot decide which name to give for produced
381
+ # target. Therefore, the name must be passed.
382
+ #
383
+ # This in effect, means that composing generators are runnable only at
384
+ # the top-level of a transformation graph, or if their name is passed
385
+ # explicitly. Thus, we dissallow composing generators in the middle. For
386
+ # example, the transformation CPP -> OBJ -> STATIC_LIB -> RSP -> EXE
387
+ # will not be allowed as the OBJ -> STATIC_LIB generator is composing.
388
+ if ! $(self.composing) || $(name)
389
+ {
390
+ run-really $(project) $(name) : $(property-set) : $(sources) ;
391
+ }
392
+ }
393
+
394
+ rule run-really ( project name ? : property-set : sources + )
395
+ {
396
+ # Targets that this generator will consume directly.
397
+ local consumed = ;
398
+ # Targets that can not be consumed and will be returned as-is.
399
+ local bypassed = ;
400
+
401
+ if $(self.composing)
402
+ {
403
+ consumed = [ convert-multiple-sources-to-consumable-types $(project)
404
+ : $(property-set) : $(sources) ] ;
405
+ }
406
+ else
407
+ {
408
+ consumed = [ convert-to-consumable-types $(project) $(name)
409
+ : $(property-set) : $(sources) ] ;
410
+ }
411
+
412
+ local result ;
413
+ if $(consumed)
414
+ {
415
+ result = [ construct-result $(consumed) : $(project) $(name) :
416
+ $(property-set) ] ;
417
+ }
418
+
419
+ if $(result)
420
+ {
421
+ generators.dout [ indent ] " SUCCESS: " $(result) ;
422
+ }
423
+ else
424
+ {
425
+ generators.dout [ indent ] " FAILURE" ;
426
+ }
427
+ generators.dout ;
428
+ return $(result) ;
429
+ }
430
+
431
+ # Constructs the dependency graph to be returned by this generator.
432
+ #
433
+ rule construct-result
434
+ (
435
+ consumed + # Already prepared list of consumable targets.
436
+ # Composing generators may receive multiple sources
437
+ # all of which will have types matching those in
438
+ # $(self.source-types). Non-composing generators with
439
+ # multiple $(self.source-types) will receive exactly
440
+ # len $(self.source-types) sources with types matching
441
+ # those in $(self.source-types). And non-composing
442
+ # generators with only a single source type may
443
+ # receive multiple sources with all of them of the
444
+ # type listed in $(self.source-types).
445
+ : project name ?
446
+ : property-set # Properties to be used for all actions created here.
447
+ )
448
+ {
449
+ local result ;
450
+ # If this is 1->1 transformation, apply it to all consumed targets in
451
+ # order.
452
+ if ! $(self.source-types[2]) && ! $(self.composing)
453
+ {
454
+ for local r in $(consumed)
455
+ {
456
+ result += [ generated-targets $(r) : $(property-set) :
457
+ $(project) $(name) ] ;
458
+ }
459
+ }
460
+ else if $(consumed)
461
+ {
462
+ result += [ generated-targets $(consumed) : $(property-set) :
463
+ $(project) $(name) ] ;
464
+ }
465
+ return $(result) ;
466
+ }
467
+
468
+ # Determine target name from fullname (maybe including path components)
469
+ # Place optional prefix and postfix around basename
470
+ #
471
+ rule determine-target-name ( fullname : prefix ? : postfix ? )
472
+ {
473
+ # See if we need to add directory to the target name.
474
+ local dir = $(fullname:D) ;
475
+ local name = $(fullname:B) ;
476
+
477
+ name = $(prefix:E=)$(name) ;
478
+ name = $(name)$(postfix:E=) ;
479
+
480
+ if $(dir) &&
481
+ # Never append '..' to target path.
482
+ ! [ MATCH .*(\\.\\.).* : $(dir) ]
483
+ &&
484
+ ! [ path.is-rooted $(dir) ]
485
+ {
486
+ # Relative path is always relative to the source
487
+ # directory. Retain it, so that users can have files
488
+ # with the same in two different subdirectories.
489
+ name = $(dir)/$(name) ;
490
+ }
491
+ return $(name) ;
492
+ }
493
+
494
+ # Determine the name of the produced target from the names of the sources.
495
+ #
496
+ rule determine-output-name ( sources + )
497
+ {
498
+ # The simple case if when a name of source has single dot. Then, we take
499
+ # the part before dot. Several dots can be caused by:
500
+ # - using source file like a.host.cpp, or
501
+ # - a type whose suffix has a dot. Say, we can type 'host_cpp' with
502
+ # extension 'host.cpp'.
503
+ # In the first case, we want to take the part up to the last dot. In the
504
+ # second case -- not sure, but for now take the part up to the last dot
505
+ # too.
506
+ name = [ utility.basename [ $(sources[1]).name ] ] ;
507
+
508
+ for local s in $(sources[2])
509
+ {
510
+ local n2 = [ utility.basename [ $(s).name ] ] ;
511
+ if $(n2) != $(name)
512
+ {
513
+ errors.error "$(self.id): source targets have different names: cannot determine target name" ;
514
+ }
515
+ }
516
+ name = [ determine-target-name [ $(sources[1]).name ] ] ;
517
+ return $(name) ;
518
+ }
519
+
520
+ # Constructs targets that are created after consuming 'sources'. The result
521
+ # will be the list of virtual-target, which has the same length as the
522
+ # 'target-types' attribute and with corresponding types.
523
+ #
524
+ # When 'name' is empty, all source targets must have the same 'name'
525
+ # attribute value, which will be used instead of the 'name' argument.
526
+ #
527
+ # The 'name' attribute value for each generated target will be equal to
528
+ # the 'name' parameter if there is no name pattern for this type. Otherwise,
529
+ # the '%' symbol in the name pattern will be replaced with the 'name'
530
+ # parameter to obtain the 'name' attribute.
531
+ #
532
+ # For example, if targets types are T1 and T2 (with name pattern "%_x"),
533
+ # suffixes for T1 and T2 are .t1 and .t2, and source is foo.z, then created
534
+ # files would be "foo.t1" and "foo_x.t2". The 'name' attribute actually
535
+ # determines the basename of a file.
536
+ #
537
+ # Note that this pattern mechanism has nothing to do with implicit patterns
538
+ # in make. It is a way to produce a target whose name is different than the
539
+ # name of its source.
540
+ #
541
+ rule generated-targets ( sources + : property-set : project name ? )
542
+ {
543
+ if ! $(name)
544
+ {
545
+ name = [ determine-output-name $(sources) ] ;
546
+ }
547
+
548
+ # Assign an action for each target.
549
+ local action = [ action-class ] ;
550
+ local a = [ class.new $(action) $(sources) : $(self.rule-name) :
551
+ $(property-set) ] ;
552
+
553
+ # Create generated target for each target type.
554
+ local targets ;
555
+ local pre = $(self.name-prefix) ;
556
+ local post = $(self.name-postfix) ;
557
+ for local t in $(self.target-types)
558
+ {
559
+ local generated-name = $(pre[1])$(name:BS)$(post[1]) ;
560
+ generated-name = $(generated-name:R=$(name:D)) ;
561
+ pre = $(pre[2-]) ;
562
+ post = $(post[2-]) ;
563
+
564
+ targets += [ class.new file-target $(generated-name) : $(t) :
565
+ $(project) : $(a) ] ;
566
+ }
567
+
568
+ return [ sequence.transform virtual-target.register : $(targets) ] ;
569
+ }
570
+
571
+ # Attempts to convert 'sources' to targets of types that this generator can
572
+ # handle. The intention is to produce the set of targets that can be used
573
+ # when the generator is run.
574
+ #
575
+ rule convert-to-consumable-types
576
+ (
577
+ project name ?
578
+ : property-set
579
+ : sources +
580
+ : only-one ? # Convert 'source' to only one of the source types. If
581
+ # there is more that one possibility, report an error.
582
+ )
583
+ {
584
+ local _consumed ;
585
+ local missing-types ;
586
+
587
+ if $(sources[2])
588
+ {
589
+ # Do not know how to handle several sources yet. Just try to pass
590
+ # the request to other generator.
591
+ missing-types = $(self.source-types) ;
592
+ }
593
+ else
594
+ {
595
+ local temp = [ consume-directly $(sources) ] ;
596
+ if $(temp[1])
597
+ {
598
+ _consumed = $(temp[1]) ;
599
+ }
600
+ missing-types = $(temp[2-]) ;
601
+ }
602
+
603
+ # No need to search for transformation if some source type has consumed
604
+ # source and no more source types are needed.
605
+ if $(only-one) && $(_consumed)
606
+ {
607
+ missing-types = ;
608
+ }
609
+
610
+ # TODO: we should check that only one source type if create of
611
+ # 'only-one' is true.
612
+
613
+ if $(missing-types)
614
+ {
615
+ local transformed = [ generators.construct-types $(project) $(name)
616
+ : $(missing-types) : $(property-set) : $(sources) ] ;
617
+
618
+ # Add targets of right type to 'consumed'. Add others to 'bypassed'.
619
+ # The 'generators.construct' rule has done its best to convert
620
+ # everything to the required type. There is no need to rerun it on
621
+ # targets of different types.
622
+
623
+ # NOTE: ignoring usage requirements.
624
+ for local t in $(transformed[2-])
625
+ {
626
+ if [ $(t).type ] in $(missing-types)
627
+ {
628
+ _consumed += $(t) ;
629
+ }
630
+ }
631
+ }
632
+
633
+ return [ sequence.unique $(_consumed) ] ;
634
+ }
635
+
636
+ # Converts several files to consumable types. Called for composing
637
+ # generators only.
638
+ #
639
+ rule convert-multiple-sources-to-consumable-types ( project : property-set :
640
+ sources * )
641
+ {
642
+ local result ;
643
+ # We process each source one-by-one, trying to convert it to a usable
644
+ # type.
645
+ for local source in $(sources)
646
+ {
647
+ local _c = [ convert-to-consumable-types $(project) : $(property-set)
648
+ : $(source) : true ] ;
649
+ if ! $(_c)
650
+ {
651
+ generators.dout [ indent ] " failed to convert " $(source) ;
652
+ }
653
+ result += $(_c) ;
654
+ }
655
+ return $(result) ;
656
+ }
657
+
658
+ rule consume-directly ( source )
659
+ {
660
+ local real-source-type = [ $(source).type ] ;
661
+
662
+ # If there are no source types, we can consume anything.
663
+ local source-types = $(self.source-types) ;
664
+ source-types ?= $(real-source-type) ;
665
+
666
+ local result = "" ;
667
+ local missing-types ;
668
+
669
+ for local st in $(source-types)
670
+ {
671
+ # The 'source' if of the right type already.
672
+ if $(real-source-type) = $(st) || [ type.is-derived
673
+ $(real-source-type) $(st) ]
674
+ {
675
+ result = $(source) ;
676
+ }
677
+ else
678
+ {
679
+ missing-types += $(st) ;
680
+ }
681
+ }
682
+ return $(result) $(missing-types) ;
683
+ }
684
+
685
+ # Returns the class to be used to actions. Default implementation returns
686
+ # "action".
687
+ #
688
+ rule action-class ( )
689
+ {
690
+ return "action" ;
691
+ }
692
+ }
693
+
694
+
695
+ # Registers a new generator instance 'g'.
696
+ #
697
+ rule register ( g )
698
+ {
699
+ .all-generators += $(g) ;
700
+
701
+ # A generator can produce several targets of the same type. We want unique
702
+ # occurrence of that generator in .generators.$(t) in that case, otherwise,
703
+ # it will be tried twice and we will get a false ambiguity.
704
+ for local t in [ sequence.unique [ $(g).target-types ] ]
705
+ {
706
+ .generators.$(t) += $(g) ;
707
+ }
708
+
709
+ # Update the set of generators for toolset.
710
+
711
+ # TODO: should we check that generator with this id is not already
712
+ # registered. For example, the fop.jam module intentionally declared two
713
+ # generators with the same id, so such check will break it.
714
+ local id = [ $(g).id ] ;
715
+
716
+ # Some generators have multiple periods in their name, so a simple $(id:S=)
717
+ # will not generate the right toolset name. E.g. if id = gcc.compile.c++,
718
+ # then .generators-for-toolset.$(id:S=) will append to
719
+ # .generators-for-toolset.gcc.compile, which is a separate value from
720
+ # .generators-for-toolset.gcc. Correcting this makes generator inheritance
721
+ # work properly. See also inherit-generators in the toolset module.
722
+ local base = $(id) ;
723
+ while $(base:S)
724
+ {
725
+ base = $(base:B) ;
726
+ }
727
+ .generators-for-toolset.$(base) += $(g) ;
728
+
729
+
730
+ # After adding a new generator that can construct new target types, we need
731
+ # to clear the related cached viable source target type information for
732
+ # constructing a specific target type or using a specific generator. Cached
733
+ # viable source target type lists affected by this are those containing any
734
+ # of the target types constructed by the new generator or any of their base
735
+ # target types.
736
+ #
737
+ # A more advanced alternative to clearing that cached viable source target
738
+ # type information would be to expand it with additional source types or
739
+ # even better - mark it as needing to be expanded on next use.
740
+ #
741
+ # Also see the http://thread.gmane.org/gmane.comp.lib.boost.build/19077
742
+ # mailing list thread for an even more advanced idea of how we could convert
743
+ # Boost Build's Jamfile processing, target selection and generator selection
744
+ # into separate steps which would prevent these caches from ever being
745
+ # invalidated.
746
+ #
747
+ # For now we just clear all the cached viable source target type information
748
+ # that does not simply state 'all types' and may implement a more detailed
749
+ # algorithm later on if it becomes needed.
750
+
751
+ invalidate-extendable-viable-source-target-type-cache ;
752
+ }
753
+
754
+
755
+ # Creates a new non-composing 'generator' class instance and registers it.
756
+ # Returns the created instance. Rationale: the instance is returned so that it
757
+ # is possible to first register a generator and then call its 'run' method,
758
+ # bypassing the whole generator selection process.
759
+ #
760
+ rule register-standard ( id : source-types * : target-types + : requirements * )
761
+ {
762
+ local g = [ new generator $(id) : $(source-types) : $(target-types) :
763
+ $(requirements) ] ;
764
+ register $(g) ;
765
+ return $(g) ;
766
+ }
767
+
768
+
769
+ # Creates a new composing 'generator' class instance and registers it.
770
+ #
771
+ rule register-composing ( id : source-types * : target-types + : requirements *
772
+ )
773
+ {
774
+ local g = [ new generator $(id) true : $(source-types) : $(target-types) :
775
+ $(requirements) ] ;
776
+ register $(g) ;
777
+ return $(g) ;
778
+ }
779
+
780
+
781
+ # Returns all generators belonging to the given 'toolset', i.e. whose ids are
782
+ # '$(toolset).<something>'.
783
+ #
784
+ rule generators-for-toolset ( toolset )
785
+ {
786
+ return $(.generators-for-toolset.$(toolset)) ;
787
+ }
788
+
789
+
790
+ # Make generator 'overrider-id' be preferred to 'overridee-id'. If, when
791
+ # searching for generators that could produce a target of a certain type, both
792
+ # those generators are among viable generators, the overridden generator is
793
+ # immediately discarded.
794
+ #
795
+ # The overridden generators are discarded immediately after computing the list
796
+ # of viable generators but before running any of them.
797
+ #
798
+ rule override ( overrider-id : overridee-id )
799
+ {
800
+ .override.$(overrider-id) += $(overridee-id) ;
801
+ }
802
+
803
+
804
+ # Returns a list of source type which can possibly be converted to 'target-type'
805
+ # by some chain of generator invocation.
806
+ #
807
+ # More formally, takes all generators for 'target-type' and returns a union of
808
+ # source types for those generators and result of calling itself recursively on
809
+ # source types.
810
+ #
811
+ # Returns '*' in case any type should be considered a viable source type for the
812
+ # given type.
813
+ #
814
+ local rule viable-source-types-real ( target-type )
815
+ {
816
+ local result ;
817
+
818
+ # 't0' is the initial list of target types we need to process to get a list
819
+ # of their viable source target types. New target types will not be added to
820
+ # this list.
821
+ local t0 = [ type.all-bases $(target-type) ] ;
822
+
823
+ # 't' is the list of target types which have not yet been processed to get a
824
+ # list of their viable source target types. This list will get expanded as
825
+ # we locate more target types to process.
826
+ local t = $(t0) ;
827
+
828
+ while $(t)
829
+ {
830
+ # Find all generators for the current type. Unlike
831
+ # 'find-viable-generators' we do not care about the property-set.
832
+ local generators = $(.generators.$(t[1])) ;
833
+ t = $(t[2-]) ;
834
+
835
+ while $(generators)
836
+ {
837
+ local g = $(generators[1]) ;
838
+ generators = $(generators[2-]) ;
839
+
840
+ if ! [ $(g).source-types ]
841
+ {
842
+ # Empty source types -- everything can be accepted.
843
+ result = * ;
844
+ # This will terminate this loop.
845
+ generators = ;
846
+ # This will terminate the outer loop.
847
+ t = ;
848
+ }
849
+
850
+ for local source-type in [ $(g).source-types ]
851
+ {
852
+ if ! $(source-type) in $(result)
853
+ {
854
+ # If a generator accepts a 'source-type' it will also
855
+ # happily accept any type derived from it.
856
+ for local n in [ type.all-derived $(source-type) ]
857
+ {
858
+ if ! $(n) in $(result)
859
+ {
860
+ # Here there is no point in adding target types to
861
+ # the list of types to process in case they are or
862
+ # have already been on that list. We optimize this
863
+ # check by realizing that we only need to avoid the
864
+ # original target type's base types. Other target
865
+ # types that are or have been on the list of target
866
+ # types to process have been added to the 'result'
867
+ # list as well and have thus already been eliminated
868
+ # by the previous if.
869
+ if ! $(n) in $(t0)
870
+ {
871
+ t += $(n) ;
872
+ }
873
+ result += $(n) ;
874
+ }
875
+ }
876
+ }
877
+ }
878
+ }
879
+ }
880
+
881
+ return $(result) ;
882
+ }
883
+
884
+
885
+ # Helper rule, caches the result of 'viable-source-types-real'.
886
+ #
887
+ rule viable-source-types ( target-type )
888
+ {
889
+ local key = .vst.$(target-type) ;
890
+ if ! $($(key))
891
+ {
892
+ .vst-cached-types += $(target-type) ;
893
+ local v = [ viable-source-types-real $(target-type) ] ;
894
+ if ! $(v)
895
+ {
896
+ v = none ;
897
+ }
898
+ $(key) = $(v) ;
899
+ }
900
+
901
+ if $($(key)) != none
902
+ {
903
+ return $($(key)) ;
904
+ }
905
+ }
906
+
907
+
908
+ # Returns the list of source types, which, when passed to 'run' method of
909
+ # 'generator', has some change of being eventually used (probably after
910
+ # conversion by other generators).
911
+ #
912
+ # Returns '*' in case any type should be considered a viable source type for the
913
+ # given generator.
914
+ #
915
+ rule viable-source-types-for-generator-real ( generator )
916
+ {
917
+ local source-types = [ $(generator).source-types ] ;
918
+ if ! $(source-types)
919
+ {
920
+ # If generator does not specify any source types, it might be a special
921
+ # generator like builtin.lib-generator which just relays to other
922
+ # generators. Return '*' to indicate that any source type is possibly
923
+ # OK, since we do not know for sure.
924
+ return * ;
925
+ }
926
+ else
927
+ {
928
+ local result ;
929
+ while $(source-types)
930
+ {
931
+ local s = $(source-types[1]) ;
932
+ source-types = $(source-types[2-]) ;
933
+ local viable-sources = [ generators.viable-source-types $(s) ] ;
934
+ if $(viable-sources) = *
935
+ {
936
+ result = * ;
937
+ source-types = ; # Terminate the loop.
938
+ }
939
+ else
940
+ {
941
+ result += [ type.all-derived $(s) ] $(viable-sources) ;
942
+ }
943
+ }
944
+ return [ sequence.unique $(result) ] ;
945
+ }
946
+ }
947
+
948
+
949
+ # Helper rule, caches the result of 'viable-source-types-for-generator'.
950
+ #
951
+ local rule viable-source-types-for-generator ( generator )
952
+ {
953
+ local key = .vstg.$(generator) ;
954
+ if ! $($(key))
955
+ {
956
+ .vstg-cached-generators += $(generator) ;
957
+ local v = [ viable-source-types-for-generator-real $(generator) ] ;
958
+ if ! $(v)
959
+ {
960
+ v = none ;
961
+ }
962
+ $(key) = $(v) ;
963
+ }
964
+
965
+ if $($(key)) != none
966
+ {
967
+ return $($(key)) ;
968
+ }
969
+ }
970
+
971
+
972
+ # Returns usage requirements + list of created targets.
973
+ #
974
+ local rule try-one-generator-really ( project name ? : generator : target-type
975
+ : property-set : sources * )
976
+ {
977
+ local targets =
978
+ [ $(generator).run $(project) $(name) : $(property-set) : $(sources) ] ;
979
+
980
+ local usage-requirements ;
981
+ local success ;
982
+
983
+ generators.dout [ indent ] returned $(targets) ;
984
+
985
+ if $(targets)
986
+ {
987
+ success = true ;
988
+
989
+ if [ class.is-a $(targets[1]) : property-set ]
990
+ {
991
+ usage-requirements = $(targets[1]) ;
992
+ targets = $(targets[2-]) ;
993
+ }
994
+ else
995
+ {
996
+ usage-requirements = [ property-set.empty ] ;
997
+ }
998
+ }
999
+
1000
+ generators.dout [ indent ] " generator" [ $(generator).id ] " spawned " ;
1001
+ generators.dout [ indent ] " " $(targets) ;
1002
+ if $(usage-requirements)
1003
+ {
1004
+ generators.dout [ indent ] " with usage requirements:" $(x) ;
1005
+ }
1006
+
1007
+ if $(success)
1008
+ {
1009
+ return $(usage-requirements) $(targets) ;
1010
+ }
1011
+ }
1012
+
1013
+
1014
+ # Checks if generator invocation can be pruned, because it is guaranteed to
1015
+ # fail. If so, quickly returns an empty list. Otherwise, calls
1016
+ # try-one-generator-really.
1017
+ #
1018
+ local rule try-one-generator ( project name ? : generator : target-type
1019
+ : property-set : sources * )
1020
+ {
1021
+ local source-types ;
1022
+ for local s in $(sources)
1023
+ {
1024
+ source-types += [ $(s).type ] ;
1025
+ }
1026
+ local viable-source-types = [ viable-source-types-for-generator $(generator)
1027
+ ] ;
1028
+
1029
+ if $(source-types) && $(viable-source-types) != * &&
1030
+ ! [ set.intersection $(source-types) : $(viable-source-types) ]
1031
+ {
1032
+ local id = [ $(generator).id ] ;
1033
+ generators.dout [ indent ] " ** generator '$(id)' pruned" ;
1034
+ #generators.dout [ indent ] "source-types" '$(source-types)' ;
1035
+ #generators.dout [ indent ] "viable-source-types" '$(viable-source-types)' ;
1036
+ }
1037
+ else
1038
+ {
1039
+ return [ try-one-generator-really $(project) $(name) : $(generator) :
1040
+ $(target-type) : $(property-set) : $(sources) ] ;
1041
+ }
1042
+ }
1043
+
1044
+
1045
+ rule construct-types ( project name ? : target-types + : property-set
1046
+ : sources + )
1047
+ {
1048
+ local result ;
1049
+ local usage-requirements = [ property-set.empty ] ;
1050
+ for local t in $(target-types)
1051
+ {
1052
+ local r = [ construct $(project) $(name) : $(t) : $(property-set) :
1053
+ $(sources) ] ;
1054
+ if $(r)
1055
+ {
1056
+ usage-requirements = [ $(usage-requirements).add $(r[1]) ] ;
1057
+ result += $(r[2-]) ;
1058
+ }
1059
+ }
1060
+ # TODO: have to introduce parameter controlling if several types can be
1061
+ # matched and add appropriate checks.
1062
+
1063
+ # TODO: need to review the documentation for 'construct' to see if it should
1064
+ # return $(source) even if nothing can be done with it. Currents docs seem
1065
+ # to imply that, contrary to the behaviour.
1066
+ if $(result)
1067
+ {
1068
+ return $(usage-requirements) $(result) ;
1069
+ }
1070
+ else
1071
+ {
1072
+ return $(usage-requirements) $(sources) ;
1073
+ }
1074
+ }
1075
+
1076
+
1077
+ # Ensures all 'targets' have their type. If this is not so, exists with error.
1078
+ #
1079
+ local rule ensure-type ( targets * )
1080
+ {
1081
+ for local t in $(targets)
1082
+ {
1083
+ if ! [ $(t).type ]
1084
+ {
1085
+ errors.error "target" [ $(t).str ] "has no type" ;
1086
+ }
1087
+ }
1088
+ }
1089
+
1090
+
1091
+ # Returns generators which can be used to construct target of specified type
1092
+ # with specified properties. Uses the following algorithm:
1093
+ # - iterates over requested target-type and all its bases (in the order returned
1094
+ # by type.all-bases).
1095
+ # - for each type find all generators that generate that type and whose
1096
+ # requirements are satisfied by properties.
1097
+ # - if the set of generators is not empty, returns that set.
1098
+ #
1099
+ # Note: this algorithm explicitly ignores generators for base classes if there
1100
+ # is at least one generator for the requested target-type.
1101
+ #
1102
+ local rule find-viable-generators-aux ( target-type : property-set )
1103
+ {
1104
+ # Select generators that can create the required target type.
1105
+ local viable-generators = ;
1106
+ local generator-rank = ;
1107
+
1108
+ import type ;
1109
+ local t = [ type.all-bases $(target-type) ] ;
1110
+
1111
+ generators.dout [ indent ] find-viable-generators target-type= $(target-type)
1112
+ property-set= [ $(property-set).as-path ] ;
1113
+
1114
+ # Get the list of generators for the requested type. If no generator is
1115
+ # registered, try base type, and so on.
1116
+ local generators ;
1117
+ while $(t[1])
1118
+ {
1119
+ generators.dout [ indent ] "trying type" $(t[1]) ;
1120
+ if $(.generators.$(t[1]))
1121
+ {
1122
+ generators.dout [ indent ] "there are generators for this type" ;
1123
+ generators = $(.generators.$(t[1])) ;
1124
+
1125
+ if $(t[1]) != $(target-type)
1126
+ {
1127
+ # We are here because there were no generators found for
1128
+ # target-type but there are some generators for its base type.
1129
+ # We will try to use them, but they will produce targets of
1130
+ # base type, not of 'target-type'. So, we clone the generators
1131
+ # and modify the list of target types.
1132
+ local generators2 ;
1133
+ for local g in $(generators)
1134
+ {
1135
+ # generators.register adds a generator to the list of
1136
+ # generators for toolsets, which is a bit strange, but
1137
+ # should work. That list is only used when inheriting a
1138
+ # toolset, which should have been done before running
1139
+ # generators.
1140
+ generators2 += [ $(g).clone-and-change-target-type $(t[1]) :
1141
+ $(target-type) ] ;
1142
+ generators.register $(generators2[-1]) ;
1143
+ }
1144
+ generators = $(generators2) ;
1145
+ }
1146
+ t = ;
1147
+ }
1148
+ t = $(t[2-]) ;
1149
+ }
1150
+
1151
+ for local g in $(generators)
1152
+ {
1153
+ generators.dout [ indent ] "trying generator" [ $(g).id ] "(" [ $(g).source-types ] -> [ $(g).target-types ] ")" ;
1154
+
1155
+ local m = [ $(g).match-rank $(property-set) ] ;
1156
+ if $(m)
1157
+ {
1158
+ generators.dout [ indent ] " is viable" ;
1159
+ viable-generators += $(g) ;
1160
+ }
1161
+ }
1162
+
1163
+ return $(viable-generators) ;
1164
+ }
1165
+
1166
+
1167
+ rule find-viable-generators ( target-type : property-set )
1168
+ {
1169
+ local key = $(target-type).$(property-set) ;
1170
+ local l = $(.fv.$(key)) ;
1171
+ if ! $(l)
1172
+ {
1173
+ l = [ find-viable-generators-aux $(target-type) : $(property-set) ] ;
1174
+ if ! $(l)
1175
+ {
1176
+ l = none ;
1177
+ }
1178
+ .fv.$(key) = $(l) ;
1179
+ }
1180
+
1181
+ if $(l) = none
1182
+ {
1183
+ l = ;
1184
+ }
1185
+
1186
+ local viable-generators ;
1187
+ for local g in $(l)
1188
+ {
1189
+ # Avoid trying the same generator twice on different levels.
1190
+ if ! $(g) in $(.active-generators)
1191
+ {
1192
+ viable-generators += $(g) ;
1193
+ }
1194
+ else
1195
+ {
1196
+ generators.dout [ indent ] " generator " [ $(g).id ] "is active, discaring" ;
1197
+ }
1198
+ }
1199
+
1200
+ # Generators which override 'all'.
1201
+ local all-overrides ;
1202
+ # Generators which are overriden.
1203
+ local overriden-ids ;
1204
+ for local g in $(viable-generators)
1205
+ {
1206
+ local id = [ $(g).id ] ;
1207
+ local this-overrides = $(.override.$(id)) ;
1208
+ overriden-ids += $(this-overrides) ;
1209
+ if all in $(this-overrides)
1210
+ {
1211
+ all-overrides += $(g) ;
1212
+ }
1213
+ }
1214
+ if $(all-overrides)
1215
+ {
1216
+ viable-generators = $(all-overrides) ;
1217
+ }
1218
+ local result ;
1219
+ for local g in $(viable-generators)
1220
+ {
1221
+ if ! [ $(g).id ] in $(overriden-ids)
1222
+ {
1223
+ result += $(g) ;
1224
+ }
1225
+ }
1226
+
1227
+ return $(result) ;
1228
+ }
1229
+
1230
+
1231
+ .construct-stack = ;
1232
+
1233
+
1234
+ # Attempts to construct a target by finding viable generators, running them and
1235
+ # selecting the dependency graph.
1236
+ #
1237
+ local rule construct-really ( project name ? : target-type : property-set :
1238
+ sources * )
1239
+ {
1240
+ viable-generators = [ find-viable-generators $(target-type) :
1241
+ $(property-set) ] ;
1242
+
1243
+ generators.dout [ indent ] "*** " [ sequence.length $(viable-generators) ]
1244
+ " viable generators" ;
1245
+
1246
+ local result ;
1247
+ local generators-that-succeeded ;
1248
+ for local g in $(viable-generators)
1249
+ {
1250
+ # This variable will be restored on exit from this scope.
1251
+ local .active-generators = $(g) $(.active-generators) ;
1252
+
1253
+ local r = [ try-one-generator $(project) $(name) : $(g) : $(target-type)
1254
+ : $(property-set) : $(sources) ] ;
1255
+
1256
+ if $(r)
1257
+ {
1258
+ generators-that-succeeded += $(g) ;
1259
+ if $(result)
1260
+ {
1261
+ ECHO "Error: ambiguity found when searching for best transformation" ;
1262
+ ECHO "Trying to produce type '$(target-type)' from: " ;
1263
+ for local s in $(sources)
1264
+ {
1265
+ ECHO " - " [ $(s).str ] ;
1266
+ }
1267
+ ECHO "Generators that succeeded:" ;
1268
+ for local g in $(generators-that-succeeded)
1269
+ {
1270
+ ECHO " - " [ $(g).id ] ;
1271
+ }
1272
+ ECHO "First generator produced: " ;
1273
+ for local t in $(result[2-])
1274
+ {
1275
+ ECHO " - " [ $(t).str ] ;
1276
+ }
1277
+ ECHO "Second generator produced: " ;
1278
+ for local t in $(r[2-])
1279
+ {
1280
+ ECHO " - " [ $(t).str ] ;
1281
+ }
1282
+ EXIT ;
1283
+ }
1284
+ else
1285
+ {
1286
+ result = $(r) ;
1287
+ }
1288
+ }
1289
+ }
1290
+
1291
+ return $(result) ;
1292
+ }
1293
+
1294
+
1295
+ # Attempts to create a target of 'target-type' with 'properties' from 'sources'.
1296
+ # The 'sources' are treated as a collection of *possible* ingridients, i.e.
1297
+ # there is no obligation to consume them all.
1298
+ #
1299
+ # Returns a list of targets. When this invocation is first instance of
1300
+ # 'construct' in stack, returns only targets of requested 'target-type',
1301
+ # otherwise, returns also unused sources and additionally generated targets.
1302
+ #
1303
+ # If 'top-level' is set, does not suppress generators that are already
1304
+ # used in the stack. This may be useful in cases where a generator
1305
+ # has to build a metatargets -- for example a target corresponding to
1306
+ # built tool.
1307
+ #
1308
+ rule construct ( project name ? : target-type : property-set * : sources * : top-level ? )
1309
+ {
1310
+ local saved-stack ;
1311
+ if $(top-level)
1312
+ {
1313
+ saved-active = $(.active-generators) ;
1314
+ .active-generators = ;
1315
+ }
1316
+
1317
+ if (.construct-stack)
1318
+ {
1319
+ ensure-type $(sources) ;
1320
+ }
1321
+
1322
+ .construct-stack += 1 ;
1323
+
1324
+ increase-indent ;
1325
+
1326
+ if $(.debug)
1327
+ {
1328
+ generators.dout [ indent ] "*** construct" $(target-type) ;
1329
+
1330
+ for local s in $(sources)
1331
+ {
1332
+ generators.dout [ indent ] " from" $(s) ;
1333
+ }
1334
+ generators.dout [ indent ] " properties:" [ $(property-set).raw ] ;
1335
+ }
1336
+
1337
+ local result = [ construct-really $(project) $(name) : $(target-type) :
1338
+ $(property-set) : $(sources) ] ;
1339
+
1340
+ decrease-indent ;
1341
+
1342
+ .construct-stack = $(.construct-stack[2-]) ;
1343
+
1344
+ if $(top-level)
1345
+ {
1346
+ .active-generators = $(saved-active) ;
1347
+ }
1348
+
1349
+ return $(result) ;
1350
+ }
1351
+
1352
+ # Given 'result', obtained from some generator or generators.construct, adds
1353
+ # 'raw-properties' as usage requirements to it. If result already contains usage
1354
+ # requirements -- that is the first element of result of an instance of the
1355
+ # property-set class, the existing usage requirements and 'raw-properties' are
1356
+ # combined.
1357
+ #
1358
+ rule add-usage-requirements ( result * : raw-properties * )
1359
+ {
1360
+ if $(result)
1361
+ {
1362
+ if [ class.is-a $(result[1]) : property-set ]
1363
+ {
1364
+ return [ $(result[1]).add-raw $(raw-properties) ] $(result[2-]) ;
1365
+ }
1366
+ else
1367
+ {
1368
+ return [ property-set.create $(raw-properties) ] $(result) ;
1369
+ }
1370
+ }
1371
+ }
1372
+
1373
+ rule dump ( )
1374
+ {
1375
+ for local g in $(.all-generators)
1376
+ {
1377
+ ECHO [ $(g).id ] ":" [ $(g).source-types ] -> [ $(g).target-types ] ;
1378
+ }
1379
+ }
1380
+
mosesdecoder/jam-files/boost-build/build/modifiers.jam ADDED
@@ -0,0 +1,232 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2003 Rene Rivera
2
+ # Distributed under the Boost Software License, Version 1.0.
3
+ # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
4
+
5
+ # Modifiers are generalized generators that mutate targets in specific ways.
6
+ # This structure allows for grouping a variety of functionality in an
7
+ # orthogonal way to the functionality in toolsets, and without specifying
8
+ # more target variations. In turn the modifiers can be used as building
9
+ # blocks to implement simple requests, like the <version> feature.
10
+
11
+ import modules ;
12
+ import feature ;
13
+ import errors ;
14
+ import type ;
15
+ import "class" : new ;
16
+ import generators ;
17
+ import property ;
18
+ import virtual-target ;
19
+ import numbers ;
20
+ import sequence ;
21
+ import symlink ;
22
+ import property-set ;
23
+
24
+ # Base generator for creating targets that are modifications of existing
25
+ # targets.
26
+ #
27
+ class modifier : generator
28
+ {
29
+ rule __init__ (
30
+ id
31
+ composing ?
32
+ : source-types *
33
+ : target-types-and-names +
34
+ : requirements *
35
+ )
36
+ {
37
+ generator.__init__ $(id) $(composing)
38
+ : $(source-types)
39
+ : $(target-types-and-names)
40
+ : $(requirements) ;
41
+
42
+ self.targets-in-progress = ;
43
+ }
44
+
45
+ # Wraps the generation of the target to call before and after rules to
46
+ # affect the real target.
47
+ #
48
+ rule run ( project name ? : property-set : sources + )
49
+ {
50
+ local result ;
51
+ local current-target = $(project)^$(name) ;
52
+ if ! $(current-target) in $(self.targets-in-progress)
53
+ {
54
+ # Before modifications...
55
+ local project_ =
56
+ [ modify-project-before
57
+ $(project) $(name) : $(property-set) : $(sources) ] ;
58
+ local name_ =
59
+ [ modify-name-before
60
+ $(project) $(name) : $(property-set) : $(sources) ] ;
61
+ local property-set_ =
62
+ [ modify-properties-before
63
+ $(project) $(name) : $(property-set) : $(sources) ] ;
64
+ local sources_ =
65
+ [ modify-sources-before
66
+ $(project) $(name) : $(property-set) : $(sources) ] ;
67
+ project = $(project_) ;
68
+ name = $(name_) ;
69
+ property-set = $(property-set_) ;
70
+ sources = $(sources_) ;
71
+
72
+ # Generate the real target...
73
+ local target-type-p =
74
+ [ property.select <main-target-type> : [ $(property-set).raw ] ] ;
75
+ self.targets-in-progress += $(current-target) ;
76
+ result =
77
+ [ generators.construct $(project) $(name)
78
+ : $(target-type-p:G=)
79
+ : $(property-set)
80
+ : $(sources) ] ;
81
+ self.targets-in-progress = $(self.targets-in-progress[1--2]) ;
82
+
83
+ # After modifications...
84
+ result =
85
+ [ modify-target-after $(result)
86
+ : $(project) $(name)
87
+ : $(property-set)
88
+ : $(sources) ] ;
89
+ }
90
+ return $(result) ;
91
+ }
92
+
93
+ rule modify-project-before ( project name ? : property-set : sources + )
94
+ {
95
+ return $(project) ;
96
+ }
97
+
98
+ rule modify-name-before ( project name ? : property-set : sources + )
99
+ {
100
+ return $(name) ;
101
+ }
102
+
103
+ rule modify-properties-before ( project name ? : property-set : sources + )
104
+ {
105
+ return $(property-set) ;
106
+ }
107
+
108
+ rule modify-sources-before ( project name ? : property-set : sources + )
109
+ {
110
+ return $(sources) ;
111
+ }
112
+
113
+ rule modify-target-after ( target : project name ? : property-set : sources + )
114
+ {
115
+ return $(target) ;
116
+ }
117
+
118
+ # Utility, clones a file-target with optional changes to the name, type and
119
+ # project of the target.
120
+ # NOTE: This functionality should be moved, and generalized, to
121
+ # virtual-targets.
122
+ #
123
+ rule clone-file-target ( target : new-name ? : new-type ? : new-project ? )
124
+ {
125
+ # Need a MUTCH better way to clone a target...
126
+ new-name ?= [ $(target).name ] ;
127
+ new-type ?= [ $(target).type ] ;
128
+ new-project ?= [ $(target).project ] ;
129
+ local result = [ new file-target $(new-name) : $(new-type) : $(new-project) ] ;
130
+
131
+ if [ $(target).dependencies ] { $(result).depends [ $(target).dependencies ] ; }
132
+ $(result).root [ $(target).root ] ;
133
+ $(result).set-usage-requirements [ $(target).usage-requirements ] ;
134
+
135
+ local action = [ $(target).action ] ;
136
+ local action-class = [ modules.peek $(action) : __class__ ] ;
137
+
138
+ local ps = [ $(action).properties ] ;
139
+ local cloned-action = [ new $(action-class) $(result) :
140
+ [ $(action).sources ] : [ $(action).action-name ] : $(ps) ] ;
141
+ $(result).action $(cloned-action) ;
142
+
143
+ return $(result) ;
144
+ }
145
+ }
146
+
147
+
148
+ # A modifier that changes the name of a target, after it's generated, given a
149
+ # regular expression to split the name, and a set of token to insert between the
150
+ # split tokens of the name. This also exposes the target for other uses with a
151
+ # symlink to the original name (optionally).
152
+ #
153
+ class name-modifier : modifier
154
+ {
155
+ rule __init__ ( )
156
+ {
157
+ # Apply ourselves to EXE targets, for now.
158
+ modifier.__init__ name.modifier : : EXE LIB : <name-modify>yes ;
159
+ }
160
+
161
+ # Modifies the name, by cloning the target with the new name.
162
+ #
163
+ rule modify-target-after ( target : project name ? : property-set : sources + )
164
+ {
165
+ local result = $(target) ;
166
+
167
+ local name-mod-p = [ property.select <name-modifier> : [ $(property-set).raw ] ] ;
168
+ if $(name-mod-p)
169
+ {
170
+ local new-name = [ modify-name [ $(target).name ] : $(name-mod-p:G=) ] ;
171
+ if $(new-name) != [ $(target).name ]
172
+ {
173
+ result = [ clone-file-target $(target) : $(new-name) ] ;
174
+ }
175
+ local expose-original-as-symlink = [ MATCH "<symlink>(.*)" : $(name-mod-p) ] ;
176
+ if $(expose-original-as-symlink)
177
+ {
178
+ local symlink-t = [ new symlink-targets $(project) : $(name) : [ $(result).name ] ] ;
179
+ result = [ $(symlink-t).construct $(result)
180
+ : [ property-set.create [ $(property-set).raw ] <symlink-location>build-relative ] ] ;
181
+ }
182
+ }
183
+
184
+ return $(result) ;
185
+ }
186
+
187
+ # Do the transformation of the name.
188
+ #
189
+ rule modify-name ( name : modifier-spec + )
190
+ {
191
+ local match = [ MATCH "<match>(.*)" : $(modifier-spec) ] ;
192
+ local name-parts = [ MATCH $(match) : $(name) ] ;
193
+ local insertions = [ sequence.insertion-sort [ MATCH "(<[0123456789]+>.*)" : $(modifier-spec) ] ] ;
194
+ local new-name-parts ;
195
+ local insert-position = 1 ;
196
+ while $(insertions)
197
+ {
198
+ local insertion = [ MATCH "<$(insert-position)>(.*)" : $(insertions[1]) ] ;
199
+ if $(insertion)
200
+ {
201
+ new-name-parts += $(insertion) ;
202
+ insertions = $(insertions[2-]) ;
203
+ }
204
+ new-name-parts += $(name-parts[1]) ;
205
+ name-parts = $(name-parts[2-]) ;
206
+ insert-position = [ numbers.increment $(insert-position) ] ;
207
+ }
208
+ new-name-parts += $(name-parts) ;
209
+ return [ sequence.join $(new-name-parts) ] ;
210
+ }
211
+
212
+ rule optional-properties ( )
213
+ {
214
+ return <name-modify>yes ;
215
+ }
216
+ }
217
+ feature.feature name-modifier : : free ;
218
+ feature.feature name-modify : no yes : incidental optional ;
219
+ generators.register [ new name-modifier ] ;
220
+
221
+ # Translates <version> property to a set of modification properties
222
+ # that are applied by the name-modifier, and symlink-modifier.
223
+ #
224
+ rule version-to-modifier ( property : properties * )
225
+ {
226
+ return
227
+ <name-modify>yes
228
+ <name-modifier><match>"^([^.]*)(.*)" <name-modifier><2>.$(property:G=)
229
+ <name-modifier><symlink>yes
230
+ ;
231
+ }
232
+ feature.action <version> : version-to-modifier ;
mosesdecoder/jam-files/boost-build/build/property.jam ADDED
@@ -0,0 +1,788 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2001, 2002, 2003 Dave Abrahams
2
+ # Copyright 2006 Rene Rivera
3
+ # Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
4
+ # Distributed under the Boost Software License, Version 1.0.
5
+ # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
6
+
7
+ import errors ;
8
+ import feature ;
9
+ import indirect ;
10
+ import path ;
11
+ import regex ;
12
+ import string ;
13
+ import sequence ;
14
+ import set ;
15
+ import utility ;
16
+
17
+
18
+ # Refines 'properties' by overriding any non-free and non-conditional properties
19
+ # for which a different value is specified in 'requirements'. Returns the
20
+ # resulting list of properties.
21
+ #
22
+ rule refine ( properties * : requirements * )
23
+ {
24
+ local result ;
25
+ local error ;
26
+
27
+ # All the 'requirements' elements should be present in the result. Record
28
+ # them so that we can handle 'properties'.
29
+ for local r in $(requirements)
30
+ {
31
+ # Do not consider conditional requirements.
32
+ if ! [ MATCH (:) : $(r:G=) ]
33
+ {
34
+ # Note: cannot use a local variable here, so use an ugly name.
35
+ __require__$(r:G) = $(r:G=) ;
36
+ }
37
+ }
38
+
39
+ for local p in $(properties)
40
+ {
41
+ if [ MATCH (:) : $(p:G=) ]
42
+ {
43
+ # Do not modify conditional properties.
44
+ result += $(p) ;
45
+ }
46
+ else if free in [ feature.attributes $(p:G) ]
47
+ {
48
+ # Do not modify free properties.
49
+ result += $(p) ;
50
+ }
51
+ else
52
+ {
53
+ local required-value = $(__require__$(p:G)) ;
54
+ if $(required-value)
55
+ {
56
+ if $(p:G=) != $(required-value)
57
+ {
58
+ result += $(p:G)$(required-value) ;
59
+ }
60
+ else
61
+ {
62
+ result += $(p) ;
63
+ }
64
+ }
65
+ else
66
+ {
67
+ result += $(p) ;
68
+ }
69
+ }
70
+ }
71
+
72
+ # Unset our ugly map.
73
+ for local r in $(requirements)
74
+ {
75
+ __require__$(r:G) = ;
76
+ }
77
+
78
+ if $(error)
79
+ {
80
+ return $(error) ;
81
+ }
82
+ else
83
+ {
84
+ return [ sequence.unique $(result) $(requirements) ] ;
85
+ }
86
+ }
87
+
88
+
89
+ # Removes all conditional properties whose conditions are not met. For those
90
+ # with met conditions, removes the condition. Properties in conditions are
91
+ # looked up in 'context'.
92
+ #
93
+ rule evaluate-conditionals-in-context ( properties * : context * )
94
+ {
95
+ local base ;
96
+ local conditionals ;
97
+ for local p in $(properties)
98
+ {
99
+ if [ MATCH (:<) : $(p) ]
100
+ {
101
+ conditionals += $(p) ;
102
+ }
103
+ else
104
+ {
105
+ base += $(p) ;
106
+ }
107
+ }
108
+
109
+ local result = $(base) ;
110
+ for local p in $(conditionals)
111
+ {
112
+ # Separate condition and property.
113
+ local s = [ MATCH (.*):(<.*) : $(p) ] ;
114
+ # Split condition into individual properties.
115
+ local condition = [ regex.split $(s[1]) "," ] ;
116
+ # Evaluate condition.
117
+ if ! [ MATCH (!).* : $(condition:G=) ]
118
+ {
119
+ # Only positive checks
120
+ if $(condition) in $(context)
121
+ {
122
+ result += $(s[2]) ;
123
+ }
124
+ }
125
+ else
126
+ {
127
+ # Have negative checks
128
+ local fail ;
129
+ while $(condition)
130
+ {
131
+ local c = $(condition[1]) ;
132
+ local m = [ MATCH !(.*) : $(c) ] ;
133
+ if $(m)
134
+ {
135
+ local p = $(m:G=$(c:G)) ;
136
+ if $(p) in $(context)
137
+ {
138
+ fail = true ;
139
+ c = ;
140
+ }
141
+ }
142
+ else
143
+ {
144
+ if ! $(c) in $(context)
145
+ {
146
+ fail = true ;
147
+ c = ;
148
+ }
149
+ }
150
+ condition = $(condition[2-]) ;
151
+ }
152
+ if ! $(fail)
153
+ {
154
+ result += $(s[2]) ;
155
+ }
156
+ }
157
+ }
158
+ return $(result) ;
159
+ }
160
+
161
+
162
+ rule expand-subfeatures-in-conditions ( properties * )
163
+ {
164
+ local result ;
165
+ for local p in $(properties)
166
+ {
167
+ local s = [ MATCH (.*):(<.*) : $(p) ] ;
168
+ if ! $(s)
169
+ {
170
+ result += $(p) ;
171
+ }
172
+ else
173
+ {
174
+ local condition = $(s[1]) ;
175
+ local value = $(s[2]) ;
176
+ # Condition might include several elements.
177
+ condition = [ regex.split $(condition) "," ] ;
178
+ local e ;
179
+ for local c in $(condition)
180
+ {
181
+ # It is common for a condition to include a toolset or
182
+ # subfeatures that have not been defined. In that case we want
183
+ # the condition to simply 'never be satisfied' and validation
184
+ # would only produce a spurious error so we prevent it by
185
+ # passing 'true' as the second parameter.
186
+ e += [ feature.expand-subfeatures $(c) : true ] ;
187
+ }
188
+ if $(e) = $(condition)
189
+ {
190
+ # (todo)
191
+ # This is just an optimization and possibly a premature one at
192
+ # that.
193
+ # (todo) (12.07.2008.) (Jurko)
194
+ result += $(p) ;
195
+ }
196
+ else
197
+ {
198
+ result += $(e:J=,):$(value) ;
199
+ }
200
+ }
201
+ }
202
+ return $(result) ;
203
+ }
204
+
205
+
206
+ # Helper for as-path, below. Orders properties with the implicit ones first, and
207
+ # within the two sections in alphabetical order of feature name.
208
+ #
209
+ local rule path-order ( x y )
210
+ {
211
+ if $(y:G) && ! $(x:G)
212
+ {
213
+ return true ;
214
+ }
215
+ else if $(x:G) && ! $(y:G)
216
+ {
217
+ return ;
218
+ }
219
+ else
220
+ {
221
+ if ! $(x:G)
222
+ {
223
+ x = [ feature.expand-subfeatures $(x) ] ;
224
+ y = [ feature.expand-subfeatures $(y) ] ;
225
+ }
226
+
227
+ if $(x[1]) < $(y[1])
228
+ {
229
+ return true ;
230
+ }
231
+ }
232
+ }
233
+
234
+
235
+ local rule abbreviate-dashed ( string )
236
+ {
237
+ local r ;
238
+ for local part in [ regex.split $(string) - ]
239
+ {
240
+ r += [ string.abbreviate $(part) ] ;
241
+ }
242
+ return $(r:J=-) ;
243
+ }
244
+
245
+
246
+ local rule identity ( string )
247
+ {
248
+ return $(string) ;
249
+ }
250
+
251
+
252
+ if --abbreviate-paths in [ modules.peek : ARGV ]
253
+ {
254
+ .abbrev = abbreviate-dashed ;
255
+ }
256
+ else
257
+ {
258
+ .abbrev = identity ;
259
+ }
260
+
261
+
262
+ # Returns a path representing the given expanded property set.
263
+ #
264
+ rule as-path ( properties * )
265
+ {
266
+ local entry = .result.$(properties:J=-) ;
267
+
268
+ if ! $($(entry))
269
+ {
270
+ # Trim redundancy.
271
+ properties = [ feature.minimize $(properties) ] ;
272
+
273
+ # Sort according to path-order.
274
+ properties = [ sequence.insertion-sort $(properties) : path-order ] ;
275
+
276
+ local components ;
277
+ for local p in $(properties)
278
+ {
279
+ if $(p:G)
280
+ {
281
+ local f = [ utility.ungrist $(p:G) ] ;
282
+ p = $(f)-$(p:G=) ;
283
+ }
284
+ components += [ $(.abbrev) $(p) ] ;
285
+ }
286
+
287
+ $(entry) = $(components:J=/) ;
288
+ }
289
+
290
+ return $($(entry)) ;
291
+ }
292
+
293
+
294
+ # Exit with error if property is not valid.
295
+ #
296
+ local rule validate1 ( property )
297
+ {
298
+ local msg ;
299
+ if $(property:G)
300
+ {
301
+ local feature = $(property:G) ;
302
+ local value = $(property:G=) ;
303
+
304
+ if ! [ feature.valid $(feature) ]
305
+ {
306
+ # Ungrist for better error messages.
307
+ feature = [ utility.ungrist $(property:G) ] ;
308
+ msg = "unknown feature '$(feature)'" ;
309
+ }
310
+ else if $(value) && ! free in [ feature.attributes $(feature) ]
311
+ {
312
+ feature.validate-value-string $(feature) $(value) ;
313
+ }
314
+ else if ! ( $(value) || ( optional in [ feature.attributes $(feature) ] ) )
315
+ {
316
+ # Ungrist for better error messages.
317
+ feature = [ utility.ungrist $(property:G) ] ;
318
+ msg = "No value specified for feature '$(feature)'" ;
319
+ }
320
+ }
321
+ else
322
+ {
323
+ local feature = [ feature.implied-feature $(property) ] ;
324
+ feature.validate-value-string $(feature) $(property) ;
325
+ }
326
+ if $(msg)
327
+ {
328
+ errors.error "Invalid property "'$(property:J=" ")'": "$(msg:J=" "). ;
329
+ }
330
+ }
331
+
332
+
333
+ rule validate ( properties * )
334
+ {
335
+ for local p in $(properties)
336
+ {
337
+ validate1 $(p) ;
338
+ }
339
+ }
340
+
341
+
342
+ rule validate-property-sets ( property-sets * )
343
+ {
344
+ for local s in $(property-sets)
345
+ {
346
+ validate [ feature.split $(s) ] ;
347
+ }
348
+ }
349
+
350
+
351
+ # Expands any implicit property values in the given property 'specification' so
352
+ # they explicitly state their feature.
353
+ #
354
+ rule make ( specification * )
355
+ {
356
+ local result ;
357
+ for local e in $(specification)
358
+ {
359
+ if $(e:G)
360
+ {
361
+ result += $(e) ;
362
+ }
363
+ else if [ feature.is-implicit-value $(e) ]
364
+ {
365
+ local feature = [ feature.implied-feature $(e) ] ;
366
+ result += $(feature)$(e) ;
367
+ }
368
+ else
369
+ {
370
+ errors.error "'$(e)' is not a valid property specification" ;
371
+ }
372
+ }
373
+ return $(result) ;
374
+ }
375
+
376
+
377
+ # Returns a property set containing all the elements in 'properties' that do not
378
+ # have their attributes listed in 'attributes'.
379
+ #
380
+ rule remove ( attributes + : properties * )
381
+ {
382
+ local result ;
383
+ for local e in $(properties)
384
+ {
385
+ if ! [ set.intersection $(attributes) : [ feature.attributes $(e:G) ] ]
386
+ {
387
+ result += $(e) ;
388
+ }
389
+ }
390
+ return $(result) ;
391
+ }
392
+
393
+
394
+ # Returns a property set containing all the elements in 'properties' that have
395
+ # their attributes listed in 'attributes'.
396
+ #
397
+ rule take ( attributes + : properties * )
398
+ {
399
+ local result ;
400
+ for local e in $(properties)
401
+ {
402
+ if [ set.intersection $(attributes) : [ feature.attributes $(e:G) ] ]
403
+ {
404
+ result += $(e) ;
405
+ }
406
+ }
407
+ return $(result) ;
408
+ }
409
+
410
+
411
+ # Selects properties corresponding to any of the given features.
412
+ #
413
+ rule select ( features * : properties * )
414
+ {
415
+ local result ;
416
+
417
+ # Add any missing angle brackets.
418
+ local empty = "" ;
419
+ features = $(empty:G=$(features)) ;
420
+
421
+ for local p in $(properties)
422
+ {
423
+ if $(p:G) in $(features)
424
+ {
425
+ result += $(p) ;
426
+ }
427
+ }
428
+ return $(result) ;
429
+ }
430
+
431
+
432
+ # Returns a modified version of properties with all values of the given feature
433
+ # replaced by the given value. If 'value' is empty the feature will be removed.
434
+ #
435
+ rule change ( properties * : feature value ? )
436
+ {
437
+ local result ;
438
+ for local p in $(properties)
439
+ {
440
+ if $(p:G) = $(feature)
441
+ {
442
+ result += $(value:G=$(feature)) ;
443
+ }
444
+ else
445
+ {
446
+ result += $(p) ;
447
+ }
448
+ }
449
+ return $(result) ;
450
+ }
451
+
452
+
453
+ # If 'property' is a conditional property, returns the condition and the
454
+ # property. E.g. <variant>debug,<toolset>gcc:<inlining>full will become
455
+ # <variant>debug,<toolset>gcc <inlining>full. Otherwise, returns an empty
456
+ # string.
457
+ #
458
+ rule split-conditional ( property )
459
+ {
460
+ local m = [ MATCH "(.+):<(.+)" : $(property) ] ;
461
+ if $(m)
462
+ {
463
+ return $(m[1]) <$(m[2]) ;
464
+ }
465
+ }
466
+
467
+
468
+ # Interpret all path properties in 'properties' as relative to 'path'. The
469
+ # property values are assumed to be in system-specific form, and will be
470
+ # translated into normalized form.
471
+ #
472
+ rule translate-paths ( properties * : path )
473
+ {
474
+ local result ;
475
+ for local p in $(properties)
476
+ {
477
+ local split = [ split-conditional $(p) ] ;
478
+ local condition = "" ;
479
+ if $(split)
480
+ {
481
+ condition = $(split[1]): ;
482
+ p = $(split[2]) ;
483
+ }
484
+
485
+ if path in [ feature.attributes $(p:G) ]
486
+ {
487
+ local values = [ regex.split $(p:TG=) "&&" ] ;
488
+ local t ;
489
+ for local v in $(values)
490
+ {
491
+ t += [ path.root [ path.make $(v) ] $(path) ] ;
492
+ }
493
+ t = $(t:J="&&") ;
494
+ result += $(condition)$(t:TG=$(p:G)) ;
495
+ }
496
+ else
497
+ {
498
+ result += $(condition)$(p) ;
499
+ }
500
+ }
501
+ return $(result) ;
502
+ }
503
+
504
+
505
+ # Assumes that all feature values that start with '@' are names of rules, used
506
+ # in 'context-module'. Such rules can be either local to the module or global.
507
+ # Converts such values into 'indirect-rule' format (see indirect.jam), so they
508
+ # can be called from other modules. Does nothing for such values that are
509
+ # already in the 'indirect-rule' format.
510
+ #
511
+ rule translate-indirect ( specification * : context-module )
512
+ {
513
+ local result ;
514
+ for local p in $(specification)
515
+ {
516
+ local m = [ MATCH ^@(.+) : $(p:G=) ] ;
517
+ if $(m)
518
+ {
519
+ local v ;
520
+ if [ MATCH "^([^%]*)%([^%]+)$" : $(m) ]
521
+ {
522
+ # Rule is already in the 'indirect-rule' format.
523
+ v = $(m) ;
524
+ }
525
+ else
526
+ {
527
+ if ! [ MATCH ".*([.]).*" : $(m) ]
528
+ {
529
+ # This is an unqualified rule name. The user might want to
530
+ # set flags on this rule name and toolset.flag
531
+ # auto-qualifies it. Need to do the same here so flag
532
+ # setting works. We can arrange for toolset.flag to *not*
533
+ # auto-qualify the argument but then two rules defined in
534
+ # two Jamfiles would conflict.
535
+ m = $(context-module).$(m) ;
536
+ }
537
+ v = [ indirect.make $(m) : $(context-module) ] ;
538
+ }
539
+
540
+ v = @$(v) ;
541
+ result += $(v:G=$(p:G)) ;
542
+ }
543
+ else
544
+ {
545
+ result += $(p) ;
546
+ }
547
+ }
548
+ return $(result) ;
549
+ }
550
+
551
+
552
+ # Binds all dependency properties in a list relative to the given project.
553
+ # Targets with absolute paths will be left unchanged and targets which have a
554
+ # project specified will have the path to the project interpreted relative to
555
+ # the specified location.
556
+ #
557
+ rule translate-dependencies ( specification * : project-id : location )
558
+ {
559
+ local result ;
560
+ for local p in $(specification)
561
+ {
562
+ local split = [ split-conditional $(p) ] ;
563
+ local condition = "" ;
564
+ if $(split)
565
+ {
566
+ condition = $(split[1]): ;
567
+ p = $(split[2]) ;
568
+ }
569
+ if dependency in [ feature.attributes $(p:G) ]
570
+ {
571
+ local split-target = [ regex.match (.*)//(.*) : $(p:G=) ] ;
572
+ if $(split-target)
573
+ {
574
+ local rooted = [ path.root [ path.make $(split-target[1]) ]
575
+ [ path.root $(location) [ path.pwd ] ] ] ;
576
+ result += $(condition)$(p:G)$(rooted)//$(split-target[2]) ;
577
+ }
578
+ else if [ path.is-rooted $(p:G=) ]
579
+ {
580
+ result += $(condition)$(p) ;
581
+ }
582
+ else
583
+ {
584
+ result += $(condition)$(p:G)$(project-id)//$(p:G=) ;
585
+ }
586
+ }
587
+ else
588
+ {
589
+ result += $(condition)$(p) ;
590
+ }
591
+ }
592
+ return $(result) ;
593
+ }
594
+
595
+
596
+ # Class maintaining a property set -> string mapping.
597
+ #
598
+ class property-map
599
+ {
600
+ import errors ;
601
+ import numbers ;
602
+ import sequence ;
603
+
604
+ rule __init__ ( )
605
+ {
606
+ self.next-flag = 1 ;
607
+ }
608
+
609
+ # Associate 'value' with 'properties'.
610
+ #
611
+ rule insert ( properties + : value )
612
+ {
613
+ self.all-flags += $(self.next-flag) ;
614
+ self.properties.$(self.next-flag) = $(properties) ;
615
+ self.value.$(self.next-flag) = $(value) ;
616
+
617
+ self.next-flag = [ numbers.increment $(self.next-flag) ] ;
618
+ }
619
+
620
+ # Returns the value associated with 'properties' or any subset of it. If
621
+ # more than one subset has a value assigned to it, returns the value for the
622
+ # longest subset, if it is unique.
623
+ #
624
+ rule find ( properties + )
625
+ {
626
+ return [ find-replace $(properties) ] ;
627
+ }
628
+
629
+ # Returns the value associated with 'properties'. If 'value' parameter is
630
+ # given, replaces the found value.
631
+ #
632
+ rule find-replace ( properties + : value ? )
633
+ {
634
+ # First find all matches.
635
+ local matches ;
636
+ local match-ranks ;
637
+ for local i in $(self.all-flags)
638
+ {
639
+ if $(self.properties.$(i)) in $(properties)
640
+ {
641
+ matches += $(i) ;
642
+ match-ranks += [ sequence.length $(self.properties.$(i)) ] ;
643
+ }
644
+ }
645
+ local best = [ sequence.select-highest-ranked $(matches)
646
+ : $(match-ranks) ] ;
647
+ if $(best[2])
648
+ {
649
+ errors.error "Ambiguous key $(properties:J= :E=)" ;
650
+ }
651
+ local original = $(self.value.$(best)) ;
652
+ if $(value)
653
+ {
654
+ self.value.$(best) = $(value) ;
655
+ }
656
+ return $(original) ;
657
+ }
658
+ }
659
+
660
+
661
+ rule __test__ ( )
662
+ {
663
+ import assert ;
664
+ import "class" : new ;
665
+ import errors : try catch ;
666
+ import feature ;
667
+
668
+ # Local rules must be explicitly re-imported.
669
+ import property : path-order abbreviate-dashed ;
670
+
671
+ feature.prepare-test property-test-temp ;
672
+
673
+ feature.feature toolset : gcc : implicit symmetric ;
674
+ feature.subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4 3.0 3.0.1
675
+ 3.0.2 : optional ;
676
+ feature.feature define : : free ;
677
+ feature.feature runtime-link : dynamic static : symmetric link-incompatible ;
678
+ feature.feature optimization : on off ;
679
+ feature.feature variant : debug release : implicit composite symmetric ;
680
+ feature.feature rtti : on off : link-incompatible ;
681
+
682
+ feature.compose <variant>debug : <define>_DEBUG <optimization>off ;
683
+ feature.compose <variant>release : <define>NDEBUG <optimization>on ;
684
+
685
+ validate <toolset>gcc <toolset>gcc-3.0.1 : $(test-space) ;
686
+
687
+ assert.true path-order $(test-space) debug <define>foo ;
688
+ assert.false path-order $(test-space) <define>foo debug ;
689
+ assert.true path-order $(test-space) gcc debug ;
690
+ assert.false path-order $(test-space) debug gcc ;
691
+ assert.true path-order $(test-space) <optimization>on <rtti>on ;
692
+ assert.false path-order $(test-space) <rtti>on <optimization>on ;
693
+
694
+ assert.result-set-equal <toolset>gcc <rtti>off <define>FOO
695
+ : refine <toolset>gcc <rtti>off
696
+ : <define>FOO
697
+ : $(test-space) ;
698
+
699
+ assert.result-set-equal <toolset>gcc <optimization>on
700
+ : refine <toolset>gcc <optimization>off
701
+ : <optimization>on
702
+ : $(test-space) ;
703
+
704
+ assert.result-set-equal <toolset>gcc <rtti>off
705
+ : refine <toolset>gcc : <rtti>off : $(test-space) ;
706
+
707
+ assert.result-set-equal <toolset>gcc <rtti>off <rtti>off:<define>FOO
708
+ : refine <toolset>gcc : <rtti>off <rtti>off:<define>FOO
709
+ : $(test-space) ;
710
+
711
+ assert.result-set-equal <toolset>gcc:<define>foo <toolset>gcc:<define>bar
712
+ : refine <toolset>gcc:<define>foo : <toolset>gcc:<define>bar
713
+ : $(test-space) ;
714
+
715
+ assert.result <define>MY_RELEASE
716
+ : evaluate-conditionals-in-context
717
+ <variant>release,<rtti>off:<define>MY_RELEASE
718
+ : <toolset>gcc <variant>release <rtti>off ;
719
+
720
+ assert.result debug
721
+ : as-path <optimization>off <variant>debug
722
+ : $(test-space) ;
723
+
724
+ assert.result gcc/debug/rtti-off
725
+ : as-path <toolset>gcc <optimization>off <rtti>off <variant>debug
726
+ : $(test-space) ;
727
+
728
+ assert.result optmz-off : abbreviate-dashed optimization-off ;
729
+ assert.result rntm-lnk-sttc : abbreviate-dashed runtime-link-static ;
730
+
731
+ try ;
732
+ validate <feature>value : $(test-space) ;
733
+ catch "Invalid property '<feature>value': unknown feature 'feature'." ;
734
+
735
+ try ;
736
+ validate <rtti>default : $(test-space) ;
737
+ catch \"default\" is not a known value of feature <rtti> ;
738
+
739
+ validate <define>WHATEVER : $(test-space) ;
740
+
741
+ try ;
742
+ validate <rtti> : $(test-space) ;
743
+ catch "Invalid property '<rtti>': No value specified for feature 'rtti'." ;
744
+
745
+ try ;
746
+ validate value : $(test-space) ;
747
+ catch "value" is not a value of an implicit feature ;
748
+
749
+ assert.result-set-equal <rtti>on
750
+ : remove free implicit : <toolset>gcc <define>foo <rtti>on : $(test-space) ;
751
+
752
+ assert.result-set-equal <include>a
753
+ : select include : <include>a <toolset>gcc ;
754
+
755
+ assert.result-set-equal <include>a
756
+ : select include bar : <include>a <toolset>gcc ;
757
+
758
+ assert.result-set-equal <include>a <toolset>gcc
759
+ : select include <bar> <toolset> : <include>a <toolset>gcc ;
760
+
761
+ assert.result-set-equal <toolset>kylix <include>a
762
+ : change <toolset>gcc <include>a : <toolset> kylix ;
763
+
764
+ pm = [ new property-map ] ;
765
+ $(pm).insert <toolset>gcc : o ;
766
+ $(pm).insert <toolset>gcc <os>NT : obj ;
767
+ $(pm).insert <toolset>gcc <os>CYGWIN : obj ;
768
+
769
+ assert.equal o : [ $(pm).find <toolset>gcc ] ;
770
+
771
+ assert.equal obj : [ $(pm).find <toolset>gcc <os>NT ] ;
772
+
773
+ try ;
774
+ $(pm).find <toolset>gcc <os>NT <os>CYGWIN ;
775
+ catch "Ambiguous key <toolset>gcc <os>NT <os>CYGWIN" ;
776
+
777
+ # Test ordinary properties.
778
+ assert.result : split-conditional <toolset>gcc ;
779
+
780
+ # Test properties with ":".
781
+ assert.result : split-conditional <define>FOO=A::B ;
782
+
783
+ # Test conditional feature.
784
+ assert.result-set-equal <toolset>gcc,<toolset-gcc:version>3.0 <define>FOO
785
+ : split-conditional <toolset>gcc,<toolset-gcc:version>3.0:<define>FOO ;
786
+
787
+ feature.finish-test property-test-temp ;
788
+ }
mosesdecoder/jam-files/boost-build/build/scanner.jam ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2003 Dave Abrahams
2
+ # Copyright 2002, 2003, 2004, 2005 Vladimir Prus
3
+ # Distributed under the Boost Software License, Version 1.0.
4
+ # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
5
+
6
+ # Implements scanners: objects that compute implicit dependencies for
7
+ # files, such as includes in C++.
8
+ #
9
+ # Scanner has a regular expression used to find dependencies, some
10
+ # data needed to interpret those dependencies (for example, include
11
+ # paths), and a code which actually established needed relationship
12
+ # between actual jam targets.
13
+ #
14
+ # Scanner objects are created by actions, when they try to actualize
15
+ # virtual targets, passed to 'virtual-target.actualize' method and are
16
+ # then associated with actual targets. It is possible to use
17
+ # several scanners for a virtual-target. For example, a single source
18
+ # might be used by to compile actions, with different include paths.
19
+ # In this case, two different actual targets will be created, each
20
+ # having scanner of its own.
21
+ #
22
+ # Typically, scanners are created from target type and action's
23
+ # properties, using the rule 'get' in this module. Directly creating
24
+ # scanners is not recommended, because it might create many equvivalent
25
+ # but different instances, and lead in unneeded duplication of
26
+ # actual targets. However, actions can also create scanners in a special
27
+ # way, instead of relying on just target type.
28
+
29
+ import "class" : new ;
30
+ import property virtual-target property-set ;
31
+ import errors : error ;
32
+
33
+ # Base scanner class.
34
+ class scanner
35
+ {
36
+ rule __init__ ( )
37
+ {
38
+ }
39
+
40
+ # Returns a pattern to use for scanning
41
+ rule pattern ( )
42
+ {
43
+ error "method must be overriden" ;
44
+ }
45
+
46
+ # Establish necessary relationship between targets,
47
+ # given actual target beeing scanned, and a list of
48
+ # pattern matches in that file.
49
+ rule process ( target : matches * )
50
+ {
51
+ error "method must be overriden" ;
52
+ }
53
+ }
54
+
55
+ # Registers a new generator class, specifying a set of
56
+ # properties relevant to this scanner. Ctor for that class
57
+ # should have one parameter: list of properties.
58
+ rule register ( scanner-class : relevant-properties * )
59
+ {
60
+ .registered += $(scanner-class) ;
61
+ .relevant-properties.$(scanner-class) = $(relevant-properties) ;
62
+ }
63
+
64
+ # Common scanner class, which can be used when there's only one
65
+ # kind of includes (unlike C, where "" and <> includes have different
66
+ # search paths).
67
+ class common-scanner : scanner
68
+ {
69
+ import scanner ;
70
+ rule __init__ ( includes * )
71
+ {
72
+ scanner.__init__ ;
73
+ self.includes = $(includes) ;
74
+ }
75
+
76
+ rule process ( target : matches * : binding )
77
+ {
78
+ local target_path = [ NORMALIZE_PATH $(binding:D) ] ;
79
+
80
+ NOCARE $(matches) ;
81
+ INCLUDES $(target) : $(matches) ;
82
+ SEARCH on $(matches) = $(target_path) $(self.includes:G=) ;
83
+ ISFILE $(matches) ;
84
+
85
+ scanner.propagate $(__name__) : $(matches) : $(target) ;
86
+ }
87
+ }
88
+
89
+
90
+ # Returns an instance of previously registered scanner,
91
+ # with the specified properties.
92
+ rule get ( scanner-class : property-set )
93
+ {
94
+ if ! $(scanner-class) in $(.registered)
95
+ {
96
+ error "attempt to get unregisted scanner" ;
97
+ }
98
+
99
+ local r = $(.rv-cache.$(property-set)) ;
100
+ if ! $(r)
101
+ {
102
+ r = [ property-set.create
103
+ [ property.select $(.relevant-properties.$(scanner-class)) :
104
+ [ $(property-set).raw ] ] ] ;
105
+ .rv-cache.$(property-set) = $(r) ;
106
+ }
107
+
108
+ if ! $(scanner.$(scanner-class).$(r:J=-))
109
+ {
110
+ scanner.$(scanner-class).$(r:J=-) = [ new $(scanner-class) [ $(r).raw ] ] ;
111
+ }
112
+ return $(scanner.$(scanner-class).$(r:J=-)) ;
113
+ }
114
+
115
+
116
+ # Installs the specified scanner on actual target 'target'.
117
+ rule install ( scanner : target
118
+ vtarget # virtual target from which 'target' was actualized
119
+ )
120
+ {
121
+ HDRSCAN on $(target) = [ $(scanner).pattern ] ;
122
+ SCANNER on $(target) = $(scanner) ;
123
+ HDRRULE on $(target) = scanner.hdrrule ;
124
+
125
+ # scanner reflects difference in properties affecting
126
+ # binding of 'target', which will be known when processing
127
+ # includes for it, will give information on how to
128
+ # interpret quoted includes.
129
+ HDRGRIST on $(target) = $(scanner) ;
130
+ }
131
+
132
+ # Propagate scanner setting from 'including-target' to 'targets'.
133
+ rule propagate ( scanner : targets * : including-target )
134
+ {
135
+ HDRSCAN on $(targets) = [ on $(including-target) return $(HDRSCAN) ] ;
136
+ SCANNER on $(targets) = $(scanner) ;
137
+ HDRRULE on $(targets) = scanner.hdrrule ;
138
+ HDRGRIST on $(targets) = [ on $(including-target) return $(HDRGRIST) ] ;
139
+ }
140
+
141
+
142
+ rule hdrrule ( target : matches * : binding )
143
+ {
144
+ local scanner = [ on $(target) return $(SCANNER) ] ;
145
+ $(scanner).process $(target) : $(matches) : $(binding) ;
146
+ }
147
+ # hdrrule must be available at global scope so that it can be invoked
148
+ # by header scanning
149
+ IMPORT scanner : hdrrule : : scanner.hdrrule ;
150
+
151
+
152
+
153
+
mosesdecoder/jam-files/boost-build/build/toolset.jam ADDED
@@ -0,0 +1,575 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2003 Dave Abrahams
2
+ # Copyright 2005 Rene Rivera
3
+ # Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
4
+ # Distributed under the Boost Software License, Version 1.0.
5
+ # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
6
+
7
+ # Support for toolset definition.
8
+
9
+ import errors ;
10
+ import feature ;
11
+ import generators ;
12
+ import numbers ;
13
+ import path ;
14
+ import property ;
15
+ import regex ;
16
+ import sequence ;
17
+ import set ;
18
+ import property-set ;
19
+
20
+
21
+ .flag-no = 1 ;
22
+
23
+ .ignore-requirements = ;
24
+
25
+ # This is used only for testing, to make sure we do not get random extra
26
+ # elements in paths.
27
+ if --ignore-toolset-requirements in [ modules.peek : ARGV ]
28
+ {
29
+ .ignore-requirements = 1 ;
30
+ }
31
+
32
+
33
+ # Initializes an additional toolset-like module. First load the 'toolset-module'
34
+ # and then calls its 'init' rule with trailing arguments.
35
+ #
36
+ rule using ( toolset-module : * )
37
+ {
38
+ import $(toolset-module) ;
39
+ $(toolset-module).init $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
40
+ }
41
+
42
+
43
+ # Expands subfeatures in each property sets, e.g. '<toolset>gcc-3.2' will be
44
+ # converted to '<toolset>gcc/<toolset-version>3.2'.
45
+ #
46
+ local rule normalize-condition ( property-sets * )
47
+ {
48
+ local result ;
49
+ for local p in $(property-sets)
50
+ {
51
+ local split = [ feature.split $(p) ] ;
52
+ local expanded = [ feature.expand-subfeatures [ feature.split $(p) ] ] ;
53
+ result += $(expanded:J=/) ;
54
+ }
55
+ return $(result) ;
56
+ }
57
+
58
+
59
+ # Specifies if the 'flags' rule should check that the invoking module is the
60
+ # same as the module we are setting the flag for. 'v' can be either 'checked' or
61
+ # 'unchecked'. Subsequent call to 'pop-checking-for-flags-module' will restore
62
+ # the setting that was in effect before calling this rule.
63
+ #
64
+ rule push-checking-for-flags-module ( v )
65
+ {
66
+ .flags-module-checking = $(v) $(.flags-module-checking) ;
67
+ }
68
+
69
+ rule pop-checking-for-flags-module ( )
70
+ {
71
+ .flags-module-checking = $(.flags-module-checking[2-]) ;
72
+ }
73
+
74
+
75
+ # Specifies the flags (variables) that must be set on targets under certain
76
+ # conditions, described by arguments.
77
+ #
78
+ rule flags (
79
+ rule-or-module # If contains a dot, should be a rule name. The flags will
80
+ # be applied when that rule is used to set up build
81
+ # actions.
82
+ #
83
+ # If does not contain dot, should be a module name. The
84
+ # flag will be applied for all rules in that module. If
85
+ # module for rule is different from the calling module, an
86
+ # error is issued.
87
+
88
+ variable-name # Variable that should be set on target.
89
+ condition * : # A condition when this flag should be applied. Should be a
90
+ # set of property sets. If one of those property sets is
91
+ # contained in the build properties, the flag will be used.
92
+ # Implied values are not allowed: "<toolset>gcc" should be
93
+ # used, not just "gcc". Subfeatures, like in
94
+ # "<toolset>gcc-3.2" are allowed. If left empty, the flag
95
+ # will be used unconditionally.
96
+ #
97
+ # Propery sets may use value-less properties ('<a>' vs.
98
+ # '<a>value') to match absent properties. This allows to
99
+ # separately match:
100
+ #
101
+ # <architecture>/<address-model>64
102
+ # <architecture>ia64/<address-model>
103
+ #
104
+ # Where both features are optional. Without this syntax
105
+ # we would be forced to define "default" values.
106
+
107
+ values * : # The value to add to variable. If <feature> is specified,
108
+ # then the value of 'feature' will be added.
109
+ unchecked ? # If value 'unchecked' is passed, will not test that flags
110
+ # are set for the calling module.
111
+ : hack-hack ? # For
112
+ # flags rule OPTIONS <cxx-abi> : -model ansi
113
+ # Treat <cxx-abi> as condition
114
+ # FIXME: ugly hack.
115
+ )
116
+ {
117
+ local caller = [ CALLER_MODULE ] ;
118
+ if ! [ MATCH ".*([.]).*" : $(rule-or-module) ]
119
+ && [ MATCH "(Jamfile<.*)" : $(caller) ]
120
+ {
121
+ # Unqualified rule name, used inside Jamfile. Most likely used with
122
+ # 'make' or 'notfile' rules. This prevents setting flags on the entire
123
+ # Jamfile module (this will be considered as rule), but who cares?
124
+ # Probably, 'flags' rule should be split into 'flags' and
125
+ # 'flags-on-module'.
126
+ rule-or-module = $(caller).$(rule-or-module) ;
127
+ }
128
+ else
129
+ {
130
+ local module_ = [ MATCH "([^.]*).*" : $(rule-or-module) ] ;
131
+ if $(unchecked) != unchecked
132
+ && $(.flags-module-checking[1]) != unchecked
133
+ && $(module_) != $(caller)
134
+ {
135
+ errors.error "Module $(caller) attempted to set flags for module $(module_)" ;
136
+ }
137
+ }
138
+
139
+ if $(condition) && ! $(condition:G=) && ! $(hack-hack)
140
+ {
141
+ # We have condition in the form '<feature>', that is, without value.
142
+ # That is an older syntax:
143
+ # flags gcc.link RPATH <dll-path> ;
144
+ # for compatibility, convert it to
145
+ # flags gcc.link RPATH : <dll-path> ;
146
+ values = $(condition) ;
147
+ condition = ;
148
+ }
149
+
150
+ if $(condition)
151
+ {
152
+ property.validate-property-sets $(condition) ;
153
+ condition = [ normalize-condition $(condition) ] ;
154
+ }
155
+
156
+ add-flag $(rule-or-module) : $(variable-name) : $(condition) : $(values) ;
157
+ }
158
+
159
+
160
+ # Adds a new flag setting with the specified values. Does no checking.
161
+ #
162
+ local rule add-flag ( rule-or-module : variable-name : condition * : values * )
163
+ {
164
+ .$(rule-or-module).flags += $(.flag-no) ;
165
+
166
+ # Store all flags for a module.
167
+ local module_ = [ MATCH "([^.]*).*" : $(rule-or-module) ] ;
168
+ .module-flags.$(module_) += $(.flag-no) ;
169
+ # Store flag-no -> rule-or-module mapping.
170
+ .rule-or-module.$(.flag-no) = $(rule-or-module) ;
171
+
172
+ .$(rule-or-module).variable.$(.flag-no) += $(variable-name) ;
173
+ .$(rule-or-module).values.$(.flag-no) += $(values) ;
174
+ .$(rule-or-module).condition.$(.flag-no) += $(condition) ;
175
+
176
+ .flag-no = [ numbers.increment $(.flag-no) ] ;
177
+ }
178
+
179
+
180
+ # Returns the first element of 'property-sets' which is a subset of
181
+ # 'properties' or an empty list if no such element exists.
182
+ #
183
+ rule find-property-subset ( property-sets * : properties * )
184
+ {
185
+ # Cut property values off.
186
+ local prop-keys = $(properties:G) ;
187
+
188
+ local result ;
189
+ for local s in $(property-sets)
190
+ {
191
+ if ! $(result)
192
+ {
193
+ # Handle value-less properties like '<architecture>' (compare with
194
+ # '<architecture>x86').
195
+
196
+ local set = [ feature.split $(s) ] ;
197
+
198
+ # Find the set of features that
199
+ # - have no property specified in required property set
200
+ # - are omitted in the build property set.
201
+ local default-props ;
202
+ for local i in $(set)
203
+ {
204
+ # If $(i) is a value-less property it should match default value
205
+ # of an optional property. See the first line in the example
206
+ # below:
207
+ #
208
+ # property set properties result
209
+ # <a> <b>foo <b>foo match
210
+ # <a> <b>foo <a>foo <b>foo no match
211
+ # <a>foo <b>foo <b>foo no match
212
+ # <a>foo <b>foo <a>foo <b>foo match
213
+ if ! ( $(i:G=) || ( $(i:G) in $(prop-keys) ) )
214
+ {
215
+ default-props += $(i) ;
216
+ }
217
+ }
218
+
219
+ if $(set) in $(properties) $(default-props)
220
+ {
221
+ result = $(s) ;
222
+ }
223
+ }
224
+ }
225
+ return $(result) ;
226
+ }
227
+
228
+
229
+ # Returns a value to be added to some flag for some target based on the flag's
230
+ # value definition and the given target's property set.
231
+ #
232
+ rule handle-flag-value ( value * : properties * )
233
+ {
234
+ local result ;
235
+ if $(value:G)
236
+ {
237
+ local matches = [ property.select $(value) : $(properties) ] ;
238
+ for local p in $(matches)
239
+ {
240
+ local att = [ feature.attributes $(p:G) ] ;
241
+ if dependency in $(att)
242
+ {
243
+ # The value of a dependency feature is a target and needs to be
244
+ # actualized.
245
+ result += [ $(p:G=).actualize ] ;
246
+ }
247
+ else if path in $(att) || free in $(att)
248
+ {
249
+ local values ;
250
+ # Treat features with && in the value specially -- each
251
+ # &&-separated element is considered a separate value. This is
252
+ # needed to handle searched libraries or include paths, which
253
+ # may need to be in a specific order.
254
+ if ! [ MATCH (&&) : $(p:G=) ]
255
+ {
256
+ values = $(p:G=) ;
257
+ }
258
+ else
259
+ {
260
+ values = [ regex.split $(p:G=) "&&" ] ;
261
+ }
262
+ if path in $(att)
263
+ {
264
+ result += [ sequence.transform path.native : $(values) ] ;
265
+ }
266
+ else
267
+ {
268
+ result += $(values) ;
269
+ }
270
+ }
271
+ else
272
+ {
273
+ result += $(p:G=) ;
274
+ }
275
+ }
276
+ }
277
+ else
278
+ {
279
+ result += $(value) ;
280
+ }
281
+ return $(result) ;
282
+ }
283
+
284
+
285
+ # Given a rule name and a property set, returns a list of interleaved variables
286
+ # names and values which must be set on targets for that rule/property-set
287
+ # combination.
288
+ #
289
+ rule set-target-variables-aux ( rule-or-module : property-set )
290
+ {
291
+ local result ;
292
+ properties = [ $(property-set).raw ] ;
293
+ for local f in $(.$(rule-or-module).flags)
294
+ {
295
+ local variable = $(.$(rule-or-module).variable.$(f)) ;
296
+ local condition = $(.$(rule-or-module).condition.$(f)) ;
297
+ local values = $(.$(rule-or-module).values.$(f)) ;
298
+
299
+ if ! $(condition) ||
300
+ [ find-property-subset $(condition) : $(properties) ]
301
+ {
302
+ local processed ;
303
+ for local v in $(values)
304
+ {
305
+ # The value might be <feature-name> so needs special treatment.
306
+ processed += [ handle-flag-value $(v) : $(properties) ] ;
307
+ }
308
+ for local r in $(processed)
309
+ {
310
+ result += $(variable) $(r) ;
311
+ }
312
+ }
313
+ }
314
+
315
+ # Strip away last dot separated part and recurse.
316
+ local next = [ MATCH ^(.+)\\.([^\\.])* : $(rule-or-module) ] ;
317
+ if $(next)
318
+ {
319
+ result += [ set-target-variables-aux $(next[1]) : $(property-set) ] ;
320
+ }
321
+ return $(result) ;
322
+ }
323
+
324
+ rule relevant-features ( rule-or-module )
325
+ {
326
+ local result ;
327
+ if ! $(.relevant-features.$(rule-or-module))
328
+ {
329
+ for local f in $(.$(rule-or-module).flags)
330
+ {
331
+ local condition = $(.$(rule-or-module).condition.$(f)) ;
332
+ local values = $(.$(rule-or-module).values.$(f)) ;
333
+
334
+ for local c in $(condition)
335
+ {
336
+ for local p in [ feature.split $(c) ]
337
+ {
338
+ if $(p:G)
339
+ {
340
+ result += $(p:G) ;
341
+ }
342
+ else
343
+ {
344
+ local temp = [ feature.expand-subfeatures $(p) ] ;
345
+ result += $(temp:G) ;
346
+ }
347
+ }
348
+ }
349
+
350
+ for local v in $(values)
351
+ {
352
+ if $(v:G)
353
+ {
354
+ result += $(v:G) ;
355
+ }
356
+ }
357
+ }
358
+
359
+ # Strip away last dot separated part and recurse.
360
+ local next = [ MATCH ^(.+)\\.([^\\.])* : $(rule-or-module) ] ;
361
+ if $(next)
362
+ {
363
+ result += [ relevant-features $(next[1]) ] ;
364
+ }
365
+ result = [ sequence.unique $(result) ] ;
366
+ if $(result[1]) = ""
367
+ {
368
+ result = $(result) ;
369
+ }
370
+ .relevant-features.$(rule-or-module) = $(result) ;
371
+ return $(result) ;
372
+ }
373
+ else
374
+ {
375
+ return $(.relevant-features.$(rule-or-module)) ;
376
+ }
377
+ }
378
+
379
+ rule filter-property-set ( rule-or-module : property-set )
380
+ {
381
+ if ! $(.filtered.property-set.$(rule-or-module).$(property-set))
382
+ {
383
+ local relevant = [ relevant-features $(rule-or-module) ] ;
384
+ local result ;
385
+ for local p in [ $(property-set).raw ]
386
+ {
387
+ if $(p:G) in $(relevant)
388
+ {
389
+ result += $(p) ;
390
+ }
391
+ }
392
+ .filtered.property-set.$(rule-or-module).$(property-set) = [ property-set.create $(result) ] ;
393
+ }
394
+ return $(.filtered.property-set.$(rule-or-module).$(property-set)) ;
395
+ }
396
+
397
+ rule set-target-variables ( rule-or-module targets + : property-set )
398
+ {
399
+ property-set = [ filter-property-set $(rule-or-module) : $(property-set) ] ;
400
+ local key = $(rule-or-module).$(property-set) ;
401
+ local settings = $(.stv.$(key)) ;
402
+ if ! $(settings)
403
+ {
404
+ settings = [ set-target-variables-aux $(rule-or-module) :
405
+ $(property-set) ] ;
406
+
407
+ if ! $(settings)
408
+ {
409
+ settings = none ;
410
+ }
411
+ .stv.$(key) = $(settings) ;
412
+ }
413
+
414
+ if $(settings) != none
415
+ {
416
+ local var-name = ;
417
+ for local name-or-value in $(settings)
418
+ {
419
+ if $(var-name)
420
+ {
421
+ $(var-name) on $(targets) += $(name-or-value) ;
422
+ var-name = ;
423
+ }
424
+ else
425
+ {
426
+ var-name = $(name-or-value) ;
427
+ }
428
+ }
429
+ }
430
+ }
431
+
432
+
433
+ # Make toolset 'toolset', defined in a module of the same name, inherit from
434
+ # 'base'.
435
+ # 1. The 'init' rule from 'base' is imported into 'toolset' with full name.
436
+ # Another 'init' is called, which forwards to the base one.
437
+ # 2. All generators from 'base' are cloned. The ids are adjusted and <toolset>
438
+ # property in requires is adjusted too.
439
+ # 3. All flags are inherited.
440
+ # 4. All rules are imported.
441
+ #
442
+ rule inherit ( toolset : base )
443
+ {
444
+ import $(base) ;
445
+ inherit-generators $(toolset) : $(base) ;
446
+ inherit-flags $(toolset) : $(base) ;
447
+ inherit-rules $(toolset) : $(base) ;
448
+ }
449
+
450
+
451
+ rule inherit-generators ( toolset properties * : base : generators-to-ignore * )
452
+ {
453
+ properties ?= <toolset>$(toolset) ;
454
+ local base-generators = [ generators.generators-for-toolset $(base) ] ;
455
+ for local g in $(base-generators)
456
+ {
457
+ local id = [ $(g).id ] ;
458
+
459
+ if ! $(id) in $(generators-to-ignore)
460
+ {
461
+ # Some generator names have multiple periods in their name, so
462
+ # $(id:B=$(toolset)) does not generate the right new-id name. E.g.
463
+ # if id = gcc.compile.c++ then $(id:B=darwin) = darwin.c++, which is
464
+ # not what we want. Manually parse the base and suffix. If there is
465
+ # a better way to do this, I would love to see it. See also the
466
+ # register() rule in the generators module.
467
+ local base = $(id) ;
468
+ local suffix = "" ;
469
+ while $(base:S)
470
+ {
471
+ suffix = $(base:S)$(suffix) ;
472
+ base = $(base:B) ;
473
+ }
474
+ local new-id = $(toolset)$(suffix) ;
475
+
476
+ generators.register [ $(g).clone $(new-id) : $(properties) ] ;
477
+ }
478
+ }
479
+ }
480
+
481
+
482
+ # Brings all flag definitions from the 'base' toolset into the 'toolset'
483
+ # toolset. Flag definitions whose conditions make use of properties in
484
+ # 'prohibited-properties' are ignored. Do not confuse property and feature, for
485
+ # example <debug-symbols>on and <debug-symbols>off, so blocking one of them does
486
+ # not block the other one.
487
+ #
488
+ # The flag conditions are not altered at all, so if a condition includes a name,
489
+ # or version of a base toolset, it will not ever match the inheriting toolset.
490
+ # When such flag settings must be inherited, define a rule in base toolset
491
+ # module and call it as needed.
492
+ #
493
+ rule inherit-flags ( toolset : base : prohibited-properties * : prohibited-vars * )
494
+ {
495
+ for local f in $(.module-flags.$(base))
496
+ {
497
+ local rule-or-module = $(.rule-or-module.$(f)) ;
498
+ if ( [ set.difference
499
+ $(.$(rule-or-module).condition.$(f)) :
500
+ $(prohibited-properties) ]
501
+ || ! $(.$(rule-or-module).condition.$(f))
502
+ ) && ( ! $(.$(rule-or-module).variable.$(f)) in $(prohibited-vars) )
503
+ {
504
+ local rule_ = [ MATCH "[^.]*\.(.*)" : $(rule-or-module) ] ;
505
+ local new-rule-or-module ;
506
+ if $(rule_)
507
+ {
508
+ new-rule-or-module = $(toolset).$(rule_) ;
509
+ }
510
+ else
511
+ {
512
+ new-rule-or-module = $(toolset) ;
513
+ }
514
+
515
+ add-flag
516
+ $(new-rule-or-module)
517
+ : $(.$(rule-or-module).variable.$(f))
518
+ : $(.$(rule-or-module).condition.$(f))
519
+ : $(.$(rule-or-module).values.$(f)) ;
520
+ }
521
+ }
522
+ }
523
+
524
+
525
+ rule inherit-rules ( toolset : base : localize ? )
526
+ {
527
+ # It appears that "action" creates a local rule.
528
+ local base-generators = [ generators.generators-for-toolset $(base) ] ;
529
+ local rules ;
530
+ for local g in $(base-generators)
531
+ {
532
+ rules += [ MATCH "[^.]*\.(.*)" : [ $(g).rule-name ] ] ;
533
+ }
534
+ rules = [ sequence.unique $(rules) ] ;
535
+ IMPORT $(base) : $(rules) : $(toolset) : $(rules) : $(localize) ;
536
+ IMPORT $(toolset) : $(rules) : : $(toolset).$(rules) ;
537
+ }
538
+
539
+
540
+ # Return the list of global 'toolset requirements'. Those requirements will be
541
+ # automatically added to the requirements of any main target.
542
+ #
543
+ rule requirements ( )
544
+ {
545
+ return $(.requirements) ;
546
+ }
547
+
548
+
549
+ # Adds elements to the list of global 'toolset requirements'. The requirements
550
+ # will be automatically added to the requirements for all main targets, as if
551
+ # they were specified literally. For best results, all requirements added should
552
+ # be conditional or indirect conditional.
553
+ #
554
+ rule add-requirements ( requirements * )
555
+ {
556
+ if ! $(.ignore-requirements)
557
+ {
558
+ .requirements += $(requirements) ;
559
+ }
560
+ }
561
+
562
+
563
+ rule __test__ ( )
564
+ {
565
+ import assert ;
566
+ local p = <b>0 <c>1 <d>2 <e>3 <f>4 ;
567
+ assert.result <c>1/<d>2/<e>3 : find-property-subset <c>1/<d>2/<e>3 <a>0/<b>0/<c>1 <d>2/<e>5 <a>9 : $(p) ;
568
+ assert.result : find-property-subset <a>0/<b>0/<c>9/<d>9/<e>5 <a>9 : $(p) ;
569
+
570
+ local p-set = <a>/<b> <a>0/<b> <a>/<b>1 <a>0/<b>1 ;
571
+ assert.result <a>/<b> : find-property-subset $(p-set) : ;
572
+ assert.result <a>0/<b> : find-property-subset $(p-set) : <a>0 <c>2 ;
573
+ assert.result <a>/<b>1 : find-property-subset $(p-set) : <b>1 <c>2 ;
574
+ assert.result <a>0/<b>1 : find-property-subset $(p-set) : <a>0 <b>1 ;
575
+ }
mosesdecoder/jam-files/boost-build/build/type.jam ADDED
@@ -0,0 +1,425 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2002, 2003 Dave Abrahams
2
+ # Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
3
+ # Distributed under the Boost Software License, Version 1.0.
4
+ # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
5
+
6
+ # Deals with target type declaration and defines target class which supports
7
+ # typed targets.
8
+
9
+ import "class" : new ;
10
+ import errors ;
11
+ import feature ;
12
+ import generators : * ;
13
+ import project ;
14
+ import property ;
15
+ import scanner ;
16
+ import os ;
17
+
18
+ # The following import would create a circular dependency:
19
+ # project -> project-root -> builtin -> type -> targets -> project
20
+ # import targets ;
21
+
22
+ # The feature is optional so it would never get added implicitly. It is used
23
+ # only for internal purposes and in all cases we want to use it explicitly.
24
+ feature.feature target-type : : composite optional ;
25
+
26
+ feature.feature main-target-type : : optional incidental ;
27
+ feature.feature base-target-type : : composite optional free ;
28
+
29
+
30
+ # Registers a target type, possible derived from a 'base-type'. Providing a list
31
+ # of 'suffixes' here is a shortcut for separately calling the register-suffixes
32
+ # rule with the given suffixes and the set-generated-target-suffix rule with the
33
+ # first given suffix.
34
+ #
35
+ rule register ( type : suffixes * : base-type ? )
36
+ {
37
+ # Type names cannot contain hyphens, because when used as feature-values
38
+ # they would be interpreted as composite features which need to be
39
+ # decomposed.
40
+ switch $(type)
41
+ {
42
+ case *-* : errors.error "type name \"$(type)\" contains a hyphen" ;
43
+ }
44
+
45
+ if $(type) in $(.types)
46
+ {
47
+ errors.error "Type $(type) is already registered." ;
48
+ }
49
+ else
50
+ {
51
+ .types += $(type) ;
52
+ .base.$(type) = $(base-type) ;
53
+ .derived.$(base-type) += $(type) ;
54
+
55
+ if $(suffixes)-is-not-empty
56
+ {
57
+ # Specify mapping from suffixes to type.
58
+ register-suffixes $(suffixes) : $(type) ;
59
+ # By default generated targets of 'type' will use the first of
60
+ #'suffixes'. This may be overriden.
61
+ set-generated-target-suffix $(type) : : $(suffixes[1]) ;
62
+ }
63
+
64
+ feature.extend target-type : $(type) ;
65
+ feature.extend main-target-type : $(type) ;
66
+ feature.extend base-target-type : $(type) ;
67
+
68
+ feature.compose <target-type>$(type) : $(base-type:G=<base-target-type>) ;
69
+ feature.compose <base-target-type>$(type) : <base-target-type>$(base-type) ;
70
+
71
+ # We used to declare the main target rule only when a 'main' parameter
72
+ # has been specified. However, it is hard to decide that a type will
73
+ # *never* need a main target rule and so from time to time we needed to
74
+ # make yet another type 'main'. So now a main target rule is defined for
75
+ # each type.
76
+ main-rule-name = [ type-to-rule-name $(type) ] ;
77
+ .main-target-type.$(main-rule-name) = $(type) ;
78
+ IMPORT $(__name__) : main-target-rule : : $(main-rule-name) ;
79
+
80
+ # Adding a new derived type affects generator selection so we need to
81
+ # make the generator selection module update any of its cached
82
+ # information related to a new derived type being defined.
83
+ generators.update-cached-information-with-a-new-type $(type) ;
84
+ }
85
+ }
86
+
87
+
88
+ # Given a type, returns the name of the main target rule which creates targets
89
+ # of that type.
90
+ #
91
+ rule type-to-rule-name ( type )
92
+ {
93
+ # Lowercase everything. Convert underscores to dashes.
94
+ import regex ;
95
+ local n = [ regex.split $(type:L) "_" ] ;
96
+ return $(n:J=-) ;
97
+ }
98
+
99
+
100
+ # Given a main target rule name, returns the type for which it creates targets.
101
+ #
102
+ rule type-from-rule-name ( rule-name )
103
+ {
104
+ return $(.main-target-type.$(rule-name)) ;
105
+ }
106
+
107
+
108
+ # Specifies that files with suffix from 'suffixes' be recognized as targets of
109
+ # type 'type'. Issues an error if a different type is already specified for any
110
+ # of the suffixes.
111
+ #
112
+ rule register-suffixes ( suffixes + : type )
113
+ {
114
+ for local s in $(suffixes)
115
+ {
116
+ if ! $(.type.$(s))
117
+ {
118
+ .type.$(s) = $(type) ;
119
+ }
120
+ else if $(.type.$(s)) != $(type)
121
+ {
122
+ errors.error Attempting to specify multiple types for suffix
123
+ \"$(s)\" : "Old type $(.type.$(s)), New type $(type)" ;
124
+ }
125
+ }
126
+ }
127
+
128
+
129
+ # Returns true iff type has been registered.
130
+ #
131
+ rule registered ( type )
132
+ {
133
+ if $(type) in $(.types)
134
+ {
135
+ return true ;
136
+ }
137
+ }
138
+
139
+
140
+ # Issues an error if 'type' is unknown.
141
+ #
142
+ rule validate ( type )
143
+ {
144
+ if ! [ registered $(type) ]
145
+ {
146
+ errors.error "Unknown target type $(type)" ;
147
+ }
148
+ }
149
+
150
+
151
+ # Sets a scanner class that will be used for this 'type'.
152
+ #
153
+ rule set-scanner ( type : scanner )
154
+ {
155
+ validate $(type) ;
156
+ .scanner.$(type) = $(scanner) ;
157
+ }
158
+
159
+
160
+ # Returns a scanner instance appropriate to 'type' and 'properties'.
161
+ #
162
+ rule get-scanner ( type : property-set )
163
+ {
164
+ if $(.scanner.$(type))
165
+ {
166
+ return [ scanner.get $(.scanner.$(type)) : $(property-set) ] ;
167
+ }
168
+ }
169
+
170
+
171
+ # Returns a base type for the given type or nothing in case the given type is
172
+ # not derived.
173
+ #
174
+ rule base ( type )
175
+ {
176
+ return $(.base.$(type)) ;
177
+ }
178
+
179
+
180
+ # Returns the given type and all of its base types in order of their distance
181
+ # from type.
182
+ #
183
+ rule all-bases ( type )
184
+ {
185
+ local result = $(type) ;
186
+ while $(type)
187
+ {
188
+ type = [ base $(type) ] ;
189
+ result += $(type) ;
190
+ }
191
+ return $(result) ;
192
+ }
193
+
194
+
195
+ # Returns the given type and all of its derived types in order of their distance
196
+ # from type.
197
+ #
198
+ rule all-derived ( type )
199
+ {
200
+ local result = $(type) ;
201
+ for local d in $(.derived.$(type))
202
+ {
203
+ result += [ all-derived $(d) ] ;
204
+ }
205
+ return $(result) ;
206
+ }
207
+
208
+
209
+ # Returns true if 'type' is equal to 'base' or has 'base' as its direct or
210
+ # indirect base.
211
+ #
212
+ rule is-derived ( type base )
213
+ {
214
+ if $(base) in [ all-bases $(type) ]
215
+ {
216
+ return true ;
217
+ }
218
+ }
219
+
220
+ # Returns true if 'type' is either derived from or is equal to 'base'.
221
+ #
222
+ # TODO: It might be that is-derived and is-subtype were meant to be different
223
+ # rules - one returning true for type = base and one not, but as currently
224
+ # implemented they are actually the same. Clean this up.
225
+ #
226
+ rule is-subtype ( type base )
227
+ {
228
+ return [ is-derived $(type) $(base) ] ;
229
+ }
230
+
231
+
232
+ # Store suffixes for generated targets.
233
+ .suffixes = [ new property-map ] ;
234
+
235
+ # Store prefixes for generated targets (e.g. "lib" for library).
236
+ .prefixes = [ new property-map ] ;
237
+
238
+
239
+ # Sets a file suffix to be used when generating a target of 'type' with the
240
+ # specified properties. Can be called with no properties if no suffix has
241
+ # already been specified for the 'type'. The 'suffix' parameter can be an empty
242
+ # string ("") to indicate that no suffix should be used.
243
+ #
244
+ # Note that this does not cause files with 'suffix' to be automatically
245
+ # recognized as being of 'type'. Two different types can use the same suffix for
246
+ # their generated files but only one type can be auto-detected for a file with
247
+ # that suffix. User should explicitly specify which one using the
248
+ # register-suffixes rule.
249
+ #
250
+ rule set-generated-target-suffix ( type : properties * : suffix )
251
+ {
252
+ set-generated-target-ps suffix : $(type) : $(properties) : $(suffix) ;
253
+ }
254
+
255
+
256
+ # Change the suffix previously registered for this type/properties combination.
257
+ # If suffix is not yet specified, sets it.
258
+ #
259
+ rule change-generated-target-suffix ( type : properties * : suffix )
260
+ {
261
+ change-generated-target-ps suffix : $(type) : $(properties) : $(suffix) ;
262
+ }
263
+
264
+
265
+ # Returns the suffix used when generating a file of 'type' with the given
266
+ # properties.
267
+ #
268
+ rule generated-target-suffix ( type : property-set )
269
+ {
270
+ return [ generated-target-ps suffix : $(type) : $(property-set) ] ;
271
+ }
272
+
273
+
274
+ # Sets a target prefix that should be used when generating targets of 'type'
275
+ # with the specified properties. Can be called with empty properties if no
276
+ # prefix for 'type' has been specified yet.
277
+ #
278
+ # The 'prefix' parameter can be empty string ("") to indicate that no prefix
279
+ # should be used.
280
+ #
281
+ # Usage example: library names use the "lib" prefix on unix.
282
+ #
283
+ rule set-generated-target-prefix ( type : properties * : prefix )
284
+ {
285
+ set-generated-target-ps prefix : $(type) : $(properties) : $(prefix) ;
286
+ }
287
+
288
+
289
+ # Change the prefix previously registered for this type/properties combination.
290
+ # If prefix is not yet specified, sets it.
291
+ #
292
+ rule change-generated-target-prefix ( type : properties * : prefix )
293
+ {
294
+ change-generated-target-ps prefix : $(type) : $(properties) : $(prefix) ;
295
+ }
296
+
297
+
298
+ rule generated-target-prefix ( type : property-set )
299
+ {
300
+ return [ generated-target-ps prefix : $(type) : $(property-set) ] ;
301
+ }
302
+
303
+
304
+ # Common rules for prefix/suffix provisioning follow.
305
+
306
+ local rule set-generated-target-ps ( ps : type : properties * : psval )
307
+ {
308
+ properties = <target-type>$(type) $(properties) ;
309
+ $(.$(ps)es).insert $(properties) : $(psval) ;
310
+ }
311
+
312
+
313
+ local rule change-generated-target-ps ( ps : type : properties * : psval )
314
+ {
315
+ properties = <target-type>$(type) $(properties) ;
316
+ local prev = [ $(.$(ps)es).find-replace $(properties) : $(psval) ] ;
317
+ if ! $(prev)
318
+ {
319
+ set-generated-target-ps $(ps) : $(type) : $(properties) : $(psval) ;
320
+ }
321
+ }
322
+
323
+
324
+ # Returns either prefix or suffix (as indicated by 'ps') that should be used
325
+ # when generating a target of 'type' with the specified properties. Parameter
326
+ # 'ps' can be either "prefix" or "suffix". If no prefix/suffix is specified for
327
+ # 'type', returns prefix/suffix for base type, if any.
328
+ #
329
+ local rule generated-target-ps-real ( ps : type : properties * )
330
+ {
331
+ local result ;
332
+ local found ;
333
+ while $(type) && ! $(found)
334
+ {
335
+ result = [ $(.$(ps)es).find <target-type>$(type) $(properties) ] ;
336
+ # If the prefix/suffix is explicitly set to an empty string, we consider
337
+ # prefix/suffix to be found. If we were not to compare with "", there
338
+ # would be no way to specify an empty prefix/suffix.
339
+ if $(result)-is-not-empty
340
+ {
341
+ found = true ;
342
+ }
343
+ type = $(.base.$(type)) ;
344
+ }
345
+ if $(result) = ""
346
+ {
347
+ result = ;
348
+ }
349
+ return $(result) ;
350
+ }
351
+
352
+
353
+ local rule generated-target-ps ( ps : type : property-set )
354
+ {
355
+ local key = .$(ps).$(type).$(property-set) ;
356
+ local v = $($(key)) ;
357
+ if ! $(v)
358
+ {
359
+ v = [ generated-target-ps-real $(ps) : $(type) : [ $(property-set).raw ]
360
+ ] ;
361
+ if ! $(v)
362
+ {
363
+ v = none ;
364
+ }
365
+ $(key) = $(v) ;
366
+ }
367
+
368
+ if $(v) != none
369
+ {
370
+ return $(v) ;
371
+ }
372
+ }
373
+
374
+
375
+ # Returns file type given its name. If there are several dots in filename, tries
376
+ # each suffix. E.g. for name of "file.so.1.2" suffixes "2", "1", and "so" will
377
+ # be tried.
378
+ #
379
+ rule type ( filename )
380
+ {
381
+ if [ os.name ] in NT CYGWIN
382
+ {
383
+ filename = $(filename:L) ;
384
+ }
385
+ local type ;
386
+ while ! $(type) && $(filename:S)
387
+ {
388
+ local suffix = $(filename:S) ;
389
+ type = $(.type$(suffix)) ;
390
+ filename = $(filename:S=) ;
391
+ }
392
+ return $(type) ;
393
+ }
394
+
395
+
396
+ # Rule used to construct all main targets. Note that this rule gets imported
397
+ # into the global namespace under different alias names and the exact target
398
+ # type to construct is selected based on the alias used to actually invoke this
399
+ # rule.
400
+ #
401
+ rule main-target-rule ( name : sources * : requirements * : default-build * :
402
+ usage-requirements * )
403
+ {
404
+ # First discover the required target type based on the exact alias used to
405
+ # invoke this rule.
406
+ local bt = [ BACKTRACE 1 ] ;
407
+ local rulename = $(bt[4]) ;
408
+ local target-type = [ type-from-rule-name $(rulename) ] ;
409
+
410
+ # This is a circular module dependency and so must be imported here.
411
+ import targets ;
412
+
413
+ return [ targets.create-typed-target $(target-type) : [ project.current ] :
414
+ $(name) : $(sources) : $(requirements) : $(default-build) :
415
+ $(usage-requirements) ] ;
416
+ }
417
+
418
+
419
+ rule __test__ ( )
420
+ {
421
+ import assert ;
422
+
423
+ # TODO: Add tests for all the is-derived, is-base & related type relation
424
+ # checking rules.
425
+ }
mosesdecoder/jam-files/engine/boehm_gc/NT_X64_STATIC_THREADS_MAKEFILE ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Makefile for Windows NT. Assumes Microsoft compiler.
2
+ # DLLs are included in the root set under NT, but not under win32S.
3
+ # Use "nmake nodebug=1 all" for optimized versions of library, gctest and editor.
4
+
5
+ MY_CPU=AMD64
6
+ CPU=$(MY_CPU)
7
+ !include <ntwin32.mak>
8
+
9
+ # Make sure that .cc is not viewed as a suffix. It is for VC++2005, but
10
+ # not earlier versions. We can deal with either, but not inconsistency.
11
+ .SUFFIXES:
12
+ .SUFFIXES: .obj .cpp .c
13
+
14
+ # Atomic_ops installation directory. For win32, the source directory
15
+ # should do, since we only need the headers.
16
+ # We assume this was manually unpacked, since I'm not sure there is
17
+ # a Windows standard command line tool to do this.
18
+ AO_VERSION=1.2
19
+ AO_SRC_DIR=libatomic_ops-$(AO_VERSION)/src
20
+ AO_INCLUDE_DIR=$(AO_SRC_DIR)
21
+
22
+ 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 stubborn.obj dyn_load.obj typd_mlc.obj ptr_chck.obj gc_cpp.obj mallocx.obj win32_threads.obj msvc_dbg.obj thread_local_alloc.obj
23
+
24
+ all: gctest.exe cord\de.exe test_cpp.exe
25
+
26
+ .c.obj:
27
+ $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -D__STDC__ -DGC_NOT_DLL -DGC_WIN32_THREADS -DTHREAD_LOCAL_ALLOC $*.c /Fo$*.obj /wd4701 -D_CRT_SECURE_NO_DEPRECATE
28
+ # Disable "may not be initialized" warnings. They're too approximate.
29
+ # Disable crt security warnings, since unfortunately they warn about all sorts
30
+ # of safe uses of strncpy. It would be nice to leave the rest enabled.
31
+
32
+ .cpp.obj:
33
+ $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DGC_NOT_DLL $*.CPP -DGC_WIN32_THREADS -DTHREAD_LOCAL_ALLOC /Fo$*.obj -D_CRT_SECURE_NO_DEPRECATE
34
+
35
+ $(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_mark.h include\private\msvc_dbg.h
36
+
37
+ gc.lib: $(OBJS)
38
+ lib /MACHINE:X64 /out:gc.lib $(OBJS)
39
+
40
+ gctest.exe: tests\test.obj gc.lib
41
+ # This produces a "GUI" applications that opens no windows and writes to the log file
42
+ # "gc.log". This was done to make the result runnable under win32s and
43
+ # should be fixed.
44
+ $(link) $(ldebug) $(guiflags) -stack:131072 -out:$*.exe tests\test.obj $(guilibs) gc.lib
45
+
46
+ cord\de_win.rbj: cord\de_win.res
47
+ cvtres /MACHINE:$(MY_CPU) /OUT:cord\de_win.rbj cord\de_win.res
48
+
49
+ cord\de.obj cord\de_win.obj: include\cord.h include\private\cord_pos.h cord\de_win.h cord\de_cmds.h
50
+
51
+ cord\de_win.res: cord\de_win.rc cord\de_win.h cord\de_cmds.h
52
+ $(rc) $(rcvars) -r -fo cord\de_win.res cord\de_win.rc
53
+
54
+ # Cord/de is a real win32 gui application.
55
+ cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj cord\de_win.rbj gc.lib
56
+ $(link) $(ldebug) $(guiflags) -stack:16384 -out:cord\de.exe cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj cord\de_win.rbj gc.lib $(guilibs)
57
+
58
+ gc_cpp.obj: include\gc_cpp.h include\gc.h
59
+
60
+ gc_cpp.cpp: gc_cpp.cc
61
+ copy gc_cpp.cc gc_cpp.cpp
62
+
63
+ test_cpp.cpp: tests\test_cpp.cc
64
+ copy tests\test_cpp.cc test_cpp.cpp
65
+
66
+ # This generates the C++ test executable. The executable expects
67
+ # a single numeric argument, which is the number of iterations.
68
+ # The output appears in the file "gc.log".
69
+ test_cpp.exe: test_cpp.obj include\gc_cpp.h include\gc.h gc.lib
70
+ $(link) $(ldebug) $(guiflags) -stack:16384 -out:test_cpp.exe test_cpp.obj gc.lib $(guilibs)
71
+
72
+ AO_SCR_DIR:
73
+ tar xvfz $(AO_SRC_DIR).tar.gz;
74
+
mosesdecoder/jam-files/engine/boehm_gc/SMakefile.amiga ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # Rewritten smakefile for amiga / sas/c. -Kjetil M.
3
+ # Dont use the cord-package if you define parm=both or parm=reg.
4
+
5
+
6
+ #----------------TOOLS--------------------------------
7
+ CC=sc
8
+ LINKER=slink
9
+ LIBER=oml
10
+
11
+ #----------------CPU OPTIONS--------------------------
12
+
13
+ CPU=68060
14
+
15
+ #----------------FPU OPTIONS--------------------------
16
+
17
+ MATH=8
18
+ MATHLIB=LIB:scm881.lib
19
+
20
+ #----------------COMPILER OPTIONS---------------------
21
+
22
+ IGNORE= IGNORE=85 IGNORE=154 IGNORE=161 IGNORE=100
23
+
24
+ OPTIMIZE=optimize optimizetime optglobal optimizerdepth=100 optimizerpeephole optloop OPTSCHED optimizerinlocal optimizerrecurdepth=100
25
+ # optimizerinline optimizercomplexity=100
26
+
27
+ OPT= $(OPTIMIZE) CPU=$(CPU) math=$(MATH) NOSTACKCHECK VERBOSE \
28
+ MAPHUNK NOVERSION NOICONS nodebug \
29
+ parm=reg \
30
+ DEFINE __USE_SYSBASE
31
+
32
+
33
+ SOPT= $(OPT) $(IGNORE) \
34
+ DEFINE AMIGA_SKIP_SEG \
35
+ DEFINE ATOMIC_UNCOLLECTABLE \
36
+ DEFINE GC_AMIGA_FASTALLOC \
37
+ DEFINE GC_AMIGA_RETRY \
38
+ DEFINE GC_AMIGA_PRINTSTATS \
39
+ DEFINE GC_AMIGA_GC
40
+
41
+
42
+ #DEFINE ALL_INTERIOR_POINTERS \
43
+
44
+
45
+ SCOPT= $(SOPT) define GC_AMIGA_MAKINGLIB
46
+
47
+ CSCOPT= $(OPT) DEFINE AMIGA IGNORE=100 IGNORE=161
48
+
49
+ #------------------LINKING----------------------------
50
+
51
+
52
+ all: gctest setjmp_t cord/cordtest
53
+
54
+ clean:
55
+ delete *.lib gctest setjmp_t *.o *.lnk cord/*.o cord/*.lib cord/*.lnk cord/cordtest
56
+ smake
57
+
58
+ test: setjmp_t gctest cord/cordtest
59
+ setjmp_t
60
+ gctest
61
+ cord/cordtest
62
+
63
+ gctest: gc$(CPU).lib GCAmigaOS$(CPU).lib test.o
64
+ $(LINKER) LIB:c.o test.o TO gctest LIB gc$(CPU).lib LIB:sc.lib $(MATHLIB)
65
+
66
+ setjmp_t: setjmp_t.o gc.h
67
+ $(LINKER) LIB:c.o setjmp_t.o to setjmp_t lib LIB:sc.lib
68
+
69
+ cord/cordtest: cord/cordtest.o cord/cord$(CPU).lib gc$(CPU).lib
70
+ slink LIB:c.o cord/cordtest.o LIB $(MATHLIB) gc$(CPU).lib cord/cord$(CPU).lib LIB:sc.lib TO cord/cordtest
71
+
72
+
73
+ #------------------LIBBING----------------------------
74
+
75
+ 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 real_malloc.o dyn_load.o dbg_mlc.o malloc.o stubborn.o checksums.o typd_mlc.o ptr_chck.o mallocx.o
76
+
77
+ gc$(CPU).lib: $(OBJS)
78
+ $(LIBER) gc$(CPU).lib r $(OBJS)
79
+
80
+
81
+ COBJS = cord/cordbscs.o cord/cordprnt.o cord/cordxtra.o
82
+
83
+ cord/cord$(CPU).lib: $(COBJS)
84
+ oml cord/cord$(CPU).lib r $(COBJS)
85
+
86
+ #------------------COMPILING--------------------------
87
+
88
+ INC= gc_private.h gc_hdrs.h gc.h gcconfig.h
89
+
90
+ alloc.o : alloc.c $(INC)
91
+ $(CC) alloc.c $(SCOPT) ignore=7
92
+
93
+ reclaim.o : reclaim.c $(INC)
94
+ $(CC) reclaim.c $(SCOPT)
95
+
96
+ allchblk.o : allchblk.c $(INC)
97
+ $(CC) allchblk.c $(SCOPT)
98
+
99
+ misc.o : misc.c $(INC)
100
+ $(CC) misc.c $(SCOPT)
101
+
102
+ os_dep.o : os_dep.c $(INC) AmigaOS.c
103
+ $(CC) os_dep.c $(SCOPT)
104
+
105
+ mark_rts.o : mark_rts.c $(INC)
106
+ $(CC) mark_rts.c $(SCOPT)
107
+
108
+ headers.o : headers.c $(INC)
109
+ $(CC) headers.c $(SCOPT)
110
+
111
+ mark.o : mark.c $(INC)
112
+ $(CC) mark.c $(SCOPT)
113
+
114
+ obj_map.o : obj_map.c $(INC)
115
+ $(CC) obj_map.c $(SCOPT)
116
+
117
+ blacklst.o : blacklst.c $(INC)
118
+ $(CC) blacklst.c $(SCOPT)
119
+
120
+ finalize.o : finalize.c $(INC)
121
+ $(CC) finalize.c $(SCOPT) noopt #Could sas/c still have problems with this one? Gctest sometimes fails to finalize all.
122
+
123
+ new_hblk.o : new_hblk.c $(INC)
124
+ $(CC) new_hblk.c $(SCOPT)
125
+
126
+ real_malloc.o : real_malloc.c $(INC)
127
+ $(CC) real_malloc.c $(SCOPT)
128
+
129
+ dyn_load.o : dyn_load.c $(INC)
130
+ $(CC) dyn_load.c $(SCOPT)
131
+
132
+ dbg_mlc.o : dbg_mlc.c $(INC)
133
+ $(CC) dbg_mlc.c $(SCOPT)
134
+
135
+ malloc.o : malloc.c $(INC)
136
+ $(CC) malloc.c $(SCOPT)
137
+
138
+ mallocx.o : mallocx.c $(INC)
139
+ $(CC) mallocx.c $(SCOPT)
140
+
141
+ stubborn.o : stubborn.c $(INC)
142
+ $(CC) stubborn.c $(SCOPT)
143
+
144
+ checksums.o : checksums.c $(INC)
145
+ $(CC) checksums.c $(SCOPT)
146
+
147
+ typd_mlc.o: typd_mlc.c $(INC)
148
+ $(CC) typd_mlc.c $(SCOPT)
149
+
150
+ mach_dep.o : mach_dep.c $(INC)
151
+ $(CC) mach_dep.c $(SCOPT)
152
+
153
+ ptr_chck.o: ptr_chck.c $(INC)
154
+ $(CC) ptr_chck.c $(SCOPT)
155
+
156
+ test.o : test.c $(INC)
157
+ $(CC) test.c $(SOPT)
158
+
159
+ setjmp_t: setjmp_t.c gc.h
160
+ $(CC) setjmp_t.c $(SOPT)
161
+
162
+
163
+ # cords:
164
+
165
+ cord/cordbscs.o: cord/cordbscs.c
166
+ sc cord/cordbscs.c $(CSCOPT)
167
+
168
+ cord/cordprnt.o: cord/cordprnt.c
169
+ sc cord/cordprnt.c $(CSCOPT)
170
+
171
+ cord/cordxtra.o: cord/cordxtra.c
172
+ sc cord/cordxtra.c $(CSCOPT)
173
+
174
+ cord/cordtest.o: cord/cordtest.c
175
+ sc cord/cordtest.c $(CSCOPT)
176
+
177
+
mosesdecoder/jam-files/engine/boehm_gc/alpha_mach_dep.S ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .arch ev6
2
+
3
+ .text
4
+ .align 4
5
+ .globl GC_push_regs
6
+ .ent GC_push_regs 2
7
+ GC_push_regs:
8
+ ldgp $gp, 0($27)
9
+ lda $sp, -16($sp)
10
+ stq $26, 0($sp)
11
+ .mask 0x04000000, 0
12
+ .frame $sp, 16, $26, 0
13
+
14
+ /* $0 integer result */
15
+ /* $1-$8 temp regs - not preserved cross calls */
16
+ /* $9-$15 call saved regs */
17
+ /* $16-$21 argument regs - not preserved cross calls */
18
+ /* $22-$28 temp regs - not preserved cross calls */
19
+ /* $29 global pointer - not preserved cross calls */
20
+ /* $30 stack pointer */
21
+
22
+ # define call_push(x) \
23
+ mov x, $16; \
24
+ jsr $26, GC_push_one; \
25
+ ldgp $gp, 0($26)
26
+
27
+ call_push($9)
28
+ call_push($10)
29
+ call_push($11)
30
+ call_push($12)
31
+ call_push($13)
32
+ call_push($14)
33
+ call_push($15)
34
+
35
+ /* $f0-$f1 floating point results */
36
+ /* $f2-$f9 call saved regs */
37
+ /* $f10-$f30 temp regs - not preserved cross calls */
38
+
39
+ /* Use the most efficient transfer method for this hardware. */
40
+ /* Bit 1 detects the FIX extension, which includes ftoit. */
41
+ amask 2, $0
42
+ bne $0, $use_stack
43
+
44
+ #undef call_push
45
+ #define call_push(x) \
46
+ ftoit x, $16; \
47
+ jsr $26, GC_push_one; \
48
+ ldgp $gp, 0($26)
49
+
50
+ call_push($f2)
51
+ call_push($f3)
52
+ call_push($f4)
53
+ call_push($f5)
54
+ call_push($f6)
55
+ call_push($f7)
56
+ call_push($f8)
57
+ call_push($f9)
58
+
59
+ ldq $26, 0($sp)
60
+ lda $sp, 16($sp)
61
+ ret $31, ($26), 1
62
+
63
+ .align 4
64
+ $use_stack:
65
+
66
+ #undef call_push
67
+ #define call_push(x) \
68
+ stt x, 8($sp); \
69
+ ldq $16, 8($sp); \
70
+ jsr $26, GC_push_one; \
71
+ ldgp $gp, 0($26)
72
+
73
+ call_push($f2)
74
+ call_push($f3)
75
+ call_push($f4)
76
+ call_push($f5)
77
+ call_push($f6)
78
+ call_push($f7)
79
+ call_push($f8)
80
+ call_push($f9)
81
+
82
+ ldq $26, 0($sp)
83
+ lda $sp, 16($sp)
84
+ ret $31, ($26), 1
85
+
86
+ .end GC_push_regs
mosesdecoder/jam-files/engine/boehm_gc/backgraph.c ADDED
@@ -0,0 +1,469 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright (c) 2001 by Hewlett-Packard Company. All rights reserved.
3
+ *
4
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
6
+ *
7
+ * Permission is hereby granted to use or copy this program
8
+ * for any purpose, provided the above notices are retained on all copies.
9
+ * Permission to modify the code and to distribute modified code is granted,
10
+ * provided the above notices are retained, and a notice that the code was
11
+ * modified is included with the above copyright notice.
12
+ *
13
+ */
14
+
15
+ /*
16
+ * This implements a full, though not well-tuned, representation of the
17
+ * backwards points-to graph. This is used to test for non-GC-robust
18
+ * data structures; the code is not used during normal garbage collection.
19
+ *
20
+ * One restriction is that we drop all back-edges from nodes with very
21
+ * high in-degree, and simply add them add them to a list of such
22
+ * nodes. They are then treated as permanent roots. Id this by itself
23
+ * doesn't introduce a space leak, then such nodes can't contribute to
24
+ * a growing space leak.
25
+ */
26
+
27
+ #ifdef MAKE_BACK_GRAPH
28
+
29
+ #define MAX_IN 10 /* Maximum in-degree we handle directly */
30
+
31
+ #include "private/dbg_mlc.h"
32
+ #include <unistd.h>
33
+
34
+ #if !defined(DBG_HDRS_ALL) || (ALIGNMENT != CPP_WORDSZ/8) || !defined(UNIX_LIKE)
35
+ # error Configuration doesnt support MAKE_BACK_GRAPH
36
+ #endif
37
+
38
+ /* We store single back pointers directly in the object's oh_bg_ptr field. */
39
+ /* If there is more than one ptr to an object, we store q | FLAG_MANY, */
40
+ /* where q is a pointer to a back_edges object. */
41
+ /* Every once in a while we use a back_edges object even for a single */
42
+ /* pointer, since we need the other fields in the back_edges structure to */
43
+ /* be present in some fraction of the objects. Otherwise we get serious */
44
+ /* performance issues. */
45
+ #define FLAG_MANY 2
46
+
47
+ typedef struct back_edges_struct {
48
+ word n_edges; /* Number of edges, including those in continuation */
49
+ /* structures. */
50
+ unsigned short flags;
51
+ # define RETAIN 1 /* Directly points to a reachable object; */
52
+ /* retain for next GC. */
53
+ unsigned short height_gc_no;
54
+ /* If height > 0, then the GC_gc_no value when it */
55
+ /* was computed. If it was computed this cycle, then */
56
+ /* it is current. If it was computed during the */
57
+ /* last cycle, then it represents the old height, */
58
+ /* which is only saved for live objects referenced by */
59
+ /* dead ones. This may grow due to refs from newly */
60
+ /* dead objects. */
61
+ signed_word height;
62
+ /* Longest path through unreachable nodes to this node */
63
+ /* that we found using depth first search. */
64
+
65
+ # define HEIGHT_UNKNOWN ((signed_word)(-2))
66
+ # define HEIGHT_IN_PROGRESS ((signed_word)(-1))
67
+ ptr_t edges[MAX_IN];
68
+ struct back_edges_struct *cont;
69
+ /* Pointer to continuation structure; we use only the */
70
+ /* edges field in the continuation. */
71
+ /* also used as free list link. */
72
+ } back_edges;
73
+
74
+ /* Allocate a new back edge structure. Should be more sophisticated */
75
+ /* if this were production code. */
76
+ #define MAX_BACK_EDGE_STRUCTS 100000
77
+ static back_edges *back_edge_space = 0;
78
+ int GC_n_back_edge_structs = 0; /* Serves as pointer to never used */
79
+ /* back_edges space. */
80
+ static back_edges *avail_back_edges = 0;
81
+ /* Pointer to free list of deallocated */
82
+ /* back_edges structures. */
83
+
84
+ static back_edges * new_back_edges(void)
85
+ {
86
+ if (0 == back_edge_space) {
87
+ back_edge_space = (back_edges *)
88
+ GET_MEM(MAX_BACK_EDGE_STRUCTS*sizeof(back_edges));
89
+ }
90
+ if (0 != avail_back_edges) {
91
+ back_edges * result = avail_back_edges;
92
+ avail_back_edges = result -> cont;
93
+ result -> cont = 0;
94
+ return result;
95
+ }
96
+ if (GC_n_back_edge_structs >= MAX_BACK_EDGE_STRUCTS - 1) {
97
+ ABORT("needed too much space for back edges: adjust "
98
+ "MAX_BACK_EDGE_STRUCTS");
99
+ }
100
+ return back_edge_space + (GC_n_back_edge_structs++);
101
+ }
102
+
103
+ /* Deallocate p and its associated continuation structures. */
104
+ static void deallocate_back_edges(back_edges *p)
105
+ {
106
+ back_edges *last = p;
107
+
108
+ while (0 != last -> cont) last = last -> cont;
109
+ last -> cont = avail_back_edges;
110
+ avail_back_edges = p;
111
+ }
112
+
113
+ /* Table of objects that are currently on the depth-first search */
114
+ /* stack. Only objects with in-degree one are in this table. */
115
+ /* Other objects are identified using HEIGHT_IN_PROGRESS. */
116
+ /* FIXME: This data structure NEEDS IMPROVEMENT. */
117
+ #define INITIAL_IN_PROGRESS 10000
118
+ static ptr_t * in_progress_space = 0;
119
+ static size_t in_progress_size = 0;
120
+ static size_t n_in_progress = 0;
121
+
122
+ static void push_in_progress(ptr_t p)
123
+ {
124
+ if (n_in_progress >= in_progress_size)
125
+ if (in_progress_size == 0) {
126
+ in_progress_size = INITIAL_IN_PROGRESS;
127
+ in_progress_space = (ptr_t *)GET_MEM(in_progress_size * sizeof(ptr_t));
128
+ } else {
129
+ ptr_t * new_in_progress_space;
130
+ in_progress_size *= 2;
131
+ new_in_progress_space = (ptr_t *)
132
+ GET_MEM(in_progress_size * sizeof(ptr_t));
133
+ BCOPY(in_progress_space, new_in_progress_space,
134
+ n_in_progress * sizeof(ptr_t));
135
+ in_progress_space = new_in_progress_space;
136
+ /* FIXME: This just drops the old space. */
137
+ }
138
+ if (in_progress_space == 0)
139
+ ABORT("MAKE_BACK_GRAPH: Out of in-progress space: "
140
+ "Huge linear data structure?");
141
+ in_progress_space[n_in_progress++] = p;
142
+ }
143
+
144
+ static GC_bool is_in_progress(ptr_t p)
145
+ {
146
+ int i;
147
+ for (i = 0; i < n_in_progress; ++i) {
148
+ if (in_progress_space[i] == p) return TRUE;
149
+ }
150
+ return FALSE;
151
+ }
152
+
153
+ static void pop_in_progress(ptr_t p)
154
+ {
155
+ --n_in_progress;
156
+ GC_ASSERT(in_progress_space[n_in_progress] == p);
157
+ }
158
+
159
+ #define GET_OH_BG_PTR(p) \
160
+ (ptr_t)REVEAL_POINTER(((oh *)(p)) -> oh_bg_ptr)
161
+ #define SET_OH_BG_PTR(p,q) (((oh *)(p)) -> oh_bg_ptr) = HIDE_POINTER(q)
162
+
163
+ /* Execute s once for each predecessor q of p in the points-to graph. */
164
+ /* s should be a bracketed statement. We declare q. */
165
+ #define FOR_EACH_PRED(q, p, s) \
166
+ { \
167
+ ptr_t q = GET_OH_BG_PTR(p); \
168
+ if (!((word)q & FLAG_MANY)) { \
169
+ if (q && !((word)q & 1)) s \
170
+ /* !((word)q & 1) checks for a misnterpreted freelist link */ \
171
+ } else { \
172
+ back_edges *orig_be_ = (back_edges *)((word)q & ~FLAG_MANY); \
173
+ back_edges *be_ = orig_be_; \
174
+ int total_, local_; \
175
+ int n_edges_ = be_ -> n_edges; \
176
+ for (total_ = 0, local_ = 0; total_ < n_edges_; ++local_, ++total_) { \
177
+ if (local_ == MAX_IN) { \
178
+ be_ = be_ -> cont; \
179
+ local_ = 0; \
180
+ } \
181
+ q = be_ -> edges[local_]; s \
182
+ } \
183
+ } \
184
+ }
185
+
186
+ /* Ensure that p has a back_edges structure associated with it. */
187
+ static void ensure_struct(ptr_t p)
188
+ {
189
+ ptr_t old_back_ptr = GET_OH_BG_PTR(p);
190
+
191
+ if (!((word)old_back_ptr & FLAG_MANY)) {
192
+ back_edges *be = new_back_edges();
193
+ be -> flags = 0;
194
+ if (0 == old_back_ptr) {
195
+ be -> n_edges = 0;
196
+ } else {
197
+ be -> n_edges = 1;
198
+ be -> edges[0] = old_back_ptr;
199
+ }
200
+ be -> height = HEIGHT_UNKNOWN;
201
+ be -> height_gc_no = GC_gc_no - 1;
202
+ GC_ASSERT(be >= back_edge_space);
203
+ SET_OH_BG_PTR(p, (word)be | FLAG_MANY);
204
+ }
205
+ }
206
+
207
+ /* Add the (forward) edge from p to q to the backward graph. Both p */
208
+ /* q are pointers to the object base, i.e. pointers to an oh. */
209
+ static void add_edge(ptr_t p, ptr_t q)
210
+ {
211
+ ptr_t old_back_ptr = GET_OH_BG_PTR(q);
212
+ back_edges * be, *be_cont;
213
+ word i;
214
+ static unsigned random_number = 13;
215
+ # define GOT_LUCKY_NUMBER (((++random_number) & 0x7f) == 0)
216
+ /* A not very random number we use to occasionally allocate a */
217
+ /* back_edges structure even for a single backward edge. This */
218
+ /* prevents us from repeatedly tracing back through very long */
219
+ /* chains, since we will have some place to store height and */
220
+ /* in_progress flags along the way. */
221
+
222
+ GC_ASSERT(p == GC_base(p) && q == GC_base(q));
223
+ if (!GC_HAS_DEBUG_INFO(q) || !GC_HAS_DEBUG_INFO(p)) {
224
+ /* This is really a misinterpreted free list link, since we saw */
225
+ /* a pointer to a free list. Dont overwrite it! */
226
+ return;
227
+ }
228
+ if (0 == old_back_ptr) {
229
+ SET_OH_BG_PTR(q, p);
230
+ if (GOT_LUCKY_NUMBER) ensure_struct(q);
231
+ return;
232
+ }
233
+ /* Check whether it was already in the list of predecessors. */
234
+ FOR_EACH_PRED(pred, q, { if (p == pred) return; });
235
+ ensure_struct(q);
236
+ old_back_ptr = GET_OH_BG_PTR(q);
237
+ be = (back_edges *)((word)old_back_ptr & ~FLAG_MANY);
238
+ for (i = be -> n_edges, be_cont = be; i > MAX_IN;
239
+ be_cont = be_cont -> cont, i -= MAX_IN) {}
240
+ if (i == MAX_IN) {
241
+ be_cont -> cont = new_back_edges();
242
+ be_cont = be_cont -> cont;
243
+ i = 0;
244
+ }
245
+ be_cont -> edges[i] = p;
246
+ be -> n_edges++;
247
+ if (be -> n_edges == 100) {
248
+ # if 0
249
+ if (GC_print_stats) {
250
+ GC_err_printf("The following object has in-degree >= 100:\n");
251
+ GC_print_heap_obj(q);
252
+ }
253
+ # endif
254
+ }
255
+ }
256
+
257
+ typedef void (*per_object_func)(ptr_t p, size_t n_bytes, word gc_descr);
258
+
259
+ static void per_object_helper(struct hblk *h, word fn)
260
+ {
261
+ hdr * hhdr = HDR(h);
262
+ size_t sz = hhdr -> hb_sz;
263
+ word descr = hhdr -> hb_descr;
264
+ per_object_func f = (per_object_func)fn;
265
+ int i = 0;
266
+
267
+ do {
268
+ f((ptr_t)(h -> hb_body + i), sz, descr);
269
+ i += sz;
270
+ } while (i + sz <= BYTES_TO_WORDS(HBLKSIZE));
271
+ }
272
+
273
+ void GC_apply_to_each_object(per_object_func f)
274
+ {
275
+ GC_apply_to_all_blocks(per_object_helper, (word)f);
276
+ }
277
+
278
+ static void reset_back_edge(ptr_t p, size_t n_bytes, word gc_descr)
279
+ {
280
+ /* Skip any free list links, or dropped blocks */
281
+ if (GC_HAS_DEBUG_INFO(p)) {
282
+ ptr_t old_back_ptr = GET_OH_BG_PTR(p);
283
+ if ((word)old_back_ptr & FLAG_MANY) {
284
+ back_edges *be = (back_edges *)((word)old_back_ptr & ~FLAG_MANY);
285
+ if (!(be -> flags & RETAIN)) {
286
+ deallocate_back_edges(be);
287
+ SET_OH_BG_PTR(p, 0);
288
+ } else {
289
+ word *currentp;
290
+
291
+ GC_ASSERT(GC_is_marked(p));
292
+
293
+ /* Back edges may point to objects that will not be retained. */
294
+ /* Delete them for now, but remember the height. */
295
+ /* Some will be added back at next GC. */
296
+ be -> n_edges = 0;
297
+ if (0 != be -> cont) {
298
+ deallocate_back_edges(be -> cont);
299
+ be -> cont = 0;
300
+ }
301
+
302
+ GC_ASSERT(GC_is_marked(p));
303
+
304
+ /* We only retain things for one GC cycle at a time. */
305
+ be -> flags &= ~RETAIN;
306
+ }
307
+ } else /* Simple back pointer */ {
308
+ /* Clear to avoid dangling pointer. */
309
+ SET_OH_BG_PTR(p, 0);
310
+ }
311
+ }
312
+ }
313
+
314
+ static void add_back_edges(ptr_t p, size_t n_bytes, word gc_descr)
315
+ {
316
+ word *currentp = (word *)(p + sizeof(oh));
317
+
318
+ /* For now, fix up non-length descriptors conservatively. */
319
+ if((gc_descr & GC_DS_TAGS) != GC_DS_LENGTH) {
320
+ gc_descr = n_bytes;
321
+ }
322
+ while (currentp < (word *)(p + gc_descr)) {
323
+ word current = *currentp++;
324
+ FIXUP_POINTER(current);
325
+ if (current >= (word)GC_least_plausible_heap_addr &&
326
+ current <= (word)GC_greatest_plausible_heap_addr) {
327
+ ptr_t target = GC_base((void *)current);
328
+ if (0 != target) {
329
+ add_edge(p, target);
330
+ }
331
+ }
332
+ }
333
+ }
334
+
335
+ /* Rebuild the representation of the backward reachability graph. */
336
+ /* Does not examine mark bits. Can be called before GC. */
337
+ void GC_build_back_graph(void)
338
+ {
339
+ GC_apply_to_each_object(add_back_edges);
340
+ }
341
+
342
+ /* Return an approximation to the length of the longest simple path */
343
+ /* through unreachable objects to p. We refer to this as the height */
344
+ /* of p. */
345
+ static word backwards_height(ptr_t p)
346
+ {
347
+ word result;
348
+ ptr_t back_ptr = GET_OH_BG_PTR(p);
349
+ back_edges *be;
350
+
351
+ if (0 == back_ptr) return 1;
352
+ if (!((word)back_ptr & FLAG_MANY)) {
353
+ if (is_in_progress(p)) return 0; /* DFS back edge, i.e. we followed */
354
+ /* an edge to an object already */
355
+ /* on our stack: ignore */
356
+ push_in_progress(p);
357
+ result = backwards_height(back_ptr)+1;
358
+ pop_in_progress(p);
359
+ return result;
360
+ }
361
+ be = (back_edges *)((word)back_ptr & ~FLAG_MANY);
362
+ if (be -> height >= 0 && be -> height_gc_no == GC_gc_no)
363
+ return be -> height;
364
+ /* Ignore back edges in DFS */
365
+ if (be -> height == HEIGHT_IN_PROGRESS) return 0;
366
+ result = (be -> height > 0? be -> height : 1);
367
+ be -> height = HEIGHT_IN_PROGRESS;
368
+ FOR_EACH_PRED(q, p, {
369
+ word this_height;
370
+ if (GC_is_marked(q) && !(FLAG_MANY & (word)GET_OH_BG_PTR(p))) {
371
+ if (GC_print_stats)
372
+ GC_log_printf("Found bogus pointer from 0x%lx to 0x%lx\n", q, p);
373
+ /* Reachable object "points to" unreachable one. */
374
+ /* Could be caused by our lax treatment of GC descriptors. */
375
+ this_height = 1;
376
+ } else {
377
+ this_height = backwards_height(q);
378
+ }
379
+ if (this_height >= result) result = this_height + 1;
380
+ });
381
+ be -> height = result;
382
+ be -> height_gc_no = GC_gc_no;
383
+ return result;
384
+ }
385
+
386
+ word GC_max_height;
387
+ ptr_t GC_deepest_obj;
388
+
389
+ /* Compute the maximum height of every unreachable predecessor p of a */
390
+ /* reachable object. Arrange to save the heights of all such objects p */
391
+ /* so that they can be used in calculating the height of objects in the */
392
+ /* next GC. */
393
+ /* Set GC_max_height to be the maximum height we encounter, and */
394
+ /* GC_deepest_obj to be the corresponding object. */
395
+ static void update_max_height(ptr_t p, size_t n_bytes, word gc_descr)
396
+ {
397
+ if (GC_is_marked(p) && GC_HAS_DEBUG_INFO(p)) {
398
+ int i;
399
+ word p_height = 0;
400
+ ptr_t p_deepest_obj = 0;
401
+ ptr_t back_ptr;
402
+ back_edges *be = 0;
403
+
404
+ /* If we remembered a height last time, use it as a minimum. */
405
+ /* It may have increased due to newly unreachable chains pointing */
406
+ /* to p, but it can't have decreased. */
407
+ back_ptr = GET_OH_BG_PTR(p);
408
+ if (0 != back_ptr && ((word)back_ptr & FLAG_MANY)) {
409
+ be = (back_edges *)((word)back_ptr & ~FLAG_MANY);
410
+ if (be -> height != HEIGHT_UNKNOWN) p_height = be -> height;
411
+ }
412
+ FOR_EACH_PRED(q, p, {
413
+ if (!GC_is_marked(q) && GC_HAS_DEBUG_INFO(q)) {
414
+ word q_height;
415
+
416
+ q_height = backwards_height(q);
417
+ if (q_height > p_height) {
418
+ p_height = q_height;
419
+ p_deepest_obj = q;
420
+ }
421
+ }
422
+ });
423
+ if (p_height > 0) {
424
+ /* Remember the height for next time. */
425
+ if (be == 0) {
426
+ ensure_struct(p);
427
+ back_ptr = GET_OH_BG_PTR(p);
428
+ be = (back_edges *)((word)back_ptr & ~FLAG_MANY);
429
+ }
430
+ be -> flags |= RETAIN;
431
+ be -> height = p_height;
432
+ be -> height_gc_no = GC_gc_no;
433
+ }
434
+ if (p_height > GC_max_height) {
435
+ GC_max_height = p_height;
436
+ GC_deepest_obj = p_deepest_obj;
437
+ }
438
+ }
439
+ }
440
+
441
+ word GC_max_max_height = 0;
442
+
443
+ void GC_traverse_back_graph(void)
444
+ {
445
+ GC_max_height = 0;
446
+ GC_apply_to_each_object(update_max_height);
447
+ if (0 != GC_deepest_obj)
448
+ GC_set_mark_bit(GC_deepest_obj); /* Keep it until we can print it. */
449
+ }
450
+
451
+ void GC_print_back_graph_stats(void)
452
+ {
453
+ GC_printf("Maximum backwards height of reachable objects at GC %lu is %ld\n",
454
+ (unsigned long) GC_gc_no, (unsigned long)GC_max_height);
455
+ if (GC_max_height > GC_max_max_height) {
456
+ GC_max_max_height = GC_max_height;
457
+ GC_printf("The following unreachable object is last in a longest chain "
458
+ "of unreachable objects:\n");
459
+ GC_print_heap_obj(GC_deepest_obj);
460
+ }
461
+ if (GC_print_stats) {
462
+ GC_log_printf("Needed max total of %ld back-edge structs\n",
463
+ GC_n_back_edge_structs);
464
+ }
465
+ GC_apply_to_each_object(reset_back_edge);
466
+ GC_deepest_obj = 0;
467
+ }
468
+
469
+ #endif /* MAKE_BACK_GRAPH */
mosesdecoder/jam-files/engine/boehm_gc/bdw-gc.pc ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ prefix=/usr/local
2
+ exec_prefix=${prefix}
3
+ libdir=${exec_prefix}/lib
4
+ includedir=${prefix}/include
5
+
6
+ Name: Boehm-Demers-Weiser Conservative Garbage Collector
7
+ Description: A garbage collector for C and C++
8
+ Version: 7.0
9
+ Libs: -L${libdir} -lgc
10
+ Cflags: -I${includedir}
mosesdecoder/jam-files/engine/boehm_gc/callprocs ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ #!/bin/sh
2
+ GC_DEBUG=1
3
+ export GC_DEBUG
4
+ $* 2>&1 | awk '{print "0x3e=c\""$0"\""};/^\t##PC##=/ {if ($2 != 0) {print $2"?i"}}' | adb $1 | sed "s/^ >/>/"
mosesdecoder/jam-files/engine/boehm_gc/compile ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #! /bin/sh
2
+ # Wrapper for compilers which do not understand `-c -o'.
3
+
4
+ scriptversion=2004-10-12.08
5
+
6
+ # Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc.
7
+ # Written by Tom Tromey <tromey@cygnus.com>.
8
+ #
9
+ # This program is free software; you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation; either version 2, or (at your option)
12
+ # any later version.
13
+ #
14
+ # This program is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with this program; if not, write to the Free Software
21
+ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
+
23
+ # As a special exception to the GNU General Public License, if you
24
+ # distribute this file as part of a program that contains a
25
+ # configuration script generated by Autoconf, you may include it under
26
+ # the same distribution terms that you use for the rest of that program.
27
+
28
+ # This file is maintained in Automake, please report
29
+ # bugs to <bug-automake@gnu.org> or send patches to
30
+ # <automake-patches@gnu.org>.
31
+
32
+ case $1 in
33
+ '')
34
+ echo "$0: No command. Try \`$0 --help' for more information." 1>&2
35
+ exit 1;
36
+ ;;
37
+ -h | --h*)
38
+ cat <<\EOF
39
+ Usage: compile [--help] [--version] PROGRAM [ARGS]
40
+
41
+ Wrapper for compilers which do not understand `-c -o'.
42
+ Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
43
+ arguments, and rename the output as expected.
44
+
45
+ If you are trying to build a whole package this is not the
46
+ right script to run: please start by reading the file `INSTALL'.
47
+
48
+ Report bugs to <bug-automake@gnu.org>.
49
+ EOF
50
+ exit 0
51
+ ;;
52
+ -v | --v*)
53
+ echo "compile $scriptversion"
54
+ exit 0
55
+ ;;
56
+ esac
57
+
58
+ ofile=
59
+ cfile=
60
+ eat=
61
+
62
+ for arg
63
+ do
64
+ if test -n "$eat"; then
65
+ eat=
66
+ else
67
+ case $1 in
68
+ -o)
69
+ # configure might choose to run compile as `compile cc -o foo foo.c'.
70
+ # So we strip `-o arg' only if arg is an object.
71
+ eat=1
72
+ case $2 in
73
+ *.o | *.obj)
74
+ ofile=$2
75
+ ;;
76
+ *)
77
+ set x "$@" -o "$2"
78
+ shift
79
+ ;;
80
+ esac
81
+ ;;
82
+ *.c)
83
+ cfile=$1
84
+ set x "$@" "$1"
85
+ shift
86
+ ;;
87
+ *)
88
+ set x "$@" "$1"
89
+ shift
90
+ ;;
91
+ esac
92
+ fi
93
+ shift
94
+ done
95
+
96
+ if test -z "$ofile" || test -z "$cfile"; then
97
+ # If no `-o' option was seen then we might have been invoked from a
98
+ # pattern rule where we don't need one. That is ok -- this is a
99
+ # normal compilation that the losing compiler can handle. If no
100
+ # `.c' file was seen then we are probably linking. That is also
101
+ # ok.
102
+ exec "$@"
103
+ fi
104
+
105
+ # Name of file we expect compiler to create.
106
+ cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
107
+
108
+ # Create the lock directory.
109
+ # Note: use `[/.-]' here to ensure that we don't use the same name
110
+ # that we are using for the .o file. Also, base the name on the expected
111
+ # object file name, since that is what matters with a parallel build.
112
+ lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d
113
+ while true; do
114
+ if mkdir "$lockdir" >/dev/null 2>&1; then
115
+ break
116
+ fi
117
+ sleep 1
118
+ done
119
+ # FIXME: race condition here if user kills between mkdir and trap.
120
+ trap "rmdir '$lockdir'; exit 1" 1 2 15
121
+
122
+ # Run the compile.
123
+ "$@"
124
+ ret=$?
125
+
126
+ if test -f "$cofile"; then
127
+ mv "$cofile" "$ofile"
128
+ elif test -f "${cofile}bj"; then
129
+ mv "${cofile}bj" "$ofile"
130
+ fi
131
+
132
+ rmdir "$lockdir"
133
+ exit $ret
134
+
135
+ # Local Variables:
136
+ # mode: shell-script
137
+ # sh-indentation: 2
138
+ # eval: (add-hook 'write-file-hooks 'time-stamp)
139
+ # time-stamp-start: "scriptversion="
140
+ # time-stamp-format: "%:y-%02m-%02d.%02H"
141
+ # time-stamp-end: "$"
142
+ # End:
mosesdecoder/jam-files/engine/boehm_gc/configure ADDED
The diff for this file is too large to render. See raw diff
 
mosesdecoder/jam-files/engine/boehm_gc/doc/README ADDED
@@ -0,0 +1,548 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 1988, 1989 Hans-J. Boehm, Alan J. Demers
2
+ Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved.
3
+ Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
4
+ Copyright (c) 1999-2005 Hewlett-Packard Development Company, L.P.
5
+
6
+ The file linux_threads.c is also
7
+ Copyright (c) 1998 by Fergus Henderson. All rights reserved.
8
+
9
+ The files Makefile.am, and configure.in are
10
+ Copyright (c) 2001 by Red Hat Inc. All rights reserved.
11
+
12
+ Several files supporting GNU-style builds are copyrighted by the Free
13
+ Software Foundation, and carry a different license from that given
14
+ below. The files included in the libatomic_ops distribution (included
15
+ here) use either the license below, or a similar MIT-style license,
16
+ or, for some files not actually used by the garbage-collector library, the
17
+ GPL.
18
+
19
+ THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
20
+ OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
21
+
22
+ Permission is hereby granted to use or copy this program
23
+ for any purpose, provided the above notices are retained on all copies.
24
+ Permission to modify the code and to distribute modified code is granted,
25
+ provided the above notices are retained, and a notice that the code was
26
+ modified is included with the above copyright notice.
27
+
28
+ A few of the files needed to use the GNU-style build procedure come with
29
+ slightly different licenses, though they are all similar in spirit. A few
30
+ are GPL'ed, but with an exception that should cover all uses in the
31
+ collector. (If you are concerned about such things, I recommend you look
32
+ at the notice in config.guess or ltmain.sh.)
33
+
34
+ This is version 7.0 of a conservative garbage collector for C and C++.
35
+
36
+ You might find a more recent version of this at
37
+
38
+ http://www.hpl.hp.com/personal/Hans_Boehm/gc
39
+
40
+ OVERVIEW
41
+
42
+ This is intended to be a general purpose, garbage collecting storage
43
+ allocator. The algorithms used are described in:
44
+
45
+ Boehm, H., and M. Weiser, "Garbage Collection in an Uncooperative Environment",
46
+ Software Practice & Experience, September 1988, pp. 807-820.
47
+
48
+ Boehm, H., A. Demers, and S. Shenker, "Mostly Parallel Garbage Collection",
49
+ Proceedings of the ACM SIGPLAN '91 Conference on Programming Language Design
50
+ and Implementation, SIGPLAN Notices 26, 6 (June 1991), pp. 157-164.
51
+
52
+ Boehm, H., "Space Efficient Conservative Garbage Collection", Proceedings
53
+ of the ACM SIGPLAN '91 Conference on Programming Language Design and
54
+ Implementation, SIGPLAN Notices 28, 6 (June 1993), pp. 197-206.
55
+
56
+ Boehm H., "Reducing Garbage Collector Cache Misses", Proceedings of the
57
+ 2000 International Symposium on Memory Management.
58
+
59
+ Possible interactions between the collector and optimizing compilers are
60
+ discussed in
61
+
62
+ Boehm, H., and D. Chase, "A Proposal for GC-safe C Compilation",
63
+ The Journal of C Language Translation 4, 2 (December 1992).
64
+
65
+ and
66
+
67
+ Boehm H., "Simple GC-safe Compilation", Proceedings
68
+ of the ACM SIGPLAN '96 Conference on Programming Language Design and
69
+ Implementation.
70
+
71
+ (Some of these are also available from
72
+ http://www.hpl.hp.com/personal/Hans_Boehm/papers/, among other places.)
73
+
74
+ Unlike the collector described in the second reference, this collector
75
+ operates either with the mutator stopped during the entire collection
76
+ (default) or incrementally during allocations. (The latter is supported
77
+ on fewer machines.) On the most common platforms, it can be built
78
+ with or without thread support. On a few platforms, it can take advantage
79
+ of a multiprocessor to speed up garbage collection.
80
+
81
+ Many of the ideas underlying the collector have previously been explored
82
+ by others. Notably, some of the run-time systems developed at Xerox PARC
83
+ in the early 1980s conservatively scanned thread stacks to locate possible
84
+ pointers (cf. Paul Rovner, "On Adding Garbage Collection and Runtime Types
85
+ to a Strongly-Typed Statically Checked, Concurrent Language" Xerox PARC
86
+ CSL 84-7). Doug McIlroy wrote a simpler fully conservative collector that
87
+ was part of version 8 UNIX (tm), but appears to not have received
88
+ widespread use.
89
+
90
+ Rudimentary tools for use of the collector as a leak detector are included
91
+ (see http://www.hpl.hp.com/personal/Hans_Boehm/gc/leak.html),
92
+ as is a fairly sophisticated string package "cord" that makes use of the
93
+ collector. (See doc/README.cords and H.-J. Boehm, R. Atkinson, and M. Plass,
94
+ "Ropes: An Alternative to Strings", Software Practice and Experience 25, 12
95
+ (December 1995), pp. 1315-1330. This is very similar to the "rope" package
96
+ in Xerox Cedar, or the "rope" package in the SGI STL or the g++ distribution.)
97
+
98
+ Further collector documantation can be found at
99
+
100
+ http://www.hpl.hp.com/personal/Hans_Boehm/gc
101
+
102
+
103
+ GENERAL DESCRIPTION
104
+
105
+ This is a garbage collecting storage allocator that is intended to be
106
+ used as a plug-in replacement for C's malloc.
107
+
108
+ Since the collector does not require pointers to be tagged, it does not
109
+ attempt to ensure that all inaccessible storage is reclaimed. However,
110
+ in our experience, it is typically more successful at reclaiming unused
111
+ memory than most C programs using explicit deallocation. Unlike manually
112
+ introduced leaks, the amount of unreclaimed memory typically stays
113
+ bounded.
114
+
115
+ In the following, an "object" is defined to be a region of memory allocated
116
+ by the routines described below.
117
+
118
+ Any objects not intended to be collected must be pointed to either
119
+ from other such accessible objects, or from the registers,
120
+ stack, data, or statically allocated bss segments. Pointers from
121
+ the stack or registers may point to anywhere inside an object.
122
+ The same is true for heap pointers if the collector is compiled with
123
+ ALL_INTERIOR_POINTERS defined, or GC_all_interior_pointers is otherwise
124
+ set, as is now the default.
125
+
126
+ Compiling without ALL_INTERIOR_POINTERS may reduce accidental retention
127
+ of garbage objects, by requiring pointers from the heap to to the beginning
128
+ of an object. But this no longer appears to be a significant
129
+ issue for most programs occupying a small fraction of the possible
130
+ address space.
131
+
132
+ There are a number of routines which modify the pointer recognition
133
+ algorithm. GC_register_displacement allows certain interior pointers
134
+ to be recognized even if ALL_INTERIOR_POINTERS is nor defined.
135
+ GC_malloc_ignore_off_page allows some pointers into the middle of large objects
136
+ to be disregarded, greatly reducing the probablility of accidental
137
+ retention of large objects. For most purposes it seems best to compile
138
+ with ALL_INTERIOR_POINTERS and to use GC_malloc_ignore_off_page if
139
+ you get collector warnings from allocations of very large objects.
140
+ See README.debugging for details.
141
+
142
+ WARNING: pointers inside memory allocated by the standard "malloc" are not
143
+ seen by the garbage collector. Thus objects pointed to only from such a
144
+ region may be prematurely deallocated. It is thus suggested that the
145
+ standard "malloc" be used only for memory regions, such as I/O buffers, that
146
+ are guaranteed not to contain pointers to garbage collectable memory.
147
+ Pointers in C language automatic, static, or register variables,
148
+ are correctly recognized. (Note that GC_malloc_uncollectable has semantics
149
+ similar to standard malloc, but allocates objects that are traced by the
150
+ collector.)
151
+
152
+ WARNING: the collector does not always know how to find pointers in data
153
+ areas that are associated with dynamic libraries. This is easy to
154
+ remedy IF you know how to find those data areas on your operating
155
+ system (see GC_add_roots). Code for doing this under SunOS, IRIX 5.X and 6.X,
156
+ HP/UX, Alpha OSF/1, Linux, and win32 is included and used by default. (See
157
+ README.win32 for win32 details.) On other systems pointers from dynamic
158
+ library data areas may not be considered by the collector.
159
+ If you're writing a program that depends on the collector scanning
160
+ dynamic library data areas, it may be a good idea to include at least
161
+ one call to GC_is_visible() to ensure that those areas are visible
162
+ to the collector.
163
+
164
+ Note that the garbage collector does not need to be informed of shared
165
+ read-only data. However if the shared library mechanism can introduce
166
+ discontiguous data areas that may contain pointers, then the collector does
167
+ need to be informed.
168
+
169
+ Signal processing for most signals may be deferred during collection,
170
+ and during uninterruptible parts of the allocation process.
171
+ Like standard ANSI C mallocs, by default it is unsafe to invoke
172
+ malloc (and other GC routines) from a signal handler while another
173
+ malloc call may be in progress. Removing -DNO_SIGNALS from Makefile
174
+ attempts to remedy that. But that may not be reliable with a compiler that
175
+ substantially reorders memory operations inside GC_malloc.
176
+
177
+ The allocator/collector can also be configured for thread-safe operation.
178
+ (Full signal safety can also be achieved, but only at the cost of two system
179
+ calls per malloc, which is usually unacceptable.)
180
+ WARNING: the collector does not guarantee to scan thread-local storage
181
+ (e.g. of the kind accessed with pthread_getspecific()). The collector
182
+ does scan thread stacks, though, so generally the best solution is to
183
+ ensure that any pointers stored in thread-local storage are also
184
+ stored on the thread's stack for the duration of their lifetime.
185
+ (This is arguably a longstanding bug, but it hasn't been fixed yet.)
186
+
187
+ INSTALLATION AND PORTABILITY
188
+
189
+ As distributed, the collector operates silently
190
+ In the event of problems, this can usually be changed by defining the
191
+ GC_PRINT_STATS or GC_PRINT_VERBOSE_STATS environment variables. This
192
+ will result in a few lines of descriptive output for each collection.
193
+ (The given statistics exhibit a few peculiarities.
194
+ Things don't appear to add up for a variety of reasons, most notably
195
+ fragmentation losses. These are probably much more significant for the
196
+ contrived program "test.c" than for your application.)
197
+
198
+ On most Un*x-like platforms, the collector can be built either using a
199
+ GNU autoconf-based build infrastructure (type "configure; make" in the
200
+ simplest case), or with a classic makefile by itself (type
201
+ "cp Makefile.direct Makefile; make"). Here we focus on the latter option.
202
+ On other platforms, typically only the latter option is available, though
203
+ with a different supplied Makefile.)
204
+
205
+ Typing "make test" nstead of "make" will automatically build the collector
206
+ and then run setjmp_test and gctest. Setjmp_test will give you information
207
+ about configuring the collector, which is useful primarily if you have
208
+ a machine that's not already supported. Gctest is a somewhat superficial
209
+ test of collector functionality. Failure is indicated by a core dump or
210
+ a message to the effect that the collector is broken. Gctest takes about
211
+ a second to two to run on reasonable 2007 vintage desktops.
212
+ It may use up to about 30MB of memory. (The
213
+ multi-threaded version will use more. 64-bit versions may use more.)
214
+ "Make test" will also, as its last step, attempt to build and test the
215
+ "cord" string library.)
216
+
217
+ The Makefile will generate a library gc.a which you should link against.
218
+ Typing "make cords" will add the cord library to gc.a.
219
+ Note that this requires an ANSI C compiler.
220
+
221
+ It is suggested that if you need to replace a piece of the collector
222
+ (e.g. GC_mark_rts.c) you simply list your version ahead of gc.a on the
223
+ ld command line, rather than replacing the one in gc.a. (This will
224
+ generate numerous warnings under some versions of AIX, but it still
225
+ works.)
226
+
227
+ All include files that need to be used by clients will be put in the
228
+ include subdirectory. (Normally this is just gc.h. "Make cords" adds
229
+ "cord.h" and "ec.h".)
230
+
231
+ The collector currently is designed to run essentially unmodified on
232
+ machines that use a flat 32-bit or 64-bit address space.
233
+ That includes the vast majority of Workstations and X86 (X >= 3) PCs.
234
+ (The list here was deleted because it was getting too long and constantly
235
+ out of date.)
236
+
237
+ In a few cases (Amiga, OS/2, Win32, MacOS) a separate makefile
238
+ or equivalent is supplied. Many of these have separate README.system
239
+ files.
240
+
241
+ Dynamic libraries are completely supported only under SunOS/Solaris,
242
+ (and even that support is not functional on the last Sun 3 release),
243
+ Linux, FreeBSD, NetBSD, IRIX 5&6, HP/UX, Win32 (not Win32S) and OSF/1
244
+ on DEC AXP machines plus perhaps a few others listed near the top
245
+ of dyn_load.c. On other machines we recommend that you do one of
246
+ the following:
247
+
248
+ 1) Add dynamic library support (and send us the code).
249
+ 2) Use static versions of the libraries.
250
+ 3) Arrange for dynamic libraries to use the standard malloc.
251
+ This is still dangerous if the library stores a pointer to a
252
+ garbage collected object. But nearly all standard interfaces
253
+ prohibit this, because they deal correctly with pointers
254
+ to stack allocated objects. (Strtok is an exception. Don't
255
+ use it.)
256
+
257
+ In all cases we assume that pointer alignment is consistent with that
258
+ enforced by the standard C compilers. If you use a nonstandard compiler
259
+ you may have to adjust the alignment parameters defined in gc_priv.h.
260
+ Note that this may also be an issue with packed records/structs, if those
261
+ enforce less alignment for pointers.
262
+
263
+ A port to a machine that is not byte addressed, or does not use 32 bit
264
+ or 64 bit addresses will require a major effort. A port to plain MSDOS
265
+ or win16 is hard.
266
+
267
+ For machines not already mentioned, or for nonstandard compilers,
268
+ some porting suggestions are provided in the "porting.html" file.
269
+
270
+ THE C INTERFACE TO THE ALLOCATOR
271
+
272
+ The following routines are intended to be directly called by the user.
273
+ Note that usually only GC_malloc is necessary. GC_clear_roots and GC_add_roots
274
+ calls may be required if the collector has to trace from nonstandard places
275
+ (e.g. from dynamic library data areas on a machine on which the
276
+ collector doesn't already understand them.) On some machines, it may
277
+ be desirable to set GC_stacktop to a good approximation of the stack base.
278
+ (This enhances code portability on HP PA machines, since there is no
279
+ good way for the collector to compute this value.) Client code may include
280
+ "gc.h", which defines all of the following, plus many others.
281
+
282
+ 1) GC_malloc(nbytes)
283
+ - allocate an object of size nbytes. Unlike malloc, the object is
284
+ cleared before being returned to the user. Gc_malloc will
285
+ invoke the garbage collector when it determines this to be appropriate.
286
+ GC_malloc may return 0 if it is unable to acquire sufficient
287
+ space from the operating system. This is the most probable
288
+ consequence of running out of space. Other possible consequences
289
+ are that a function call will fail due to lack of stack space,
290
+ or that the collector will fail in other ways because it cannot
291
+ maintain its internal data structures, or that a crucial system
292
+ process will fail and take down the machine. Most of these
293
+ possibilities are independent of the malloc implementation.
294
+
295
+ 2) GC_malloc_atomic(nbytes)
296
+ - allocate an object of size nbytes that is guaranteed not to contain any
297
+ pointers. The returned object is not guaranteed to be cleared.
298
+ (Can always be replaced by GC_malloc, but results in faster collection
299
+ times. The collector will probably run faster if large character
300
+ arrays, etc. are allocated with GC_malloc_atomic than if they are
301
+ statically allocated.)
302
+
303
+ 3) GC_realloc(object, new_size)
304
+ - change the size of object to be new_size. Returns a pointer to the
305
+ new object, which may, or may not, be the same as the pointer to
306
+ the old object. The new object is taken to be atomic iff the old one
307
+ was. If the new object is composite and larger than the original object,
308
+ then the newly added bytes are cleared (we hope). This is very likely
309
+ to allocate a new object, unless MERGE_SIZES is defined in gc_priv.h.
310
+ Even then, it is likely to recycle the old object only if the object
311
+ is grown in small additive increments (which, we claim, is generally bad
312
+ coding practice.)
313
+
314
+ 4) GC_free(object)
315
+ - explicitly deallocate an object returned by GC_malloc or
316
+ GC_malloc_atomic. Not necessary, but can be used to minimize
317
+ collections if performance is critical. Probably a performance
318
+ loss for very small objects (<= 8 bytes).
319
+
320
+ 5) GC_expand_hp(bytes)
321
+ - Explicitly increase the heap size. (This is normally done automatically
322
+ if a garbage collection failed to GC_reclaim enough memory. Explicit
323
+ calls to GC_expand_hp may prevent unnecessarily frequent collections at
324
+ program startup.)
325
+
326
+ 6) GC_malloc_ignore_off_page(bytes)
327
+ - identical to GC_malloc, but the client promises to keep a pointer to
328
+ the somewhere within the first 256 bytes of the object while it is
329
+ live. (This pointer should nortmally be declared volatile to prevent
330
+ interference from compiler optimizations.) This is the recommended
331
+ way to allocate anything that is likely to be larger than 100Kbytes
332
+ or so. (GC_malloc may result in failure to reclaim such objects.)
333
+
334
+ 7) GC_set_warn_proc(proc)
335
+ - Can be used to redirect warnings from the collector. Such warnings
336
+ should be rare, and should not be ignored during code development.
337
+
338
+ 8) GC_enable_incremental()
339
+ - Enables generational and incremental collection. Useful for large
340
+ heaps on machines that provide access to page dirty information.
341
+ Some dirty bit implementations may interfere with debugging
342
+ (by catching address faults) and place restrictions on heap arguments
343
+ to system calls (since write faults inside a system call may not be
344
+ handled well).
345
+
346
+ 9) Several routines to allow for registration of finalization code.
347
+ User supplied finalization code may be invoked when an object becomes
348
+ unreachable. To call (*f)(obj, x) when obj becomes inaccessible, use
349
+ GC_register_finalizer(obj, f, x, 0, 0);
350
+ For more sophisticated uses, and for finalization ordering issues,
351
+ see gc.h.
352
+
353
+ The global variable GC_free_space_divisor may be adjusted up from its
354
+ default value of 4 to use less space and more collection time, or down for
355
+ the opposite effect. Setting it to 1 or 0 will effectively disable collections
356
+ and cause all allocations to simply grow the heap.
357
+
358
+ The variable GC_non_gc_bytes, which is normally 0, may be changed to reflect
359
+ the amount of memory allocated by the above routines that should not be
360
+ considered as a candidate for collection. Careless use may, of course, result
361
+ in excessive memory consumption.
362
+
363
+ Some additional tuning is possible through the parameters defined
364
+ near the top of gc_priv.h.
365
+
366
+ If only GC_malloc is intended to be used, it might be appropriate to define:
367
+
368
+ #define malloc(n) GC_malloc(n)
369
+ #define calloc(m,n) GC_malloc((m)*(n))
370
+
371
+ For small pieces of VERY allocation intensive code, gc_inl.h
372
+ includes some allocation macros that may be used in place of GC_malloc
373
+ and friends.
374
+
375
+ All externally visible names in the garbage collector start with "GC_".
376
+ To avoid name conflicts, client code should avoid this prefix, except when
377
+ accessing garbage collector routines or variables.
378
+
379
+ There are provisions for allocation with explicit type information.
380
+ This is rarely necessary. Details can be found in gc_typed.h.
381
+
382
+ THE C++ INTERFACE TO THE ALLOCATOR:
383
+
384
+ The Ellis-Hull C++ interface to the collector is included in
385
+ the collector distribution. If you intend to use this, type
386
+ "make c++" after the initial build of the collector is complete.
387
+ See gc_cpp.h for the definition of the interface. This interface
388
+ tries to approximate the Ellis-Detlefs C++ garbage collection
389
+ proposal without compiler changes.
390
+
391
+ Very often it will also be necessary to use gc_allocator.h and the
392
+ allocator declared there to construct STL data structures. Otherwise
393
+ subobjects of STL data structures wil be allcoated using a system
394
+ allocator, and objects they refer to may be prematurely collected.
395
+
396
+ USE AS LEAK DETECTOR:
397
+
398
+ The collector may be used to track down leaks in C programs that are
399
+ intended to run with malloc/free (e.g. code with extreme real-time or
400
+ portability constraints). To do so define FIND_LEAK in Makefile
401
+ This will cause the collector to invoke the report_leak
402
+ routine defined near the top of reclaim.c whenever an inaccessible
403
+ object is found that has not been explicitly freed. Such objects will
404
+ also be automatically reclaimed.
405
+ If all objects are allocated with GC_DEBUG_MALLOC (see next section), then
406
+ the default version of report_leak will report at least the source file and
407
+ line number at which the leaked object was allocated. This may sometimes be
408
+ sufficient. (On a few machines, it will also report a cryptic stack trace.
409
+ If this is not symbolic, it can somethimes be called into a sympolic stack
410
+ trace by invoking program "foo" with "callprocs foo". Callprocs is a short
411
+ shell script that invokes adb to expand program counter values to symbolic
412
+ addresses. It was largely supplied by Scott Schwartz.)
413
+ Note that the debugging facilities described in the next section can
414
+ sometimes be slightly LESS effective in leak finding mode, since in
415
+ leak finding mode, GC_debug_free actually results in reuse of the object.
416
+ (Otherwise the object is simply marked invalid.) Also note that the test
417
+ program is not designed to run meaningfully in FIND_LEAK mode.
418
+ Use "make gc.a" to build the collector.
419
+
420
+ DEBUGGING FACILITIES:
421
+
422
+ The routines GC_debug_malloc, GC_debug_malloc_atomic, GC_debug_realloc,
423
+ and GC_debug_free provide an alternate interface to the collector, which
424
+ provides some help with memory overwrite errors, and the like.
425
+ Objects allocated in this way are annotated with additional
426
+ information. Some of this information is checked during garbage
427
+ collections, and detected inconsistencies are reported to stderr.
428
+
429
+ Simple cases of writing past the end of an allocated object should
430
+ be caught if the object is explicitly deallocated, or if the
431
+ collector is invoked while the object is live. The first deallocation
432
+ of an object will clear the debugging info associated with an
433
+ object, so accidentally repeated calls to GC_debug_free will report the
434
+ deallocation of an object without debugging information. Out of
435
+ memory errors will be reported to stderr, in addition to returning
436
+ NIL.
437
+
438
+ GC_debug_malloc checking during garbage collection is enabled
439
+ with the first call to GC_debug_malloc. This will result in some
440
+ slowdown during collections. If frequent heap checks are desired,
441
+ this can be achieved by explicitly invoking GC_gcollect, e.g. from
442
+ the debugger.
443
+
444
+ GC_debug_malloc allocated objects should not be passed to GC_realloc
445
+ or GC_free, and conversely. It is however acceptable to allocate only
446
+ some objects with GC_debug_malloc, and to use GC_malloc for other objects,
447
+ provided the two pools are kept distinct. In this case, there is a very
448
+ low probablility that GC_malloc allocated objects may be misidentified as
449
+ having been overwritten. This should happen with probability at most
450
+ one in 2**32. This probability is zero if GC_debug_malloc is never called.
451
+
452
+ GC_debug_malloc, GC_malloc_atomic, and GC_debug_realloc take two
453
+ additional trailing arguments, a string and an integer. These are not
454
+ interpreted by the allocator. They are stored in the object (the string is
455
+ not copied). If an error involving the object is detected, they are printed.
456
+
457
+ The macros GC_MALLOC, GC_MALLOC_ATOMIC, GC_REALLOC, GC_FREE, and
458
+ GC_REGISTER_FINALIZER are also provided. These require the same arguments
459
+ as the corresponding (nondebugging) routines. If gc.h is included
460
+ with GC_DEBUG defined, they call the debugging versions of these
461
+ functions, passing the current file name and line number as the two
462
+ extra arguments, where appropriate. If gc.h is included without GC_DEBUG
463
+ defined, then all these macros will instead be defined to their nondebugging
464
+ equivalents. (GC_REGISTER_FINALIZER is necessary, since pointers to
465
+ objects with debugging information are really pointers to a displacement
466
+ of 16 bytes form the object beginning, and some translation is necessary
467
+ when finalization routines are invoked. For details, about what's stored
468
+ in the header, see the definition of the type oh in debug_malloc.c)
469
+
470
+ INCREMENTAL/GENERATIONAL COLLECTION:
471
+
472
+ The collector normally interrupts client code for the duration of
473
+ a garbage collection mark phase. This may be unacceptable if interactive
474
+ response is needed for programs with large heaps. The collector
475
+ can also run in a "generational" mode, in which it usually attempts to
476
+ collect only objects allocated since the last garbage collection.
477
+ Furthermore, in this mode, garbage collections run mostly incrementally,
478
+ with a small amount of work performed in response to each of a large number of
479
+ GC_malloc requests.
480
+
481
+ This mode is enabled by a call to GC_enable_incremental().
482
+
483
+ Incremental and generational collection is effective in reducing
484
+ pause times only if the collector has some way to tell which objects
485
+ or pages have been recently modified. The collector uses two sources
486
+ of information:
487
+
488
+ 1. Information provided by the VM system. This may be provided in
489
+ one of several forms. Under Solaris 2.X (and potentially under other
490
+ similar systems) information on dirty pages can be read from the
491
+ /proc file system. Under other systems (currently SunOS4.X) it is
492
+ possible to write-protect the heap, and catch the resulting faults.
493
+ On these systems we require that system calls writing to the heap
494
+ (other than read) be handled specially by client code.
495
+ See os_dep.c for details.
496
+
497
+ 2. Information supplied by the programmer. We define "stubborn"
498
+ objects to be objects that are rarely changed. Such an object
499
+ can be allocated (and enabled for writing) with GC_malloc_stubborn.
500
+ Once it has been initialized, the collector should be informed with
501
+ a call to GC_end_stubborn_change. Subsequent writes that store
502
+ pointers into the object must be preceded by a call to
503
+ GC_change_stubborn.
504
+
505
+ This mechanism performs best for objects that are written only for
506
+ initialization, and such that only one stubborn object is writable
507
+ at once. It is typically not worth using for short-lived
508
+ objects. Stubborn objects are treated less efficiently than pointerfree
509
+ (atomic) objects.
510
+
511
+ A rough rule of thumb is that, in the absence of VM information, garbage
512
+ collection pauses are proportional to the amount of pointerful storage
513
+ plus the amount of modified "stubborn" storage that is reachable during
514
+ the collection.
515
+
516
+ Initial allocation of stubborn objects takes longer than allocation
517
+ of other objects, since other data structures need to be maintained.
518
+
519
+ We recommend against random use of stubborn objects in client
520
+ code, since bugs caused by inappropriate writes to stubborn objects
521
+ are likely to be very infrequently observed and hard to trace.
522
+ However, their use may be appropriate in a few carefully written
523
+ library routines that do not make the objects themselves available
524
+ for writing by client code.
525
+
526
+
527
+ BUGS:
528
+
529
+ Any memory that does not have a recognizable pointer to it will be
530
+ reclaimed. Exclusive-or'ing forward and backward links in a list
531
+ doesn't cut it.
532
+ Some C optimizers may lose the last undisguised pointer to a memory
533
+ object as a consequence of clever optimizations. This has almost
534
+ never been observed in practice. Send mail to boehm@acm.org
535
+ for suggestions on how to fix your compiler.
536
+ This is not a real-time collector. In the standard configuration,
537
+ percentage of time required for collection should be constant across
538
+ heap sizes. But collection pauses will increase for larger heaps.
539
+ They will decrease with the number of processors if parallel marking
540
+ is enabled.
541
+ (On 2007 vintage machines, GC times may be on the order of 5 msecs
542
+ per MB of accessible memory that needs to be scanned and processor.
543
+ Your mileage may vary.) The incremental/generational collection facility
544
+ may help in some cases.
545
+ Please address bug reports to boehm@acm.org. If you are
546
+ contemplating a major addition, you might also send mail to ask whether
547
+ it's already been done (or whether we tried and discarded it).
548
+
mosesdecoder/jam-files/engine/boehm_gc/doc/README.amiga ADDED
@@ -0,0 +1,322 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ===========================================================================
2
+ Kjetil S. Matheussen's notes (28-11-2000)
3
+ ===========================================================================
4
+ Compiles under SAS/C again. Should allso still compile under other
5
+ amiga compilers without big changes. I haven't checked if it still
6
+ works under gcc, because I don't have gcc for amiga. But I have
7
+ updated 'Makefile', and hope it compiles fine.
8
+
9
+
10
+ WHATS NEW:
11
+
12
+ 1.
13
+ Made a pretty big effort in preventing GCs allocating-functions from returning
14
+ chip-mem.
15
+
16
+ The lower part of the new file AmigaOS.c does this in various ways, mainly by
17
+ wrapping GC_malloc, GC_malloc_atomic, GC_malloc_uncollectable,
18
+ GC_malloc_atomic_uncollectable, GC_malloc_stubborn, GC_malloc_ignore_off_page
19
+ and GC_malloc_atomic_ignore_off_page. GC_realloc is allso wrapped, but
20
+ doesn't do the same effort in preventing to return chip-mem.
21
+ Other allocating-functions (f.ex. GC_*_typed_) can probably be
22
+ used without any problems, but beware that the warn hook will not be called.
23
+ In case of problems, don't define GC_AMIGA_FASTALLOC.
24
+
25
+ Programs using more time actually using the memory allocated
26
+ (instead of just allocate and free rapidly) have
27
+ the most to earn on this, but even gctest now normally runs twice
28
+ as fast and uses less memory, on my poor 8MB machine.
29
+
30
+ The changes have only effect when there is no more
31
+ fast-mem left. But with the way GC works, it
32
+ could happen quite often. Beware that an atexit handler had to be added,
33
+ so using the abort() function will make a big memory-loss.
34
+ If you absolutely must call abort() instead of exit(), try calling
35
+ the GC_amiga_free_all_mem function before abort().
36
+
37
+ New amiga-spesific compilation flags:
38
+
39
+ GC_AMIGA_FASTALLOC - By NOT defining this option, GC will work like before,
40
+ it will not try to force fast-mem out of the OS, and
41
+ it will use normal calloc for allocation, and the rest
42
+ of the following flags will have no effect.
43
+
44
+ GC_AMIGA_ONLYFAST - Makes GC never to return chip-mem. GC_AMIGA_RETRY have
45
+ no effect if this flag is set.
46
+
47
+ GC_AMIGA_GC - If gc returns NULL, do a GC_gcollect, and try again. This
48
+ usually is a success with the standard GC configuration.
49
+ It is allso the most important flag to set to prevent
50
+ GC from returning chip-mem. Beware that it slows down a lot
51
+ when a program is rapidly allocating/deallocating when
52
+ theres either very little fast-memory left or verly little
53
+ chip-memory left. Its not a very common situation, but gctest
54
+ sometimes (very rare) use many minutes because of this.
55
+
56
+ GC_AMIGA_RETRY - If gc succeed allocating memory, but it is chip-mem,
57
+ try again and see if it is fast-mem. Most of the time,
58
+ it will actually return fast-mem for the second try.
59
+ I have set max number of retries to 9 or size/5000. You
60
+ can change this if you like. (see GC_amiga_rec_alloc())
61
+
62
+ GC_AMIGA_PRINTSTATS - Gather some statistics during the execution of a
63
+ program, and prints out the info when the atexit-handler
64
+ is called.
65
+
66
+ My reccomendation is to set all this flags, except GC_AMIGA_PRINTSTATS and
67
+ GC_AMIGA_ONLYFAST.
68
+
69
+ If your program demands high response-time, you should
70
+ not define GC_AMIGA_GC, and possible allso define GC_AMIGA_ONLYFAST.
71
+ GC_AMIGA_RETRY does not seem to slow down much.
72
+
73
+ Allso, when compiling up programs, and GC_AMIGA_FASTALLOC was not defined when
74
+ compilling gc, you can define GC_AMIGA_MAKINGLIB to avoid having these allocation-
75
+ functions wrapped. (see gc.h)
76
+
77
+ Note that GC_realloc must not be called before any of
78
+ the other above mentioned allocating-functions have been called. (shouldn't be
79
+ any programs doing so either, I hope).
80
+
81
+ Another note. The allocation-function is wrapped when defining
82
+ GC_AMIGA_FASTALLOC by letting the function go thru the new
83
+ GC_amiga_allocwrapper_do function-pointer (see gc.h). Means that
84
+ sending function-pointers, such as GC_malloc, GC_malloc_atomic, etc.,
85
+ for later to be called like f.ex this, (*GC_malloc_functionpointer)(size),
86
+ will not wrap the function. This is normally not a big problem, unless
87
+ all allocation function is called like this, which will cause the
88
+ atexit un-allocating function never to be called. Then you either
89
+ have to manually add the atexit handler, or call the allocation-
90
+ functions function-pointer functions like this;
91
+ (*GC_amiga_allocwrapper_do)(size,GC_malloc_functionpointer).
92
+ There are probably better ways this problem could be handled, unfortunately,
93
+ I didn't find any without rewriting or replacing a lot of the GC-code, which
94
+ I really didn't want to. (Making new GC_malloc_* functions, and just
95
+ define f.ex GC_malloc as GC_amiga_malloc should allso work).
96
+
97
+
98
+ New amiga-spesific function:
99
+
100
+ void GC_amiga_set_toany(void (*func)(void));
101
+
102
+ 'func' is a function that will be called right before gc has to change
103
+ allocation-method from MEMF_FAST to MEMF_ANY. Ie. when it is likely
104
+ it will return chip-mem.
105
+
106
+
107
+ 2. A few small compiler-spesific additions to make it compile with SAS/C again.
108
+
109
+ 3. Updated and rewritten the smakefile, so that it works again and that
110
+ the "unnecesarry" 'SCOPTIONS' files could be removed. Allso included
111
+ the cord-smakefile stuff in the main smakefile, so that the cord smakefile
112
+ could be removed too. By writing smake -f Smakefile.smk, both gc.lib and
113
+ cord.lib will be made.
114
+
115
+
116
+
117
+ STILL MISSING:
118
+
119
+ Programs can not be started from workbench, at least not for SAS/C. (Martin
120
+ Tauchmanns note about that it now works with workbench is definitely wrong
121
+ when concerning SAS/C). I guess it works if you use the old "#if 0'ed"-code,
122
+ but I haven't tested it. I think the reason for MT to replace the
123
+ "#if 0'ed"-code was only because it was a bit to SAS/C-spesific. But I
124
+ don't know. An iconx-script solves this problem anyway.
125
+
126
+
127
+ BEWARE!
128
+
129
+ -To run gctest, set the stack to around 200000 bytes first.
130
+ -SAS/C-spesific: cord will crash if you compile gc.lib with
131
+ either parm=reg or parm=both. (missing legal prototypes for
132
+ function-pointers someplace is the reason I guess.).
133
+
134
+
135
+ tested with software: Radium, http://www.stud.ifi.uio.no/~ksvalast/radium/
136
+
137
+ tested with hardware: MC68060
138
+
139
+
140
+ -ksvalast@ifi.uio.no
141
+
142
+
143
+ ===========================================================================
144
+ Martin Tauchmann's notes (1-Apr-99)
145
+ ===========================================================================
146
+
147
+ 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/>
148
+ Modify the `Makefile`
149
+ CC=cc $(ABI_FLAG)
150
+ to
151
+ CC=gcc $(ABI_FLAG)
152
+
153
+ TECHNICAL NOTES
154
+
155
+ - `GC_get_stack_base()`, `GC_register_data_segments()` works now with every
156
+ C compiler; also Workbench.
157
+
158
+ - Removed AMIGA_SKIP_SEG, but the Code-Segment must not be scanned by GC.
159
+
160
+
161
+ PROBLEMS
162
+ - When the Linker, does`t merge all Code-Segments to an single one. LD of GCC
163
+ do it always.
164
+
165
+ - With ixemul.library V47.3, when an GC program launched from another program
166
+ (example: `Make` or `if_mach M68K AMIGA gctest`), `GC_register_data_segments()`
167
+ found the Segment-List of the caller program.
168
+ Can be fixed, if the run-time initialization code (for C programs, usually *crt0*)
169
+ support `__data` and `__bss`.
170
+
171
+ - PowerPC Amiga currently not supported.
172
+
173
+ - Dynamic libraries (dyn_load.c) not supported.
174
+
175
+
176
+ TESTED WITH SOFTWARE
177
+
178
+ `Optimized Oberon 2 C` (oo2c) <http://cognac.informatik.uni-kl.de/download/index.html>
179
+
180
+
181
+ TESTED WITH HARDWARE
182
+
183
+ MC68030
184
+
185
+
186
+ CONTACT
187
+
188
+ Please, contact me at <martintauchmann@bigfoot.com>, when you change the
189
+ Amiga port. <http://martintauchmann.home.pages.de>
190
+
191
+ ===========================================================================
192
+ Michel Schinz's notes
193
+ ===========================================================================
194
+ WHO DID WHAT
195
+
196
+ The original Amiga port was made by Jesper Peterson. I (Michel Schinz)
197
+ modified it slightly to reflect the changes made in the new official
198
+ distributions, and to take advantage of the new SAS/C 6.x features. I also
199
+ created a makefile to compile the "cord" package (see the cord
200
+ subdirectory).
201
+
202
+ TECHNICAL NOTES
203
+
204
+ In addition to Jesper's notes, I have the following to say:
205
+
206
+ - Starting with version 4.3, gctest checks to see if the code segment is
207
+ added to the root set or not, and complains if it is. Previous versions
208
+ of this Amiga port added the code segment to the root set, so I tried to
209
+ fix that. The only problem is that, as far as I know, it is impossible to
210
+ know which segments are code segments and which are data segments (there
211
+ are indeed solutions to this problem, like scanning the program on disk
212
+ or patch the LoadSeg functions, but they are rather complicated). The
213
+ solution I have chosen (see os_dep.c) is to test whether the program
214
+ counter is in the segment we are about to add to the root set, and if it
215
+ is, to skip the segment. The problems are that this solution is rather
216
+ awkward and that it works only for one code segment. This means that if
217
+ your program has more than one code segment, all of them but one will be
218
+ added to the root set. This isn't a big problem in fact, since the
219
+ collector will continue to work correctly, but it may be slower.
220
+
221
+ Anyway, the code which decides whether to skip a segment or not can be
222
+ removed simply by not defining AMIGA_SKIP_SEG. But notice that if you do
223
+ so, gctest will complain (it will say that "GC_is_visible produced wrong
224
+ failure indication"). However, it may be useful if you happen to have
225
+ pointers stored in a code segment (you really shouldn't).
226
+
227
+ If anyone has a good solution to the problem of finding, when a program
228
+ is loaded in memory, whether a segment is a code or a data segment,
229
+ please let me know.
230
+
231
+ PROBLEMS
232
+
233
+ If you have any problem with this version, please contact me at
234
+ schinz@alphanet.ch (but do *not* send long files, since we pay for
235
+ every mail!).
236
+
237
+ ===========================================================================
238
+ Jesper Peterson's notes
239
+ ===========================================================================
240
+
241
+ ADDITIONAL NOTES FOR AMIGA PORT
242
+
243
+ These notes assume some familiarity with Amiga internals.
244
+
245
+ WHY I PORTED TO THE AMIGA
246
+
247
+ The sole reason why I made this port was as a first step in getting
248
+ the Sather(*) language on the Amiga. A port of this language will
249
+ be done as soon as the Sather 1.0 sources are made available to me.
250
+ Given this motivation, the garbage collection (GC) port is rather
251
+ minimal.
252
+
253
+ (*) For information on Sather read the comp.lang.sather newsgroup.
254
+
255
+ LIMITATIONS
256
+
257
+ This port assumes that the startup code linked with target programs
258
+ is that supplied with SAS/C versions 6.0 or later. This allows
259
+ assumptions to be made about where to find the stack base pointer
260
+ and data segments when programs are run from WorkBench, as opposed
261
+ to running from the CLI. The compiler dependent code is all in the
262
+ GC_get_stack_base() and GC_register_data_segments() functions, but
263
+ may spread as I add Amiga specific features.
264
+
265
+ Given that SAS/C was assumed, the port is set up to be built with
266
+ "smake" using the "SMakefile". Compiler options in "SCoptions" can
267
+ be set with "scopts" program. Both "smake" and "scopts" are part of
268
+ the SAS/C commercial development system.
269
+
270
+ In keeping with the porting philosophy outlined above, this port
271
+ will not behave well with Amiga specific code. Especially not inter-
272
+ process comms via messages, and setting up public structures like
273
+ Intuition objects or anything else in the system lists. For the
274
+ time being the use of this library is limited to single threaded
275
+ ANSI/POSIX compliant or near-complient code. (ie. Stick to stdio
276
+ for now). Given this limitation there is currently no mechanism for
277
+ allocating "CHIP" or "PUBLIC" memory under the garbage collector.
278
+ I'll add this after giving it considerable thought. The major
279
+ problem is the entire physical address space may have to me scanned,
280
+ since there is no telling who we may have passed memory to.
281
+
282
+ If you allocate your own stack in client code, you will have to
283
+ assign the pointer plus stack size to GC_stackbottom.
284
+
285
+ The initial stack size of the target program can be compiled in by
286
+ setting the __stack symbol (see SAS documentaion). It can be over-
287
+ ridden from the CLI by running the AmigaDOS "stack" program, or from
288
+ the WorkBench by setting the stack size in the tool types window.
289
+
290
+ SAS/C COMPILER OPTIONS (SCoptions)
291
+
292
+ You may wish to check the "CPU" code option is appropriate for your
293
+ intended target system.
294
+
295
+ Under no circumstances set the "StackExtend" code option in either
296
+ compiling the library or *ANY* client code.
297
+
298
+ All benign compiler warnings have been suppressed. These mainly
299
+ involve lack of prototypes in the code, and dead assignments
300
+ detected by the optimizer.
301
+
302
+ THE GOOD NEWS
303
+
304
+ The library as it stands is compatible with the GigaMem commercial
305
+ virtual memory software, and probably similar PD software.
306
+
307
+ The performance of "gctest" on an Amiga 2630 (68030 @ 25Mhz)
308
+ compares favourably with an HP9000 with similar architecture (a 325
309
+ with a 68030 I think).
310
+
311
+ -----------------------------------------------------------------------
312
+
313
+ The Amiga port has been brought to you by:
314
+
315
+ Jesper Peterson.
316
+
317
+ jep@mtiame.mtia.oz.au (preferred, but 1 week turnaround)
318
+ jep@orca1.vic.design.telecom.au (that's orca<one>, 1 day turnaround)
319
+
320
+ At least one of these addresses should be around for a while, even
321
+ though I don't work for either of the companies involved.
322
+
mosesdecoder/jam-files/engine/boehm_gc/doc/README.changes ADDED
The diff for this file is too large to render. See raw diff
 
mosesdecoder/jam-files/engine/boehm_gc/doc/README.ews4800 ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GC on EWS4800
2
+ -------------
3
+
4
+ 1. About EWS4800
5
+ EWS4800 is 32bit/64bit workstation.
6
+
7
+ Vender: NEC Corporation
8
+ OS: UX/4800 R9.* - R13.* (SystemV R4.2)
9
+ CPU: R4000, R4400, R10000 (MIPS)
10
+
11
+ 2. Compiler
12
+
13
+ 32bit:
14
+ Use ANSI C compiler.
15
+ CC = /usr/abiccs/bin/cc
16
+
17
+ 64bit:
18
+ Use 64bit ANSI C compiler.
19
+ CC = /usr/ccs64/bin/cc
20
+ AR = /usr/ccs64/bin/ar
21
+
22
+ 3. ELF file format
23
+ *** Caution: The following infomation is empirical. ***
24
+
25
+ 32bit:
26
+ ELF file has an unique format. (See a.out(4) and end(3C).)
27
+
28
+ &_start
29
+ : text segment
30
+ &etext
31
+ DATASTART
32
+ : data segment (initialized)
33
+ &edata
34
+ DATASTART2
35
+ : data segment (uninitialized)
36
+ &end
37
+
38
+ Here, DATASTART and DATASTART2 are macros of GC, and are defined as
39
+ the following equations. (See include/private/gcconfig.h.)
40
+ The algorithm for DATASTART is similar with the function
41
+ GC_SysVGetDataStart() in os_dep.c.
42
+
43
+ DATASTART = ((&etext + 0x3ffff) & ~0x3ffff) + (&etext & 0xffff)
44
+
45
+ Dynamically linked:
46
+ DATASTART2 = (&_gp + 0x8000 + 0x3ffff) & ~0x3ffff
47
+
48
+ Statically linked:
49
+ DATASTART2 = &edata
50
+
51
+ GC has to check addresses both between DATASTART and &edata, and
52
+ between DATASTART2 and &end. If a program accesses between &etext
53
+ and DATASTART, or between &edata and DATASTART2, the segmentation
54
+ error occurs and the program stops.
55
+
56
+ If a program is statically linked, there is not a gap between
57
+ &edata and DATASTART2. The global symbol &_DYNAMIC_LINKING is used
58
+ for the detection.
59
+
60
+ 64bit:
61
+ ELF file has a simple format. (See end(3C).)
62
+
63
+ _ftext
64
+ : text segment
65
+ _etext
66
+ _fdata = DATASTART
67
+ : data segment (initialized)
68
+ _edata
69
+ _fbss
70
+ : data segment (uninitialized)
71
+ _end = DATAEND
72
+
73
+ --
74
+ Hironori SAKAMOTO <hsaka@mth.biglobe.ne.jp>
75
+
76
+
77
+ When using the new "configure; make" build process, please
78
+ run configure with the --disable-shared option. "Make check" does not
79
+ yet pass with dynamic libraries. Ther reasons for that are not yet
80
+ understood. (HB, paraphrasing message from Hironori SAKAMOTO.)
81
+
mosesdecoder/jam-files/engine/boehm_gc/doc/README.macros ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The collector uses a large amount of conditional compilation in order to
2
+ deal with platform dependencies. This violates a number of known coding
3
+ standards. On the other hand, it seems to be the only practical way to
4
+ support this many platforms without excessive code duplication.
5
+
6
+ A few guidelines have mostly been followed in order to keep this manageable:
7
+
8
+ 1) #if and #ifdef directives are properly indented whenever easily possible.
9
+ All known C compilers allow whitespace between the "#" and the "if" to make
10
+ this possible. ANSI C also allows white space before the "#", though we
11
+ avoid that. It has the known disadvantages that it differs from the normal
12
+ GNU conventions, and that it makes patches larger than otherwise necessary.
13
+ In my opinion, it's still well worth it, for the same reason that we indent
14
+ ordinary "if" statements.
15
+
16
+ 2) Whenever possible, tests are performed on the macros defined in gcconfig.h
17
+ instead of directly testing patform-specific predefined macros. This makes it
18
+ relatively easy to adapt to new compilers with a different set of predefined
19
+ macros. Currently these macros generally identify platforms instead of
20
+ features. In many cases, this is a mistake.
21
+
22
+ Many of the tested configuration macros are at least somewhat defined in
23
+ either include/private/gcconfig.h or in Makefile.direct. Here is an attempt
24
+ at defining some of the remainder: (Thanks to Walter Bright for suggesting
25
+ this. This is a work in progress)
26
+
27
+ MACRO EXPLANATION
28
+ ----- -----------
29
+
30
+ __DMC__ Always #define'd by the Digital Mars compiler. Expands
31
+ to the compiler version number in hex, i.e. 0x810 is
32
+ version 8.1b0
33
+
34
+ _ENABLE_ARRAYNEW
35
+ #define'd by the Digital Mars C++ compiler when
36
+ operator new[] and delete[] are separately
37
+ overloadable. Used in gc_cpp.h.
38
+
39
+ _MSC_VER Expands to the Visual C++ compiler version. Assumed to
40
+ not be defined for other compilers (at least if they behave
41
+ appreciably differently).
42
+
43
+ _DLL Defined by Visual C++ if dynamic libraries are being built
44
+ or used. Used to test whether __declspec(dllimport) or
45
+ __declspec(dllexport) needs to be added to declarations
46
+ to support the case in which the collector is in a dll.
47
+
48
+ GC_DLL User-settable macro that forces the effect of _DLL. Set
49
+ by gc.h if _DLL is defined and GC_NOT_DLL is undefined.
50
+ This is the macro that is tested internally to determine
51
+ whether the GC is in its own dynamic library. May need
52
+ to be set by clients before including gc.h. Note that
53
+ inside the GC implementation it indicates that the
54
+ collector is in its own dynamic library, should export
55
+ its symbols, etc. But in clients it indicates that the
56
+ GC resides in a different DLL, its entry points should
57
+ be referenced accordingly, and precautions may need to
58
+ be taken to properly deal with statically allocated
59
+ variables in the main program. Used only for MS Windows.
60
+
61
+ GC_NOT_DLL User-settable macro that overrides _DLL, e.g. if dynamic
62
+ libraries are used, but the collector is in a static library.
63
+
64
+ __STDC__ Assumed to be defined only by compilers that understand
65
+ prototypes and other C89 features. Its value is generally
66
+ not used, since we are fine with most nonconforming extensions.
67
+
68
+ SUNOS5SIGS Solaris-like signal handling. This is probably misnamed,
69
+ since it really doesn't guarantee much more than Posix.
70
+ Currently set only for Solaris2.X, HPUX, and DRSNX. Should
71
+ probably be set for some other platforms.
72
+
73
+ PCR Set if the collector is being built as part of the Xerox
74
+ Portable Common Runtime.
75
+
76
+ USE_COMPILER_TLS Assume the existence of __thread-style thread-local
77
+ storage. Set automatically for thread-local allocation with
78
+ the HP/UX vendor compiler. Usable with gcc on sufficiently
79
+ up-to-date ELF platforms.
80
+
81
+
82
+
mosesdecoder/jam-files/engine/boehm_gc/doc/README.rs6000 ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ We have so far failed to find a good way to determine the stack base.
2
+ It is highly recommended that GC_stackbottom be set explicitly on program
3
+ startup. The supplied value sometimes causes failure under AIX 4.1, though
4
+ it appears to work under 3.X. HEURISTIC2 seems to work under 4.1, but
5
+ involves a substantial performance penalty, and will fail if there is
6
+ no limit on stack size.
7
+
8
+ There is no thread support. (I assume recent versions of AIX provide
9
+ pthreads? I no longer have access to a machine ...)
mosesdecoder/jam-files/engine/boehm_gc/doc/doc.am ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ #
3
+ # THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
4
+ # OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
5
+ #
6
+ # Permission is hereby granted to use or copy this program
7
+ # for any purpose, provided the above notices are retained on all copies.
8
+ # Permission to modify the code and to distribute modified code is granted,
9
+ # provided the above notices are retained, and a notice that the code was
10
+ # modified is included with the above copyright notice.
11
+ #
12
+ # Modified by: Grzegorz Jakacki <jakacki at acm dot org>
13
+ # Modified by: Petter Urkedal <petter.urkedal@nordita.dk>
14
+
15
+ ## Process this file with automake to produce Makefile.in.
16
+
17
+ # installed documentation
18
+ #
19
+ dist_pkgdata_DATA = \
20
+ doc/barrett_diagram \
21
+ doc/debugging.html \
22
+ doc/gc.man \
23
+ doc/gcdescr.html \
24
+ doc/README \
25
+ doc/README.amiga \
26
+ doc/README.arm.cross \
27
+ doc/README.autoconf \
28
+ doc/README.changes \
29
+ doc/README.contributors \
30
+ doc/README.cords \
31
+ doc/README.DGUX386 \
32
+ doc/README.dj \
33
+ doc/README.environment \
34
+ doc/README.ews4800 \
35
+ doc/README.hp \
36
+ doc/README.linux \
37
+ doc/README.Mac \
38
+ doc/README.MacOSX \
39
+ doc/README.macros \
40
+ doc/README.OS2 \
41
+ doc/README.rs6000 \
42
+ doc/README.sgi \
43
+ doc/README.solaris2 \
44
+ doc/README.uts \
45
+ doc/README.win32 \
46
+ doc/README.win64 \
47
+ doc/overview.html \
48
+ doc/tree.html \
49
+ doc/leak.html \
50
+ doc/gcinterface.html \
51
+ doc/scale.html \
52
+ doc/README.darwin \
53
+ doc/simple_example.html \
54
+ doc/porting.html
55
+
mosesdecoder/jam-files/engine/boehm_gc/doc/gcdescr.html ADDED
@@ -0,0 +1,621 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <HTML>
2
+ <HEAD>
3
+ <TITLE> Conservative GC Algorithmic Overview </TITLE>
4
+ <AUTHOR> Hans-J. Boehm, HP Labs (Some of this was written at SGI)</author>
5
+ </HEAD>
6
+ <BODY>
7
+ <H1> <I>This is under construction, and may always be.</i> </h1>
8
+ <H1> Conservative GC Algorithmic Overview </h1>
9
+ <P>
10
+ This is a description of the algorithms and data structures used in our
11
+ conservative garbage collector. I expect the level of detail to increase
12
+ with time. For a survey of GC algorithms, see for example
13
+ <A HREF="ftp://ftp.cs.utexas.edu/pub/garbage/gcsurvey.ps"> Paul Wilson's
14
+ excellent paper</a>. For an overview of the collector interface,
15
+ see <A HREF="gcinterface.html">here</a>.
16
+ <P>
17
+ This description is targeted primarily at someone trying to understand the
18
+ source code. It specifically refers to variable and function names.
19
+ It may also be useful for understanding the algorithms at a higher level.
20
+ <P>
21
+ The description here assumes that the collector is used in default mode.
22
+ In particular, we assume that it used as a garbage collector, and not just
23
+ a leak detector. We initially assume that it is used in stop-the-world,
24
+ non-incremental mode, though the presence of the incremental collector
25
+ will be apparent in the design.
26
+ We assume the default finalization model, but the code affected by that
27
+ is very localized.
28
+ <H2> Introduction </h2>
29
+ The garbage collector uses a modified mark-sweep algorithm. Conceptually
30
+ it operates roughly in four phases, which are performed occasionally
31
+ as part of a memory allocation:
32
+
33
+ <OL>
34
+
35
+ <LI>
36
+ <I>Preparation</i> Each object has an associated mark bit.
37
+ Clear all mark bits, indicating that all objects
38
+ are potentially unreachable.
39
+
40
+ <LI>
41
+ <I>Mark phase</i> Marks all objects that can be reachable via chains of
42
+ pointers from variables. Often the collector has no real information
43
+ about the location of pointer variables in the heap, so it
44
+ views all static data areas, stacks and registers as potentially containing
45
+ pointers. Any bit patterns that represent addresses inside
46
+ heap objects managed by the collector are viewed as pointers.
47
+ Unless the client program has made heap object layout information
48
+ available to the collector, any heap objects found to be reachable from
49
+ variables are again scanned similarly.
50
+
51
+ <LI>
52
+ <I>Sweep phase</i> Scans the heap for inaccessible, and hence unmarked,
53
+ objects, and returns them to an appropriate free list for reuse. This is
54
+ not really a separate phase; even in non incremental mode this is operation
55
+ is usually performed on demand during an allocation that discovers an empty
56
+ free list. Thus the sweep phase is very unlikely to touch a page that
57
+ would not have been touched shortly thereafter anyway.
58
+
59
+ <LI>
60
+ <I>Finalization phase</i> Unreachable objects which had been registered
61
+ for finalization are enqueued for finalization outside the collector.
62
+
63
+ </ol>
64
+
65
+ <P>
66
+ The remaining sections describe the memory allocation data structures,
67
+ and then the last 3 collection phases in more detail. We conclude by
68
+ outlining some of the additional features implemented in the collector.
69
+
70
+ <H2>Allocation</h2>
71
+ The collector includes its own memory allocator. The allocator obtains
72
+ memory from the system in a platform-dependent way. Under UNIX, it
73
+ uses either <TT>malloc</tt>, <TT>sbrk</tt>, or <TT>mmap</tt>.
74
+ <P>
75
+ Most static data used by the allocator, as well as that needed by the
76
+ rest of the garbage collector is stored inside the
77
+ <TT>_GC_arrays</tt> structure.
78
+ This allows the garbage collector to easily ignore the collectors own
79
+ data structures when it searches for root pointers. Other allocator
80
+ and collector internal data structures are allocated dynamically
81
+ with <TT>GC_scratch_alloc</tt>. <TT>GC_scratch_alloc</tt> does not
82
+ allow for deallocation, and is therefore used only for permanent data
83
+ structures.
84
+ <P>
85
+ The allocator allocates objects of different <I>kinds</i>.
86
+ Different kinds are handled somewhat differently by certain parts
87
+ of the garbage collector. Certain kinds are scanned for pointers,
88
+ others are not. Some may have per-object type descriptors that
89
+ determine pointer locations. Or a specific kind may correspond
90
+ to one specific object layout. Two built-in kinds are uncollectable.
91
+ One (<TT>STUBBORN</tt>) is immutable without special precautions.
92
+ In spite of that, it is very likely that most C clients of the
93
+ collector currently
94
+ use at most two kinds: <TT>NORMAL</tt> and <TT>PTRFREE</tt> objects.
95
+ The <A HREF="http://gcc.gnu.org/java">gcj</a> runtime also makes
96
+ heavy use of a kind (allocated with GC_gcj_malloc) that stores
97
+ type information at a known offset in method tables.
98
+ <P>
99
+ The collector uses a two level allocator. A large block is defined to
100
+ be one larger than half of <TT>HBLKSIZE</tt>, which is a power of 2,
101
+ typically on the order of the page size.
102
+ <P>
103
+ Large block sizes are rounded up to
104
+ the next multiple of <TT>HBLKSIZE</tt> and then allocated by
105
+ <TT>GC_allochblk</tt>. Recent versions of the collector
106
+ use an approximate best fit algorithm by keeping free lists for
107
+ several large block sizes.
108
+ The actual
109
+ implementation of <TT>GC_allochblk</tt>
110
+ is significantly complicated by black-listing issues
111
+ (see below).
112
+ <P>
113
+ Small blocks are allocated in chunks of size <TT>HBLKSIZE</tt>.
114
+ Each chunk is
115
+ dedicated to only one object size and kind. The allocator maintains
116
+ separate free lists for each size and kind of object.
117
+ <P>
118
+ Once a large block is split for use in smaller objects, it can only
119
+ be used for objects of that size, unless the collector discovers a completely
120
+ empty chunk. Completely empty chunks are restored to the appropriate
121
+ large block free list.
122
+ <P>
123
+ In order to avoid allocating blocks for too many distinct object sizes,
124
+ the collector normally does not directly allocate objects of every possible
125
+ request size. Instead request are rounded up to one of a smaller number
126
+ of allocated sizes, for which free lists are maintained. The exact
127
+ allocated sizes are computed on demand, but subject to the constraint
128
+ that they increase roughly in geometric progression. Thus objects
129
+ requested early in the execution are likely to be allocated with exactly
130
+ the requested size, subject to alignment constraints.
131
+ See <TT>GC_init_size_map</tt> for details.
132
+ <P>
133
+ The actual size rounding operation during small object allocation is
134
+ implemented as a table lookup in <TT>GC_size_map</tt>.
135
+ <P>
136
+ Both collector initialization and computation of allocated sizes are
137
+ handled carefully so that they do not slow down the small object fast
138
+ allocation path. An attempt to allocate before the collector is initialized,
139
+ or before the appropriate <TT>GC_size_map</tt> entry is computed,
140
+ will take the same path as an allocation attempt with an empty free list.
141
+ This results in a call to the slow path code (<TT>GC_generic_malloc_inner</tt>)
142
+ which performs the appropriate initialization checks.
143
+ <P>
144
+ In non-incremental mode, we make a decision about whether to garbage collect
145
+ whenever an allocation would otherwise have failed with the current heap size.
146
+ If the total amount of allocation since the last collection is less than
147
+ the heap size divided by <TT>GC_free_space_divisor</tt>, we try to
148
+ expand the heap. Otherwise, we initiate a garbage collection. This ensures
149
+ that the amount of garbage collection work per allocated byte remains
150
+ constant.
151
+ <P>
152
+ The above is in fact an oversimplification of the real heap expansion
153
+ and GC triggering heuristic, which adjusts slightly for root size
154
+ and certain kinds of
155
+ fragmentation. In particular:
156
+ <UL>
157
+ <LI> Programs with a large root set size and
158
+ little live heap memory will expand the heap to amortize the cost of
159
+ scanning the roots.
160
+ <LI> Versions 5.x of the collector actually collect more frequently in
161
+ nonincremental mode. The large block allocator usually refuses to split
162
+ large heap blocks once the garbage collection threshold is
163
+ reached. This often has the effect of collecting well before the
164
+ heap fills up, thus reducing fragmentation and working set size at the
165
+ expense of GC time. Versions 6.x choose an intermediate strategy depending
166
+ on how much large object allocation has taken place in the past.
167
+ (If the collector is configured to unmap unused pages, versions 6.x
168
+ use the 5.x strategy.)
169
+ <LI> In calculating the amount of allocation since the last collection we
170
+ give partial credit for objects we expect to be explicitly deallocated.
171
+ Even if all objects are explicitly managed, it is often desirable to collect
172
+ on rare occasion, since that is our only mechanism for coalescing completely
173
+ empty chunks.
174
+ </ul>
175
+ <P>
176
+ It has been suggested that this should be adjusted so that we favor
177
+ expansion if the resulting heap still fits into physical memory.
178
+ In many cases, that would no doubt help. But it is tricky to do this
179
+ in a way that remains robust if multiple application are contending
180
+ for a single pool of physical memory.
181
+
182
+ <H2>Mark phase</h2>
183
+
184
+ At each collection, the collector marks all objects that are
185
+ possibly reachable from pointer variables. Since it cannot generally
186
+ tell where pointer variables are located, it scans the following
187
+ <I>root segments</i> for pointers:
188
+ <UL>
189
+ <LI>The registers. Depending on the architecture, this may be done using
190
+ assembly code, or by calling a <TT>setjmp</tt>-like function which saves
191
+ register contents on the stack.
192
+ <LI>The stack(s). In the case of a single-threaded application,
193
+ on most platforms this
194
+ is done by scanning the memory between (an approximation of) the current
195
+ stack pointer and <TT>GC_stackbottom</tt>. (For Itanium, the register stack
196
+ scanned separately.) The <TT>GC_stackbottom</tt> variable is set in
197
+ a highly platform-specific way depending on the appropriate configuration
198
+ information in <TT>gcconfig.h</tt>. Note that the currently active
199
+ stack needs to be scanned carefully, since callee-save registers of
200
+ client code may appear inside collector stack frames, which may
201
+ change during the mark process. This is addressed by scanning
202
+ some sections of the stack "eagerly", effectively capturing a snapshot
203
+ at one point in time.
204
+ <LI>Static data region(s). In the simplest case, this is the region
205
+ between <TT>DATASTART</tt> and <TT>DATAEND</tt>, as defined in
206
+ <TT>gcconfig.h</tt>. However, in most cases, this will also involve
207
+ static data regions associated with dynamic libraries. These are
208
+ identified by the mostly platform-specific code in <TT>dyn_load.c</tt>.
209
+ </ul>
210
+ The marker maintains an explicit stack of memory regions that are known
211
+ to be accessible, but that have not yet been searched for contained pointers.
212
+ Each stack entry contains the starting address of the block to be scanned,
213
+ as well as a descriptor of the block. If no layout information is
214
+ available for the block, then the descriptor is simply a length.
215
+ (For other possibilities, see <TT>gc_mark.h</tt>.)
216
+ <P>
217
+ At the beginning of the mark phase, all root segments
218
+ (as described above) are pushed on the
219
+ stack by <TT>GC_push_roots</tt>. (Registers and eagerly processed
220
+ stack sections are processed by pushing the referenced objects instead
221
+ of the stack section itself.) If <TT>ALL_INTERIOR_PTRS</tt> is not
222
+ defined, then stack roots require special treatment. In this case, the
223
+ normal marking code ignores interior pointers, but <TT>GC_push_all_stack</tt>
224
+ explicitly checks for interior pointers and pushes descriptors for target
225
+ objects.
226
+ <P>
227
+ The marker is structured to allow incremental marking.
228
+ Each call to <TT>GC_mark_some</tt> performs a small amount of
229
+ work towards marking the heap.
230
+ It maintains
231
+ explicit state in the form of <TT>GC_mark_state</tt>, which
232
+ identifies a particular sub-phase. Some other pieces of state, most
233
+ notably the mark stack, identify how much work remains to be done
234
+ in each sub-phase. The normal progression of mark states for
235
+ a stop-the-world collection is:
236
+ <OL>
237
+ <LI> <TT>MS_INVALID</tt> indicating that there may be accessible unmarked
238
+ objects. In this case <TT>GC_objects_are_marked</tt> will simultaneously
239
+ be false, so the mark state is advanced to
240
+ <LI> <TT>MS_PUSH_UNCOLLECTABLE</tt> indicating that it suffices to push
241
+ uncollectable objects, roots, and then mark everything reachable from them.
242
+ <TT>Scan_ptr</tt> is advanced through the heap until all uncollectable
243
+ objects are pushed, and objects reachable from them are marked.
244
+ At that point, the next call to <TT>GC_mark_some</tt> calls
245
+ <TT>GC_push_roots</tt> to push the roots. It the advances the
246
+ mark state to
247
+ <LI> <TT>MS_ROOTS_PUSHED</tt> asserting that once the mark stack is
248
+ empty, all reachable objects are marked. Once in this state, we work
249
+ only on emptying the mark stack. Once this is completed, the state
250
+ changes to
251
+ <LI> <TT>MS_NONE</tt> indicating that reachable objects are marked.
252
+ </ol>
253
+
254
+ The core mark routine <TT>GC_mark_from</tt>, is called
255
+ repeatedly by several of the sub-phases when the mark stack starts to fill
256
+ up. It is also called repeatedly in <TT>MS_ROOTS_PUSHED</tt> state
257
+ to empty the mark stack.
258
+ The routine is designed to only perform a limited amount of marking at
259
+ each call, so that it can also be used by the incremental collector.
260
+ It is fairly carefully tuned, since it usually consumes a large majority
261
+ of the garbage collection time.
262
+ <P>
263
+ The fact that it perform a only a small amount of work per call also
264
+ allows it to be used as the core routine of the parallel marker. In that
265
+ case it is normally invoked on thread-private mark stacks instead of the
266
+ global mark stack. More details can be found in
267
+ <A HREF="scale.html">scale.html</a>
268
+ <P>
269
+ The marker correctly handles mark stack overflows. Whenever the mark stack
270
+ overflows, the mark state is reset to <TT>MS_INVALID</tt>.
271
+ Since there are already marked objects in the heap,
272
+ this eventually forces a complete
273
+ scan of the heap, searching for pointers, during which any unmarked objects
274
+ referenced by marked objects are again pushed on the mark stack. This
275
+ process is repeated until the mark phase completes without a stack overflow.
276
+ Each time the stack overflows, an attempt is made to grow the mark stack.
277
+ All pieces of the collector that push regions onto the mark stack have to be
278
+ careful to ensure forward progress, even in case of repeated mark stack
279
+ overflows. Every mark attempt results in additional marked objects.
280
+ <P>
281
+ Each mark stack entry is processed by examining all candidate pointers
282
+ in the range described by the entry. If the region has no associated
283
+ type information, then this typically requires that each 4-byte aligned
284
+ quantity (8-byte aligned with 64-bit pointers) be considered a candidate
285
+ pointer.
286
+ <P>
287
+ We determine whether a candidate pointer is actually the address of
288
+ a heap block. This is done in the following steps:
289
+ <NL>
290
+ <LI> The candidate pointer is checked against rough heap bounds.
291
+ These heap bounds are maintained such that all actual heap objects
292
+ fall between them. In order to facilitate black-listing (see below)
293
+ we also include address regions that the heap is likely to expand into.
294
+ Most non-pointers fail this initial test.
295
+ <LI> The candidate pointer is divided into two pieces; the most significant
296
+ bits identify a <TT>HBLKSIZE</tt>-sized page in the address space, and
297
+ the least significant bits specify an offset within that page.
298
+ (A hardware page may actually consist of multiple such pages.
299
+ HBLKSIZE is usually the page size divided by a small power of two.)
300
+ <LI>
301
+ The page address part of the candidate pointer is looked up in a
302
+ <A HREF="tree.html">table</a>.
303
+ Each table entry contains either 0, indicating that the page is not part
304
+ of the garbage collected heap, a small integer <I>n</i>, indicating
305
+ that the page is part of large object, starting at least <I>n</i> pages
306
+ back, or a pointer to a descriptor for the page. In the first case,
307
+ the candidate pointer i not a true pointer and can be safely ignored.
308
+ In the last two cases, we can obtain a descriptor for the page containing
309
+ the beginning of the object.
310
+ <LI>
311
+ The starting address of the referenced object is computed.
312
+ The page descriptor contains the size of the object(s)
313
+ in that page, the object kind, and the necessary mark bits for those
314
+ objects. The size information can be used to map the candidate pointer
315
+ to the object starting address. To accelerate this process, the page header
316
+ also contains a pointer to a precomputed map of page offsets to displacements
317
+ from the beginning of an object. The use of this map avoids a
318
+ potentially slow integer remainder operation in computing the object
319
+ start address.
320
+ <LI>
321
+ The mark bit for the target object is checked and set. If the object
322
+ was previously unmarked, the object is pushed on the mark stack.
323
+ The descriptor is read from the page descriptor. (This is computed
324
+ from information <TT>GC_obj_kinds</tt> when the page is first allocated.)
325
+ </nl>
326
+ <P>
327
+ At the end of the mark phase, mark bits for left-over free lists are cleared,
328
+ in case a free list was accidentally marked due to a stray pointer.
329
+
330
+ <H2>Sweep phase</h2>
331
+
332
+ At the end of the mark phase, all blocks in the heap are examined.
333
+ Unmarked large objects are immediately returned to the large object free list.
334
+ Each small object page is checked to see if all mark bits are clear.
335
+ If so, the entire page is returned to the large object free list.
336
+ Small object pages containing some reachable object are queued for later
337
+ sweeping, unless we determine that the page contains very little free
338
+ space, in which case it is not examined further.
339
+ <P>
340
+ This initial sweep pass touches only block headers, not
341
+ the blocks themselves. Thus it does not require significant paging, even
342
+ if large sections of the heap are not in physical memory.
343
+ <P>
344
+ Nonempty small object pages are swept when an allocation attempt
345
+ encounters an empty free list for that object size and kind.
346
+ Pages for the correct size and kind are repeatedly swept until at
347
+ least one empty block is found. Sweeping such a page involves
348
+ scanning the mark bit array in the page header, and building a free
349
+ list linked through the first words in the objects themselves.
350
+ This does involve touching the appropriate data page, but in most cases
351
+ it will be touched only just before it is used for allocation.
352
+ Hence any paging is essentially unavoidable.
353
+ <P>
354
+ Except in the case of pointer-free objects, we maintain the invariant
355
+ that any object in a small object free list is cleared (except possibly
356
+ for the link field). Thus it becomes the burden of the small object
357
+ sweep routine to clear objects. This has the advantage that we can
358
+ easily recover from accidentally marking a free list, though that could
359
+ also be handled by other means. The collector currently spends a fair
360
+ amount of time clearing objects, and this approach should probably be
361
+ revisited.
362
+ <P>
363
+ In most configurations, we use specialized sweep routines to handle common
364
+ small object sizes. Since we allocate one mark bit per word, it becomes
365
+ easier to examine the relevant mark bits if the object size divides
366
+ the word length evenly. We also suitably unroll the inner sweep loop
367
+ in each case. (It is conceivable that profile-based procedure cloning
368
+ in the compiler could make this unnecessary and counterproductive. I
369
+ know of no existing compiler to which this applies.)
370
+ <P>
371
+ The sweeping of small object pages could be avoided completely at the expense
372
+ of examining mark bits directly in the allocator. This would probably
373
+ be more expensive, since each allocation call would have to reload
374
+ a large amount of state (e.g. next object address to be swept, position
375
+ in mark bit table) before it could do its work. The current scheme
376
+ keeps the allocator simple and allows useful optimizations in the sweeper.
377
+
378
+ <H2>Finalization</h2>
379
+ Both <TT>GC_register_disappearing_link</tt> and
380
+ <TT>GC_register_finalizer</tt> add the request to a corresponding hash
381
+ table. The hash table is allocated out of collected memory, but
382
+ the reference to the finalizable object is hidden from the collector.
383
+ Currently finalization requests are processed non-incrementally at the
384
+ end of a mark cycle.
385
+ <P>
386
+ The collector makes an initial pass over the table of finalizable objects,
387
+ pushing the contents of unmarked objects onto the mark stack.
388
+ After pushing each object, the marker is invoked to mark all objects
389
+ reachable from it. The object itself is not explicitly marked.
390
+ This assures that objects on which a finalizer depends are neither
391
+ collected nor finalized.
392
+ <P>
393
+ If in the process of marking from an object the
394
+ object itself becomes marked, we have uncovered
395
+ a cycle involving the object. This usually results in a warning from the
396
+ collector. Such objects are not finalized, since it may be
397
+ unsafe to do so. See the more detailed
398
+ <A HREF="http://www.hpl.hp.com/personal/Hans_Boehm/gc/finalization.html"> discussion of finalization semantics</a>.
399
+ <P>
400
+ Any objects remaining unmarked at the end of this process are added to
401
+ a queue of objects whose finalizers can be run. Depending on collector
402
+ configuration, finalizers are dequeued and run either implicitly during
403
+ allocation calls, or explicitly in response to a user request.
404
+ (Note that the former is unfortunately both the default and not generally safe.
405
+ If finalizers perform synchronization, it may result in deadlocks.
406
+ Nontrivial finalizers generally need to perform synchronization, and
407
+ thus require a different collector configuration.)
408
+ <P>
409
+ The collector provides a mechanism for replacing the procedure that is
410
+ used to mark through objects. This is used both to provide support for
411
+ Java-style unordered finalization, and to ignore certain kinds of cycles,
412
+ <I>e.g.</i> those arising from C++ implementations of virtual inheritance.
413
+
414
+ <H2>Generational Collection and Dirty Bits</h2>
415
+ We basically use the concurrent and generational GC algorithm described in
416
+ <A HREF="http://www.hpl.hp.com/personal/Hans_Boehm/gc/papers/pldi91.ps.Z">"Mostly Parallel Garbage Collection"</a>,
417
+ by Boehm, Demers, and Shenker.
418
+ <P>
419
+ The most significant modification is that
420
+ the collector always starts running in the allocating thread.
421
+ There is no separate garbage collector thread. (If parallel GC is
422
+ enabled, helper threads may also be woken up.)
423
+ If an allocation attempt either requests a large object, or encounters
424
+ an empty small object free list, and notices that there is a collection
425
+ in progress, it immediately performs a small amount of marking work
426
+ as described above.
427
+ <P>
428
+ This change was made both because we wanted to easily accommodate
429
+ single-threaded environments, and because a separate GC thread requires
430
+ very careful control over the scheduler to prevent the mutator from
431
+ out-running the collector, and hence provoking unneeded heap growth.
432
+ <P>
433
+ In incremental mode, the heap is always expanded when we encounter
434
+ insufficient space for an allocation. Garbage collection is triggered
435
+ whenever we notice that more than
436
+ <TT>GC_heap_size</tt>/2 * <TT>GC_free_space_divisor</tt>
437
+ bytes of allocation have taken place.
438
+ After <TT>GC_full_freq</tt> minor collections a major collection
439
+ is started.
440
+ <P>
441
+ All collections initially run interrupted until a predetermined
442
+ amount of time (50 msecs by default) has expired. If this allows
443
+ the collection to complete entirely, we can avoid correcting
444
+ for data structure modifications during the collection. If it does
445
+ not complete, we return control to the mutator, and perform small
446
+ amounts of additional GC work during those later allocations that
447
+ cannot be satisfied from small object free lists. When marking completes,
448
+ the set of modified pages is retrieved, and we mark once again from
449
+ marked objects on those pages, this time with the mutator stopped.
450
+ <P>
451
+ We keep track of modified pages using one of several distinct mechanisms:
452
+ <OL>
453
+ <LI>
454
+ Through explicit mutator cooperation. Currently this requires
455
+ the use of <TT>GC_malloc_stubborn</tt>, and is rarely used.
456
+ <LI>
457
+ (<TT>MPROTECT_VDB</tt>) By write-protecting physical pages and
458
+ catching write faults. This is
459
+ implemented for many Unix-like systems and for win32. It is not possible
460
+ in a few environments.
461
+ <LI>
462
+ (<TT>PROC_VDB</tt>) By retrieving dirty bit information from /proc.
463
+ (Currently only Sun's
464
+ Solaris supports this. Though this is considerably cleaner, performance
465
+ may actually be better with mprotect and signals.)
466
+ <LI>
467
+ (<TT>PCR_VDB</tt>) By relying on an external dirty bit implementation, in this
468
+ case the one in Xerox PCR.
469
+ <LI>
470
+ (<TT>DEFAULT_VDB</tt>) By treating all pages as dirty. This is the default if
471
+ none of the other techniques is known to be usable, and
472
+ <TT>GC_malloc_stubborn</tt> is not used. Practical only for testing, or if
473
+ the vast majority of objects use <TT>GC_malloc_stubborn</tt>.
474
+ </ol>
475
+
476
+ <H2>Black-listing</h2>
477
+
478
+ The collector implements <I>black-listing</i> of pages, as described
479
+ in
480
+ <A HREF="http://www.acm.org/pubs/citations/proceedings/pldi/155090/p197-boehm/">
481
+ Boehm, ``Space Efficient Conservative Collection'', PLDI '93</a>, also available
482
+ <A HREF="papers/pldi93.ps.Z">here</a>.
483
+ <P>
484
+ During the mark phase, the collector tracks ``near misses'', i.e. attempts
485
+ to follow a ``pointer'' to just outside the garbage-collected heap, or
486
+ to a currently unallocated page inside the heap. Pages that have been
487
+ the targets of such near misses are likely to be the targets of
488
+ misidentified ``pointers'' in the future. To minimize the future
489
+ damage caused by such misidentifications they will be allocated only to
490
+ small pointerfree objects.
491
+ <P>
492
+ The collector understands two different kinds of black-listing. A
493
+ page may be black listed for interior pointer references
494
+ (<TT>GC_add_to_black_list_stack</tt>), if it was the target of a near
495
+ miss from a location that requires interior pointer recognition,
496
+ <I>e.g.</i> the stack, or the heap if <TT>GC_all_interior_pointers</tt>
497
+ is set. In this case, we also avoid allocating large blocks that include
498
+ this page.
499
+ <P>
500
+ If the near miss came from a source that did not require interior
501
+ pointer recognition, it is black-listed with
502
+ <TT>GC_add_to_black_list_normal</tt>.
503
+ A page black-listed in this way may appear inside a large object,
504
+ so long as it is not the first page of a large object.
505
+ <P>
506
+ The <TT>GC_allochblk</tt> routine respects black-listing when assigning
507
+ a block to a particular object kind and size. It occasionally
508
+ drops (i.e. allocates and forgets) blocks that are completely black-listed
509
+ in order to avoid excessively long large block free lists containing
510
+ only unusable blocks. This would otherwise become an issue
511
+ if there is low demand for small pointerfree objects.
512
+
513
+ <H2>Thread support</h2>
514
+ We support several different threading models. Unfortunately Pthreads,
515
+ the only reasonably well standardized thread model, supports too narrow
516
+ an interface for conservative garbage collection. There appears to be
517
+ no completely portable way to allow the collector
518
+ to coexist with various Pthreads
519
+ implementations. Hence we currently support only the more
520
+ common Pthreads implementations.
521
+ <P>
522
+ In particular, it is very difficult for the collector to stop all other
523
+ threads in the system and examine the register contents. This is currently
524
+ accomplished with very different mechanisms for some Pthreads
525
+ implementations. The Solaris implementation temporarily disables much
526
+ of the user-level threads implementation by stopping kernel-level threads
527
+ ("lwp"s). The Linux/HPUX/OSF1 and Irix implementations sends signals to
528
+ individual Pthreads and has them wait in the signal handler.
529
+ <P>
530
+ The Linux and Irix implementations use
531
+ only documented Pthreads calls, but rely on extensions to their semantics.
532
+ The Linux implementation <TT>linux_threads.c</tt> relies on only very
533
+ mild extensions to the pthreads semantics, and already supports a large number
534
+ of other Unix-like pthreads implementations. Our goal is to make this the
535
+ only pthread support in the collector.
536
+ <P>
537
+ (The Irix implementation is separate only for historical reasons and should
538
+ clearly be merged. The current Solaris implementation probably performs
539
+ better in the uniprocessor case, but does not support thread operations in the
540
+ collector. Hence it cannot support the parallel marker.)
541
+ <P>
542
+ All implementations must
543
+ intercept thread creation and a few other thread-specific calls to allow
544
+ enumeration of threads and location of thread stacks. This is current
545
+ accomplished with <TT># define</tt>'s in <TT>gc.h</tt>
546
+ (really <TT>gc_pthread_redirects.h</tt>), or optionally
547
+ by using ld's function call wrapping mechanism under Linux.
548
+ <P>
549
+ Recent versions of the collector support several facilites to enhance
550
+ the processor-scalability and thread performance of the collector.
551
+ These are discussed in more detail <A HREF="scale.html">here</a>.
552
+ We briefly outline the data approach to thread-local allocation in the
553
+ next section.
554
+ <H2>Thread-local allocation</h2>
555
+ If thread-local allocation is enabled, the collector keeps separate
556
+ arrays of free lists for each thread. Thread-local allocation
557
+ is currently only supported on a few platforms.
558
+ <P>
559
+ The free list arrays associated
560
+ with each thread are only used to satisfy requests for objects that
561
+ are both very small, and belong to one of a small number of well-known
562
+ kinds. These currently include "normal" and pointer-free objects.
563
+ Depending onthe configuration, "gcj" objects may also be included.
564
+ <P>
565
+ Thread-local free list entries contain either a pointer to the first
566
+ element of a free list, or they contain a counter of the number of
567
+ allocation "granules" allocated so far. Initially they contain the
568
+ value one, i.e. a small counter value.
569
+ <P>
570
+ Thread-local allocation allocates directly through the global
571
+ allocator, if the object is of a size or kind not covered by the
572
+ local free lists.
573
+ <P>
574
+ If there is an appropriate local free list, the allocator checks whether it
575
+ contains a sufficiently small counter value. If so, the counter is simply
576
+ incremented by the counter value, and the global allocator is used.
577
+ In this way, the initial few allocations of a given size bypass the local
578
+ allocator. A thread that only allocates a handful of objects of a given
579
+ size will not build up its own free list for that size. This avoids
580
+ wasting space for unpopular objects sizes or kinds.
581
+ <P>
582
+ Once the counter passes a threshold, <TT>GC_malloc_many</tt> is called
583
+ to allocate roughly <TT>HBLKSIZE</tt> space and put it on the corresponding
584
+ local free list. Further allocations of that size and kind then use
585
+ this free list, and no longer need to acquire the allocation lock.
586
+ The allocation procedure is otherwise similar to the global free lists.
587
+ The local free lists are also linked using the first word in the object.
588
+ In most cases this means they require considerably less time.
589
+ <P>
590
+ Local free lists are treated buy most of the rest of the collector
591
+ as though they were in-use reachable data. This requires some care,
592
+ since pointer-free objects are not normally traced, and hence a special
593
+ tracing procedure is required to mark all objects on pointer-free and
594
+ gcj local free lists.
595
+ <P>
596
+ On thread exit, any remaining thread-local free list entries are
597
+ transferred back to the global free list.
598
+ <P>
599
+ Note that if the collector is configured for thread-local allocation,
600
+ GC versions before 7 do not invoke the thread-local allocator by default.
601
+ <TT>GC_malloc</tt> only uses thread-local allocation in version 7 and later.
602
+ In earlier versions, <TT>GC_MALLOC</tt> (all caps) may be directed
603
+ to use thread-local allocation by defining <TT>GC_REDIRECT_TO_LOCAL</tt>
604
+ and then include <TT>gc_local_alloc.h</tt>.
605
+ <P>
606
+ For some more details see <A HREF="scale.html">here</a>, and the
607
+ technical report entitled
608
+ <A HREF="http://www.hpl.hp.com/techreports/2000/HPL-2000-165.html">
609
+ ``Fast Multiprocessor Memory Allocation and Garbage Collection''
610
+ </a>
611
+ <P>
612
+ <HR>
613
+ <P>
614
+ Comments are appreciated. Please send mail to
615
+ <A HREF="mailto:boehm@acm.org"><TT>boehm@acm.org</tt></a> or
616
+ <A HREF="mailto:Hans.Boehm@hp.com"><TT>Hans.Boehm@hp.com</tt></a>
617
+ <P>
618
+ This is a modified copy of a page written while the author was at SGI.
619
+ The original was <A HREF="http://reality.sgi.com/boehm/gcdescr.html">here</a>.
620
+ </body>
621
+ </html>
mosesdecoder/jam-files/engine/boehm_gc/doc/scale.html ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <HTML>
2
+ <HEAD>
3
+ <TITLE>Garbage collector scalability</TITLE>
4
+ </HEAD>
5
+ <BODY>
6
+ <H1>Garbage collector scalability</h1>
7
+ In its default configuration, the Boehm-Demers-Weiser garbage collector
8
+ is not thread-safe. It can be made thread-safe for a number of environments
9
+ by building the collector with the appropriate
10
+ <TT>-D</tt><I>XXX</i><TT>-THREADS</tt> compilation
11
+ flag. This has primarily two effects:
12
+ <OL>
13
+ <LI> It causes the garbage collector to stop all other threads when
14
+ it needs to see a consistent memory state.
15
+ <LI> It causes the collector to acquire a lock around essentially all
16
+ allocation and garbage collection activity.
17
+ </ol>
18
+ Since a single lock is used for all allocation-related activity, only one
19
+ thread can be allocating or collecting at one point. This inherently
20
+ limits performance of multi-threaded applications on multiprocessors.
21
+ <P>
22
+ On most platforms, the allocator/collector lock is implemented as a
23
+ spin lock with exponential back-off. Longer wait times are implemented
24
+ by yielding and/or sleeping. If a collection is in progress, the pure
25
+ spinning stage is skipped. This has the advantage that uncontested and
26
+ thus most uniprocessor lock acquisitions are very cheap. It has the
27
+ disadvantage that the application may sleep for small periods of time
28
+ even when there is work to be done. And threads may be unnecessarily
29
+ woken up for short periods. Nonetheless, this scheme empirically
30
+ outperforms native queue-based mutual exclusion implementations in most
31
+ cases, sometimes drastically so.
32
+ <H2>Options for enhanced scalability</h2>
33
+ Version 6.0 of the collector adds two facilities to enhance collector
34
+ scalability on multiprocessors. As of 6.0alpha1, these are supported
35
+ only under Linux on X86 and IA64 processors, though ports to other
36
+ otherwise supported Pthreads platforms should be straightforward.
37
+ They are intended to be used together.
38
+ <UL>
39
+ <LI>
40
+ Building the collector with <TT>-DPARALLEL_MARK</tt> allows the collector to
41
+ run the mark phase in parallel in multiple threads, and thus on multiple
42
+ processors. The mark phase typically consumes the large majority of the
43
+ collection time. Thus this largely parallelizes the garbage collector
44
+ itself, though not the allocation process. Currently the marking is
45
+ performed by the thread that triggered the collection, together with
46
+ <I>N</i>-1 dedicated
47
+ threads, where <I>N</i> is the number of processors detected by the collector.
48
+ The dedicated threads are created once at initialization time.
49
+ <P>
50
+ A second effect of this flag is to switch to a more concurrent
51
+ implementation of <TT>GC_malloc_many</tt>, so that free lists can be
52
+ built, and memory can be cleared, by more than one thread concurrently.
53
+ <LI>
54
+ Building the collector with -DTHREAD_LOCAL_ALLOC adds support for thread
55
+ local allocation. It does not, by itself, cause thread local allocation
56
+ to be used. It simply allows the use of the interface in
57
+ <TT>gc_local_alloc.h</tt>.
58
+ <P>
59
+ Memory returned from thread-local allocators is completely interchangeable
60
+ with that returned by the standard allocators. It may be used by other
61
+ threads. The only difference is that, if the thread allocates enough
62
+ memory of a certain kind, it will build a thread-local free list for
63
+ objects of that kind, and allocate from that. This greatly reduces
64
+ locking. The thread-local free lists are refilled using
65
+ <TT>GC_malloc_many</tt>.
66
+ <P>
67
+ An important side effect of this flag is to replace the default
68
+ spin-then-sleep lock to be replace by a spin-then-queue based implementation.
69
+ This <I>reduces performance</i> for the standard allocation functions,
70
+ though it usually improves performance when thread-local allocation is
71
+ used heavily, and thus the number of short-duration lock acquisitions
72
+ is greatly reduced.
73
+ </ul>
74
+ <P>
75
+ The easiest way to switch an application to thread-local allocation is to
76
+ <OL>
77
+ <LI> Define the macro <TT>GC_REDIRECT_TO_LOCAL</tt>,
78
+ and then include the <TT>gc.h</tt>
79
+ header in each client source file.
80
+ <LI> Invoke <TT>GC_thr_init()</tt> before any allocation.
81
+ <LI> Allocate using <TT>GC_MALLOC</tt>, <TT>GC_MALLOC_ATOMIC</tt>,
82
+ and/or <TT>GC_GCJ_MALLOC</tt>.
83
+ </ol>
84
+ <H2>The Parallel Marking Algorithm</h2>
85
+ We use an algorithm similar to
86
+ <A HREF="http://www.yl.is.s.u-tokyo.ac.jp/gc/">that developed by
87
+ Endo, Taura, and Yonezawa</a> at the University of Tokyo.
88
+ However, the data structures and implementation are different,
89
+ and represent a smaller change to the original collector source,
90
+ probably at the expense of extreme scalability. Some of
91
+ the refinements they suggest, <I>e.g.</i> splitting large
92
+ objects, were also incorporated into out approach.
93
+ <P>
94
+ The global mark stack is transformed into a global work queue.
95
+ Unlike the usual case, it never shrinks during a mark phase.
96
+ The mark threads remove objects from the queue by copying them to a
97
+ local mark stack and changing the global descriptor to zero, indicating
98
+ that there is no more work to be done for this entry.
99
+ This removal
100
+ is done with no synchronization. Thus it is possible for more than
101
+ one worker to remove the same entry, resulting in some work duplication.
102
+ <P>
103
+ The global work queue grows only if a marker thread decides to
104
+ return some of its local mark stack to the global one. This
105
+ is done if the global queue appears to be running low, or if
106
+ the local stack is in danger of overflowing. It does require
107
+ synchronization, but should be relatively rare.
108
+ <P>
109
+ The sequential marking code is reused to process local mark stacks.
110
+ Hence the amount of additional code required for parallel marking
111
+ is minimal.
112
+ <P>
113
+ It should be possible to use generational collection in the presence of the
114
+ parallel collector, by calling <TT>GC_enable_incremental()</tt>.
115
+ This does not result in fully incremental collection, since parallel mark
116
+ phases cannot currently be interrupted, and doing so may be too
117
+ expensive.
118
+ <P>
119
+ Gcj-style mark descriptors do not currently mix with the combination
120
+ of local allocation and incremental collection. They should work correctly
121
+ with one or the other, but not both.
122
+ <P>
123
+ The number of marker threads is set on startup to the number of
124
+ available processors (or to the value of the <TT>GC_NPROCS</tt>
125
+ environment variable). If only a single processor is detected,
126
+ parallel marking is disabled.
127
+ <P>
128
+ Note that setting GC_NPROCS to 1 also causes some lock acquisitions inside
129
+ the collector to immediately yield the processor instead of busy waiting
130
+ first. In the case of a multiprocessor and a client with multiple
131
+ simultaneously runnable threads, this may have disastrous performance
132
+ consequences (e.g. a factor of 10 slowdown).
133
+ <H2>Performance</h2>
134
+ We conducted some simple experiments with a version of
135
+ <A HREF="gc_bench.html">our GC benchmark</a> that was slightly modified to
136
+ run multiple concurrent client threads in the same address space.
137
+ Each client thread does the same work as the original benchmark, but they share
138
+ a heap.
139
+ This benchmark involves very little work outside of memory allocation.
140
+ This was run with GC 6.0alpha3 on a dual processor Pentium III/500 machine
141
+ under Linux 2.2.12.
142
+ <P>
143
+ Running with a thread-unsafe collector, the benchmark ran in 9
144
+ seconds. With the simple thread-safe collector,
145
+ built with <TT>-DLINUX_THREADS</tt>, the execution time
146
+ increased to 10.3 seconds, or 23.5 elapsed seconds with two clients.
147
+ (The times for the <TT>malloc</tt>/i<TT>free</tt> version
148
+ with glibc <TT>malloc</tt>
149
+ are 10.51 (standard library, pthreads not linked),
150
+ 20.90 (one thread, pthreads linked),
151
+ and 24.55 seconds respectively. The benchmark favors a
152
+ garbage collector, since most objects are small.)
153
+ <P>
154
+ The following table gives execution times for the collector built
155
+ with parallel marking and thread-local allocation support
156
+ (<TT>-DGC_LINUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC</tt>). We tested
157
+ the client using either one or two marker threads, and running
158
+ one or two client threads. Note that the client uses thread local
159
+ allocation exclusively. With -DTHREAD_LOCAL_ALLOC the collector
160
+ switches to a locking strategy that is better tuned to less frequent
161
+ lock acquisition. The standard allocation primitives thus peform
162
+ slightly worse than without -DTHREAD_LOCAL_ALLOC, and should be
163
+ avoided in time-critical code.
164
+ <P>
165
+ (The results using <TT>pthread_mutex_lock</tt>
166
+ directly for allocation locking would have been worse still, at
167
+ least for older versions of linuxthreads.
168
+ With THREAD_LOCAL_ALLOC, we first repeatedly try to acquire the
169
+ lock with pthread_mutex_try_lock(), busy_waiting between attempts.
170
+ After a fixed number of attempts, we use pthread_mutex_lock().)
171
+ <P>
172
+ These measurements do not use incremental collection, nor was prefetching
173
+ enabled in the marker. We used the C version of the benchmark.
174
+ All measurements are in elapsed seconds on an unloaded machine.
175
+ <P>
176
+ <TABLE BORDER ALIGN="CENTER">
177
+ <TR><TH>Number of threads</th><TH>1 marker thread (secs.)</th>
178
+ <TH>2 marker threads (secs.)</th></tr>
179
+ <TR><TD>1 client</td><TD ALIGN="CENTER">10.45</td><TD ALIGN="CENTER">7.85</td>
180
+ <TR><TD>2 clients</td><TD ALIGN="CENTER">19.95</td><TD ALIGN="CENTER">12.3</td>
181
+ </table>
182
+ <PP>
183
+ The execution time for the single threaded case is slightly worse than with
184
+ simple locking. However, even the single-threaded benchmark runs faster than
185
+ even the thread-unsafe version if a second processor is available.
186
+ The execution time for two clients with thread local allocation time is
187
+ only 1.4 times the sequential execution time for a single thread in a
188
+ thread-unsafe environment, even though it involves twice the client work.
189
+ That represents close to a
190
+ factor of 2 improvement over the 2 client case with the old collector.
191
+ The old collector clearly
192
+ still suffered from some contention overhead, in spite of the fact that the
193
+ locking scheme had been fairly well tuned.
194
+ <P>
195
+ Full linear speedup (i.e. the same execution time for 1 client on one
196
+ processor as 2 clients on 2 processors)
197
+ is probably not achievable on this kind of
198
+ hardware even with such a small number of processors,
199
+ since the memory system is
200
+ a major constraint for the garbage collector,
201
+ the processors usually share a single memory bus, and thus
202
+ the aggregate memory bandwidth does not increase in
203
+ proportion to the number of processors.
204
+ <P>
205
+ These results are likely to be very sensitive to both hardware and OS
206
+ issues. Preliminary experiments with an older Pentium Pro machine running
207
+ an older kernel were far less encouraging.
208
+
209
+ </body>
210
+ </html>
mosesdecoder/jam-files/engine/boehm_gc/doc/simple_example.html ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <HTML>
2
+ <HEAD>
3
+ <TITLE>Using the Garbage Collector: A simple example</title>
4
+ </head>
5
+ <BODY>
6
+ <H1>Using the Garbage Collector: A simple example</h1>
7
+ The following consists of step-by-step instructions for building and
8
+ using the collector. We'll assume a Linux/gcc platform and
9
+ a single-threaded application. <FONT COLOR=green>The green
10
+ text contains information about other platforms or scenarios.
11
+ It can be skipped, especially on first reading</font>.
12
+ <H2>Building the collector</h2>
13
+ If you haven't already so, unpack the collector and enter
14
+ the newly created directory with
15
+ <PRE>
16
+ tar xvfz gc<version>.tar.gz
17
+ cd gc<version>
18
+ </pre>
19
+ <P>
20
+ You can configure, build, and install the collector in a private
21
+ directory, say /home/xyz/gc, with the following commands:
22
+ <PRE>
23
+ ./configure --prefix=/home/xyz/gc --disable-threads
24
+ make
25
+ make check
26
+ make install
27
+ </pre>
28
+ Here the "<TT>make check</tt>" command is optional, but highly recommended.
29
+ It runs a basic correctness test which usually takes well under a minute.
30
+ <FONT COLOR=green>
31
+ <H3>Other platforms</h3>
32
+ On non-Unix, non-Linux platforms, the collector is usually built by copying
33
+ the appropriate makefile (see the platform-specific README in doc/README.xxx
34
+ in the distribution) to the file "Makefile" (overwriting the copy of
35
+ Makefile.direct that was originally there), and then typing "make"
36
+ (or "nmake" or ...). This builds the library in the source tree. You may
37
+ want to move it and the files in the include directory to a more convenient
38
+ place.
39
+ <P>
40
+ If you use a makefile that does not require running a configure script,
41
+ you should first look at the makefile, and adjust any options that are
42
+ documented there.
43
+ <P>
44
+ If your platform provides a "make" utility, that is generally preferred
45
+ to platform- and compiler- dependent "project" files. (At least that is the
46
+ strong preference of the would-be maintainer of those project files.)
47
+ <H3>Threads</h3>
48
+ If you need thread support, configure the collector with
49
+ <PRE>
50
+ --enable-threads=posix --enable-thread-local-alloc --enable-parallel-mark
51
+ </pre>
52
+ instead of
53
+ <TT>--disable-threads</tt>
54
+ If your target is a real old-fashioned uniprocessor (no "hyperthreading",
55
+ etc.) you will want to omit <TT>--enable-parallel-mark</tt>.
56
+ <H3>C++</h3>
57
+ You will need to include the C++ support, which unfortunately tends to
58
+ be among the least portable parts of the collector, since it seems
59
+ to rely on some corner cases of the language. On Linux, it
60
+ suffices to add <TT>--enable-cplusplus</tt> to the configure options.
61
+ </font>
62
+ <H2>Writing the program</h2>
63
+ You will need a
64
+ <PRE>
65
+ #include "gc.h"
66
+ </pre>
67
+ at the beginning of every file that allocates memory through the
68
+ garbage collector. Call <TT>GC_MALLOC</tt> wherever you would
69
+ have call <TT>malloc</tt>. This initializes memory to zero like
70
+ <TT>calloc</tt>; there is no need to explicitly clear the
71
+ result.
72
+ <P>
73
+ If you know that an object will not contain pointers to the
74
+ garbage-collected heap, and you don't need it to be initialized,
75
+ call <TT>GC_MALLOC_ATOMIC</tt> instead.
76
+ <P>
77
+ A function <TT>GC_FREE</tt> is provided but need not be called.
78
+ For very small objects, your program will probably perform better if
79
+ you do not call it, and let the collector do its job.
80
+ <P>
81
+ A <TT>GC_REALLOC</tt> function behaves like the C library <TT>realloc</tt>.
82
+ It allocates uninitialized pointer-free memory if the original
83
+ object was allocated that way.
84
+ <P>
85
+ The following program <TT>loop.c</tt> is a trivial example:
86
+ <PRE>
87
+ #include "gc.h"
88
+ #include &lt;assert.h&gt;
89
+ #include &lt;stdio.h&gt;
90
+
91
+ int main()
92
+ {
93
+ int i;
94
+
95
+ GC_INIT(); /* Optional on Linux/X86; see below. */
96
+ for (i = 0; i < 10000000; ++i)
97
+ {
98
+ int **p = (int **) GC_MALLOC(sizeof(int *));
99
+ int *q = (int *) GC_MALLOC_ATOMIC(sizeof(int));
100
+ assert(*p == 0);
101
+ *p = (int *) GC_REALLOC(q, 2 * sizeof(int));
102
+ if (i % 100000 == 0)
103
+ printf("Heap size = %d\n", GC_get_heap_size());
104
+ }
105
+ return 0;
106
+ }
107
+ </pre>
108
+ <FONT COLOR=green>
109
+ <H3>Interaction with the system malloc</h3>
110
+ It is usually best not to mix garbage-collected allocation with the system
111
+ <TT>malloc-free</tt>. If you do, you need to be careful not to store
112
+ pointers to the garbage-collected heap in memory allocated with the system
113
+ <TT>malloc</tt>.
114
+ <H3>Other Platforms</h3>
115
+ On some other platforms it is necessary to call <TT>GC_INIT()</tt> from the main program,
116
+ which is presumed to be part of the main executable, not a dynamic library.
117
+ This can never hurt, and is thus generally good practice.
118
+
119
+ <H3>Threads</h3>
120
+ For a multithreaded program some more rules apply:
121
+ <UL>
122
+ <LI>
123
+ Files that either allocate through the GC <I>or make thread-related calls</i>
124
+ should first define the macro <TT>GC_THREADS</tt>, and then
125
+ include <TT>"gc.h"</tt>. On some platforms this will redefine some
126
+ threads primitives, e.g. to let the collector keep track of thread creation.
127
+ <LI>
128
+ To take advantage of fast thread-local allocation, use the following instead
129
+ of including <TT>gc.h</tt>:
130
+ <PRE>
131
+ #define GC_REDIRECT_TO_LOCAL
132
+ #include "gc_local_alloc.h"
133
+ </pre>
134
+ This will cause GC_MALLOC and GC_MALLOC_ATOMIC to keep per-thread allocation
135
+ caches, and greatly reduce the number of lock acquisitions during allocation.
136
+ </ul>
137
+
138
+ <H3>C++</h3>
139
+ In the case of C++, you need to be especially careful not to store pointers
140
+ to the garbage-collected heap in areas that are not traced by the collector.
141
+ The collector includes some <A HREF="gcinterface.html">alternate interfaces</a>
142
+ to make that easier.
143
+
144
+ <H3>Debugging</h3>
145
+ Additional debug checks can be performed by defining <TT>GC_DEBUG</tt> before
146
+ including <TT>gc.h</tt>. Additional options are available if the collector
147
+ is also built with <TT>--enable-full_debug</tt> and all allocations are
148
+ performed with <TT>GC_DEBUG</tt> defined.
149
+
150
+ <H3>What if I can't rewrite/recompile my program?</h3>
151
+ You may be able to build the collector with <TT>--enable-redirect-malloc</tt>
152
+ and set the <TT>LD_PRELOAD</tt> environment variable to point to the resulting
153
+ library, thus replacing the standard <TT>malloc</tt> with its garbage-collected
154
+ counterpart. This is rather platform dependent. See the
155
+ <A HREF="leak.html">leak detection documentation</a> for some more details.
156
+
157
+ </font>
158
+
159
+ <H2>Compiling and linking</h2>
160
+
161
+ The above application <TT>loop.c</tt> test program can be compiled and linked
162
+ with
163
+
164
+ <PRE>
165
+ cc -I/home/xyz/gc/include loop.c /home/xyz/gc/lib/libgc.a -o loop
166
+ </pre>
167
+
168
+ The <TT>-I</tt> option directs the compiler to the right include
169
+ directory. In this case, we list the static library
170
+ directly on the compile line; the dynamic library could have been
171
+ used instead, provided we arranged for the dynamic loader to find
172
+ it, e.g. by setting <TT>LD_LIBRARY_PATH</tt>.
173
+
174
+ <FONT COLOR=green>
175
+
176
+ <H3>Threads</h3>
177
+
178
+ On pthread platforms, you will of course also have to link with
179
+ <TT>-lpthread</tt>,
180
+ and compile with any thread-safety options required by your compiler.
181
+ On some platforms, you may also need to link with <TT>-ldl</tt>
182
+ or <TT>-lrt</tt>.
183
+ Looking at threadlibs.c in the GC build directory
184
+ should give you the appropriate
185
+ list if a plain <TT>-lpthread</tt> doesn't work.
186
+
187
+ </font>
188
+
189
+ <H2>Running the executable</h2>
190
+
191
+ The executable can of course be run normally, e.g. by typing
192
+
193
+ <PRE>
194
+ ./loop
195
+ </pre>
196
+
197
+ The operation of the collector is affected by a number of environment variables.
198
+ For example, setting <TT>GC_PRINT_STATS</tt> produces some
199
+ GC statistics on stdout.
200
+ See <TT>README.environment</tt> in the distribution for details.
201
+ </body>
202
+ </html>
mosesdecoder/jam-files/engine/boehm_gc/finalize.c ADDED
@@ -0,0 +1,869 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
3
+ * Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved.
4
+ * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
5
+ * Copyright (C) 2007 Free Software Foundation, Inc
6
+
7
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
8
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
9
+ *
10
+ * Permission is hereby granted to use or copy this program
11
+ * for any purpose, provided the above notices are retained on all copies.
12
+ * Permission to modify the code and to distribute modified code is granted,
13
+ * provided the above notices are retained, and a notice that the code was
14
+ * modified is included with the above copyright notice.
15
+ */
16
+ /* Boehm, February 1, 1996 1:19 pm PST */
17
+ # define I_HIDE_POINTERS
18
+ # include "private/gc_pmark.h"
19
+
20
+ # ifdef FINALIZE_ON_DEMAND
21
+ int GC_finalize_on_demand = 1;
22
+ # else
23
+ int GC_finalize_on_demand = 0;
24
+ # endif
25
+
26
+ # ifdef JAVA_FINALIZATION
27
+ int GC_java_finalization = 1;
28
+ # else
29
+ int GC_java_finalization = 0;
30
+ # endif
31
+
32
+ /* Type of mark procedure used for marking from finalizable object. */
33
+ /* This procedure normally does not mark the object, only its */
34
+ /* descendents. */
35
+ typedef void finalization_mark_proc(/* ptr_t finalizable_obj_ptr */);
36
+
37
+ # define HASH3(addr,size,log_size) \
38
+ ((((word)(addr) >> 3) ^ ((word)(addr) >> (3+(log_size)))) \
39
+ & ((size) - 1))
40
+ #define HASH2(addr,log_size) HASH3(addr, 1 << log_size, log_size)
41
+
42
+ struct hash_chain_entry {
43
+ word hidden_key;
44
+ struct hash_chain_entry * next;
45
+ };
46
+
47
+ unsigned GC_finalization_failures = 0;
48
+ /* Number of finalization requests that failed for lack of memory. */
49
+
50
+ static struct disappearing_link {
51
+ struct hash_chain_entry prolog;
52
+ # define dl_hidden_link prolog.hidden_key
53
+ /* Field to be cleared. */
54
+ # define dl_next(x) (struct disappearing_link *)((x) -> prolog.next)
55
+ # define dl_set_next(x,y) (x) -> prolog.next = (struct hash_chain_entry *)(y)
56
+
57
+ word dl_hidden_obj; /* Pointer to object base */
58
+ } **dl_head = 0;
59
+
60
+ static signed_word log_dl_table_size = -1;
61
+ /* Binary log of */
62
+ /* current size of array pointed to by dl_head. */
63
+ /* -1 ==> size is 0. */
64
+
65
+ word GC_dl_entries = 0; /* Number of entries currently in disappearing */
66
+ /* link table. */
67
+
68
+ static struct finalizable_object {
69
+ struct hash_chain_entry prolog;
70
+ # define fo_hidden_base prolog.hidden_key
71
+ /* Pointer to object base. */
72
+ /* No longer hidden once object */
73
+ /* is on finalize_now queue. */
74
+ # define fo_next(x) (struct finalizable_object *)((x) -> prolog.next)
75
+ # define fo_set_next(x,y) (x) -> prolog.next = (struct hash_chain_entry *)(y)
76
+ GC_finalization_proc fo_fn; /* Finalizer. */
77
+ ptr_t fo_client_data;
78
+ word fo_object_size; /* In bytes. */
79
+ finalization_mark_proc * fo_mark_proc; /* Mark-through procedure */
80
+ } **fo_head = 0;
81
+
82
+ struct finalizable_object * GC_finalize_now = 0;
83
+ /* LIst of objects that should be finalized now. */
84
+
85
+ static signed_word log_fo_table_size = -1;
86
+
87
+ word GC_fo_entries = 0;
88
+
89
+ void GC_push_finalizer_structures(void)
90
+ {
91
+ GC_push_all((ptr_t)(&dl_head), (ptr_t)(&dl_head) + sizeof(word));
92
+ GC_push_all((ptr_t)(&fo_head), (ptr_t)(&fo_head) + sizeof(word));
93
+ GC_push_all((ptr_t)(&GC_finalize_now),
94
+ (ptr_t)(&GC_finalize_now) + sizeof(word));
95
+ }
96
+
97
+ /* Double the size of a hash table. *size_ptr is the log of its current */
98
+ /* size. May be a noop. */
99
+ /* *table is a pointer to an array of hash headers. If we succeed, we */
100
+ /* update both *table and *log_size_ptr. */
101
+ /* Lock is held. Signals are disabled. */
102
+ void GC_grow_table(struct hash_chain_entry ***table,
103
+ signed_word *log_size_ptr)
104
+ {
105
+ register word i;
106
+ register struct hash_chain_entry *p;
107
+ signed_word log_old_size = *log_size_ptr;
108
+ signed_word log_new_size = log_old_size + 1;
109
+ word old_size = ((log_old_size == -1)? 0: (1 << log_old_size));
110
+ word new_size = (word)1 << log_new_size;
111
+ /* FIXME: Power of 2 size often gets rounded up to one more page. */
112
+ struct hash_chain_entry **new_table = (struct hash_chain_entry **)
113
+ GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE(
114
+ (size_t)new_size * sizeof(struct hash_chain_entry *), NORMAL);
115
+
116
+ if (new_table == 0) {
117
+ if (table == 0) {
118
+ ABORT("Insufficient space for initial table allocation");
119
+ } else {
120
+ return;
121
+ }
122
+ }
123
+ for (i = 0; i < old_size; i++) {
124
+ p = (*table)[i];
125
+ while (p != 0) {
126
+ ptr_t real_key = (ptr_t)REVEAL_POINTER(p -> hidden_key);
127
+ struct hash_chain_entry *next = p -> next;
128
+ size_t new_hash = HASH3(real_key, new_size, log_new_size);
129
+
130
+ p -> next = new_table[new_hash];
131
+ new_table[new_hash] = p;
132
+ p = next;
133
+ }
134
+ }
135
+ *log_size_ptr = log_new_size;
136
+ *table = new_table;
137
+ }
138
+
139
+ int GC_register_disappearing_link(void * * link)
140
+ {
141
+ ptr_t base;
142
+
143
+ base = (ptr_t)GC_base((void *)link);
144
+ if (base == 0)
145
+ ABORT("Bad arg to GC_register_disappearing_link");
146
+ return(GC_general_register_disappearing_link(link, base));
147
+ }
148
+
149
+ int GC_general_register_disappearing_link(void * * link, void * obj)
150
+ {
151
+ struct disappearing_link *curr_dl;
152
+ size_t index;
153
+ struct disappearing_link * new_dl;
154
+ DCL_LOCK_STATE;
155
+
156
+ if ((word)link & (ALIGNMENT-1))
157
+ ABORT("Bad arg to GC_general_register_disappearing_link");
158
+ # ifdef THREADS
159
+ LOCK();
160
+ # endif
161
+ if (log_dl_table_size == -1
162
+ || GC_dl_entries > ((word)1 << log_dl_table_size)) {
163
+ GC_grow_table((struct hash_chain_entry ***)(&dl_head),
164
+ &log_dl_table_size);
165
+ if (GC_print_stats) {
166
+ GC_log_printf("Grew dl table to %u entries\n",
167
+ (1 << log_dl_table_size));
168
+ }
169
+ }
170
+ index = HASH2(link, log_dl_table_size);
171
+ curr_dl = dl_head[index];
172
+ for (curr_dl = dl_head[index]; curr_dl != 0; curr_dl = dl_next(curr_dl)) {
173
+ if (curr_dl -> dl_hidden_link == HIDE_POINTER(link)) {
174
+ curr_dl -> dl_hidden_obj = HIDE_POINTER(obj);
175
+ # ifdef THREADS
176
+ UNLOCK();
177
+ # endif
178
+ return(1);
179
+ }
180
+ }
181
+ new_dl = (struct disappearing_link *)
182
+ GC_INTERNAL_MALLOC(sizeof(struct disappearing_link),NORMAL);
183
+ if (0 == new_dl) {
184
+ # ifdef THREADS
185
+ UNLOCK();
186
+ # endif
187
+ new_dl = (struct disappearing_link *)
188
+ GC_oom_fn(sizeof(struct disappearing_link));
189
+ if (0 == new_dl) {
190
+ GC_finalization_failures++;
191
+ return(0);
192
+ }
193
+ /* It's not likely we'll make it here, but ... */
194
+ # ifdef THREADS
195
+ LOCK();
196
+ # endif
197
+ }
198
+ new_dl -> dl_hidden_obj = HIDE_POINTER(obj);
199
+ new_dl -> dl_hidden_link = HIDE_POINTER(link);
200
+ dl_set_next(new_dl, dl_head[index]);
201
+ dl_head[index] = new_dl;
202
+ GC_dl_entries++;
203
+ # ifdef THREADS
204
+ UNLOCK();
205
+ # endif
206
+ return(0);
207
+ }
208
+
209
+ int GC_unregister_disappearing_link(void * * link)
210
+ {
211
+ struct disappearing_link *curr_dl, *prev_dl;
212
+ size_t index;
213
+ DCL_LOCK_STATE;
214
+
215
+ LOCK();
216
+ index = HASH2(link, log_dl_table_size);
217
+ if (((word)link & (ALIGNMENT-1))) goto out;
218
+ prev_dl = 0; curr_dl = dl_head[index];
219
+ while (curr_dl != 0) {
220
+ if (curr_dl -> dl_hidden_link == HIDE_POINTER(link)) {
221
+ if (prev_dl == 0) {
222
+ dl_head[index] = dl_next(curr_dl);
223
+ } else {
224
+ dl_set_next(prev_dl, dl_next(curr_dl));
225
+ }
226
+ GC_dl_entries--;
227
+ UNLOCK();
228
+ # ifdef DBG_HDRS_ALL
229
+ dl_set_next(curr_dl, 0);
230
+ # else
231
+ GC_free((void *)curr_dl);
232
+ # endif
233
+ return(1);
234
+ }
235
+ prev_dl = curr_dl;
236
+ curr_dl = dl_next(curr_dl);
237
+ }
238
+ out:
239
+ UNLOCK();
240
+ return(0);
241
+ }
242
+
243
+ /* Possible finalization_marker procedures. Note that mark stack */
244
+ /* overflow is handled by the caller, and is not a disaster. */
245
+ GC_API void GC_normal_finalize_mark_proc(ptr_t p)
246
+ {
247
+ hdr * hhdr = HDR(p);
248
+
249
+ PUSH_OBJ(p, hhdr, GC_mark_stack_top,
250
+ &(GC_mark_stack[GC_mark_stack_size]));
251
+ }
252
+
253
+ /* This only pays very partial attention to the mark descriptor. */
254
+ /* It does the right thing for normal and atomic objects, and treats */
255
+ /* most others as normal. */
256
+ GC_API void GC_ignore_self_finalize_mark_proc(ptr_t p)
257
+ {
258
+ hdr * hhdr = HDR(p);
259
+ word descr = hhdr -> hb_descr;
260
+ ptr_t q, r;
261
+ ptr_t scan_limit;
262
+ ptr_t target_limit = p + hhdr -> hb_sz - 1;
263
+
264
+ if ((descr & GC_DS_TAGS) == GC_DS_LENGTH) {
265
+ scan_limit = p + descr - sizeof(word);
266
+ } else {
267
+ scan_limit = target_limit + 1 - sizeof(word);
268
+ }
269
+ for (q = p; q <= scan_limit; q += ALIGNMENT) {
270
+ r = *(ptr_t *)q;
271
+ if (r < p || r > target_limit) {
272
+ GC_PUSH_ONE_HEAP(r, q);
273
+ }
274
+ }
275
+ }
276
+
277
+ /*ARGSUSED*/
278
+ GC_API void GC_null_finalize_mark_proc(ptr_t p)
279
+ {
280
+ }
281
+
282
+ /* Possible finalization_marker procedures. Note that mark stack */
283
+ /* overflow is handled by the caller, and is not a disaster. */
284
+
285
+ /* GC_unreachable_finalize_mark_proc is an alias for normal marking, */
286
+ /* but it is explicitly tested for, and triggers different */
287
+ /* behavior. Objects registered in this way are not finalized */
288
+ /* if they are reachable by other finalizable objects, eve if those */
289
+ /* other objects specify no ordering. */
290
+ GC_API void GC_unreachable_finalize_mark_proc(ptr_t p)
291
+ {
292
+ GC_normal_finalize_mark_proc(p);
293
+ }
294
+
295
+
296
+
297
+ /* Register a finalization function. See gc.h for details. */
298
+ /* in the nonthreads case, we try to avoid disabling signals, */
299
+ /* since it can be expensive. Threads packages typically */
300
+ /* make it cheaper. */
301
+ /* The last parameter is a procedure that determines */
302
+ /* marking for finalization ordering. Any objects marked */
303
+ /* by that procedure will be guaranteed to not have been */
304
+ /* finalized when this finalizer is invoked. */
305
+ GC_API void GC_register_finalizer_inner(void * obj,
306
+ GC_finalization_proc fn, void *cd,
307
+ GC_finalization_proc *ofn, void **ocd,
308
+ finalization_mark_proc mp)
309
+ {
310
+ ptr_t base;
311
+ struct finalizable_object * curr_fo, * prev_fo;
312
+ size_t index;
313
+ struct finalizable_object *new_fo;
314
+ hdr *hhdr;
315
+ DCL_LOCK_STATE;
316
+
317
+ # ifdef THREADS
318
+ LOCK();
319
+ # endif
320
+ if (log_fo_table_size == -1
321
+ || GC_fo_entries > ((word)1 << log_fo_table_size)) {
322
+ GC_grow_table((struct hash_chain_entry ***)(&fo_head),
323
+ &log_fo_table_size);
324
+ if (GC_print_stats) {
325
+ GC_log_printf("Grew fo table to %u entries\n",
326
+ (1 << log_fo_table_size));
327
+ }
328
+ }
329
+ /* in the THREADS case signals are disabled and we hold allocation */
330
+ /* lock; otherwise neither is true. Proceed carefully. */
331
+ base = (ptr_t)obj;
332
+ index = HASH2(base, log_fo_table_size);
333
+ prev_fo = 0; curr_fo = fo_head[index];
334
+ while (curr_fo != 0) {
335
+ GC_ASSERT(GC_size(curr_fo) >= sizeof(struct finalizable_object));
336
+ if (curr_fo -> fo_hidden_base == HIDE_POINTER(base)) {
337
+ /* Interruption by a signal in the middle of this */
338
+ /* should be safe. The client may see only *ocd */
339
+ /* updated, but we'll declare that to be his */
340
+ /* problem. */
341
+ if (ocd) *ocd = (void *) (curr_fo -> fo_client_data);
342
+ if (ofn) *ofn = curr_fo -> fo_fn;
343
+ /* Delete the structure for base. */
344
+ if (prev_fo == 0) {
345
+ fo_head[index] = fo_next(curr_fo);
346
+ } else {
347
+ fo_set_next(prev_fo, fo_next(curr_fo));
348
+ }
349
+ if (fn == 0) {
350
+ GC_fo_entries--;
351
+ /* May not happen if we get a signal. But a high */
352
+ /* estimate will only make the table larger than */
353
+ /* necessary. */
354
+ # if !defined(THREADS) && !defined(DBG_HDRS_ALL)
355
+ GC_free((void *)curr_fo);
356
+ # endif
357
+ } else {
358
+ curr_fo -> fo_fn = fn;
359
+ curr_fo -> fo_client_data = (ptr_t)cd;
360
+ curr_fo -> fo_mark_proc = mp;
361
+ /* Reinsert it. We deleted it first to maintain */
362
+ /* consistency in the event of a signal. */
363
+ if (prev_fo == 0) {
364
+ fo_head[index] = curr_fo;
365
+ } else {
366
+ fo_set_next(prev_fo, curr_fo);
367
+ }
368
+ }
369
+ # ifdef THREADS
370
+ UNLOCK();
371
+ # endif
372
+ return;
373
+ }
374
+ prev_fo = curr_fo;
375
+ curr_fo = fo_next(curr_fo);
376
+ }
377
+ if (ofn) *ofn = 0;
378
+ if (ocd) *ocd = 0;
379
+ if (fn == 0) {
380
+ # ifdef THREADS
381
+ UNLOCK();
382
+ # endif
383
+ return;
384
+ }
385
+ GET_HDR(base, hhdr);
386
+ if (0 == hhdr) {
387
+ /* We won't collect it, hence finalizer wouldn't be run. */
388
+ # ifdef THREADS
389
+ UNLOCK();
390
+ # endif
391
+ return;
392
+ }
393
+ new_fo = (struct finalizable_object *)
394
+ GC_INTERNAL_MALLOC(sizeof(struct finalizable_object),NORMAL);
395
+ GC_ASSERT(GC_size(new_fo) >= sizeof(struct finalizable_object));
396
+ if (EXPECT(0 == new_fo, FALSE)) {
397
+ # ifdef THREADS
398
+ UNLOCK();
399
+ # endif
400
+ new_fo = (struct finalizable_object *)
401
+ GC_oom_fn(sizeof(struct finalizable_object));
402
+ if (0 == new_fo) {
403
+ GC_finalization_failures++;
404
+ return;
405
+ }
406
+ /* It's not likely we'll make it here, but ... */
407
+ # ifdef THREADS
408
+ LOCK();
409
+ # endif
410
+ }
411
+ new_fo -> fo_hidden_base = (word)HIDE_POINTER(base);
412
+ new_fo -> fo_fn = fn;
413
+ new_fo -> fo_client_data = (ptr_t)cd;
414
+ new_fo -> fo_object_size = hhdr -> hb_sz;
415
+ new_fo -> fo_mark_proc = mp;
416
+ fo_set_next(new_fo, fo_head[index]);
417
+ GC_fo_entries++;
418
+ fo_head[index] = new_fo;
419
+ # ifdef THREADS
420
+ UNLOCK();
421
+ # endif
422
+ }
423
+
424
+ void GC_register_finalizer(void * obj,
425
+ GC_finalization_proc fn, void * cd,
426
+ GC_finalization_proc *ofn, void ** ocd)
427
+ {
428
+ GC_register_finalizer_inner(obj, fn, cd, ofn,
429
+ ocd, GC_normal_finalize_mark_proc);
430
+ }
431
+
432
+ void GC_register_finalizer_ignore_self(void * obj,
433
+ GC_finalization_proc fn, void * cd,
434
+ GC_finalization_proc *ofn, void ** ocd)
435
+ {
436
+ GC_register_finalizer_inner(obj, fn, cd, ofn,
437
+ ocd, GC_ignore_self_finalize_mark_proc);
438
+ }
439
+
440
+ void GC_register_finalizer_no_order(void * obj,
441
+ GC_finalization_proc fn, void * cd,
442
+ GC_finalization_proc *ofn, void ** ocd)
443
+ {
444
+ GC_register_finalizer_inner(obj, fn, cd, ofn,
445
+ ocd, GC_null_finalize_mark_proc);
446
+ }
447
+
448
+ static GC_bool need_unreachable_finalization = FALSE;
449
+ /* Avoid the work if this isn't used. */
450
+
451
+ void GC_register_finalizer_unreachable(void * obj,
452
+ GC_finalization_proc fn, void * cd,
453
+ GC_finalization_proc *ofn, void ** ocd)
454
+ {
455
+ need_unreachable_finalization = TRUE;
456
+ GC_ASSERT(GC_java_finalization);
457
+ GC_register_finalizer_inner(obj, fn, cd, ofn,
458
+ ocd, GC_unreachable_finalize_mark_proc);
459
+ }
460
+
461
+ #ifndef NO_DEBUGGING
462
+ void GC_dump_finalization(void)
463
+ {
464
+ struct disappearing_link * curr_dl;
465
+ struct finalizable_object * curr_fo;
466
+ ptr_t real_ptr, real_link;
467
+ int dl_size = (log_dl_table_size == -1 ) ? 0 : (1 << log_dl_table_size);
468
+ int fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << log_fo_table_size);
469
+ int i;
470
+
471
+ GC_printf("Disappearing links:\n");
472
+ for (i = 0; i < dl_size; i++) {
473
+ for (curr_dl = dl_head[i]; curr_dl != 0; curr_dl = dl_next(curr_dl)) {
474
+ real_ptr = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_obj);
475
+ real_link = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_link);
476
+ GC_printf("Object: %p, Link:%p\n", real_ptr, real_link);
477
+ }
478
+ }
479
+ GC_printf("Finalizers:\n");
480
+ for (i = 0; i < fo_size; i++) {
481
+ for (curr_fo = fo_head[i]; curr_fo != 0; curr_fo = fo_next(curr_fo)) {
482
+ real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
483
+ GC_printf("Finalizable object: %p\n", real_ptr);
484
+ }
485
+ }
486
+ }
487
+ #endif
488
+
489
+ /* Called with world stopped. Cause disappearing links to disappear, */
490
+ /* and invoke finalizers. */
491
+ void GC_finalize(void)
492
+ {
493
+ struct disappearing_link * curr_dl, * prev_dl, * next_dl;
494
+ struct finalizable_object * curr_fo, * prev_fo, * next_fo;
495
+ ptr_t real_ptr, real_link;
496
+ size_t i;
497
+ size_t dl_size = (log_dl_table_size == -1 ) ? 0 : (1 << log_dl_table_size);
498
+ size_t fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << log_fo_table_size);
499
+
500
+ /* Make disappearing links disappear */
501
+ for (i = 0; i < dl_size; i++) {
502
+ curr_dl = dl_head[i];
503
+ prev_dl = 0;
504
+ while (curr_dl != 0) {
505
+ real_ptr = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_obj);
506
+ real_link = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_link);
507
+ if (!GC_is_marked(real_ptr)) {
508
+ *(word *)real_link = 0;
509
+ next_dl = dl_next(curr_dl);
510
+ if (prev_dl == 0) {
511
+ dl_head[i] = next_dl;
512
+ } else {
513
+ dl_set_next(prev_dl, next_dl);
514
+ }
515
+ GC_clear_mark_bit((ptr_t)curr_dl);
516
+ GC_dl_entries--;
517
+ curr_dl = next_dl;
518
+ } else {
519
+ prev_dl = curr_dl;
520
+ curr_dl = dl_next(curr_dl);
521
+ }
522
+ }
523
+ }
524
+ /* Mark all objects reachable via chains of 1 or more pointers */
525
+ /* from finalizable objects. */
526
+ GC_ASSERT(GC_mark_state == MS_NONE);
527
+ for (i = 0; i < fo_size; i++) {
528
+ for (curr_fo = fo_head[i]; curr_fo != 0; curr_fo = fo_next(curr_fo)) {
529
+ GC_ASSERT(GC_size(curr_fo) >= sizeof(struct finalizable_object));
530
+ real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
531
+ if (!GC_is_marked(real_ptr)) {
532
+ GC_MARKED_FOR_FINALIZATION(real_ptr);
533
+ GC_MARK_FO(real_ptr, curr_fo -> fo_mark_proc);
534
+ if (GC_is_marked(real_ptr)) {
535
+ WARN("Finalization cycle involving %lx\n", real_ptr);
536
+ }
537
+ }
538
+ }
539
+ }
540
+ /* Enqueue for finalization all objects that are still */
541
+ /* unreachable. */
542
+ GC_bytes_finalized = 0;
543
+ for (i = 0; i < fo_size; i++) {
544
+ curr_fo = fo_head[i];
545
+ prev_fo = 0;
546
+ while (curr_fo != 0) {
547
+ real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
548
+ if (!GC_is_marked(real_ptr)) {
549
+ if (!GC_java_finalization) {
550
+ GC_set_mark_bit(real_ptr);
551
+ }
552
+ /* Delete from hash table */
553
+ next_fo = fo_next(curr_fo);
554
+ if (prev_fo == 0) {
555
+ fo_head[i] = next_fo;
556
+ } else {
557
+ fo_set_next(prev_fo, next_fo);
558
+ }
559
+ GC_fo_entries--;
560
+ /* Add to list of objects awaiting finalization. */
561
+ fo_set_next(curr_fo, GC_finalize_now);
562
+ GC_finalize_now = curr_fo;
563
+ /* unhide object pointer so any future collections will */
564
+ /* see it. */
565
+ curr_fo -> fo_hidden_base =
566
+ (word) REVEAL_POINTER(curr_fo -> fo_hidden_base);
567
+ GC_bytes_finalized +=
568
+ curr_fo -> fo_object_size
569
+ + sizeof(struct finalizable_object);
570
+ GC_ASSERT(GC_is_marked(GC_base((ptr_t)curr_fo)));
571
+ curr_fo = next_fo;
572
+ } else {
573
+ prev_fo = curr_fo;
574
+ curr_fo = fo_next(curr_fo);
575
+ }
576
+ }
577
+ }
578
+
579
+ if (GC_java_finalization) {
580
+ /* make sure we mark everything reachable from objects finalized
581
+ using the no_order mark_proc */
582
+ for (curr_fo = GC_finalize_now;
583
+ curr_fo != NULL; curr_fo = fo_next(curr_fo)) {
584
+ real_ptr = (ptr_t)curr_fo -> fo_hidden_base;
585
+ if (!GC_is_marked(real_ptr)) {
586
+ if (curr_fo -> fo_mark_proc == GC_null_finalize_mark_proc) {
587
+ GC_MARK_FO(real_ptr, GC_normal_finalize_mark_proc);
588
+ }
589
+ if (curr_fo -> fo_mark_proc != GC_unreachable_finalize_mark_proc) {
590
+ GC_set_mark_bit(real_ptr);
591
+ }
592
+ }
593
+ }
594
+
595
+ /* now revive finalize-when-unreachable objects reachable from
596
+ other finalizable objects */
597
+ if (need_unreachable_finalization) {
598
+ curr_fo = GC_finalize_now;
599
+ prev_fo = 0;
600
+ while (curr_fo != 0) {
601
+ next_fo = fo_next(curr_fo);
602
+ if (curr_fo -> fo_mark_proc == GC_unreachable_finalize_mark_proc) {
603
+ real_ptr = (ptr_t)curr_fo -> fo_hidden_base;
604
+ if (!GC_is_marked(real_ptr)) {
605
+ GC_set_mark_bit(real_ptr);
606
+ } else {
607
+ if (prev_fo == 0)
608
+ GC_finalize_now = next_fo;
609
+ else
610
+ fo_set_next(prev_fo, next_fo);
611
+
612
+ curr_fo -> fo_hidden_base =
613
+ (word) HIDE_POINTER(curr_fo -> fo_hidden_base);
614
+ GC_bytes_finalized -=
615
+ curr_fo -> fo_object_size + sizeof(struct finalizable_object);
616
+
617
+ i = HASH2(real_ptr, log_fo_table_size);
618
+ fo_set_next (curr_fo, fo_head[i]);
619
+ GC_fo_entries++;
620
+ fo_head[i] = curr_fo;
621
+ curr_fo = prev_fo;
622
+ }
623
+ }
624
+ prev_fo = curr_fo;
625
+ curr_fo = next_fo;
626
+ }
627
+ }
628
+ }
629
+
630
+ /* Remove dangling disappearing links. */
631
+ for (i = 0; i < dl_size; i++) {
632
+ curr_dl = dl_head[i];
633
+ prev_dl = 0;
634
+ while (curr_dl != 0) {
635
+ real_link = GC_base((ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_link));
636
+ if (real_link != 0 && !GC_is_marked(real_link)) {
637
+ next_dl = dl_next(curr_dl);
638
+ if (prev_dl == 0) {
639
+ dl_head[i] = next_dl;
640
+ } else {
641
+ dl_set_next(prev_dl, next_dl);
642
+ }
643
+ GC_clear_mark_bit((ptr_t)curr_dl);
644
+ GC_dl_entries--;
645
+ curr_dl = next_dl;
646
+ } else {
647
+ prev_dl = curr_dl;
648
+ curr_dl = dl_next(curr_dl);
649
+ }
650
+ }
651
+ }
652
+ }
653
+
654
+ #ifndef JAVA_FINALIZATION_NOT_NEEDED
655
+
656
+ /* Enqueue all remaining finalizers to be run - Assumes lock is
657
+ * held, and signals are disabled */
658
+ void GC_enqueue_all_finalizers(void)
659
+ {
660
+ struct finalizable_object * curr_fo, * prev_fo, * next_fo;
661
+ ptr_t real_ptr;
662
+ register int i;
663
+ int fo_size;
664
+
665
+ fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << log_fo_table_size);
666
+ GC_bytes_finalized = 0;
667
+ for (i = 0; i < fo_size; i++) {
668
+ curr_fo = fo_head[i];
669
+ prev_fo = 0;
670
+ while (curr_fo != 0) {
671
+ real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
672
+ GC_MARK_FO(real_ptr, GC_normal_finalize_mark_proc);
673
+ GC_set_mark_bit(real_ptr);
674
+
675
+ /* Delete from hash table */
676
+ next_fo = fo_next(curr_fo);
677
+ if (prev_fo == 0) {
678
+ fo_head[i] = next_fo;
679
+ } else {
680
+ fo_set_next(prev_fo, next_fo);
681
+ }
682
+ GC_fo_entries--;
683
+
684
+ /* Add to list of objects awaiting finalization. */
685
+ fo_set_next(curr_fo, GC_finalize_now);
686
+ GC_finalize_now = curr_fo;
687
+
688
+ /* unhide object pointer so any future collections will */
689
+ /* see it. */
690
+ curr_fo -> fo_hidden_base =
691
+ (word) REVEAL_POINTER(curr_fo -> fo_hidden_base);
692
+
693
+ GC_bytes_finalized +=
694
+ curr_fo -> fo_object_size + sizeof(struct finalizable_object);
695
+ curr_fo = next_fo;
696
+ }
697
+ }
698
+
699
+ return;
700
+ }
701
+
702
+ /* Invoke all remaining finalizers that haven't yet been run.
703
+ * This is needed for strict compliance with the Java standard,
704
+ * which can make the runtime guarantee that all finalizers are run.
705
+ * Unfortunately, the Java standard implies we have to keep running
706
+ * finalizers until there are no more left, a potential infinite loop.
707
+ * YUCK.
708
+ * Note that this is even more dangerous than the usual Java
709
+ * finalizers, in that objects reachable from static variables
710
+ * may have been finalized when these finalizers are run.
711
+ * Finalizers run at this point must be prepared to deal with a
712
+ * mostly broken world.
713
+ * This routine is externally callable, so is called without
714
+ * the allocation lock.
715
+ */
716
+ GC_API void GC_finalize_all(void)
717
+ {
718
+ DCL_LOCK_STATE;
719
+
720
+ LOCK();
721
+ while (GC_fo_entries > 0) {
722
+ GC_enqueue_all_finalizers();
723
+ UNLOCK();
724
+ GC_INVOKE_FINALIZERS();
725
+ LOCK();
726
+ }
727
+ UNLOCK();
728
+ }
729
+ #endif
730
+
731
+ /* Returns true if it is worth calling GC_invoke_finalizers. (Useful if */
732
+ /* finalizers can only be called from some kind of `safe state' and */
733
+ /* getting into that safe state is expensive.) */
734
+ int GC_should_invoke_finalizers(void)
735
+ {
736
+ return GC_finalize_now != 0;
737
+ }
738
+
739
+ /* Invoke finalizers for all objects that are ready to be finalized. */
740
+ /* Should be called without allocation lock. */
741
+ int GC_invoke_finalizers(void)
742
+ {
743
+ struct finalizable_object * curr_fo;
744
+ int count = 0;
745
+ word bytes_freed_before;
746
+ DCL_LOCK_STATE;
747
+
748
+ while (GC_finalize_now != 0) {
749
+ # ifdef THREADS
750
+ LOCK();
751
+ # endif
752
+ if (count == 0) {
753
+ bytes_freed_before = GC_bytes_freed;
754
+ /* Don't do this outside, since we need the lock. */
755
+ }
756
+ curr_fo = GC_finalize_now;
757
+ # ifdef THREADS
758
+ if (curr_fo != 0) GC_finalize_now = fo_next(curr_fo);
759
+ UNLOCK();
760
+ if (curr_fo == 0) break;
761
+ # else
762
+ GC_finalize_now = fo_next(curr_fo);
763
+ # endif
764
+ fo_set_next(curr_fo, 0);
765
+ (*(curr_fo -> fo_fn))((ptr_t)(curr_fo -> fo_hidden_base),
766
+ curr_fo -> fo_client_data);
767
+ curr_fo -> fo_client_data = 0;
768
+ ++count;
769
+ # ifdef UNDEFINED
770
+ /* This is probably a bad idea. It throws off accounting if */
771
+ /* nearly all objects are finalizable. O.w. it shouldn't */
772
+ /* matter. */
773
+ GC_free((void *)curr_fo);
774
+ # endif
775
+ }
776
+ /* bytes_freed_before is initialized whenever count != 0 */
777
+ if (count != 0 && bytes_freed_before != GC_bytes_freed) {
778
+ LOCK();
779
+ GC_finalizer_bytes_freed += (GC_bytes_freed - bytes_freed_before);
780
+ UNLOCK();
781
+ }
782
+ return count;
783
+ }
784
+
785
+ void (* GC_finalizer_notifier)() = (void (*) (void))0;
786
+
787
+ static GC_word last_finalizer_notification = 0;
788
+
789
+ void GC_notify_or_invoke_finalizers(void)
790
+ {
791
+ /* This is a convenient place to generate backtraces if appropriate, */
792
+ /* since that code is not callable with the allocation lock. */
793
+ # if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)
794
+ static word last_back_trace_gc_no = 1; /* Skip first one. */
795
+
796
+ if (GC_gc_no > last_back_trace_gc_no) {
797
+ word i;
798
+
799
+ # ifdef KEEP_BACK_PTRS
800
+ LOCK();
801
+ /* Stops when GC_gc_no wraps; that's OK. */
802
+ last_back_trace_gc_no = (word)(-1); /* disable others. */
803
+ for (i = 0; i < GC_backtraces; ++i) {
804
+ /* FIXME: This tolerates concurrent heap mutation, */
805
+ /* which may cause occasional mysterious results. */
806
+ /* We need to release the GC lock, since GC_print_callers */
807
+ /* acquires it. It probably shouldn't. */
808
+ UNLOCK();
809
+ GC_generate_random_backtrace_no_gc();
810
+ LOCK();
811
+ }
812
+ last_back_trace_gc_no = GC_gc_no;
813
+ UNLOCK();
814
+ # endif
815
+ # ifdef MAKE_BACK_GRAPH
816
+ if (GC_print_back_height)
817
+ GC_print_back_graph_stats();
818
+ # endif
819
+ }
820
+ # endif
821
+ if (GC_finalize_now == 0) return;
822
+ if (!GC_finalize_on_demand) {
823
+ (void) GC_invoke_finalizers();
824
+ # ifndef THREADS
825
+ GC_ASSERT(GC_finalize_now == 0);
826
+ # endif /* Otherwise GC can run concurrently and add more */
827
+ return;
828
+ }
829
+ if (GC_finalizer_notifier != (void (*) (void))0
830
+ && last_finalizer_notification != GC_gc_no) {
831
+ last_finalizer_notification = GC_gc_no;
832
+ GC_finalizer_notifier();
833
+ }
834
+ }
835
+
836
+ void * GC_call_with_alloc_lock(GC_fn_type fn, void * client_data)
837
+ {
838
+ void * result;
839
+ DCL_LOCK_STATE;
840
+
841
+ # ifdef THREADS
842
+ LOCK();
843
+ /* FIXME - This looks wrong!! */
844
+ SET_LOCK_HOLDER();
845
+ # endif
846
+ result = (*fn)(client_data);
847
+ # ifdef THREADS
848
+ # ifndef GC_ASSERTIONS
849
+ UNSET_LOCK_HOLDER();
850
+ # endif /* o.w. UNLOCK() does it implicitly */
851
+ UNLOCK();
852
+ # endif
853
+ return(result);
854
+ }
855
+
856
+ #if !defined(NO_DEBUGGING)
857
+
858
+ void GC_print_finalization_stats(void)
859
+ {
860
+ struct finalizable_object *fo = GC_finalize_now;
861
+ size_t ready = 0;
862
+
863
+ GC_printf("%u finalization table entries; %u disappearing links\n",
864
+ GC_fo_entries, GC_dl_entries);
865
+ for (; 0 != fo; fo = fo_next(fo)) ++ready;
866
+ GC_printf("%u objects are eligible for immediate finalization\n", ready);
867
+ }
868
+
869
+ #endif /* NO_DEBUGGING */
mosesdecoder/jam-files/engine/boehm_gc/gc.mak ADDED
@@ -0,0 +1,2220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Microsoft Developer Studio Generated NMAKE File, Format Version 4.10
2
+ # This has been hand-edited way too many times.
3
+ # A clean, manually generated makefile would be an improvement.
4
+
5
+ # TARGTYPE "Win32 (x86) Application" 0x0101
6
+ # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
7
+
8
+ AO_VERSION=1.2
9
+ !IF "$(CFG)" == ""
10
+ CFG=gctest - Win32 Release
11
+ !MESSAGE No configuration specified. Defaulting to cord - Win32 Debug.
12
+ !ENDIF
13
+
14
+ !IF "$(CFG)" != "gc - Win32 Release" && "$(CFG)" != "gc - Win32 Debug" &&\
15
+ "$(CFG)" != "gctest - Win32 Release" && "$(CFG)" != "gctest - Win32 Debug" &&\
16
+ "$(CFG)" != "cord - Win32 Release" && "$(CFG)" != "cord - Win32 Debug"
17
+ !MESSAGE Invalid configuration "$(CFG)" specified.
18
+ !MESSAGE You can specify a configuration when running NMAKE on this makefile
19
+ !MESSAGE by defining the macro CFG on the command line. For example:
20
+ !MESSAGE
21
+ !MESSAGE NMAKE /f "gc.mak" CFG="cord - Win32 Debug"
22
+ !MESSAGE
23
+ !MESSAGE Possible choices for configuration are:
24
+ !MESSAGE
25
+ !MESSAGE "gc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
26
+ !MESSAGE "gc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
27
+ !MESSAGE "gctest - Win32 Release" (based on "Win32 (x86) Application")
28
+ !MESSAGE "gctest - Win32 Debug" (based on "Win32 (x86) Application")
29
+ !MESSAGE "cord - Win32 Release" (based on "Win32 (x86) Application")
30
+ !MESSAGE "cord - Win32 Debug" (based on "Win32 (x86) Application")
31
+ !MESSAGE
32
+ !ERROR An invalid configuration is specified.
33
+ !ENDIF
34
+
35
+ !IF "$(OS)" == "Windows_NT"
36
+ NULL=
37
+ !ELSE
38
+ NULL=nul
39
+ !ENDIF
40
+ ################################################################################
41
+ # Begin Project
42
+ # PROP Target_Last_Scanned "gctest - Win32 Debug"
43
+
44
+ !IF "$(CFG)" == "gc - Win32 Release"
45
+
46
+ # PROP BASE Use_MFC 0
47
+ # PROP BASE Use_Debug_Libraries 0
48
+ # PROP BASE Output_Dir "Release"
49
+ # PROP BASE Intermediate_Dir "Release"
50
+ # PROP BASE Target_Dir ""
51
+ # PROP Use_MFC 0
52
+ # PROP Use_Debug_Libraries 0
53
+ # PROP Output_Dir "Release"
54
+ # PROP Intermediate_Dir "Release"
55
+ # PROP Target_Dir ""
56
+ OUTDIR=.\Release
57
+ INTDIR=.\Release
58
+
59
+ ALL : ".\Release\gc.dll" ".\Release\gc.bsc"
60
+
61
+ CLEAN :
62
+ -@erase ".\Release\allchblk.obj"
63
+ -@erase ".\Release\allchblk.sbr"
64
+ -@erase ".\Release\alloc.obj"
65
+ -@erase ".\Release\alloc.sbr"
66
+ -@erase ".\Release\blacklst.obj"
67
+ -@erase ".\Release\blacklst.sbr"
68
+ -@erase ".\Release\checksums.obj"
69
+ -@erase ".\Release\checksums.sbr"
70
+ -@erase ".\Release\dbg_mlc.obj"
71
+ -@erase ".\Release\dbg_mlc.sbr"
72
+ -@erase ".\Release\dyn_load.obj"
73
+ -@erase ".\Release\dyn_load.sbr"
74
+ -@erase ".\Release\finalize.obj"
75
+ -@erase ".\Release\finalize.sbr"
76
+ -@erase ".\Release\gc.bsc"
77
+ -@erase ".\Release\gc_cpp.obj"
78
+ -@erase ".\Release\gc_cpp.sbr"
79
+ -@erase ".\Release\gc.dll"
80
+ -@erase ".\Release\gc.exp"
81
+ -@erase ".\Release\gc.lib"
82
+ -@erase ".\Release\headers.obj"
83
+ -@erase ".\Release\headers.sbr"
84
+ -@erase ".\Release\mach_dep.obj"
85
+ -@erase ".\Release\mach_dep.sbr"
86
+ -@erase ".\Release\malloc.obj"
87
+ -@erase ".\Release\malloc.sbr"
88
+ -@erase ".\Release\mallocx.obj"
89
+ -@erase ".\Release\mallocx.sbr"
90
+ -@erase ".\Release\mark.obj"
91
+ -@erase ".\Release\mark.sbr"
92
+ -@erase ".\Release\mark_rts.obj"
93
+ -@erase ".\Release\mark_rts.sbr"
94
+ -@erase ".\Release\misc.obj"
95
+ -@erase ".\Release\misc.sbr"
96
+ -@erase ".\Release\new_hblk.obj"
97
+ -@erase ".\Release\new_hblk.sbr"
98
+ -@erase ".\Release\obj_map.obj"
99
+ -@erase ".\Release\obj_map.sbr"
100
+ -@erase ".\Release\os_dep.obj"
101
+ -@erase ".\Release\os_dep.sbr"
102
+ -@erase ".\Release\ptr_chck.obj"
103
+ -@erase ".\Release\ptr_chck.sbr"
104
+ -@erase ".\Release\reclaim.obj"
105
+ -@erase ".\Release\reclaim.sbr"
106
+ -@erase ".\Release\stubborn.obj"
107
+ -@erase ".\Release\stubborn.sbr"
108
+ -@erase ".\Release\typd_mlc.obj"
109
+ -@erase ".\Release\typd_mlc.sbr"
110
+ -@erase ".\Release\win32_threads.obj"
111
+ -@erase ".\Release\win32_threads.sbr"
112
+ -@erase ".\Release\msvc_dbg.obj"
113
+ -@erase ".\Release\msvc_dbg.sbr"
114
+
115
+ "$(OUTDIR)" :
116
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
117
+
118
+ CPP=cl.exe
119
+ # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
120
+ # ADD CPP /nologo /MD /W3 /GX /O2 /I include /D "NDEBUG" /D "GC_BUILD" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS" /FR /YX /c
121
+ CPP_PROJ=/nologo /MD /W3 /GX /O2 /I include /D "NDEBUG" /D "GC_BUILD" /D\
122
+ "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D\
123
+ "GC_WIN32_THREADS" /FR"$(INTDIR)/" /Fp"$(INTDIR)/gc.pch" \
124
+ /Ilibatomic_ops-$(AO_VERSION)/src /YX /Fo"$(INTDIR)/" /c
125
+ CPP_OBJS=.\Release/
126
+ CPP_SBRS=.\Release/
127
+
128
+ .c{$(CPP_OBJS)}.obj:
129
+ $(CPP) $(CPP_PROJ) $<
130
+
131
+ .cpp{$(CPP_OBJS)}.obj:
132
+ $(CPP) $(CPP_PROJ) $<
133
+
134
+ .cxx{$(CPP_OBJS)}.obj:
135
+ $(CPP) $(CPP_PROJ) $<
136
+
137
+ .c{$(CPP_SBRS)}.sbr:
138
+ $(CPP) $(CPP_PROJ) $<
139
+
140
+ .cpp{$(CPP_SBRS)}.sbr:
141
+ $(CPP) $(CPP_PROJ) $<
142
+
143
+ .cxx{$(CPP_SBRS)}.sbr:
144
+ $(CPP) $(CPP_PROJ) $<
145
+
146
+ MTL=mktyplib.exe
147
+ # ADD BASE MTL /nologo /D "NDEBUG" /win32
148
+ # ADD MTL /nologo /D "NDEBUG" /win32
149
+ MTL_PROJ=/nologo /D "NDEBUG" /win32
150
+ RSC=rc.exe
151
+ # ADD BASE RSC /l 0x809 /d "NDEBUG"
152
+ # ADD RSC /l 0x809 /d "NDEBUG"
153
+ BSC32=bscmake.exe
154
+ # ADD BASE BSC32 /nologo
155
+ # ADD BSC32 /nologo
156
+ BSC32_FLAGS=/nologo /o"$(OUTDIR)/gc.bsc"
157
+ BSC32_SBRS= \
158
+ ".\Release\allchblk.sbr" \
159
+ ".\Release\alloc.sbr" \
160
+ ".\Release\blacklst.sbr" \
161
+ ".\Release\checksums.sbr" \
162
+ ".\Release\dbg_mlc.sbr" \
163
+ ".\Release\dyn_load.sbr" \
164
+ ".\Release\finalize.sbr" \
165
+ ".\Release\gc_cpp.sbr" \
166
+ ".\Release\headers.sbr" \
167
+ ".\Release\mach_dep.sbr" \
168
+ ".\Release\malloc.sbr" \
169
+ ".\Release\mallocx.sbr" \
170
+ ".\Release\mark.sbr" \
171
+ ".\Release\mark_rts.sbr" \
172
+ ".\Release\misc.sbr" \
173
+ ".\Release\new_hblk.sbr" \
174
+ ".\Release\obj_map.sbr" \
175
+ ".\Release\os_dep.sbr" \
176
+ ".\Release\ptr_chck.sbr" \
177
+ ".\Release\reclaim.sbr" \
178
+ ".\Release\stubborn.sbr" \
179
+ ".\Release\typd_mlc.sbr" \
180
+ ".\Release\msvc_dbg.sbr" \
181
+ ".\Release\win32_threads.sbr"
182
+
183
+ ".\Release\gc.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
184
+ $(BSC32) @<<
185
+ $(BSC32_FLAGS) $(BSC32_SBRS)
186
+ <<
187
+
188
+ LINK32=link.exe
189
+ # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
190
+ # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
191
+ LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
192
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
193
+ odbccp32.lib /nologo /subsystem:windows /dll /incremental:no\
194
+ /pdb:"$(OUTDIR)/gc.pdb" /machine:I386 /out:"$(OUTDIR)/gc.dll"\
195
+ /implib:"$(OUTDIR)/gc.lib"
196
+ LINK32_OBJS= \
197
+ ".\Release\allchblk.obj" \
198
+ ".\Release\alloc.obj" \
199
+ ".\Release\blacklst.obj" \
200
+ ".\Release\checksums.obj" \
201
+ ".\Release\dbg_mlc.obj" \
202
+ ".\Release\dyn_load.obj" \
203
+ ".\Release\finalize.obj" \
204
+ ".\Release\gc_cpp.obj" \
205
+ ".\Release\headers.obj" \
206
+ ".\Release\mach_dep.obj" \
207
+ ".\Release\malloc.obj" \
208
+ ".\Release\mallocx.obj" \
209
+ ".\Release\mark.obj" \
210
+ ".\Release\mark_rts.obj" \
211
+ ".\Release\misc.obj" \
212
+ ".\Release\new_hblk.obj" \
213
+ ".\Release\obj_map.obj" \
214
+ ".\Release\os_dep.obj" \
215
+ ".\Release\ptr_chck.obj" \
216
+ ".\Release\reclaim.obj" \
217
+ ".\Release\stubborn.obj" \
218
+ ".\Release\typd_mlc.obj" \
219
+ ".\Release\msvc_dbg.obj" \
220
+ ".\Release\win32_threads.obj"
221
+
222
+ ".\Release\gc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
223
+ $(LINK32) @<<
224
+ $(LINK32_FLAGS) $(LINK32_OBJS)
225
+ <<
226
+
227
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
228
+
229
+ # PROP BASE Use_MFC 0
230
+ # PROP BASE Use_Debug_Libraries 1
231
+ # PROP BASE Output_Dir "Debug"
232
+ # PROP BASE Intermediate_Dir "Debug"
233
+ # PROP BASE Target_Dir ""
234
+ # PROP Use_MFC 0
235
+ # PROP Use_Debug_Libraries 1
236
+ # PROP Output_Dir "Debug"
237
+ # PROP Intermediate_Dir "Debug"
238
+ # PROP Target_Dir ""
239
+ OUTDIR=.\Debug
240
+ INTDIR=.\Debug
241
+
242
+ ALL : ".\Debug\gc.dll" ".\Debug\gc.bsc"
243
+
244
+ CLEAN :
245
+ -@erase ".\Debug\allchblk.obj"
246
+ -@erase ".\Debug\allchblk.sbr"
247
+ -@erase ".\Debug\alloc.obj"
248
+ -@erase ".\Debug\alloc.sbr"
249
+ -@erase ".\Debug\blacklst.obj"
250
+ -@erase ".\Debug\blacklst.sbr"
251
+ -@erase ".\Debug\checksums.obj"
252
+ -@erase ".\Debug\checksums.sbr"
253
+ -@erase ".\Debug\dbg_mlc.obj"
254
+ -@erase ".\Debug\dbg_mlc.sbr"
255
+ -@erase ".\Debug\dyn_load.obj"
256
+ -@erase ".\Debug\dyn_load.sbr"
257
+ -@erase ".\Debug\finalize.obj"
258
+ -@erase ".\Debug\finalize.sbr"
259
+ -@erase ".\Debug\gc_cpp.obj"
260
+ -@erase ".\Debug\gc_cpp.sbr"
261
+ -@erase ".\Debug\gc.bsc"
262
+ -@erase ".\Debug\gc.dll"
263
+ -@erase ".\Debug\gc.exp"
264
+ -@erase ".\Debug\gc.lib"
265
+ -@erase ".\Debug\gc.map"
266
+ -@erase ".\Debug\gc.pdb"
267
+ -@erase ".\Debug\headers.obj"
268
+ -@erase ".\Debug\headers.sbr"
269
+ -@erase ".\Debug\mach_dep.obj"
270
+ -@erase ".\Debug\mach_dep.sbr"
271
+ -@erase ".\Debug\malloc.obj"
272
+ -@erase ".\Debug\malloc.sbr"
273
+ -@erase ".\Debug\mallocx.obj"
274
+ -@erase ".\Debug\mallocx.sbr"
275
+ -@erase ".\Debug\mark.obj"
276
+ -@erase ".\Debug\mark.sbr"
277
+ -@erase ".\Debug\mark_rts.obj"
278
+ -@erase ".\Debug\mark_rts.sbr"
279
+ -@erase ".\Debug\misc.obj"
280
+ -@erase ".\Debug\misc.sbr"
281
+ -@erase ".\Debug\new_hblk.obj"
282
+ -@erase ".\Debug\new_hblk.sbr"
283
+ -@erase ".\Debug\obj_map.obj"
284
+ -@erase ".\Debug\obj_map.sbr"
285
+ -@erase ".\Debug\os_dep.obj"
286
+ -@erase ".\Debug\os_dep.sbr"
287
+ -@erase ".\Debug\ptr_chck.obj"
288
+ -@erase ".\Debug\ptr_chck.sbr"
289
+ -@erase ".\Debug\reclaim.obj"
290
+ -@erase ".\Debug\reclaim.sbr"
291
+ -@erase ".\Debug\stubborn.obj"
292
+ -@erase ".\Debug\stubborn.sbr"
293
+ -@erase ".\Debug\typd_mlc.obj"
294
+ -@erase ".\Debug\typd_mlc.sbr"
295
+ -@erase ".\Debug\vc40.idb"
296
+ -@erase ".\Debug\vc40.pdb"
297
+ -@erase ".\Debug\win32_threads.obj"
298
+ -@erase ".\Debug\win32_threads.sbr"
299
+ -@erase ".\Debug\msvc_dbg.obj"
300
+ -@erase ".\Debug\msvc_dbg.sbr"
301
+
302
+ "$(OUTDIR)" :
303
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
304
+
305
+ CPP=cl.exe
306
+ # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
307
+ # ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I include /D "_DEBUG" /D "GC_BUILD" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS" /FR /YX /c
308
+ CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I include /D "_DEBUG" /D "GC_BUILD"\
309
+ /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" \
310
+ /D "GC_ASSERTIONS" /D "__STDC__" /D\
311
+ "GC_WIN32_THREADS" /FR"$(INTDIR)/" /Fp"$(INTDIR)/gc.pch" /YX /Fo"$(INTDIR)/"\
312
+ /Ilibatomic_ops-$(AO_VERSION)/src /Fd"$(INTDIR)/" /c
313
+ CPP_OBJS=.\Debug/
314
+ CPP_SBRS=.\Debug/
315
+
316
+ .c{$(CPP_OBJS)}.obj:
317
+ $(CPP) $(CPP_PROJ) $<
318
+
319
+ .cpp{$(CPP_OBJS)}.obj:
320
+ $(CPP) $(CPP_PROJ) $<
321
+
322
+ .cxx{$(CPP_OBJS)}.obj:
323
+ $(CPP) $(CPP_PROJ) $<
324
+
325
+ .c{$(CPP_SBRS)}.sbr:
326
+ $(CPP) $(CPP_PROJ) $<
327
+
328
+ .cpp{$(CPP_SBRS)}.sbr:
329
+ $(CPP) $(CPP_PROJ) $<
330
+
331
+ .cxx{$(CPP_SBRS)}.sbr:
332
+ $(CPP) $(CPP_PROJ) $<
333
+
334
+ MTL=mktyplib.exe
335
+ # ADD BASE MTL /nologo /D "_DEBUG" /win32
336
+ # ADD MTL /nologo /D "_DEBUG" /win32
337
+ MTL_PROJ=/nologo /D "_DEBUG" /win32
338
+ RSC=rc.exe
339
+ # ADD BASE RSC /l 0x809 /d "_DEBUG"
340
+ # ADD RSC /l 0x809 /d "_DEBUG"
341
+ BSC32=bscmake.exe
342
+ # ADD BASE BSC32 /nologo
343
+ # ADD BSC32 /nologo
344
+ BSC32_FLAGS=/nologo /o"$(OUTDIR)/gc.bsc"
345
+ BSC32_SBRS= \
346
+ ".\Debug\allchblk.sbr" \
347
+ ".\Debug\alloc.sbr" \
348
+ ".\Debug\blacklst.sbr" \
349
+ ".\Debug\checksums.sbr" \
350
+ ".\Debug\dbg_mlc.sbr" \
351
+ ".\Debug\dyn_load.sbr" \
352
+ ".\Debug\finalize.sbr" \
353
+ ".\Debug\gc_cpp.sbr" \
354
+ ".\Debug\headers.sbr" \
355
+ ".\Debug\mach_dep.sbr" \
356
+ ".\Debug\malloc.sbr" \
357
+ ".\Debug\mallocx.sbr" \
358
+ ".\Debug\mark.sbr" \
359
+ ".\Debug\mark_rts.sbr" \
360
+ ".\Debug\misc.sbr" \
361
+ ".\Debug\new_hblk.sbr" \
362
+ ".\Debug\obj_map.sbr" \
363
+ ".\Debug\os_dep.sbr" \
364
+ ".\Debug\ptr_chck.sbr" \
365
+ ".\Debug\reclaim.sbr" \
366
+ ".\Debug\stubborn.sbr" \
367
+ ".\Debug\typd_mlc.sbr" \
368
+ ".\Debug\msvc_dbg.sbr" \
369
+ ".\Debug\win32_threads.sbr"
370
+
371
+ ".\Debug\gc.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
372
+ $(BSC32) @<<
373
+ $(BSC32_FLAGS) $(BSC32_SBRS)
374
+ <<
375
+
376
+ LINK32=link.exe
377
+ # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
378
+ # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386
379
+ LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
380
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
381
+ odbccp32.lib /nologo /subsystem:windows /dll /incremental:no\
382
+ /pdb:"$(OUTDIR)/gc.pdb" /map:"$(INTDIR)/gc.map" /debug /machine:I386\
383
+ /out:"$(OUTDIR)/gc.dll" /implib:"$(OUTDIR)/gc.lib"
384
+ LINK32_OBJS= \
385
+ ".\Debug\allchblk.obj" \
386
+ ".\Debug\alloc.obj" \
387
+ ".\Debug\blacklst.obj" \
388
+ ".\Debug\checksums.obj" \
389
+ ".\Debug\dbg_mlc.obj" \
390
+ ".\Debug\dyn_load.obj" \
391
+ ".\Debug\finalize.obj" \
392
+ ".\Debug\gc_cpp.obj" \
393
+ ".\Debug\headers.obj" \
394
+ ".\Debug\mach_dep.obj" \
395
+ ".\Debug\malloc.obj" \
396
+ ".\Debug\mallocx.obj" \
397
+ ".\Debug\mark.obj" \
398
+ ".\Debug\mark_rts.obj" \
399
+ ".\Debug\misc.obj" \
400
+ ".\Debug\new_hblk.obj" \
401
+ ".\Debug\obj_map.obj" \
402
+ ".\Debug\os_dep.obj" \
403
+ ".\Debug\ptr_chck.obj" \
404
+ ".\Debug\reclaim.obj" \
405
+ ".\Debug\stubborn.obj" \
406
+ ".\Debug\typd_mlc.obj" \
407
+ ".\Debug\msvc_dbg.obj" \
408
+ ".\Debug\win32_threads.obj"
409
+
410
+ ".\Debug\gc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
411
+ $(LINK32) @<<
412
+ $(LINK32_FLAGS) $(LINK32_OBJS)
413
+ <<
414
+
415
+ !ELSEIF "$(CFG)" == "gctest - Win32 Release"
416
+
417
+ # PROP BASE Use_MFC 0
418
+ # PROP BASE Use_Debug_Libraries 0
419
+ # PROP BASE Output_Dir "gctest\Release"
420
+ # PROP BASE Intermediate_Dir "gctest\Release"
421
+ # PROP BASE Target_Dir "gctest"
422
+ # PROP Use_MFC 0
423
+ # PROP Use_Debug_Libraries 0
424
+ # PROP Output_Dir "gctest\Release"
425
+ # PROP Intermediate_Dir "gctest\Release"
426
+ # PROP Target_Dir "gctest"
427
+ OUTDIR=.\gctest\Release
428
+ INTDIR=.\gctest\Release
429
+
430
+ ALL : "gc - Win32 Release" ".\Release\gctest.exe"
431
+
432
+ CLEAN :
433
+ -@erase ".\gctest\Release\test.obj"
434
+ -@erase ".\Release\gctest.exe"
435
+
436
+ "$(OUTDIR)" :
437
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
438
+
439
+ test.c : tests\test.c
440
+ copy tests\test.c test.c
441
+
442
+ CPP=cl.exe
443
+ # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
444
+ # ADD CPP /nologo /MD /W3 /GX /O2 /I include /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS" /YX /c
445
+ CPP_PROJ=/nologo /MD /W3 /GX /O2 /I include /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D\
446
+ "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS"\
447
+ /Ilibatomic_ops-$(AO_VERSION)/src /Fp"$(INTDIR)/gctest.pch" \
448
+ /YX /Fo"$(INTDIR)/" /c
449
+ CPP_OBJS=.\gctest\Release/
450
+ CPP_SBRS=.\.
451
+
452
+ .c{$(CPP_OBJS)}.obj:
453
+ $(CPP) $(CPP_PROJ) $<
454
+
455
+ .cpp{$(CPP_OBJS)}.obj:
456
+ $(CPP) $(CPP_PROJ) $<
457
+
458
+ .cxx{$(CPP_OBJS)}.obj:
459
+ $(CPP) $(CPP_PROJ) $<
460
+
461
+ .c{$(CPP_SBRS)}.sbr:
462
+ $(CPP) $(CPP_PROJ) $<
463
+
464
+ .cpp{$(CPP_SBRS)}.sbr:
465
+ $(CPP) $(CPP_PROJ) $<
466
+
467
+ .cxx{$(CPP_SBRS)}.sbr:
468
+ $(CPP) $(CPP_PROJ) $<
469
+
470
+ MTL=mktyplib.exe
471
+ # ADD BASE MTL /nologo /D "NDEBUG" /win32
472
+ # ADD MTL /nologo /D "NDEBUG" /win32
473
+ MTL_PROJ=/nologo /D "NDEBUG" /win32
474
+ RSC=rc.exe
475
+ # ADD BASE RSC /l 0x809 /d "NDEBUG"
476
+ # ADD RSC /l 0x809 /d "NDEBUG"
477
+ BSC32=bscmake.exe
478
+ # ADD BASE BSC32 /nologo
479
+ # ADD BSC32 /nologo
480
+ BSC32_FLAGS=/nologo /o"$(OUTDIR)/gctest.bsc"
481
+ BSC32_SBRS= \
482
+
483
+ LINK32=link.exe
484
+ # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
485
+ # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"Release/gctest.exe"
486
+ LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
487
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
488
+ odbccp32.lib /nologo /subsystem:windows /incremental:no\
489
+ /pdb:"$(OUTDIR)/gctest.pdb" /machine:I386 /out:"Release/gctest.exe"
490
+ LINK32_OBJS= \
491
+ ".\gctest\Release\test.obj" \
492
+ ".\Release\gc.lib"
493
+
494
+ ".\Release\gctest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
495
+ $(LINK32) @<<
496
+ $(LINK32_FLAGS) $(LINK32_OBJS)
497
+ <<
498
+
499
+ !ELSEIF "$(CFG)" == "gctest - Win32 Debug"
500
+
501
+ # PROP BASE Use_MFC 0
502
+ # PROP BASE Use_Debug_Libraries 1
503
+ # PROP BASE Output_Dir "gctest\Debug"
504
+ # PROP BASE Intermediate_Dir "gctest\Debug"
505
+ # PROP BASE Target_Dir "gctest"
506
+ # PROP Use_MFC 0
507
+ # PROP Use_Debug_Libraries 1
508
+ # PROP Output_Dir "gctest\Debug"
509
+ # PROP Intermediate_Dir "gctest\Debug"
510
+ # PROP Target_Dir "gctest"
511
+ OUTDIR=.\gctest\Debug
512
+ INTDIR=.\gctest\Debug
513
+
514
+ ALL : "gc - Win32 Debug" ".\Debug\gctest.exe" ".\gctest\Debug\gctest.bsc"
515
+
516
+ CLEAN :
517
+ -@erase ".\Debug\gctest.exe"
518
+ -@erase ".\gctest\Debug\gctest.bsc"
519
+ -@erase ".\gctest\Debug\gctest.map"
520
+ -@erase ".\gctest\Debug\gctest.pdb"
521
+ -@erase ".\gctest\Debug\test.obj"
522
+ -@erase ".\gctest\Debug\test.sbr"
523
+ -@erase ".\gctest\Debug\vc40.idb"
524
+ -@erase ".\gctest\Debug\vc40.pdb"
525
+
526
+ "$(OUTDIR)" :
527
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
528
+
529
+ CPP=cl.exe
530
+ # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
531
+ # ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS" /FR /YX /c
532
+ CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I include /D "_DEBUG" /D "WIN32" /D "_WINDOWS"\
533
+ /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "GC_WIN32_THREADS" /FR"$(INTDIR)/"\
534
+ /Ilibatomic_ops-$(AO_VERSION)/src /Fp"$(INTDIR)/gctest.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
535
+ CPP_OBJS=.\gctest\Debug/
536
+ CPP_SBRS=.\gctest\Debug/
537
+
538
+ .c{$(CPP_OBJS)}.obj:
539
+ $(CPP) $(CPP_PROJ) $<
540
+
541
+ .cpp{$(CPP_OBJS)}.obj:
542
+ $(CPP) $(CPP_PROJ) $<
543
+
544
+ .cxx{$(CPP_OBJS)}.obj:
545
+ $(CPP) $(CPP_PROJ) $<
546
+
547
+ .c{$(CPP_SBRS)}.sbr:
548
+ $(CPP) $(CPP_PROJ) $<
549
+
550
+ .cpp{$(CPP_SBRS)}.sbr:
551
+ $(CPP) $(CPP_PROJ) $<
552
+
553
+ .cxx{$(CPP_SBRS)}.sbr:
554
+ $(CPP) $(CPP_PROJ) $<
555
+
556
+ MTL=mktyplib.exe
557
+ # ADD BASE MTL /nologo /D "_DEBUG" /win32
558
+ # ADD MTL /nologo /D "_DEBUG" /win32
559
+ MTL_PROJ=/nologo /D "_DEBUG" /win32
560
+ RSC=rc.exe
561
+ # ADD BASE RSC /l 0x809 /d "_DEBUG"
562
+ # ADD RSC /l 0x809 /d "_DEBUG"
563
+ BSC32=bscmake.exe
564
+ # ADD BASE BSC32 /nologo
565
+ # ADD BSC32 /nologo
566
+ BSC32_FLAGS=/nologo /o"$(OUTDIR)/gctest.bsc"
567
+ BSC32_SBRS= \
568
+ ".\gctest\Debug\test.sbr"
569
+
570
+ ".\gctest\Debug\gctest.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
571
+ $(BSC32) @<<
572
+ $(BSC32_FLAGS) $(BSC32_SBRS)
573
+ <<
574
+
575
+ LINK32=link.exe
576
+ # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
577
+ # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /incremental:no /map /debug /machine:I386 /out:"Debug/gctest.exe"
578
+ LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
579
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
580
+ odbccp32.lib /nologo /subsystem:windows /incremental:no\
581
+ /pdb:"$(OUTDIR)/gctest.pdb" /map:"$(INTDIR)/gctest.map" /debug /machine:I386\
582
+ /out:"Debug/gctest.exe"
583
+ LINK32_OBJS= \
584
+ ".\Debug\gc.lib" \
585
+ ".\gctest\Debug\test.obj"
586
+
587
+ ".\Debug\gctest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
588
+ $(LINK32) @<<
589
+ $(LINK32_FLAGS) $(LINK32_OBJS)
590
+ <<
591
+
592
+ !ELSEIF "$(CFG)" == "cord - Win32 Release"
593
+
594
+ # PROP BASE Use_MFC 0
595
+ # PROP BASE Use_Debug_Libraries 0
596
+ # PROP BASE Output_Dir "cord\Release"
597
+ # PROP BASE Intermediate_Dir "cord\Release"
598
+ # PROP BASE Target_Dir "cord"
599
+ # PROP Use_MFC 0
600
+ # PROP Use_Debug_Libraries 0
601
+ # PROP Output_Dir "cord\Release"
602
+ # PROP Intermediate_Dir "cord\Release"
603
+ # PROP Target_Dir "cord"
604
+ OUTDIR=.\cord\Release
605
+ INTDIR=.\cord\Release
606
+
607
+ ALL : "gc - Win32 Release" ".\Release\de.exe"
608
+
609
+ CLEAN :
610
+ -@erase ".\cord\Release\cordbscs.obj"
611
+ -@erase ".\cord\Release\cordxtra.obj"
612
+ -@erase ".\cord\Release\de.obj"
613
+ -@erase ".\cord\Release\de_win.obj"
614
+ -@erase ".\cord\Release\de_win.res"
615
+ -@erase ".\Release\de.exe"
616
+
617
+ "$(OUTDIR)" :
618
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
619
+
620
+ CPP=cl.exe
621
+ # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
622
+ # ADD CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /YX /c
623
+ CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "." /I include /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D\
624
+ /Ilibatomic_ops-$(AO_VERSION)/src "ALL_INTERIOR_POINTERS" /Fp"$(INTDIR)/cord.pch" /YX /Fo"$(INTDIR)/" /c
625
+ CPP_OBJS=.\cord\Release/
626
+ CPP_SBRS=.\.
627
+
628
+ .c{$(CPP_OBJS)}.obj:
629
+ $(CPP) $(CPP_PROJ) $<
630
+
631
+ .cpp{$(CPP_OBJS)}.obj:
632
+ $(CPP) $(CPP_PROJ) $<
633
+
634
+ .cxx{$(CPP_OBJS)}.obj:
635
+ $(CPP) $(CPP_PROJ) $<
636
+
637
+ .c{$(CPP_SBRS)}.sbr:
638
+ $(CPP) $(CPP_PROJ) $<
639
+
640
+ .cpp{$(CPP_SBRS)}.sbr:
641
+ $(CPP) $(CPP_PROJ) $<
642
+
643
+ .cxx{$(CPP_SBRS)}.sbr:
644
+ $(CPP) $(CPP_PROJ) $<
645
+
646
+ MTL=mktyplib.exe
647
+ # ADD BASE MTL /nologo /D "NDEBUG" /win32
648
+ # ADD MTL /nologo /D "NDEBUG" /win32
649
+ MTL_PROJ=/nologo /D "NDEBUG" /win32
650
+ RSC=rc.exe
651
+ # ADD BASE RSC /l 0x809 /d "NDEBUG"
652
+ # ADD RSC /l 0x809 /d "NDEBUG"
653
+ RSC_PROJ=/l 0x809 /fo"$(INTDIR)/de_win.res" /d "NDEBUG"
654
+ BSC32=bscmake.exe
655
+ # ADD BASE BSC32 /nologo
656
+ # ADD BSC32 /nologo
657
+ BSC32_FLAGS=/nologo /o"$(OUTDIR)/cord.bsc"
658
+ BSC32_SBRS= \
659
+
660
+ LINK32=link.exe
661
+ # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
662
+ # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"Release/de.exe"
663
+ LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
664
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
665
+ odbccp32.lib /nologo /subsystem:windows /incremental:no /pdb:"$(OUTDIR)/de.pdb"\
666
+ /machine:I386 /out:"Release/de.exe"
667
+ LINK32_OBJS= \
668
+ ".\cord\Release\cordbscs.obj" \
669
+ ".\cord\Release\cordxtra.obj" \
670
+ ".\cord\Release\de.obj" \
671
+ ".\cord\Release\de_win.obj" \
672
+ ".\cord\Release\de_win.res" \
673
+ ".\Release\gc.lib"
674
+
675
+ ".\Release\de.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
676
+ $(LINK32) @<<
677
+ $(LINK32_FLAGS) $(LINK32_OBJS)
678
+ <<
679
+
680
+ !ELSEIF "$(CFG)" == "cord - Win32 Debug"
681
+
682
+ # PROP BASE Use_MFC 0
683
+ # PROP BASE Use_Debug_Libraries 1
684
+ # PROP BASE Output_Dir "cord\Debug"
685
+ # PROP BASE Intermediate_Dir "cord\Debug"
686
+ # PROP BASE Target_Dir "cord"
687
+ # PROP Use_MFC 0
688
+ # PROP Use_Debug_Libraries 1
689
+ # PROP Output_Dir "cord\Debug"
690
+ # PROP Intermediate_Dir "cord\Debug"
691
+ # PROP Target_Dir "cord"
692
+ OUTDIR=.\cord\Debug
693
+ INTDIR=.\cord\Debug
694
+
695
+ ALL : "gc - Win32 Debug" ".\Debug\de.exe"
696
+
697
+ CLEAN :
698
+ -@erase ".\cord\Debug\cordbscs.obj"
699
+ -@erase ".\cord\Debug\cordxtra.obj"
700
+ -@erase ".\cord\Debug\de.obj"
701
+ -@erase ".\cord\Debug\de.pdb"
702
+ -@erase ".\cord\Debug\de_win.obj"
703
+ -@erase ".\cord\Debug\de_win.res"
704
+ -@erase ".\cord\Debug\vc40.idb"
705
+ -@erase ".\cord\Debug\vc40.pdb"
706
+ -@erase ".\Debug\de.exe"
707
+ -@erase ".\Debug\de.ilk"
708
+
709
+ "$(OUTDIR)" :
710
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
711
+
712
+ CPP=cl.exe
713
+ # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
714
+ # ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "." /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /YX /c
715
+ CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "." /I include /D "_DEBUG" /D "WIN32" /D\
716
+ "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /Fp"$(INTDIR)/cord.pch" /YX\
717
+ /Ilibatomic_ops-$(AO_VERSION)/src /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
718
+ CPP_OBJS=.\cord\Debug/
719
+ CPP_SBRS=.\.
720
+
721
+ .c{$(CPP_OBJS)}.obj:
722
+ $(CPP) $(CPP_PROJ) $<
723
+
724
+ .cpp{$(CPP_OBJS)}.obj:
725
+ $(CPP) $(CPP_PROJ) $<
726
+
727
+ .cxx{$(CPP_OBJS)}.obj:
728
+ $(CPP) $(CPP_PROJ) $<
729
+
730
+ .c{$(CPP_SBRS)}.sbr:
731
+ $(CPP) $(CPP_PROJ) $<
732
+
733
+ .cpp{$(CPP_SBRS)}.sbr:
734
+ $(CPP) $(CPP_PROJ) $<
735
+
736
+ .cxx{$(CPP_SBRS)}.sbr:
737
+ $(CPP) $(CPP_PROJ) $<
738
+
739
+ MTL=mktyplib.exe
740
+ # ADD BASE MTL /nologo /D "_DEBUG" /win32
741
+ # ADD MTL /nologo /D "_DEBUG" /win32
742
+ MTL_PROJ=/nologo /D "_DEBUG" /win32
743
+ RSC=rc.exe
744
+ # ADD BASE RSC /l 0x809 /d "_DEBUG"
745
+ # ADD RSC /l 0x809 /d "_DEBUG"
746
+ RSC_PROJ=/l 0x809 /fo"$(INTDIR)/de_win.res" /d "_DEBUG"
747
+ BSC32=bscmake.exe
748
+ # ADD BASE BSC32 /nologo
749
+ # ADD BSC32 /nologo
750
+ BSC32_FLAGS=/nologo /o"$(OUTDIR)/cord.bsc"
751
+ BSC32_SBRS= \
752
+
753
+ LINK32=link.exe
754
+ # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
755
+ # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"Debug/de.exe"
756
+ LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
757
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
758
+ odbccp32.lib /nologo /subsystem:windows /incremental:yes\
759
+ /pdb:"$(OUTDIR)/de.pdb" /debug /machine:I386 /out:"Debug/de.exe"
760
+ LINK32_OBJS= \
761
+ ".\cord\Debug\cordbscs.obj" \
762
+ ".\cord\Debug\cordxtra.obj" \
763
+ ".\cord\Debug\de.obj" \
764
+ ".\cord\Debug\de_win.obj" \
765
+ ".\cord\Debug\de_win.res" \
766
+ ".\Debug\gc.lib"
767
+
768
+ ".\Debug\de.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
769
+ $(LINK32) @<<
770
+ $(LINK32_FLAGS) $(LINK32_OBJS)
771
+ <<
772
+
773
+ !ENDIF
774
+
775
+ ################################################################################
776
+ # Begin Target
777
+
778
+ # Name "gc - Win32 Release"
779
+ # Name "gc - Win32 Debug"
780
+
781
+ !IF "$(CFG)" == "gc - Win32 Release"
782
+
783
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
784
+
785
+ !ENDIF
786
+
787
+ ################################################################################
788
+ # Begin Source File
789
+
790
+ SOURCE=.\gc_cpp.cpp
791
+
792
+ !IF "$(CFG)" == "gc - Win32 Release"
793
+
794
+ DEP_CPP_RECLA=\
795
+ ".\include\private\gcconfig.h"\
796
+ ".\include\gc.h"\
797
+ ".\include\private\gc_hdrs.h"\
798
+ ".\include\private\gc_priv.h"\
799
+ ".\include\gc_cpp.h"\
800
+ {$(INCLUDE)}"\sys\TYPES.H"\
801
+
802
+ NODEP_CPP_RECLA=\
803
+ ".\th\PCR_Th.h"\
804
+ ".\th\PCR_ThCrSec.h"\
805
+ ".\th\PCR_ThCtl.h"\
806
+
807
+
808
+ ".\Release\gc_cpp.obj" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
809
+
810
+ ".\Release\gc_cpp.sbr" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
811
+
812
+
813
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
814
+
815
+ DEP_CPP_RECLA=\
816
+ ".\include\private\gcconfig.h"\
817
+ ".\include\gc.h"\
818
+ ".\include\private\gc_hdrs.h"\
819
+ ".\include\private\gc_priv.h"\
820
+ ".\include\gc_cpp.h"\
821
+ {$(INCLUDE)}"\sys\TYPES.H"\
822
+
823
+ NODEP_CPP_RECLA=\
824
+ ".\th\PCR_Th.h"\
825
+ ".\th\PCR_ThCrSec.h"\
826
+ ".\th\PCR_ThCtl.h"\
827
+
828
+
829
+ ".\Debug\gc_cpp.obj" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
830
+
831
+ ".\Debug\gc_cpp.sbr" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
832
+
833
+
834
+ !ENDIF
835
+
836
+ # End Source File
837
+ ################################################################################
838
+ # Begin Source File
839
+
840
+ SOURCE=.\reclaim.c
841
+
842
+ !IF "$(CFG)" == "gc - Win32 Release"
843
+
844
+ DEP_CPP_RECLA=\
845
+ ".\include\private\gcconfig.h"\
846
+ ".\include\gc.h"\
847
+ ".\include\private\gc_hdrs.h"\
848
+ ".\include\private\gc_priv.h"\
849
+ {$(INCLUDE)}"\sys\TYPES.H"\
850
+
851
+ NODEP_CPP_RECLA=\
852
+ ".\th\PCR_Th.h"\
853
+ ".\th\PCR_ThCrSec.h"\
854
+ ".\th\PCR_ThCtl.h"\
855
+
856
+
857
+ ".\Release\reclaim.obj" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
858
+
859
+ ".\Release\reclaim.sbr" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
860
+
861
+
862
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
863
+
864
+ DEP_CPP_RECLA=\
865
+ ".\include\private\gcconfig.h"\
866
+ ".\include\gc.h"\
867
+ ".\include\private\gc_hdrs.h"\
868
+ ".\include\private\gc_priv.h"\
869
+ {$(INCLUDE)}"\sys\TYPES.H"\
870
+
871
+ NODEP_CPP_RECLA=\
872
+ ".\th\PCR_Th.h"\
873
+ ".\th\PCR_ThCrSec.h"\
874
+ ".\th\PCR_ThCtl.h"\
875
+
876
+
877
+ ".\Debug\reclaim.obj" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
878
+
879
+ ".\Debug\reclaim.sbr" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
880
+
881
+
882
+ !ENDIF
883
+
884
+ # End Source File
885
+
886
+ ################################################################################
887
+ # Begin Source File
888
+
889
+ SOURCE=.\os_dep.c
890
+
891
+ !IF "$(CFG)" == "gc - Win32 Release"
892
+
893
+ DEP_CPP_OS_DE=\
894
+ ".\include\private\gcconfig.h"\
895
+ ".\include\gc.h"\
896
+ ".\include\private\gc_hdrs.h"\
897
+ ".\include\private\gc_priv.h"\
898
+ {$(INCLUDE)}"\sys\STAT.H"\
899
+ {$(INCLUDE)}"\sys\TYPES.H"\
900
+
901
+ NODEP_CPP_OS_DE=\
902
+ ".\il\PCR_IL.h"\
903
+ ".\mm\PCR_MM.h"\
904
+ ".\th\PCR_Th.h"\
905
+ ".\th\PCR_ThCrSec.h"\
906
+ ".\th\PCR_ThCtl.h"\
907
+ ".\vd\PCR_VD.h"\
908
+
909
+
910
+ ".\Release\os_dep.obj" : $(SOURCE) $(DEP_CPP_OS_DE) "$(INTDIR)"
911
+
912
+ ".\Release\os_dep.sbr" : $(SOURCE) $(DEP_CPP_OS_DE) "$(INTDIR)"
913
+
914
+
915
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
916
+
917
+ DEP_CPP_OS_DE=\
918
+ ".\include\private\gcconfig.h"\
919
+ ".\include\gc.h"\
920
+ ".\include\private\gc_hdrs.h"\
921
+ ".\include\private\gc_priv.h"\
922
+ {$(INCLUDE)}"\sys\STAT.H"\
923
+ {$(INCLUDE)}"\sys\TYPES.H"\
924
+
925
+ NODEP_CPP_OS_DE=\
926
+ ".\il\PCR_IL.h"\
927
+ ".\mm\PCR_MM.h"\
928
+ ".\th\PCR_Th.h"\
929
+ ".\th\PCR_ThCrSec.h"\
930
+ ".\th\PCR_ThCtl.h"\
931
+ ".\vd\PCR_VD.h"\
932
+
933
+
934
+ ".\Debug\os_dep.obj" : $(SOURCE) $(DEP_CPP_OS_DE) "$(INTDIR)"
935
+
936
+ ".\Debug\os_dep.sbr" : $(SOURCE) $(DEP_CPP_OS_DE) "$(INTDIR)"
937
+
938
+
939
+ !ENDIF
940
+
941
+ # End Source File
942
+ ################################################################################
943
+ # Begin Source File
944
+
945
+ SOURCE=.\misc.c
946
+
947
+ !IF "$(CFG)" == "gc - Win32 Release"
948
+
949
+ DEP_CPP_MISC_=\
950
+ ".\include\private\gcconfig.h"\
951
+ ".\include\gc.h"\
952
+ ".\include\private\gc_hdrs.h"\
953
+ ".\include\private\gc_priv.h"\
954
+ {$(INCLUDE)}"\sys\TYPES.H"\
955
+
956
+ NODEP_CPP_MISC_=\
957
+ ".\il\PCR_IL.h"\
958
+ ".\th\PCR_Th.h"\
959
+ ".\th\PCR_ThCrSec.h"\
960
+ ".\th\PCR_ThCtl.h"\
961
+
962
+
963
+ ".\Release\misc.obj" : $(SOURCE) $(DEP_CPP_MISC_) "$(INTDIR)"
964
+
965
+ ".\Release\misc.sbr" : $(SOURCE) $(DEP_CPP_MISC_) "$(INTDIR)"
966
+
967
+
968
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
969
+
970
+ DEP_CPP_MISC_=\
971
+ ".\include\private\gcconfig.h"\
972
+ ".\include\gc.h"\
973
+ ".\include\private\gc_hdrs.h"\
974
+ ".\include\private\gc_priv.h"\
975
+ {$(INCLUDE)}"\sys\TYPES.H"\
976
+
977
+ NODEP_CPP_MISC_=\
978
+ ".\il\PCR_IL.h"\
979
+ ".\th\PCR_Th.h"\
980
+ ".\th\PCR_ThCrSec.h"\
981
+ ".\th\PCR_ThCtl.h"\
982
+
983
+
984
+ ".\Debug\misc.obj" : $(SOURCE) $(DEP_CPP_MISC_) "$(INTDIR)"
985
+
986
+ ".\Debug\misc.sbr" : $(SOURCE) $(DEP_CPP_MISC_) "$(INTDIR)"
987
+
988
+
989
+ !ENDIF
990
+
991
+ # End Source File
992
+ ################################################################################
993
+ # Begin Source File
994
+
995
+ SOURCE=.\mark_rts.c
996
+
997
+ !IF "$(CFG)" == "gc - Win32 Release"
998
+
999
+ DEP_CPP_MARK_=\
1000
+ ".\include\private\gcconfig.h"\
1001
+ ".\include\gc.h"\
1002
+ ".\include\private\gc_hdrs.h"\
1003
+ ".\include\private\gc_priv.h"\
1004
+ {$(INCLUDE)}"\sys\TYPES.H"\
1005
+
1006
+ NODEP_CPP_MARK_=\
1007
+ ".\th\PCR_Th.h"\
1008
+ ".\th\PCR_ThCrSec.h"\
1009
+ ".\th\PCR_ThCtl.h"\
1010
+
1011
+
1012
+ ".\Release\mark_rts.obj" : $(SOURCE) $(DEP_CPP_MARK_) "$(INTDIR)"
1013
+
1014
+ ".\Release\mark_rts.sbr" : $(SOURCE) $(DEP_CPP_MARK_) "$(INTDIR)"
1015
+
1016
+
1017
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1018
+
1019
+ DEP_CPP_MARK_=\
1020
+ ".\include\private\gcconfig.h"\
1021
+ ".\include\gc.h"\
1022
+ ".\include\private\gc_hdrs.h"\
1023
+ ".\include\private\gc_priv.h"\
1024
+ {$(INCLUDE)}"\sys\TYPES.H"\
1025
+
1026
+ NODEP_CPP_MARK_=\
1027
+ ".\th\PCR_Th.h"\
1028
+ ".\th\PCR_ThCrSec.h"\
1029
+ ".\th\PCR_ThCtl.h"\
1030
+
1031
+
1032
+ ".\Debug\mark_rts.obj" : $(SOURCE) $(DEP_CPP_MARK_) "$(INTDIR)"
1033
+
1034
+ ".\Debug\mark_rts.sbr" : $(SOURCE) $(DEP_CPP_MARK_) "$(INTDIR)"
1035
+
1036
+
1037
+ !ENDIF
1038
+
1039
+ # End Source File
1040
+ ################################################################################
1041
+ # Begin Source File
1042
+
1043
+ SOURCE=.\mach_dep.c
1044
+
1045
+ !IF "$(CFG)" == "gc - Win32 Release"
1046
+
1047
+ DEP_CPP_MACH_=\
1048
+ ".\include\private\gcconfig.h"\
1049
+ ".\include\gc.h"\
1050
+ ".\include\private\gc_hdrs.h"\
1051
+ ".\include\private\gc_priv.h"\
1052
+ {$(INCLUDE)}"\sys\TYPES.H"\
1053
+
1054
+ NODEP_CPP_MACH_=\
1055
+ ".\th\PCR_Th.h"\
1056
+ ".\th\PCR_ThCrSec.h"\
1057
+ ".\th\PCR_ThCtl.h"\
1058
+
1059
+
1060
+ ".\Release\mach_dep.obj" : $(SOURCE) $(DEP_CPP_MACH_) "$(INTDIR)"
1061
+
1062
+ ".\Release\mach_dep.sbr" : $(SOURCE) $(DEP_CPP_MACH_) "$(INTDIR)"
1063
+
1064
+
1065
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1066
+
1067
+ DEP_CPP_MACH_=\
1068
+ ".\include\private\gcconfig.h"\
1069
+ ".\include\gc.h"\
1070
+ ".\include\private\gc_hdrs.h"\
1071
+ ".\include\private\gc_priv.h"\
1072
+ {$(INCLUDE)}"\sys\TYPES.H"\
1073
+
1074
+ NODEP_CPP_MACH_=\
1075
+ ".\th\PCR_Th.h"\
1076
+ ".\th\PCR_ThCrSec.h"\
1077
+ ".\th\PCR_ThCtl.h"\
1078
+
1079
+
1080
+ ".\Debug\mach_dep.obj" : $(SOURCE) $(DEP_CPP_MACH_) "$(INTDIR)"
1081
+
1082
+ ".\Debug\mach_dep.sbr" : $(SOURCE) $(DEP_CPP_MACH_) "$(INTDIR)"
1083
+
1084
+
1085
+ !ENDIF
1086
+
1087
+ # End Source File
1088
+ ################################################################################
1089
+ # Begin Source File
1090
+
1091
+ SOURCE=.\headers.c
1092
+
1093
+ !IF "$(CFG)" == "gc - Win32 Release"
1094
+
1095
+ DEP_CPP_HEADE=\
1096
+ ".\include\private\gcconfig.h"\
1097
+ ".\include\gc.h"\
1098
+ ".\include\private\gc_hdrs.h"\
1099
+ ".\include\private\gc_priv.h"\
1100
+ {$(INCLUDE)}"\sys\TYPES.H"\
1101
+
1102
+ NODEP_CPP_HEADE=\
1103
+ ".\th\PCR_Th.h"\
1104
+ ".\th\PCR_ThCrSec.h"\
1105
+ ".\th\PCR_ThCtl.h"\
1106
+
1107
+
1108
+ ".\Release\headers.obj" : $(SOURCE) $(DEP_CPP_HEADE) "$(INTDIR)"
1109
+
1110
+ ".\Release\headers.sbr" : $(SOURCE) $(DEP_CPP_HEADE) "$(INTDIR)"
1111
+
1112
+
1113
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1114
+
1115
+ DEP_CPP_HEADE=\
1116
+ ".\include\private\gcconfig.h"\
1117
+ ".\include\gc.h"\
1118
+ ".\include\private\gc_hdrs.h"\
1119
+ ".\include\private\gc_priv.h"\
1120
+ {$(INCLUDE)}"\sys\TYPES.H"\
1121
+
1122
+ NODEP_CPP_HEADE=\
1123
+ ".\th\PCR_Th.h"\
1124
+ ".\th\PCR_ThCrSec.h"\
1125
+ ".\th\PCR_ThCtl.h"\
1126
+
1127
+
1128
+ ".\Debug\headers.obj" : $(SOURCE) $(DEP_CPP_HEADE) "$(INTDIR)"
1129
+
1130
+ ".\Debug\headers.sbr" : $(SOURCE) $(DEP_CPP_HEADE) "$(INTDIR)"
1131
+
1132
+
1133
+ !ENDIF
1134
+
1135
+ # End Source File
1136
+ ################################################################################
1137
+ # Begin Source File
1138
+
1139
+ SOURCE=.\alloc.c
1140
+
1141
+ !IF "$(CFG)" == "gc - Win32 Release"
1142
+
1143
+ DEP_CPP_ALLOC=\
1144
+ ".\include\private\gcconfig.h"\
1145
+ ".\include\gc.h"\
1146
+ ".\include\private\gc_hdrs.h"\
1147
+ ".\include\private\gc_priv.h"\
1148
+ {$(INCLUDE)}"\sys\TYPES.H"\
1149
+
1150
+ NODEP_CPP_ALLOC=\
1151
+ ".\th\PCR_Th.h"\
1152
+ ".\th\PCR_ThCrSec.h"\
1153
+ ".\th\PCR_ThCtl.h"\
1154
+
1155
+
1156
+ ".\Release\alloc.obj" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)"
1157
+
1158
+ ".\Release\alloc.sbr" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)"
1159
+
1160
+
1161
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1162
+
1163
+ DEP_CPP_ALLOC=\
1164
+ ".\include\private\gcconfig.h"\
1165
+ ".\include\gc.h"\
1166
+ ".\include\private\gc_hdrs.h"\
1167
+ ".\include\private\gc_priv.h"\
1168
+ {$(INCLUDE)}"\sys\TYPES.H"\
1169
+
1170
+ NODEP_CPP_ALLOC=\
1171
+ ".\th\PCR_Th.h"\
1172
+ ".\th\PCR_ThCrSec.h"\
1173
+ ".\th\PCR_ThCtl.h"\
1174
+
1175
+
1176
+ ".\Debug\alloc.obj" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)"
1177
+
1178
+ ".\Debug\alloc.sbr" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)"
1179
+
1180
+
1181
+ !ENDIF
1182
+
1183
+ # End Source File
1184
+ ################################################################################
1185
+ # Begin Source File
1186
+
1187
+ SOURCE=.\allchblk.c
1188
+
1189
+ !IF "$(CFG)" == "gc - Win32 Release"
1190
+
1191
+ DEP_CPP_ALLCH=\
1192
+ ".\include\private\gcconfig.h"\
1193
+ ".\include\gc.h"\
1194
+ ".\include\private\gc_hdrs.h"\
1195
+ ".\include\private\gc_priv.h"\
1196
+ {$(INCLUDE)}"\sys\TYPES.H"\
1197
+
1198
+ NODEP_CPP_ALLCH=\
1199
+ ".\th\PCR_Th.h"\
1200
+ ".\th\PCR_ThCrSec.h"\
1201
+ ".\th\PCR_ThCtl.h"\
1202
+
1203
+
1204
+ ".\Release\allchblk.obj" : $(SOURCE) $(DEP_CPP_ALLCH) "$(INTDIR)"
1205
+
1206
+ ".\Release\allchblk.sbr" : $(SOURCE) $(DEP_CPP_ALLCH) "$(INTDIR)"
1207
+
1208
+
1209
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1210
+
1211
+ DEP_CPP_ALLCH=\
1212
+ ".\include\private\gcconfig.h"\
1213
+ ".\include\gc.h"\
1214
+ ".\include\private\gc_hdrs.h"\
1215
+ ".\include\private\gc_priv.h"\
1216
+ {$(INCLUDE)}"\sys\TYPES.H"\
1217
+
1218
+ NODEP_CPP_ALLCH=\
1219
+ ".\th\PCR_Th.h"\
1220
+ ".\th\PCR_ThCrSec.h"\
1221
+ ".\th\PCR_ThCtl.h"\
1222
+
1223
+
1224
+ ".\Debug\allchblk.obj" : $(SOURCE) $(DEP_CPP_ALLCH) "$(INTDIR)"
1225
+
1226
+ ".\Debug\allchblk.sbr" : $(SOURCE) $(DEP_CPP_ALLCH) "$(INTDIR)"
1227
+
1228
+
1229
+ !ENDIF
1230
+
1231
+ # End Source File
1232
+ ################################################################################
1233
+ # Begin Source File
1234
+
1235
+ SOURCE=.\stubborn.c
1236
+
1237
+ !IF "$(CFG)" == "gc - Win32 Release"
1238
+
1239
+ DEP_CPP_STUBB=\
1240
+ ".\include\private\gcconfig.h"\
1241
+ ".\include\gc.h"\
1242
+ ".\include\private\gc_hdrs.h"\
1243
+ ".\include\private\gc_priv.h"\
1244
+ {$(INCLUDE)}"\sys\TYPES.H"\
1245
+
1246
+ NODEP_CPP_STUBB=\
1247
+ ".\th\PCR_Th.h"\
1248
+ ".\th\PCR_ThCrSec.h"\
1249
+ ".\th\PCR_ThCtl.h"\
1250
+
1251
+
1252
+ ".\Release\stubborn.obj" : $(SOURCE) $(DEP_CPP_STUBB) "$(INTDIR)"
1253
+
1254
+ ".\Release\stubborn.sbr" : $(SOURCE) $(DEP_CPP_STUBB) "$(INTDIR)"
1255
+
1256
+
1257
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1258
+
1259
+ DEP_CPP_STUBB=\
1260
+ ".\include\private\gcconfig.h"\
1261
+ ".\include\gc.h"\
1262
+ ".\include\private\gc_hdrs.h"\
1263
+ ".\include\private\gc_priv.h"\
1264
+ {$(INCLUDE)}"\sys\TYPES.H"\
1265
+
1266
+ NODEP_CPP_STUBB=\
1267
+ ".\th\PCR_Th.h"\
1268
+ ".\th\PCR_ThCrSec.h"\
1269
+ ".\th\PCR_ThCtl.h"\
1270
+
1271
+
1272
+ ".\Debug\stubborn.obj" : $(SOURCE) $(DEP_CPP_STUBB) "$(INTDIR)"
1273
+
1274
+ ".\Debug\stubborn.sbr" : $(SOURCE) $(DEP_CPP_STUBB) "$(INTDIR)"
1275
+
1276
+
1277
+ !ENDIF
1278
+
1279
+ # End Source File
1280
+ ################################################################################
1281
+ # Begin Source File
1282
+
1283
+ SOURCE=.\obj_map.c
1284
+
1285
+ !IF "$(CFG)" == "gc - Win32 Release"
1286
+
1287
+ DEP_CPP_OBJ_M=\
1288
+ ".\include\private\gcconfig.h"\
1289
+ ".\include\gc.h"\
1290
+ ".\include\private\gc_hdrs.h"\
1291
+ ".\include\private\gc_priv.h"\
1292
+ {$(INCLUDE)}"\sys\TYPES.H"\
1293
+
1294
+ NODEP_CPP_OBJ_M=\
1295
+ ".\th\PCR_Th.h"\
1296
+ ".\th\PCR_ThCrSec.h"\
1297
+ ".\th\PCR_ThCtl.h"\
1298
+
1299
+
1300
+ ".\Release\obj_map.obj" : $(SOURCE) $(DEP_CPP_OBJ_M) "$(INTDIR)"
1301
+
1302
+ ".\Release\obj_map.sbr" : $(SOURCE) $(DEP_CPP_OBJ_M) "$(INTDIR)"
1303
+
1304
+
1305
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1306
+
1307
+ DEP_CPP_OBJ_M=\
1308
+ ".\include\private\gcconfig.h"\
1309
+ ".\include\gc.h"\
1310
+ ".\include\private\gc_hdrs.h"\
1311
+ ".\include\private\gc_priv.h"\
1312
+ {$(INCLUDE)}"\sys\TYPES.H"\
1313
+
1314
+ NODEP_CPP_OBJ_M=\
1315
+ ".\th\PCR_Th.h"\
1316
+ ".\th\PCR_ThCrSec.h"\
1317
+ ".\th\PCR_ThCtl.h"\
1318
+
1319
+
1320
+ ".\Debug\obj_map.obj" : $(SOURCE) $(DEP_CPP_OBJ_M) "$(INTDIR)"
1321
+
1322
+ ".\Debug\obj_map.sbr" : $(SOURCE) $(DEP_CPP_OBJ_M) "$(INTDIR)"
1323
+
1324
+
1325
+ !ENDIF
1326
+
1327
+ # End Source File
1328
+ ################################################################################
1329
+ # Begin Source File
1330
+
1331
+ SOURCE=.\new_hblk.c
1332
+
1333
+ !IF "$(CFG)" == "gc - Win32 Release"
1334
+
1335
+ DEP_CPP_NEW_H=\
1336
+ ".\include\private\gcconfig.h"\
1337
+ ".\include\gc.h"\
1338
+ ".\include\private\gc_hdrs.h"\
1339
+ ".\include\private\gc_priv.h"\
1340
+ {$(INCLUDE)}"\sys\TYPES.H"\
1341
+
1342
+ NODEP_CPP_NEW_H=\
1343
+ ".\th\PCR_Th.h"\
1344
+ ".\th\PCR_ThCrSec.h"\
1345
+ ".\th\PCR_ThCtl.h"\
1346
+
1347
+
1348
+ ".\Release\new_hblk.obj" : $(SOURCE) $(DEP_CPP_NEW_H) "$(INTDIR)"
1349
+
1350
+ ".\Release\new_hblk.sbr" : $(SOURCE) $(DEP_CPP_NEW_H) "$(INTDIR)"
1351
+
1352
+
1353
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1354
+
1355
+ DEP_CPP_NEW_H=\
1356
+ ".\include\private\gcconfig.h"\
1357
+ ".\include\gc.h"\
1358
+ ".\include\private\gc_hdrs.h"\
1359
+ ".\include\private\gc_priv.h"\
1360
+ {$(INCLUDE)}"\sys\TYPES.H"\
1361
+
1362
+ NODEP_CPP_NEW_H=\
1363
+ ".\th\PCR_Th.h"\
1364
+ ".\th\PCR_ThCrSec.h"\
1365
+ ".\th\PCR_ThCtl.h"\
1366
+
1367
+
1368
+ ".\Debug\new_hblk.obj" : $(SOURCE) $(DEP_CPP_NEW_H) "$(INTDIR)"
1369
+
1370
+ ".\Debug\new_hblk.sbr" : $(SOURCE) $(DEP_CPP_NEW_H) "$(INTDIR)"
1371
+
1372
+
1373
+ !ENDIF
1374
+
1375
+ # End Source File
1376
+ ################################################################################
1377
+ # Begin Source File
1378
+
1379
+ SOURCE=.\mark.c
1380
+
1381
+ !IF "$(CFG)" == "gc - Win32 Release"
1382
+
1383
+ DEP_CPP_MARK_C=\
1384
+ ".\include\private\gcconfig.h"\
1385
+ ".\include\gc.h"\
1386
+ ".\include\private\gc_hdrs.h"\
1387
+ ".\include\private\gc_pmark.h"\
1388
+ ".\include\gc_mark.h"\
1389
+ ".\include\private\gc_priv.h"\
1390
+ {$(INCLUDE)}"\sys\TYPES.H"\
1391
+
1392
+ NODEP_CPP_MARK_C=\
1393
+ ".\th\PCR_Th.h"\
1394
+ ".\th\PCR_ThCrSec.h"\
1395
+ ".\th\PCR_ThCtl.h"\
1396
+
1397
+
1398
+ ".\Release\mark.obj" : $(SOURCE) $(DEP_CPP_MARK_C) "$(INTDIR)"
1399
+
1400
+ ".\Release\mark.sbr" : $(SOURCE) $(DEP_CPP_MARK_C) "$(INTDIR)"
1401
+
1402
+
1403
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1404
+
1405
+ DEP_CPP_MARK_C=\
1406
+ ".\include\private\gcconfig.h"\
1407
+ ".\include\gc.h"\
1408
+ ".\include\private\gc_hdrs.h"\
1409
+ ".\include\private\gc_pmark.h"\
1410
+ ".\include\gc_mark.h"\
1411
+ ".\include\private\gc_priv.h"\
1412
+ {$(INCLUDE)}"\sys\TYPES.H"\
1413
+
1414
+ NODEP_CPP_MARK_C=\
1415
+ ".\th\PCR_Th.h"\
1416
+ ".\th\PCR_ThCrSec.h"\
1417
+ ".\th\PCR_ThCtl.h"\
1418
+
1419
+
1420
+ ".\Debug\mark.obj" : $(SOURCE) $(DEP_CPP_MARK_C) "$(INTDIR)"
1421
+
1422
+ ".\Debug\mark.sbr" : $(SOURCE) $(DEP_CPP_MARK_C) "$(INTDIR)"
1423
+
1424
+
1425
+ !ENDIF
1426
+
1427
+ # End Source File
1428
+ ################################################################################
1429
+ # Begin Source File
1430
+
1431
+ SOURCE=.\malloc.c
1432
+
1433
+ !IF "$(CFG)" == "gc - Win32 Release"
1434
+
1435
+ DEP_CPP_MALLO=\
1436
+ ".\include\private\gcconfig.h"\
1437
+ ".\include\gc.h"\
1438
+ ".\include\private\gc_hdrs.h"\
1439
+ ".\include\private\gc_priv.h"\
1440
+ {$(INCLUDE)}"\sys\TYPES.H"\
1441
+
1442
+ NODEP_CPP_MALLO=\
1443
+ ".\th\PCR_Th.h"\
1444
+ ".\th\PCR_ThCrSec.h"\
1445
+ ".\th\PCR_ThCtl.h"\
1446
+
1447
+
1448
+ ".\Release\malloc.obj" : $(SOURCE) $(DEP_CPP_MALLO) "$(INTDIR)"
1449
+
1450
+ ".\Release\malloc.sbr" : $(SOURCE) $(DEP_CPP_MALLO) "$(INTDIR)"
1451
+
1452
+
1453
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1454
+
1455
+ DEP_CPP_MALLO=\
1456
+ ".\include\private\gcconfig.h"\
1457
+ ".\include\gc.h"\
1458
+ ".\include\private\gc_hdrs.h"\
1459
+ ".\include\private\gc_priv.h"\
1460
+ {$(INCLUDE)}"\sys\TYPES.H"\
1461
+
1462
+ NODEP_CPP_MALLO=\
1463
+ ".\th\PCR_Th.h"\
1464
+ ".\th\PCR_ThCrSec.h"\
1465
+ ".\th\PCR_ThCtl.h"\
1466
+
1467
+
1468
+ ".\Debug\malloc.obj" : $(SOURCE) $(DEP_CPP_MALLO) "$(INTDIR)"
1469
+
1470
+ ".\Debug\malloc.sbr" : $(SOURCE) $(DEP_CPP_MALLO) "$(INTDIR)"
1471
+
1472
+
1473
+ !ENDIF
1474
+
1475
+ # End Source File
1476
+ ################################################################################
1477
+ # Begin Source File
1478
+
1479
+ SOURCE=.\mallocx.c
1480
+
1481
+ !IF "$(CFG)" == "gc - Win32 Release"
1482
+
1483
+ DEP_CPP_MALLX=\
1484
+ ".\include\private\gcconfig.h"\
1485
+ ".\include\gc.h"\
1486
+ ".\include\private\gc_hdrs.h"\
1487
+ ".\include\private\gc_priv.h"\
1488
+ {$(INCLUDE)}"\sys\TYPES.H"\
1489
+
1490
+ NODEP_CPP_MALLX=\
1491
+ ".\th\PCR_Th.h"\
1492
+ ".\th\PCR_ThCrSec.h"\
1493
+ ".\th\PCR_ThCtl.h"\
1494
+
1495
+
1496
+ ".\Release\mallocx.obj" : $(SOURCE) $(DEP_CPP_MALLX) "$(INTDIR)"
1497
+
1498
+ ".\Release\mallocx.sbr" : $(SOURCE) $(DEP_CPP_MALLX) "$(INTDIR)"
1499
+
1500
+
1501
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1502
+
1503
+ DEP_CPP_MALLX=\
1504
+ ".\include\private\gcconfig.h"\
1505
+ ".\include\gc.h"\
1506
+ ".\include\private\gc_hdrs.h"\
1507
+ ".\include\private\gc_priv.h"\
1508
+ {$(INCLUDE)}"\sys\TYPES.H"\
1509
+
1510
+ NODEP_CPP_MALLX=\
1511
+ ".\th\PCR_Th.h"\
1512
+ ".\th\PCR_ThCrSec.h"\
1513
+ ".\th\PCR_ThCtl.h"\
1514
+
1515
+
1516
+ ".\Debug\mallocx.obj" : $(SOURCE) $(DEP_CPP_MALLX) "$(INTDIR)"
1517
+
1518
+ ".\Debug\mallocx.sbr" : $(SOURCE) $(DEP_CPP_MALLX) "$(INTDIR)"
1519
+
1520
+
1521
+ !ENDIF
1522
+
1523
+ # End Source File
1524
+ ################################################################################
1525
+ # Begin Source File
1526
+
1527
+ SOURCE=.\finalize.c
1528
+
1529
+ !IF "$(CFG)" == "gc - Win32 Release"
1530
+
1531
+ DEP_CPP_FINAL=\
1532
+ ".\include\private\gcconfig.h"\
1533
+ ".\include\gc.h"\
1534
+ ".\include\private\gc_hdrs.h"\
1535
+ ".\include\private\gc_pmark.h"\
1536
+ ".\include\gc_mark.h"\
1537
+ ".\include\private\gc_priv.h"\
1538
+ {$(INCLUDE)}"\sys\TYPES.H"\
1539
+
1540
+ NODEP_CPP_FINAL=\
1541
+ ".\th\PCR_Th.h"\
1542
+ ".\th\PCR_ThCrSec.h"\
1543
+ ".\th\PCR_ThCtl.h"\
1544
+
1545
+
1546
+ ".\Release\finalize.obj" : $(SOURCE) $(DEP_CPP_FINAL) "$(INTDIR)"
1547
+
1548
+ ".\Release\finalize.sbr" : $(SOURCE) $(DEP_CPP_FINAL) "$(INTDIR)"
1549
+
1550
+
1551
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1552
+
1553
+ DEP_CPP_FINAL=\
1554
+ ".\include\private\gcconfig.h"\
1555
+ ".\include\gc.h"\
1556
+ ".\include\private\gc_hdrs.h"\
1557
+ ".\include\private\gc_pmark.h"\
1558
+ ".\include\gc_mark.h"\
1559
+ ".\include\private\gc_priv.h"\
1560
+ {$(INCLUDE)}"\sys\TYPES.H"\
1561
+
1562
+ NODEP_CPP_FINAL=\
1563
+ ".\th\PCR_Th.h"\
1564
+ ".\th\PCR_ThCrSec.h"\
1565
+ ".\th\PCR_ThCtl.h"\
1566
+
1567
+
1568
+ ".\Debug\finalize.obj" : $(SOURCE) $(DEP_CPP_FINAL) "$(INTDIR)"
1569
+
1570
+ ".\Debug\finalize.sbr" : $(SOURCE) $(DEP_CPP_FINAL) "$(INTDIR)"
1571
+
1572
+
1573
+ !ENDIF
1574
+
1575
+ # End Source File
1576
+ ################################################################################
1577
+ # Begin Source File
1578
+
1579
+ SOURCE=.\dbg_mlc.c
1580
+
1581
+ !IF "$(CFG)" == "gc - Win32 Release"
1582
+
1583
+ DEP_CPP_DBG_M=\
1584
+ ".\include\private\gcconfig.h"\
1585
+ ".\include\gc.h"\
1586
+ ".\include\private\gc_hdrs.h"\
1587
+ ".\include\private\gc_priv.h"\
1588
+ {$(INCLUDE)}"\sys\TYPES.H"\
1589
+
1590
+ NODEP_CPP_DBG_M=\
1591
+ ".\th\PCR_Th.h"\
1592
+ ".\th\PCR_ThCrSec.h"\
1593
+ ".\th\PCR_ThCtl.h"\
1594
+
1595
+
1596
+ ".\Release\dbg_mlc.obj" : $(SOURCE) $(DEP_CPP_DBG_M) "$(INTDIR)"
1597
+
1598
+ ".\Release\dbg_mlc.sbr" : $(SOURCE) $(DEP_CPP_DBG_M) "$(INTDIR)"
1599
+
1600
+
1601
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1602
+
1603
+ DEP_CPP_DBG_M=\
1604
+ ".\include\private\gcconfig.h"\
1605
+ ".\include\gc.h"\
1606
+ ".\include\private\gc_hdrs.h"\
1607
+ ".\include\private\gc_priv.h"\
1608
+ {$(INCLUDE)}"\sys\TYPES.H"\
1609
+
1610
+ NODEP_CPP_DBG_M=\
1611
+ ".\th\PCR_Th.h"\
1612
+ ".\th\PCR_ThCrSec.h"\
1613
+ ".\th\PCR_ThCtl.h"\
1614
+
1615
+
1616
+ ".\Debug\dbg_mlc.obj" : $(SOURCE) $(DEP_CPP_DBG_M) "$(INTDIR)"
1617
+
1618
+ ".\Debug\dbg_mlc.sbr" : $(SOURCE) $(DEP_CPP_DBG_M) "$(INTDIR)"
1619
+
1620
+
1621
+ !ENDIF
1622
+
1623
+ # End Source File
1624
+ ################################################################################
1625
+ # Begin Source File
1626
+
1627
+ SOURCE=.\blacklst.c
1628
+
1629
+ !IF "$(CFG)" == "gc - Win32 Release"
1630
+
1631
+ DEP_CPP_BLACK=\
1632
+ ".\include\private\gcconfig.h"\
1633
+ ".\include\gc.h"\
1634
+ ".\include\private\gc_hdrs.h"\
1635
+ ".\include\private\gc_priv.h"\
1636
+ {$(INCLUDE)}"\sys\TYPES.H"\
1637
+
1638
+ NODEP_CPP_BLACK=\
1639
+ ".\th\PCR_Th.h"\
1640
+ ".\th\PCR_ThCrSec.h"\
1641
+ ".\th\PCR_ThCtl.h"\
1642
+
1643
+
1644
+ ".\Release\blacklst.obj" : $(SOURCE) $(DEP_CPP_BLACK) "$(INTDIR)"
1645
+
1646
+ ".\Release\blacklst.sbr" : $(SOURCE) $(DEP_CPP_BLACK) "$(INTDIR)"
1647
+
1648
+
1649
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1650
+
1651
+ DEP_CPP_BLACK=\
1652
+ ".\include\private\gcconfig.h"\
1653
+ ".\include\gc.h"\
1654
+ ".\include\private\gc_hdrs.h"\
1655
+ ".\include\private\gc_priv.h"\
1656
+ {$(INCLUDE)}"\sys\TYPES.H"\
1657
+
1658
+ NODEP_CPP_BLACK=\
1659
+ ".\th\PCR_Th.h"\
1660
+ ".\th\PCR_ThCrSec.h"\
1661
+ ".\th\PCR_ThCtl.h"\
1662
+
1663
+
1664
+ ".\Debug\blacklst.obj" : $(SOURCE) $(DEP_CPP_BLACK) "$(INTDIR)"
1665
+
1666
+ ".\Debug\blacklst.sbr" : $(SOURCE) $(DEP_CPP_BLACK) "$(INTDIR)"
1667
+
1668
+
1669
+ !ENDIF
1670
+
1671
+ # End Source File
1672
+ ################################################################################
1673
+ # Begin Source File
1674
+
1675
+ SOURCE=.\typd_mlc.c
1676
+
1677
+ !IF "$(CFG)" == "gc - Win32 Release"
1678
+
1679
+ DEP_CPP_TYPD_=\
1680
+ ".\include\private\gcconfig.h"\
1681
+ ".\include\gc.h"\
1682
+ ".\include\private\gc_hdrs.h"\
1683
+ ".\include\private\gc_pmark.h"\
1684
+ ".\include\gc_mark.h"\
1685
+ ".\include\private\gc_priv.h"\
1686
+ ".\include\gc_typed.h"\
1687
+ {$(INCLUDE)}"\sys\TYPES.H"\
1688
+
1689
+ NODEP_CPP_TYPD_=\
1690
+ ".\th\PCR_Th.h"\
1691
+ ".\th\PCR_ThCrSec.h"\
1692
+ ".\th\PCR_ThCtl.h"\
1693
+
1694
+
1695
+ ".\Release\typd_mlc.obj" : $(SOURCE) $(DEP_CPP_TYPD_) "$(INTDIR)"
1696
+
1697
+ ".\Release\typd_mlc.sbr" : $(SOURCE) $(DEP_CPP_TYPD_) "$(INTDIR)"
1698
+
1699
+
1700
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1701
+
1702
+ DEP_CPP_TYPD_=\
1703
+ ".\include\private\gcconfig.h"\
1704
+ ".\include\gc.h"\
1705
+ ".\include\private\gc_hdrs.h"\
1706
+ ".\include\private\gc_pmark.h"\
1707
+ ".\include\gc_mark.h"\
1708
+ ".\include\private\gc_priv.h"\
1709
+ ".\include\gc_typed.h"\
1710
+ {$(INCLUDE)}"\sys\TYPES.H"\
1711
+
1712
+ NODEP_CPP_TYPD_=\
1713
+ ".\th\PCR_Th.h"\
1714
+ ".\th\PCR_ThCrSec.h"\
1715
+ ".\th\PCR_ThCtl.h"\
1716
+
1717
+
1718
+ ".\Debug\typd_mlc.obj" : $(SOURCE) $(DEP_CPP_TYPD_) "$(INTDIR)"
1719
+
1720
+ ".\Debug\typd_mlc.sbr" : $(SOURCE) $(DEP_CPP_TYPD_) "$(INTDIR)"
1721
+
1722
+
1723
+ !ENDIF
1724
+
1725
+ # End Source File
1726
+ ################################################################################
1727
+ # Begin Source File
1728
+
1729
+ SOURCE=.\ptr_chck.c
1730
+
1731
+ !IF "$(CFG)" == "gc - Win32 Release"
1732
+
1733
+ DEP_CPP_PTR_C=\
1734
+ ".\include\private\gcconfig.h"\
1735
+ ".\include\gc.h"\
1736
+ ".\include\private\gc_hdrs.h"\
1737
+ ".\include\private\gc_pmark.h"\
1738
+ ".\include\gc_mark.h"\
1739
+ ".\include\private\gc_priv.h"\
1740
+ {$(INCLUDE)}"\sys\TYPES.H"\
1741
+
1742
+ NODEP_CPP_PTR_C=\
1743
+ ".\th\PCR_Th.h"\
1744
+ ".\th\PCR_ThCrSec.h"\
1745
+ ".\th\PCR_ThCtl.h"\
1746
+
1747
+
1748
+ ".\Release\ptr_chck.obj" : $(SOURCE) $(DEP_CPP_PTR_C) "$(INTDIR)"
1749
+
1750
+ ".\Release\ptr_chck.sbr" : $(SOURCE) $(DEP_CPP_PTR_C) "$(INTDIR)"
1751
+
1752
+
1753
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1754
+
1755
+ DEP_CPP_PTR_C=\
1756
+ ".\include\private\gcconfig.h"\
1757
+ ".\include\gc.h"\
1758
+ ".\include\private\gc_hdrs.h"\
1759
+ ".\include\private\gc_pmark.h"\
1760
+ ".\include\gc_mark.h"\
1761
+ ".\include\private\gc_priv.h"\
1762
+ {$(INCLUDE)}"\sys\TYPES.H"\
1763
+
1764
+ NODEP_CPP_PTR_C=\
1765
+ ".\th\PCR_Th.h"\
1766
+ ".\th\PCR_ThCrSec.h"\
1767
+ ".\th\PCR_ThCtl.h"\
1768
+
1769
+
1770
+ ".\Debug\ptr_chck.obj" : $(SOURCE) $(DEP_CPP_PTR_C) "$(INTDIR)"
1771
+
1772
+ ".\Debug\ptr_chck.sbr" : $(SOURCE) $(DEP_CPP_PTR_C) "$(INTDIR)"
1773
+
1774
+
1775
+ !ENDIF
1776
+
1777
+ # End Source File
1778
+ ################################################################################
1779
+ # Begin Source File
1780
+
1781
+ SOURCE=.\dyn_load.c
1782
+
1783
+ !IF "$(CFG)" == "gc - Win32 Release"
1784
+
1785
+ DEP_CPP_DYN_L=\
1786
+ ".\include\private\gcconfig.h"\
1787
+ ".\include\gc.h"\
1788
+ ".\include\private\gc_hdrs.h"\
1789
+ ".\include\private\gc_priv.h"\
1790
+ {$(INCLUDE)}"\sys\STAT.H"\
1791
+ {$(INCLUDE)}"\sys\TYPES.H"\
1792
+
1793
+ NODEP_CPP_DYN_L=\
1794
+ ".\il\PCR_IL.h"\
1795
+ ".\mm\PCR_MM.h"\
1796
+ ".\th\PCR_Th.h"\
1797
+ ".\th\PCR_ThCrSec.h"\
1798
+ ".\th\PCR_ThCtl.h"\
1799
+
1800
+
1801
+ ".\Release\dyn_load.obj" : $(SOURCE) $(DEP_CPP_DYN_L) "$(INTDIR)"
1802
+
1803
+ ".\Release\dyn_load.sbr" : $(SOURCE) $(DEP_CPP_DYN_L) "$(INTDIR)"
1804
+
1805
+
1806
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1807
+
1808
+ DEP_CPP_DYN_L=\
1809
+ ".\include\private\gcconfig.h"\
1810
+ ".\include\gc.h"\
1811
+ ".\include\private\gc_hdrs.h"\
1812
+ ".\include\private\gc_priv.h"\
1813
+ {$(INCLUDE)}"\sys\STAT.H"\
1814
+ {$(INCLUDE)}"\sys\TYPES.H"\
1815
+
1816
+ NODEP_CPP_DYN_L=\
1817
+ ".\il\PCR_IL.h"\
1818
+ ".\mm\PCR_MM.h"\
1819
+ ".\th\PCR_Th.h"\
1820
+ ".\th\PCR_ThCrSec.h"\
1821
+ ".\th\PCR_ThCtl.h"\
1822
+
1823
+
1824
+ ".\Debug\dyn_load.obj" : $(SOURCE) $(DEP_CPP_DYN_L) "$(INTDIR)"
1825
+
1826
+ ".\Debug\dyn_load.sbr" : $(SOURCE) $(DEP_CPP_DYN_L) "$(INTDIR)"
1827
+
1828
+
1829
+ !ENDIF
1830
+
1831
+ # End Source File
1832
+ ################################################################################
1833
+ # Begin Source File
1834
+
1835
+ SOURCE=.\win32_threads.c
1836
+
1837
+ !IF "$(CFG)" == "gc - Win32 Release"
1838
+
1839
+ DEP_CPP_WIN32=\
1840
+ ".\include\private\gcconfig.h"\
1841
+ ".\include\gc.h"\
1842
+ ".\include\private\gc_hdrs.h"\
1843
+ ".\include\private\gc_priv.h"\
1844
+ {$(INCLUDE)}"\sys\TYPES.H"\
1845
+
1846
+ NODEP_CPP_WIN32=\
1847
+ ".\th\PCR_Th.h"\
1848
+ ".\th\PCR_ThCrSec.h"\
1849
+ ".\th\PCR_ThCtl.h"\
1850
+
1851
+
1852
+ ".\Release\win32_threads.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
1853
+
1854
+ ".\Release\win32_threads.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
1855
+
1856
+
1857
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1858
+
1859
+ DEP_CPP_WIN32=\
1860
+ ".\include\private\gcconfig.h"\
1861
+ ".\include\gc.h"\
1862
+ ".\include\private\gc_hdrs.h"\
1863
+ ".\include\private\gc_priv.h"\
1864
+ {$(INCLUDE)}"\sys\TYPES.H"\
1865
+
1866
+ NODEP_CPP_WIN32=\
1867
+ ".\th\PCR_Th.h"\
1868
+ ".\th\PCR_ThCrSec.h"\
1869
+ ".\th\PCR_ThCtl.h"\
1870
+
1871
+
1872
+ ".\Debug\win32_threads.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
1873
+
1874
+ ".\Debug\win32_threads.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
1875
+
1876
+
1877
+ !ENDIF
1878
+
1879
+ # End Source File
1880
+ ################################################################################
1881
+ # Begin Source File
1882
+
1883
+ SOURCE=.\msvc_dbg.c
1884
+
1885
+ !IF "$(CFG)" == "gc - Win32 Release"
1886
+
1887
+ DEP_CPP_WIN32=\
1888
+ ".\include\private\gcconfig.h"\
1889
+ ".\include\gc.h"\
1890
+ ".\include\private\gc_hdrs.h"\
1891
+ ".\include\private\gc_priv.h"\
1892
+ ".\include\private\msvc_dbg.h"\
1893
+ {$(INCLUDE)}"\sys\TYPES.H"\
1894
+
1895
+ NODEP_CPP_WIN32=\
1896
+ ".\th\PCR_Th.h"\
1897
+ ".\th\PCR_ThCrSec.h"\
1898
+ ".\th\PCR_ThCtl.h"\
1899
+
1900
+
1901
+ ".\Release\msvc_dbg.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
1902
+
1903
+ ".\Release\msvc_dbg.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
1904
+
1905
+
1906
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1907
+
1908
+ DEP_CPP_WIN32=\
1909
+ ".\include\private\gcconfig.h"\
1910
+ ".\include\gc.h"\
1911
+ ".\include\private\gc_hdrs.h"\
1912
+ ".\include\private\gc_priv.h"\
1913
+ ".\include\private\msvc_dbg.h"\
1914
+ {$(INCLUDE)}"\sys\TYPES.H"\
1915
+
1916
+ NODEP_CPP_WIN32=\
1917
+ ".\th\PCR_Th.h"\
1918
+ ".\th\PCR_ThCrSec.h"\
1919
+ ".\th\PCR_ThCtl.h"\
1920
+
1921
+
1922
+ ".\Debug\msvc_dbg.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
1923
+
1924
+ ".\Debug\msvc_dbg.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
1925
+
1926
+
1927
+ !ENDIF
1928
+
1929
+ # End Source File
1930
+ ################################################################################
1931
+ # Begin Source File
1932
+
1933
+ SOURCE=.\checksums.c
1934
+
1935
+ !IF "$(CFG)" == "gc - Win32 Release"
1936
+
1937
+ DEP_CPP_CHECK=\
1938
+ ".\include\private\gcconfig.h"\
1939
+ ".\include\gc.h"\
1940
+ ".\include\private\gc_hdrs.h"\
1941
+ ".\include\private\gc_priv.h"\
1942
+ {$(INCLUDE)}"\sys\TYPES.H"\
1943
+
1944
+ NODEP_CPP_CHECK=\
1945
+ ".\th\PCR_Th.h"\
1946
+ ".\th\PCR_ThCrSec.h"\
1947
+ ".\th\PCR_ThCtl.h"\
1948
+
1949
+
1950
+ ".\Release\checksums.obj" : $(SOURCE) $(DEP_CPP_CHECK) "$(INTDIR)"
1951
+
1952
+ ".\Release\checksums.sbr" : $(SOURCE) $(DEP_CPP_CHECK) "$(INTDIR)"
1953
+
1954
+
1955
+ !ELSEIF "$(CFG)" == "gc - Win32 Debug"
1956
+
1957
+ DEP_CPP_CHECK=\
1958
+ ".\include\private\gcconfig.h"\
1959
+ ".\include\gc.h"\
1960
+ ".\include\private\gc_hdrs.h"\
1961
+ ".\include\private\gc_priv.h"\
1962
+ {$(INCLUDE)}"\sys\TYPES.H"\
1963
+
1964
+ NODEP_CPP_CHECK=\
1965
+ ".\th\PCR_Th.h"\
1966
+ ".\th\PCR_ThCrSec.h"\
1967
+ ".\th\PCR_ThCtl.h"\
1968
+
1969
+
1970
+ ".\Debug\checksums.obj" : $(SOURCE) $(DEP_CPP_CHECK) "$(INTDIR)"
1971
+
1972
+ ".\Debug\checksums.sbr" : $(SOURCE) $(DEP_CPP_CHECK) "$(INTDIR)"
1973
+
1974
+
1975
+ !ENDIF
1976
+
1977
+ # End Source File
1978
+ # End Target
1979
+ ################################################################################
1980
+ # Begin Target
1981
+
1982
+ # Name "gctest - Win32 Release"
1983
+ # Name "gctest - Win32 Debug"
1984
+
1985
+ !IF "$(CFG)" == "gctest - Win32 Release"
1986
+
1987
+ !ELSEIF "$(CFG)" == "gctest - Win32 Debug"
1988
+
1989
+ !ENDIF
1990
+
1991
+ ################################################################################
1992
+ # Begin Project Dependency
1993
+
1994
+ # Project_Dep_Name "gc"
1995
+
1996
+ !IF "$(CFG)" == "gctest - Win32 Release"
1997
+
1998
+ "gc - Win32 Release" :
1999
+ $(MAKE) /$(MAKEFLAGS) /F ".\gc.mak" CFG="gc - Win32 Release"
2000
+
2001
+ !ELSEIF "$(CFG)" == "gctest - Win32 Debug"
2002
+
2003
+ "gc - Win32 Debug" :
2004
+ $(MAKE) /$(MAKEFLAGS) /F ".\gc.mak" CFG="gc - Win32 Debug"
2005
+
2006
+ !ENDIF
2007
+
2008
+ # End Project Dependency
2009
+ ################################################################################
2010
+ # Begin Source File
2011
+
2012
+ SOURCE=.\tests\test.c
2013
+ DEP_CPP_TEST_=\
2014
+ ".\include\private\gcconfig.h"\
2015
+ ".\include\gc.h"\
2016
+ ".\include\private\gc_hdrs.h"\
2017
+ ".\include\private\gc_priv.h"\
2018
+ ".\include\gc_typed.h"\
2019
+ {$(INCLUDE)}"\sys\TYPES.H"\
2020
+
2021
+ NODEP_CPP_TEST_=\
2022
+ ".\th\PCR_Th.h"\
2023
+ ".\th\PCR_ThCrSec.h"\
2024
+ ".\th\PCR_ThCtl.h"\
2025
+
2026
+
2027
+ !IF "$(CFG)" == "gctest - Win32 Release"
2028
+
2029
+
2030
+ ".\gctest\Release\test.obj" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)"
2031
+
2032
+
2033
+ !ELSEIF "$(CFG)" == "gctest - Win32 Debug"
2034
+
2035
+
2036
+ ".\gctest\Debug\test.obj" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)"
2037
+
2038
+ ".\gctest\Debug\test.sbr" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)"
2039
+
2040
+
2041
+ !ENDIF
2042
+
2043
+ # End Source File
2044
+ # End Target
2045
+ ################################################################################
2046
+ # Begin Target
2047
+
2048
+ # Name "cord - Win32 Release"
2049
+ # Name "cord - Win32 Debug"
2050
+
2051
+ !IF "$(CFG)" == "cord - Win32 Release"
2052
+
2053
+ !ELSEIF "$(CFG)" == "cord - Win32 Debug"
2054
+
2055
+ !ENDIF
2056
+
2057
+ ################################################################################
2058
+ # Begin Project Dependency
2059
+
2060
+ # Project_Dep_Name "gc"
2061
+
2062
+ !IF "$(CFG)" == "cord - Win32 Release"
2063
+
2064
+ "gc - Win32 Release" :
2065
+ $(MAKE) /$(MAKEFLAGS) /F ".\gc.mak" CFG="gc - Win32 Release"
2066
+
2067
+ !ELSEIF "$(CFG)" == "cord - Win32 Debug"
2068
+
2069
+ "gc - Win32 Debug" :
2070
+ $(MAKE) /$(MAKEFLAGS) /F ".\gc.mak" CFG="gc - Win32 Debug"
2071
+
2072
+ !ENDIF
2073
+
2074
+ # End Project Dependency
2075
+ ################################################################################
2076
+ # Begin Source File
2077
+
2078
+ SOURCE=.\cord\de_win.c
2079
+ DEP_CPP_DE_WI=\
2080
+ ".\include\cord.h"\
2081
+ ".\cord\de_cmds.h"\
2082
+ ".\cord\de_win.h"\
2083
+ ".\include\private\cord_pos.h"\
2084
+
2085
+ NODEP_CPP_DE_WI=\
2086
+ ".\include\gc.h"\
2087
+
2088
+
2089
+ !IF "$(CFG)" == "cord - Win32 Release"
2090
+
2091
+
2092
+ ".\cord\Release\de_win.obj" : $(SOURCE) $(DEP_CPP_DE_WI) "$(INTDIR)"
2093
+ $(CPP) $(CPP_PROJ) $(SOURCE)
2094
+
2095
+
2096
+ !ELSEIF "$(CFG)" == "cord - Win32 Debug"
2097
+
2098
+
2099
+ ".\cord\Debug\de_win.obj" : $(SOURCE) $(DEP_CPP_DE_WI) "$(INTDIR)"
2100
+ $(CPP) $(CPP_PROJ) $(SOURCE)
2101
+
2102
+
2103
+ !ENDIF
2104
+
2105
+ # End Source File
2106
+ ################################################################################
2107
+ # Begin Source File
2108
+
2109
+ SOURCE=.\cord\de.c
2110
+ DEP_CPP_DE_C2e=\
2111
+ ".\include\cord.h"\
2112
+ ".\cord\de_cmds.h"\
2113
+ ".\cord\de_win.h"\
2114
+ ".\include\private\cord_pos.h"\
2115
+
2116
+ NODEP_CPP_DE_C2e=\
2117
+ ".\include\gc.h"\
2118
+
2119
+
2120
+ !IF "$(CFG)" == "cord - Win32 Release"
2121
+
2122
+
2123
+ ".\cord\Release\de.obj" : $(SOURCE) $(DEP_CPP_DE_C2e) "$(INTDIR)"
2124
+ $(CPP) $(CPP_PROJ) $(SOURCE)
2125
+
2126
+
2127
+ !ELSEIF "$(CFG)" == "cord - Win32 Debug"
2128
+
2129
+
2130
+ ".\cord\Debug\de.obj" : $(SOURCE) $(DEP_CPP_DE_C2e) "$(INTDIR)"
2131
+ $(CPP) $(CPP_PROJ) $(SOURCE)
2132
+
2133
+
2134
+ !ENDIF
2135
+
2136
+ # End Source File
2137
+ ################################################################################
2138
+ # Begin Source File
2139
+
2140
+ SOURCE=.\cord\cordxtra.c
2141
+ DEP_CPP_CORDX=\
2142
+ ".\include\cord.h"\
2143
+ ".\include\ec.h"\
2144
+ ".\include\private\cord_pos.h"\
2145
+
2146
+ NODEP_CPP_CORDX=\
2147
+ ".\include\gc.h"\
2148
+
2149
+
2150
+ !IF "$(CFG)" == "cord - Win32 Release"
2151
+
2152
+
2153
+ ".\cord\Release\cordxtra.obj" : $(SOURCE) $(DEP_CPP_CORDX) "$(INTDIR)"
2154
+ $(CPP) $(CPP_PROJ) $(SOURCE)
2155
+
2156
+
2157
+ !ELSEIF "$(CFG)" == "cord - Win32 Debug"
2158
+
2159
+
2160
+ ".\cord\Debug\cordxtra.obj" : $(SOURCE) $(DEP_CPP_CORDX) "$(INTDIR)"
2161
+ $(CPP) $(CPP_PROJ) $(SOURCE)
2162
+
2163
+
2164
+ !ENDIF
2165
+
2166
+ # End Source File
2167
+ ################################################################################
2168
+ # Begin Source File
2169
+
2170
+ SOURCE=.\cord\cordbscs.c
2171
+ DEP_CPP_CORDB=\
2172
+ ".\include\cord.h"\
2173
+ ".\include\private\cord_pos.h"\
2174
+
2175
+ NODEP_CPP_CORDB=\
2176
+ ".\include\gc.h"\
2177
+
2178
+
2179
+ !IF "$(CFG)" == "cord - Win32 Release"
2180
+
2181
+
2182
+ ".\cord\Release\cordbscs.obj" : $(SOURCE) $(DEP_CPP_CORDB) "$(INTDIR)"
2183
+ $(CPP) $(CPP_PROJ) $(SOURCE)
2184
+
2185
+
2186
+ !ELSEIF "$(CFG)" == "cord - Win32 Debug"
2187
+
2188
+
2189
+ ".\cord\Debug\cordbscs.obj" : $(SOURCE) $(DEP_CPP_CORDB) "$(INTDIR)"
2190
+ $(CPP) $(CPP_PROJ) $(SOURCE)
2191
+
2192
+
2193
+ !ENDIF
2194
+
2195
+ # End Source File
2196
+ ################################################################################
2197
+ # Begin Source File
2198
+
2199
+ SOURCE=.\cord\de_win.RC
2200
+
2201
+ !IF "$(CFG)" == "cord - Win32 Release"
2202
+
2203
+
2204
+ ".\cord\Release\de_win.res" : $(SOURCE) "$(INTDIR)"
2205
+ $(RSC) /l 0x809 /fo"$(INTDIR)/de_win.res" /i "cord" /d "NDEBUG" $(SOURCE)
2206
+
2207
+
2208
+ !ELSEIF "$(CFG)" == "cord - Win32 Debug"
2209
+
2210
+
2211
+ ".\cord\Debug\de_win.res" : $(SOURCE) "$(INTDIR)"
2212
+ $(RSC) /l 0x809 /fo"$(INTDIR)/de_win.res" /i "cord" /d "_DEBUG" $(SOURCE)
2213
+
2214
+
2215
+ !ENDIF
2216
+
2217
+ # End Source File
2218
+ # End Target
2219
+ # End Project
2220
+ ################################################################################
mosesdecoder/jam-files/engine/boehm_gc/gc_cpp.cpp ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ // Visual C++ seems to prefer a .cpp extension to .cc
2
+ #include "gc_cpp.cc"
mosesdecoder/jam-files/engine/boehm_gc/hpux_test_and_clear.s ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .SPACE $PRIVATE$
2
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
3
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
4
+ .SPACE $TEXT$
5
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
6
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
7
+ .IMPORT $global$,DATA
8
+ .IMPORT $$dyncall,MILLICODE
9
+ .SPACE $TEXT$
10
+ .SUBSPA $CODE$
11
+
12
+ .align 4
13
+ .EXPORT GC_test_and_clear,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
14
+ GC_test_and_clear
15
+ .PROC
16
+ .CALLINFO FRAME=0,NO_CALLS
17
+ .ENTRY
18
+ ldcw,co (%r26),%r28
19
+ bv,n 0(%r2)
20
+ .EXIT
21
+ .PROCEND
mosesdecoder/jam-files/engine/boehm_gc/mips_ultrix_mach_dep.s ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # define call_push(x) move $4,x; jal GC_push_one
2
+
3
+ .text
4
+ # Mark from machine registers that are saved by C compiler
5
+ .globl GC_push_regs
6
+ .ent GC_push_regs
7
+ GC_push_regs:
8
+ subu $sp,8 ## Need to save only return address
9
+ sw $31,4($sp)
10
+ .mask 0x80000000,-4
11
+ .frame $sp,8,$31
12
+ call_push($2)
13
+ call_push($3)
14
+ call_push($16)
15
+ call_push($17)
16
+ call_push($18)
17
+ call_push($19)
18
+ call_push($20)
19
+ call_push($21)
20
+ call_push($22)
21
+ call_push($23)
22
+ call_push($30)
23
+ lw $31,4($sp)
24
+ addu $sp,8
25
+ j $31
26
+ .end GC_push_regs
mosesdecoder/jam-files/engine/boehm_gc/misc.c ADDED
@@ -0,0 +1,1177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
3
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
4
+ * Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved.
5
+ *
6
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
7
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
8
+ *
9
+ * Permission is hereby granted to use or copy this program
10
+ * for any purpose, provided the above notices are retained on all copies.
11
+ * Permission to modify the code and to distribute modified code is granted,
12
+ * provided the above notices are retained, and a notice that the code was
13
+ * modified is included with the above copyright notice.
14
+ */
15
+ /* Boehm, July 31, 1995 5:02 pm PDT */
16
+
17
+
18
+ #include <stdio.h>
19
+ #include <limits.h>
20
+ #include <stdarg.h>
21
+ #ifndef _WIN32_WCE
22
+ #include <signal.h>
23
+ #endif
24
+
25
+ #define I_HIDE_POINTERS /* To make GC_call_with_alloc_lock visible */
26
+ #include "private/gc_pmark.h"
27
+
28
+ #ifdef GC_SOLARIS_THREADS
29
+ # include <sys/syscall.h>
30
+ #endif
31
+ #if defined(MSWIN32) || defined(MSWINCE)
32
+ # define WIN32_LEAN_AND_MEAN
33
+ # define NOSERVICE
34
+ # include <windows.h>
35
+ # include <tchar.h>
36
+ #endif
37
+
38
+ #ifdef UNIX_LIKE
39
+ # include <fcntl.h>
40
+ # include <sys/types.h>
41
+ # include <sys/stat.h>
42
+
43
+ int GC_log; /* Forward decl, so we can set it. */
44
+ #endif
45
+
46
+ #ifdef NONSTOP
47
+ # include <floss.h>
48
+ #endif
49
+
50
+ #if defined(THREADS) && defined(PCR)
51
+ # include "il/PCR_IL.h"
52
+ PCR_Th_ML GC_allocate_ml;
53
+ #endif
54
+ /* For other platforms with threads, the lock and possibly */
55
+ /* GC_lock_holder variables are defined in the thread support code. */
56
+
57
+ #if defined(NOSYS) || defined(ECOS)
58
+ #undef STACKBASE
59
+ #endif
60
+
61
+ /* Dont unnecessarily call GC_register_main_static_data() in case */
62
+ /* dyn_load.c isn't linked in. */
63
+ #ifdef DYNAMIC_LOADING
64
+ # define GC_REGISTER_MAIN_STATIC_DATA() GC_register_main_static_data()
65
+ #else
66
+ # define GC_REGISTER_MAIN_STATIC_DATA() TRUE
67
+ #endif
68
+
69
+ GC_FAR struct _GC_arrays GC_arrays /* = { 0 } */;
70
+
71
+
72
+ GC_bool GC_debugging_started = FALSE;
73
+ /* defined here so we don't have to load debug_malloc.o */
74
+
75
+ void (*GC_check_heap) (void) = (void (*) (void))0;
76
+ void (*GC_print_all_smashed) (void) = (void (*) (void))0;
77
+
78
+ void (*GC_start_call_back) (void) = (void (*) (void))0;
79
+
80
+ ptr_t GC_stackbottom = 0;
81
+
82
+ #ifdef IA64
83
+ ptr_t GC_register_stackbottom = 0;
84
+ #endif
85
+
86
+ GC_bool GC_dont_gc = 0;
87
+
88
+ GC_bool GC_dont_precollect = 0;
89
+
90
+ GC_bool GC_quiet = 0;
91
+
92
+ #ifndef SMALL_CONFIG
93
+ GC_bool GC_print_stats = 0;
94
+ #endif
95
+
96
+ GC_bool GC_print_back_height = 0;
97
+
98
+ #ifndef NO_DEBUGGING
99
+ GC_bool GC_dump_regularly = 0; /* Generate regular debugging dumps. */
100
+ #endif
101
+
102
+ #ifdef KEEP_BACK_PTRS
103
+ long GC_backtraces = 0; /* Number of random backtraces to */
104
+ /* generate for each GC. */
105
+ #endif
106
+
107
+ #ifdef FIND_LEAK
108
+ int GC_find_leak = 1;
109
+ #else
110
+ int GC_find_leak = 0;
111
+ #endif
112
+
113
+ #ifdef ALL_INTERIOR_POINTERS
114
+ int GC_all_interior_pointers = 1;
115
+ #else
116
+ int GC_all_interior_pointers = 0;
117
+ #endif
118
+
119
+ long GC_large_alloc_warn_interval = 5;
120
+ /* Interval between unsuppressed warnings. */
121
+
122
+ long GC_large_alloc_warn_suppressed = 0;
123
+ /* Number of warnings suppressed so far. */
124
+
125
+ /*ARGSUSED*/
126
+ void * GC_default_oom_fn(size_t bytes_requested)
127
+ {
128
+ return(0);
129
+ }
130
+
131
+ void * (*GC_oom_fn) (size_t bytes_requested) = GC_default_oom_fn;
132
+
133
+ void * GC_project2(void *arg1, void *arg2)
134
+ {
135
+ return arg2;
136
+ }
137
+
138
+ /* Set things up so that GC_size_map[i] >= granules(i), */
139
+ /* but not too much bigger */
140
+ /* and so that size_map contains relatively few distinct entries */
141
+ /* This was originally stolen from Russ Atkinson's Cedar */
142
+ /* quantization alogrithm (but we precompute it). */
143
+ void GC_init_size_map(void)
144
+ {
145
+ int i;
146
+
147
+ /* Map size 0 to something bigger. */
148
+ /* This avoids problems at lower levels. */
149
+ GC_size_map[0] = 1;
150
+ for (i = 1; i <= GRANULES_TO_BYTES(TINY_FREELISTS-1) - EXTRA_BYTES; i++) {
151
+ GC_size_map[i] = ROUNDED_UP_GRANULES(i);
152
+ GC_ASSERT(GC_size_map[i] < TINY_FREELISTS);
153
+ }
154
+ /* We leave the rest of the array to be filled in on demand. */
155
+ }
156
+
157
+ /* Fill in additional entries in GC_size_map, including the ith one */
158
+ /* We assume the ith entry is currently 0. */
159
+ /* Note that a filled in section of the array ending at n always */
160
+ /* has length at least n/4. */
161
+ void GC_extend_size_map(size_t i)
162
+ {
163
+ size_t orig_granule_sz = ROUNDED_UP_GRANULES(i);
164
+ size_t granule_sz = orig_granule_sz;
165
+ size_t byte_sz = GRANULES_TO_BYTES(granule_sz);
166
+ /* The size we try to preserve. */
167
+ /* Close to i, unless this would */
168
+ /* introduce too many distinct sizes. */
169
+ size_t smaller_than_i = byte_sz - (byte_sz >> 3);
170
+ size_t much_smaller_than_i = byte_sz - (byte_sz >> 2);
171
+ size_t low_limit; /* The lowest indexed entry we */
172
+ /* initialize. */
173
+ size_t j;
174
+
175
+ if (GC_size_map[smaller_than_i] == 0) {
176
+ low_limit = much_smaller_than_i;
177
+ while (GC_size_map[low_limit] != 0) low_limit++;
178
+ } else {
179
+ low_limit = smaller_than_i + 1;
180
+ while (GC_size_map[low_limit] != 0) low_limit++;
181
+ granule_sz = ROUNDED_UP_GRANULES(low_limit);
182
+ granule_sz += granule_sz >> 3;
183
+ if (granule_sz < orig_granule_sz) granule_sz = orig_granule_sz;
184
+ }
185
+ /* For these larger sizes, we use an even number of granules. */
186
+ /* This makes it easier to, for example, construct a 16byte-aligned */
187
+ /* allocator even if GRANULE_BYTES is 8. */
188
+ granule_sz += 1;
189
+ granule_sz &= ~1;
190
+ if (granule_sz > MAXOBJGRANULES) {
191
+ granule_sz = MAXOBJGRANULES;
192
+ }
193
+ /* If we can fit the same number of larger objects in a block, */
194
+ /* do so. */
195
+ {
196
+ size_t number_of_objs = HBLK_GRANULES/granule_sz;
197
+ granule_sz = HBLK_GRANULES/number_of_objs;
198
+ granule_sz &= ~1;
199
+ }
200
+ byte_sz = GRANULES_TO_BYTES(granule_sz);
201
+ /* We may need one extra byte; */
202
+ /* don't always fill in GC_size_map[byte_sz] */
203
+ byte_sz -= EXTRA_BYTES;
204
+
205
+ for (j = low_limit; j <= byte_sz; j++) GC_size_map[j] = granule_sz;
206
+ }
207
+
208
+
209
+ /*
210
+ * The following is a gross hack to deal with a problem that can occur
211
+ * on machines that are sloppy about stack frame sizes, notably SPARC.
212
+ * Bogus pointers may be written to the stack and not cleared for
213
+ * a LONG time, because they always fall into holes in stack frames
214
+ * that are not written. We partially address this by clearing
215
+ * sections of the stack whenever we get control.
216
+ */
217
+ word GC_stack_last_cleared = 0; /* GC_no when we last did this */
218
+ # ifdef THREADS
219
+ # define BIG_CLEAR_SIZE 2048 /* Clear this much now and then. */
220
+ # define SMALL_CLEAR_SIZE 256 /* Clear this much every time. */
221
+ # endif
222
+ # define CLEAR_SIZE 213 /* Granularity for GC_clear_stack_inner */
223
+ # define DEGRADE_RATE 50
224
+
225
+ ptr_t GC_min_sp; /* Coolest stack pointer value from which we've */
226
+ /* already cleared the stack. */
227
+
228
+ ptr_t GC_high_water;
229
+ /* "hottest" stack pointer value we have seen */
230
+ /* recently. Degrades over time. */
231
+
232
+ word GC_bytes_allocd_at_reset;
233
+
234
+ #if defined(ASM_CLEAR_CODE)
235
+ extern void *GC_clear_stack_inner(void *, ptr_t);
236
+ #else
237
+ /* Clear the stack up to about limit. Return arg. */
238
+ /*ARGSUSED*/
239
+ void * GC_clear_stack_inner(void *arg, ptr_t limit)
240
+ {
241
+ word dummy[CLEAR_SIZE];
242
+
243
+ BZERO(dummy, CLEAR_SIZE*sizeof(word));
244
+ if ((ptr_t)(dummy) COOLER_THAN limit) {
245
+ (void) GC_clear_stack_inner(arg, limit);
246
+ }
247
+ /* Make sure the recursive call is not a tail call, and the bzero */
248
+ /* call is not recognized as dead code. */
249
+ GC_noop1((word)dummy);
250
+ return(arg);
251
+ }
252
+ #endif
253
+
254
+ /* Clear some of the inaccessible part of the stack. Returns its */
255
+ /* argument, so it can be used in a tail call position, hence clearing */
256
+ /* another frame. */
257
+ void * GC_clear_stack(void *arg)
258
+ {
259
+ ptr_t sp = GC_approx_sp(); /* Hotter than actual sp */
260
+ # ifdef THREADS
261
+ word dummy[SMALL_CLEAR_SIZE];
262
+ static unsigned random_no = 0;
263
+ /* Should be more random than it is ... */
264
+ /* Used to occasionally clear a bigger */
265
+ /* chunk. */
266
+ # endif
267
+ ptr_t limit;
268
+
269
+ # define SLOP 400
270
+ /* Extra bytes we clear every time. This clears our own */
271
+ /* activation record, and should cause more frequent */
272
+ /* clearing near the cold end of the stack, a good thing. */
273
+ # define GC_SLOP 4000
274
+ /* We make GC_high_water this much hotter than we really saw */
275
+ /* saw it, to cover for GC noise etc. above our current frame. */
276
+ # define CLEAR_THRESHOLD 100000
277
+ /* We restart the clearing process after this many bytes of */
278
+ /* allocation. Otherwise very heavily recursive programs */
279
+ /* with sparse stacks may result in heaps that grow almost */
280
+ /* without bounds. As the heap gets larger, collection */
281
+ /* frequency decreases, thus clearing frequency would decrease, */
282
+ /* thus more junk remains accessible, thus the heap gets */
283
+ /* larger ... */
284
+ # ifdef THREADS
285
+ if (++random_no % 13 == 0) {
286
+ limit = sp;
287
+ MAKE_HOTTER(limit, BIG_CLEAR_SIZE*sizeof(word));
288
+ limit = (ptr_t)((word)limit & ~0xf);
289
+ /* Make it sufficiently aligned for assembly */
290
+ /* implementations of GC_clear_stack_inner. */
291
+ return GC_clear_stack_inner(arg, limit);
292
+ } else {
293
+ BZERO(dummy, SMALL_CLEAR_SIZE*sizeof(word));
294
+ return arg;
295
+ }
296
+ # else
297
+ if (GC_gc_no > GC_stack_last_cleared) {
298
+ /* Start things over, so we clear the entire stack again */
299
+ if (GC_stack_last_cleared == 0) GC_high_water = (ptr_t)GC_stackbottom;
300
+ GC_min_sp = GC_high_water;
301
+ GC_stack_last_cleared = GC_gc_no;
302
+ GC_bytes_allocd_at_reset = GC_bytes_allocd;
303
+ }
304
+ /* Adjust GC_high_water */
305
+ MAKE_COOLER(GC_high_water, WORDS_TO_BYTES(DEGRADE_RATE) + GC_SLOP);
306
+ if (sp HOTTER_THAN GC_high_water) {
307
+ GC_high_water = sp;
308
+ }
309
+ MAKE_HOTTER(GC_high_water, GC_SLOP);
310
+ limit = GC_min_sp;
311
+ MAKE_HOTTER(limit, SLOP);
312
+ if (sp COOLER_THAN limit) {
313
+ limit = (ptr_t)((word)limit & ~0xf);
314
+ /* Make it sufficiently aligned for assembly */
315
+ /* implementations of GC_clear_stack_inner. */
316
+ GC_min_sp = sp;
317
+ return(GC_clear_stack_inner(arg, limit));
318
+ } else if (GC_bytes_allocd - GC_bytes_allocd_at_reset > CLEAR_THRESHOLD) {
319
+ /* Restart clearing process, but limit how much clearing we do. */
320
+ GC_min_sp = sp;
321
+ MAKE_HOTTER(GC_min_sp, CLEAR_THRESHOLD/4);
322
+ if (GC_min_sp HOTTER_THAN GC_high_water) GC_min_sp = GC_high_water;
323
+ GC_bytes_allocd_at_reset = GC_bytes_allocd;
324
+ }
325
+ return(arg);
326
+ # endif
327
+ }
328
+
329
+
330
+ /* Return a pointer to the base address of p, given a pointer to a */
331
+ /* an address within an object. Return 0 o.w. */
332
+ void * GC_base(void * p)
333
+ {
334
+ ptr_t r;
335
+ struct hblk *h;
336
+ bottom_index *bi;
337
+ hdr *candidate_hdr;
338
+ ptr_t limit;
339
+
340
+ r = p;
341
+ if (!GC_is_initialized) return 0;
342
+ h = HBLKPTR(r);
343
+ GET_BI(r, bi);
344
+ candidate_hdr = HDR_FROM_BI(bi, r);
345
+ if (candidate_hdr == 0) return(0);
346
+ /* If it's a pointer to the middle of a large object, move it */
347
+ /* to the beginning. */
348
+ while (IS_FORWARDING_ADDR_OR_NIL(candidate_hdr)) {
349
+ h = FORWARDED_ADDR(h,candidate_hdr);
350
+ r = (ptr_t)h;
351
+ candidate_hdr = HDR(h);
352
+ }
353
+ if (HBLK_IS_FREE(candidate_hdr)) return(0);
354
+ /* Make sure r points to the beginning of the object */
355
+ r = (ptr_t)((word)r & ~(WORDS_TO_BYTES(1) - 1));
356
+ {
357
+ size_t offset = HBLKDISPL(r);
358
+ signed_word sz = candidate_hdr -> hb_sz;
359
+ size_t obj_displ = offset % sz;
360
+
361
+ r -= obj_displ;
362
+ limit = r + sz;
363
+ if (limit > (ptr_t)(h + 1) && sz <= HBLKSIZE) {
364
+ return(0);
365
+ }
366
+ if ((ptr_t)p >= limit) return(0);
367
+ }
368
+ return((void *)r);
369
+ }
370
+
371
+
372
+ /* Return the size of an object, given a pointer to its base. */
373
+ /* (For small obects this also happens to work from interior pointers, */
374
+ /* but that shouldn't be relied upon.) */
375
+ size_t GC_size(void * p)
376
+ {
377
+ hdr * hhdr = HDR(p);
378
+
379
+ return hhdr -> hb_sz;
380
+ }
381
+
382
+ size_t GC_get_heap_size(void)
383
+ {
384
+ return GC_heapsize;
385
+ }
386
+
387
+ size_t GC_get_free_bytes(void)
388
+ {
389
+ return GC_large_free_bytes;
390
+ }
391
+
392
+ size_t GC_get_bytes_since_gc(void)
393
+ {
394
+ return GC_bytes_allocd;
395
+ }
396
+
397
+ size_t GC_get_total_bytes(void)
398
+ {
399
+ return GC_bytes_allocd+GC_bytes_allocd_before_gc;
400
+ }
401
+
402
+ GC_bool GC_is_initialized = FALSE;
403
+
404
+ # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
405
+ extern void GC_init_parallel(void);
406
+ # endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
407
+
408
+ void GC_init(void)
409
+ {
410
+ DCL_LOCK_STATE;
411
+
412
+ #if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
413
+ if (!GC_is_initialized) {
414
+ BOOL (WINAPI *pfn) (LPCRITICAL_SECTION, DWORD) = NULL;
415
+ HMODULE hK32 = GetModuleHandleA("kernel32.dll");
416
+ if (hK32)
417
+ pfn = (BOOL (WINAPI *) (LPCRITICAL_SECTION, DWORD))
418
+ GetProcAddress (hK32,
419
+ "InitializeCriticalSectionAndSpinCount");
420
+ if (pfn)
421
+ pfn(&GC_allocate_ml, 4000);
422
+ else
423
+ InitializeCriticalSection (&GC_allocate_ml);
424
+ }
425
+ #endif /* MSWIN32 */
426
+
427
+ LOCK();
428
+ GC_init_inner();
429
+ UNLOCK();
430
+
431
+ # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
432
+ /* Make sure marker threads and started and thread local */
433
+ /* allocation is initialized, in case we didn't get */
434
+ /* called from GC_init_parallel(); */
435
+ {
436
+ GC_init_parallel();
437
+ }
438
+ # endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
439
+
440
+ # if defined(DYNAMIC_LOADING) && defined(DARWIN)
441
+ {
442
+ /* This must be called WITHOUT the allocation lock held
443
+ and before any threads are created */
444
+ extern void GC_init_dyld();
445
+ GC_init_dyld();
446
+ }
447
+ # endif
448
+ }
449
+
450
+ #if defined(MSWIN32) || defined(MSWINCE)
451
+ CRITICAL_SECTION GC_write_cs;
452
+ #endif
453
+
454
+ #ifdef MSWIN32
455
+ extern void GC_init_win32(void);
456
+ #endif
457
+
458
+ extern void GC_setpagesize();
459
+
460
+
461
+ #ifdef MSWIN32
462
+ extern GC_bool GC_no_win32_dlls;
463
+ #else
464
+ # define GC_no_win32_dlls FALSE
465
+ #endif
466
+
467
+ void GC_exit_check(void)
468
+ {
469
+ GC_gcollect();
470
+ }
471
+
472
+ #ifdef SEARCH_FOR_DATA_START
473
+ extern void GC_init_linux_data_start(void);
474
+ #endif
475
+
476
+ #ifdef UNIX_LIKE
477
+
478
+ extern void GC_set_and_save_fault_handler(void (*handler)(int));
479
+
480
+ static void looping_handler(sig)
481
+ int sig;
482
+ {
483
+ GC_err_printf("Caught signal %d: looping in handler\n", sig);
484
+ for(;;);
485
+ }
486
+
487
+ static GC_bool installed_looping_handler = FALSE;
488
+
489
+ static void maybe_install_looping_handler()
490
+ {
491
+ /* Install looping handler before the write fault handler, so we */
492
+ /* handle write faults correctly. */
493
+ if (!installed_looping_handler && 0 != GETENV("GC_LOOP_ON_ABORT")) {
494
+ GC_set_and_save_fault_handler(looping_handler);
495
+ installed_looping_handler = TRUE;
496
+ }
497
+ }
498
+
499
+ #else /* !UNIX_LIKE */
500
+
501
+ # define maybe_install_looping_handler()
502
+
503
+ #endif
504
+
505
+ void GC_init_inner()
506
+ {
507
+ # if !defined(THREADS) && defined(GC_ASSERTIONS)
508
+ word dummy;
509
+ # endif
510
+ word initial_heap_sz = (word)MINHINCR;
511
+
512
+ if (GC_is_initialized) return;
513
+ # if defined(MSWIN32) || defined(MSWINCE)
514
+ InitializeCriticalSection(&GC_write_cs);
515
+ # endif
516
+ # if (!defined(SMALL_CONFIG))
517
+ if (0 != GETENV("GC_PRINT_STATS")) {
518
+ GC_print_stats = 1;
519
+ }
520
+ if (0 != GETENV("GC_PRINT_VERBOSE_STATS")) {
521
+ GC_print_stats = VERBOSE;
522
+ }
523
+ # if defined(UNIX_LIKE)
524
+ {
525
+ char * file_name = GETENV("GC_LOG_FILE");
526
+ if (0 != file_name) {
527
+ int log_d = open(file_name, O_CREAT|O_WRONLY|O_APPEND, 0666);
528
+ if (log_d < 0) {
529
+ GC_log_printf("Failed to open %s as log file\n", file_name);
530
+ } else {
531
+ GC_log = log_d;
532
+ }
533
+ }
534
+ }
535
+ # endif
536
+ # endif
537
+ # ifndef NO_DEBUGGING
538
+ if (0 != GETENV("GC_DUMP_REGULARLY")) {
539
+ GC_dump_regularly = 1;
540
+ }
541
+ # endif
542
+ # ifdef KEEP_BACK_PTRS
543
+ {
544
+ char * backtraces_string = GETENV("GC_BACKTRACES");
545
+ if (0 != backtraces_string) {
546
+ GC_backtraces = atol(backtraces_string);
547
+ if (backtraces_string[0] == '\0') GC_backtraces = 1;
548
+ }
549
+ }
550
+ # endif
551
+ if (0 != GETENV("GC_FIND_LEAK")) {
552
+ GC_find_leak = 1;
553
+ atexit(GC_exit_check);
554
+ }
555
+ if (0 != GETENV("GC_ALL_INTERIOR_POINTERS")) {
556
+ GC_all_interior_pointers = 1;
557
+ }
558
+ if (0 != GETENV("GC_DONT_GC")) {
559
+ GC_dont_gc = 1;
560
+ }
561
+ if (0 != GETENV("GC_PRINT_BACK_HEIGHT")) {
562
+ GC_print_back_height = 1;
563
+ }
564
+ if (0 != GETENV("GC_NO_BLACKLIST_WARNING")) {
565
+ GC_large_alloc_warn_interval = LONG_MAX;
566
+ }
567
+ {
568
+ char * addr_string = GETENV("GC_TRACE");
569
+ if (0 != addr_string) {
570
+ # ifndef ENABLE_TRACE
571
+ WARN("Tracing not enabled: Ignoring GC_TRACE value\n", 0);
572
+ # else
573
+ # ifdef STRTOULL
574
+ long long addr = strtoull(addr_string, NULL, 16);
575
+ # else
576
+ long addr = strtoul(addr_string, NULL, 16);
577
+ # endif
578
+ if (addr < 0x1000)
579
+ WARN("Unlikely trace address: 0x%lx\n", (GC_word)addr);
580
+ GC_trace_addr = (ptr_t)addr;
581
+ # endif
582
+ }
583
+ }
584
+ {
585
+ char * time_limit_string = GETENV("GC_PAUSE_TIME_TARGET");
586
+ if (0 != time_limit_string) {
587
+ long time_limit = atol(time_limit_string);
588
+ if (time_limit < 5) {
589
+ WARN("GC_PAUSE_TIME_TARGET environment variable value too small "
590
+ "or bad syntax: Ignoring\n", 0);
591
+ } else {
592
+ GC_time_limit = time_limit;
593
+ }
594
+ }
595
+ }
596
+ {
597
+ char * interval_string = GETENV("GC_LARGE_ALLOC_WARN_INTERVAL");
598
+ if (0 != interval_string) {
599
+ long interval = atol(interval_string);
600
+ if (interval <= 0) {
601
+ WARN("GC_LARGE_ALLOC_WARN_INTERVAL environment variable has "
602
+ "bad value: Ignoring\n", 0);
603
+ } else {
604
+ GC_large_alloc_warn_interval = interval;
605
+ }
606
+ }
607
+ }
608
+ maybe_install_looping_handler();
609
+ /* Adjust normal object descriptor for extra allocation. */
610
+ if (ALIGNMENT > GC_DS_TAGS && EXTRA_BYTES != 0) {
611
+ GC_obj_kinds[NORMAL].ok_descriptor = ((word)(-ALIGNMENT) | GC_DS_LENGTH);
612
+ }
613
+ GC_setpagesize();
614
+ GC_exclude_static_roots(beginGC_arrays, endGC_arrays);
615
+ GC_exclude_static_roots(beginGC_obj_kinds, endGC_obj_kinds);
616
+ # ifdef SEPARATE_GLOBALS
617
+ GC_exclude_static_roots(beginGC_objfreelist, endGC_objfreelist);
618
+ GC_exclude_static_roots(beginGC_aobjfreelist, endGC_aobjfreelist);
619
+ # endif
620
+ # ifdef MSWIN32
621
+ GC_init_win32();
622
+ # endif
623
+ # if defined(USE_PROC_FOR_LIBRARIES) && defined(GC_LINUX_THREADS)
624
+ WARN("USE_PROC_FOR_LIBRARIES + GC_LINUX_THREADS performs poorly.\n", 0);
625
+ /* If thread stacks are cached, they tend to be scanned in */
626
+ /* entirety as part of the root set. This wil grow them to */
627
+ /* maximum size, and is generally not desirable. */
628
+ # endif
629
+ # if defined(SEARCH_FOR_DATA_START)
630
+ GC_init_linux_data_start();
631
+ # endif
632
+ # if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__)
633
+ GC_init_netbsd_elf();
634
+ # endif
635
+ # if !defined(THREADS) || defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) \
636
+ || defined(GC_SOLARIS_THREADS)
637
+ if (GC_stackbottom == 0) {
638
+ GC_stackbottom = GC_get_main_stack_base();
639
+ # if (defined(LINUX) || defined(HPUX)) && defined(IA64)
640
+ GC_register_stackbottom = GC_get_register_stack_base();
641
+ # endif
642
+ } else {
643
+ # if (defined(LINUX) || defined(HPUX)) && defined(IA64)
644
+ if (GC_register_stackbottom == 0) {
645
+ WARN("GC_register_stackbottom should be set with GC_stackbottom\n", 0);
646
+ /* The following may fail, since we may rely on */
647
+ /* alignment properties that may not hold with a user set */
648
+ /* GC_stackbottom. */
649
+ GC_register_stackbottom = GC_get_register_stack_base();
650
+ }
651
+ # endif
652
+ }
653
+ # endif
654
+ /* Ignore gcc -Wall warnings on the following. */
655
+ GC_STATIC_ASSERT(sizeof (ptr_t) == sizeof(word));
656
+ GC_STATIC_ASSERT(sizeof (signed_word) == sizeof(word));
657
+ GC_STATIC_ASSERT(sizeof (struct hblk) == HBLKSIZE);
658
+ # ifndef THREADS
659
+ # ifdef STACK_GROWS_DOWN
660
+ GC_ASSERT((word)(&dummy) <= (word)GC_stackbottom);
661
+ # else
662
+ GC_ASSERT((word)(&dummy) >= (word)GC_stackbottom);
663
+ # endif
664
+ # endif
665
+ # if !defined(_AUX_SOURCE) || defined(__GNUC__)
666
+ GC_ASSERT((word)(-1) > (word)0);
667
+ /* word should be unsigned */
668
+ # endif
669
+ GC_ASSERT((ptr_t)(word)(-1) > (ptr_t)0);
670
+ /* Ptr_t comparisons should behave as unsigned comparisons. */
671
+ GC_ASSERT((signed_word)(-1) < (signed_word)0);
672
+ # if !defined(SMALL_CONFIG)
673
+ if (GC_incremental || 0 != GETENV("GC_ENABLE_INCREMENTAL")) {
674
+ /* This used to test for !GC_no_win32_dlls. Why? */
675
+ GC_setpagesize();
676
+ /* For GWW_MPROTECT on Win32, this needs to happen before any */
677
+ /* heap memory is allocated. */
678
+ GC_dirty_init();
679
+ GC_ASSERT(GC_bytes_allocd == 0)
680
+ GC_incremental = TRUE;
681
+ }
682
+ # endif /* !SMALL_CONFIG */
683
+
684
+ /* Add initial guess of root sets. Do this first, since sbrk(0) */
685
+ /* might be used. */
686
+ if (GC_REGISTER_MAIN_STATIC_DATA()) GC_register_data_segments();
687
+ GC_init_headers();
688
+ GC_bl_init();
689
+ GC_mark_init();
690
+ {
691
+ char * sz_str = GETENV("GC_INITIAL_HEAP_SIZE");
692
+ if (sz_str != NULL) {
693
+ initial_heap_sz = atoi(sz_str);
694
+ if (initial_heap_sz <= MINHINCR * HBLKSIZE) {
695
+ WARN("Bad initial heap size %s - ignoring it.\n",
696
+ sz_str);
697
+ }
698
+ initial_heap_sz = divHBLKSZ(initial_heap_sz);
699
+ }
700
+ }
701
+ {
702
+ char * sz_str = GETENV("GC_MAXIMUM_HEAP_SIZE");
703
+ if (sz_str != NULL) {
704
+ word max_heap_sz = (word)atol(sz_str);
705
+ if (max_heap_sz < initial_heap_sz * HBLKSIZE) {
706
+ WARN("Bad maximum heap size %s - ignoring it.\n",
707
+ sz_str);
708
+ }
709
+ if (0 == GC_max_retries) GC_max_retries = 2;
710
+ GC_set_max_heap_size(max_heap_sz);
711
+ }
712
+ }
713
+ if (!GC_expand_hp_inner(initial_heap_sz)) {
714
+ GC_err_printf("Can't start up: not enough memory\n");
715
+ EXIT();
716
+ }
717
+ GC_initialize_offsets();
718
+ GC_register_displacement_inner(0L);
719
+ # if defined(GC_LINUX_THREADS) && defined(REDIRECT_MALLOC)
720
+ if (!GC_all_interior_pointers) {
721
+ /* TLS ABI uses pointer-sized offsets for dtv. */
722
+ GC_register_displacement_inner(sizeof(void *));
723
+ }
724
+ # endif
725
+ GC_init_size_map();
726
+ # ifdef PCR
727
+ if (PCR_IL_Lock(PCR_Bool_false, PCR_allSigsBlocked, PCR_waitForever)
728
+ != PCR_ERes_okay) {
729
+ ABORT("Can't lock load state\n");
730
+ } else if (PCR_IL_Unlock() != PCR_ERes_okay) {
731
+ ABORT("Can't unlock load state\n");
732
+ }
733
+ PCR_IL_Unlock();
734
+ GC_pcr_install();
735
+ # endif
736
+ GC_is_initialized = TRUE;
737
+ # if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)
738
+ GC_thr_init();
739
+ # endif
740
+ COND_DUMP;
741
+ /* Get black list set up and/or incremental GC started */
742
+ if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner();
743
+ # ifdef STUBBORN_ALLOC
744
+ GC_stubborn_init();
745
+ # endif
746
+ # if defined(GC_LINUX_THREADS) && defined(REDIRECT_MALLOC)
747
+ {
748
+ extern void GC_init_lib_bounds(void);
749
+ GC_init_lib_bounds();
750
+ }
751
+ # endif
752
+ /* Convince lint that some things are used */
753
+ # ifdef LINT
754
+ {
755
+ extern char * GC_copyright[];
756
+ extern int GC_read();
757
+ extern void GC_register_finalizer_no_order();
758
+
759
+ GC_noop(GC_copyright, GC_find_header,
760
+ GC_push_one, GC_call_with_alloc_lock, GC_read,
761
+ GC_dont_expand,
762
+ # ifndef NO_DEBUGGING
763
+ GC_dump,
764
+ # endif
765
+ GC_register_finalizer_no_order);
766
+ }
767
+ # endif
768
+ }
769
+
770
+ void GC_enable_incremental(void)
771
+ {
772
+ # if !defined(SMALL_CONFIG) && !defined(KEEP_BACK_PTRS)
773
+ /* If we are keeping back pointers, the GC itself dirties all */
774
+ /* pages on which objects have been marked, making */
775
+ /* incremental GC pointless. */
776
+ if (!GC_find_leak) {
777
+ DCL_LOCK_STATE;
778
+
779
+ LOCK();
780
+ if (GC_incremental) goto out;
781
+ GC_setpagesize();
782
+ /* if (GC_no_win32_dlls) goto out; Should be win32S test? */
783
+ maybe_install_looping_handler(); /* Before write fault handler! */
784
+ GC_incremental = TRUE;
785
+ if (!GC_is_initialized) {
786
+ GC_init_inner();
787
+ } else {
788
+ GC_dirty_init();
789
+ }
790
+ if (!GC_dirty_maintained) goto out;
791
+ if (GC_dont_gc) {
792
+ /* Can't easily do it. */
793
+ UNLOCK();
794
+ return;
795
+ }
796
+ if (GC_bytes_allocd > 0) {
797
+ /* There may be unmarked reachable objects */
798
+ GC_gcollect_inner();
799
+ } /* else we're OK in assuming everything's */
800
+ /* clean since nothing can point to an */
801
+ /* unmarked object. */
802
+ GC_read_dirty();
803
+ out:
804
+ UNLOCK();
805
+ } else {
806
+ GC_init();
807
+ }
808
+ # else
809
+ GC_init();
810
+ # endif
811
+ }
812
+
813
+
814
+ #if defined(MSWIN32) || defined(MSWINCE)
815
+ # if defined(_MSC_VER) && defined(_DEBUG)
816
+ # include <crtdbg.h>
817
+ # endif
818
+ # ifdef OLD_WIN32_LOG_FILE
819
+ # define LOG_FILE _T("gc.log")
820
+ # endif
821
+
822
+ HANDLE GC_stdout = 0;
823
+
824
+ void GC_deinit()
825
+ {
826
+ if (GC_is_initialized) {
827
+ DeleteCriticalSection(&GC_write_cs);
828
+ }
829
+ }
830
+
831
+ # ifndef THREADS
832
+ # define GC_need_to_lock 0 /* Not defined without threads */
833
+ # endif
834
+ int GC_write(const char *buf, size_t len)
835
+ {
836
+ BOOL tmp;
837
+ DWORD written;
838
+ if (len == 0)
839
+ return 0;
840
+ if (GC_need_to_lock) EnterCriticalSection(&GC_write_cs);
841
+ if (GC_stdout == INVALID_HANDLE_VALUE) {
842
+ if (GC_need_to_lock) LeaveCriticalSection(&GC_write_cs);
843
+ return -1;
844
+ } else if (GC_stdout == 0) {
845
+ char * file_name = GETENV("GC_LOG_FILE");
846
+ char logPath[_MAX_PATH + 5];
847
+
848
+ if (0 == file_name) {
849
+ # ifdef OLD_WIN32_LOG_FILE
850
+ strcpy(logPath, LOG_FILE);
851
+ # else
852
+ GetModuleFileName(NULL, logPath, _MAX_PATH);
853
+ strcat(logPath, ".log");
854
+ # endif
855
+ file_name = logPath;
856
+ }
857
+ GC_stdout = CreateFile(logPath, GENERIC_WRITE,
858
+ FILE_SHARE_READ,
859
+ NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH,
860
+ NULL);
861
+ if (GC_stdout == INVALID_HANDLE_VALUE)
862
+ ABORT("Open of log file failed");
863
+ }
864
+ tmp = WriteFile(GC_stdout, buf, (DWORD)len, &written, NULL);
865
+ if (!tmp)
866
+ DebugBreak();
867
+ # if defined(_MSC_VER) && defined(_DEBUG)
868
+ _CrtDbgReport(_CRT_WARN, NULL, 0, NULL, "%.*s", len, buf);
869
+ # endif
870
+ if (GC_need_to_lock) LeaveCriticalSection(&GC_write_cs);
871
+ return tmp ? (int)written : -1;
872
+ }
873
+ # undef GC_need_to_lock
874
+
875
+ #endif
876
+
877
+ #if defined(OS2) || defined(MACOS)
878
+ FILE * GC_stdout = NULL;
879
+ FILE * GC_stderr = NULL;
880
+ FILE * GC_log = NULL;
881
+ int GC_tmp; /* Should really be local ... */
882
+
883
+ void GC_set_files()
884
+ {
885
+ if (GC_stdout == NULL) {
886
+ GC_stdout = stdout;
887
+ }
888
+ if (GC_stderr == NULL) {
889
+ GC_stderr = stderr;
890
+ }
891
+ if (GC_log == NULL) {
892
+ GC_log = stderr;
893
+ }
894
+ }
895
+ #endif
896
+
897
+ #if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32) && !defined(MSWINCE)
898
+ int GC_stdout = 1;
899
+ int GC_stderr = 2;
900
+ int GC_log = 2;
901
+ # if !defined(AMIGA)
902
+ # include <unistd.h>
903
+ # endif
904
+ #endif
905
+
906
+ #if !defined(MSWIN32) && !defined(MSWINCE) && !defined(OS2) \
907
+ && !defined(MACOS) && !defined(ECOS) && !defined(NOSYS)
908
+ int GC_write(fd, buf, len)
909
+ int fd;
910
+ const char *buf;
911
+ size_t len;
912
+ {
913
+ register int bytes_written = 0;
914
+ register int result;
915
+
916
+ while (bytes_written < len) {
917
+ # ifdef GC_SOLARIS_THREADS
918
+ result = syscall(SYS_write, fd, buf + bytes_written,
919
+ len - bytes_written);
920
+ # else
921
+ result = write(fd, buf + bytes_written, len - bytes_written);
922
+ # endif
923
+ if (-1 == result) return(result);
924
+ bytes_written += result;
925
+ }
926
+ return(bytes_written);
927
+ }
928
+ #endif /* UN*X */
929
+
930
+ #ifdef ECOS
931
+ int GC_write(fd, buf, len)
932
+ {
933
+ _Jv_diag_write (buf, len);
934
+ return len;
935
+ }
936
+ #endif
937
+
938
+ #ifdef NOSYS
939
+ int GC_write(fd, buf, len)
940
+ {
941
+ /* No writing. */
942
+ return len;
943
+ }
944
+ #endif
945
+
946
+
947
+ #if defined(MSWIN32) || defined(MSWINCE)
948
+ /* FIXME: This is pretty ugly ... */
949
+ # define WRITE(f, buf, len) GC_write(buf, len)
950
+ #else
951
+ # if defined(OS2) || defined(MACOS)
952
+ # define WRITE(f, buf, len) (GC_set_files(), \
953
+ GC_tmp = fwrite((buf), 1, (len), (f)), \
954
+ fflush(f), GC_tmp)
955
+ # else
956
+ # define WRITE(f, buf, len) GC_write((f), (buf), (len))
957
+ # endif
958
+ #endif
959
+
960
+ #define BUFSZ 1024
961
+ #ifdef _MSC_VER
962
+ # define vsnprintf _vsnprintf
963
+ #endif
964
+ /* A version of printf that is unlikely to call malloc, and is thus safer */
965
+ /* to call from the collector in case malloc has been bound to GC_malloc. */
966
+ /* Floating point arguments ans formats should be avoided, since fp */
967
+ /* conversion is more likely to allocate. */
968
+ /* Assumes that no more than BUFSZ-1 characters are written at once. */
969
+ void GC_printf(const char *format, ...)
970
+ {
971
+ va_list args;
972
+ char buf[BUFSZ+1];
973
+
974
+ va_start(args, format);
975
+ if (GC_quiet) return;
976
+ buf[BUFSZ] = 0x15;
977
+ (void) vsnprintf(buf, BUFSZ, format, args);
978
+ va_end(args);
979
+ if (buf[BUFSZ] != 0x15) ABORT("GC_printf clobbered stack");
980
+ if (WRITE(GC_stdout, buf, strlen(buf)) < 0) ABORT("write to stdout failed");
981
+ }
982
+
983
+ void GC_err_printf(const char *format, ...)
984
+ {
985
+ va_list args;
986
+ char buf[BUFSZ+1];
987
+
988
+ va_start(args, format);
989
+ buf[BUFSZ] = 0x15;
990
+ (void) vsnprintf(buf, BUFSZ, format, args);
991
+ va_end(args);
992
+ if (buf[BUFSZ] != 0x15) ABORT("GC_printf clobbered stack");
993
+ if (WRITE(GC_stderr, buf, strlen(buf)) < 0) ABORT("write to stderr failed");
994
+ }
995
+
996
+ void GC_log_printf(const char *format, ...)
997
+ {
998
+ va_list args;
999
+ char buf[BUFSZ+1];
1000
+
1001
+ va_start(args, format);
1002
+ buf[BUFSZ] = 0x15;
1003
+ (void) vsnprintf(buf, BUFSZ, format, args);
1004
+ va_end(args);
1005
+ if (buf[BUFSZ] != 0x15) ABORT("GC_printf clobbered stack");
1006
+ if (WRITE(GC_log, buf, strlen(buf)) < 0) ABORT("write to log failed");
1007
+ }
1008
+
1009
+ void GC_err_puts(const char *s)
1010
+ {
1011
+ if (WRITE(GC_stderr, s, strlen(s)) < 0) ABORT("write to stderr failed");
1012
+ }
1013
+
1014
+ #if defined(LINUX) && !defined(SMALL_CONFIG)
1015
+ void GC_err_write(buf, len)
1016
+ const char *buf;
1017
+ size_t len;
1018
+ {
1019
+ if (WRITE(GC_stderr, buf, len) < 0) ABORT("write to stderr failed");
1020
+ }
1021
+ #endif
1022
+
1023
+ void GC_default_warn_proc(char *msg, GC_word arg)
1024
+ {
1025
+ GC_err_printf(msg, arg);
1026
+ }
1027
+
1028
+ GC_warn_proc GC_current_warn_proc = GC_default_warn_proc;
1029
+
1030
+ GC_warn_proc GC_set_warn_proc(GC_warn_proc p)
1031
+ {
1032
+ GC_warn_proc result;
1033
+
1034
+ # ifdef GC_WIN32_THREADS
1035
+ GC_ASSERT(GC_is_initialized);
1036
+ # endif
1037
+ LOCK();
1038
+ result = GC_current_warn_proc;
1039
+ GC_current_warn_proc = p;
1040
+ UNLOCK();
1041
+ return(result);
1042
+ }
1043
+
1044
+ GC_word GC_set_free_space_divisor (GC_word value)
1045
+ {
1046
+ GC_word old = GC_free_space_divisor;
1047
+ GC_free_space_divisor = value;
1048
+ return old;
1049
+ }
1050
+
1051
+ #ifndef PCR
1052
+ void GC_abort(const char *msg)
1053
+ {
1054
+ # if defined(MSWIN32)
1055
+ (void) MessageBoxA(NULL, msg, "Fatal error in gc", MB_ICONERROR|MB_OK);
1056
+ # else
1057
+ GC_err_printf("%s\n", msg);
1058
+ # endif
1059
+ if (GETENV("GC_LOOP_ON_ABORT") != NULL) {
1060
+ /* In many cases it's easier to debug a running process. */
1061
+ /* It's arguably nicer to sleep, but that makes it harder */
1062
+ /* to look at the thread if the debugger doesn't know much */
1063
+ /* about threads. */
1064
+ for(;;) {}
1065
+ }
1066
+ # if defined(MSWIN32) || defined(MSWINCE)
1067
+ DebugBreak();
1068
+ # else
1069
+ (void) abort();
1070
+ # endif
1071
+ }
1072
+ #endif
1073
+
1074
+ void GC_enable()
1075
+ {
1076
+ LOCK();
1077
+ GC_dont_gc--;
1078
+ UNLOCK();
1079
+ }
1080
+
1081
+ void GC_disable()
1082
+ {
1083
+ LOCK();
1084
+ GC_dont_gc++;
1085
+ UNLOCK();
1086
+ }
1087
+
1088
+ /* Helper procedures for new kind creation. */
1089
+ void ** GC_new_free_list_inner()
1090
+ {
1091
+ void *result = GC_INTERNAL_MALLOC((MAXOBJGRANULES+1)*sizeof(ptr_t),
1092
+ PTRFREE);
1093
+ if (result == 0) ABORT("Failed to allocate freelist for new kind");
1094
+ BZERO(result, (MAXOBJGRANULES+1)*sizeof(ptr_t));
1095
+ return result;
1096
+ }
1097
+
1098
+ void ** GC_new_free_list()
1099
+ {
1100
+ void *result;
1101
+ LOCK();
1102
+ result = GC_new_free_list_inner();
1103
+ UNLOCK();
1104
+ return result;
1105
+ }
1106
+
1107
+ unsigned GC_new_kind_inner(void **fl, GC_word descr, int adjust, int clear)
1108
+ {
1109
+ unsigned result = GC_n_kinds++;
1110
+
1111
+ if (GC_n_kinds > MAXOBJKINDS) ABORT("Too many kinds");
1112
+ GC_obj_kinds[result].ok_freelist = fl;
1113
+ GC_obj_kinds[result].ok_reclaim_list = 0;
1114
+ GC_obj_kinds[result].ok_descriptor = descr;
1115
+ GC_obj_kinds[result].ok_relocate_descr = adjust;
1116
+ GC_obj_kinds[result].ok_init = clear;
1117
+ return result;
1118
+ }
1119
+
1120
+ unsigned GC_new_kind(void **fl, GC_word descr, int adjust, int clear)
1121
+ {
1122
+ unsigned result;
1123
+ LOCK();
1124
+ result = GC_new_kind_inner(fl, descr, adjust, clear);
1125
+ UNLOCK();
1126
+ return result;
1127
+ }
1128
+
1129
+ unsigned GC_new_proc_inner(GC_mark_proc proc)
1130
+ {
1131
+ unsigned result = GC_n_mark_procs++;
1132
+
1133
+ if (GC_n_mark_procs > MAX_MARK_PROCS) ABORT("Too many mark procedures");
1134
+ GC_mark_procs[result] = proc;
1135
+ return result;
1136
+ }
1137
+
1138
+ unsigned GC_new_proc(GC_mark_proc proc)
1139
+ {
1140
+ unsigned result;
1141
+ LOCK();
1142
+ result = GC_new_proc_inner(proc);
1143
+ UNLOCK();
1144
+ return result;
1145
+ }
1146
+
1147
+ void * GC_call_with_stack_base(GC_stack_base_func fn, void *arg)
1148
+ {
1149
+ int dummy;
1150
+ struct GC_stack_base base;
1151
+
1152
+ base.mem_base = (void *)&dummy;
1153
+ # ifdef IA64
1154
+ base.reg_base = (void *)GC_save_regs_in_stack();
1155
+ /* Unnecessarily flushes register stack, */
1156
+ /* but that probably doesn't hurt. */
1157
+ # endif
1158
+ return fn(&base, arg);
1159
+ }
1160
+
1161
+ #if !defined(NO_DEBUGGING)
1162
+
1163
+ void GC_dump()
1164
+ {
1165
+ GC_printf("***Static roots:\n");
1166
+ GC_print_static_roots();
1167
+ GC_printf("\n***Heap sections:\n");
1168
+ GC_print_heap_sects();
1169
+ GC_printf("\n***Free blocks:\n");
1170
+ GC_print_hblkfreelist();
1171
+ GC_printf("\n***Blocks in use:\n");
1172
+ GC_print_block_list();
1173
+ GC_printf("\n***Finalization statistics:\n");
1174
+ GC_print_finalization_stats();
1175
+ }
1176
+
1177
+ #endif /* NO_DEBUGGING */
mosesdecoder/jam-files/engine/boehm_gc/os_dep.c ADDED
The diff for this file is too large to render. See raw diff
 
mosesdecoder/jam-files/engine/boehm_gc/pcr_interface.c ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
3
+ *
4
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
6
+ *
7
+ * Permission is hereby granted to use or copy this program
8
+ * for any purpose, provided the above notices are retained on all copies.
9
+ * Permission to modify the code and to distribute modified code is granted,
10
+ * provided the above notices are retained, and a notice that the code was
11
+ * modified is included with the above copyright notice.
12
+ */
13
+ # include "private/gc_priv.h"
14
+
15
+ # ifdef PCR
16
+ /*
17
+ * Note that POSIX PCR requires an ANSI C compiler. Hence we are allowed
18
+ * to make the same assumption here.
19
+ * We wrap all of the allocator functions to avoid questions of
20
+ * compatibility between the prototyped and nonprototyped versions of the f
21
+ */
22
+ # include "config/PCR_StdTypes.h"
23
+ # include "mm/PCR_MM.h"
24
+ # include <errno.h>
25
+
26
+ # define MY_MAGIC 17L
27
+ # define MY_DEBUGMAGIC 42L
28
+
29
+ void * GC_AllocProc(size_t size, PCR_Bool ptrFree, PCR_Bool clear )
30
+ {
31
+ if (ptrFree) {
32
+ void * result = (void *)GC_malloc_atomic(size);
33
+ if (clear && result != 0) BZERO(result, size);
34
+ return(result);
35
+ } else {
36
+ return((void *)GC_malloc(size));
37
+ }
38
+ }
39
+
40
+ void * GC_DebugAllocProc(size_t size, PCR_Bool ptrFree, PCR_Bool clear )
41
+ {
42
+ if (ptrFree) {
43
+ void * result = (void *)GC_debug_malloc_atomic(size, __FILE__,
44
+ __LINE__);
45
+ if (clear && result != 0) BZERO(result, size);
46
+ return(result);
47
+ } else {
48
+ return((void *)GC_debug_malloc(size, __FILE__, __LINE__));
49
+ }
50
+ }
51
+
52
+ # define GC_ReallocProc GC_realloc
53
+ void * GC_DebugReallocProc(void * old_object, size_t new_size_in_bytes)
54
+ {
55
+ return(GC_debug_realloc(old_object, new_size_in_bytes, __FILE__, __LINE__));
56
+ }
57
+
58
+ # define GC_FreeProc GC_free
59
+ # define GC_DebugFreeProc GC_debug_free
60
+
61
+ typedef struct {
62
+ PCR_ERes (*ed_proc)(void *p, size_t size, PCR_Any data);
63
+ GC_bool ed_pointerfree;
64
+ PCR_ERes ed_fail_code;
65
+ PCR_Any ed_client_data;
66
+ } enumerate_data;
67
+
68
+ void GC_enumerate_block(struct hblk *h; enumerate_data * ed)
69
+ {
70
+ register hdr * hhdr;
71
+ register int sz;
72
+ ptr_t p;
73
+ ptr_t lim;
74
+ word descr;
75
+ # error This code was updated without testing.
76
+ # error and its precursor was clearly broken.
77
+
78
+ hhdr = HDR(h);
79
+ descr = hhdr -> hb_descr;
80
+ sz = hhdr -> hb_sz;
81
+ if (descr != 0 && ed -> ed_pointerfree
82
+ || descr == 0 && !(ed -> ed_pointerfree)) return;
83
+ lim = (ptr_t)(h+1) - sz;
84
+ p = (ptr_t)h;
85
+ do {
86
+ if (PCR_ERes_IsErr(ed -> ed_fail_code)) return;
87
+ ed -> ed_fail_code =
88
+ (*(ed -> ed_proc))(p, sz, ed -> ed_client_data);
89
+ p+= sz;
90
+ } while (p <= lim);
91
+ }
92
+
93
+ struct PCR_MM_ProcsRep * GC_old_allocator = 0;
94
+
95
+ PCR_ERes GC_EnumerateProc(
96
+ PCR_Bool ptrFree,
97
+ PCR_ERes (*proc)(void *p, size_t size, PCR_Any data),
98
+ PCR_Any data
99
+ )
100
+ {
101
+ enumerate_data ed;
102
+
103
+ ed.ed_proc = proc;
104
+ ed.ed_pointerfree = ptrFree;
105
+ ed.ed_fail_code = PCR_ERes_okay;
106
+ ed.ed_client_data = data;
107
+ GC_apply_to_all_blocks(GC_enumerate_block, &ed);
108
+ if (ed.ed_fail_code != PCR_ERes_okay) {
109
+ return(ed.ed_fail_code);
110
+ } else {
111
+ /* Also enumerate objects allocated by my predecessors */
112
+ return((*(GC_old_allocator->mmp_enumerate))(ptrFree, proc, data));
113
+ }
114
+ }
115
+
116
+ void GC_DummyFreeProc(void *p) {}
117
+
118
+ void GC_DummyShutdownProc(void) {}
119
+
120
+ struct PCR_MM_ProcsRep GC_Rep = {
121
+ MY_MAGIC,
122
+ GC_AllocProc,
123
+ GC_ReallocProc,
124
+ GC_DummyFreeProc, /* mmp_free */
125
+ GC_FreeProc, /* mmp_unsafeFree */
126
+ GC_EnumerateProc,
127
+ GC_DummyShutdownProc /* mmp_shutdown */
128
+ };
129
+
130
+ struct PCR_MM_ProcsRep GC_DebugRep = {
131
+ MY_DEBUGMAGIC,
132
+ GC_DebugAllocProc,
133
+ GC_DebugReallocProc,
134
+ GC_DummyFreeProc, /* mmp_free */
135
+ GC_DebugFreeProc, /* mmp_unsafeFree */
136
+ GC_EnumerateProc,
137
+ GC_DummyShutdownProc /* mmp_shutdown */
138
+ };
139
+
140
+ GC_bool GC_use_debug = 0;
141
+
142
+ void GC_pcr_install()
143
+ {
144
+ PCR_MM_Install((GC_use_debug? &GC_DebugRep : &GC_Rep), &GC_old_allocator);
145
+ }
146
+
147
+ PCR_ERes
148
+ PCR_GC_Setup(void)
149
+ {
150
+ return PCR_ERes_okay;
151
+ }
152
+
153
+ PCR_ERes
154
+ PCR_GC_Run(void)
155
+ {
156
+
157
+ if( !PCR_Base_TestPCRArg("-nogc") ) {
158
+ GC_quiet = ( PCR_Base_TestPCRArg("-gctrace") ? 0 : 1 );
159
+ GC_use_debug = (GC_bool)PCR_Base_TestPCRArg("-debug_alloc");
160
+ GC_init();
161
+ if( !PCR_Base_TestPCRArg("-nogc_incremental") ) {
162
+ /*
163
+ * awful hack to test whether VD is implemented ...
164
+ */
165
+ if( PCR_VD_Start( 0, NIL, 0) != PCR_ERes_FromErr(ENOSYS) ) {
166
+ GC_enable_incremental();
167
+ }
168
+ }
169
+ }
170
+ return PCR_ERes_okay;
171
+ }
172
+
173
+ void GC_push_thread_structures(void)
174
+ {
175
+ /* PCR doesn't work unless static roots are pushed. Can't get here. */
176
+ ABORT("In GC_push_thread_structures()");
177
+ }
178
+
179
+ # endif
mosesdecoder/jam-files/engine/boehm_gc/pthread_support.c ADDED
@@ -0,0 +1,1495 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
3
+ * Copyright (c) 1996 by Silicon Graphics. All rights reserved.
4
+ * Copyright (c) 1998 by Fergus Henderson. All rights reserved.
5
+ * Copyright (c) 2000-2005 by Hewlett-Packard Company. All rights reserved.
6
+ *
7
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
8
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
9
+ *
10
+ * Permission is hereby granted to use or copy this program
11
+ * for any purpose, provided the above notices are retained on all copies.
12
+ * Permission to modify the code and to distribute modified code is granted,
13
+ * provided the above notices are retained, and a notice that the code was
14
+ * modified is included with the above copyright notice.
15
+ */
16
+ /*
17
+ * Support code originally for LinuxThreads, the clone()-based kernel
18
+ * thread package for Linux which is included in libc6.
19
+ *
20
+ * This code no doubt makes some assumptions beyond what is
21
+ * guaranteed by the pthread standard, though it now does
22
+ * very little of that. It now also supports NPTL, and many
23
+ * other Posix thread implementations. We are trying to merge
24
+ * all flavors of pthread dupport code into this file.
25
+ */
26
+ /* DG/UX ix86 support <takis@xfree86.org> */
27
+ /*
28
+ * Linux_threads.c now also includes some code to support HPUX and
29
+ * OSF1 (Compaq Tru64 Unix, really). The OSF1 support is based on Eric Benson's
30
+ * patch.
31
+ *
32
+ * Eric also suggested an alternate basis for a lock implementation in
33
+ * his code:
34
+ * + #elif defined(OSF1)
35
+ * + unsigned long GC_allocate_lock = 0;
36
+ * + msemaphore GC_allocate_semaphore;
37
+ * + # define GC_TRY_LOCK() \
38
+ * + ((msem_lock(&GC_allocate_semaphore, MSEM_IF_NOWAIT) == 0) \
39
+ * + ? (GC_allocate_lock = 1) \
40
+ * + : 0)
41
+ * + # define GC_LOCK_TAKEN GC_allocate_lock
42
+ */
43
+
44
+ /*#define DEBUG_THREADS 1*/
45
+
46
+ # include "private/pthread_support.h"
47
+
48
+ # if defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS)
49
+
50
+ # if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE)
51
+ # define _POSIX4A_DRAFT10_SOURCE 1
52
+ # endif
53
+
54
+ # if defined(GC_DGUX386_THREADS) && !defined(_USING_POSIX4A_DRAFT10)
55
+ # define _USING_POSIX4A_DRAFT10 1
56
+ # endif
57
+
58
+ # include <stdlib.h>
59
+ # include <pthread.h>
60
+ # include <sched.h>
61
+ # include <time.h>
62
+ # include <errno.h>
63
+ # include <unistd.h>
64
+ # include <sys/mman.h>
65
+ # include <sys/time.h>
66
+ # include <sys/types.h>
67
+ # include <sys/stat.h>
68
+ # include <fcntl.h>
69
+ # include <signal.h>
70
+
71
+ # include "gc_inline.h"
72
+
73
+ #if defined(GC_DARWIN_THREADS)
74
+ # include "private/darwin_semaphore.h"
75
+ #else
76
+ # include <semaphore.h>
77
+ #endif /* !GC_DARWIN_THREADS */
78
+
79
+ #if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS)
80
+ # include <sys/sysctl.h>
81
+ #endif /* GC_DARWIN_THREADS */
82
+
83
+ #if defined(GC_NETBSD_THREADS)
84
+ # include <sys/param.h>
85
+ # include <sys/sysctl.h>
86
+ #endif /* GC_NETBSD_THREADS */
87
+
88
+ /* Allocator lock definitions. */
89
+ #if !defined(USE_SPIN_LOCK)
90
+ pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;
91
+ #endif
92
+ unsigned long GC_lock_holder = NO_THREAD;
93
+ /* Used only for assertions, and to prevent */
94
+ /* recursive reentry in the system call wrapper. */
95
+
96
+ #if defined(GC_DGUX386_THREADS)
97
+ # include <sys/dg_sys_info.h>
98
+ # include <sys/_int_psem.h>
99
+ /* sem_t is an uint in DG/UX */
100
+ typedef unsigned int sem_t;
101
+ #endif /* GC_DGUX386_THREADS */
102
+
103
+ #ifndef __GNUC__
104
+ # define __inline__
105
+ #endif
106
+
107
+ /* Undefine macros used to redirect pthread primitives. */
108
+ # undef pthread_create
109
+ # if !defined(GC_DARWIN_THREADS)
110
+ # undef pthread_sigmask
111
+ # endif
112
+ # undef pthread_join
113
+ # undef pthread_detach
114
+ # if defined(GC_OSF1_THREADS) && defined(_PTHREAD_USE_MANGLED_NAMES_) \
115
+ && !defined(_PTHREAD_USE_PTDNAM_)
116
+ /* Restore the original mangled names on Tru64 UNIX. */
117
+ # define pthread_create __pthread_create
118
+ # define pthread_join __pthread_join
119
+ # define pthread_detach __pthread_detach
120
+ # endif
121
+
122
+ #ifdef GC_USE_LD_WRAP
123
+ # define WRAP_FUNC(f) __wrap_##f
124
+ # define REAL_FUNC(f) __real_##f
125
+ #else
126
+ # ifdef GC_USE_DLOPEN_WRAP
127
+ # include <dlfcn.h>
128
+ # define WRAP_FUNC(f) f
129
+ # define REAL_FUNC(f) GC_real_##f
130
+ /* We define both GC_f and plain f to be the wrapped function. */
131
+ /* In that way plain calls work, as do calls from files that */
132
+ /* included gc.h, wich redefined f to GC_f. */
133
+ /* FIXME: Needs work for DARWIN and True64 (OSF1) */
134
+ typedef int (* GC_pthread_create_t)(pthread_t *, const pthread_attr_t *,
135
+ void * (*)(void *), void *);
136
+ static GC_pthread_create_t GC_real_pthread_create;
137
+ typedef int (* GC_pthread_sigmask_t)(int, const sigset_t *, sigset_t *);
138
+ static GC_pthread_sigmask_t GC_real_pthread_sigmask;
139
+ typedef int (* GC_pthread_join_t)(pthread_t, void **);
140
+ static GC_pthread_join_t GC_real_pthread_join;
141
+ typedef int (* GC_pthread_detach_t)(pthread_t);
142
+ static GC_pthread_detach_t GC_real_pthread_detach;
143
+ # else
144
+ # define WRAP_FUNC(f) GC_##f
145
+ # if !defined(GC_DGUX386_THREADS)
146
+ # define REAL_FUNC(f) f
147
+ # else /* GC_DGUX386_THREADS */
148
+ # define REAL_FUNC(f) __d10_##f
149
+ # endif /* GC_DGUX386_THREADS */
150
+ # endif
151
+ #endif
152
+
153
+ #if defined(GC_USE_DL_WRAP) || defined(GC_USE_DLOPEN_WRAP)
154
+ /* Define GC_ functions as aliases for the plain ones, which will */
155
+ /* be intercepted. This allows files which include gc.h, and hence */
156
+ /* generate referemces to the GC_ symbols, to see the right symbols. */
157
+ int GC_pthread_create(pthread_t * t, const pthread_attr_t * a,
158
+ void * (* fn)(void *), void * arg) {
159
+ return pthread_create(t, a, fn, arg);
160
+ }
161
+ int GC_pthread_sigmask(int how, const sigset_t *mask, sigset_t *old) {
162
+ return pthread_sigmask(how, mask, old);
163
+ }
164
+ int GC_pthread_join(pthread_t t, void **res) {
165
+ return pthread_join(t, res);
166
+ }
167
+ int GC_pthread_detach(pthread_t t) {
168
+ return pthread_detach(t);
169
+ }
170
+ #endif /* Linker-based interception. */
171
+
172
+ #ifdef GC_USE_DLOPEN_WRAP
173
+ static GC_bool GC_syms_initialized = FALSE;
174
+
175
+ void GC_init_real_syms(void)
176
+ {
177
+ void *dl_handle;
178
+ # define LIBPTHREAD_NAME "libpthread.so.0"
179
+ # define LIBPTHREAD_NAME_LEN 16 /* incl. trailing 0 */
180
+ size_t len = LIBPTHREAD_NAME_LEN - 1;
181
+ char namebuf[LIBPTHREAD_NAME_LEN];
182
+ static char *libpthread_name = LIBPTHREAD_NAME;
183
+
184
+ if (GC_syms_initialized) return;
185
+ # ifdef RTLD_NEXT
186
+ dl_handle = RTLD_NEXT;
187
+ # else
188
+ dl_handle = dlopen(libpthread_name, RTLD_LAZY);
189
+ if (NULL == dl_handle) {
190
+ while (isdigit(libpthread_name[len-1])) --len;
191
+ if (libpthread_name[len-1] == '.') --len;
192
+ memcpy(namebuf, libpthread_name, len);
193
+ namebuf[len] = '\0';
194
+ dl_handle = dlopen(namebuf, RTLD_LAZY);
195
+ }
196
+ if (NULL == dl_handle) ABORT("Couldn't open libpthread\n");
197
+ # endif
198
+ GC_real_pthread_create = (GC_pthread_create_t)
199
+ dlsym(dl_handle, "pthread_create");
200
+ GC_real_pthread_sigmask = (GC_pthread_sigmask_t)
201
+ dlsym(dl_handle, "pthread_sigmask");
202
+ GC_real_pthread_join = (GC_pthread_join_t)
203
+ dlsym(dl_handle, "pthread_join");
204
+ GC_real_pthread_detach = (GC_pthread_detach_t)
205
+ dlsym(dl_handle, "pthread_detach");
206
+ GC_syms_initialized = TRUE;
207
+ }
208
+
209
+ # define INIT_REAL_SYMS() if (!GC_syms_initialized) GC_init_real_syms();
210
+ #else
211
+ # define INIT_REAL_SYMS()
212
+ #endif
213
+
214
+ void GC_thr_init(void);
215
+
216
+ static GC_bool parallel_initialized = FALSE;
217
+
218
+ GC_bool GC_need_to_lock = FALSE;
219
+
220
+ void GC_init_parallel(void);
221
+
222
+ long GC_nprocs = 1; /* Number of processors. We may not have */
223
+ /* access to all of them, but this is as good */
224
+ /* a guess as any ... */
225
+
226
+ #ifdef THREAD_LOCAL_ALLOC
227
+ /* We must explicitly mark ptrfree and gcj free lists, since the free */
228
+ /* list links wouldn't otherwise be found. We also set them in the */
229
+ /* normal free lists, since that involves touching less memory than if */
230
+ /* we scanned them normally. */
231
+ void GC_mark_thread_local_free_lists(void)
232
+ {
233
+ int i;
234
+ GC_thread p;
235
+
236
+ for (i = 0; i < THREAD_TABLE_SZ; ++i) {
237
+ for (p = GC_threads[i]; 0 != p; p = p -> next) {
238
+ GC_mark_thread_local_fls_for(&(p->tlfs));
239
+ }
240
+ }
241
+ }
242
+
243
+ #if defined(GC_ASSERTIONS)
244
+ /* Check that all thread-local free-lists are completely marked. */
245
+ /* also check that thread-specific-data structures are marked. */
246
+ void GC_check_tls(void) {
247
+ int i;
248
+ GC_thread p;
249
+
250
+ for (i = 0; i < THREAD_TABLE_SZ; ++i) {
251
+ for (p = GC_threads[i]; 0 != p; p = p -> next) {
252
+ GC_check_tls_for(&(p->tlfs));
253
+ }
254
+ }
255
+ # if defined(USE_CUSTOM_SPECIFIC)
256
+ if (GC_thread_key != 0)
257
+ GC_check_tsd_marks(GC_thread_key);
258
+ # endif
259
+ }
260
+ #endif /* GC_ASSERTIONS */
261
+
262
+ #endif /* Thread_local_alloc */
263
+
264
+ #ifdef PARALLEL_MARK
265
+
266
+ # ifndef MAX_MARKERS
267
+ # define MAX_MARKERS 16
268
+ # endif
269
+
270
+ static ptr_t marker_sp[MAX_MARKERS] = {0};
271
+ #ifdef IA64
272
+ static ptr_t marker_bsp[MAX_MARKERS] = {0};
273
+ #endif
274
+
275
+ void * GC_mark_thread(void * id)
276
+ {
277
+ word my_mark_no = 0;
278
+
279
+ marker_sp[(word)id] = GC_approx_sp();
280
+ # ifdef IA64
281
+ marker_bsp[(word)id] = GC_save_regs_in_stack();
282
+ # endif
283
+ for (;; ++my_mark_no) {
284
+ /* GC_mark_no is passed only to allow GC_help_marker to terminate */
285
+ /* promptly. This is important if it were called from the signal */
286
+ /* handler or from the GC lock acquisition code. Under Linux, it's */
287
+ /* not safe to call it from a signal handler, since it uses mutexes */
288
+ /* and condition variables. Since it is called only here, the */
289
+ /* argument is unnecessary. */
290
+ if (my_mark_no < GC_mark_no || my_mark_no > GC_mark_no + 2) {
291
+ /* resynchronize if we get far off, e.g. because GC_mark_no */
292
+ /* wrapped. */
293
+ my_mark_no = GC_mark_no;
294
+ }
295
+ # ifdef DEBUG_THREADS
296
+ GC_printf("Starting mark helper for mark number %lu\n", my_mark_no);
297
+ # endif
298
+ GC_help_marker(my_mark_no);
299
+ }
300
+ }
301
+
302
+ extern long GC_markers; /* Number of mark threads we would */
303
+ /* like to have. Includes the */
304
+ /* initiating thread. */
305
+
306
+ pthread_t GC_mark_threads[MAX_MARKERS];
307
+
308
+ #define PTHREAD_CREATE REAL_FUNC(pthread_create)
309
+
310
+ static void start_mark_threads(void)
311
+ {
312
+ unsigned i;
313
+ pthread_attr_t attr;
314
+
315
+ if (GC_markers > MAX_MARKERS) {
316
+ WARN("Limiting number of mark threads\n", 0);
317
+ GC_markers = MAX_MARKERS;
318
+ }
319
+ if (0 != pthread_attr_init(&attr)) ABORT("pthread_attr_init failed");
320
+
321
+ if (0 != pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
322
+ ABORT("pthread_attr_setdetachstate failed");
323
+
324
+ # if defined(HPUX) || defined(GC_DGUX386_THREADS)
325
+ /* Default stack size is usually too small: fix it. */
326
+ /* Otherwise marker threads or GC may run out of */
327
+ /* space. */
328
+ # define MIN_STACK_SIZE (8*HBLKSIZE*sizeof(word))
329
+ {
330
+ size_t old_size;
331
+ int code;
332
+
333
+ if (pthread_attr_getstacksize(&attr, &old_size) != 0)
334
+ ABORT("pthread_attr_getstacksize failed\n");
335
+ if (old_size < MIN_STACK_SIZE) {
336
+ if (pthread_attr_setstacksize(&attr, MIN_STACK_SIZE) != 0)
337
+ ABORT("pthread_attr_setstacksize failed\n");
338
+ }
339
+ }
340
+ # endif /* HPUX || GC_DGUX386_THREADS */
341
+ if (GC_print_stats) {
342
+ GC_log_printf("Starting %ld marker threads\n", GC_markers - 1);
343
+ }
344
+ for (i = 0; i < GC_markers - 1; ++i) {
345
+ if (0 != PTHREAD_CREATE(GC_mark_threads + i, &attr,
346
+ GC_mark_thread, (void *)(word)i)) {
347
+ WARN("Marker thread creation failed, errno = %ld.\n", errno);
348
+ }
349
+ }
350
+ }
351
+
352
+ #endif /* PARALLEL_MARK */
353
+
354
+ GC_bool GC_thr_initialized = FALSE;
355
+
356
+ volatile GC_thread GC_threads[THREAD_TABLE_SZ];
357
+
358
+ void GC_push_thread_structures(void)
359
+ {
360
+ GC_ASSERT(I_HOLD_LOCK());
361
+ GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads));
362
+ # if defined(THREAD_LOCAL_ALLOC)
363
+ GC_push_all((ptr_t)(&GC_thread_key),
364
+ (ptr_t)(&GC_thread_key)+sizeof(&GC_thread_key));
365
+ # endif
366
+ }
367
+
368
+ /* It may not be safe to allocate when we register the first thread. */
369
+ static struct GC_Thread_Rep first_thread;
370
+
371
+ /* Add a thread to GC_threads. We assume it wasn't already there. */
372
+ /* Caller holds allocation lock. */
373
+ GC_thread GC_new_thread(pthread_t id)
374
+ {
375
+ int hv = NUMERIC_THREAD_ID(id) % THREAD_TABLE_SZ;
376
+ GC_thread result;
377
+ static GC_bool first_thread_used = FALSE;
378
+
379
+ GC_ASSERT(I_HOLD_LOCK());
380
+ if (!first_thread_used) {
381
+ result = &first_thread;
382
+ first_thread_used = TRUE;
383
+ } else {
384
+ result = (struct GC_Thread_Rep *)
385
+ GC_INTERNAL_MALLOC(sizeof(struct GC_Thread_Rep), NORMAL);
386
+ GC_ASSERT(result -> flags == 0);
387
+ }
388
+ if (result == 0) return(0);
389
+ result -> id = id;
390
+ result -> next = GC_threads[hv];
391
+ GC_threads[hv] = result;
392
+ GC_ASSERT(result -> flags == 0 && result -> thread_blocked == 0);
393
+ return(result);
394
+ }
395
+
396
+ /* Delete a thread from GC_threads. We assume it is there. */
397
+ /* (The code intentionally traps if it wasn't.) */
398
+ void GC_delete_thread(pthread_t id)
399
+ {
400
+ int hv = NUMERIC_THREAD_ID(id) % THREAD_TABLE_SZ;
401
+ register GC_thread p = GC_threads[hv];
402
+ register GC_thread prev = 0;
403
+
404
+ GC_ASSERT(I_HOLD_LOCK());
405
+ while (!THREAD_EQUAL(p -> id, id)) {
406
+ prev = p;
407
+ p = p -> next;
408
+ }
409
+ if (prev == 0) {
410
+ GC_threads[hv] = p -> next;
411
+ } else {
412
+ prev -> next = p -> next;
413
+ }
414
+ # ifdef GC_DARWIN_THREADS
415
+ mach_port_deallocate(mach_task_self(), p->stop_info.mach_thread);
416
+ # endif
417
+ GC_INTERNAL_FREE(p);
418
+ }
419
+
420
+ /* If a thread has been joined, but we have not yet */
421
+ /* been notified, then there may be more than one thread */
422
+ /* in the table with the same pthread id. */
423
+ /* This is OK, but we need a way to delete a specific one. */
424
+ void GC_delete_gc_thread(GC_thread gc_id)
425
+ {
426
+ pthread_t id = gc_id -> id;
427
+ int hv = NUMERIC_THREAD_ID(id) % THREAD_TABLE_SZ;
428
+ register GC_thread p = GC_threads[hv];
429
+ register GC_thread prev = 0;
430
+
431
+ GC_ASSERT(I_HOLD_LOCK());
432
+ while (p != gc_id) {
433
+ prev = p;
434
+ p = p -> next;
435
+ }
436
+ if (prev == 0) {
437
+ GC_threads[hv] = p -> next;
438
+ } else {
439
+ prev -> next = p -> next;
440
+ }
441
+ # ifdef GC_DARWIN_THREADS
442
+ mach_port_deallocate(mach_task_self(), p->stop_info.mach_thread);
443
+ # endif
444
+ GC_INTERNAL_FREE(p);
445
+ }
446
+
447
+ /* Return a GC_thread corresponding to a given pthread_t. */
448
+ /* Returns 0 if it's not there. */
449
+ /* Caller holds allocation lock or otherwise inhibits */
450
+ /* updates. */
451
+ /* If there is more than one thread with the given id we */
452
+ /* return the most recent one. */
453
+ GC_thread GC_lookup_thread(pthread_t id)
454
+ {
455
+ int hv = NUMERIC_THREAD_ID(id) % THREAD_TABLE_SZ;
456
+ register GC_thread p = GC_threads[hv];
457
+
458
+ while (p != 0 && !THREAD_EQUAL(p -> id, id)) p = p -> next;
459
+ return(p);
460
+ }
461
+
462
+ #ifdef HANDLE_FORK
463
+ /* Remove all entries from the GC_threads table, except the */
464
+ /* one for the current thread. We need to do this in the child */
465
+ /* process after a fork(), since only the current thread */
466
+ /* survives in the child. */
467
+ void GC_remove_all_threads_but_me(void)
468
+ {
469
+ pthread_t self = pthread_self();
470
+ int hv;
471
+ GC_thread p, next, me;
472
+
473
+ for (hv = 0; hv < THREAD_TABLE_SZ; ++hv) {
474
+ me = 0;
475
+ for (p = GC_threads[hv]; 0 != p; p = next) {
476
+ next = p -> next;
477
+ if (THREAD_EQUAL(p -> id, self)) {
478
+ me = p;
479
+ p -> next = 0;
480
+ } else {
481
+ # ifdef THREAD_LOCAL_ALLOC
482
+ if (!(p -> flags & FINISHED)) {
483
+ GC_destroy_thread_local(&(p->tlfs));
484
+ }
485
+ # endif /* THREAD_LOCAL_ALLOC */
486
+ if (p != &first_thread) GC_INTERNAL_FREE(p);
487
+ }
488
+ }
489
+ GC_threads[hv] = me;
490
+ }
491
+ }
492
+ #endif /* HANDLE_FORK */
493
+
494
+ #ifdef USE_PROC_FOR_LIBRARIES
495
+ GC_bool GC_segment_is_thread_stack(ptr_t lo, ptr_t hi)
496
+ {
497
+ int i;
498
+ GC_thread p;
499
+
500
+ GC_ASSERT(I_HOLD_LOCK());
501
+ # ifdef PARALLEL_MARK
502
+ for (i = 0; i < GC_markers; ++i) {
503
+ if (marker_sp[i] > lo & marker_sp[i] < hi) return TRUE;
504
+ # ifdef IA64
505
+ if (marker_bsp[i] > lo & marker_bsp[i] < hi) return TRUE;
506
+ # endif
507
+ }
508
+ # endif
509
+ for (i = 0; i < THREAD_TABLE_SZ; i++) {
510
+ for (p = GC_threads[i]; p != 0; p = p -> next) {
511
+ if (0 != p -> stack_end) {
512
+ # ifdef STACK_GROWS_UP
513
+ if (p -> stack_end >= lo && p -> stack_end < hi) return TRUE;
514
+ # else /* STACK_GROWS_DOWN */
515
+ if (p -> stack_end > lo && p -> stack_end <= hi) return TRUE;
516
+ # endif
517
+ }
518
+ }
519
+ }
520
+ return FALSE;
521
+ }
522
+ #endif /* USE_PROC_FOR_LIBRARIES */
523
+
524
+ #ifdef IA64
525
+ /* Find the largest stack_base smaller than bound. May be used */
526
+ /* to find the boundary between a register stack and adjacent */
527
+ /* immediately preceding memory stack. */
528
+ ptr_t GC_greatest_stack_base_below(ptr_t bound)
529
+ {
530
+ int i;
531
+ GC_thread p;
532
+ ptr_t result = 0;
533
+
534
+ GC_ASSERT(I_HOLD_LOCK());
535
+ # ifdef PARALLEL_MARK
536
+ for (i = 0; i < GC_markers; ++i) {
537
+ if (marker_sp[i] > result && marker_sp[i] < bound)
538
+ result = marker_sp[i];
539
+ }
540
+ # endif
541
+ for (i = 0; i < THREAD_TABLE_SZ; i++) {
542
+ for (p = GC_threads[i]; p != 0; p = p -> next) {
543
+ if (p -> stack_end > result && p -> stack_end < bound) {
544
+ result = p -> stack_end;
545
+ }
546
+ }
547
+ }
548
+ return result;
549
+ }
550
+ #endif /* IA64 */
551
+
552
+ #ifdef GC_LINUX_THREADS
553
+ /* Return the number of processors, or i<= 0 if it can't be determined. */
554
+ int GC_get_nprocs(void)
555
+ {
556
+ /* Should be "return sysconf(_SC_NPROCESSORS_ONLN);" but that */
557
+ /* appears to be buggy in many cases. */
558
+ /* We look for lines "cpu<n>" in /proc/stat. */
559
+ # define STAT_BUF_SIZE 4096
560
+ # define STAT_READ read
561
+ /* If read is wrapped, this may need to be redefined to call */
562
+ /* the real one. */
563
+ char stat_buf[STAT_BUF_SIZE];
564
+ int f;
565
+ word result = 1;
566
+ /* Some old kernels only have a single "cpu nnnn ..." */
567
+ /* entry in /proc/stat. We identify those as */
568
+ /* uniprocessors. */
569
+ size_t i, len = 0;
570
+
571
+ f = open("/proc/stat", O_RDONLY);
572
+ if (f < 0 || (len = STAT_READ(f, stat_buf, STAT_BUF_SIZE)) < 100) {
573
+ WARN("Couldn't read /proc/stat\n", 0);
574
+ return -1;
575
+ }
576
+ for (i = 0; i < len - 100; ++i) {
577
+ if (stat_buf[i] == '\n' && stat_buf[i+1] == 'c'
578
+ && stat_buf[i+2] == 'p' && stat_buf[i+3] == 'u') {
579
+ int cpu_no = atoi(stat_buf + i + 4);
580
+ if (cpu_no >= result) result = cpu_no + 1;
581
+ }
582
+ }
583
+ close(f);
584
+ return result;
585
+ }
586
+ #endif /* GC_LINUX_THREADS */
587
+
588
+ /* We hold the GC lock. Wait until an in-progress GC has finished. */
589
+ /* Repeatedly RELEASES GC LOCK in order to wait. */
590
+ /* If wait_for_all is true, then we exit with the GC lock held and no */
591
+ /* collection in progress; otherwise we just wait for the current GC */
592
+ /* to finish. */
593
+ extern GC_bool GC_collection_in_progress(void);
594
+ void GC_wait_for_gc_completion(GC_bool wait_for_all)
595
+ {
596
+ GC_ASSERT(I_HOLD_LOCK());
597
+ if (GC_incremental && GC_collection_in_progress()) {
598
+ int old_gc_no = GC_gc_no;
599
+
600
+ /* Make sure that no part of our stack is still on the mark stack, */
601
+ /* since it's about to be unmapped. */
602
+ while (GC_incremental && GC_collection_in_progress()
603
+ && (wait_for_all || old_gc_no == GC_gc_no)) {
604
+ ENTER_GC();
605
+ GC_in_thread_creation = TRUE;
606
+ GC_collect_a_little_inner(1);
607
+ GC_in_thread_creation = FALSE;
608
+ EXIT_GC();
609
+ UNLOCK();
610
+ sched_yield();
611
+ LOCK();
612
+ }
613
+ }
614
+ }
615
+
616
+ #ifdef HANDLE_FORK
617
+ /* Procedures called before and after a fork. The goal here is to make */
618
+ /* it safe to call GC_malloc() in a forked child. It's unclear that is */
619
+ /* attainable, since the single UNIX spec seems to imply that one */
620
+ /* should only call async-signal-safe functions, and we probably can't */
621
+ /* quite guarantee that. But we give it our best shot. (That same */
622
+ /* spec also implies that it's not safe to call the system malloc */
623
+ /* between fork() and exec(). Thus we're doing no worse than it. */
624
+
625
+ /* Called before a fork() */
626
+ void GC_fork_prepare_proc(void)
627
+ {
628
+ /* Acquire all relevant locks, so that after releasing the locks */
629
+ /* the child will see a consistent state in which monitor */
630
+ /* invariants hold. Unfortunately, we can't acquire libc locks */
631
+ /* we might need, and there seems to be no guarantee that libc */
632
+ /* must install a suitable fork handler. */
633
+ /* Wait for an ongoing GC to finish, since we can't finish it in */
634
+ /* the (one remaining thread in) the child. */
635
+ LOCK();
636
+ # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
637
+ GC_wait_for_reclaim();
638
+ # endif
639
+ GC_wait_for_gc_completion(TRUE);
640
+ # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
641
+ GC_acquire_mark_lock();
642
+ # endif
643
+ }
644
+
645
+ /* Called in parent after a fork() */
646
+ void GC_fork_parent_proc(void)
647
+ {
648
+ # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
649
+ GC_release_mark_lock();
650
+ # endif
651
+ UNLOCK();
652
+ }
653
+
654
+ /* Called in child after a fork() */
655
+ void GC_fork_child_proc(void)
656
+ {
657
+ /* Clean up the thread table, so that just our thread is left. */
658
+ # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
659
+ GC_release_mark_lock();
660
+ # endif
661
+ GC_remove_all_threads_but_me();
662
+ # ifdef PARALLEL_MARK
663
+ /* Turn off parallel marking in the child, since we are probably */
664
+ /* just going to exec, and we would have to restart mark threads. */
665
+ GC_markers = 1;
666
+ GC_parallel = FALSE;
667
+ # endif /* PARALLEL_MARK */
668
+ UNLOCK();
669
+ }
670
+ #endif /* HANDLE_FORK */
671
+
672
+ #if defined(GC_DGUX386_THREADS)
673
+ /* Return the number of processors, or i<= 0 if it can't be determined. */
674
+ int GC_get_nprocs(void)
675
+ {
676
+ /* <takis@XFree86.Org> */
677
+ int numCpus;
678
+ struct dg_sys_info_pm_info pm_sysinfo;
679
+ int status =0;
680
+
681
+ status = dg_sys_info((long int *) &pm_sysinfo,
682
+ DG_SYS_INFO_PM_INFO_TYPE, DG_SYS_INFO_PM_CURRENT_VERSION);
683
+ if (status < 0)
684
+ /* set -1 for error */
685
+ numCpus = -1;
686
+ else
687
+ /* Active CPUs */
688
+ numCpus = pm_sysinfo.idle_vp_count;
689
+
690
+ # ifdef DEBUG_THREADS
691
+ GC_printf("Number of active CPUs in this system: %d\n", numCpus);
692
+ # endif
693
+ return(numCpus);
694
+ }
695
+ #endif /* GC_DGUX386_THREADS */
696
+
697
+ #if defined(GC_NETBSD_THREADS)
698
+ static int get_ncpu(void)
699
+ {
700
+ int mib[] = {CTL_HW,HW_NCPU};
701
+ int res;
702
+ size_t len = sizeof(res);
703
+
704
+ sysctl(mib, sizeof(mib)/sizeof(int), &res, &len, NULL, 0);
705
+ return res;
706
+ }
707
+ #endif /* GC_NETBSD_THREADS */
708
+
709
+ # if defined(GC_LINUX_THREADS) && defined(INCLUDE_LINUX_THREAD_DESCR)
710
+ __thread int dummy_thread_local;
711
+ # endif
712
+
713
+ /* We hold the allocation lock. */
714
+ void GC_thr_init(void)
715
+ {
716
+ # ifndef GC_DARWIN_THREADS
717
+ int dummy;
718
+ # endif
719
+ GC_thread t;
720
+
721
+ if (GC_thr_initialized) return;
722
+ GC_thr_initialized = TRUE;
723
+
724
+ # ifdef HANDLE_FORK
725
+ /* Prepare for a possible fork. */
726
+ pthread_atfork(GC_fork_prepare_proc, GC_fork_parent_proc,
727
+ GC_fork_child_proc);
728
+ # endif /* HANDLE_FORK */
729
+ # if defined(INCLUDE_LINUX_THREAD_DESCR)
730
+ /* Explicitly register the region including the address */
731
+ /* of a thread local variable. This should included thread */
732
+ /* locals for the main thread, except for those allocated */
733
+ /* in response to dlopen calls. */
734
+ {
735
+ ptr_t thread_local_addr = (ptr_t)(&dummy_thread_local);
736
+ ptr_t main_thread_start, main_thread_end;
737
+ if (!GC_enclosing_mapping(thread_local_addr, &main_thread_start,
738
+ &main_thread_end)) {
739
+ ABORT("Failed to find mapping for main thread thread locals");
740
+ }
741
+ GC_add_roots_inner(main_thread_start, main_thread_end, FALSE);
742
+ }
743
+ # endif
744
+ /* Add the initial thread, so we can stop it. */
745
+ t = GC_new_thread(pthread_self());
746
+ # ifdef GC_DARWIN_THREADS
747
+ t -> stop_info.mach_thread = mach_thread_self();
748
+ # else
749
+ t -> stop_info.stack_ptr = (ptr_t)(&dummy);
750
+ # endif
751
+ t -> flags = DETACHED | MAIN_THREAD;
752
+
753
+ GC_stop_init();
754
+
755
+ /* Set GC_nprocs. */
756
+ {
757
+ char * nprocs_string = GETENV("GC_NPROCS");
758
+ GC_nprocs = -1;
759
+ if (nprocs_string != NULL) GC_nprocs = atoi(nprocs_string);
760
+ }
761
+ if (GC_nprocs <= 0) {
762
+ # if defined(GC_HPUX_THREADS)
763
+ GC_nprocs = pthread_num_processors_np();
764
+ # endif
765
+ # if defined(GC_OSF1_THREADS) || defined(GC_AIX_THREADS) \
766
+ || defined(GC_SOLARIS_THREADS)
767
+ GC_nprocs = sysconf(_SC_NPROCESSORS_ONLN);
768
+ if (GC_nprocs <= 0) GC_nprocs = 1;
769
+ # endif
770
+ # if defined(GC_IRIX_THREADS)
771
+ GC_nprocs = sysconf(_SC_NPROC_ONLN);
772
+ if (GC_nprocs <= 0) GC_nprocs = 1;
773
+ # endif
774
+ # if defined(GC_NETBSD_THREADS)
775
+ GC_nprocs = get_ncpu();
776
+ # endif
777
+ # if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS)
778
+ int ncpus = 1;
779
+ size_t len = sizeof(ncpus);
780
+ sysctl((int[2]) {CTL_HW, HW_NCPU}, 2, &ncpus, &len, NULL, 0);
781
+ GC_nprocs = ncpus;
782
+ # endif
783
+ # if defined(GC_LINUX_THREADS) || defined(GC_DGUX386_THREADS)
784
+ GC_nprocs = GC_get_nprocs();
785
+ # endif
786
+ # if defined(GC_GNU_THREADS)
787
+ if (GC_nprocs <= 0) GC_nprocs = 1;
788
+ # endif
789
+ }
790
+ if (GC_nprocs <= 0) {
791
+ WARN("GC_get_nprocs() returned %ld\n", GC_nprocs);
792
+ GC_nprocs = 2;
793
+ # ifdef PARALLEL_MARK
794
+ GC_markers = 1;
795
+ # endif
796
+ } else {
797
+ # ifdef PARALLEL_MARK
798
+ {
799
+ char * markers_string = GETENV("GC_MARKERS");
800
+ if (markers_string != NULL) {
801
+ GC_markers = atoi(markers_string);
802
+ } else {
803
+ GC_markers = GC_nprocs;
804
+ }
805
+ }
806
+ # endif
807
+ }
808
+ # ifdef PARALLEL_MARK
809
+ if (GC_print_stats) {
810
+ GC_log_printf("Number of processors = %ld, "
811
+ "number of marker threads = %ld\n", GC_nprocs, GC_markers);
812
+ }
813
+ if (GC_markers == 1) {
814
+ GC_parallel = FALSE;
815
+ if (GC_print_stats) {
816
+ GC_log_printf(
817
+ "Single marker thread, turning off parallel marking\n");
818
+ }
819
+ } else {
820
+ GC_parallel = TRUE;
821
+ /* Disable true incremental collection, but generational is OK. */
822
+ GC_time_limit = GC_TIME_UNLIMITED;
823
+ }
824
+ /* If we are using a parallel marker, actually start helper threads. */
825
+ if (GC_parallel) start_mark_threads();
826
+ # endif
827
+ }
828
+
829
+
830
+ /* Perform all initializations, including those that */
831
+ /* may require allocation. */
832
+ /* Called without allocation lock. */
833
+ /* Must be called before a second thread is created. */
834
+ /* Did we say it's called without the allocation lock? */
835
+ void GC_init_parallel(void)
836
+ {
837
+ if (parallel_initialized) return;
838
+ parallel_initialized = TRUE;
839
+
840
+ /* GC_init() calls us back, so set flag first. */
841
+ if (!GC_is_initialized) GC_init();
842
+ /* Initialize thread local free lists if used. */
843
+ # if defined(THREAD_LOCAL_ALLOC)
844
+ LOCK();
845
+ GC_init_thread_local(&(GC_lookup_thread(pthread_self())->tlfs));
846
+ UNLOCK();
847
+ # endif
848
+ }
849
+
850
+
851
+ #if !defined(GC_DARWIN_THREADS)
852
+ int WRAP_FUNC(pthread_sigmask)(int how, const sigset_t *set, sigset_t *oset)
853
+ {
854
+ sigset_t fudged_set;
855
+
856
+ INIT_REAL_SYMS();
857
+ if (set != NULL && (how == SIG_BLOCK || how == SIG_SETMASK)) {
858
+ fudged_set = *set;
859
+ sigdelset(&fudged_set, SIG_SUSPEND);
860
+ set = &fudged_set;
861
+ }
862
+ return(REAL_FUNC(pthread_sigmask)(how, set, oset));
863
+ }
864
+ #endif /* !GC_DARWIN_THREADS */
865
+
866
+ /* Wrapper for functions that are likely to block for an appreciable */
867
+ /* length of time. */
868
+
869
+ struct blocking_data {
870
+ void (*fn)(void *);
871
+ void *arg;
872
+ };
873
+
874
+ static void GC_do_blocking_inner(ptr_t data, void * context) {
875
+ struct blocking_data * d = (struct blocking_data *) data;
876
+ GC_thread me;
877
+ LOCK();
878
+ me = GC_lookup_thread(pthread_self());
879
+ GC_ASSERT(!(me -> thread_blocked));
880
+ # ifdef SPARC
881
+ me -> stop_info.stack_ptr = GC_save_regs_in_stack();
882
+ # elif !defined(GC_DARWIN_THREADS)
883
+ me -> stop_info.stack_ptr = GC_approx_sp();
884
+ # endif
885
+ # ifdef IA64
886
+ me -> backing_store_ptr = GC_save_regs_in_stack();
887
+ # endif
888
+ me -> thread_blocked = TRUE;
889
+ /* Save context here if we want to support precise stack marking */
890
+ UNLOCK();
891
+ (d -> fn)(d -> arg);
892
+ LOCK(); /* This will block if the world is stopped. */
893
+ me -> thread_blocked = FALSE;
894
+ UNLOCK();
895
+ }
896
+
897
+ void GC_do_blocking(void (*fn)(void *), void *arg) {
898
+ struct blocking_data my_data;
899
+
900
+ my_data.fn = fn;
901
+ my_data.arg = arg;
902
+ GC_with_callee_saves_pushed(GC_do_blocking_inner, (ptr_t)(&my_data));
903
+ }
904
+
905
+ struct start_info {
906
+ void *(*start_routine)(void *);
907
+ void *arg;
908
+ word flags;
909
+ sem_t registered; /* 1 ==> in our thread table, but */
910
+ /* parent hasn't yet noticed. */
911
+ };
912
+
913
+ int GC_unregister_my_thread(void)
914
+ {
915
+ GC_thread me;
916
+
917
+ LOCK();
918
+ /* Wait for any GC that may be marking from our stack to */
919
+ /* complete before we remove this thread. */
920
+ GC_wait_for_gc_completion(FALSE);
921
+ me = GC_lookup_thread(pthread_self());
922
+ # if defined(THREAD_LOCAL_ALLOC)
923
+ GC_destroy_thread_local(&(me->tlfs));
924
+ # endif
925
+ if (me -> flags & DETACHED) {
926
+ GC_delete_thread(pthread_self());
927
+ } else {
928
+ me -> flags |= FINISHED;
929
+ }
930
+ # if defined(THREAD_LOCAL_ALLOC)
931
+ GC_remove_specific(GC_thread_key);
932
+ # endif
933
+ UNLOCK();
934
+ return GC_SUCCESS;
935
+ }
936
+
937
+ /* Called at thread exit. */
938
+ /* Never called for main thread. That's OK, since it */
939
+ /* results in at most a tiny one-time leak. And */
940
+ /* linuxthreads doesn't reclaim the main threads */
941
+ /* resources or id anyway. */
942
+ void GC_thread_exit_proc(void *arg)
943
+ {
944
+ GC_unregister_my_thread();
945
+ }
946
+
947
+ int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval)
948
+ {
949
+ int result;
950
+ GC_thread thread_gc_id;
951
+
952
+ INIT_REAL_SYMS();
953
+ LOCK();
954
+ thread_gc_id = GC_lookup_thread(thread);
955
+ /* This is guaranteed to be the intended one, since the thread id */
956
+ /* cant have been recycled by pthreads. */
957
+ UNLOCK();
958
+ result = REAL_FUNC(pthread_join)(thread, retval);
959
+ # if defined (GC_FREEBSD_THREADS)
960
+ /* On FreeBSD, the wrapped pthread_join() sometimes returns (what
961
+ appears to be) a spurious EINTR which caused the test and real code
962
+ to gratuitously fail. Having looked at system pthread library source
963
+ code, I see how this return code may be generated. In one path of
964
+ code, pthread_join() just returns the errno setting of the thread
965
+ being joined. This does not match the POSIX specification or the
966
+ local man pages thus I have taken the liberty to catch this one
967
+ spurious return value properly conditionalized on GC_FREEBSD_THREADS. */
968
+ if (result == EINTR) result = 0;
969
+ # endif
970
+ if (result == 0) {
971
+ LOCK();
972
+ /* Here the pthread thread id may have been recycled. */
973
+ GC_delete_gc_thread(thread_gc_id);
974
+ UNLOCK();
975
+ }
976
+ return result;
977
+ }
978
+
979
+ int
980
+ WRAP_FUNC(pthread_detach)(pthread_t thread)
981
+ {
982
+ int result;
983
+ GC_thread thread_gc_id;
984
+
985
+ INIT_REAL_SYMS();
986
+ LOCK();
987
+ thread_gc_id = GC_lookup_thread(thread);
988
+ UNLOCK();
989
+ result = REAL_FUNC(pthread_detach)(thread);
990
+ if (result == 0) {
991
+ LOCK();
992
+ thread_gc_id -> flags |= DETACHED;
993
+ /* Here the pthread thread id may have been recycled. */
994
+ if (thread_gc_id -> flags & FINISHED) {
995
+ GC_delete_gc_thread(thread_gc_id);
996
+ }
997
+ UNLOCK();
998
+ }
999
+ return result;
1000
+ }
1001
+
1002
+ GC_bool GC_in_thread_creation = FALSE; /* Protected by allocation lock. */
1003
+
1004
+ GC_thread GC_register_my_thread_inner(struct GC_stack_base *sb,
1005
+ pthread_t my_pthread)
1006
+ {
1007
+ GC_thread me;
1008
+
1009
+ GC_in_thread_creation = TRUE; /* OK to collect from unknown thread. */
1010
+ me = GC_new_thread(my_pthread);
1011
+ GC_in_thread_creation = FALSE;
1012
+ # ifdef GC_DARWIN_THREADS
1013
+ me -> stop_info.mach_thread = mach_thread_self();
1014
+ # else
1015
+ me -> stop_info.stack_ptr = sb -> mem_base;
1016
+ # endif
1017
+ me -> stack_end = sb -> mem_base;
1018
+ # ifdef IA64
1019
+ me -> backing_store_end = sb -> reg_base;
1020
+ # endif /* IA64 */
1021
+ return me;
1022
+ }
1023
+
1024
+ int GC_register_my_thread(struct GC_stack_base *sb)
1025
+ {
1026
+ pthread_t my_pthread = pthread_self();
1027
+ GC_thread me;
1028
+
1029
+ LOCK();
1030
+ me = GC_lookup_thread(my_pthread);
1031
+ if (0 == me) {
1032
+ me = GC_register_my_thread_inner(sb, my_pthread);
1033
+ me -> flags |= DETACHED;
1034
+ /* Treat as detached, since we do not need to worry about */
1035
+ /* pointer results. */
1036
+ UNLOCK();
1037
+ return GC_SUCCESS;
1038
+ } else {
1039
+ UNLOCK();
1040
+ return GC_DUPLICATE;
1041
+ }
1042
+ }
1043
+
1044
+ void * GC_inner_start_routine(struct GC_stack_base *sb, void * arg)
1045
+ {
1046
+ struct start_info * si = arg;
1047
+ void * result;
1048
+ GC_thread me;
1049
+ pthread_t my_pthread;
1050
+ void *(*start)(void *);
1051
+ void *start_arg;
1052
+
1053
+ my_pthread = pthread_self();
1054
+ # ifdef DEBUG_THREADS
1055
+ GC_printf("Starting thread 0x%x\n", (unsigned)my_pthread);
1056
+ GC_printf("pid = %ld\n", (long) getpid());
1057
+ GC_printf("sp = 0x%lx\n", (long) &arg);
1058
+ # endif
1059
+ LOCK();
1060
+ me = GC_register_my_thread_inner(sb, my_pthread);
1061
+ me -> flags = si -> flags;
1062
+ UNLOCK();
1063
+ start = si -> start_routine;
1064
+ # ifdef DEBUG_THREADS
1065
+ GC_printf("start_routine = %p\n", (void *)start);
1066
+ # endif
1067
+ start_arg = si -> arg;
1068
+ sem_post(&(si -> registered)); /* Last action on si. */
1069
+ /* OK to deallocate. */
1070
+ pthread_cleanup_push(GC_thread_exit_proc, 0);
1071
+ # if defined(THREAD_LOCAL_ALLOC)
1072
+ LOCK();
1073
+ GC_init_thread_local(&(me->tlfs));
1074
+ UNLOCK();
1075
+ # endif
1076
+ result = (*start)(start_arg);
1077
+ # if DEBUG_THREADS
1078
+ GC_printf("Finishing thread 0x%x\n", (unsigned)pthread_self());
1079
+ # endif
1080
+ me -> status = result;
1081
+ pthread_cleanup_pop(1);
1082
+ /* Cleanup acquires lock, ensuring that we can't exit */
1083
+ /* while a collection that thinks we're alive is trying to stop */
1084
+ /* us. */
1085
+ return(result);
1086
+ }
1087
+
1088
+ void * GC_start_routine(void * arg)
1089
+ {
1090
+ # ifdef INCLUDE_LINUX_THREAD_DESCR
1091
+ struct GC_stack_base sb;
1092
+
1093
+ # ifdef REDIRECT_MALLOC
1094
+ /* GC_get_stack_base may call pthread_getattr_np, which can */
1095
+ /* unfortunately call realloc, which may allocate from an */
1096
+ /* unregistered thread. This is unpleasant, since it might */
1097
+ /* force heap growth. */
1098
+ GC_disable();
1099
+ # endif
1100
+ if (GC_get_stack_base(&sb) != GC_SUCCESS)
1101
+ ABORT("Failed to get thread stack base.");
1102
+ # ifdef REDIRECT_MALLOC
1103
+ GC_enable();
1104
+ # endif
1105
+ return GC_inner_start_routine(&sb, arg);
1106
+ # else
1107
+ return GC_call_with_stack_base(GC_inner_start_routine, arg);
1108
+ # endif
1109
+ }
1110
+
1111
+ int
1112
+ WRAP_FUNC(pthread_create)(pthread_t *new_thread,
1113
+ const pthread_attr_t *attr,
1114
+ void *(*start_routine)(void *), void *arg)
1115
+ {
1116
+ int result;
1117
+ int detachstate;
1118
+ word my_flags = 0;
1119
+ struct start_info * si;
1120
+ /* This is otherwise saved only in an area mmapped by the thread */
1121
+ /* library, which isn't visible to the collector. */
1122
+
1123
+ /* We resist the temptation to muck with the stack size here, */
1124
+ /* even if the default is unreasonably small. That's the client's */
1125
+ /* responsibility. */
1126
+
1127
+ INIT_REAL_SYMS();
1128
+ LOCK();
1129
+ si = (struct start_info *)GC_INTERNAL_MALLOC(sizeof(struct start_info),
1130
+ NORMAL);
1131
+ UNLOCK();
1132
+ if (!parallel_initialized) GC_init_parallel();
1133
+ if (0 == si) return(ENOMEM);
1134
+ sem_init(&(si -> registered), 0, 0);
1135
+ si -> start_routine = start_routine;
1136
+ si -> arg = arg;
1137
+ LOCK();
1138
+ if (!GC_thr_initialized) GC_thr_init();
1139
+ # ifdef GC_ASSERTIONS
1140
+ {
1141
+ size_t stack_size = 0;
1142
+ if (NULL != attr) {
1143
+ pthread_attr_getstacksize(attr, &stack_size);
1144
+ }
1145
+ if (0 == stack_size) {
1146
+ pthread_attr_t my_attr;
1147
+ pthread_attr_init(&my_attr);
1148
+ pthread_attr_getstacksize(&my_attr, &stack_size);
1149
+ }
1150
+ /* On Solaris 10, with default attr initialization, */
1151
+ /* stack_size remains 0. Fudge it. */
1152
+ if (0 == stack_size) {
1153
+ # ifndef SOLARIS
1154
+ WARN("Failed to get stack size for assertion checking\n", 0);
1155
+ # endif
1156
+ stack_size = 1000000;
1157
+ }
1158
+ # ifdef PARALLEL_MARK
1159
+ GC_ASSERT(stack_size >= (8*HBLKSIZE*sizeof(word)));
1160
+ # else
1161
+ /* FreeBSD-5.3/Alpha: default pthread stack is 64K, */
1162
+ /* HBLKSIZE=8192, sizeof(word)=8 */
1163
+ GC_ASSERT(stack_size >= 65536);
1164
+ # endif
1165
+ /* Our threads may need to do some work for the GC. */
1166
+ /* Ridiculously small threads won't work, and they */
1167
+ /* probably wouldn't work anyway. */
1168
+ }
1169
+ # endif
1170
+ if (NULL == attr) {
1171
+ detachstate = PTHREAD_CREATE_JOINABLE;
1172
+ } else {
1173
+ pthread_attr_getdetachstate(attr, &detachstate);
1174
+ }
1175
+ if (PTHREAD_CREATE_DETACHED == detachstate) my_flags |= DETACHED;
1176
+ si -> flags = my_flags;
1177
+ UNLOCK();
1178
+ # ifdef DEBUG_THREADS
1179
+ GC_printf("About to start new thread from thread 0x%x\n",
1180
+ (unsigned)pthread_self());
1181
+ # endif
1182
+ GC_need_to_lock = TRUE;
1183
+
1184
+ result = REAL_FUNC(pthread_create)(new_thread, attr, GC_start_routine, si);
1185
+
1186
+ # ifdef DEBUG_THREADS
1187
+ GC_printf("Started thread 0x%x\n", (unsigned)(*new_thread));
1188
+ # endif
1189
+ /* Wait until child has been added to the thread table. */
1190
+ /* This also ensures that we hold onto si until the child is done */
1191
+ /* with it. Thus it doesn't matter whether it is otherwise */
1192
+ /* visible to the collector. */
1193
+ if (0 == result) {
1194
+ while (0 != sem_wait(&(si -> registered))) {
1195
+ if (EINTR != errno) ABORT("sem_wait failed");
1196
+ }
1197
+ }
1198
+ sem_destroy(&(si -> registered));
1199
+ LOCK();
1200
+ GC_INTERNAL_FREE(si);
1201
+ UNLOCK();
1202
+
1203
+ return(result);
1204
+ }
1205
+
1206
+ /* Spend a few cycles in a way that can't introduce contention with */
1207
+ /* othre threads. */
1208
+ void GC_pause(void)
1209
+ {
1210
+ int i;
1211
+ # if !defined(__GNUC__) || defined(__INTEL_COMPILER)
1212
+ volatile word dummy = 0;
1213
+ # endif
1214
+
1215
+ for (i = 0; i < 10; ++i) {
1216
+ # if defined(__GNUC__) && !defined(__INTEL_COMPILER)
1217
+ __asm__ __volatile__ (" " : : : "memory");
1218
+ # else
1219
+ /* Something that's unlikely to be optimized away. */
1220
+ GC_noop(++dummy);
1221
+ # endif
1222
+ }
1223
+ }
1224
+
1225
+ #define SPIN_MAX 128 /* Maximum number of calls to GC_pause before */
1226
+ /* give up. */
1227
+
1228
+ volatile GC_bool GC_collecting = 0;
1229
+ /* A hint that we're in the collector and */
1230
+ /* holding the allocation lock for an */
1231
+ /* extended period. */
1232
+
1233
+ #if !defined(USE_SPIN_LOCK) || defined(PARALLEL_MARK)
1234
+ /* If we don't want to use the below spinlock implementation, either */
1235
+ /* because we don't have a GC_test_and_set implementation, or because */
1236
+ /* we don't want to risk sleeping, we can still try spinning on */
1237
+ /* pthread_mutex_trylock for a while. This appears to be very */
1238
+ /* beneficial in many cases. */
1239
+ /* I suspect that under high contention this is nearly always better */
1240
+ /* than the spin lock. But it's a bit slower on a uniprocessor. */
1241
+ /* Hence we still default to the spin lock. */
1242
+ /* This is also used to acquire the mark lock for the parallel */
1243
+ /* marker. */
1244
+
1245
+ /* Here we use a strict exponential backoff scheme. I don't know */
1246
+ /* whether that's better or worse than the above. We eventually */
1247
+ /* yield by calling pthread_mutex_lock(); it never makes sense to */
1248
+ /* explicitly sleep. */
1249
+
1250
+ #define LOCK_STATS
1251
+ #ifdef LOCK_STATS
1252
+ unsigned long GC_spin_count = 0;
1253
+ unsigned long GC_block_count = 0;
1254
+ unsigned long GC_unlocked_count = 0;
1255
+ #endif
1256
+
1257
+ void GC_generic_lock(pthread_mutex_t * lock)
1258
+ {
1259
+ #ifndef NO_PTHREAD_TRYLOCK
1260
+ unsigned pause_length = 1;
1261
+ unsigned i;
1262
+
1263
+ if (0 == pthread_mutex_trylock(lock)) {
1264
+ # ifdef LOCK_STATS
1265
+ ++GC_unlocked_count;
1266
+ # endif
1267
+ return;
1268
+ }
1269
+ for (; pause_length <= SPIN_MAX; pause_length <<= 1) {
1270
+ for (i = 0; i < pause_length; ++i) {
1271
+ GC_pause();
1272
+ }
1273
+ switch(pthread_mutex_trylock(lock)) {
1274
+ case 0:
1275
+ # ifdef LOCK_STATS
1276
+ ++GC_spin_count;
1277
+ # endif
1278
+ return;
1279
+ case EBUSY:
1280
+ break;
1281
+ default:
1282
+ ABORT("Unexpected error from pthread_mutex_trylock");
1283
+ }
1284
+ }
1285
+ #endif /* !NO_PTHREAD_TRYLOCK */
1286
+ # ifdef LOCK_STATS
1287
+ ++GC_block_count;
1288
+ # endif
1289
+ pthread_mutex_lock(lock);
1290
+ }
1291
+
1292
+ #endif /* !USE_SPIN_LOCK || PARALLEL_MARK */
1293
+
1294
+ #if defined(USE_SPIN_LOCK)
1295
+
1296
+ /* Reasonably fast spin locks. Basically the same implementation */
1297
+ /* as STL alloc.h. This isn't really the right way to do this. */
1298
+ /* but until the POSIX scheduling mess gets straightened out ... */
1299
+
1300
+ volatile AO_TS_t GC_allocate_lock = 0;
1301
+
1302
+
1303
+ void GC_lock(void)
1304
+ {
1305
+ # define low_spin_max 30 /* spin cycles if we suspect uniprocessor */
1306
+ # define high_spin_max SPIN_MAX /* spin cycles for multiprocessor */
1307
+ static unsigned spin_max = low_spin_max;
1308
+ unsigned my_spin_max;
1309
+ static unsigned last_spins = 0;
1310
+ unsigned my_last_spins;
1311
+ int i;
1312
+
1313
+ if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_CLEAR) {
1314
+ return;
1315
+ }
1316
+ my_spin_max = spin_max;
1317
+ my_last_spins = last_spins;
1318
+ for (i = 0; i < my_spin_max; i++) {
1319
+ if (GC_collecting || GC_nprocs == 1) goto yield;
1320
+ if (i < my_last_spins/2) {
1321
+ GC_pause();
1322
+ continue;
1323
+ }
1324
+ if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_CLEAR) {
1325
+ /*
1326
+ * got it!
1327
+ * Spinning worked. Thus we're probably not being scheduled
1328
+ * against the other process with which we were contending.
1329
+ * Thus it makes sense to spin longer the next time.
1330
+ */
1331
+ last_spins = i;
1332
+ spin_max = high_spin_max;
1333
+ return;
1334
+ }
1335
+ }
1336
+ /* We are probably being scheduled against the other process. Sleep. */
1337
+ spin_max = low_spin_max;
1338
+ yield:
1339
+ for (i = 0;; ++i) {
1340
+ if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_CLEAR) {
1341
+ return;
1342
+ }
1343
+ # define SLEEP_THRESHOLD 12
1344
+ /* Under Linux very short sleeps tend to wait until */
1345
+ /* the current time quantum expires. On old Linux */
1346
+ /* kernels nanosleep(<= 2ms) just spins under Linux. */
1347
+ /* (Under 2.4, this happens only for real-time */
1348
+ /* processes.) We want to minimize both behaviors */
1349
+ /* here. */
1350
+ if (i < SLEEP_THRESHOLD) {
1351
+ sched_yield();
1352
+ } else {
1353
+ struct timespec ts;
1354
+
1355
+ if (i > 24) i = 24;
1356
+ /* Don't wait for more than about 15msecs, even */
1357
+ /* under extreme contention. */
1358
+ ts.tv_sec = 0;
1359
+ ts.tv_nsec = 1 << i;
1360
+ nanosleep(&ts, 0);
1361
+ }
1362
+ }
1363
+ }
1364
+
1365
+ #else /* !USE_SPINLOCK */
1366
+ void GC_lock(void)
1367
+ {
1368
+ #ifndef NO_PTHREAD_TRYLOCK
1369
+ if (1 == GC_nprocs || GC_collecting) {
1370
+ pthread_mutex_lock(&GC_allocate_ml);
1371
+ } else {
1372
+ GC_generic_lock(&GC_allocate_ml);
1373
+ }
1374
+ #else /* !NO_PTHREAD_TRYLOCK */
1375
+ pthread_mutex_lock(&GC_allocate_ml);
1376
+ #endif /* !NO_PTHREAD_TRYLOCK */
1377
+ }
1378
+
1379
+ #endif /* !USE_SPINLOCK */
1380
+
1381
+ #if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
1382
+
1383
+ #ifdef GC_ASSERTIONS
1384
+ unsigned long GC_mark_lock_holder = NO_THREAD;
1385
+ #endif
1386
+
1387
+ #if 0
1388
+ /* Ugly workaround for a linux threads bug in the final versions */
1389
+ /* of glibc2.1. Pthread_mutex_trylock sets the mutex owner */
1390
+ /* field even when it fails to acquire the mutex. This causes */
1391
+ /* pthread_cond_wait to die. Remove for glibc2.2. */
1392
+ /* According to the man page, we should use */
1393
+ /* PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, but that isn't actually */
1394
+ /* defined. */
1395
+ static pthread_mutex_t mark_mutex =
1396
+ {0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, {0, 0}};
1397
+ #else
1398
+ static pthread_mutex_t mark_mutex = PTHREAD_MUTEX_INITIALIZER;
1399
+ #endif
1400
+
1401
+ static pthread_cond_t builder_cv = PTHREAD_COND_INITIALIZER;
1402
+
1403
+ void GC_acquire_mark_lock(void)
1404
+ {
1405
+ /*
1406
+ if (pthread_mutex_lock(&mark_mutex) != 0) {
1407
+ ABORT("pthread_mutex_lock failed");
1408
+ }
1409
+ */
1410
+ GC_generic_lock(&mark_mutex);
1411
+ # ifdef GC_ASSERTIONS
1412
+ GC_mark_lock_holder = NUMERIC_THREAD_ID(pthread_self());
1413
+ # endif
1414
+ }
1415
+
1416
+ void GC_release_mark_lock(void)
1417
+ {
1418
+ GC_ASSERT(GC_mark_lock_holder == NUMERIC_THREAD_ID(pthread_self()));
1419
+ # ifdef GC_ASSERTIONS
1420
+ GC_mark_lock_holder = NO_THREAD;
1421
+ # endif
1422
+ if (pthread_mutex_unlock(&mark_mutex) != 0) {
1423
+ ABORT("pthread_mutex_unlock failed");
1424
+ }
1425
+ }
1426
+
1427
+ /* Collector must wait for a freelist builders for 2 reasons: */
1428
+ /* 1) Mark bits may still be getting examined without lock. */
1429
+ /* 2) Partial free lists referenced only by locals may not be scanned */
1430
+ /* correctly, e.g. if they contain "pointer-free" objects, since the */
1431
+ /* free-list link may be ignored. */
1432
+ void GC_wait_builder(void)
1433
+ {
1434
+ GC_ASSERT(GC_mark_lock_holder == NUMERIC_THREAD_ID(pthread_self()));
1435
+ # ifdef GC_ASSERTIONS
1436
+ GC_mark_lock_holder = NO_THREAD;
1437
+ # endif
1438
+ if (pthread_cond_wait(&builder_cv, &mark_mutex) != 0) {
1439
+ ABORT("pthread_cond_wait failed");
1440
+ }
1441
+ GC_ASSERT(GC_mark_lock_holder == NO_THREAD);
1442
+ # ifdef GC_ASSERTIONS
1443
+ GC_mark_lock_holder = NUMERIC_THREAD_ID(pthread_self());
1444
+ # endif
1445
+ }
1446
+
1447
+ void GC_wait_for_reclaim(void)
1448
+ {
1449
+ GC_acquire_mark_lock();
1450
+ while (GC_fl_builder_count > 0) {
1451
+ GC_wait_builder();
1452
+ }
1453
+ GC_release_mark_lock();
1454
+ }
1455
+
1456
+ void GC_notify_all_builder(void)
1457
+ {
1458
+ GC_ASSERT(GC_mark_lock_holder == NUMERIC_THREAD_ID(pthread_self()));
1459
+ if (pthread_cond_broadcast(&builder_cv) != 0) {
1460
+ ABORT("pthread_cond_broadcast failed");
1461
+ }
1462
+ }
1463
+
1464
+ #endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
1465
+
1466
+ #ifdef PARALLEL_MARK
1467
+
1468
+ static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER;
1469
+
1470
+ void GC_wait_marker(void)
1471
+ {
1472
+ GC_ASSERT(GC_mark_lock_holder == NUMERIC_THREAD_ID(pthread_self()));
1473
+ # ifdef GC_ASSERTIONS
1474
+ GC_mark_lock_holder = NO_THREAD;
1475
+ # endif
1476
+ if (pthread_cond_wait(&mark_cv, &mark_mutex) != 0) {
1477
+ ABORT("pthread_cond_wait failed");
1478
+ }
1479
+ GC_ASSERT(GC_mark_lock_holder == NO_THREAD);
1480
+ # ifdef GC_ASSERTIONS
1481
+ GC_mark_lock_holder = NUMERIC_THREAD_ID(pthread_self());
1482
+ # endif
1483
+ }
1484
+
1485
+ void GC_notify_all_marker(void)
1486
+ {
1487
+ if (pthread_cond_broadcast(&mark_cv) != 0) {
1488
+ ABORT("pthread_cond_broadcast failed");
1489
+ }
1490
+ }
1491
+
1492
+ #endif /* PARALLEL_MARK */
1493
+
1494
+ # endif /* GC_LINUX_THREADS and friends */
1495
+
mosesdecoder/jam-files/engine/boehm_gc/reclaim.c ADDED
@@ -0,0 +1,608 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
3
+ * Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved.
4
+ * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
5
+ * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
6
+ *
7
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
8
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
9
+ *
10
+ * Permission is hereby granted to use or copy this program
11
+ * for any purpose, provided the above notices are retained on all copies.
12
+ * Permission to modify the code and to distribute modified code is granted,
13
+ * provided the above notices are retained, and a notice that the code was
14
+ * modified is included with the above copyright notice.
15
+ */
16
+
17
+ #include <stdio.h>
18
+ #include "private/gc_priv.h"
19
+
20
+ signed_word GC_bytes_found = 0;
21
+ /* Number of bytes of memory reclaimed */
22
+
23
+ #if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
24
+ word GC_fl_builder_count = 0;
25
+ /* Number of threads currently building free lists without */
26
+ /* holding GC lock. It is not safe to collect if this is */
27
+ /* nonzero. */
28
+ #endif /* PARALLEL_MARK */
29
+
30
+ /* We defer printing of leaked objects until we're done with the GC */
31
+ /* cycle, since the routine for printing objects needs to run outside */
32
+ /* the collector, e.g. without the allocation lock. */
33
+ #define MAX_LEAKED 40
34
+ ptr_t GC_leaked[MAX_LEAKED];
35
+ unsigned GC_n_leaked = 0;
36
+
37
+ GC_bool GC_have_errors = FALSE;
38
+
39
+ void GC_add_leaked(ptr_t leaked)
40
+ {
41
+ if (GC_n_leaked < MAX_LEAKED) {
42
+ GC_have_errors = TRUE;
43
+ GC_leaked[GC_n_leaked++] = leaked;
44
+ /* Make sure it's not reclaimed this cycle */
45
+ GC_set_mark_bit(leaked);
46
+ }
47
+ }
48
+
49
+ static GC_bool printing_errors = FALSE;
50
+ /* Print all objects on the list after printing any smashed objs. */
51
+ /* Clear both lists. */
52
+ void GC_print_all_errors ()
53
+ {
54
+ unsigned i;
55
+
56
+ LOCK();
57
+ if (printing_errors) {
58
+ UNLOCK();
59
+ return;
60
+ }
61
+ printing_errors = TRUE;
62
+ UNLOCK();
63
+ if (GC_debugging_started) GC_print_all_smashed();
64
+ for (i = 0; i < GC_n_leaked; ++i) {
65
+ ptr_t p = GC_leaked[i];
66
+ if (HDR(p) -> hb_obj_kind == PTRFREE) {
67
+ GC_err_printf("Leaked atomic object at ");
68
+ } else {
69
+ GC_err_printf("Leaked composite object at ");
70
+ }
71
+ GC_print_heap_obj(p);
72
+ GC_err_printf("\n");
73
+ GC_free(p);
74
+ GC_leaked[i] = 0;
75
+ }
76
+ GC_n_leaked = 0;
77
+ printing_errors = FALSE;
78
+ }
79
+
80
+
81
+ /*
82
+ * reclaim phase
83
+ *
84
+ */
85
+
86
+
87
+ /*
88
+ * Test whether a block is completely empty, i.e. contains no marked
89
+ * objects. This does not require the block to be in physical
90
+ * memory.
91
+ */
92
+
93
+ GC_bool GC_block_empty(hdr *hhdr)
94
+ {
95
+ return (hhdr -> hb_n_marks == 0);
96
+ }
97
+
98
+ GC_bool GC_block_nearly_full(hdr *hhdr)
99
+ {
100
+ return (hhdr -> hb_n_marks > 7 * HBLK_OBJS(hhdr -> hb_sz)/8);
101
+ }
102
+
103
+ /* FIXME: This should perhaps again be specialized for USE_MARK_BYTES */
104
+ /* and USE_MARK_BITS cases. */
105
+
106
+ /*
107
+ * Restore unmarked small objects in h of size sz to the object
108
+ * free list. Returns the new list.
109
+ * Clears unmarked objects. Sz is in bytes.
110
+ */
111
+ /*ARGSUSED*/
112
+ ptr_t GC_reclaim_clear(struct hblk *hbp, hdr *hhdr, size_t sz,
113
+ ptr_t list, signed_word *count)
114
+ {
115
+ word bit_no = 0;
116
+ word *p, *q, *plim;
117
+ signed_word n_bytes_found = 0;
118
+
119
+ GC_ASSERT(hhdr == GC_find_header((ptr_t)hbp));
120
+ GC_ASSERT(sz == hhdr -> hb_sz);
121
+ GC_ASSERT((sz & (BYTES_PER_WORD-1)) == 0);
122
+ p = (word *)(hbp->hb_body);
123
+ plim = (word *)(hbp->hb_body + HBLKSIZE - sz);
124
+
125
+ /* go through all words in block */
126
+ while( p <= plim ) {
127
+ if( mark_bit_from_hdr(hhdr, bit_no) ) {
128
+ p = (word *)((ptr_t)p + sz);
129
+ } else {
130
+ n_bytes_found += sz;
131
+ /* object is available - put on list */
132
+ obj_link(p) = list;
133
+ list = ((ptr_t)p);
134
+ /* Clear object, advance p to next object in the process */
135
+ q = (word *)((ptr_t)p + sz);
136
+ # ifdef USE_MARK_BYTES
137
+ GC_ASSERT(!(sz & 1)
138
+ && !((word)p & (2 * sizeof(word) - 1)));
139
+ p[1] = 0;
140
+ p += 2;
141
+ while (p < q) {
142
+ CLEAR_DOUBLE(p);
143
+ p += 2;
144
+ }
145
+ # else
146
+ p++; /* Skip link field */
147
+ while (p < q) {
148
+ *p++ = 0;
149
+ }
150
+ # endif
151
+ }
152
+ bit_no += MARK_BIT_OFFSET(sz);
153
+ }
154
+ *count += n_bytes_found;
155
+ return(list);
156
+ }
157
+
158
+ /* The same thing, but don't clear objects: */
159
+ /*ARGSUSED*/
160
+ ptr_t GC_reclaim_uninit(struct hblk *hbp, hdr *hhdr, size_t sz,
161
+ ptr_t list, signed_word *count)
162
+ {
163
+ word bit_no = 0;
164
+ word *p, *plim;
165
+ signed_word n_bytes_found = 0;
166
+
167
+ GC_ASSERT(sz == hhdr -> hb_sz);
168
+ p = (word *)(hbp->hb_body);
169
+ plim = (word *)((ptr_t)hbp + HBLKSIZE - sz);
170
+
171
+ /* go through all words in block */
172
+ while( p <= plim ) {
173
+ if( !mark_bit_from_hdr(hhdr, bit_no) ) {
174
+ n_bytes_found += sz;
175
+ /* object is available - put on list */
176
+ obj_link(p) = list;
177
+ list = ((ptr_t)p);
178
+ }
179
+ p = (word *)((ptr_t)p + sz);
180
+ bit_no += MARK_BIT_OFFSET(sz);
181
+ }
182
+ *count += n_bytes_found;
183
+ return(list);
184
+ }
185
+
186
+ /* Don't really reclaim objects, just check for unmarked ones: */
187
+ /*ARGSUSED*/
188
+ void GC_reclaim_check(struct hblk *hbp, hdr *hhdr, word sz)
189
+ {
190
+ word bit_no = 0;
191
+ ptr_t p, plim;
192
+
193
+ GC_ASSERT(sz == hhdr -> hb_sz);
194
+ p = hbp->hb_body;
195
+ plim = p + HBLKSIZE - sz;
196
+
197
+ /* go through all words in block */
198
+ while( p <= plim ) {
199
+ if( !mark_bit_from_hdr(hhdr, bit_no) ) {
200
+ GC_add_leaked(p);
201
+ }
202
+ p += sz;
203
+ bit_no += MARK_BIT_OFFSET(sz);
204
+ }
205
+ }
206
+
207
+
208
+ /*
209
+ * Generic procedure to rebuild a free list in hbp.
210
+ * Also called directly from GC_malloc_many.
211
+ * Sz is now in bytes.
212
+ */
213
+ ptr_t GC_reclaim_generic(struct hblk * hbp, hdr *hhdr, size_t sz,
214
+ GC_bool init, ptr_t list, signed_word *count)
215
+ {
216
+ ptr_t result = list;
217
+
218
+ GC_ASSERT(GC_find_header((ptr_t)hbp) == hhdr);
219
+ GC_remove_protection(hbp, 1, (hhdr)->hb_descr == 0 /* Pointer-free? */);
220
+ if (init) {
221
+ result = GC_reclaim_clear(hbp, hhdr, sz, list, count);
222
+ } else {
223
+ GC_ASSERT((hhdr)->hb_descr == 0 /* Pointer-free block */);
224
+ result = GC_reclaim_uninit(hbp, hhdr, sz, list, count);
225
+ }
226
+ if (IS_UNCOLLECTABLE(hhdr -> hb_obj_kind)) GC_set_hdr_marks(hhdr);
227
+ return result;
228
+ }
229
+
230
+ /*
231
+ * Restore unmarked small objects in the block pointed to by hbp
232
+ * to the appropriate object free list.
233
+ * If entirely empty blocks are to be completely deallocated, then
234
+ * caller should perform that check.
235
+ */
236
+ void GC_reclaim_small_nonempty_block(struct hblk *hbp,
237
+ int report_if_found, signed_word *count)
238
+ {
239
+ hdr *hhdr = HDR(hbp);
240
+ size_t sz = hhdr -> hb_sz;
241
+ int kind = hhdr -> hb_obj_kind;
242
+ struct obj_kind * ok = &GC_obj_kinds[kind];
243
+ void **flh = &(ok -> ok_freelist[BYTES_TO_GRANULES(sz)]);
244
+
245
+ hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no;
246
+
247
+ if (report_if_found) {
248
+ GC_reclaim_check(hbp, hhdr, sz);
249
+ } else {
250
+ *flh = GC_reclaim_generic(hbp, hhdr, sz,
251
+ (ok -> ok_init || GC_debugging_started),
252
+ *flh, &GC_bytes_found);
253
+ }
254
+ }
255
+
256
+ /*
257
+ * Restore an unmarked large object or an entirely empty blocks of small objects
258
+ * to the heap block free list.
259
+ * Otherwise enqueue the block for later processing
260
+ * by GC_reclaim_small_nonempty_block.
261
+ * If report_if_found is TRUE, then process any block immediately, and
262
+ * simply report free objects; do not actually reclaim them.
263
+ */
264
+ void GC_reclaim_block(struct hblk *hbp, word report_if_found)
265
+ {
266
+ hdr * hhdr = HDR(hbp);
267
+ size_t sz = hhdr -> hb_sz; /* size of objects in current block */
268
+ struct obj_kind * ok = &GC_obj_kinds[hhdr -> hb_obj_kind];
269
+ struct hblk ** rlh;
270
+
271
+ if( sz > MAXOBJBYTES ) { /* 1 big object */
272
+ if( !mark_bit_from_hdr(hhdr, 0) ) {
273
+ if (report_if_found) {
274
+ GC_add_leaked((ptr_t)hbp);
275
+ } else {
276
+ size_t blocks = OBJ_SZ_TO_BLOCKS(sz);
277
+ if (blocks > 1) {
278
+ GC_large_allocd_bytes -= blocks * HBLKSIZE;
279
+ }
280
+ GC_bytes_found += sz;
281
+ GC_freehblk(hbp);
282
+ }
283
+ } else {
284
+ if (hhdr -> hb_descr != 0) {
285
+ GC_composite_in_use += sz;
286
+ } else {
287
+ GC_atomic_in_use += sz;
288
+ }
289
+ }
290
+ } else {
291
+ GC_bool empty = GC_block_empty(hhdr);
292
+ # ifdef PARALLEL_MARK
293
+ /* Count can be low or one too high because we sometimes */
294
+ /* have to ignore decrements. Objects can also potentially */
295
+ /* be repeatedly marked by each marker. */
296
+ /* Here we assume two markers, but this is extremely */
297
+ /* unlikely to fail spuriously with more. And if it does, it */
298
+ /* should be looked at. */
299
+ GC_ASSERT(hhdr -> hb_n_marks <= 2 * (HBLKSIZE/sz + 1) + 16);
300
+ # else
301
+ GC_ASSERT(sz * hhdr -> hb_n_marks <= HBLKSIZE);
302
+ # endif
303
+ if (hhdr -> hb_descr != 0) {
304
+ GC_composite_in_use += sz * hhdr -> hb_n_marks;
305
+ } else {
306
+ GC_atomic_in_use += sz * hhdr -> hb_n_marks;
307
+ }
308
+ if (report_if_found) {
309
+ GC_reclaim_small_nonempty_block(hbp, (int)report_if_found,
310
+ &GC_bytes_found);
311
+ } else if (empty) {
312
+ GC_bytes_found += HBLKSIZE;
313
+ GC_freehblk(hbp);
314
+ } else if (TRUE != GC_block_nearly_full(hhdr)){
315
+ /* group of smaller objects, enqueue the real work */
316
+ rlh = &(ok -> ok_reclaim_list[BYTES_TO_GRANULES(sz)]);
317
+ hhdr -> hb_next = *rlh;
318
+ *rlh = hbp;
319
+ } /* else not worth salvaging. */
320
+ /* We used to do the nearly_full check later, but we */
321
+ /* already have the right cache context here. Also */
322
+ /* doing it here avoids some silly lock contention in */
323
+ /* GC_malloc_many. */
324
+ }
325
+ }
326
+
327
+ #if !defined(NO_DEBUGGING)
328
+ /* Routines to gather and print heap block info */
329
+ /* intended for debugging. Otherwise should be called */
330
+ /* with lock. */
331
+
332
+ struct Print_stats
333
+ {
334
+ size_t number_of_blocks;
335
+ size_t total_bytes;
336
+ };
337
+
338
+ #ifdef USE_MARK_BYTES
339
+
340
+ /* Return the number of set mark bits in the given header */
341
+ int GC_n_set_marks(hdr *hhdr)
342
+ {
343
+ int result = 0;
344
+ int i;
345
+ size_t sz = hhdr -> hb_sz;
346
+ int offset = MARK_BIT_OFFSET(sz);
347
+ int limit = FINAL_MARK_BIT(sz);
348
+
349
+ for (i = 0; i < limit; i += offset) {
350
+ result += hhdr -> hb_marks[i];
351
+ }
352
+ GC_ASSERT(hhdr -> hb_marks[limit]);
353
+ return(result);
354
+ }
355
+
356
+ #else
357
+
358
+ /* Number of set bits in a word. Not performance critical. */
359
+ static int set_bits(word n)
360
+ {
361
+ word m = n;
362
+ int result = 0;
363
+
364
+ while (m > 0) {
365
+ if (m & 1) result++;
366
+ m >>= 1;
367
+ }
368
+ return(result);
369
+ }
370
+
371
+ /* Return the number of set mark bits in the given header */
372
+ int GC_n_set_marks(hdr *hhdr)
373
+ {
374
+ int result = 0;
375
+ int i;
376
+ int n_mark_words;
377
+ # ifdef MARK_BIT_PER_OBJ
378
+ int n_objs = HBLK_OBJS(hhdr -> hb_sz);
379
+
380
+ if (0 == n_objs) n_objs = 1;
381
+ n_mark_words = divWORDSZ(n_objs + WORDSZ - 1);
382
+ # else /* MARK_BIT_PER_GRANULE */
383
+ n_mark_words = MARK_BITS_SZ;
384
+ # endif
385
+ for (i = 0; i < n_mark_words - 1; i++) {
386
+ result += set_bits(hhdr -> hb_marks[i]);
387
+ }
388
+ # ifdef MARK_BIT_PER_OBJ
389
+ result += set_bits((hhdr -> hb_marks[n_mark_words - 1])
390
+ << (n_mark_words * WORDSZ - n_objs));
391
+ # else
392
+ result += set_bits(hhdr -> hb_marks[n_mark_words - 1]);
393
+ # endif
394
+ return(result - 1);
395
+ }
396
+
397
+ #endif /* !USE_MARK_BYTES */
398
+
399
+ /*ARGSUSED*/
400
+ void GC_print_block_descr(struct hblk *h, word /* struct PrintStats */ raw_ps)
401
+ {
402
+ hdr * hhdr = HDR(h);
403
+ size_t bytes = hhdr -> hb_sz;
404
+ struct Print_stats *ps;
405
+ unsigned n_marks = GC_n_set_marks(hhdr);
406
+
407
+ if (hhdr -> hb_n_marks != n_marks) {
408
+ GC_printf("(%u:%u,%u!=%u)", hhdr -> hb_obj_kind,
409
+ bytes,
410
+ hhdr -> hb_n_marks, n_marks);
411
+ } else {
412
+ GC_printf("(%u:%u,%u)", hhdr -> hb_obj_kind,
413
+ bytes, n_marks);
414
+ }
415
+ bytes += HBLKSIZE-1;
416
+ bytes &= ~(HBLKSIZE-1);
417
+
418
+ ps = (struct Print_stats *)raw_ps;
419
+ ps->total_bytes += bytes;
420
+ ps->number_of_blocks++;
421
+ }
422
+
423
+ void GC_print_block_list()
424
+ {
425
+ struct Print_stats pstats;
426
+
427
+ GC_printf("(kind(0=ptrfree,1=normal,2=unc.):size_in_bytes, #_marks_set)\n");
428
+ pstats.number_of_blocks = 0;
429
+ pstats.total_bytes = 0;
430
+ GC_apply_to_all_blocks(GC_print_block_descr, (word)&pstats);
431
+ GC_printf("\nblocks = %lu, bytes = %lu\n",
432
+ (unsigned long)pstats.number_of_blocks,
433
+ (unsigned long)pstats.total_bytes);
434
+ }
435
+
436
+ /* Currently for debugger use only: */
437
+ void GC_print_free_list(int kind, size_t sz_in_granules)
438
+ {
439
+ struct obj_kind * ok = &GC_obj_kinds[kind];
440
+ ptr_t flh = ok -> ok_freelist[sz_in_granules];
441
+ struct hblk *lastBlock = 0;
442
+ int n = 0;
443
+
444
+ while (flh){
445
+ struct hblk *block = HBLKPTR(flh);
446
+ if (block != lastBlock){
447
+ GC_printf("\nIn heap block at 0x%x:\n\t", block);
448
+ lastBlock = block;
449
+ }
450
+ GC_printf("%d: 0x%x;", ++n, flh);
451
+ flh = obj_link(flh);
452
+ }
453
+ }
454
+
455
+ #endif /* NO_DEBUGGING */
456
+
457
+ /*
458
+ * Clear all obj_link pointers in the list of free objects *flp.
459
+ * Clear *flp.
460
+ * This must be done before dropping a list of free gcj-style objects,
461
+ * since may otherwise end up with dangling "descriptor" pointers.
462
+ * It may help for other pointer-containing objects.
463
+ */
464
+ void GC_clear_fl_links(void **flp)
465
+ {
466
+ void *next = *flp;
467
+
468
+ while (0 != next) {
469
+ *flp = 0;
470
+ flp = &(obj_link(next));
471
+ next = *flp;
472
+ }
473
+ }
474
+
475
+ /*
476
+ * Perform GC_reclaim_block on the entire heap, after first clearing
477
+ * small object free lists (if we are not just looking for leaks).
478
+ */
479
+ void GC_start_reclaim(GC_bool report_if_found)
480
+ {
481
+ unsigned kind;
482
+
483
+ # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
484
+ GC_ASSERT(0 == GC_fl_builder_count);
485
+ # endif
486
+ /* Reset in use counters. GC_reclaim_block recomputes them. */
487
+ GC_composite_in_use = 0;
488
+ GC_atomic_in_use = 0;
489
+ /* Clear reclaim- and free-lists */
490
+ for (kind = 0; kind < GC_n_kinds; kind++) {
491
+ void **fop;
492
+ void **lim;
493
+ struct hblk ** rlp;
494
+ struct hblk ** rlim;
495
+ struct hblk ** rlist = GC_obj_kinds[kind].ok_reclaim_list;
496
+ GC_bool should_clobber = (GC_obj_kinds[kind].ok_descriptor != 0);
497
+
498
+ if (rlist == 0) continue; /* This kind not used. */
499
+ if (!report_if_found) {
500
+ lim = &(GC_obj_kinds[kind].ok_freelist[MAXOBJGRANULES+1]);
501
+ for( fop = GC_obj_kinds[kind].ok_freelist; fop < lim; fop++ ) {
502
+ if (*fop != 0) {
503
+ if (should_clobber) {
504
+ GC_clear_fl_links(fop);
505
+ } else {
506
+ *fop = 0;
507
+ }
508
+ }
509
+ }
510
+ } /* otherwise free list objects are marked, */
511
+ /* and its safe to leave them */
512
+ rlim = rlist + MAXOBJGRANULES+1;
513
+ for( rlp = rlist; rlp < rlim; rlp++ ) {
514
+ *rlp = 0;
515
+ }
516
+ }
517
+
518
+
519
+ /* Go through all heap blocks (in hblklist) and reclaim unmarked objects */
520
+ /* or enqueue the block for later processing. */
521
+ GC_apply_to_all_blocks(GC_reclaim_block, (word)report_if_found);
522
+
523
+ # ifdef EAGER_SWEEP
524
+ /* This is a very stupid thing to do. We make it possible anyway, */
525
+ /* so that you can convince yourself that it really is very stupid. */
526
+ GC_reclaim_all((GC_stop_func)0, FALSE);
527
+ # endif
528
+ # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
529
+ GC_ASSERT(0 == GC_fl_builder_count);
530
+ # endif
531
+
532
+ }
533
+
534
+ /*
535
+ * Sweep blocks of the indicated object size and kind until either the
536
+ * appropriate free list is nonempty, or there are no more blocks to
537
+ * sweep.
538
+ */
539
+ void GC_continue_reclaim(size_t sz /* granules */, int kind)
540
+ {
541
+ hdr * hhdr;
542
+ struct hblk * hbp;
543
+ struct obj_kind * ok = &(GC_obj_kinds[kind]);
544
+ struct hblk ** rlh = ok -> ok_reclaim_list;
545
+ void **flh = &(ok -> ok_freelist[sz]);
546
+
547
+ if (rlh == 0) return; /* No blocks of this kind. */
548
+ rlh += sz;
549
+ while ((hbp = *rlh) != 0) {
550
+ hhdr = HDR(hbp);
551
+ *rlh = hhdr -> hb_next;
552
+ GC_reclaim_small_nonempty_block(hbp, FALSE, &GC_bytes_found);
553
+ if (*flh != 0) break;
554
+ }
555
+ }
556
+
557
+ /*
558
+ * Reclaim all small blocks waiting to be reclaimed.
559
+ * Abort and return FALSE when/if (*stop_func)() returns TRUE.
560
+ * If this returns TRUE, then it's safe to restart the world
561
+ * with incorrectly cleared mark bits.
562
+ * If ignore_old is TRUE, then reclaim only blocks that have been
563
+ * recently reclaimed, and discard the rest.
564
+ * Stop_func may be 0.
565
+ */
566
+ GC_bool GC_reclaim_all(GC_stop_func stop_func, GC_bool ignore_old)
567
+ {
568
+ word sz;
569
+ unsigned kind;
570
+ hdr * hhdr;
571
+ struct hblk * hbp;
572
+ struct obj_kind * ok;
573
+ struct hblk ** rlp;
574
+ struct hblk ** rlh;
575
+ CLOCK_TYPE start_time;
576
+ CLOCK_TYPE done_time;
577
+
578
+ if (GC_print_stats == VERBOSE)
579
+ GET_TIME(start_time);
580
+
581
+ for (kind = 0; kind < GC_n_kinds; kind++) {
582
+ ok = &(GC_obj_kinds[kind]);
583
+ rlp = ok -> ok_reclaim_list;
584
+ if (rlp == 0) continue;
585
+ for (sz = 1; sz <= MAXOBJGRANULES; sz++) {
586
+ rlh = rlp + sz;
587
+ while ((hbp = *rlh) != 0) {
588
+ if (stop_func != (GC_stop_func)0 && (*stop_func)()) {
589
+ return(FALSE);
590
+ }
591
+ hhdr = HDR(hbp);
592
+ *rlh = hhdr -> hb_next;
593
+ if (!ignore_old || hhdr -> hb_last_reclaimed == GC_gc_no - 1) {
594
+ /* It's likely we'll need it this time, too */
595
+ /* It's been touched recently, so this */
596
+ /* shouldn't trigger paging. */
597
+ GC_reclaim_small_nonempty_block(hbp, FALSE, &GC_bytes_found);
598
+ }
599
+ }
600
+ }
601
+ }
602
+ if (GC_print_stats == VERBOSE) {
603
+ GET_TIME(done_time);
604
+ GC_log_printf("Disposing of reclaim lists took %lu msecs\n",
605
+ MS_TIME_DIFF(done_time,start_time));
606
+ }
607
+ return(TRUE);
608
+ }
mosesdecoder/jam-files/engine/boehm_gc/sparc_netbsd_mach_dep.s ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ! SPARCompiler 3.0 and later apparently no longer handles
2
+ ! asm outside functions. So we need a separate .s file
3
+ ! This is only set up for SunOS 4.
4
+ ! Assumes this is called before the stack contents are
5
+ ! examined.
6
+
7
+ #include "machine/asm.h"
8
+
9
+ .seg "text"
10
+ .globl _C_LABEL(GC_save_regs_in_stack)
11
+ .globl _C_LABEL(GC_push_regs)
12
+ _C_LABEL(GC_save_regs_in_stack):
13
+ _C_LABEL(GC_push_regs):
14
+ ta 0x3 ! ST_FLUSH_WINDOWS
15
+ mov %sp,%o0
16
+ retl
17
+ nop
18
+
19
+ .globl _C_LABEL(GC_clear_stack_inner)
20
+ _C_LABEL(GC_clear_stack_inner):
21
+ mov %sp,%o2 ! Save sp
22
+ add %sp,-8,%o3 ! p = sp-8
23
+ clr %g1 ! [g0,g1] = 0
24
+ add %o1,-0x60,%sp ! Move sp out of the way,
25
+ ! so that traps still work.
26
+ ! Includes some extra words
27
+ ! so we can be sloppy below.
28
+ loop:
29
+ std %g0,[%o3] ! *(long long *)p = 0
30
+ cmp %o3,%o1
31
+ bgu loop ! if (p > limit) goto loop
32
+ add %o3,-8,%o3 ! p -= 8 (delay slot)
33
+ retl
34
+ mov %o2,%sp ! Restore sp., delay slot
mosesdecoder/jam-files/engine/boehm_gc/version.h ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* The version here should match that in configure/configure.ac */
2
+ /* Eventually this one may become unnecessary. For now we need */
3
+ /* it to keep the old-style build process working. */
4
+ #define GC_TMP_VERSION_MAJOR 7
5
+ #define GC_TMP_VERSION_MINOR 0
6
+ #define GC_TMP_ALPHA_VERSION GC_NOT_ALPHA
7
+
8
+ #ifndef GC_NOT_ALPHA
9
+ # define GC_NOT_ALPHA 0xff
10
+ #endif
11
+
12
+ #if defined(GC_VERSION_MAJOR)
13
+ # if GC_TMP_VERSION_MAJOR != GC_VERSION_MAJOR || \
14
+ GC_TMP_VERSION_MINOR != GC_VERSION_MINOR || \
15
+ defined(GC_ALPHA_VERSION) != (GC_TMP_ALPHA_VERSION != GC_NOT_ALPHA) || \
16
+ defined(GC_ALPHA_VERSION) && GC_TMP_ALPHA_VERSION != GC_ALPHA_VERSION
17
+ # error Inconsistent version info. Check README, version.h, and configure.ac.
18
+ # endif
19
+ #else
20
+ # define GC_VERSION_MAJOR GC_TMP_VERSION_MAJOR
21
+ # define GC_VERSION_MINOR GC_TMP_VERSION_MINOR
22
+ # define GC_ALPHA_VERSION GC_TMP_ALPHA_VERSION
23
+ #endif
24
+
25
+
26
+ #ifndef GC_NO_VERSION_VAR
27
+
28
+ unsigned GC_version = ((GC_VERSION_MAJOR << 16) | (GC_VERSION_MINOR << 8) | GC_TMP_ALPHA_VERSION);
29
+
30
+ #endif /* GC_NO_VERSION_VAR */
mosesdecoder/lm/common/compare.hh ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef LM_COMMON_COMPARE_H
2
+ #define LM_COMMON_COMPARE_H
3
+
4
+ #include "lm/word_index.hh"
5
+
6
+ #include <functional>
7
+ #include <string>
8
+
9
+ namespace lm {
10
+
11
+ /**
12
+ * Abstract parent class for defining custom n-gram comparators.
13
+ */
14
+ template <class Child> class Comparator : public std::binary_function<const void *, const void *, bool> {
15
+ public:
16
+
17
+ /**
18
+ * Constructs a comparator capable of comparing two n-grams.
19
+ *
20
+ * @param order Number of words in each n-gram
21
+ */
22
+ explicit Comparator(std::size_t order) : order_(order) {}
23
+
24
+ /**
25
+ * Applies the comparator using the Compare method that must be defined in any class that inherits from this class.
26
+ *
27
+ * @param lhs A pointer to the n-gram on the left-hand side of the comparison
28
+ * @param rhs A pointer to the n-gram on the right-hand side of the comparison
29
+ *
30
+ * @see ContextOrder::Compare
31
+ * @see PrefixOrder::Compare
32
+ * @see SuffixOrder::Compare
33
+ */
34
+ inline bool operator()(const void *lhs, const void *rhs) const {
35
+ return static_cast<const Child*>(this)->Compare(static_cast<const WordIndex*>(lhs), static_cast<const WordIndex*>(rhs));
36
+ }
37
+
38
+ /** Gets the n-gram order defined for this comparator. */
39
+ std::size_t Order() const { return order_; }
40
+
41
+ protected:
42
+ std::size_t order_;
43
+ };
44
+
45
+ /**
46
+ * N-gram comparator that compares n-grams according to their reverse (suffix) order.
47
+ *
48
+ * This comparator compares n-grams lexicographically, one word at a time,
49
+ * beginning with the last word of each n-gram and ending with the first word of each n-gram.
50
+ *
51
+ * Some examples of n-gram comparisons as defined by this comparator:
52
+ * - a b c == a b c
53
+ * - a b c < a b d
54
+ * - a b c > a d b
55
+ * - a b c > a b b
56
+ * - a b c > x a c
57
+ * - a b c < x y z
58
+ */
59
+ class SuffixOrder : public Comparator<SuffixOrder> {
60
+ public:
61
+
62
+ /**
63
+ * Constructs a comparator capable of comparing two n-grams.
64
+ *
65
+ * @param order Number of words in each n-gram
66
+ */
67
+ explicit SuffixOrder(std::size_t order) : Comparator<SuffixOrder>(order) {}
68
+
69
+ /**
70
+ * Compares two n-grams lexicographically, one word at a time,
71
+ * beginning with the last word of each n-gram and ending with the first word of each n-gram.
72
+ *
73
+ * @param lhs A pointer to the n-gram on the left-hand side of the comparison
74
+ * @param rhs A pointer to the n-gram on the right-hand side of the comparison
75
+ */
76
+ inline bool Compare(const WordIndex *lhs, const WordIndex *rhs) const {
77
+ for (std::size_t i = order_ - 1; i != 0; --i) {
78
+ if (lhs[i] != rhs[i])
79
+ return lhs[i] < rhs[i];
80
+ }
81
+ return lhs[0] < rhs[0];
82
+ }
83
+
84
+ static const unsigned kMatchOffset = 1;
85
+ };
86
+
87
+
88
+ /**
89
+ * N-gram comparator that compares n-grams according to the reverse (suffix) order of the n-gram context.
90
+ *
91
+ * This comparator compares n-grams lexicographically, one word at a time,
92
+ * beginning with the penultimate word of each n-gram and ending with the first word of each n-gram;
93
+ * finally, this comparator compares the last word of each n-gram.
94
+ *
95
+ * Some examples of n-gram comparisons as defined by this comparator:
96
+ * - a b c == a b c
97
+ * - a b c < a b d
98
+ * - a b c < a d b
99
+ * - a b c > a b b
100
+ * - a b c > x a c
101
+ * - a b c < x y z
102
+ */
103
+ class ContextOrder : public Comparator<ContextOrder> {
104
+ public:
105
+
106
+ /**
107
+ * Constructs a comparator capable of comparing two n-grams.
108
+ *
109
+ * @param order Number of words in each n-gram
110
+ */
111
+ explicit ContextOrder(std::size_t order) : Comparator<ContextOrder>(order) {}
112
+
113
+ /**
114
+ * Compares two n-grams lexicographically, one word at a time,
115
+ * beginning with the penultimate word of each n-gram and ending with the first word of each n-gram;
116
+ * finally, this comparator compares the last word of each n-gram.
117
+ *
118
+ * @param lhs A pointer to the n-gram on the left-hand side of the comparison
119
+ * @param rhs A pointer to the n-gram on the right-hand side of the comparison
120
+ */
121
+ inline bool Compare(const WordIndex *lhs, const WordIndex *rhs) const {
122
+ for (int i = order_ - 2; i >= 0; --i) {
123
+ if (lhs[i] != rhs[i])
124
+ return lhs[i] < rhs[i];
125
+ }
126
+ return lhs[order_ - 1] < rhs[order_ - 1];
127
+ }
128
+ };
129
+
130
+ /**
131
+ * N-gram comparator that compares n-grams according to their natural (prefix) order.
132
+ *
133
+ * This comparator compares n-grams lexicographically, one word at a time,
134
+ * beginning with the first word of each n-gram and ending with the last word of each n-gram.
135
+ *
136
+ * Some examples of n-gram comparisons as defined by this comparator:
137
+ * - a b c == a b c
138
+ * - a b c < a b d
139
+ * - a b c < a d b
140
+ * - a b c > a b b
141
+ * - a b c < x a c
142
+ * - a b c < x y z
143
+ */
144
+ class PrefixOrder : public Comparator<PrefixOrder> {
145
+ public:
146
+
147
+ /**
148
+ * Constructs a comparator capable of comparing two n-grams.
149
+ *
150
+ * @param order Number of words in each n-gram
151
+ */
152
+ explicit PrefixOrder(std::size_t order) : Comparator<PrefixOrder>(order) {}
153
+
154
+ /**
155
+ * Compares two n-grams lexicographically, one word at a time,
156
+ * beginning with the first word of each n-gram and ending with the last word of each n-gram.
157
+ *
158
+ * @param lhs A pointer to the n-gram on the left-hand side of the comparison
159
+ * @param rhs A pointer to the n-gram on the right-hand side of the comparison
160
+ */
161
+ inline bool Compare(const WordIndex *lhs, const WordIndex *rhs) const {
162
+ for (std::size_t i = 0; i < order_; ++i) {
163
+ if (lhs[i] != rhs[i])
164
+ return lhs[i] < rhs[i];
165
+ }
166
+ return false;
167
+ }
168
+
169
+ static const unsigned kMatchOffset = 0;
170
+ };
171
+
172
+ } // namespace lm
173
+
174
+ #endif // LM_COMMON_COMPARE_H
mosesdecoder/lm/common/model_buffer.cc ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "lm/common/model_buffer.hh"
2
+ #include "util/exception.hh"
3
+ #include "util/file_stream.hh"
4
+ #include "util/file.hh"
5
+ #include "util/file_piece.hh"
6
+ #include "util/stream/io.hh"
7
+ #include "util/stream/multi_stream.hh"
8
+
9
+ #include <boost/lexical_cast.hpp>
10
+
11
+ namespace lm {
12
+
13
+ namespace {
14
+ const char kMetadataHeader[] = "KenLM intermediate binary file";
15
+ } // namespace
16
+
17
+ ModelBuffer::ModelBuffer(StringPiece file_base, bool keep_buffer, bool output_q)
18
+ : file_base_(file_base.data(), file_base.size()), keep_buffer_(keep_buffer), output_q_(output_q),
19
+ vocab_file_(keep_buffer ? util::CreateOrThrow((file_base_ + ".vocab").c_str()) : util::MakeTemp(file_base_)) {}
20
+
21
+ ModelBuffer::ModelBuffer(StringPiece file_base)
22
+ : file_base_(file_base.data(), file_base.size()), keep_buffer_(false) {
23
+ const std::string full_name = file_base_ + ".kenlm_intermediate";
24
+ util::FilePiece in(full_name.c_str());
25
+ StringPiece token = in.ReadLine();
26
+ UTIL_THROW_IF2(token != kMetadataHeader, "File " << full_name << " begins with \"" << token << "\" not " << kMetadataHeader);
27
+
28
+ token = in.ReadDelimited();
29
+ UTIL_THROW_IF2(token != "Counts", "Expected Counts, got \"" << token << "\" in " << full_name);
30
+ char got;
31
+ while ((got = in.get()) == ' ') {
32
+ counts_.push_back(in.ReadULong());
33
+ }
34
+ UTIL_THROW_IF2(got != '\n', "Expected newline at end of counts.");
35
+
36
+ token = in.ReadDelimited();
37
+ UTIL_THROW_IF2(token != "Payload", "Expected Payload, got \"" << token << "\" in " << full_name);
38
+ token = in.ReadDelimited();
39
+ if (token == "q") {
40
+ output_q_ = true;
41
+ } else if (token == "pb") {
42
+ output_q_ = false;
43
+ } else {
44
+ UTIL_THROW(util::Exception, "Unknown payload " << token);
45
+ }
46
+
47
+ vocab_file_.reset(util::OpenReadOrThrow((file_base_ + ".vocab").c_str()));
48
+
49
+ files_.Init(counts_.size());
50
+ for (unsigned long i = 0; i < counts_.size(); ++i) {
51
+ files_.push_back(util::OpenReadOrThrow((file_base_ + '.' + boost::lexical_cast<std::string>(i + 1)).c_str()));
52
+ }
53
+ }
54
+
55
+ void ModelBuffer::Sink(util::stream::Chains &chains, const std::vector<uint64_t> &counts) {
56
+ counts_ = counts;
57
+ // Open files.
58
+ files_.Init(chains.size());
59
+ for (std::size_t i = 0; i < chains.size(); ++i) {
60
+ if (keep_buffer_) {
61
+ files_.push_back(util::CreateOrThrow(
62
+ (file_base_ + '.' + boost::lexical_cast<std::string>(i + 1)).c_str()
63
+ ));
64
+ } else {
65
+ files_.push_back(util::MakeTemp(file_base_));
66
+ }
67
+ chains[i] >> util::stream::Write(files_.back().get());
68
+ }
69
+ if (keep_buffer_) {
70
+ util::scoped_fd metadata(util::CreateOrThrow((file_base_ + ".kenlm_intermediate").c_str()));
71
+ util::FileStream meta(metadata.get(), 200);
72
+ meta << kMetadataHeader << "\nCounts";
73
+ for (std::vector<uint64_t>::const_iterator i = counts_.begin(); i != counts_.end(); ++i) {
74
+ meta << ' ' << *i;
75
+ }
76
+ meta << "\nPayload " << (output_q_ ? "q" : "pb") << '\n';
77
+ }
78
+ }
79
+
80
+ void ModelBuffer::Source(util::stream::Chains &chains) {
81
+ assert(chains.size() <= files_.size());
82
+ for (unsigned int i = 0; i < chains.size(); ++i) {
83
+ chains[i] >> util::stream::PRead(files_[i].get());
84
+ }
85
+ }
86
+
87
+ void ModelBuffer::Source(std::size_t order_minus_1, util::stream::Chain &chain) {
88
+ chain >> util::stream::PRead(files_[order_minus_1].get());
89
+ }
90
+
91
+ } // namespace
mosesdecoder/lm/common/model_buffer.hh ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef LM_COMMON_MODEL_BUFFER_H
2
+ #define LM_COMMON_MODEL_BUFFER_H
3
+
4
+ /* Format with separate files in suffix order. Each file contains
5
+ * n-grams of the same order.
6
+ */
7
+
8
+ #include "util/file.hh"
9
+ #include "util/fixed_array.hh"
10
+
11
+ #include <string>
12
+ #include <vector>
13
+
14
+ namespace util { namespace stream {
15
+ class Chains;
16
+ class Chain;
17
+ }} // namespaces
18
+
19
+ namespace lm {
20
+
21
+ class ModelBuffer {
22
+ public:
23
+ // Construct for writing. Must call VocabFile() and fill it with null-delimited vocab words.
24
+ ModelBuffer(StringPiece file_base, bool keep_buffer, bool output_q);
25
+
26
+ // Load from file.
27
+ explicit ModelBuffer(StringPiece file_base);
28
+
29
+ // Must call VocabFile and populate before calling this function.
30
+ void Sink(util::stream::Chains &chains, const std::vector<uint64_t> &counts);
31
+
32
+ // Read files and write to the given chains. If fewer chains are provided,
33
+ // only do the lower orders.
34
+ void Source(util::stream::Chains &chains);
35
+
36
+ void Source(std::size_t order_minus_1, util::stream::Chain &chain);
37
+
38
+ // The order of the n-gram model that is associated with the model buffer.
39
+ std::size_t Order() const { return counts_.size(); }
40
+ // Requires Sink or load from file.
41
+ const std::vector<uint64_t> &Counts() const {
42
+ assert(!counts_.empty());
43
+ return counts_;
44
+ }
45
+
46
+ int VocabFile() const { return vocab_file_.get(); }
47
+ int StealVocabFile() { return vocab_file_.release(); }
48
+
49
+ bool Keep() const { return keep_buffer_; }
50
+
51
+ private:
52
+ const std::string file_base_;
53
+ const bool keep_buffer_;
54
+ bool output_q_;
55
+ std::vector<uint64_t> counts_;
56
+
57
+ util::scoped_fd vocab_file_;
58
+ util::FixedArray<util::scoped_fd> files_;
59
+ };
60
+
61
+ } // namespace lm
62
+
63
+ #endif // LM_COMMON_MODEL_BUFFER_H
mosesdecoder/lm/common/ngram_stream.hh ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef LM_BUILDER_NGRAM_STREAM_H
2
+ #define LM_BUILDER_NGRAM_STREAM_H
3
+
4
+ #include "lm/common/ngram.hh"
5
+ #include "util/stream/chain.hh"
6
+ #include "util/stream/multi_stream.hh"
7
+ #include "util/stream/stream.hh"
8
+
9
+ #include <cstddef>
10
+
11
+ namespace lm {
12
+
13
+ template <class Proxy> class ProxyStream {
14
+ public:
15
+ // Make an invalid stream.
16
+ ProxyStream() {}
17
+
18
+ explicit ProxyStream(const util::stream::ChainPosition &position, const Proxy &proxy = Proxy())
19
+ : proxy_(proxy), stream_(position) {
20
+ proxy_.ReBase(stream_.Get());
21
+ }
22
+
23
+ Proxy &operator*() { return proxy_; }
24
+ const Proxy &operator*() const { return proxy_; }
25
+
26
+ Proxy *operator->() { return &proxy_; }
27
+ const Proxy *operator->() const { return &proxy_; }
28
+
29
+ void *Get() { return stream_.Get(); }
30
+ const void *Get() const { return stream_.Get(); }
31
+
32
+ operator bool() const { return stream_; }
33
+ bool operator!() const { return !stream_; }
34
+ void Poison() { stream_.Poison(); }
35
+
36
+ ProxyStream<Proxy> &operator++() {
37
+ ++stream_;
38
+ proxy_.ReBase(stream_.Get());
39
+ return *this;
40
+ }
41
+
42
+ private:
43
+ Proxy proxy_;
44
+ util::stream::Stream stream_;
45
+ };
46
+
47
+ template <class Payload> class NGramStream : public ProxyStream<NGram<Payload> > {
48
+ public:
49
+ // Make an invalid stream.
50
+ NGramStream() {}
51
+
52
+ explicit NGramStream(const util::stream::ChainPosition &position) :
53
+ ProxyStream<NGram<Payload> >(position, NGram<Payload>(NULL, NGram<Payload>::OrderFromSize(position.GetChain().EntrySize()))) {}
54
+ };
55
+
56
+ template <class Payload> class NGramStreams : public util::stream::GenericStreams<NGramStream<Payload> > {
57
+ private:
58
+ typedef util::stream::GenericStreams<NGramStream<Payload> > P;
59
+ public:
60
+ NGramStreams() : P() {}
61
+ NGramStreams(const util::stream::ChainPositions &positions) : P(positions) {}
62
+ };
63
+
64
+ } // namespace
65
+ #endif // LM_BUILDER_NGRAM_STREAM_H
mosesdecoder/lm/common/print.hh ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef LM_COMMON_PRINT_H
2
+ #define LM_COMMON_PRINT_H
3
+
4
+ #include "lm/word_index.hh"
5
+ #include "util/mmap.hh"
6
+ #include "util/string_piece.hh"
7
+
8
+ #include <cassert>
9
+ #include <vector>
10
+
11
+ namespace util { namespace stream { class ChainPositions; }}
12
+
13
+ // Warning: PrintARPA routines read all unigrams before all bigrams before all
14
+ // trigrams etc. So if other parts of the chain move jointly, you'll have to
15
+ // buffer.
16
+
17
+ namespace lm {
18
+
19
+ class VocabReconstitute {
20
+ public:
21
+ // fd must be alive for life of this object; does not take ownership.
22
+ explicit VocabReconstitute(int fd);
23
+
24
+ const char *Lookup(WordIndex index) const {
25
+ assert(index < map_.size() - 1);
26
+ return map_[index];
27
+ }
28
+
29
+ StringPiece LookupPiece(WordIndex index) const {
30
+ return StringPiece(map_[index], map_[index + 1] - 1 - map_[index]);
31
+ }
32
+
33
+ std::size_t Size() const {
34
+ // There's an extra entry to support StringPiece lengths.
35
+ return map_.size() - 1;
36
+ }
37
+
38
+ private:
39
+ util::scoped_memory memory_;
40
+ std::vector<const char*> map_;
41
+ };
42
+
43
+ class PrintARPA {
44
+ public:
45
+ // Does not take ownership of vocab_fd or out_fd.
46
+ explicit PrintARPA(int vocab_fd, int out_fd, const std::vector<uint64_t> &counts)
47
+ : vocab_fd_(vocab_fd), out_fd_(out_fd), counts_(counts) {}
48
+
49
+ void Run(const util::stream::ChainPositions &positions);
50
+
51
+ private:
52
+ int vocab_fd_;
53
+ int out_fd_;
54
+ std::vector<uint64_t> counts_;
55
+ };
56
+
57
+ } // namespace lm
58
+ #endif // LM_COMMON_PRINT_H
mosesdecoder/lm/common/size_option.cc ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <boost/program_options.hpp>
2
+ #include "util/usage.hh"
3
+
4
+ namespace lm {
5
+
6
+ namespace {
7
+ class SizeNotify {
8
+ public:
9
+ explicit SizeNotify(std::size_t &out) : behind_(out) {}
10
+
11
+ void operator()(const std::string &from) {
12
+ behind_ = util::ParseSize(from);
13
+ }
14
+
15
+ private:
16
+ std::size_t &behind_;
17
+ };
18
+ }
19
+
20
+ boost::program_options::typed_value<std::string> *SizeOption(std::size_t &to, const char *default_value) {
21
+ return boost::program_options::value<std::string>()->notifier(SizeNotify(to))->default_value(default_value);
22
+ }
23
+
24
+ } // namespace lm
mosesdecoder/lm/common/size_option.hh ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <boost/program_options.hpp>
2
+
3
+ #include <cstddef>
4
+ #include <string>
5
+
6
+ namespace lm {
7
+
8
+ // Create a boost program option for data sizes. This parses sizes like 1T and 10k.
9
+ boost::program_options::typed_value<std::string> *SizeOption(std::size_t &to, const char *default_value);
10
+
11
+ } // namespace lm
mosesdecoder/lm/common/special.hh ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef LM_COMMON_SPECIAL_H
2
+ #define LM_COMMON_SPECIAL_H
3
+
4
+ #include "lm/word_index.hh"
5
+
6
+ namespace lm {
7
+
8
+ class SpecialVocab {
9
+ public:
10
+ SpecialVocab(WordIndex bos, WordIndex eos) : bos_(bos), eos_(eos) {}
11
+
12
+ bool IsSpecial(WordIndex word) const {
13
+ return word == kUNK || word == bos_ || word == eos_;
14
+ }
15
+
16
+ WordIndex UNK() const { return kUNK; }
17
+ WordIndex BOS() const { return bos_; }
18
+ WordIndex EOS() const { return eos_; }
19
+
20
+ private:
21
+ WordIndex bos_;
22
+ WordIndex eos_;
23
+ };
24
+
25
+ } // namespace lm
26
+
27
+ #endif // LM_COMMON_SPECIAL_H
mosesdecoder/lm/config.cc ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "lm/config.hh"
2
+
3
+ #include <iostream>
4
+
5
+ namespace lm {
6
+ namespace ngram {
7
+
8
+ Config::Config() :
9
+ show_progress(true),
10
+ messages(&std::cerr),
11
+ enumerate_vocab(NULL),
12
+ unknown_missing(COMPLAIN),
13
+ sentence_marker_missing(THROW_UP),
14
+ positive_log_probability(THROW_UP),
15
+ unknown_missing_logprob(-100.0),
16
+ probing_multiplier(1.5),
17
+ building_memory(1073741824ULL), // 1 GB
18
+ temporary_directory_prefix(""),
19
+ arpa_complain(ALL),
20
+ write_mmap(NULL),
21
+ write_method(WRITE_AFTER),
22
+ include_vocab(true),
23
+ rest_function(REST_MAX),
24
+ prob_bits(8),
25
+ backoff_bits(8),
26
+ pointer_bhiksha_bits(22),
27
+ load_method(util::POPULATE_OR_READ) {}
28
+
29
+ } // namespace ngram
30
+ } // namespace lm