1995-08-09 08:06:35 -07:00
|
|
|
/***********************************************************************/
|
|
|
|
/* */
|
1996-04-30 07:53:58 -07:00
|
|
|
/* Objective Caml */
|
1995-08-09 08:06:35 -07:00
|
|
|
/* */
|
|
|
|
/* Damien Doligez, projet Para, INRIA Rocquencourt */
|
|
|
|
/* */
|
1996-04-30 07:53:58 -07:00
|
|
|
/* Copyright 1996 Institut National de Recherche en Informatique et */
|
1999-11-17 10:59:06 -08:00
|
|
|
/* en Automatique. All rights reserved. This file is distributed */
|
|
|
|
/* under the terms of the GNU Library General Public License. */
|
1995-08-09 08:06:35 -07:00
|
|
|
/* */
|
|
|
|
/***********************************************************************/
|
|
|
|
|
|
|
|
/* $Id$ */
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
#include <string.h>
|
|
|
|
#include "config.h"
|
|
|
|
#include "fail.h"
|
|
|
|
#include "gc.h"
|
|
|
|
#include "gc_ctrl.h"
|
|
|
|
#include "major_gc.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "minor_gc.h"
|
|
|
|
#include "misc.h"
|
|
|
|
#include "mlvalues.h"
|
|
|
|
#include "roots.h"
|
1995-12-22 08:48:17 -08:00
|
|
|
#include "signals.h"
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
asize_t minor_heap_size;
|
1995-12-22 09:49:35 -08:00
|
|
|
char *young_start = NULL, *young_end = NULL;
|
|
|
|
char *young_ptr = NULL, *young_limit = NULL;
|
1995-05-04 03:15:53 -07:00
|
|
|
static value **ref_table = NULL, **ref_table_end, **ref_table_threshold;
|
|
|
|
value **ref_table_ptr = NULL, **ref_table_limit;
|
|
|
|
static asize_t ref_table_size, ref_table_reserve;
|
1995-07-24 05:46:59 -07:00
|
|
|
int in_minor_collection = 0;
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1997-09-02 05:55:01 -07:00
|
|
|
void set_minor_heap_size (asize_t size)
|
1995-05-04 03:15:53 -07:00
|
|
|
{
|
|
|
|
char *new_heap;
|
|
|
|
value **new_table;
|
|
|
|
|
|
|
|
Assert (size >= Minor_heap_min);
|
|
|
|
Assert (size <= Minor_heap_max);
|
|
|
|
Assert (size % sizeof (value) == 0);
|
1995-07-10 02:48:27 -07:00
|
|
|
if (young_ptr != young_end) minor_collection ();
|
|
|
|
Assert (young_ptr == young_end);
|
1995-05-04 03:15:53 -07:00
|
|
|
new_heap = (char *) stat_alloc (size);
|
|
|
|
if (young_start != NULL){
|
1997-11-20 07:30:43 -08:00
|
|
|
stat_free (young_start);
|
1995-05-04 03:15:53 -07:00
|
|
|
}
|
|
|
|
young_start = new_heap;
|
|
|
|
young_end = new_heap + size;
|
1995-12-22 09:49:35 -08:00
|
|
|
young_limit = young_start;
|
1995-07-10 02:48:27 -07:00
|
|
|
young_ptr = young_end;
|
1995-05-04 03:15:53 -07:00
|
|
|
minor_heap_size = size;
|
|
|
|
|
|
|
|
ref_table_size = minor_heap_size / sizeof (value) / 8;
|
|
|
|
ref_table_reserve = 256;
|
|
|
|
new_table = (value **) stat_alloc ((ref_table_size + ref_table_reserve)
|
1997-05-19 08:42:21 -07:00
|
|
|
* sizeof (value *));
|
1997-11-20 07:30:43 -08:00
|
|
|
if (ref_table != NULL) stat_free (ref_table);
|
1995-05-04 03:15:53 -07:00
|
|
|
ref_table = new_table;
|
|
|
|
ref_table_ptr = ref_table;
|
|
|
|
ref_table_threshold = ref_table + ref_table_size;
|
|
|
|
ref_table_limit = ref_table_threshold;
|
|
|
|
ref_table_end = ref_table + ref_table_size + ref_table_reserve;
|
|
|
|
}
|
|
|
|
|
1997-09-02 05:55:01 -07:00
|
|
|
void oldify (value v, value *p)
|
1995-05-04 03:15:53 -07:00
|
|
|
{
|
1995-07-17 09:11:08 -07:00
|
|
|
value result, field0;
|
|
|
|
header_t hd;
|
|
|
|
mlsize_t sz, i;
|
1999-11-09 07:38:39 -08:00
|
|
|
tag_t tag;
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
tail_call:
|
|
|
|
if (Is_block (v) && Is_young (v)){
|
1995-07-10 02:48:27 -07:00
|
|
|
Assert (Hp_val (v) >= young_ptr);
|
1995-07-17 09:11:08 -07:00
|
|
|
hd = Hd_val (v);
|
|
|
|
tag = Tag_hd (hd);
|
|
|
|
if (Is_blue_hd (hd)){ /* Already forwarded ? */
|
1995-05-04 03:15:53 -07:00
|
|
|
*p = Field (v, 0); /* Then the forward pointer is the first field. */
|
1995-07-17 09:11:08 -07:00
|
|
|
}else if (tag == Infix_tag) {
|
|
|
|
mlsize_t offset = Infix_offset_hd (hd);
|
1995-10-30 02:21:28 -08:00
|
|
|
oldify(v - offset, p);
|
1995-07-10 02:48:27 -07:00
|
|
|
*p += offset;
|
1995-07-17 09:11:08 -07:00
|
|
|
}else if (tag >= No_scan_tag){
|
|
|
|
sz = Wosize_hd (hd);
|
|
|
|
result = alloc_shr (sz, tag);
|
|
|
|
for (i = 0; i < sz; i++) Field(result, i) = Field(v, i);
|
|
|
|
Hd_val (v) = Bluehd_hd (hd); /* Put the forward flag. */
|
1995-05-04 03:15:53 -07:00
|
|
|
Field (v, 0) = result; /* And the forward pointer. */
|
|
|
|
*p = result;
|
|
|
|
}else{
|
|
|
|
/* We can do recursive calls before all the fields are filled, because
|
|
|
|
we will not be calling the major GC. */
|
1995-07-17 09:11:08 -07:00
|
|
|
sz = Wosize_hd (hd);
|
|
|
|
result = alloc_shr (sz, tag);
|
1995-05-04 03:15:53 -07:00
|
|
|
*p = result;
|
1995-07-17 09:11:08 -07:00
|
|
|
field0 = Field (v, 0);
|
|
|
|
Hd_val (v) = Bluehd_hd (hd); /* Put the forward flag. */
|
1995-05-04 03:15:53 -07:00
|
|
|
Field (v, 0) = result; /* And the forward pointer. */
|
1995-07-17 09:11:08 -07:00
|
|
|
if (sz == 1) {
|
1995-05-04 03:15:53 -07:00
|
|
|
p = &Field (result, 0);
|
|
|
|
v = field0;
|
|
|
|
goto tail_call;
|
1995-07-17 09:11:08 -07:00
|
|
|
} else {
|
1995-10-30 02:21:28 -08:00
|
|
|
oldify (field0, &Field (result, 0));
|
1995-05-04 03:15:53 -07:00
|
|
|
for (i = 1; i < sz - 1; i++){
|
1995-10-30 02:21:28 -08:00
|
|
|
oldify (Field(v, i), &Field (result, i));
|
1995-05-04 03:15:53 -07:00
|
|
|
}
|
|
|
|
p = &Field (result, i);
|
|
|
|
v = Field (v, i);
|
|
|
|
goto tail_call;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
*p = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-09-02 05:55:01 -07:00
|
|
|
void minor_collection (void)
|
1995-05-04 03:15:53 -07:00
|
|
|
{
|
|
|
|
value **r;
|
|
|
|
long prev_alloc_words = allocated_words;
|
|
|
|
|
1995-07-24 05:46:59 -07:00
|
|
|
in_minor_collection = 1;
|
1998-08-07 11:43:39 -07:00
|
|
|
gc_message (0x02, "<", 0);
|
1995-07-10 02:48:27 -07:00
|
|
|
oldify_local_roots();
|
1995-10-30 02:21:28 -08:00
|
|
|
for (r = ref_table; r < ref_table_ptr; r++) oldify (**r, *r);
|
1995-07-10 02:48:27 -07:00
|
|
|
stat_minor_words += Wsize_bsize (young_end - young_ptr);
|
|
|
|
young_ptr = young_end;
|
1995-05-04 03:15:53 -07:00
|
|
|
ref_table_ptr = ref_table;
|
|
|
|
ref_table_limit = ref_table_threshold;
|
1998-08-07 11:43:39 -07:00
|
|
|
gc_message (0x02, ">", 0);
|
1995-07-24 05:46:59 -07:00
|
|
|
in_minor_collection = 0;
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
stat_promoted_words += allocated_words - prev_alloc_words;
|
|
|
|
++ stat_minor_collections;
|
|
|
|
major_collection_slice ();
|
1995-08-08 06:37:34 -07:00
|
|
|
force_major_slice = 0;
|
1995-05-04 03:15:53 -07:00
|
|
|
}
|
|
|
|
|
1997-09-02 05:55:01 -07:00
|
|
|
value check_urgent_gc (value extra_root)
|
1996-11-15 07:25:26 -08:00
|
|
|
{
|
1999-11-29 11:03:05 -08:00
|
|
|
CAMLparam1 (extra_root);
|
|
|
|
if (force_major_slice) minor_collection();
|
|
|
|
CAMLreturn (extra_root);
|
1996-11-15 07:25:26 -08:00
|
|
|
}
|
|
|
|
|
1997-09-02 05:55:01 -07:00
|
|
|
void realloc_ref_table (void)
|
1995-05-04 03:15:53 -07:00
|
|
|
{ Assert (ref_table_ptr == ref_table_limit);
|
|
|
|
Assert (ref_table_limit <= ref_table_end);
|
|
|
|
Assert (ref_table_limit >= ref_table_threshold);
|
|
|
|
|
|
|
|
if (ref_table_limit == ref_table_threshold){
|
1998-08-07 11:43:39 -07:00
|
|
|
gc_message (0x08, "ref_table threshold crossed\n", 0);
|
1995-05-04 03:15:53 -07:00
|
|
|
ref_table_limit = ref_table_end;
|
1995-08-08 06:37:34 -07:00
|
|
|
urge_major_slice ();
|
1995-07-24 05:46:59 -07:00
|
|
|
}else{ /* This will almost never happen with the bytecode interpreter. */
|
1995-05-04 03:15:53 -07:00
|
|
|
asize_t sz;
|
|
|
|
asize_t cur_ptr = ref_table_ptr - ref_table;
|
1995-08-08 06:37:34 -07:00
|
|
|
Assert (force_major_slice);
|
1995-12-22 08:48:17 -08:00
|
|
|
|
1995-07-24 05:46:59 -07:00
|
|
|
ref_table_size *= 2;
|
1995-05-04 03:15:53 -07:00
|
|
|
sz = (ref_table_size + ref_table_reserve) * sizeof (value *);
|
1998-08-07 11:43:39 -07:00
|
|
|
gc_message (0x08, "Growing ref_table to %ldk bytes\n", (long) sz / 1024);
|
1995-05-04 03:15:53 -07:00
|
|
|
ref_table = (value **) realloc ((char *) ref_table, sz);
|
|
|
|
if (ref_table == NULL) fatal_error ("Fatal error: ref_table overflow\n");
|
|
|
|
ref_table_end = ref_table + ref_table_size + ref_table_reserve;
|
|
|
|
ref_table_threshold = ref_table + ref_table_size;
|
|
|
|
ref_table_ptr = ref_table + cur_ptr;
|
|
|
|
ref_table_limit = ref_table_end;
|
|
|
|
}
|
|
|
|
}
|