~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to o/gbc.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright (C) 1994 M. Hagiya, W. Schelter, T. Yuasa
 
3
  
 
4
  This file is part of GNU Common Lisp, herein referred to as GCL
 
5
  
 
6
  GCL is free software; you can redistribute it and/or modify it under
 
7
  the terms of the GNU LIBRARY GENERAL PUBLIC LICENSE as published by
 
8
  the Free Software Foundation; either version 2, or (at your option)
 
9
  any later version.
 
10
  
 
11
  GCL is distributed in the hope that it will be useful, but WITHOUT
 
12
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
13
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public 
 
14
  License for more details.
 
15
  
 
16
  You should have received a copy of the GNU Library General Public License 
 
17
  along with GCL; see the file COPYING.  If not, write to the Free Software
 
18
  Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
19
  
 
20
*/
 
21
 
 
22
/*
 
23
  GBC.c
 
24
  IMPLEMENTATION-DEPENDENT
 
25
*/
 
26
 
 
27
#define DEBUG
 
28
 
 
29
#define IN_GBC
 
30
#define NEED_MP_H
 
31
#include <string.h>
 
32
#include <stdlib.h>
 
33
#include "include.h"
 
34
#include "page.h"
 
35
 
 
36
 
 
37
#ifdef SGC
 
38
static void
 
39
sgc_contblock_sweep_phase(void);
 
40
 
 
41
static void
 
42
sgc_sweep_phase(void);
 
43
 
 
44
static void
 
45
sgc_mark_phase(void);
 
46
 
 
47
static int
 
48
sgc_count_writable(int);
 
49
 
 
50
#endif
 
51
 
 
52
static void
 
53
mark_c_stack(jmp_buf, int, void (*)(void *,void *,int));
 
54
 
 
55
static void
 
56
mark_contblock(void *, int);
 
57
 
 
58
static void
 
59
mark_object(object);
 
60
 
 
61
 
 
62
/* the following in line definitions seem to be twice as fast (at
 
63
   least on mc68020) as going to the assembly function calls in bitop.c so
 
64
   since this is more portable and faster lets use them --W. Schelter
 
65
   These assume that DBEGIN is divisible by 32, or else we should have
 
66
   #define Shamt(x) (((((int) x -DBEGIN) >> 2) & ~(~0 << 5)))
 
67
*/ 
 
68
#define BBITS_CHAR 3
 
69
 
 
70
#if SIZEOF_LONG == 4
 
71
#define BBYTES_LONG 2
 
72
#elif SIZEOF_LONG == 8
 
73
#define BBYTES_LONG 3
 
74
#else
 
75
#error Do not recognize SIZEOF_LONG
 
76
#endif
 
77
 
 
78
#if CPTR_ALIGN == 8
 
79
#define BBYTES_CONTBLOCK 3
 
80
#elif CPTR_ALIGN == 16
 
81
#define BBYTES_CONTBLOCK 4
 
82
#else
 
83
#error Do not recognize CPTR_ALIGN
 
84
#endif
 
85
 
 
86
#define BBITS_LONG (BBYTES_LONG+BBITS_CHAR)
 
87
#define BCHARS_TABLE (BBITS_LONG+BBYTES_CONTBLOCK)
 
88
 
 
89
#define Shamt(x) (((((unsigned long) x) >> BBYTES_CONTBLOCK) & ~(~0 << BBITS_LONG)))
 
90
#define Madr(x) (mark_table+((((unsigned long) x) - ((unsigned long)DBEGIN)) >> (BCHARS_TABLE)))
 
91
#define get_mark_bit(x) (*(Madr(x)) >> Shamt(x) & 1)
 
92
#define set_mark_bit(x) ((*(Madr(x))) |= ((unsigned long)1 << Shamt(x)))
 
93
 
 
94
/*  #define Shamt(x) (((((long) x) >> 3) & ~(~0 << 6))) */
 
95
/*  #define Madr(x) (mark_table+((((long) x) - ((long)DBEGIN)) >> (9))) */
 
96
/*  #define get_mark_bit(x) (*(Madr(x)) >> Shamt(x) & 1) */
 
97
/*  #define set_mark_bit(x) ((*(Madr(x))) |= ((unsigned long)1 << Shamt(x))) */
 
98
 
 
99
#ifdef KCLOVM
 
100
void mark_all_stacks();
 
101
bool ovm_process_created; 
 
102
#endif
 
103
 
 
104
 
 
105
static int gc_time         = -1;
 
106
static int gc_start        = 0;
 
107
static int gc_recursive    = 0;
 
108
#ifdef SGC
 
109
int sgc_enabled=0;
 
110
#endif
 
111
long first_protectable_page = 0;
 
112
 
 
113
int runtime(void);
 
114
 
 
115
static char *copy_relblock(char *p, int s);
 
116
 
 
117
extern bool saving_system;
 
118
extern long real_maxpage;
 
119
extern long new_holepage;
 
120
 
 
121
#define available_pages \
 
122
        (real_maxpage-page(heap_end)-(new_holepage>=holepage ? new_holepage : holepage)-2*nrbpage-real_maxpage/32)
 
123
 
 
124
struct apage {
 
125
  char apage_self[PAGESIZE];
 
126
};
 
127
 
 
128
long maxpage;
 
129
 
 
130
object sSAnotify_gbcA;
 
131
 
 
132
#ifdef DEBUG
 
133
bool debug;
 
134
object sSAgbc_messageA;
 
135
#endif
 
136
 
 
137
#define MARK_ORIGIN_MAX         300
 
138
#define MARK_ORIGIN_BLOCK_MAX   20
 
139
 
 
140
#ifdef AV
 
141
/*
 
142
  See bitop.c.
 
143
*/
 
144
#endif
 
145
#ifdef MV
 
146
 
 
147
 
 
148
 
 
149
 
 
150
 
 
151
 
 
152
 
 
153
 
 
154
 
 
155
 
 
156
 
 
157
 
 
158
 
 
159
 
 
160
#endif
 
161
 
 
162
#define symbol_marked(x)        ((x)->d.m)
 
163
 
 
164
object *mark_origin[MARK_ORIGIN_MAX];
 
165
int mark_origin_max;
 
166
 
 
167
struct {
 
168
  object        *mob_addr;      /*  mark origin block address  */
 
169
  int   mob_size;       /*  mark origin block size  */
 
170
} mark_origin_block[MARK_ORIGIN_BLOCK_MAX];
 
171
int mark_origin_block_max;
 
172
 
 
173
/* must be a long * to match with SIZEOF_LONG usage above*/
 
174
long *mark_table;
 
175
 
 
176
enum type what_to_collect;
 
177
 
 
178
 
 
179
 
 
180
void
 
181
enter_mark_origin(object *p)
 
182
{
 
183
  unsigned long np=page(p);
 
184
/*   if (np>=MAXPAGE) */
 
185
/*     error("Address supplied to enter_mar_origin out of range"); */
 
186
  if (mark_origin_max >= MARK_ORIGIN_MAX)
 
187
    error("too many mark origins");
 
188
#ifdef SGC
 
189
  if (np<MAXPAGE)
 
190
    sgc_type_map[np] |= SGC_PERM_WRITABLE ;
 
191
#endif  
 
192
  mark_origin[mark_origin_max++] = p;
 
193
}
 
194
 
 
195
/* static void */
 
196
/* enter_mark_origin_block(object *p, int n) { */
 
197
/*   if (mark_origin_block_max >= MARK_ORIGIN_BLOCK_MAX) */
 
198
/*     error("too many mark origin blocks"); */
 
199
/*   mark_origin_block[mark_origin_block_max].mob_addr = p; */
 
200
/*   mark_origin_block[mark_origin_block_max++].mob_size = n; */
 
201
/* } */
 
202
 
 
203
static void
 
204
mark_cons(object x) {
 
205
  
 
206
  cs_check(x);
 
207
  
 
208
  /*  x is already marked.  */
 
209
  
 
210
 BEGIN:  
 
211
  if (NULL_OR_ON_C_STACK(x->c.c_car)) goto MARK_CDR;
 
212
  if (type_of(x->c.c_car) == t_cons) {
 
213
    if (x->c.c_car->c.m)
 
214
      ;
 
215
    else {
 
216
      x->c.c_car->c.m = TRUE;
 
217
      mark_cons(x->c.c_car);
 
218
    }
 
219
  } else
 
220
    mark_object(x->c.c_car);
 
221
 MARK_CDR:  
 
222
  x = x->c.c_cdr;
 
223
  if (NULL_OR_ON_C_STACK(x))
 
224
    return;
 
225
  if (type_of(x) == t_cons) {
 
226
    if (x->c.m)
 
227
      return;
 
228
    x->c.m = TRUE;
 
229
    goto BEGIN;
 
230
  }
 
231
  if (x == Cnil)
 
232
    return;
 
233
  mark_object(x);
 
234
}
 
235
 
 
236
/* Whenever two arrays are linked together by displacement,
 
237
   if one is live, the other will be made live */
 
238
#define mark_displaced_field(ar) mark_object(ar->a.a_displaced)
 
239
 
 
240
static void
 
241
mark_object(object x) {
 
242
  
 
243
  long i;
 
244
  int j;
 
245
  object *p;
 
246
  char *cp;
 
247
  
 
248
  cs_check(x);
 
249
 BEGIN:
 
250
  /* if the body of x is in the c stack, its elements
 
251
     are marked anyway by the c stack mark carefully, and
 
252
     if this x is somehow hanging around in a cons that
 
253
     should be dead, we dont want to mark it. -wfs
 
254
  */
 
255
  
 
256
  if (NULL_OR_ON_C_STACK(x))
 
257
    return;
 
258
  if (x->d.m)
 
259
    return;
 
260
  x->d.m = TRUE;
 
261
  switch (type_of(x)) {
 
262
  case t_fixnum:
 
263
    break;
 
264
    
 
265
  case t_ratio:
 
266
    mark_object(x->rat.rat_num);
 
267
    x = x->rat.rat_den;
 
268
    goto BEGIN;
 
269
    
 
270
  case t_shortfloat:
 
271
    break;
 
272
    
 
273
  case t_longfloat:
 
274
    break;
 
275
    
 
276
  case t_complex:
 
277
    mark_object(x->cmp.cmp_imag);
 
278
    x = x->cmp.cmp_real;
 
279
    goto BEGIN;
 
280
    
 
281
  case t_character:
 
282
    break;
 
283
    
 
284
  case t_symbol:
 
285
    mark_object(x->s.s_plist);
 
286
    mark_object(x->s.s_gfdef);
 
287
    mark_object(x->s.s_dbind);
 
288
    if (x->s.s_self == NULL)
 
289
      break;
 
290
    if ((int)what_to_collect >= (int)t_contiguous) {
 
291
      if (inheap(x->s.s_self)) {
 
292
        if (what_to_collect == t_contiguous)
 
293
          mark_contblock(x->s.s_self,
 
294
                         x->s.s_fillp);
 
295
      } else
 
296
        x->s.s_self =
 
297
          copy_relblock(x->s.s_self, x->s.s_fillp);
 
298
    }
 
299
    break;
 
300
    
 
301
  case t_package:
 
302
    mark_object(x->p.p_name);
 
303
    mark_object(x->p.p_nicknames);
 
304
    mark_object(x->p.p_shadowings);
 
305
    mark_object(x->p.p_uselist);
 
306
    mark_object(x->p.p_usedbylist);
 
307
    if (what_to_collect != t_contiguous)
 
308
      break;
 
309
    if (x->p.p_internal != NULL)
 
310
      mark_contblock((char *)(x->p.p_internal),
 
311
                     x->p.p_internal_size*sizeof(object));
 
312
    if (x->p.p_external != NULL)
 
313
      mark_contblock((char *)(x->p.p_external),
 
314
                     x->p.p_external_size*sizeof(object));
 
315
    break;
 
316
    
 
317
  case t_cons:
 
318
    /*
 
319
      mark_object(x->c.c_car);
 
320
      x = x->c.c_cdr;
 
321
      goto BEGIN;
 
322
    */
 
323
    mark_cons(x);
 
324
    break;
 
325
    
 
326
  case t_hashtable:
 
327
    mark_object(x->ht.ht_rhsize);
 
328
    mark_object(x->ht.ht_rhthresh);
 
329
    if (x->ht.ht_self == NULL)
 
330
      break;
 
331
    for (i = 0, j = x->ht.ht_size;  i < j;  i++) {
 
332
      mark_object(x->ht.ht_self[i].hte_key);
 
333
      mark_object(x->ht.ht_self[i].hte_value);
 
334
    }
 
335
    if ((short)what_to_collect >= (short)t_contiguous) {
 
336
      if (inheap(x->ht.ht_self)) {
 
337
        if (what_to_collect == t_contiguous)
 
338
          mark_contblock((char *)(x->ht.ht_self),
 
339
                         j * sizeof(struct htent));
 
340
      } else
 
341
        x->ht.ht_self = (struct htent *)
 
342
          copy_relblock((char *)(x->ht.ht_self),
 
343
                        j * sizeof(struct htent));
 
344
    }
 
345
    break;
 
346
    
 
347
  case t_array:
 
348
    if ((x->a.a_displaced) != Cnil)
 
349
      mark_displaced_field(x);
 
350
    if ((int)what_to_collect >= (int)t_contiguous &&
 
351
        x->a.a_dims != NULL) {
 
352
      if (inheap(x->a.a_dims)) {
 
353
        if (what_to_collect == t_contiguous)
 
354
          mark_contblock((char *)(x->a.a_dims),
 
355
                         sizeof(int)*x->a.a_rank);
 
356
      } else
 
357
        x->a.a_dims = (int *)
 
358
          copy_relblock((char *)(x->a.a_dims),
 
359
                        sizeof(int)*x->a.a_rank);
 
360
    }
 
361
    if ((enum aelttype)x->a.a_elttype == aet_ch)
 
362
      goto CASE_STRING;
 
363
    if ((enum aelttype)x->a.a_elttype == aet_bit)
 
364
      goto CASE_BITVECTOR;
 
365
    if ((enum aelttype)x->a.a_elttype == aet_object)
 
366
      goto CASE_GENERAL;
 
367
    
 
368
  CASE_SPECIAL:
 
369
    cp = (char *)(x->fixa.fixa_self);
 
370
    if (cp == NULL)
 
371
      break;
 
372
    /* set j to the size in char of the body of the array */
 
373
    
 
374
    switch((enum aelttype)x->a.a_elttype){
 
375
#define  ROUND_RB_POINTERS_DOUBLE \
 
376
{int tem =  ((long)rb_pointer1) & (sizeof(double)-1); \
 
377
   if (tem) \
 
378
     { rb_pointer +=  (sizeof(double) - tem); \
 
379
       rb_pointer1 +=  (sizeof(double) - tem); \
 
380
     }}
 
381
    case aet_lf:
 
382
      j= sizeof(longfloat)*x->lfa.lfa_dim;
 
383
      if (((int)what_to_collect >= (int)t_contiguous) &&
 
384
          !(inheap(cp))) ROUND_RB_POINTERS_DOUBLE;
 
385
      break;
 
386
    case aet_char:
 
387
    case aet_uchar:
 
388
      j=sizeof(char)*x->a.a_dim;
 
389
      break;
 
390
    case aet_short:
 
391
    case aet_ushort:
 
392
      j=sizeof(short)*x->a.a_dim;
 
393
      break;
 
394
    default:
 
395
      j=sizeof(fixnum)*x->fixa.fixa_dim;}
 
396
    
 
397
    goto COPY;
 
398
    
 
399
  CASE_GENERAL:
 
400
    p = x->a.a_self;
 
401
    if (p == NULL
 
402
#ifdef HAVE_ALLOCA
 
403
        || (char *)p >= core_end
 
404
#endif  
 
405
        )
 
406
      break;
 
407
    j=0;
 
408
    if (x->a.a_displaced->c.c_car == Cnil)
 
409
      for (i = 0, j = x->a.a_dim;  i < j;  i++)
 
410
        mark_object(p[i]);
 
411
    cp = (char *)p;
 
412
    j *= sizeof(object);
 
413
  COPY:
 
414
    if ((int)what_to_collect >= (int)t_contiguous) {
 
415
      if (inheap(cp)) {
 
416
        if (what_to_collect == t_contiguous)
 
417
          mark_contblock(cp, j);
 
418
      } else if (x->a.a_displaced == Cnil) {
 
419
#ifdef HAVE_ALLOCA
 
420
        if (!NULL_OR_ON_C_STACK(cp))  /* only if body of array not on C stack */
 
421
#endif                    
 
422
          x->a.a_self = (object *)copy_relblock(cp, j);}
 
423
      else if (x->a.a_displaced->c.c_car == Cnil) {
 
424
        i = (long)(object *)copy_relblock(cp, j)
 
425
          - (long)(x->a.a_self);
 
426
        adjust_displaced(x, i);
 
427
      }
 
428
    }
 
429
    break;
 
430
    
 
431
  case t_vector:
 
432
    if ((x->v.v_displaced) != Cnil)
 
433
      mark_displaced_field(x);
 
434
    if ((enum aelttype)x->v.v_elttype == aet_object)
 
435
      goto CASE_GENERAL;
 
436
    else
 
437
      goto CASE_SPECIAL;
 
438
    
 
439
  case t_bignum:
 
440
#ifdef SDEBUG
 
441
    if (type_map[page(x->big.big_self)] < t_contiguous)
 
442
      {
 
443
        printf("bad body for %x (%x)\n",x,cp);
 
444
        
 
445
      }
 
446
#endif          
 
447
#ifndef GMP_USE_MALLOC
 
448
    if ((int)what_to_collect >= (int)t_contiguous) {
 
449
      j = MP_ALLOCATED(x);
 
450
      cp = (char *)MP_SELF(x);
 
451
      if (cp == 0)
 
452
        break;
 
453
#ifdef PARI
 
454
      if (j != lg(MP(x))  &&
 
455
          /* we don't bother to zero this register,
 
456
             and its contents may get over written */
 
457
          ! (x == big_register_1 &&
 
458
             (int)(cp) <= top &&
 
459
             (int) cp >= bot))
 
460
        printf("bad length 0x%x ",x);
 
461
#endif
 
462
      j = j * MP_LIMB_SIZE;
 
463
      if (inheap(cp)) {
 
464
        if (what_to_collect == t_contiguous)
 
465
          mark_contblock(cp, j);
 
466
      } else{
 
467
        MP_SELF(x) = (void *) copy_relblock(cp, j);}}
 
468
#endif /* not GMP_USE_MALLOC */
 
469
    break;
 
470
    
 
471
  CASE_STRING:
 
472
  case t_string:
 
473
    if ((x->st.st_displaced) != Cnil)
 
474
      mark_displaced_field(x);
 
475
    j = x->st.st_dim;
 
476
    cp = x->st.st_self;
 
477
    if (cp == NULL)
 
478
      break;
 
479
  COPY_STRING:
 
480
    if ((int)what_to_collect >= (int)t_contiguous) {
 
481
      if (inheap(cp)) {
 
482
        if (what_to_collect == t_contiguous)
 
483
          mark_contblock(cp, j);
 
484
      } else if (x->st.st_displaced == Cnil)
 
485
        x->st.st_self = copy_relblock(cp, j);
 
486
      else if (x->st.st_displaced->c.c_car == Cnil) {
 
487
        i = copy_relblock(cp, j) - cp;
 
488
        adjust_displaced(x, i);
 
489
      }
 
490
    }
 
491
    break;
 
492
    
 
493
  CASE_BITVECTOR:
 
494
  case t_bitvector:
 
495
    if ((x->bv.bv_displaced) != Cnil)
 
496
      mark_displaced_field(x);
 
497
    /* We make bitvectors multiple of sizeof(int) in size allocated
 
498
       Assume 8 = number of bits in char */
 
499
    
 
500
#define W_SIZE (8*sizeof(int))
 
501
    j= sizeof(int) *
 
502
      ((BV_OFFSET(x) + x->bv.bv_dim + W_SIZE -1)/W_SIZE);
 
503
    cp = x->bv.bv_self;
 
504
    if (cp == NULL)
 
505
      break;
 
506
    goto COPY_STRING;
 
507
    
 
508
  case t_structure:
 
509
    mark_object(x->str.str_def);
 
510
    p = x->str.str_self;
 
511
    if (p == NULL)
 
512
      break;
 
513
    {object def=x->str.str_def;
 
514
    unsigned char * s_type = &SLOT_TYPE(def,0);
 
515
    unsigned short *s_pos= & SLOT_POS(def,0);
 
516
    for (i = 0, j = S_DATA(def)->length;  i < j;  i++)
 
517
      if (s_type[i]==0) mark_object(STREF(object,x,s_pos[i]));
 
518
    if ((int)what_to_collect >= (int)t_contiguous) {
 
519
      if (inheap(x->str.str_self)) {
 
520
        if (what_to_collect == t_contiguous)
 
521
          mark_contblock((char *)p,
 
522
                         S_DATA(def)->size);
 
523
        
 
524
      } else
 
525
        x->str.str_self = (object *)
 
526
          copy_relblock((char *)p, S_DATA(def)->size);
 
527
    }}
 
528
    break;
 
529
    
 
530
  case t_stream:
 
531
    switch (x->sm.sm_mode) {
 
532
    case smm_input:
 
533
    case smm_output:
 
534
    case smm_io:
 
535
    case smm_socket:  
 
536
    case smm_probe:
 
537
      mark_object(x->sm.sm_object0);
 
538
      mark_object(x->sm.sm_object1);
 
539
      if (saving_system)
 
540
        {FILE *fp = x->sm.sm_fp;
 
541
        if (fp != 0 && fp != stdin && fp !=stdout
 
542
            )
 
543
          {fclose(fp);
 
544
          x->sm.sm_fp=0;
 
545
          }}
 
546
      else
 
547
        if (what_to_collect == t_contiguous &&
 
548
            x->sm.sm_fp &&
 
549
            x->sm.sm_buffer)
 
550
          mark_contblock(x->sm.sm_buffer, BUFSIZ);
 
551
      break;
 
552
      
 
553
    case smm_synonym:
 
554
      mark_object(x->sm.sm_object0);
 
555
      break;
 
556
      
 
557
    case smm_broadcast:
 
558
    case smm_concatenated:
 
559
      mark_object(x->sm.sm_object0);
 
560
      break;
 
561
      
 
562
    case smm_two_way:
 
563
    case smm_echo:
 
564
      mark_object(x->sm.sm_object0);
 
565
      mark_object(x->sm.sm_object1);
 
566
      break;
 
567
      
 
568
    case smm_string_input:
 
569
    case smm_string_output:
 
570
      mark_object(x->sm.sm_object0);
 
571
      break;
 
572
#ifdef USER_DEFINED_STREAMS
 
573
    case smm_user_defined:
 
574
      mark_object(x->sm.sm_object0);
 
575
      mark_object(x->sm.sm_object1);
 
576
      break;
 
577
#endif
 
578
    default:
 
579
      error("mark stream botch");
 
580
    }
 
581
    break;
 
582
    
 
583
  case t_random:
 
584
    break;
 
585
    
 
586
  case t_readtable:
 
587
    if (x->rt.rt_self == NULL)
 
588
      break;
 
589
    if (what_to_collect == t_contiguous)
 
590
      mark_contblock((char *)(x->rt.rt_self),
 
591
                     RTABSIZE*sizeof(struct rtent));
 
592
    for (i = 0;  i < RTABSIZE;  i++) {
 
593
      mark_object(x->rt.rt_self[i].rte_macro);
 
594
      if (x->rt.rt_self[i].rte_dtab != NULL) {
 
595
        /**/
 
596
        if (what_to_collect == t_contiguous)
 
597
          mark_contblock((char *)(x->rt.rt_self[i].rte_dtab),
 
598
                         RTABSIZE*sizeof(object));
 
599
        for (j = 0;  j < RTABSIZE;  j++)
 
600
          mark_object(x->rt.rt_self[i].rte_dtab[j]);
 
601
        /**/
 
602
      }
 
603
    }
 
604
    break;
 
605
    
 
606
  case t_pathname:
 
607
    mark_object(x->pn.pn_host);
 
608
    mark_object(x->pn.pn_device);
 
609
    mark_object(x->pn.pn_directory);
 
610
    mark_object(x->pn.pn_name);
 
611
    mark_object(x->pn.pn_type);
 
612
    mark_object(x->pn.pn_version);
 
613
    break;
 
614
    
 
615
  case t_closure:
 
616
    { int i ;
 
617
    if (what_to_collect == t_contiguous)
 
618
      mark_contblock(x->cc.cc_turbo,x->cc.cc_envdim);
 
619
    for (i= 0 ; i < x->cc.cc_envdim ; i++) {
 
620
      mark_object(x->cc.cc_turbo[i]);}}
 
621
    
 
622
  case t_cfun:
 
623
  case t_sfun:
 
624
  case t_vfun:
 
625
  case t_afun:
 
626
  case t_gfun:  
 
627
    mark_object(x->cf.cf_name);
 
628
    mark_object(x->cf.cf_data);
 
629
    break;
 
630
    
 
631
  case t_cfdata:
 
632
    
 
633
    if (x->cfd.cfd_self != NULL)
 
634
      {int i=x->cfd.cfd_fillp;
 
635
      while(i-- > 0)
 
636
        mark_object(x->cfd.cfd_self[i]);}
 
637
    if (x->cfd.cfd_start == NULL)
 
638
      break;
 
639
    if (what_to_collect == t_contiguous) {
 
640
      if (!MAYBE_DATA_P((x->cfd.cfd_start)) ||
 
641
          get_mark_bit((long *)(x->cfd.cfd_start)))
 
642
        break;
 
643
      mark_contblock(x->cfd.cfd_start, x->cfd.cfd_size);}
 
644
    break;
 
645
  case t_cclosure:
 
646
    mark_object(x->cc.cc_name);
 
647
    mark_object(x->cc.cc_env);
 
648
    mark_object(x->cc.cc_data);
 
649
    if (what_to_collect == t_contiguous) {
 
650
      if (x->cc.cc_turbo != NULL)
 
651
        mark_contblock((char *)(x->cc.cc_turbo-1),
 
652
                       (1+fix(*(x->cc.cc_turbo-1)))*sizeof(object));
 
653
    }
 
654
    break;
 
655
    
 
656
  case t_spice:
 
657
    break;
 
658
  default:
 
659
#ifdef DEBUG
 
660
    if (debug)
 
661
      printf("\ttype = %d\n", type_of(x));
 
662
#endif
 
663
    error("mark botch");
 
664
  }
 
665
}
 
666
 
 
667
static long *c_stack_where;
 
668
 
 
669
static void
 
670
mark_stack_carefully(void *topv, void *bottomv, int offset) {
 
671
 
 
672
  long m,pageoffset;
 
673
  unsigned long p;
 
674
  object x;
 
675
  struct typemanager *tm;
 
676
  register long *j;
 
677
  long *top = (long *) topv, *bottom = (long *) bottomv;
 
678
  
 
679
  /* if either of these happens we are marking the C stack
 
680
     and need to use a local */
 
681
  
 
682
  if (top==0) top = c_stack_where;
 
683
  if (bottom==0) bottom= c_stack_where;
 
684
  
 
685
  /* On machines which align local pointers on multiple of 2 rather
 
686
     than 4 we need to mark twice
 
687
  */
 
688
  
 
689
  if (offset) 
 
690
    mark_stack_carefully ( (((char *) top) +offset), bottom, 0 );
 
691
 
 
692
  for (j=top ; j >= bottom ; j--) {
 
693
    if (VALID_DATA_ADDRESS_P(*j)
 
694
        && type_map[(p=page(*j))]< (char)t_end) {
 
695
      pageoffset=((char *)*j - pagetochar(p));
 
696
      tm=tm_of((enum type) type_map[p]);
 
697
      x= (object)
 
698
        ((char *)(*j) -
 
699
         ((pageoffset=((char *)*j - pagetochar(p))) %
 
700
          tm->tm_size));
 
701
      if ((pageoffset <  (tm->tm_size * tm->tm_nppage))
 
702
          && (m=x->d.m) != FREE) {
 
703
        if (m==TRUE) continue;
 
704
        if (m!=0) {
 
705
          fprintf(stdout,
 
706
                  "**bad value %ld of d.m in gbc page %ld skipping mark**"
 
707
                  ,m,p);fflush(stdout);
 
708
          continue;
 
709
        }
 
710
        mark_object(x);
 
711
      }
 
712
    }
 
713
  }
 
714
}
 
715
 
 
716
 
 
717
static void
 
718
mark_phase(void) {
 
719
 
 
720
  STATIC int i, j;
 
721
  STATIC struct package *pp;
 
722
  STATIC bds_ptr bdp;
 
723
  STATIC frame_ptr frp;
 
724
  STATIC ihs_ptr ihsp;
 
725
  
 
726
  mark_object(Cnil);
 
727
  mark_object(Ct);
 
728
  
 
729
  mark_stack_carefully(vs_top-1,vs_org,0);
 
730
  clear_stack(vs_top,vs_limit);
 
731
  mark_stack_carefully(MVloc+(sizeof(MVloc)/sizeof(object)),MVloc,0);
 
732
  /* 
 
733
     for (p = vs_org;  p < vs_top;  p++) {
 
734
     if (p && (inheap(*p)))
 
735
     mark_object(*p);
 
736
     }
 
737
  */
 
738
#ifdef DEBUG
 
739
  if (debug) {
 
740
    printf("value stack marked\n");
 
741
    fflush(stdout);
 
742
  }
 
743
#endif
 
744
  
 
745
  for (bdp = bds_org;  bdp<=bds_top;  bdp++) {
 
746
    mark_object(bdp->bds_sym);
 
747
    mark_object(bdp->bds_val);
 
748
  }
 
749
  
 
750
  for (frp = frs_org;  frp <= frs_top;  frp++)
 
751
    mark_object(frp->frs_val);
 
752
  
 
753
  for (ihsp = ihs_org;  ihsp <= ihs_top;  ihsp++)
 
754
    mark_object(ihsp->ihs_function);
 
755
  
 
756
  for (i = 0;  i < mark_origin_max;  i++)
 
757
    mark_object(*mark_origin[i]);
 
758
  for (i = 0;  i < mark_origin_block_max;  i++)
 
759
    for (j = 0;  j < mark_origin_block[i].mob_size;  j++)
 
760
      mark_object(mark_origin_block[i].mob_addr[j]);
 
761
  
 
762
  for (pp = pack_pointer;  pp != NULL;  pp = pp->p_link)
 
763
    mark_object((object)pp);
 
764
#ifdef KCLOVM
 
765
  if (ovm_process_created)
 
766
    mark_all_stacks();
 
767
#endif
 
768
  
 
769
#ifdef DEBUG
 
770
  if (debug) {
 
771
    printf("symbol navigation\n");
 
772
    fflush(stdout);
 
773
  }
 
774
#endif
 
775
  
 
776
  /*
 
777
    if (what_to_collect != t_symbol &&
 
778
    (int)what_to_collect < (int)t_contiguous) {
 
779
  */
 
780
  
 
781
  {int size;
 
782
  
 
783
  for (pp = pack_pointer;  pp != NULL;  pp = pp->p_link) {
 
784
    size = pp->p_internal_size;
 
785
    if (pp->p_internal != NULL)
 
786
      for (i = 0;  i < size;  i++)
 
787
        mark_object(pp->p_internal[i]);
 
788
    size = pp->p_external_size;
 
789
    if (pp->p_external != NULL)
 
790
      for (i = 0;  i < size;  i++)
 
791
        mark_object(pp->p_external[i]);
 
792
  }}
 
793
  
 
794
  /* mark the c stack */
 
795
#ifndef N_RECURSION_REQD
 
796
#define N_RECURSION_REQD 2
 
797
#endif
 
798
  mark_c_stack(0,N_RECURSION_REQD,mark_stack_carefully);
 
799
  
 
800
}
 
801
 
 
802
#if defined(__ia64__)
 
803
        asm("        .text");
 
804
        asm("        .psr abi64");
 
805
        asm("        .psr lsb");
 
806
        asm("        .lsb");
 
807
        asm("");
 
808
        asm("        .text");
 
809
        asm("        .align 16");
 
810
        asm("        .global GC_save_regs_in_stack");
 
811
        asm("        .proc GC_save_regs_in_stack");
 
812
        asm("GC_save_regs_in_stack:");
 
813
        asm("        .body");
 
814
        asm("        flushrs");
 
815
        asm("        ;;");
 
816
        asm("        mov r8=ar.bsp");
 
817
        asm("        br.ret.sptk.few rp");
 
818
        asm("        .endp GC_save_regs_in_stack");
 
819
 
 
820
void * GC_save_regs_in_stack();
 
821
#endif
 
822
 
 
823
#if defined(__hppa__) /* Courtesy of Lamont Jones */
 
824
/* the calling sequence */
 
825
struct regs {
 
826
        void *callee_saves[16];
 
827
};
 
828
void hppa_save_regs(struct regs);
 
829
 
 
830
/* the code */
 
831
 
 
832
        asm(".code");
 
833
        asm(".export hppa_save_regs, entry");
 
834
        asm(".proc");
 
835
        asm(".callinfo");
 
836
        asm(".label     hppa_save_regs");
 
837
        asm(".entry");
 
838
 
 
839
        asm("stw        %r3,0(%arg0)");
 
840
        asm("stw        %r4,4(%arg0)");
 
841
        asm("stw        %r5,8(%arg0)");
 
842
        asm("stw        %r6,12(%arg0)");
 
843
        asm("stw        %r7,16(%arg0)");
 
844
        asm("stw        %r8,20(%arg0)");
 
845
        asm("stw        %r9,24(%arg0)");
 
846
        asm("stw        %r10,28(%arg0)");
 
847
        asm("stw        %r11,32(%arg0)");
 
848
        asm("stw        %r12,36(%arg0)");
 
849
        asm("stw        %r13,40(%arg0)");
 
850
        asm("stw        %r14,44(%arg0)");
 
851
        asm("stw        %r15,48(%arg0)");
 
852
        asm("stw        %r16,52(%arg0)");
 
853
        asm("stw        %r17,56(%arg0)");
 
854
        asm("bv 0(%rp)");
 
855
        asm("stw        %r18,60(%arg0)");
 
856
 
 
857
        asm(".exit");
 
858
        asm(".procend");
 
859
        asm(".end");
 
860
#endif
 
861
 
 
862
static void
 
863
mark_c_stack(jmp_buf env1, int n, void (*fn)(void *,void *,int)) {
 
864
 
 
865
#if defined(__hppa__)
 
866
  struct regs hppa_regs;
 
867
#endif
 
868
  jmp_buf env;
 
869
  int where;
 
870
  if (n== N_RECURSION_REQD)
 
871
    c_stack_where = (long *) (void *) &env;
 
872
  if (n > 0 ) {  
 
873
#if defined(__hppa__)
 
874
    hppa_save_regs(hppa_regs);
 
875
#else    
 
876
    setjmp(env);
 
877
#endif
 
878
    mark_c_stack(env,n - 1,fn);
 
879
  } else {
 
880
      
 
881
    /* If the locals of type object in a C function could be
 
882
       aligned other than on multiples of sizeof (char *)
 
883
       then define this.  At the moment 2 is the only other
 
884
       legitimate value besides 0 */
 
885
    
 
886
#ifndef C_GC_OFFSET
 
887
#define C_GC_OFFSET 0
 
888
#endif
 
889
    if (&where > cs_org)
 
890
      (*fn)(0,cs_org,C_GC_OFFSET);
 
891
    else
 
892
      (*fn)(cs_org,0,C_GC_OFFSET);}
 
893
  
 
894
#if defined(__ia64__)
 
895
    {
 
896
       extern void * __libc_ia64_register_backing_store_base;
 
897
       void * bst=GC_save_regs_in_stack();
 
898
       void * bsb=__libc_ia64_register_backing_store_base;
 
899
 
 
900
       if (bsb>bst)
 
901
          (*fn)(bsb,bst,C_GC_OFFSET);
 
902
       else
 
903
          (*fn)(bst,bsb,C_GC_OFFSET);
 
904
       
 
905
    }
 
906
#endif
 
907
 
 
908
}
 
909
 
 
910
static void
 
911
sweep_phase(void) {
 
912
 
 
913
  STATIC long i, j, k;
 
914
  STATIC object x;
 
915
  STATIC char *p;
 
916
  STATIC struct typemanager *tm;
 
917
  STATIC object f;
 
918
  
 
919
  Cnil->s.m = FALSE;
 
920
  Ct->s.m = FALSE;
 
921
  
 
922
#ifdef DEBUG
 
923
  if (debug)
 
924
    printf("type map\n");
 
925
#endif
 
926
  for (i = 0;  i < maxpage;  i++) {
 
927
    if (type_map[i] == (int)t_contiguous) {
 
928
      if (debug) {
 
929
        printf("-");
 
930
        /*
 
931
          fflush(stdout);
 
932
        */
 
933
        continue;
 
934
      }
 
935
    }
 
936
    if (type_map[i] >= (int)t_end)
 
937
      continue;
 
938
    
 
939
    tm = tm_of((enum type)type_map[i]);
 
940
    
 
941
    /*
 
942
      general sweeper
 
943
    */
 
944
    
 
945
#ifdef DEBUG
 
946
    if (debug) {
 
947
      printf("%c", tm->tm_name[0]);
 
948
      /*
 
949
        fflush(stdout);
 
950
      */
 
951
    }
 
952
#endif
 
953
    p = pagetochar(i);
 
954
    f = tm->tm_free;
 
955
    k = 0;
 
956
    for (j = tm->tm_nppage; j > 0; --j, p += tm->tm_size) {
 
957
      x = (object)p;
 
958
      if (x->d.m == FREE)
 
959
        continue;
 
960
      else if (x->d.m) {
 
961
        x->d.m = FALSE;
 
962
        continue;
 
963
      }
 
964
      /*   Since we now mark forwards and backwards on displaced
 
965
           arrays, this is not necessary.
 
966
           switch (x->d.t) {
 
967
           case t_array:
 
968
           case t_vector:
 
969
           case t_string:
 
970
           case t_bitvector:
 
971
           if (x->a.a_displaced->c.c_car != Cnil)
 
972
           {undisplace(x);
 
973
           }
 
974
           }
 
975
      */
 
976
      /*                        ((struct freelist *)x)->f_link = f; */
 
977
      
 
978
#ifdef GMP_USE_MALLOC
 
979
      if (x->d.t == t_bignum) {
 
980
        mpz_clear(MP(x));
 
981
      }
 
982
#endif
 
983
      SET_LINK(x,f);
 
984
      x->d.m = FREE;
 
985
      f = x;
 
986
      k++;
 
987
    }
 
988
    tm->tm_free = f;
 
989
    tm->tm_nfree += k;
 
990
    
 
991
  }
 
992
#ifdef DEBUG
 
993
  if (debug) {
 
994
    putchar('\n');
 
995
    fflush(stdout);
 
996
  }
 
997
#endif
 
998
}
 
999
 
 
1000
static void
 
1001
contblock_sweep_phase(void) {
 
1002
 
 
1003
  STATIC long i, j;
 
1004
  STATIC char *s, *e, *p, *q;
 
1005
  STATIC struct contblock *cbp;
 
1006
  
 
1007
  cb_pointer = NULL;
 
1008
  ncb = 0;
 
1009
  for (i = 0;  i < maxpage;) {
 
1010
    if (type_map[i] != (int)t_contiguous) {
 
1011
      i++;
 
1012
      continue;
 
1013
    }
 
1014
    for (j = i+1;
 
1015
         j < maxpage && type_map[j] == (int)t_contiguous;
 
1016
         j++)
 
1017
      ; 
 
1018
    s = pagetochar(i);
 
1019
    e = pagetochar(j);
 
1020
    for (p = s;  p < e;) {
 
1021
      if (get_mark_bit((int *)p)) {
 
1022
        /* SGC cont pages: cont blocks must be no smaller than
 
1023
           sizeof(struct contblock), and must not have a sweep
 
1024
           granularity greater than this amount (e.g. CPTR_ALIGN) if
 
1025
           contblock leaks are to be avoided.  Used to be aligned at
 
1026
           PTR_ALIGN. CM 20030827 */
 
1027
        p += CPTR_ALIGN;
 
1028
        continue;
 
1029
      }
 
1030
      q = p + CPTR_ALIGN;
 
1031
      while (q < e) {
 
1032
        if (!get_mark_bit((int *)q)) {
 
1033
          q += CPTR_ALIGN;
 
1034
          continue;
 
1035
        }
 
1036
        break;
 
1037
      }
 
1038
      insert_contblock(p, q - p);
 
1039
      p = q + CPTR_ALIGN;
 
1040
    }
 
1041
    i = j + 1;
 
1042
  }
 
1043
#ifdef DEBUG
 
1044
  if (debug) {
 
1045
    for (cbp = cb_pointer; cbp != NULL; cbp = cbp->cb_link)
 
1046
      printf("%d-byte contblock\n", cbp->cb_size);
 
1047
    fflush(stdout);
 
1048
  }
 
1049
#endif
 
1050
}
 
1051
 
 
1052
 
 
1053
int (*GBC_enter_hook)() = NULL;
 
1054
int (*GBC_exit_hook)() = NULL;
 
1055
char *old_rb_start;
 
1056
 
 
1057
void
 
1058
GBC(enum type t) {
 
1059
 
 
1060
  long i, j;
 
1061
  struct apage *pp, *qq;
 
1062
#ifdef SGC
 
1063
  int in_sgc = sgc_enabled;
 
1064
#endif
 
1065
#ifdef DEBUG
 
1066
  int tm=0;
 
1067
#endif
 
1068
  
 
1069
  if (in_signal_handler && t == t_relocatable)
 
1070
    error("cant gc relocatable in signal handler");
 
1071
  
 
1072
  if (GBC_enter_hook != NULL)
 
1073
    (*GBC_enter_hook)();
 
1074
  
 
1075
  if (!GBC_enable)
 
1076
    error("GBC is not enabled");
 
1077
  interrupt_enable = FALSE;
 
1078
  
 
1079
  if (saving_system)
 
1080
    {t = t_contiguous; gc_time = -1;
 
1081
#ifdef SGC
 
1082
    if(sgc_enabled) sgc_quit();
 
1083
#endif    
 
1084
    }
 
1085
 
 
1086
 
 
1087
#ifdef DEBUG
 
1088
  debug = symbol_value(sSAgbc_messageA) != Cnil;
 
1089
#endif
 
1090
  
 
1091
  what_to_collect = t;
 
1092
  
 
1093
  tm_table[(int)t].tm_gbccount++;
 
1094
  tm_table[(int)t].tm_adjgbccnt++;
 
1095
  
 
1096
#ifdef DEBUG
 
1097
  if (debug || (sSAnotify_gbcA->s.s_dbind != Cnil)) {
 
1098
    
 
1099
    if (gc_time < 0) gc_time=0;
 
1100
#ifdef SGC
 
1101
    printf("[%s for %ld %s pages..",
 
1102
           (sgc_enabled ? "SGC" : "GC"),
 
1103
           (sgc_enabled ? sgc_count_type(t) : tm_of(t)->tm_npage),
 
1104
           (tm_table[(int)t].tm_name)+1);
 
1105
#else
 
1106
    printf("[%s for %d %s pages..",
 
1107
           ("GC"),
 
1108
           (tm_of(t)->tm_npage),
 
1109
           (tm_table[(int)t].tm_name)+1);
 
1110
#endif
 
1111
#ifdef SGC
 
1112
    if(sgc_enabled)
 
1113
      printf("(%d writable)..",sgc_count_writable(page(core_end)));
 
1114
#endif    
 
1115
    fflush(stdout);
 
1116
  }
 
1117
#endif
 
1118
  if (gc_time >=0 && !gc_recursive++) {gc_start=runtime();}
 
1119
  
 
1120
  maxpage = page(heap_end);
 
1121
  
 
1122
  if ((int)t >= (int)t_contiguous) {
 
1123
    j = maxpage*(PAGESIZE/(CPTR_ALIGN*SIZEOF_LONG*CHAR_SIZE)) ;
 
1124
    /*
 
1125
      (PAGESIZE / sizeof(int)) = x * (sizeof(int)*CHAR_SIZE)
 
1126
      eg if PAGESIZE = 2048  x=16
 
1127
      1 page = 512 long word
 
1128
      512 bit = 16 long word
 
1129
    */
 
1130
    
 
1131
    if (t == t_relocatable)
 
1132
      j = 0;
 
1133
    /* if in sgc we don't need more pages below hole
 
1134
       just more relocatable or cleaning it */
 
1135
#ifdef SGC
 
1136
    if (sgc_enabled==0) 
 
1137
#endif
 
1138
      if (holepage < new_holepage)
 
1139
        holepage = new_holepage;
 
1140
    
 
1141
#ifdef SGC
 
1142
    i = rb_pointer - (sgc_enabled ? old_rb_start : rb_start);
 
1143
#else
 
1144
    i = rb_pointer - rb_start;
 
1145
#endif    
 
1146
 
 
1147
    if (nrbpage > (real_maxpage-page(heap_end)
 
1148
                   -holepage-real_maxpage/32)/2) {
 
1149
      if (i > nrbpage*PAGESIZE)
 
1150
        error("Can't allocate.  Good-bye!.");
 
1151
      else
 
1152
        nrbpage =
 
1153
          (real_maxpage-page(heap_end)
 
1154
           -holepage-real_maxpage/32)/2;
 
1155
    }
 
1156
    
 
1157
    if (saving_system)
 
1158
      rb_start = heap_end;
 
1159
    else
 
1160
#ifdef SGC
 
1161
      if (sgc_enabled==0)
 
1162
#endif
 
1163
        {rb_start = heap_end + PAGESIZE*holepage;}
 
1164
    
 
1165
    rb_end = heap_end + (holepage + nrbpage) *PAGESIZE;
 
1166
    
 
1167
    if (rb_start < rb_pointer)
 
1168
      rb_start1 = (char *)
 
1169
        ((long)(rb_pointer + PAGESIZE-1) & -(unsigned long)PAGESIZE);
 
1170
    else
 
1171
      rb_start1 = rb_start;
 
1172
    
 
1173
    /* as we walk through marking data, we replace the
 
1174
       relocatable pointers
 
1175
       in objects by the rb_pointer, advance that
 
1176
       by the size, and copy the actual
 
1177
       data there to rb_pointer1, and advance it by the size
 
1178
       at the end [rb_start1,rb_pointer1] is copied
 
1179
       to [rb_start,rb_pointer]
 
1180
    */
 
1181
    rb_pointer = rb_start;  /* where the new relblock will start */
 
1182
    rb_pointer1 = rb_start1;/* where we will copy it to during gc*/
 
1183
    
 
1184
    mark_table = (long *)(rb_start1 + i);
 
1185
    
 
1186
    if (rb_end < (char *)&mark_table[j])
 
1187
      i = (char *)&mark_table[j] - heap_end;
 
1188
    else
 
1189
      i = rb_end - heap_end;
 
1190
    alloc_page(-(i + PAGESIZE - 1)/PAGESIZE);
 
1191
    
 
1192
    for (i = 0;  i < j; i++)
 
1193
      mark_table[i] = 0;
 
1194
  }
 
1195
  
 
1196
#ifdef DEBUG
 
1197
  if (debug) {
 
1198
    printf("mark phase\n");
 
1199
    fflush(stdout);
 
1200
    tm = runtime();
 
1201
  }
 
1202
#endif
 
1203
#ifdef SGC
 
1204
  if(sgc_enabled)
 
1205
    { if (t < t_end && tm_of(t)->tm_sgc == 0)
 
1206
      {sgc_quit();
 
1207
      if (sSAnotify_gbcA->s.s_dbind != Cnil)
 
1208
        {fprintf(stdout, " (doing full gc)");
 
1209
        fflush(stdout);}
 
1210
      mark_phase();}
 
1211
    else
 
1212
      sgc_mark_phase();}
 
1213
  else
 
1214
#endif  
 
1215
    mark_phase();
 
1216
#ifdef DEBUG
 
1217
  if (debug) {
 
1218
    printf("mark ended (%d)\n", runtime() - tm);
 
1219
    fflush(stdout);
 
1220
  }
 
1221
#endif
 
1222
  
 
1223
#ifdef DEBUG
 
1224
  if (debug) {
 
1225
    printf("sweep phase\n");
 
1226
    fflush(stdout);
 
1227
    tm = runtime();
 
1228
  }
 
1229
#endif
 
1230
#ifdef SGC
 
1231
  if(sgc_enabled)
 
1232
    sgc_sweep_phase();
 
1233
  else
 
1234
#endif  
 
1235
    sweep_phase();
 
1236
#ifdef DEBUG
 
1237
  if (debug) {
 
1238
    printf("sweep ended (%d)\n", runtime() - tm);
 
1239
    fflush(stdout);
 
1240
  }
 
1241
#endif
 
1242
  
 
1243
  if (t == t_contiguous) {
 
1244
#ifdef DEBUG
 
1245
    if (debug) {
 
1246
      printf("contblock sweep phase\n");
 
1247
      fflush(stdout);
 
1248
      tm = runtime();
 
1249
    }
 
1250
#endif
 
1251
    
 
1252
#ifdef SGC
 
1253
    if (sgc_enabled)
 
1254
      sgc_contblock_sweep_phase();
 
1255
    else
 
1256
#endif
 
1257
      contblock_sweep_phase();
 
1258
#ifdef DEBUG
 
1259
    if (debug)
 
1260
      printf("contblock sweep ended (%d)\n",
 
1261
             runtime() - tm);
 
1262
#endif
 
1263
  }
 
1264
  
 
1265
  if ((int)t >= (int)t_contiguous) {
 
1266
    
 
1267
    if (rb_start < rb_start1) {
 
1268
      j = (rb_pointer-rb_start + PAGESIZE - 1)/PAGESIZE;
 
1269
      pp = (struct apage *)rb_start;
 
1270
      qq = (struct apage *)rb_start1;
 
1271
      for (i = 0;  i < j;  i++)
 
1272
        *pp++ = *qq++;
 
1273
    }
 
1274
    
 
1275
#ifdef SGC
 
1276
    /* we don't know which pages have relblock on them */
 
1277
    if(sgc_enabled)
 
1278
      make_writable(page(rb_start),
 
1279
                    (rb_pointer-rb_start + PAGESIZE - 1)/PAGESIZE);
 
1280
    
 
1281
#endif          
 
1282
    rb_limit = rb_end - 2*RB_GETA;
 
1283
    
 
1284
  }
 
1285
  
 
1286
#ifdef DEBUG
 
1287
  if (debug) {
 
1288
    for (i = 0, j = 0;  i < (int)t_end;  i++) {
 
1289
      if (tm_table[i].tm_type == (enum type)i) {
 
1290
        printf("%13s: %8ld used %8ld free %4ld/%ld pages\n",
 
1291
               tm_table[i].tm_name,
 
1292
               TM_NUSED(tm_table[i]),
 
1293
               tm_table[i].tm_nfree,
 
1294
               tm_table[i].tm_npage,
 
1295
               tm_table[i].tm_maxpage);
 
1296
        j += tm_table[i].tm_npage;
 
1297
      } else
 
1298
        printf("%13s: linked to %s\n",
 
1299
               tm_table[i].tm_name,
 
1300
               tm_table[(int)tm_table[i].tm_type].tm_name);
 
1301
    }
 
1302
    printf("contblock: %ld blocks %ld pages\n", ncb, ncbpage);
 
1303
    printf("hole: %ld pages\n", holepage);
 
1304
    printf("relblock: %ld bytes used %ld bytes free %ld pages\n",
 
1305
           (long)(rb_pointer - rb_start), (long)(rb_end - rb_pointer), nrbpage);
 
1306
    printf("GBC ended\n");
 
1307
    fflush(stdout);
 
1308
  }
 
1309
#endif
 
1310
  
 
1311
  interrupt_enable = TRUE;
 
1312
  
 
1313
#ifdef SGC
 
1314
  if (in_sgc && sgc_enabled==0)
 
1315
    sgc_start();
 
1316
#endif
 
1317
  
 
1318
  if (saving_system) {
 
1319
    j = (rb_pointer-rb_start+PAGESIZE-1) / PAGESIZE;
 
1320
    
 
1321
    heap_end += PAGESIZE*j;
 
1322
    
 
1323
    /* When the program is re-loaded, the system initialization
 
1324
       code may use malloc() before main() begins.  This
 
1325
       happens in Linux.  We need to allow some heap expansion
 
1326
       space for this.  One page is enough for Linux.
 
1327
       Bill Metzenthen May95.
 
1328
    */
 
1329
    if ( core_end < heap_end + PAGESIZE )
 
1330
      {
 
1331
        fprintf(stderr,
 
1332
                "Not enough memory available for saved image\n");
 
1333
        exit(1);
 
1334
      }
 
1335
    core_end = heap_end + PAGESIZE;
 
1336
    
 
1337
/*     for (i = 0;  i < maxpage;  i++) */
 
1338
/*       if ((enum type)type_map[i] == t_contiguous) */
 
1339
/*      type_map[i] = (char)t_other; */
 
1340
/*     cb_pointer = NULL; */
 
1341
/*     maxcbpage -= ncbpage; */
 
1342
/*     if (maxcbpage < 100) */
 
1343
/*       maxcbpage = 100; */
 
1344
/*     ncbpage = 0; */
 
1345
/*     ncb = 0; */
 
1346
    
 
1347
    /* hmm.... why is this test necessary.*/
 
1348
#ifdef SGC
 
1349
    if (sgc_enabled==0) 
 
1350
#endif
 
1351
      {holepage = new_holepage;
 
1352
      nrbpage = INIT_NRBPAGE;}
 
1353
    
 
1354
    if (nrbpage < 0)
 
1355
      error("no relocatable pages left");
 
1356
    
 
1357
    rb_start = heap_end + PAGESIZE*holepage;
 
1358
    rb_end = rb_start + PAGESIZE*nrbpage;
 
1359
    rb_limit = rb_end - 2*RB_GETA;
 
1360
    rb_pointer = rb_start;
 
1361
  }
 
1362
  
 
1363
  if (GBC_exit_hook != NULL)
 
1364
    (*GBC_exit_hook)();
 
1365
  
 
1366
  if(gc_time>=0 && !--gc_recursive) {gc_time=gc_time+(gc_start=(runtime()-gc_start));}
 
1367
  
 
1368
  if (sSAnotify_gbcA->s.s_dbind != Cnil) {
 
1369
    
 
1370
    if (gc_recursive)
 
1371
      fprintf(stdout, "(T=...).GC finished]\n");
 
1372
    else
 
1373
      fprintf(stdout, "(T=%d).GC finished]\n",gc_start);
 
1374
    fflush(stdout);
 
1375
 
 
1376
  }
 
1377
  
 
1378
  
 
1379
  CHECK_INTERRUPT;
 
1380
}
 
1381
 
 
1382
static void
 
1383
FFN(siLroom_report)(void) {
 
1384
 
 
1385
  int i;
 
1386
  
 
1387
  check_arg(0);
 
1388
  
 
1389
  /*
 
1390
    GBC(t_contiguous);
 
1391
  */
 
1392
  
 
1393
  vs_check_push(make_fixnum(real_maxpage));
 
1394
  vs_push(make_fixnum(available_pages));
 
1395
  vs_push(make_fixnum(ncbpage));
 
1396
  vs_push(make_fixnum(maxcbpage));
 
1397
  vs_push(make_fixnum(ncb));
 
1398
  vs_push(make_fixnum(cbgbccount));
 
1399
  vs_push(make_fixnum(holepage));
 
1400
  vs_push(make_fixnum(rb_pointer - rb_start));
 
1401
  vs_push(make_fixnum(rb_end - rb_pointer));
 
1402
  vs_push(make_fixnum(nrbpage));
 
1403
  vs_push(make_fixnum(rbgbccount));
 
1404
  for (i = 0;  i < (int)t_end;  i++) {
 
1405
    if (tm_table[i].tm_type == (enum type)i) {
 
1406
      vs_check_push(make_fixnum(TM_NUSED(tm_table[i])));
 
1407
      vs_push(make_fixnum(tm_table[i].tm_nfree));
 
1408
      vs_push(make_fixnum(tm_table[i].tm_npage));
 
1409
      vs_push(make_fixnum(tm_table[i].tm_maxpage));
 
1410
      vs_push(make_fixnum(tm_table[i].tm_gbccount));
 
1411
    } else {
 
1412
      vs_check_push(Cnil);
 
1413
      vs_push(make_fixnum(tm_table[i].tm_type));
 
1414
      vs_push(Cnil);
 
1415
      vs_push(Cnil);
 
1416
      vs_push(Cnil);
 
1417
    }
 
1418
  }
 
1419
}
 
1420
 
 
1421
static void
 
1422
FFN(siLreset_gbc_count)(void) {
 
1423
 
 
1424
  int i;
 
1425
  
 
1426
  check_arg(0);
 
1427
  
 
1428
  for (i = 0;  i < (int)t_other;  i++)
 
1429
    tm_table[i].tm_gbccount = tm_table[i].tm_adjgbccnt = 0;
 
1430
}
 
1431
 
 
1432
/* copy S bytes starting at P to beyond rb_pointer1 (temporarily)
 
1433
   but return a pointer to where this will be copied back to,
 
1434
   when gc is done.  alignment of rb_pointer is kept at a multiple
 
1435
   of sizeof(char *);
 
1436
*/
 
1437
 
 
1438
static char *
 
1439
copy_relblock(char *p, int s)
 
1440
{ char *res = rb_pointer;
 
1441
 char *q = rb_pointer1;
 
1442
 s = ROUND_UP_PTR(s);
 
1443
 rb_pointer += s;
 
1444
 rb_pointer1 += s;
 
1445
 
 
1446
 while (--s >= 0)
 
1447
   { *q++ = *p++;}
 
1448
 
 
1449
 return res;
 
1450
}
 
1451
 
 
1452
 
 
1453
static void
 
1454
mark_contblock(void *p, int s) {
 
1455
 
 
1456
  STATIC char *q;
 
1457
  STATIC char *x, *y;
 
1458
  long np=page(p);
 
1459
  
 
1460
  if (!MAYBE_DATA_P(p) || np >= MAXPAGE || (enum type)type_map[page(p)] != t_contiguous)
 
1461
    return;
 
1462
  q = p + s;
 
1463
  /* SGC cont pages: contblock pages must be no smaller than
 
1464
     sizeof(struct contblock).  CM 20030827 */
 
1465
  x = (char *)ROUND_DOWN_PTR_CONT(p);
 
1466
  y = (char *)ROUND_UP_PTR_CONT(q);
 
1467
  for (;  x < y;  x+=CPTR_ALIGN)
 
1468
    set_mark_bit(x);
 
1469
}
 
1470
 
 
1471
DEFUN_NEW("GBC",object,fLgbc,LISP
 
1472
       ,1,1,NONE,OO,OO,OO,OO,(object x0),"")
 
1473
 
 
1474
{
 
1475
  /* 1 args */
 
1476
  
 
1477
  if (x0 == Ct)
 
1478
    GBC(t_contiguous);
 
1479
  else if (x0 == Cnil)
 
1480
    GBC(t_cons);
 
1481
  else
 
1482
    { x0 = small_fixnum(1);     GBC(t_relocatable);}
 
1483
  RETURN1(x0);
 
1484
}
 
1485
 
 
1486
static void
 
1487
FFN(siLgbc_time)(void) {
 
1488
  if (vs_top>vs_base)
 
1489
    gc_time=fix(vs_base[0]);
 
1490
  else {
 
1491
    vs_base[0]=make_fixnum(gc_time);
 
1492
    vs_top=vs_base+1;
 
1493
  }
 
1494
}
 
1495
 
 
1496
#ifdef SGC
 
1497
#include "sgbc.c"
 
1498
#endif
 
1499
 
 
1500
DEFVAR("*NOTIFY-GBC*",sSAnotify_gbcA,SI,Cnil,"");
 
1501
#ifdef DEBUG
 
1502
DEFVAR("*GBC-MESSAGE*",sSAgbc_messageA,SI,Cnil,"");
 
1503
#endif
 
1504
 
 
1505
void
 
1506
gcl_init_GBC(void) {
 
1507
 
 
1508
  make_si_function("ROOM-REPORT", siLroom_report);
 
1509
  make_si_function("RESET-GBC-COUNT", siLreset_gbc_count);
 
1510
  make_si_function("GBC-TIME",siLgbc_time);
 
1511
  
 
1512
#ifdef SGC
 
1513
  /* we use that maxpage is a power of 2 in this
 
1514
     case, to quickly be able to look in our table */ 
 
1515
  { 
 
1516
    long i,j;
 
1517
  
 
1518
    for(i=j=1 ; i< 32 ; i++) 
 
1519
      if (MAXPAGE == (1 <<i))
 
1520
        j=0;
 
1521
    if (j) {
 
1522
      perror("MAXPAGE is not a power of 2.  Recompile");
 
1523
      exit(1);
 
1524
    }
 
1525
    make_si_function("SGC-ON",siLsgc_on);
 
1526
 
 
1527
  }
 
1528
#endif  
 
1529
}